--- zzzz-none-000/linux-2.6.39.4/net/ipv6/addrconf.c 2011-08-03 19:43:28.000000000 +0000 +++ puma6-atom-6490-729/linux-2.6.39.4/net/ipv6/addrconf.c 2021-11-10 13:38:18.000000000 +0000 @@ -37,6 +37,10 @@ * selection; consider scope, * status etc. */ + /* + Includes Intel Corporation's changes/modifications dated: [2/3/2014]. + Changed/modified portions - Copyright © [2014], Intel Corporation. + */ #include #include @@ -184,6 +188,9 @@ #endif .max_addresses = IPV6_MAX_ADDRESSES, .accept_ra_defrtr = 1, +#ifdef CONFIG_IPV6_MULTIPLE_TABLES + .ra_defrtr_table = RT6_TABLE_UNSPEC, +#endif .accept_ra_pinfo = 1, #ifdef CONFIG_IPV6_ROUTER_PREF .accept_ra_rtr_pref = 1, @@ -218,6 +225,9 @@ #endif .max_addresses = IPV6_MAX_ADDRESSES, .accept_ra_defrtr = 1, +#ifdef CONFIG_IPV6_MULTIPLE_TABLES + .ra_defrtr_table = RT6_TABLE_UNSPEC, +#endif .accept_ra_pinfo = 1, #ifdef CONFIG_IPV6_ROUTER_PREF .accept_ra_rtr_pref = 1, @@ -355,7 +365,7 @@ ndev = kzalloc(sizeof(struct inet6_dev), GFP_KERNEL); - if (ndev == NULL) + if (!ndev) return NULL; rwlock_init(&ndev->lock); @@ -366,7 +376,7 @@ ndev->cnf.mtu6 = dev->mtu; ndev->cnf.sysctl = NULL; ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); - if (ndev->nd_parms == NULL) { + if (!ndev->nd_parms) { kfree(ndev); return NULL; } @@ -635,7 +645,7 @@ ifa = kzalloc(sizeof(struct inet6_ifaddr), GFP_ATOMIC); - if (ifa == NULL) { + if (!ifa) { ADBG(("ipv6_add_addr: malloc failed\n")); err = -ENOBUFS; goto out; @@ -668,7 +678,7 @@ * layer address of our nexhop router */ - if (rt->rt6i_nexthop == NULL) + if (!rt->rt6i_nexthop) ifa->flags &= ~IFA_F_OPTIMISTIC; ifa->idev = idev; @@ -1269,6 +1279,46 @@ return err; } +/*! \fn int intel_ipv6_ns_filter(struct net_device *dev,struct in6_addr* dst_addr,unsigned char banned_flags) + * \brief filter neighbour solicit packets not destined to the device + * \param[in] - dev - the device the packet was received in + * \param[in] - dst_addr - the destination address of the packet + * \param[in] - banned_flags - ipv6 address banned flags. the banned flags are the ipv6 adress flags that we want to ignore + * the flags could be + * IFA_F_TEMPORARY,IFA_F_SECONDARY,IFA_F_NODAD, IFA_F_OPTIMISTIC,IFA_F_DADFAILED,IFA_F_HOMEADDRESS,IFA_F_DEPRECATED,IFA_F_TENTATIVE + * so if we want to ignore addresses that are temporary ipv6 addresses we'll add IFA_F_TEMPORARY to banned_flags + * \return 1/0 - 1 = accept, 0 = drop + */ +int intel_ipv6_ns_filter(struct net_device *dev, struct in6_addr* dst_addr,unsigned char banned_flags) +{ + struct inet6_dev *idev; + int accept = 0; + + idev = __in6_dev_get(dev); + if (idev) + { + struct inet6_ifaddr *ifp; + read_lock_bh(&idev->lock); + list_for_each_entry(ifp, &idev->addr_list, if_list) + { + if (!(ifp->flags & banned_flags)) + { + /* compare the last 3 bytes of the destination address to the last 3 bytes of the device's ipv6 address*/ + if ((ifp->addr.in6_u.u6_addr8[15] == dst_addr->in6_u.u6_addr8[15]) && + (ifp->addr.in6_u.u6_addr8[14] == dst_addr->in6_u.u6_addr8[14]) && + (ifp->addr.in6_u.u6_addr8[13] == dst_addr->in6_u.u6_addr8[13])) + { + accept =1; + break; + } + } + } + read_unlock_bh(&idev->lock); + } + return accept; +} + + static int ipv6_count_addresses(struct inet6_dev *idev) { int cnt = 0; @@ -1294,7 +1344,7 @@ continue; if (ipv6_addr_equal(&ifp->addr, addr) && !(ifp->flags&IFA_F_TENTATIVE) && - (dev == NULL || ifp->idev->dev == dev || + (!dev || ifp->idev->dev == dev || !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))) { rcu_read_unlock_bh(); return 1; @@ -1317,7 +1367,7 @@ if (!net_eq(dev_net(ifp->idev->dev), net)) continue; if (ipv6_addr_equal(&ifp->addr, addr)) { - if (dev == NULL || ifp->idev->dev == dev) + if (!dev || ifp->idev->dev == dev) return true; } } @@ -1361,7 +1411,7 @@ if (!net_eq(dev_net(ifp->idev->dev), net)) continue; if (ipv6_addr_equal(&ifp->addr, addr)) { - if (dev == NULL || ifp->idev->dev == dev || + if (!dev || ifp->idev->dev == dev || !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) { result = ifp; in6_ifa_hold(ifp); @@ -1776,6 +1826,41 @@ return idev; } +#if 1 /* PUMA6 ATOM AVM Fix Defect 9966, Defect 9967 */ +static struct rt6_info *addrconf_get_prefix_route(struct in6_addr *pfx, + int plen, + const struct net_device *dev, + u32 flags, u32 noflags) +{ + struct fib6_node *fn; + struct rt6_info *rt = NULL; + struct fib6_table *table; + + table = fib6_get_table(dev_net(dev), RT6_TABLE_PREFIX); + if (!table) + return NULL; + + read_lock_bh(&table->tb6_lock); + fn = fib6_locate(&table->tb6_root, pfx, plen, NULL, 0); + if (!fn) + goto out; + for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { + if (rt->dst.dev->ifindex != dev->ifindex) + continue; + if ((rt->rt6i_flags & flags) != flags) + continue; + if ((rt->rt6i_flags & noflags) != 0) + continue; + dst_hold(&rt->dst); + break; + } +out: + read_unlock_bh(&table->tb6_lock); + return rt; +} +#endif + + void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) { struct prefix_info *pinfo; @@ -1812,7 +1897,7 @@ in6_dev = in6_dev_get(dev); - if (in6_dev == NULL) { + if (!in6_dev) { if (net_ratelimit()) printk(KERN_DEBUG "addrconf: device %s not configured\n", dev->name); return; @@ -1841,10 +1926,20 @@ if (addrconf_finite_timeout(rt_expires)) rt_expires *= HZ; +#if 1 /* PUMA6 ATOM AVM Fix Defect 9966, Defect 9967 */ + rt = addrconf_get_prefix_route(&pinfo->prefix, + pinfo->prefix_len, + dev, + RTF_ADDRCONF | RTF_PREFIX_RT, + RTF_GATEWAY | RTF_DEFAULT); + if (rt) { +#else + rt = rt6_lookup(net, &pinfo->prefix, NULL, dev->ifindex, 1); if (rt && addrconf_is_prefix_route(rt)) { +#endif /* Autoconf prefix route */ if (valid_lft == 0) { ip6_del_rt(rt); @@ -1898,7 +1993,7 @@ ifp = ipv6_get_ifaddr(net, &addr, dev, 1); - if (ifp == NULL && valid_lft) { + if (!ifp && valid_lft) { int max_addresses = in6_dev->cnf.max_addresses; u32 addr_flags = 0; @@ -2062,7 +2157,7 @@ dev = __dev_get_by_index(net, ireq.ifr6_ifindex); err = -ENODEV; - if (dev == NULL) + if (!dev) goto err_exit; #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) @@ -2199,7 +2294,8 @@ if (!dev) return -ENODEV; - if ((idev = __in6_dev_get(dev)) == NULL) + idev = __in6_dev_get(dev); + if (!idev) return -ENXIO; read_lock_bh(&idev->lock); @@ -2340,8 +2436,9 @@ ASSERT_RTNL(); - if ((idev = ipv6_find_idev(dev)) == NULL) { - printk(KERN_DEBUG "init loopback: add_dev failed\n"); + idev = ipv6_find_idev(dev); + if (!idev) { + pr_debug("%s: add_dev failed\n", __func__); return; } @@ -2388,6 +2485,19 @@ if (IS_ERR(idev)) return; + if (idev->cnf.disable_ipv6) + return; + +#ifdef CONFIG_INTEL_DEFAULT_IPV6_AUTOCONF_DISABLES_IPV6_AUTOCONF + /* NETDK: Check if autoconfiguration is enabled for the network device or + * not? */ + if (idev->cnf.autoconf == 0) + { + printk ("Autoconfiguration disabled for %s\n", dev->name); + return; + } +#endif + memset(&addr, 0, sizeof(struct in6_addr)); addr.s6_addr32[0] = htonl(0xFE800000); @@ -2408,8 +2518,9 @@ * our v4 addrs in the tunnel */ - if ((idev = ipv6_find_idev(dev)) == NULL) { - printk(KERN_DEBUG "init sit: add_dev failed\n"); + idev = ipv6_find_idev(dev); + if (!idev) { + pr_debug("%s: add_dev failed\n", __func__); return; } @@ -2520,7 +2631,8 @@ if (idev) { idev->if_flags |= IF_READY; - run_pending = 1; + if (!idev->cnf.disable_ipv6) + run_pending = 1; } } else { if (!addrconf_qdisc_ok(dev)) { @@ -2540,7 +2652,8 @@ "link becomes ready\n", dev->name); - run_pending = 1; + if (idev && !idev->cnf.disable_ipv6) + run_pending = 1; } switch (dev->type) { @@ -2666,7 +2779,7 @@ neigh_ifdown(&nd_tbl, dev); idev = __in6_dev_get(dev); - if (idev == NULL) + if (!idev) return -ENODEV; /* @@ -3298,7 +3411,7 @@ ifm = nlmsg_data(nlh); pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]); - if (pfx == NULL) + if (!pfx) return -EINVAL; return inet6_addr_del(net, ifm->ifa_index, pfx, ifm->ifa_prefixlen); @@ -3368,7 +3481,7 @@ ifm = nlmsg_data(nlh); pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]); - if (pfx == NULL) + if (!pfx) return -EINVAL; if (tb[IFA_CACHEINFO]) { @@ -3383,14 +3496,14 @@ } dev = __dev_get_by_index(net, ifm->ifa_index); - if (dev == NULL) + if (!dev) return -ENODEV; /* We ignore other flags so far. */ ifa_flags = ifm->ifa_flags & (IFA_F_NODAD | IFA_F_HOMEADDRESS); ifa = ipv6_get_ifaddr(net, pfx, dev, 1); - if (ifa == NULL) { + if (!ifa) { /* * It would be best to check for !NLM_F_CREATE here but * userspace alreay relies on not having to provide this. @@ -3463,7 +3576,7 @@ u32 preferred, valid; nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); - if (nlh == NULL) + if (!nlh) return -EMSGSIZE; put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope), @@ -3510,7 +3623,7 @@ scope = RT_SCOPE_SITE; nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); - if (nlh == NULL) + if (!nlh) return -EMSGSIZE; put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); @@ -3535,7 +3648,7 @@ scope = RT_SCOPE_SITE; nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); - if (nlh == NULL) + if (!nlh) return -EMSGSIZE; put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); @@ -3707,7 +3820,7 @@ goto errout; addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]); - if (addr == NULL) { + if (!addr) { err = -EINVAL; goto errout; } @@ -3750,7 +3863,7 @@ int err = -ENOBUFS; skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC); - if (skb == NULL) + if (!skb) goto errout; err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0); @@ -3894,19 +4007,19 @@ NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci); nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32)); - if (nla == NULL) + if (!nla) goto nla_put_failure; ipv6_store_devconf(&idev->cnf, nla_data(nla), nla_len(nla)); /* XXX - MC not implemented */ nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64)); - if (nla == NULL) + if (!nla) goto nla_put_failure; snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla)); nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64)); - if (nla == NULL) + if (!nla) goto nla_put_failure; snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla)); @@ -3946,7 +4059,7 @@ void *protoinfo; nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); - if (nlh == NULL) + if (!nlh) return -EMSGSIZE; hdr = nlmsg_data(nlh); @@ -3967,7 +4080,7 @@ NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); protoinfo = nla_nest_start(skb, IFLA_PROTINFO); - if (protoinfo == NULL) + if (!protoinfo) goto nla_put_failure; if (inet6_fill_ifla6_attrs(skb, idev) < 0) @@ -4028,7 +4141,7 @@ int err = -ENOBUFS; skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC); - if (skb == NULL) + if (!skb) goto errout; err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0); @@ -4061,7 +4174,7 @@ struct prefix_cacheinfo ci; nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags); - if (nlh == NULL) + if (!nlh) return -EMSGSIZE; pmsg = nlmsg_data(nlh); @@ -4099,7 +4212,7 @@ int err = -ENOBUFS; skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC); - if (skb == NULL) + if (!skb) goto errout; err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0); @@ -4428,6 +4541,15 @@ .mode = 0644, .proc_handler = proc_dointvec, }, +#ifdef CONFIG_IPV6_MULTIPLE_TABLES + { + .procname = "ra_defrtr_table", + .data = &ipv6_devconf.ra_defrtr_table, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif #ifdef CONFIG_IPV6_OPTIMISTIC_DAD { .procname = "optimistic_dad", @@ -4492,7 +4614,7 @@ t = kmemdup(&addrconf_sysctl, sizeof(*t), GFP_KERNEL); - if (t == NULL) + if (!t) goto out; for (i = 0; t->addrconf_vars[i].data; i++) { @@ -4514,7 +4636,7 @@ t->sysctl_header = register_net_sysctl_table(net, addrconf_ctl_path, t->addrconf_vars); - if (t->sysctl_header == NULL) + if (!t->sysctl_header) goto free_procname; p->sysctl = t; @@ -4532,7 +4654,7 @@ { struct addrconf_sysctl_table *t; - if (p->sysctl == NULL) + if (!p->sysctl) return; t = p->sysctl; @@ -4570,11 +4692,11 @@ if (!net_eq(net, &init_net)) { all = kmemdup(all, sizeof(ipv6_devconf), GFP_KERNEL); - if (all == NULL) + if (!all) goto err_alloc_all; dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); - if (dflt == NULL) + if (!dflt) goto err_alloc_dflt; } else { /* these will be inherited by all namespaces */ @@ -4743,7 +4865,7 @@ /* clean dev list */ for_each_netdev(&init_net, dev) { - if (__in6_dev_get(dev) == NULL) + if (!__in6_dev_get(dev)) continue; addrconf_ifdown(dev, 1); } @@ -4760,3 +4882,6 @@ del_timer(&addr_chk_timer); rtnl_unlock(); } + + +EXPORT_SYMBOL(intel_ipv6_ns_filter);