--- zzzz-none-000/linux-4.9.279/net/ipv6/addrconf.c 2021-08-08 06:38:54.000000000 +0000 +++ puma7-arm-6591-750/linux-4.9.279/net/ipv6/addrconf.c 2023-02-08 10:58:16.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. + */ #define pr_fmt(fmt) "IPv6: " fmt @@ -180,6 +184,10 @@ int plen, const struct net_device *dev, u32 flags, u32 noflags); +static struct rt6_info *addrconf_get_prefix_route_by_table(const struct in6_addr *pfx, + int plen, + const struct net_device *dev, + u32 flags, u32 noflags, u32 table_id); static void addrconf_dad_start(struct inet6_ifaddr *ifp); static void addrconf_dad_work(struct work_struct *w); @@ -199,6 +207,7 @@ .hop_limit = IPV6_DEFAULT_HOPLIMIT, .mtu6 = IPV6_MIN_MTU, .accept_ra = 1, + .accept_ra_table = RT6_TABLE_DFLT, .accept_redirects = 1, .autoconf = 1, .force_mld_version = 0, @@ -219,6 +228,7 @@ .accept_ra_from_local = 0, .accept_ra_min_hop_limit= 1, .accept_ra_pinfo = 1, + .accept_ra_pinfo_autoconf = 1, #ifdef CONFIG_IPV6_ROUTER_PREF .accept_ra_rtr_pref = 1, .rtr_probe_interval = 60 * HZ, @@ -245,6 +255,7 @@ .hop_limit = IPV6_DEFAULT_HOPLIMIT, .mtu6 = IPV6_MIN_MTU, .accept_ra = 1, + .accept_ra_table = RT6_TABLE_DFLT, .accept_redirects = 1, .autoconf = 1, .force_mld_version = 0, @@ -265,6 +276,7 @@ .accept_ra_from_local = 0, .accept_ra_min_hop_limit= 1, .accept_ra_pinfo = 1, + .accept_ra_pinfo_autoconf = 1, #ifdef CONFIG_IPV6_ROUTER_PREF .accept_ra_rtr_pref = 1, .rtr_probe_interval = 60 * HZ, @@ -1729,6 +1741,45 @@ return err; } +/*! \fn int intel_ipv6_ns_filter(struct net_device *dev, const 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, const 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; @@ -2209,11 +2260,11 @@ */ static void -addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, - unsigned long expires, u32 flags) +addrconf_prefix_route_by_table(struct in6_addr *pfx, int plen, struct net_device *dev, + unsigned long expires, u32 flags, u32 table_id) { struct fib6_config cfg = { - .fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_PREFIX, + .fc_table = table_id, .fc_metric = IP6_RT_PRIO_ADDRCONF, .fc_ifindex = dev->ifindex, .fc_expires = expires, @@ -2236,19 +2287,24 @@ ip6_route_add(&cfg); } +static void +addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, + unsigned long expires, u32 flags) +{ + return addrconf_prefix_route_by_table(pfx, plen, dev, expires, flags, RT6_TABLE_PREFIX); +} -static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, +static struct rt6_info *addrconf_get_prefix_route_by_table(const struct in6_addr *pfx, int plen, const struct net_device *dev, - u32 flags, u32 noflags) + u32 flags, u32 noflags, u32 table_id) { struct fib6_node *fn; struct rt6_info *rt = NULL; struct fib6_table *table; - u32 tb_id = l3mdev_fib_table(dev) ? : RT6_TABLE_PREFIX; - table = fib6_get_table(dev_net(dev), tb_id); + table = fib6_get_table(dev_net(dev), table_id); if (!table) return NULL; @@ -2272,7 +2328,13 @@ read_unlock_bh(&table->tb6_lock); return rt; } - +static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, + int plen, + const struct net_device *dev, + u32 flags, u32 noflags) +{ + return addrconf_get_prefix_route_by_table(pfx, plen, dev, flags, noflags, RT6_TABLE_PREFIX); +} /* Create "default" multicast route to the interface */ @@ -2485,6 +2547,10 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) { + return addrconf_prefix_rcv_by_table(dev, opt, len, sllao, RT6_TABLE_PREFIX); +} +void addrconf_prefix_rcv_by_table(struct net_device *dev, u8 *opt, int len, bool sllao, u32 table_id) +{ struct prefix_info *pinfo; __u32 valid_lft; __u32 prefered_lft; @@ -2548,11 +2614,11 @@ if (addrconf_finite_timeout(rt_expires)) rt_expires *= HZ; - rt = addrconf_get_prefix_route(&pinfo->prefix, + rt = addrconf_get_prefix_route_by_table(&pinfo->prefix, pinfo->prefix_len, dev, RTF_ADDRCONF | RTF_PREFIX_RT, - RTF_GATEWAY | RTF_DEFAULT); + RTF_GATEWAY | RTF_DEFAULT, table_id); if (rt) { /* Autoconf prefix route */ @@ -2573,15 +2639,15 @@ flags |= RTF_EXPIRES; expires = jiffies_to_clock_t(rt_expires); } - addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len, - dev, expires, flags); + addrconf_prefix_route_by_table(&pinfo->prefix, pinfo->prefix_len, + dev, expires, flags, table_id); } ip6_rt_put(rt); } /* Try to figure out our local address for this prefix */ - if (pinfo->autoconf && in6_dev->cnf.autoconf) { + if (pinfo->autoconf && in6_dev->cnf.autoconf && in6_dev->cnf.accept_ra_pinfo_autoconf) { struct in6_addr addr; bool tokenized = false, dev_addr_generated = false; @@ -2846,6 +2912,17 @@ ipv6_mc_config(net->ipv6.mc_autojoin_sk, false, pfx, dev->ifindex); } +#ifdef CONFIG_INTEL_KERNEL_FORCE_IPV6_DOWN_WHEN_NO_ADDRES + /*Added this code in order to avoid transmit messages over + IPv6 w/o receiving DHCP Advertisment messages*/ + /* If the last address is deleted administratively, + disable IPv6 on this interface. + */ + if (list_empty(&idev->addr_list)) + { + addrconf_ifdown(idev->dev, 1); + } +#endif return 0; } } @@ -3201,6 +3278,16 @@ if (IS_ERR(idev)) 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 + /* this device type has no EUI support */ if (dev->type == ARPHRD_NONE && idev->addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64) @@ -3539,6 +3626,7 @@ struct list_head del_list; int _keep_addr; bool keep_addr; + bool was_ready; int state, i; ASSERT_RTNL(); @@ -3602,7 +3690,10 @@ addrconf_del_rs_timer(idev); - /* Step 2: clear flags for stateless addrconf */ + /* Step 2: clear flags for stateless addrconf, repeated down + * detection + */ + was_ready = idev->if_flags & IF_READY; if (!how) idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); @@ -3689,7 +3780,7 @@ if (how) { ipv6_ac_destroy_dev(idev); ipv6_mc_destroy_dev(idev); - } else { + } else if (was_ready) { ipv6_mc_down(idev); } @@ -4934,6 +5025,7 @@ array[DEVCONF_HOPLIMIT] = cnf->hop_limit; array[DEVCONF_MTU6] = cnf->mtu6; array[DEVCONF_ACCEPT_RA] = cnf->accept_ra; + array[DEVCONF_ACCEPT_RA_TABLE] = cnf->accept_ra_table; array[DEVCONF_ACCEPT_REDIRECTS] = cnf->accept_redirects; array[DEVCONF_AUTOCONF] = cnf->autoconf; array[DEVCONF_DAD_TRANSMITS] = cnf->dad_transmits; @@ -4958,6 +5050,7 @@ array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr; array[DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT] = cnf->accept_ra_min_hop_limit; array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo; + array[DEVCONF_ACCEPT_RA_PINFO_AUTOCONF] = cnf->accept_ra_pinfo_autoconf; #ifdef CONFIG_IPV6_ROUTER_PREF array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref; array[DEVCONF_RTR_PROBE_INTERVAL] = @@ -5793,6 +5886,13 @@ .proc_handler = proc_dointvec, }, { + .procname = "accept_ra_table", + .data = &ipv6_devconf.accept_ra_table, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { .procname = "accept_redirects", .data = &ipv6_devconf.accept_redirects, .maxlen = sizeof(int), @@ -5928,6 +6028,13 @@ .mode = 0644, .proc_handler = proc_dointvec, }, + { + .procname = "accept_ra_pinfo_autoconf", + .data = &ipv6_devconf.accept_ra_pinfo_autoconf, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, #ifdef CONFIG_IPV6_ROUTER_PREF { .procname = "accept_ra_rtr_pref", @@ -6372,3 +6479,5 @@ destroy_workqueue(addrconf_wq); } + +EXPORT_SYMBOL(intel_ipv6_ns_filter); \ No newline at end of file