fprintf(stderr, "\nUsage: %s [options]\n\n", prg);
fprintf(stderr, "Commands: -A (add a new rule)\n");
fprintf(stderr, " -D (delete a rule)\n");
- fprintf(stderr, " -F (flush - delete all rules) [not yet implemented]\n");
+ fprintf(stderr, " -F (flush - delete all rules)\n");
fprintf(stderr, " -L (list all rules)\n");
fprintf(stderr, "Mandatory: -s <src_dev> (source netdevice)\n");
fprintf(stderr, " -d <dst_dev> (destination netdevice)\n");
req.nh.nlmsg_type = RTM_DELROUTE;
break;
+ case FLUSH:
+ req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ req.nh.nlmsg_type = RTM_DELROUTE;
+ /* if_index set to 0 => remove all entries */
+ req.rtcan.src_ifindex = 0;
+ req.rtcan.dst_ifindex = 0;
+ break;
+
case LIST:
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
req.nh.nlmsg_type = RTM_GETROUTE;
/* clean netlink receive buffer */
bzero(rxbuf, sizeof(rxbuf));
- if (cmd == ADD || cmd == DEL) {
+ if (cmd != LIST) {
+
+ /*
+ * cmd == ADD || cmd == DEL || cmd == FLUSH
+ *
+ * Parse the requested netlink acknowledge return values.
+ */
err = recv(s, &rxbuf, sizeof(rxbuf), 0);
if (err < 0) {
} else {
- /* cmd == LIST (for now) */
+ /* cmd == LIST */
while (1) {
len = recv(s, &rxbuf, sizeof(rxbuf), 0);
return err;
}
+static void gw_remove_all_jobs(void)
+{
+ struct gw_job *gwj = NULL;
+ struct hlist_node *n, *nx;
+
+ spin_lock(&can_gw_list_lock);
+
+ hlist_for_each_entry_safe(gwj, n, nx, &can_gw_list, list) {
+ hlist_del(&gwj->list);
+ can_gw_unregister_filter(gwj);
+ kfree(gwj);
+ }
+
+ spin_unlock(&can_gw_list_lock);
+}
+
static int gw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
struct gw_job *gwj = NULL;
if (r->can_family != AF_CAN)
return -EPFNOSUPPORT;
+ /* if_index set to 0 => remove all entries */
+ if (!r->src_ifindex && !r->dst_ifindex) {
+ gw_remove_all_jobs();
+ return 0;
+ }
+
if (r->can_txflags & CAN_GW_TXFLAGS_ECHO)
flags |= CAN_TX_ECHO;
static __exit void gw_module_exit(void)
{
- struct gw_job *gwj = NULL;
- struct hlist_node *n, *nx;
-
rtnl_unregister_all(PF_CAN);
unregister_netdevice_notifier(¬ifier);
- spin_lock(&can_gw_list_lock);
-
- hlist_for_each_entry_safe(gwj, n, nx, &can_gw_list, list) {
- hlist_del(&gwj->list);
- can_gw_unregister_filter(gwj);
- kfree(gwj);
- }
-
- spin_unlock(&can_gw_list_lock);
+ gw_remove_all_jobs();
rcu_barrier(); /* Wait for completion of call_rcu()'s */