--- zzzz-none-000/linux-3.10.107/net/ipv6/ip6mr.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/net/ipv6/ip6mr.c 2021-02-04 17:41:59.000000000 +0000 @@ -56,9 +56,7 @@ struct mr6_table { struct list_head list; -#ifdef CONFIG_NET_NS - struct net *net; -#endif + possible_net_t net; u32 id; struct sock *mroute6_sk; struct timer_list ipmr_expire_timer; @@ -110,8 +108,8 @@ static struct mr6_table *ip6mr_new_table(struct net *net, u32 id); static void ip6mr_free_table(struct mr6_table *mrt); -static int ip6_mr_forward(struct net *net, struct mr6_table *mrt, - struct sk_buff *skb, struct mfc6_cache *cache); +static void ip6_mr_forward(struct net *net, struct mr6_table *mrt, + struct sk_buff *skb, struct mfc6_cache *cache); static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt, mifi_t mifi, int assert); static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, @@ -122,6 +120,11 @@ struct netlink_callback *cb); static void mroute_clean_tables(struct mr6_table *mrt, bool all); static void ipmr_expire_process(unsigned long arg); +static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt, + const struct in6_addr *origin, + const struct in6_addr *mcastgrp); +static ip6mr_mfc_event_offload_callback_t __rcu + ip6mr_mfc_event_offload_callback; #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES #define ip6mr_for_each_table(mrt, net) \ @@ -169,13 +172,15 @@ return -ENETUNREACH; case FR_ACT_PROHIBIT: return -EACCES; + case FR_ACT_POLICY_FAILED: + return -EACCES; case FR_ACT_BLACKHOLE: default: return -EINVAL; } mrt = ip6mr_get_table(rule->fr_net, rule->table); - if (mrt == NULL) + if (!mrt) return -EAGAIN; res->mrt = mrt; return 0; @@ -219,7 +224,6 @@ .match = ip6mr_rule_match, .configure = ip6mr_rule_configure, .compare = ip6mr_rule_compare, - .default_pref = fib_default_rule_pref, .fill = ip6mr_rule_fill, .nlgroup = RTNLGRP_IPV6_RULE, .policy = ip6mr_rule_policy, @@ -239,7 +243,7 @@ INIT_LIST_HEAD(&net->ipv6.mr6_tables); mrt = ip6mr_new_table(net, RT6_TABLE_DFLT); - if (mrt == NULL) { + if (!mrt) { err = -ENOMEM; goto err1; } @@ -252,7 +256,7 @@ return 0; err2: - kfree(mrt); + ip6mr_free_table(mrt); err1: fib_rules_unregister(ops); return err; @@ -267,8 +271,8 @@ list_del(&mrt->list); ip6mr_free_table(mrt); } - rtnl_unlock(); fib_rules_unregister(net->ipv6.mr6_rules_ops); + rtnl_unlock(); } #else #define ip6mr_for_each_table(mrt, net) \ @@ -307,11 +311,11 @@ unsigned int i; mrt = ip6mr_get_table(net, id); - if (mrt != NULL) + if (mrt) return mrt; mrt = kzalloc(sizeof(*mrt), GFP_KERNEL); - if (mrt == NULL) + if (!mrt) return NULL; mrt->id = id; write_pnet(&mrt->net, net); @@ -341,6 +345,82 @@ kfree(mrt); } +/* ip6mr_sync_entry_update() + * Call the registered offload callback to report an update to a multicast + * route entry. The callback receives the list of destination interfaces and + * the interface count + */ +static void ip6mr_sync_entry_update(struct mr6_table *mrt, + struct mfc6_cache *cache) +{ + int vifi, dest_if_count = 0; + u32 dest_dev[MAXMIFS]; + struct in6_addr mc_origin, mc_group; + ip6mr_mfc_event_offload_callback_t offload_update_cb_f; + + memset(dest_dev, 0, sizeof(dest_dev)); + + read_lock(&mrt_lock); + + for (vifi = 0; vifi < cache->mfc_un.res.maxvif; vifi++) { + if (!((cache->mfc_un.res.ttls[vifi] > 0) && + (cache->mfc_un.res.ttls[vifi] < 255))) { + continue; + } + + if (dest_if_count == MAXMIFS) { + read_unlock(&mrt_lock); + return; + } + + if (!MIF_EXISTS(mrt, vifi)) { + read_unlock(&mrt_lock); + return; + } + + dest_dev[dest_if_count] = mrt->vif6_table[vifi].dev->ifindex; + dest_if_count++; + } + + memcpy(&mc_origin, &cache->mf6c_origin, sizeof(struct in6_addr)); + memcpy(&mc_group, &cache->mf6c_mcastgrp, sizeof(struct in6_addr)); + read_unlock(&mrt_lock); + + rcu_read_lock(); + offload_update_cb_f = rcu_dereference(ip6mr_mfc_event_offload_callback); + + if (!offload_update_cb_f) { + rcu_read_unlock(); + return; + } + + offload_update_cb_f(&mc_group, &mc_origin, dest_if_count, dest_dev, + IP6MR_MFC_EVENT_UPDATE); + rcu_read_unlock(); +} + +/* ip6mr_sync_entry_delete() + * Call the registered offload callback to inform of a multicast route entry + * delete event + */ +static void ip6mr_sync_entry_delete(struct in6_addr *mc_origin, + struct in6_addr *mc_group) +{ + ip6mr_mfc_event_offload_callback_t offload_update_cb_f; + + rcu_read_lock(); + offload_update_cb_f = rcu_dereference(ip6mr_mfc_event_offload_callback); + + if (!offload_update_cb_f) { + rcu_read_unlock(); + return; + } + + offload_update_cb_f(mc_group, mc_origin, 0, NULL, + IP6MR_MFC_EVENT_DELETE); + rcu_read_unlock(); +} + #ifdef CONFIG_PROC_FS struct ipmr_mfc_iter { @@ -410,7 +490,7 @@ struct mr6_table *mrt; mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); - if (mrt == NULL) + if (!mrt) return ERR_PTR(-ENOENT); iter->mrt = mrt; @@ -457,7 +537,7 @@ const char *name = vif->dev ? vif->dev->name : "none"; seq_printf(seq, - "%2td %-10s %8ld %7ld %8ld %7ld %05X\n", + "%2td %-10s %8llu %7llu %8llu %7llu %05X\n", vif - mrt->vif6_table, name, vif->bytes_in, vif->pkt_in, vif->bytes_out, vif->pkt_out, @@ -494,7 +574,7 @@ struct mr6_table *mrt; mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); - if (mrt == NULL) + if (!mrt) return ERR_PTR(-ENOENT); it->mrt = mrt; @@ -667,7 +747,7 @@ dev_hold(reg_dev); read_unlock(&mrt_lock); - if (reg_dev == NULL) + if (!reg_dev) goto drop; skb->mac_header = skb->network_header; @@ -675,9 +755,8 @@ skb_reset_network_header(skb); skb->protocol = htons(ETH_P_IPV6); skb->ip_summed = CHECKSUM_NONE; - skb->pkt_type = PACKET_HOST; - skb_tunnel_rx(skb, reg_dev); + skb_tunnel_rx(skb, reg_dev, dev_net(reg_dev)); netif_rx(skb); @@ -701,7 +780,7 @@ struct mr6_table *mrt; struct flowi6 fl6 = { .flowi6_oif = dev->ifindex, - .flowi6_iif = skb->skb_iif, + .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX, .flowi6_mark = skb->mark, }; int err; @@ -721,8 +800,14 @@ return NETDEV_TX_OK; } +static int reg_vif_get_iflink(const struct net_device *dev) +{ + return 0; +} + static const struct net_device_ops reg_vif_netdev_ops = { .ndo_start_xmit = reg_vif_xmit, + .ndo_get_iflink = reg_vif_get_iflink, }; static void reg_vif_setup(struct net_device *dev) @@ -745,8 +830,8 @@ else sprintf(name, "pim6reg%u", mrt->id); - dev = alloc_netdev(0, name, reg_vif_setup); - if (dev == NULL) + dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, reg_vif_setup); + if (!dev) return NULL; dev_net_set(dev, net); @@ -755,7 +840,6 @@ free_netdev(dev); return NULL; } - dev->iflink = 0; if (dev_open(dev)) goto failure; @@ -764,21 +848,155 @@ return dev; failure: - /* allow the register to be completed before unregistering. */ - rtnl_unlock(); - rtnl_lock(); - unregister_netdevice(dev); return NULL; } #endif +/* ip6mr_register_mfc_event_offload_callback() + * Register the IPv6 multicast update callback for offload modules + */ +bool ip6mr_register_mfc_event_offload_callback( + ip6mr_mfc_event_offload_callback_t mfc_offload_cb) +{ + ip6mr_mfc_event_offload_callback_t offload_update_cb_f; + + rcu_read_lock(); + offload_update_cb_f = rcu_dereference(ip6mr_mfc_event_offload_callback); + + if (offload_update_cb_f) { + rcu_read_unlock(); + return false; + } + + rcu_assign_pointer(ip6mr_mfc_event_offload_callback, mfc_offload_cb); + rcu_read_unlock(); + return true; +} +EXPORT_SYMBOL(ip6mr_register_mfc_event_offload_callback); + +/* ip6mr_unregister_mfc_event_offload_callback() + * De-register the IPv6 multicast update callback for offload modules + */ +void ip6mr_unregister_mfc_event_offload_callback(void) +{ + rcu_read_lock(); + rcu_assign_pointer(ip6mr_mfc_event_offload_callback, NULL); + rcu_read_unlock(); +} +EXPORT_SYMBOL(ip6mr_unregister_mfc_event_offload_callback); + +/* ip6mr_find_mfc_entry() + * Return the destination interface list for a particular multicast flow, and + * the number of interfaces in the list + */ +int ip6mr_find_mfc_entry(struct net *net, struct in6_addr *origin, + struct in6_addr *group, u32 max_dest_cnt, + u32 dest_dev[]) +{ + int vifi, dest_if_count = 0; + struct mr6_table *mrt; + struct mfc6_cache *cache; + + mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); + if (!mrt) + return -ENOENT; + + read_lock(&mrt_lock); + cache = ip6mr_cache_find(mrt, origin, group); + if (!cache) { + read_unlock(&mrt_lock); + return -ENOENT; + } + + for (vifi = 0; vifi < cache->mfc_un.res.maxvif; vifi++) { + if (!((cache->mfc_un.res.ttls[vifi] > 0) && + (cache->mfc_un.res.ttls[vifi] < 255))) { + continue; + } + + /* We have another valid destination interface entry. Check if + * the number of the destination interfaces for the route is + * exceeding the size of the array given to us + */ + if (dest_if_count == max_dest_cnt) { + read_unlock(&mrt_lock); + return -EINVAL; + } + + if (!MIF_EXISTS(mrt, vifi)) { + read_unlock(&mrt_lock); + return -EINVAL; + } + + dest_dev[dest_if_count] = mrt->vif6_table[vifi].dev->ifindex; + dest_if_count++; + } + read_unlock(&mrt_lock); + + return dest_if_count; +} +EXPORT_SYMBOL(ip6mr_find_mfc_entry); + +/* ip6mr_mfc_stats_update() + * Update the MFC/VIF statistics for offloaded flows + */ +int ip6mr_mfc_stats_update(struct net *net, struct in6_addr *origin, + struct in6_addr *group, u64 pkts_in, + u64 bytes_in, uint64_t pkts_out, + u64 bytes_out) +{ + int vif, vifi; + struct mr6_table *mrt; + struct mfc6_cache *cache; + + mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); + + if (!mrt) + return -ENOENT; + + read_lock(&mrt_lock); + cache = ip6mr_cache_find(mrt, origin, group); + if (!cache) { + read_unlock(&mrt_lock); + return -ENOENT; + } + + vif = cache->mf6c_parent; + + if (!MIF_EXISTS(mrt, vif)) { + read_unlock(&mrt_lock); + return -EINVAL; + } + + mrt->vif6_table[vif].pkt_in += pkts_in; + mrt->vif6_table[vif].bytes_in += bytes_in; + cache->mfc_un.res.pkt += pkts_out; + cache->mfc_un.res.bytes += bytes_out; + + for (vifi = cache->mfc_un.res.minvif; + vifi < cache->mfc_un.res.maxvif; vifi++) { + if ((cache->mfc_un.res.ttls[vifi] > 0) && + (cache->mfc_un.res.ttls[vifi] < 255)) { + if (!MIF_EXISTS(mrt, vifi)) { + read_unlock(&mrt_lock); + return -EINVAL; + } + mrt->vif6_table[vifi].pkt_out += pkts_out; + mrt->vif6_table[vifi].bytes_out += bytes_out; + } + } + + read_unlock(&mrt_lock); + return 0; +} +EXPORT_SYMBOL(ip6mr_mfc_stats_update); + /* * Delete a VIF entry */ -static int mif6_delete(struct mr6_table *mrt, int vifi, int notify, - struct list_head *head) +static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head) { struct mif_device *v; struct net_device *dev; @@ -824,7 +1042,7 @@ dev->ifindex, &in6_dev->cnf); } - if ((v->flags & MIFF_REGISTER) && !notify) + if (v->flags & MIFF_REGISTER) unregister_netdevice_queue(dev, head); dev_put(dev); @@ -847,7 +1065,7 @@ atomic_dec(&mrt->cache_resolve_queue_len); - while((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) { + while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) { if (ipv6_hdr(skb)->version == 0) { struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); nlh->nlmsg_type = NLMSG_ERROR; @@ -996,7 +1214,7 @@ v->pkt_out = 0; v->link = dev->ifindex; if (v->flags & MIFF_REGISTER) - v->link = dev->iflink; + v->link = dev_get_iflink(dev); /* And finish update writing critical data */ write_lock_bh(&mrt_lock); @@ -1076,7 +1294,7 @@ static struct mfc6_cache *ip6mr_cache_alloc(void) { struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); - if (c == NULL) + if (!c) return NULL; c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1; c->mfc_un.res.minvif = MAXMIFS; @@ -1086,7 +1304,7 @@ static struct mfc6_cache *ip6mr_cache_alloc_unres(void) { struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); - if (c == NULL) + if (!c) return NULL; skb_queue_head_init(&c->mfc_un.unres.unresolved); c->mfc_un.unres.expires = jiffies + 10 * HZ; @@ -1106,7 +1324,7 @@ * Play the pending entries through our router */ - while((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { + while ((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { if (ipv6_hdr(skb)->version == 0) { struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); @@ -1203,7 +1421,7 @@ skb->ip_summed = CHECKSUM_UNNECESSARY; } - if (mrt->mroute6_sk == NULL) { + if (!mrt->mroute6_sk) { kfree_skb(skb); return -EINVAL; } @@ -1306,6 +1524,7 @@ { int line; struct mfc6_cache *c, *next; + struct in6_addr mc_origin, mc_group; line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); @@ -1314,12 +1533,20 @@ ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr) && (parent == -1 || parent == c->mf6c_parent)) { + memcpy(&mc_origin, &c->mf6c_origin, + sizeof(struct in6_addr)); + memcpy(&mc_group, &c->mf6c_mcastgrp, + sizeof(struct in6_addr)); + write_lock_bh(&mrt_lock); list_del(&c->list); write_unlock_bh(&mrt_lock); mr6_netlink_event(mrt, c, RTM_DELROUTE); ip6mr_cache_free(c); + + /* Inform offload modules of the delete event */ + ip6mr_sync_entry_delete(&mc_origin, &mc_group); return 0; } } @@ -1329,11 +1556,12 @@ static int ip6mr_device_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); struct mr6_table *mrt; struct mif_device *v; int ct; + LIST_HEAD(list); if (event != NETDEV_UNREGISTER) return NOTIFY_DONE; @@ -1342,9 +1570,10 @@ v = &mrt->vif6_table[0]; for (ct = 0; ct < mrt->maxvif; ct++, v++) { if (v->dev == dev) - mif6_delete(mrt, ct, 1, NULL); + mif6_delete(mrt, ct, &list); } } + unregister_netdevice_many(&list); return NOTIFY_DONE; } @@ -1440,6 +1669,10 @@ void ip6_mr_cleanup(void) { + rtnl_unregister(RTNL_FAMILY_IP6MR, RTM_GETROUTE); +#ifdef CONFIG_IPV6_PIMSM_V2 + inet6_del_protocol(&pim6_protocol, IPPROTO_PIM); +#endif unregister_netdevice_notifier(&ip6_mr_notifier); unregister_pernet_subsys(&ip6mr_net_ops); kmem_cache_destroy(mrt_cachep); @@ -1484,6 +1717,9 @@ c->mfc_flags |= MFC_STATIC; write_unlock_bh(&mrt_lock); mr6_netlink_event(mrt, c, RTM_NEWROUTE); + + /* Inform offload modules of the update event */ + ip6mr_sync_entry_update(mrt, c); return 0; } @@ -1492,7 +1728,7 @@ return -EINVAL; c = ip6mr_cache_alloc(); - if (c == NULL) + if (!c) return -ENOMEM; c->mf6c_origin = mfc->mf6cc_origin.sin6_addr; @@ -1542,6 +1778,7 @@ int i; LIST_HEAD(list); struct mfc6_cache *c, *next; + struct in6_addr mc_origin, mc_group; /* * Shut down all active vif entries @@ -1549,7 +1786,7 @@ for (i = 0; i < mrt->maxvif; i++) { if (!all && (mrt->vif6_table[i].flags & VIFF_STATIC)) continue; - mif6_delete(mrt, i, 0, &list); + mif6_delete(mrt, i, &list); } unregister_netdevice_many(&list); @@ -1560,12 +1797,19 @@ list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[i], list) { if (!all && (c->mfc_flags & MFC_STATIC)) continue; + memcpy(&mc_origin, &c->mf6c_origin, + sizeof(struct in6_addr)); + memcpy(&mc_group, &c->mf6c_mcastgrp, + sizeof(struct in6_addr)); write_lock_bh(&mrt_lock); list_del(&c->list); write_unlock_bh(&mrt_lock); mr6_netlink_event(mrt, c, RTM_DELROUTE); ip6mr_cache_free(c); + + /* Inform offload modules of the delete event */ + ip6mr_sync_entry_delete(&mc_origin, &mc_group); } } @@ -1635,7 +1879,7 @@ { struct mr6_table *mrt; struct flowi6 fl6 = { - .flowi6_iif = skb->skb_iif, + .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX, .flowi6_oif = skb->dev->ifindex, .flowi6_mark = skb->mark, }; @@ -1663,7 +1907,7 @@ struct mr6_table *mrt; mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); - if (mrt == NULL) + if (!mrt) return -ENOENT; if (optname != MRT6_INIT) { @@ -1702,7 +1946,7 @@ if (copy_from_user(&mifi, optval, sizeof(mifi_t))) return -EFAULT; rtnl_lock(); - ret = mif6_delete(mrt, mifi, 0, NULL); + ret = mif6_delete(mrt, mifi, NULL); rtnl_unlock(); return ret; @@ -1812,7 +2056,7 @@ struct mr6_table *mrt; mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); - if (mrt == NULL) + if (!mrt) return -ENOENT; switch (optname) { @@ -1859,7 +2103,7 @@ struct mr6_table *mrt; mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); - if (mrt == NULL) + if (!mrt) return -ENOENT; switch (cmd) { @@ -1933,7 +2177,7 @@ struct mr6_table *mrt; mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); - if (mrt == NULL) + if (!mrt) return -ENOENT; switch (cmd) { @@ -1981,13 +2225,13 @@ } #endif -static inline int ip6mr_forward2_finish(struct sk_buff *skb) +static inline int ip6mr_forward2_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { - IP6_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)), + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTFORWDATAGRAMS); - IP6_ADD_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)), + IP6_ADD_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTOCTETS, skb->len); - return dst_output(skb); + return dst_output(net, sk, skb); } /* @@ -2003,7 +2247,7 @@ struct dst_entry *dst; struct flowi6 fl6; - if (vif->dev == NULL) + if (!vif->dev) goto out_free; #ifdef CONFIG_IPV6_PIMSM_V2 @@ -2059,7 +2303,8 @@ IP6CB(skb)->flags |= IP6SKB_FORWARDED; - return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dev, + return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, + net, NULL, skb, skb->dev, dev, ip6mr_forward2_finish); out_free: @@ -2078,8 +2323,8 @@ return ct; } -static int ip6_mr_forward(struct net *net, struct mr6_table *mrt, - struct sk_buff *skb, struct mfc6_cache *cache) +static void ip6_mr_forward(struct net *net, struct mr6_table *mrt, + struct sk_buff *skb, struct mfc6_cache *cache) { int psend = -1; int vif, ct; @@ -2092,7 +2337,7 @@ if (ipv6_addr_any(&cache->mf6c_origin) && true_vifi >= 0) { struct mfc6_cache *cache_proxy; - /* For an (*,G) entry, we only check that the incomming + /* For an (*,G) entry, we only check that the incoming * interface is part of the static tree. */ cache_proxy = ip6mr_cache_find_any_parent(mrt, vif); @@ -2160,12 +2405,11 @@ last_forward: if (psend != -1) { ip6mr_forward2(net, mrt, skb, cache, psend); - return 0; + return; } dont_forward: kfree_skb(skb); - return 0; } @@ -2193,7 +2437,7 @@ read_lock(&mrt_lock); cache = ip6mr_cache_find(mrt, &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr); - if (cache == NULL) { + if (!cache) { int vif = ip6mr_find_vif(mrt, skb->dev); if (vif >= 0) @@ -2205,7 +2449,7 @@ /* * No usable cache entry */ - if (cache == NULL) { + if (!cache) { int vif; vif = ip6mr_find_vif(mrt, skb->dev); @@ -2244,13 +2488,13 @@ nla_put_u32(skb, RTA_IIF, mrt->vif6_table[c->mf6c_parent].dev->ifindex) < 0) return -EMSGSIZE; mp_attr = nla_nest_start(skb, RTA_MULTIPATH); - if (mp_attr == NULL) + if (!mp_attr) return -EMSGSIZE; for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { if (MIF_EXISTS(mrt, ct) && c->mfc_un.res.ttls[ct] < 255) { nhp = nla_reserve_nohdr(skb, sizeof(*nhp)); - if (nhp == NULL) { + if (!nhp) { nla_nest_cancel(skb, mp_attr); return -EMSGSIZE; } @@ -2283,7 +2527,7 @@ struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); - if (mrt == NULL) + if (!mrt) return -ENOENT; read_lock(&mrt_lock); @@ -2308,7 +2552,7 @@ } dev = skb->dev; - if (dev == NULL || (vif = ip6mr_find_vif(mrt, dev)) < 0) { + if (!dev || (vif = ip6mr_find_vif(mrt, dev)) < 0) { read_unlock(&mrt_lock); return -ENODEV; } @@ -2361,7 +2605,7 @@ int err; nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags); - if (nlh == NULL) + if (!nlh) return -EMSGSIZE; rtm = nlmsg_data(nlh); @@ -2380,15 +2624,16 @@ rtm->rtm_protocol = RTPROT_MROUTED; rtm->rtm_flags = 0; - if (nla_put(skb, RTA_SRC, 16, &c->mf6c_origin) || - nla_put(skb, RTA_DST, 16, &c->mf6c_mcastgrp)) + if (nla_put_in6_addr(skb, RTA_SRC, &c->mf6c_origin) || + nla_put_in6_addr(skb, RTA_DST, &c->mf6c_mcastgrp)) goto nla_put_failure; err = __ip6mr_fill_mroute(mrt, skb, c, rtm); /* do not break the dump if cache is unresolved */ if (err < 0 && err != -ENOENT) goto nla_put_failure; - return nlmsg_end(skb, nlh); + nlmsg_end(skb, nlh); + return 0; nla_put_failure: nlmsg_cancel(skb, nlh); @@ -2425,7 +2670,7 @@ skb = nlmsg_new(mr6_msgsize(mfc->mf6c_parent >= MAXMIFS, mrt->maxvif), GFP_ATOMIC); - if (skb == NULL) + if (!skb) goto errout; err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);