LCOV - code coverage report
Current view: top level - net/ipv6 - ndisc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 56 588 9.5 %
Date: 2014-04-07 Functions: 7 39 17.9 %
Branches: 42 498 8.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *      Neighbour Discovery for IPv6
       3                 :            :  *      Linux INET6 implementation
       4                 :            :  *
       5                 :            :  *      Authors:
       6                 :            :  *      Pedro Roque             <roque@di.fc.ul.pt>
       7                 :            :  *      Mike Shaver             <shaver@ingenia.com>
       8                 :            :  *
       9                 :            :  *      This program is free software; you can redistribute it and/or
      10                 :            :  *      modify it under the terms of the GNU General Public License
      11                 :            :  *      as published by the Free Software Foundation; either version
      12                 :            :  *      2 of the License, or (at your option) any later version.
      13                 :            :  */
      14                 :            : 
      15                 :            : /*
      16                 :            :  *      Changes:
      17                 :            :  *
      18                 :            :  *      Alexey I. Froloff               :       RFC6106 (DNSSL) support
      19                 :            :  *      Pierre Ynard                    :       export userland ND options
      20                 :            :  *                                              through netlink (RDNSS support)
      21                 :            :  *      Lars Fenneberg                  :       fixed MTU setting on receipt
      22                 :            :  *                                              of an RA.
      23                 :            :  *      Janos Farkas                    :       kmalloc failure checks
      24                 :            :  *      Alexey Kuznetsov                :       state machine reworked
      25                 :            :  *                                              and moved to net/core.
      26                 :            :  *      Pekka Savola                    :       RFC2461 validation
      27                 :            :  *      YOSHIFUJI Hideaki @USAGI        :       Verify ND options properly
      28                 :            :  */
      29                 :            : 
      30                 :            : #define pr_fmt(fmt) "ICMPv6: " fmt
      31                 :            : 
      32                 :            : #include <linux/module.h>
      33                 :            : #include <linux/errno.h>
      34                 :            : #include <linux/types.h>
      35                 :            : #include <linux/socket.h>
      36                 :            : #include <linux/sockios.h>
      37                 :            : #include <linux/sched.h>
      38                 :            : #include <linux/net.h>
      39                 :            : #include <linux/in6.h>
      40                 :            : #include <linux/route.h>
      41                 :            : #include <linux/init.h>
      42                 :            : #include <linux/rcupdate.h>
      43                 :            : #include <linux/slab.h>
      44                 :            : #ifdef CONFIG_SYSCTL
      45                 :            : #include <linux/sysctl.h>
      46                 :            : #endif
      47                 :            : 
      48                 :            : #include <linux/if_addr.h>
      49                 :            : #include <linux/if_arp.h>
      50                 :            : #include <linux/ipv6.h>
      51                 :            : #include <linux/icmpv6.h>
      52                 :            : #include <linux/jhash.h>
      53                 :            : 
      54                 :            : #include <net/sock.h>
      55                 :            : #include <net/snmp.h>
      56                 :            : 
      57                 :            : #include <net/ipv6.h>
      58                 :            : #include <net/protocol.h>
      59                 :            : #include <net/ndisc.h>
      60                 :            : #include <net/ip6_route.h>
      61                 :            : #include <net/addrconf.h>
      62                 :            : #include <net/icmp.h>
      63                 :            : 
      64                 :            : #include <net/netlink.h>
      65                 :            : #include <linux/rtnetlink.h>
      66                 :            : 
      67                 :            : #include <net/flow.h>
      68                 :            : #include <net/ip6_checksum.h>
      69                 :            : #include <net/inet_common.h>
      70                 :            : #include <linux/proc_fs.h>
      71                 :            : 
      72                 :            : #include <linux/netfilter.h>
      73                 :            : #include <linux/netfilter_ipv6.h>
      74                 :            : 
      75                 :            : /* Set to 3 to get tracing... */
      76                 :            : #define ND_DEBUG 1
      77                 :            : 
      78                 :            : #define ND_PRINTK(val, level, fmt, ...)                         \
      79                 :            : do {                                                            \
      80                 :            :         if (val <= ND_DEBUG)                                 \
      81                 :            :                 net_##level##_ratelimited(fmt, ##__VA_ARGS__);  \
      82                 :            : } while (0)
      83                 :            : 
      84                 :            : static u32 ndisc_hash(const void *pkey,
      85                 :            :                       const struct net_device *dev,
      86                 :            :                       __u32 *hash_rnd);
      87                 :            : static int ndisc_constructor(struct neighbour *neigh);
      88                 :            : static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
      89                 :            : static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
      90                 :            : static int pndisc_constructor(struct pneigh_entry *n);
      91                 :            : static void pndisc_destructor(struct pneigh_entry *n);
      92                 :            : static void pndisc_redo(struct sk_buff *skb);
      93                 :            : 
      94                 :            : static const struct neigh_ops ndisc_generic_ops = {
      95                 :            :         .family =               AF_INET6,
      96                 :            :         .solicit =              ndisc_solicit,
      97                 :            :         .error_report =         ndisc_error_report,
      98                 :            :         .output =               neigh_resolve_output,
      99                 :            :         .connected_output =     neigh_connected_output,
     100                 :            : };
     101                 :            : 
     102                 :            : static const struct neigh_ops ndisc_hh_ops = {
     103                 :            :         .family =               AF_INET6,
     104                 :            :         .solicit =              ndisc_solicit,
     105                 :            :         .error_report =         ndisc_error_report,
     106                 :            :         .output =               neigh_resolve_output,
     107                 :            :         .connected_output =     neigh_resolve_output,
     108                 :            : };
     109                 :            : 
     110                 :            : 
     111                 :            : static const struct neigh_ops ndisc_direct_ops = {
     112                 :            :         .family =               AF_INET6,
     113                 :            :         .output =               neigh_direct_output,
     114                 :            :         .connected_output =     neigh_direct_output,
     115                 :            : };
     116                 :            : 
     117                 :            : struct neigh_table nd_tbl = {
     118                 :            :         .family =       AF_INET6,
     119                 :            :         .key_len =      sizeof(struct in6_addr),
     120                 :            :         .hash =         ndisc_hash,
     121                 :            :         .constructor =  ndisc_constructor,
     122                 :            :         .pconstructor = pndisc_constructor,
     123                 :            :         .pdestructor =  pndisc_destructor,
     124                 :            :         .proxy_redo =   pndisc_redo,
     125                 :            :         .id =           "ndisc_cache",
     126                 :            :         .parms = {
     127                 :            :                 .tbl                    = &nd_tbl,
     128                 :            :                 .base_reachable_time    = ND_REACHABLE_TIME,
     129                 :            :                 .retrans_time           = ND_RETRANS_TIMER,
     130                 :            :                 .gc_staletime           = 60 * HZ,
     131                 :            :                 .reachable_time         = ND_REACHABLE_TIME,
     132                 :            :                 .delay_probe_time       = 5 * HZ,
     133                 :            :                 .queue_len_bytes        = 64*1024,
     134                 :            :                 .ucast_probes           = 3,
     135                 :            :                 .mcast_probes           = 3,
     136                 :            :                 .anycast_delay          = 1 * HZ,
     137                 :            :                 .proxy_delay            = (8 * HZ) / 10,
     138                 :            :                 .proxy_qlen             = 64,
     139                 :            :         },
     140                 :            :         .gc_interval =    30 * HZ,
     141                 :            :         .gc_thresh1 =    128,
     142                 :            :         .gc_thresh2 =    512,
     143                 :            :         .gc_thresh3 =   1024,
     144                 :            : };
     145                 :            : 
     146                 :          0 : static void ndisc_fill_addr_option(struct sk_buff *skb, int type, void *data)
     147                 :            : {
     148                 :          0 :         int pad   = ndisc_addr_option_pad(skb->dev->type);
     149                 :          0 :         int data_len = skb->dev->addr_len;
     150                 :            :         int space = ndisc_opt_addr_space(skb->dev);
     151                 :          0 :         u8 *opt = skb_put(skb, space);
     152                 :            : 
     153                 :          0 :         opt[0] = type;
     154                 :          0 :         opt[1] = space>>3;
     155                 :            : 
     156         [ #  # ]:          0 :         memset(opt + 2, 0, pad);
     157                 :          0 :         opt   += pad;
     158                 :          0 :         space -= pad;
     159                 :            : 
     160                 :          0 :         memcpy(opt+2, data, data_len);
     161                 :          0 :         data_len += 2;
     162                 :          0 :         opt += data_len;
     163         [ #  # ]:          0 :         if ((space -= data_len) > 0)
     164         [ #  # ]:          0 :                 memset(opt, 0, space);
     165                 :          0 : }
     166                 :            : 
     167                 :          0 : static struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur,
     168                 :            :                                             struct nd_opt_hdr *end)
     169                 :            : {
     170                 :            :         int type;
     171 [ #  # ][ #  # ]:          0 :         if (!cur || !end || cur >= end)
     172                 :            :                 return NULL;
     173                 :          0 :         type = cur->nd_opt_type;
     174                 :            :         do {
     175                 :          0 :                 cur = ((void *)cur) + (cur->nd_opt_len << 3);
     176 [ #  # ][ #  # ]:          0 :         } while(cur < end && cur->nd_opt_type != type);
     177 [ #  # ][ #  # ]:          0 :         return cur <= end && cur->nd_opt_type == type ? cur : NULL;
     178                 :            : }
     179                 :            : 
     180                 :            : static inline int ndisc_is_useropt(struct nd_opt_hdr *opt)
     181                 :            : {
     182                 :          0 :         return opt->nd_opt_type == ND_OPT_RDNSS ||
     183                 :            :                 opt->nd_opt_type == ND_OPT_DNSSL;
     184                 :            : }
     185                 :            : 
     186                 :          0 : static struct nd_opt_hdr *ndisc_next_useropt(struct nd_opt_hdr *cur,
     187                 :            :                                              struct nd_opt_hdr *end)
     188                 :            : {
     189 [ #  # ][ #  # ]:          0 :         if (!cur || !end || cur >= end)
     190                 :            :                 return NULL;
     191                 :            :         do {
     192                 :          0 :                 cur = ((void *)cur) + (cur->nd_opt_len << 3);
     193 [ #  # ][ #  # ]:          0 :         } while(cur < end && !ndisc_is_useropt(cur));
     194 [ #  # ][ #  # ]:          0 :         return cur <= end && ndisc_is_useropt(cur) ? cur : NULL;
     195                 :            : }
     196                 :            : 
     197                 :          0 : struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
     198                 :            :                                           struct ndisc_options *ndopts)
     199                 :            : {
     200                 :            :         struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)opt;
     201                 :            : 
     202 [ +  - ][ +  - ]:         93 :         if (!nd_opt || opt_len < 0 || !ndopts)
     203                 :            :                 return NULL;
     204                 :         93 :         memset(ndopts, 0, sizeof(*ndopts));
     205         [ +  + ]:        186 :         while (opt_len) {
     206                 :            :                 int l;
     207         [ +  - ]:         93 :                 if (opt_len < sizeof(struct nd_opt_hdr))
     208                 :            :                         return NULL;
     209                 :         93 :                 l = nd_opt->nd_opt_len << 3;
     210            [ + ]:         93 :                 if (opt_len < l || l == 0)
     211                 :            :                         return NULL;
     212 [ +  - ][ -  + ]:        186 :                 switch (nd_opt->nd_opt_type) {
                 [ #  # ]
     213                 :            :                 case ND_OPT_SOURCE_LL_ADDR:
     214                 :            :                 case ND_OPT_TARGET_LL_ADDR:
     215                 :            :                 case ND_OPT_MTU:
     216                 :            :                 case ND_OPT_REDIRECT_HDR:
     217         [ +  - ]:         93 :                         if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
     218                 :            :                                 ND_PRINTK(2, warn,
     219                 :            :                                           "%s: duplicated ND6 option found: type=%d\n",
     220                 :            :                                           __func__, nd_opt->nd_opt_type);
     221                 :            :                         } else {
     222                 :         93 :                                 ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
     223                 :            :                         }
     224                 :            :                         break;
     225                 :            :                 case ND_OPT_PREFIX_INFO:
     226                 :          0 :                         ndopts->nd_opts_pi_end = nd_opt;
     227         [ #  # ]:          0 :                         if (!ndopts->nd_opt_array[nd_opt->nd_opt_type])
     228                 :          0 :                                 ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
     229                 :            :                         break;
     230                 :            : #ifdef CONFIG_IPV6_ROUTE_INFO
     231                 :            :                 case ND_OPT_ROUTE_INFO:
     232                 :            :                         ndopts->nd_opts_ri_end = nd_opt;
     233                 :            :                         if (!ndopts->nd_opts_ri)
     234                 :            :                                 ndopts->nd_opts_ri = nd_opt;
     235                 :            :                         break;
     236                 :            : #endif
     237                 :            :                 default:
     238         [ #  # ]:          0 :                         if (ndisc_is_useropt(nd_opt)) {
     239                 :          0 :                                 ndopts->nd_useropts_end = nd_opt;
     240         [ #  # ]:          0 :                                 if (!ndopts->nd_useropts)
     241                 :          0 :                                         ndopts->nd_useropts = nd_opt;
     242                 :            :                         } else {
     243                 :            :                                 /*
     244                 :            :                                  * Unknown options must be silently ignored,
     245                 :            :                                  * to accommodate future extension to the
     246                 :            :                                  * protocol.
     247                 :            :                                  */
     248                 :            :                                 ND_PRINTK(2, notice,
     249                 :            :                                           "%s: ignored unsupported option; type=%d, len=%d\n",
     250                 :            :                                           __func__,
     251                 :            :                                           nd_opt->nd_opt_type,
     252                 :            :                                           nd_opt->nd_opt_len);
     253                 :            :                         }
     254                 :            :                 }
     255                 :         93 :                 opt_len -= l;
     256                 :         93 :                 nd_opt = ((void *)nd_opt) + l;
     257                 :            :         }
     258                 :            :         return ndopts;
     259                 :            : }
     260                 :            : 
     261                 :          0 : int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
     262                 :            : {
     263   [ #  #  #  #  :          0 :         switch (dev->type) {
                      # ]
     264                 :            :         case ARPHRD_ETHER:
     265                 :            :         case ARPHRD_IEEE802:    /* Not sure. Check it later. --ANK */
     266                 :            :         case ARPHRD_FDDI:
     267                 :            :                 ipv6_eth_mc_map(addr, buf);
     268                 :          0 :                 return 0;
     269                 :            :         case ARPHRD_ARCNET:
     270                 :            :                 ipv6_arcnet_mc_map(addr, buf);
     271                 :          0 :                 return 0;
     272                 :            :         case ARPHRD_INFINIBAND:
     273                 :            :                 ipv6_ib_mc_map(addr, dev->broadcast, buf);
     274                 :          0 :                 return 0;
     275                 :            :         case ARPHRD_IPGRE:
     276                 :          0 :                 return ipv6_ipgre_mc_map(addr, dev->broadcast, buf);
     277                 :            :         default:
     278         [ #  # ]:          0 :                 if (dir) {
     279                 :          0 :                         memcpy(buf, dev->broadcast, dev->addr_len);
     280                 :          0 :                         return 0;
     281                 :            :                 }
     282                 :            :         }
     283                 :            :         return -EINVAL;
     284                 :            : }
     285                 :            : 
     286                 :            : EXPORT_SYMBOL(ndisc_mc_map);
     287                 :            : 
     288                 :          0 : static u32 ndisc_hash(const void *pkey,
     289                 :            :                       const struct net_device *dev,
     290                 :            :                       __u32 *hash_rnd)
     291                 :            : {
     292                 :         93 :         return ndisc_hashfn(pkey, dev, hash_rnd);
     293                 :            : }
     294                 :            : 
     295                 :          0 : static int ndisc_constructor(struct neighbour *neigh)
     296                 :            : {
     297                 :          0 :         struct in6_addr *addr = (struct in6_addr*)&neigh->primary_key;
     298                 :          0 :         struct net_device *dev = neigh->dev;
     299                 :            :         struct inet6_dev *in6_dev;
     300                 :            :         struct neigh_parms *parms;
     301                 :            :         bool is_multicast = ipv6_addr_is_multicast(addr);
     302                 :            : 
     303                 :            :         in6_dev = in6_dev_get(dev);
     304         [ #  # ]:          0 :         if (in6_dev == NULL) {
     305                 :            :                 return -EINVAL;
     306                 :            :         }
     307                 :            : 
     308                 :          0 :         parms = in6_dev->nd_parms;
     309                 :          0 :         __neigh_parms_put(neigh->parms);
     310                 :          0 :         neigh->parms = neigh_parms_clone(parms);
     311                 :            : 
     312         [ #  # ]:          0 :         neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST;
     313         [ #  # ]:          0 :         if (!dev->header_ops) {
     314                 :          0 :                 neigh->nud_state = NUD_NOARP;
     315                 :          0 :                 neigh->ops = &ndisc_direct_ops;
     316                 :          0 :                 neigh->output = neigh_direct_output;
     317                 :            :         } else {
     318         [ #  # ]:          0 :                 if (is_multicast) {
     319                 :          0 :                         neigh->nud_state = NUD_NOARP;
     320                 :          0 :                         ndisc_mc_map(addr, neigh->ha, dev, 1);
     321         [ #  # ]:          0 :                 } else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) {
     322                 :          0 :                         neigh->nud_state = NUD_NOARP;
     323                 :          0 :                         memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
     324         [ #  # ]:          0 :                         if (dev->flags&IFF_LOOPBACK)
     325                 :          0 :                                 neigh->type = RTN_LOCAL;
     326         [ #  # ]:          0 :                 } else if (dev->flags&IFF_POINTOPOINT) {
     327                 :          0 :                         neigh->nud_state = NUD_NOARP;
     328                 :          0 :                         memcpy(neigh->ha, dev->broadcast, dev->addr_len);
     329                 :            :                 }
     330         [ #  # ]:          0 :                 if (dev->header_ops->cache)
     331                 :          0 :                         neigh->ops = &ndisc_hh_ops;
     332                 :            :                 else
     333                 :          0 :                         neigh->ops = &ndisc_generic_ops;
     334         [ #  # ]:          0 :                 if (neigh->nud_state&NUD_VALID)
     335                 :          0 :                         neigh->output = neigh->ops->connected_output;
     336                 :            :                 else
     337                 :          0 :                         neigh->output = neigh->ops->output;
     338                 :            :         }
     339                 :            :         in6_dev_put(in6_dev);
     340                 :            :         return 0;
     341                 :            : }
     342                 :            : 
     343                 :          0 : static int pndisc_constructor(struct pneigh_entry *n)
     344                 :            : {
     345                 :          0 :         struct in6_addr *addr = (struct in6_addr*)&n->key;
     346                 :            :         struct in6_addr maddr;
     347                 :          0 :         struct net_device *dev = n->dev;
     348                 :            : 
     349 [ #  # ][ #  # ]:          0 :         if (dev == NULL || __in6_dev_get(dev) == NULL)
     350                 :            :                 return -EINVAL;
     351                 :            :         addrconf_addr_solict_mult(addr, &maddr);
     352                 :          0 :         ipv6_dev_mc_inc(dev, &maddr);
     353                 :          0 :         return 0;
     354                 :            : }
     355                 :            : 
     356                 :          0 : static void pndisc_destructor(struct pneigh_entry *n)
     357                 :            : {
     358                 :          0 :         struct in6_addr *addr = (struct in6_addr*)&n->key;
     359                 :            :         struct in6_addr maddr;
     360                 :          0 :         struct net_device *dev = n->dev;
     361                 :            : 
     362 [ #  # ][ #  # ]:          0 :         if (dev == NULL || __in6_dev_get(dev) == NULL)
     363                 :          0 :                 return;
     364                 :            :         addrconf_addr_solict_mult(addr, &maddr);
     365                 :          0 :         ipv6_dev_mc_dec(dev, &maddr);
     366                 :            : }
     367                 :            : 
     368                 :          0 : static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
     369                 :            :                                        int len)
     370                 :            : {
     371                 :          0 :         int hlen = LL_RESERVED_SPACE(dev);
     372                 :          0 :         int tlen = dev->needed_tailroom;
     373                 :          0 :         struct sock *sk = dev_net(dev)->ipv6.ndisc_sk;
     374                 :            :         struct sk_buff *skb;
     375                 :            : 
     376                 :          0 :         skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC);
     377         [ #  # ]:          0 :         if (!skb) {
     378         [ #  # ]:          0 :                 ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb\n",
     379                 :            :                           __func__);
     380                 :            :                 return NULL;
     381                 :            :         }
     382                 :            : 
     383                 :          0 :         skb->protocol = htons(ETH_P_IPV6);
     384                 :          0 :         skb->dev = dev;
     385                 :            : 
     386                 :          0 :         skb_reserve(skb, hlen + sizeof(struct ipv6hdr));
     387                 :            :         skb_reset_transport_header(skb);
     388                 :            : 
     389                 :            :         /* Manually assign socket ownership as we avoid calling
     390                 :            :          * sock_alloc_send_pskb() to bypass wmem buffer limits
     391                 :            :          */
     392                 :            :         skb_set_owner_w(skb, sk);
     393                 :            : 
     394                 :          0 :         return skb;
     395                 :            : }
     396                 :            : 
     397                 :          0 : static void ip6_nd_hdr(struct sk_buff *skb,
     398                 :            :                        const struct in6_addr *saddr,
     399                 :            :                        const struct in6_addr *daddr,
     400                 :            :                        int hop_limit, int len)
     401                 :            : {
     402                 :            :         struct ipv6hdr *hdr;
     403                 :            : 
     404                 :          0 :         skb_push(skb, sizeof(*hdr));
     405                 :            :         skb_reset_network_header(skb);
     406                 :            :         hdr = ipv6_hdr(skb);
     407                 :            : 
     408                 :            :         ip6_flow_hdr(hdr, 0, 0);
     409                 :            : 
     410         [ #  # ]:          0 :         hdr->payload_len = htons(len);
     411                 :          0 :         hdr->nexthdr = IPPROTO_ICMPV6;
     412                 :          0 :         hdr->hop_limit = hop_limit;
     413                 :            : 
     414                 :          0 :         hdr->saddr = *saddr;
     415                 :          0 :         hdr->daddr = *daddr;
     416                 :          0 : }
     417                 :            : 
     418                 :          0 : static void ndisc_send_skb(struct sk_buff *skb,
     419                 :            :                            const struct in6_addr *daddr,
     420                 :            :                            const struct in6_addr *saddr)
     421                 :            : {
     422                 :            :         struct dst_entry *dst = skb_dst(skb);
     423                 :            :         struct net *net = dev_net(skb->dev);
     424                 :          0 :         struct sock *sk = net->ipv6.ndisc_sk;
     425                 :            :         struct inet6_dev *idev;
     426                 :            :         int err;
     427                 :            :         struct icmp6hdr *icmp6h = icmp6_hdr(skb);
     428                 :            :         u8 type;
     429                 :            : 
     430                 :          0 :         type = icmp6h->icmp6_type;
     431                 :            : 
     432         [ #  # ]:          0 :         if (!dst) {
     433                 :            :                 struct flowi6 fl6;
     434                 :            : 
     435                 :          0 :                 icmpv6_flow_init(sk, &fl6, type, saddr, daddr, skb->dev->ifindex);
     436                 :          0 :                 dst = icmp6_dst_alloc(skb->dev, &fl6);
     437         [ #  # ]:          0 :                 if (IS_ERR(dst)) {
     438                 :          0 :                         kfree_skb(skb);
     439                 :          0 :                         return;
     440                 :            :                 }
     441                 :            : 
     442                 :            :                 skb_dst_set(skb, dst);
     443                 :            :         }
     444                 :            : 
     445                 :          0 :         icmp6h->icmp6_cksum = csum_ipv6_magic(saddr, daddr, skb->len,
     446                 :            :                                               IPPROTO_ICMPV6,
     447                 :            :                                               csum_partial(icmp6h,
     448                 :          0 :                                                            skb->len, 0));
     449                 :            : 
     450                 :          0 :         ip6_nd_hdr(skb, saddr, daddr, inet6_sk(sk)->hop_limit, skb->len);
     451                 :            : 
     452                 :            :         rcu_read_lock();
     453                 :          0 :         idev = __in6_dev_get(dst->dev);
     454         [ #  # ]:          0 :         IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
     455                 :            : 
     456                 :          0 :         err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
     457                 :            :                       dst_output);
     458         [ #  # ]:          0 :         if (!err) {
     459         [ #  # ]:          0 :                 ICMP6MSGOUT_INC_STATS(net, idev, type);
     460         [ #  # ]:          0 :                 ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
     461                 :            :         }
     462                 :            : 
     463                 :            :         rcu_read_unlock();
     464                 :            : }
     465                 :            : 
     466                 :          0 : void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
     467                 :            :                    const struct in6_addr *daddr,
     468                 :            :                    const struct in6_addr *solicited_addr,
     469                 :            :                    bool router, bool solicited, bool override, bool inc_opt)
     470                 :            : {
     471                 :            :         struct sk_buff *skb;
     472                 :            :         struct in6_addr tmpaddr;
     473                 :            :         struct inet6_ifaddr *ifp;
     474                 :            :         const struct in6_addr *src_addr;
     475                 :            :         struct nd_msg *msg;
     476                 :            :         int optlen = 0;
     477                 :            : 
     478                 :            :         /* for anycast or proxy, solicited_addr != src_addr */
     479                 :          0 :         ifp = ipv6_get_ifaddr(dev_net(dev), solicited_addr, dev, 1);
     480         [ #  # ]:          0 :         if (ifp) {
     481                 :            :                 src_addr = solicited_addr;
     482         [ #  # ]:          0 :                 if (ifp->flags & IFA_F_OPTIMISTIC)
     483                 :            :                         override = false;
     484                 :          0 :                 inc_opt |= ifp->idev->cnf.force_tllao;
     485                 :            :                 in6_ifa_put(ifp);
     486                 :            :         } else {
     487         [ #  # ]:          0 :                 if (ipv6_dev_get_saddr(dev_net(dev), dev, daddr,
     488                 :          0 :                                        inet6_sk(dev_net(dev)->ipv6.ndisc_sk)->srcprefs,
     489                 :            :                                        &tmpaddr))
     490                 :          0 :                         return;
     491                 :            :                 src_addr = &tmpaddr;
     492                 :            :         }
     493                 :            : 
     494         [ #  # ]:          0 :         if (!dev->addr_len)
     495                 :            :                 inc_opt = 0;
     496         [ #  # ]:          0 :         if (inc_opt)
     497                 :            :                 optlen += ndisc_opt_addr_space(dev);
     498                 :            : 
     499                 :          0 :         skb = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
     500         [ #  # ]:          0 :         if (!skb)
     501                 :            :                 return;
     502                 :            : 
     503                 :          0 :         msg = (struct nd_msg *)skb_put(skb, sizeof(*msg));
     504                 :          0 :         *msg = (struct nd_msg) {
     505                 :            :                 .icmph = {
     506                 :            :                         .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT,
     507                 :            :                         .icmp6_router = router,
     508                 :            :                         .icmp6_solicited = solicited,
     509                 :            :                         .icmp6_override = override,
     510                 :            :                 },
     511                 :          0 :                 .target = *solicited_addr,
     512                 :            :         };
     513                 :            : 
     514         [ #  # ]:          0 :         if (inc_opt)
     515                 :          0 :                 ndisc_fill_addr_option(skb, ND_OPT_TARGET_LL_ADDR,
     516                 :          0 :                                        dev->dev_addr);
     517                 :            : 
     518                 :            : 
     519                 :          0 :         ndisc_send_skb(skb, daddr, src_addr);
     520                 :            : }
     521                 :            : 
     522                 :          0 : static void ndisc_send_unsol_na(struct net_device *dev)
     523                 :            : {
     524                 :            :         struct inet6_dev *idev;
     525                 :            :         struct inet6_ifaddr *ifa;
     526                 :            : 
     527                 :            :         idev = in6_dev_get(dev);
     528         [ #  # ]:          0 :         if (!idev)
     529                 :          0 :                 return;
     530                 :            : 
     531                 :          0 :         read_lock_bh(&idev->lock);
     532         [ #  # ]:          0 :         list_for_each_entry(ifa, &idev->addr_list, if_list) {
     533                 :          0 :                 ndisc_send_na(dev, NULL, &in6addr_linklocal_allnodes, &ifa->addr,
     534                 :          0 :                               /*router=*/ !!idev->cnf.forwarding,
     535                 :            :                               /*solicited=*/ false, /*override=*/ true,
     536                 :            :                               /*inc_opt=*/ true);
     537                 :            :         }
     538                 :          0 :         read_unlock_bh(&idev->lock);
     539                 :            : 
     540                 :            :         in6_dev_put(idev);
     541                 :            : }
     542                 :            : 
     543                 :          0 : void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
     544                 :            :                    const struct in6_addr *solicit,
     545                 :            :                    const struct in6_addr *daddr, const struct in6_addr *saddr)
     546                 :            : {
     547                 :            :         struct sk_buff *skb;
     548                 :            :         struct in6_addr addr_buf;
     549                 :          0 :         int inc_opt = dev->addr_len;
     550                 :            :         int optlen = 0;
     551                 :            :         struct nd_msg *msg;
     552                 :            : 
     553         [ #  # ]:          0 :         if (saddr == NULL) {
     554         [ #  # ]:          0 :                 if (ipv6_get_lladdr(dev, &addr_buf,
     555                 :            :                                    (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)))
     556                 :          0 :                         return;
     557                 :            :                 saddr = &addr_buf;
     558                 :            :         }
     559                 :            : 
     560         [ #  # ]:          0 :         if (ipv6_addr_any(saddr))
     561                 :            :                 inc_opt = false;
     562         [ #  # ]:          0 :         if (inc_opt)
     563                 :            :                 optlen += ndisc_opt_addr_space(dev);
     564                 :            : 
     565                 :          0 :         skb = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
     566         [ #  # ]:          0 :         if (!skb)
     567                 :            :                 return;
     568                 :            : 
     569                 :          0 :         msg = (struct nd_msg *)skb_put(skb, sizeof(*msg));
     570                 :          0 :         *msg = (struct nd_msg) {
     571                 :            :                 .icmph = {
     572                 :            :                         .icmp6_type = NDISC_NEIGHBOUR_SOLICITATION,
     573                 :            :                 },
     574                 :          0 :                 .target = *solicit,
     575                 :            :         };
     576                 :            : 
     577         [ #  # ]:          0 :         if (inc_opt)
     578                 :          0 :                 ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR,
     579                 :          0 :                                        dev->dev_addr);
     580                 :            : 
     581                 :          0 :         ndisc_send_skb(skb, daddr, saddr);
     582                 :            : }
     583                 :            : 
     584                 :          0 : void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr,
     585                 :            :                    const struct in6_addr *daddr)
     586                 :            : {
     587                 :            :         struct sk_buff *skb;
     588                 :            :         struct rs_msg *msg;
     589                 :          0 :         int send_sllao = dev->addr_len;
     590                 :            :         int optlen = 0;
     591                 :            : 
     592                 :            : #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
     593                 :            :         /*
     594                 :            :          * According to section 2.2 of RFC 4429, we must not
     595                 :            :          * send router solicitations with a sllao from
     596                 :            :          * optimistic addresses, but we may send the solicitation
     597                 :            :          * if we don't include the sllao.  So here we check
     598                 :            :          * if our address is optimistic, and if so, we
     599                 :            :          * suppress the inclusion of the sllao.
     600                 :            :          */
     601                 :            :         if (send_sllao) {
     602                 :            :                 struct inet6_ifaddr *ifp = ipv6_get_ifaddr(dev_net(dev), saddr,
     603                 :            :                                                            dev, 1);
     604                 :            :                 if (ifp) {
     605                 :            :                         if (ifp->flags & IFA_F_OPTIMISTIC)  {
     606                 :            :                                 send_sllao = 0;
     607                 :            :                         }
     608                 :            :                         in6_ifa_put(ifp);
     609                 :            :                 } else {
     610                 :            :                         send_sllao = 0;
     611                 :            :                 }
     612                 :            :         }
     613                 :            : #endif
     614         [ #  # ]:          0 :         if (send_sllao)
     615                 :            :                 optlen += ndisc_opt_addr_space(dev);
     616                 :            : 
     617                 :          0 :         skb = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
     618         [ #  # ]:          0 :         if (!skb)
     619                 :          0 :                 return;
     620                 :            : 
     621                 :          0 :         msg = (struct rs_msg *)skb_put(skb, sizeof(*msg));
     622                 :          0 :         *msg = (struct rs_msg) {
     623                 :            :                 .icmph = {
     624                 :            :                         .icmp6_type = NDISC_ROUTER_SOLICITATION,
     625                 :            :                 },
     626                 :            :         };
     627                 :            : 
     628         [ #  # ]:          0 :         if (send_sllao)
     629                 :          0 :                 ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR,
     630                 :          0 :                                        dev->dev_addr);
     631                 :            : 
     632                 :          0 :         ndisc_send_skb(skb, daddr, saddr);
     633                 :            : }
     634                 :            : 
     635                 :            : 
     636                 :          0 : static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
     637                 :            : {
     638                 :            :         /*
     639                 :            :          *      "The sender MUST return an ICMP
     640                 :            :          *       destination unreachable"
     641                 :            :          */
     642                 :            :         dst_link_failure(skb);
     643                 :          0 :         kfree_skb(skb);
     644                 :          0 : }
     645                 :            : 
     646                 :            : /* Called with locked neigh: either read or both */
     647                 :            : 
     648                 :          0 : static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
     649                 :            : {
     650                 :            :         struct in6_addr *saddr = NULL;
     651                 :            :         struct in6_addr mcaddr;
     652                 :          0 :         struct net_device *dev = neigh->dev;
     653                 :          0 :         struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
     654                 :          0 :         int probes = atomic_read(&neigh->probes);
     655                 :            : 
     656 [ #  # ][ #  # ]:          0 :         if (skb && ipv6_chk_addr(dev_net(dev), &ipv6_hdr(skb)->saddr, dev, 1))
     657                 :          0 :                 saddr = &ipv6_hdr(skb)->saddr;
     658                 :            : 
     659         [ #  # ]:          0 :         if ((probes -= neigh->parms->ucast_probes) < 0) {
     660         [ #  # ]:          0 :                 if (!(neigh->nud_state & NUD_VALID)) {
     661                 :          0 :                         ND_PRINTK(1, dbg,
     662                 :            :                                   "%s: trying to ucast probe in NUD_INVALID: %pI6\n",
     663                 :            :                                   __func__, target);
     664                 :            :                 }
     665                 :          0 :                 ndisc_send_ns(dev, neigh, target, target, saddr);
     666         [ #  # ]:          0 :         } else if ((probes -= neigh->parms->app_probes) < 0) {
     667                 :          0 :                 neigh_app_ns(neigh);
     668                 :            :         } else {
     669                 :            :                 addrconf_addr_solict_mult(target, &mcaddr);
     670                 :          0 :                 ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
     671                 :            :         }
     672                 :          0 : }
     673                 :            : 
     674                 :          0 : static int pndisc_is_router(const void *pkey,
     675                 :            :                             struct net_device *dev)
     676                 :            : {
     677                 :            :         struct pneigh_entry *n;
     678                 :            :         int ret = -1;
     679                 :            : 
     680                 :          0 :         read_lock_bh(&nd_tbl.lock);
     681                 :          0 :         n = __pneigh_lookup(&nd_tbl, dev_net(dev), pkey, dev);
     682         [ #  # ]:          0 :         if (n)
     683                 :          0 :                 ret = !!(n->flags & NTF_ROUTER);
     684                 :          0 :         read_unlock_bh(&nd_tbl.lock);
     685                 :            : 
     686                 :          0 :         return ret;
     687                 :            : }
     688                 :            : 
     689                 :          0 : static void ndisc_recv_ns(struct sk_buff *skb)
     690                 :            : {
     691                 :            :         struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
     692                 :          0 :         const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
     693                 :          0 :         const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
     694                 :            :         u8 *lladdr = NULL;
     695                 :          0 :         u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
     696                 :            :                                     offsetof(struct nd_msg, opt));
     697                 :            :         struct ndisc_options ndopts;
     698                 :          0 :         struct net_device *dev = skb->dev;
     699                 :            :         struct inet6_ifaddr *ifp;
     700                 :            :         struct inet6_dev *idev = NULL;
     701                 :            :         struct neighbour *neigh;
     702                 :          0 :         int dad = ipv6_addr_any(saddr);
     703                 :            :         bool inc;
     704                 :            :         int is_router = -1;
     705                 :            : 
     706         [ #  # ]:          0 :         if (skb->len < sizeof(struct nd_msg)) {
     707                 :            :                 ND_PRINTK(2, warn, "NS: packet too short\n");
     708                 :          0 :                 return;
     709                 :            :         }
     710                 :            : 
     711         [ #  # ]:          0 :         if (ipv6_addr_is_multicast(&msg->target)) {
     712                 :            :                 ND_PRINTK(2, warn, "NS: multicast target address\n");
     713                 :            :                 return;
     714                 :            :         }
     715                 :            : 
     716                 :            :         /*
     717                 :            :          * RFC2461 7.1.1:
     718                 :            :          * DAD has to be destined for solicited node multicast address.
     719                 :            :          */
     720 [ #  # ][ #  # ]:          0 :         if (dad && !ipv6_addr_is_solict_mult(daddr)) {
     721                 :            :                 ND_PRINTK(2, warn, "NS: bad DAD packet (wrong destination)\n");
     722                 :            :                 return;
     723                 :            :         }
     724                 :            : 
     725         [ #  # ]:          0 :         if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
     726                 :            :                 ND_PRINTK(2, warn, "NS: invalid ND options\n");
     727                 :            :                 return;
     728                 :            :         }
     729                 :            : 
     730         [ #  # ]:          0 :         if (ndopts.nd_opts_src_lladdr) {
     731                 :            :                 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, dev);
     732         [ #  # ]:          0 :                 if (!lladdr) {
     733                 :            :                         ND_PRINTK(2, warn,
     734                 :            :                                   "NS: invalid link-layer address length\n");
     735                 :            :                         return;
     736                 :            :                 }
     737                 :            : 
     738                 :            :                 /* RFC2461 7.1.1:
     739                 :            :                  *      If the IP source address is the unspecified address,
     740                 :            :                  *      there MUST NOT be source link-layer address option
     741                 :            :                  *      in the message.
     742                 :            :                  */
     743         [ #  # ]:          0 :                 if (dad) {
     744                 :            :                         ND_PRINTK(2, warn,
     745                 :            :                                   "NS: bad DAD packet (link-layer address option)\n");
     746                 :            :                         return;
     747                 :            :                 }
     748                 :            :         }
     749                 :            : 
     750                 :            :         inc = ipv6_addr_is_multicast(daddr);
     751                 :            : 
     752                 :          0 :         ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1);
     753         [ #  # ]:          0 :         if (ifp) {
     754                 :            : 
     755         [ #  # ]:          0 :                 if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) {
     756         [ #  # ]:          0 :                         if (dad) {
     757                 :            :                                 /*
     758                 :            :                                  * We are colliding with another node
     759                 :            :                                  * who is doing DAD
     760                 :            :                                  * so fail our DAD process
     761                 :            :                                  */
     762                 :          0 :                                 addrconf_dad_failure(ifp);
     763                 :          0 :                                 return;
     764                 :            :                         } else {
     765                 :            :                                 /*
     766                 :            :                                  * This is not a dad solicitation.
     767                 :            :                                  * If we are an optimistic node,
     768                 :            :                                  * we should respond.
     769                 :            :                                  * Otherwise, we should ignore it.
     770                 :            :                                  */
     771         [ #  # ]:          0 :                                 if (!(ifp->flags & IFA_F_OPTIMISTIC))
     772                 :            :                                         goto out;
     773                 :            :                         }
     774                 :            :                 }
     775                 :            : 
     776                 :          0 :                 idev = ifp->idev;
     777                 :            :         } else {
     778                 :            :                 struct net *net = dev_net(dev);
     779                 :            : 
     780                 :            :                 idev = in6_dev_get(dev);
     781         [ #  # ]:          0 :                 if (!idev) {
     782                 :            :                         /* XXX: count this drop? */
     783                 :            :                         return;
     784                 :            :                 }
     785                 :            : 
     786 [ #  # ][ #  # ]:          0 :                 if (ipv6_chk_acast_addr(net, dev, &msg->target) ||
     787         [ #  # ]:          0 :                     (idev->cnf.forwarding &&
     788 [ #  # ][ #  # ]:          0 :                      (net->ipv6.devconf_all->proxy_ndp || idev->cnf.proxy_ndp) &&
     789                 :            :                      (is_router = pndisc_is_router(&msg->target, dev)) >= 0)) {
     790 [ #  # ][ #  # ]:          0 :                         if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
     791         [ #  # ]:          0 :                             skb->pkt_type != PACKET_HOST &&
     792         [ #  # ]:          0 :                             inc &&
     793                 :          0 :                             idev->nd_parms->proxy_delay != 0) {
     794                 :            :                                 /*
     795                 :            :                                  * for anycast or proxy,
     796                 :            :                                  * sender should delay its response
     797                 :            :                                  * by a random time between 0 and
     798                 :            :                                  * MAX_ANYCAST_DELAY_TIME seconds.
     799                 :            :                                  * (RFC2461) -- yoshfuji
     800                 :            :                                  */
     801                 :          0 :                                 struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
     802         [ #  # ]:          0 :                                 if (n)
     803                 :          0 :                                         pneigh_enqueue(&nd_tbl, idev->nd_parms, n);
     804                 :            :                                 goto out;
     805                 :            :                         }
     806                 :            :                 } else
     807                 :            :                         goto out;
     808                 :            :         }
     809                 :            : 
     810         [ #  # ]:          0 :         if (is_router < 0)
     811                 :          0 :                 is_router = idev->cnf.forwarding;
     812                 :            : 
     813         [ #  # ]:          0 :         if (dad) {
     814                 :          0 :                 ndisc_send_na(dev, NULL, &in6addr_linklocal_allnodes, &msg->target,
     815                 :            :                               !!is_router, false, (ifp != NULL), true);
     816                 :          0 :                 goto out;
     817                 :            :         }
     818                 :            : 
     819         [ #  # ]:          0 :         if (inc)
     820                 :          0 :                 NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_mcast);
     821                 :            :         else
     822                 :          0 :                 NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_ucast);
     823                 :            : 
     824                 :            :         /*
     825                 :            :          *      update / create cache entry
     826                 :            :          *      for the source address
     827                 :            :          */
     828 [ #  # ][ #  # ]:          0 :         neigh = __neigh_lookup(&nd_tbl, saddr, dev,
     829                 :          0 :                                !inc || lladdr || !dev->addr_len);
     830         [ #  # ]:          0 :         if (neigh)
     831                 :          0 :                 neigh_update(neigh, lladdr, NUD_STALE,
     832                 :            :                              NEIGH_UPDATE_F_WEAK_OVERRIDE|
     833                 :            :                              NEIGH_UPDATE_F_OVERRIDE);
     834 [ #  # ][ #  # ]:          0 :         if (neigh || !dev->header_ops) {
     835                 :          0 :                 ndisc_send_na(dev, neigh, saddr, &msg->target,
     836                 :            :                               !!is_router,
     837                 :          0 :                               true, (ifp != NULL && inc), inc);
     838         [ #  # ]:          0 :                 if (neigh)
     839                 :            :                         neigh_release(neigh);
     840                 :            :         }
     841                 :            : 
     842                 :            : out:
     843         [ #  # ]:          0 :         if (ifp)
     844                 :            :                 in6_ifa_put(ifp);
     845                 :            :         else
     846                 :            :                 in6_dev_put(idev);
     847                 :            : }
     848                 :            : 
     849                 :          0 : static void ndisc_recv_na(struct sk_buff *skb)
     850                 :            : {
     851                 :            :         struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
     852                 :         93 :         const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
     853                 :         93 :         const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
     854                 :            :         u8 *lladdr = NULL;
     855                 :         93 :         u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
     856                 :            :                                     offsetof(struct nd_msg, opt));
     857                 :            :         struct ndisc_options ndopts;
     858                 :         93 :         struct net_device *dev = skb->dev;
     859                 :            :         struct inet6_ifaddr *ifp;
     860                 :            :         struct neighbour *neigh;
     861                 :            : 
     862         [ +  - ]:         93 :         if (skb->len < sizeof(struct nd_msg)) {
     863                 :            :                 ND_PRINTK(2, warn, "NA: packet too short\n");
     864                 :          0 :                 return;
     865                 :            :         }
     866                 :            : 
     867         [ +  - ]:         93 :         if (ipv6_addr_is_multicast(&msg->target)) {
     868                 :            :                 ND_PRINTK(2, warn, "NA: target address is multicast\n");
     869                 :            :                 return;
     870                 :            :         }
     871                 :            : 
     872 [ +  - ][ +  - ]:         93 :         if (ipv6_addr_is_multicast(daddr) &&
     873                 :         93 :             msg->icmph.icmp6_solicited) {
     874                 :            :                 ND_PRINTK(2, warn, "NA: solicited NA is multicasted\n");
     875                 :            :                 return;
     876                 :            :         }
     877                 :            : 
     878         [ +  - ]:         93 :         if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
     879                 :            :                 ND_PRINTK(2, warn, "NS: invalid ND option\n");
     880                 :            :                 return;
     881                 :            :         }
     882         [ +  - ]:         93 :         if (ndopts.nd_opts_tgt_lladdr) {
     883                 :            :                 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, dev);
     884         [ +  - ]:         93 :                 if (!lladdr) {
     885                 :            :                         ND_PRINTK(2, warn,
     886                 :            :                                   "NA: invalid link-layer address length\n");
     887                 :            :                         return;
     888                 :            :                 }
     889                 :            :         }
     890                 :         93 :         ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1);
     891         [ -  + ]:         93 :         if (ifp) {
     892         [ #  # ]:          0 :                 if (skb->pkt_type != PACKET_LOOPBACK
     893         [ #  # ]:          0 :                     && (ifp->flags & IFA_F_TENTATIVE)) {
     894                 :          0 :                                 addrconf_dad_failure(ifp);
     895                 :          0 :                                 return;
     896                 :            :                 }
     897                 :            :                 /* What should we make now? The advertisement
     898                 :            :                    is invalid, but ndisc specs say nothing
     899                 :            :                    about it. It could be misconfiguration, or
     900                 :            :                    an smart proxy agent tries to help us :-)
     901                 :            : 
     902                 :            :                    We should not print the error if NA has been
     903                 :            :                    received from loopback - it is just our own
     904                 :            :                    unsolicited advertisement.
     905                 :            :                  */
     906         [ #  # ]:          0 :                 if (skb->pkt_type != PACKET_LOOPBACK)
     907         [ #  # ]:          0 :                         ND_PRINTK(1, warn,
     908                 :            :                                   "NA: someone advertises our address %pI6 on %s!\n",
     909                 :            :                                   &ifp->addr, ifp->idev->dev->name);
     910                 :            :                 in6_ifa_put(ifp);
     911                 :            :                 return;
     912                 :            :         }
     913                 :         93 :         neigh = neigh_lookup(&nd_tbl, &msg->target, dev);
     914                 :            : 
     915         [ -  + ]:         93 :         if (neigh) {
     916                 :          0 :                 u8 old_flags = neigh->flags;
     917                 :            :                 struct net *net = dev_net(dev);
     918                 :            : 
     919         [ #  # ]:          0 :                 if (neigh->nud_state & NUD_FAILED)
     920                 :            :                         goto out;
     921                 :            : 
     922                 :            :                 /*
     923                 :            :                  * Don't update the neighbor cache entry on a proxy NA from
     924                 :            :                  * ourselves because either the proxied node is off link or it
     925                 :            :                  * has already sent a NA to us.
     926                 :            :                  */
     927 [ #  # ][ #  # ]:          0 :                 if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
                 [ #  # ]
     928   [ #  #  #  # ]:          0 :                     net->ipv6.devconf_all->forwarding && net->ipv6.devconf_all->proxy_ndp &&
     929                 :          0 :                     pneigh_lookup(&nd_tbl, net, &msg->target, dev, 0)) {
     930                 :            :                         /* XXX: idev->cnf.proxy_ndp */
     931                 :            :                         goto out;
     932                 :            :                 }
     933                 :            : 
     934         [ #  # ]:          0 :                 neigh_update(neigh, lladdr,
     935                 :          0 :                              msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
     936                 :            :                              NEIGH_UPDATE_F_WEAK_OVERRIDE|
     937         [ #  # ]:          0 :                              (msg->icmph.icmp6_override ? NEIGH_UPDATE_F_OVERRIDE : 0)|
     938                 :          0 :                              NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
     939         [ #  # ]:          0 :                              (msg->icmph.icmp6_router ? NEIGH_UPDATE_F_ISROUTER : 0));
     940                 :            : 
     941         [ #  # ]:          0 :                 if ((old_flags & ~neigh->flags) & NTF_ROUTER) {
     942                 :            :                         /*
     943                 :            :                          * Change: router to host
     944                 :            :                          */
     945                 :            :                         struct rt6_info *rt;
     946                 :          0 :                         rt = rt6_get_dflt_router(saddr, dev);
     947         [ #  # ]:          0 :                         if (rt)
     948                 :          0 :                                 ip6_del_rt(rt);
     949                 :            :                 }
     950                 :            : 
     951                 :            : out:
     952                 :            :                 neigh_release(neigh);
     953                 :            :         }
     954                 :            : }
     955                 :            : 
     956                 :          0 : static void ndisc_recv_rs(struct sk_buff *skb)
     957                 :            : {
     958                 :            :         struct rs_msg *rs_msg = (struct rs_msg *)skb_transport_header(skb);
     959                 :          0 :         unsigned long ndoptlen = skb->len - sizeof(*rs_msg);
     960                 :            :         struct neighbour *neigh;
     961                 :            :         struct inet6_dev *idev;
     962                 :          0 :         const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
     963                 :            :         struct ndisc_options ndopts;
     964                 :            :         u8 *lladdr = NULL;
     965                 :            : 
     966         [ #  # ]:          0 :         if (skb->len < sizeof(*rs_msg))
     967                 :            :                 return;
     968                 :            : 
     969                 :          0 :         idev = __in6_dev_get(skb->dev);
     970         [ #  # ]:          0 :         if (!idev) {
     971         [ #  # ]:          0 :                 ND_PRINTK(1, err, "RS: can't find in6 device\n");
     972                 :            :                 return;
     973                 :            :         }
     974                 :            : 
     975                 :            :         /* Don't accept RS if we're not in router mode */
     976         [ #  # ]:          0 :         if (!idev->cnf.forwarding)
     977                 :            :                 goto out;
     978                 :            : 
     979                 :            :         /*
     980                 :            :          * Don't update NCE if src = ::;
     981                 :            :          * this implies that the source node has no ip address assigned yet.
     982                 :            :          */
     983         [ #  # ]:          0 :         if (ipv6_addr_any(saddr))
     984                 :            :                 goto out;
     985                 :            : 
     986                 :            :         /* Parse ND options */
     987         [ #  # ]:          0 :         if (!ndisc_parse_options(rs_msg->opt, ndoptlen, &ndopts)) {
     988                 :            :                 ND_PRINTK(2, notice, "NS: invalid ND option, ignored\n");
     989                 :            :                 goto out;
     990                 :            :         }
     991                 :            : 
     992         [ #  # ]:          0 :         if (ndopts.nd_opts_src_lladdr) {
     993                 :          0 :                 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
     994                 :            :                                              skb->dev);
     995         [ #  # ]:          0 :                 if (!lladdr)
     996                 :            :                         goto out;
     997                 :            :         }
     998                 :            : 
     999                 :          0 :         neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev, 1);
    1000         [ #  # ]:          0 :         if (neigh) {
    1001                 :          0 :                 neigh_update(neigh, lladdr, NUD_STALE,
    1002                 :            :                              NEIGH_UPDATE_F_WEAK_OVERRIDE|
    1003                 :            :                              NEIGH_UPDATE_F_OVERRIDE|
    1004                 :            :                              NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
    1005                 :            :                 neigh_release(neigh);
    1006                 :            :         }
    1007                 :            : out:
    1008                 :            :         return;
    1009                 :            : }
    1010                 :            : 
    1011                 :          0 : static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt)
    1012                 :            : {
    1013                 :            :         struct icmp6hdr *icmp6h = (struct icmp6hdr *)skb_transport_header(ra);
    1014                 :            :         struct sk_buff *skb;
    1015                 :            :         struct nlmsghdr *nlh;
    1016                 :            :         struct nduseroptmsg *ndmsg;
    1017                 :            :         struct net *net = dev_net(ra->dev);
    1018                 :            :         int err;
    1019                 :          0 :         int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg)
    1020                 :            :                                     + (opt->nd_opt_len << 3));
    1021                 :          0 :         size_t msg_size = base_size + nla_total_size(sizeof(struct in6_addr));
    1022                 :            : 
    1023                 :            :         skb = nlmsg_new(msg_size, GFP_ATOMIC);
    1024         [ #  # ]:          0 :         if (skb == NULL) {
    1025                 :            :                 err = -ENOBUFS;
    1026                 :            :                 goto errout;
    1027                 :            :         }
    1028                 :            : 
    1029                 :            :         nlh = nlmsg_put(skb, 0, 0, RTM_NEWNDUSEROPT, base_size, 0);
    1030         [ #  # ]:          0 :         if (nlh == NULL) {
    1031                 :            :                 goto nla_put_failure;
    1032                 :            :         }
    1033                 :            : 
    1034                 :            :         ndmsg = nlmsg_data(nlh);
    1035                 :          0 :         ndmsg->nduseropt_family = AF_INET6;
    1036                 :          0 :         ndmsg->nduseropt_ifindex = ra->dev->ifindex;
    1037                 :          0 :         ndmsg->nduseropt_icmp_type = icmp6h->icmp6_type;
    1038                 :          0 :         ndmsg->nduseropt_icmp_code = icmp6h->icmp6_code;
    1039                 :          0 :         ndmsg->nduseropt_opts_len = opt->nd_opt_len << 3;
    1040                 :            : 
    1041                 :          0 :         memcpy(ndmsg + 1, opt, opt->nd_opt_len << 3);
    1042                 :            : 
    1043         [ #  # ]:          0 :         if (nla_put(skb, NDUSEROPT_SRCADDR, sizeof(struct in6_addr),
    1044                 :          0 :                     &ipv6_hdr(ra)->saddr))
    1045                 :            :                 goto nla_put_failure;
    1046                 :            :         nlmsg_end(skb, nlh);
    1047                 :            : 
    1048                 :          0 :         rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL, GFP_ATOMIC);
    1049                 :          0 :         return;
    1050                 :            : 
    1051                 :            : nla_put_failure:
    1052                 :            :         nlmsg_free(skb);
    1053                 :            :         err = -EMSGSIZE;
    1054                 :            : errout:
    1055                 :          0 :         rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err);
    1056                 :            : }
    1057                 :            : 
    1058                 :          0 : static void ndisc_router_discovery(struct sk_buff *skb)
    1059                 :            : {
    1060                 :            :         struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb);
    1061                 :            :         struct neighbour *neigh = NULL;
    1062                 :          0 :         struct inet6_dev *in6_dev;
    1063                 :            :         struct rt6_info *rt = NULL;
    1064                 :            :         int lifetime;
    1065                 :            :         struct ndisc_options ndopts;
    1066                 :            :         int optlen;
    1067                 :            :         unsigned int pref = 0;
    1068                 :            : 
    1069                 :          0 :         __u8 * opt = (__u8 *)(ra_msg + 1);
    1070                 :            : 
    1071                 :          0 :         optlen = (skb_tail_pointer(skb) - skb_transport_header(skb)) -
    1072                 :            :                 sizeof(struct ra_msg);
    1073                 :            : 
    1074         [ #  # ]:          0 :         if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
    1075                 :            :                 ND_PRINTK(2, warn, "RA: source address is not link-local\n");
    1076                 :          0 :                 return;
    1077                 :            :         }
    1078         [ #  # ]:          0 :         if (optlen < 0) {
    1079                 :            :                 ND_PRINTK(2, warn, "RA: packet too short\n");
    1080                 :            :                 return;
    1081                 :            :         }
    1082                 :            : 
    1083                 :            : #ifdef CONFIG_IPV6_NDISC_NODETYPE
    1084         [ #  # ]:          0 :         if (skb->ndisc_nodetype == NDISC_NODETYPE_HOST) {
    1085                 :            :                 ND_PRINTK(2, warn, "RA: from host or unauthorized router\n");
    1086                 :            :                 return;
    1087                 :            :         }
    1088                 :            : #endif
    1089                 :            : 
    1090                 :            :         /*
    1091                 :            :          *      set the RA_RECV flag in the interface
    1092                 :            :          */
    1093                 :            : 
    1094                 :          0 :         in6_dev = __in6_dev_get(skb->dev);
    1095         [ #  # ]:          0 :         if (in6_dev == NULL) {
    1096         [ #  # ]:          0 :                 ND_PRINTK(0, err, "RA: can't find inet6 device for %s\n",
    1097                 :            :                           skb->dev->name);
    1098                 :            :                 return;
    1099                 :            :         }
    1100                 :            : 
    1101         [ #  # ]:          0 :         if (!ndisc_parse_options(opt, optlen, &ndopts)) {
    1102                 :            :                 ND_PRINTK(2, warn, "RA: invalid ND options\n");
    1103                 :            :                 return;
    1104                 :            :         }
    1105                 :            : 
    1106         [ #  # ]:          0 :         if (!ipv6_accept_ra(in6_dev))
    1107                 :            :                 goto skip_linkparms;
    1108                 :            : 
    1109                 :            : #ifdef CONFIG_IPV6_NDISC_NODETYPE
    1110                 :            :         /* skip link-specific parameters from interior routers */
    1111         [ #  # ]:          0 :         if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT)
    1112                 :            :                 goto skip_linkparms;
    1113                 :            : #endif
    1114                 :            : 
    1115         [ #  # ]:          0 :         if (in6_dev->if_flags & IF_RS_SENT) {
    1116                 :            :                 /*
    1117                 :            :                  *      flag that an RA was received after an RS was sent
    1118                 :            :                  *      out on this interface.
    1119                 :            :                  */
    1120                 :          0 :                 in6_dev->if_flags |= IF_RA_RCVD;
    1121                 :            :         }
    1122                 :            : 
    1123                 :            :         /*
    1124                 :            :          * Remember the managed/otherconf flags from most recently
    1125                 :            :          * received RA message (RFC 2462) -- yoshfuji
    1126                 :            :          */
    1127                 :          0 :         in6_dev->if_flags = (in6_dev->if_flags & ~(IF_RA_MANAGED |
    1128         [ #  # ]:          0 :                                 IF_RA_OTHERCONF)) |
    1129                 :          0 :                                 (ra_msg->icmph.icmp6_addrconf_managed ?
    1130         [ #  # ]:          0 :                                         IF_RA_MANAGED : 0) |
    1131                 :          0 :                                 (ra_msg->icmph.icmp6_addrconf_other ?
    1132                 :            :                                         IF_RA_OTHERCONF : 0);
    1133                 :            : 
    1134         [ #  # ]:          0 :         if (!in6_dev->cnf.accept_ra_defrtr)
    1135                 :            :                 goto skip_defrtr;
    1136                 :            : 
    1137         [ #  # ]:          0 :         if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, NULL, 0))
    1138                 :            :                 goto skip_defrtr;
    1139                 :            : 
    1140         [ #  # ]:          0 :         lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
    1141                 :            : 
    1142                 :            : #ifdef CONFIG_IPV6_ROUTER_PREF
    1143                 :            :         pref = ra_msg->icmph.icmp6_router_pref;
    1144                 :            :         /* 10b is handled as if it were 00b (medium) */
    1145                 :            :         if (pref == ICMPV6_ROUTER_PREF_INVALID ||
    1146                 :            :             !in6_dev->cnf.accept_ra_rtr_pref)
    1147                 :            :                 pref = ICMPV6_ROUTER_PREF_MEDIUM;
    1148                 :            : #endif
    1149                 :            : 
    1150                 :          0 :         rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev);
    1151                 :            : 
    1152         [ #  # ]:          0 :         if (rt) {
    1153                 :          0 :                 neigh = dst_neigh_lookup(&rt->dst, &ipv6_hdr(skb)->saddr);
    1154         [ #  # ]:          0 :                 if (!neigh) {
    1155         [ #  # ]:          0 :                         ND_PRINTK(0, err,
    1156                 :            :                                   "RA: %s got default router without neighbour\n",
    1157                 :            :                                   __func__);
    1158                 :            :                         ip6_rt_put(rt);
    1159                 :            :                         return;
    1160                 :            :                 }
    1161                 :            :         }
    1162         [ #  # ]:          0 :         if (rt && lifetime == 0) {
    1163                 :          0 :                 ip6_del_rt(rt);
    1164                 :            :                 rt = NULL;
    1165                 :            :         }
    1166                 :            : 
    1167         [ #  # ]:          0 :         if (rt == NULL && lifetime) {
    1168                 :            :                 ND_PRINTK(3, dbg, "RA: adding default router\n");
    1169                 :            : 
    1170                 :          0 :                 rt = rt6_add_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev, pref);
    1171         [ #  # ]:          0 :                 if (rt == NULL) {
    1172         [ #  # ]:          0 :                         ND_PRINTK(0, err,
    1173                 :            :                                   "RA: %s failed to add default route\n",
    1174                 :            :                                   __func__);
    1175                 :            :                         return;
    1176                 :            :                 }
    1177                 :            : 
    1178                 :          0 :                 neigh = dst_neigh_lookup(&rt->dst, &ipv6_hdr(skb)->saddr);
    1179         [ #  # ]:          0 :                 if (neigh == NULL) {
    1180         [ #  # ]:          0 :                         ND_PRINTK(0, err,
    1181                 :            :                                   "RA: %s got default router without neighbour\n",
    1182                 :            :                                   __func__);
    1183                 :            :                         ip6_rt_put(rt);
    1184                 :            :                         return;
    1185                 :            :                 }
    1186                 :          0 :                 neigh->flags |= NTF_ROUTER;
    1187         [ #  # ]:          0 :         } else if (rt) {
    1188                 :          0 :                 rt->rt6i_flags = (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
    1189                 :            :         }
    1190                 :            : 
    1191         [ #  # ]:          0 :         if (rt)
    1192                 :          0 :                 rt6_set_expires(rt, jiffies + (HZ * lifetime));
    1193         [ #  # ]:          0 :         if (ra_msg->icmph.icmp6_hop_limit) {
    1194                 :          0 :                 in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
    1195         [ #  # ]:          0 :                 if (rt)
    1196                 :          0 :                         dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
    1197                 :          0 :                                        ra_msg->icmph.icmp6_hop_limit);
    1198                 :            :         }
    1199                 :            : 
    1200                 :            : skip_defrtr:
    1201                 :            : 
    1202                 :            :         /*
    1203                 :            :          *      Update Reachable Time and Retrans Timer
    1204                 :            :          */
    1205                 :            : 
    1206         [ #  # ]:          0 :         if (in6_dev->nd_parms) {
    1207         [ #  # ]:          0 :                 unsigned long rtime = ntohl(ra_msg->retrans_timer);
    1208                 :            : 
    1209         [ #  # ]:          0 :                 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) {
    1210                 :          0 :                         rtime = (rtime*HZ)/1000;
    1211         [ #  # ]:          0 :                         if (rtime < HZ/10)
    1212                 :            :                                 rtime = HZ/10;
    1213                 :          0 :                         in6_dev->nd_parms->retrans_time = rtime;
    1214                 :          0 :                         in6_dev->tstamp = jiffies;
    1215                 :          0 :                         inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
    1216                 :            :                 }
    1217                 :            : 
    1218         [ #  # ]:          0 :                 rtime = ntohl(ra_msg->reachable_time);
    1219         [ #  # ]:          0 :                 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/(3*HZ)) {
    1220                 :          0 :                         rtime = (rtime*HZ)/1000;
    1221                 :            : 
    1222         [ #  # ]:          0 :                         if (rtime < HZ/10)
    1223                 :            :                                 rtime = HZ/10;
    1224                 :            : 
    1225         [ #  # ]:          0 :                         if (rtime != in6_dev->nd_parms->base_reachable_time) {
    1226                 :          0 :                                 in6_dev->nd_parms->base_reachable_time = rtime;
    1227                 :          0 :                                 in6_dev->nd_parms->gc_staletime = 3 * rtime;
    1228                 :          0 :                                 in6_dev->nd_parms->reachable_time = neigh_rand_reach_time(rtime);
    1229                 :          0 :                                 in6_dev->tstamp = jiffies;
    1230                 :          0 :                                 inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
    1231                 :            :                         }
    1232                 :            :                 }
    1233                 :            :         }
    1234                 :            : 
    1235                 :            : skip_linkparms:
    1236                 :            : 
    1237                 :            :         /*
    1238                 :            :          *      Process options.
    1239                 :            :          */
    1240                 :            : 
    1241         [ #  # ]:          0 :         if (!neigh)
    1242                 :          0 :                 neigh = __neigh_lookup(&nd_tbl, &ipv6_hdr(skb)->saddr,
    1243                 :            :                                        skb->dev, 1);
    1244         [ #  # ]:          0 :         if (neigh) {
    1245                 :            :                 u8 *lladdr = NULL;
    1246         [ #  # ]:          0 :                 if (ndopts.nd_opts_src_lladdr) {
    1247                 :          0 :                         lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
    1248                 :            :                                                      skb->dev);
    1249         [ #  # ]:          0 :                         if (!lladdr) {
    1250                 :            :                                 ND_PRINTK(2, warn,
    1251                 :            :                                           "RA: invalid link-layer address length\n");
    1252                 :            :                                 goto out;
    1253                 :            :                         }
    1254                 :            :                 }
    1255                 :          0 :                 neigh_update(neigh, lladdr, NUD_STALE,
    1256                 :            :                              NEIGH_UPDATE_F_WEAK_OVERRIDE|
    1257                 :            :                              NEIGH_UPDATE_F_OVERRIDE|
    1258                 :            :                              NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
    1259                 :            :                              NEIGH_UPDATE_F_ISROUTER);
    1260                 :            :         }
    1261                 :            : 
    1262         [ #  # ]:          0 :         if (!ipv6_accept_ra(in6_dev))
    1263                 :            :                 goto out;
    1264                 :            : 
    1265                 :            : #ifdef CONFIG_IPV6_ROUTE_INFO
    1266                 :            :         if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, NULL, 0))
    1267                 :            :                 goto skip_routeinfo;
    1268                 :            : 
    1269                 :            :         if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) {
    1270                 :            :                 struct nd_opt_hdr *p;
    1271                 :            :                 for (p = ndopts.nd_opts_ri;
    1272                 :            :                      p;
    1273                 :            :                      p = ndisc_next_option(p, ndopts.nd_opts_ri_end)) {
    1274                 :            :                         struct route_info *ri = (struct route_info *)p;
    1275                 :            : #ifdef CONFIG_IPV6_NDISC_NODETYPE
    1276                 :            :                         if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT &&
    1277                 :            :                             ri->prefix_len == 0)
    1278                 :            :                                 continue;
    1279                 :            : #endif
    1280                 :            :                         if (ri->prefix_len == 0 &&
    1281                 :            :                             !in6_dev->cnf.accept_ra_defrtr)
    1282                 :            :                                 continue;
    1283                 :            :                         if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
    1284                 :            :                                 continue;
    1285                 :            :                         rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3,
    1286                 :            :                                       &ipv6_hdr(skb)->saddr);
    1287                 :            :                 }
    1288                 :            :         }
    1289                 :            : 
    1290                 :            : skip_routeinfo:
    1291                 :            : #endif
    1292                 :            : 
    1293                 :            : #ifdef CONFIG_IPV6_NDISC_NODETYPE
    1294                 :            :         /* skip link-specific ndopts from interior routers */
    1295         [ #  # ]:          0 :         if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT)
    1296                 :            :                 goto out;
    1297                 :            : #endif
    1298                 :            : 
    1299 [ #  # ][ #  # ]:          0 :         if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) {
    1300                 :            :                 struct nd_opt_hdr *p;
    1301         [ #  # ]:          0 :                 for (p = ndopts.nd_opts_pi;
    1302                 :            :                      p;
    1303                 :          0 :                      p = ndisc_next_option(p, ndopts.nd_opts_pi_end)) {
    1304                 :          0 :                         addrconf_prefix_rcv(skb->dev, (u8 *)p,
    1305                 :          0 :                                             (p->nd_opt_len) << 3,
    1306                 :          0 :                                             ndopts.nd_opts_src_lladdr != NULL);
    1307                 :            :                 }
    1308                 :            :         }
    1309                 :            : 
    1310         [ #  # ]:          0 :         if (ndopts.nd_opts_mtu) {
    1311                 :            :                 __be32 n;
    1312                 :            :                 u32 mtu;
    1313                 :            : 
    1314                 :          0 :                 memcpy(&n, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu));
    1315         [ #  # ]:          0 :                 mtu = ntohl(n);
    1316                 :            : 
    1317 [ #  # ][ #  # ]:          0 :                 if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
    1318                 :            :                         ND_PRINTK(2, warn, "RA: invalid mtu: %d\n", mtu);
    1319         [ #  # ]:          0 :                 } else if (in6_dev->cnf.mtu6 != mtu) {
    1320                 :          0 :                         in6_dev->cnf.mtu6 = mtu;
    1321                 :            : 
    1322         [ #  # ]:          0 :                         if (rt)
    1323                 :          0 :                                 dst_metric_set(&rt->dst, RTAX_MTU, mtu);
    1324                 :            : 
    1325                 :          0 :                         rt6_mtu_change(skb->dev, mtu);
    1326                 :            :                 }
    1327                 :            :         }
    1328                 :            : 
    1329         [ #  # ]:          0 :         if (ndopts.nd_useropts) {
    1330                 :            :                 struct nd_opt_hdr *p;
    1331         [ #  # ]:          0 :                 for (p = ndopts.nd_useropts;
    1332                 :            :                      p;
    1333                 :          0 :                      p = ndisc_next_useropt(p, ndopts.nd_useropts_end)) {
    1334                 :          0 :                         ndisc_ra_useropt(skb, p);
    1335                 :            :                 }
    1336                 :            :         }
    1337                 :            : 
    1338                 :            :         if (ndopts.nd_opts_tgt_lladdr || ndopts.nd_opts_rh) {
    1339                 :            :                 ND_PRINTK(2, warn, "RA: invalid RA options\n");
    1340                 :            :         }
    1341                 :            : out:
    1342                 :            :         ip6_rt_put(rt);
    1343         [ #  # ]:          0 :         if (neigh)
    1344                 :            :                 neigh_release(neigh);
    1345                 :            : }
    1346                 :            : 
    1347                 :          0 : static void ndisc_redirect_rcv(struct sk_buff *skb)
    1348                 :            : {
    1349                 :            :         u8 *hdr;
    1350                 :            :         struct ndisc_options ndopts;
    1351                 :            :         struct rd_msg *msg = (struct rd_msg *)skb_transport_header(skb);
    1352                 :          0 :         u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
    1353                 :            :                                     offsetof(struct rd_msg, opt));
    1354                 :            : 
    1355                 :            : #ifdef CONFIG_IPV6_NDISC_NODETYPE
    1356         [ #  # ]:          0 :         switch (skb->ndisc_nodetype) {
    1357                 :            :         case NDISC_NODETYPE_HOST:
    1358                 :            :         case NDISC_NODETYPE_NODEFAULT:
    1359                 :            :                 ND_PRINTK(2, warn,
    1360                 :            :                           "Redirect: from host or unauthorized router\n");
    1361                 :          0 :                 return;
    1362                 :            :         }
    1363                 :            : #endif
    1364                 :            : 
    1365         [ #  # ]:          0 :         if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
    1366                 :            :                 ND_PRINTK(2, warn,
    1367                 :            :                           "Redirect: source address is not link-local\n");
    1368                 :            :                 return;
    1369                 :            :         }
    1370                 :            : 
    1371         [ #  # ]:          0 :         if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts))
    1372                 :            :                 return;
    1373                 :            : 
    1374         [ #  # ]:          0 :         if (!ndopts.nd_opts_rh) {
    1375                 :          0 :                 ip6_redirect_no_header(skb, dev_net(skb->dev),
    1376                 :          0 :                                         skb->dev->ifindex, 0);
    1377                 :          0 :                 return;
    1378                 :            :         }
    1379                 :            : 
    1380                 :            :         hdr = (u8 *)ndopts.nd_opts_rh;
    1381                 :          0 :         hdr += 8;
    1382         [ #  # ]:          0 :         if (!pskb_pull(skb, hdr - skb_transport_header(skb)))
    1383                 :            :                 return;
    1384                 :            : 
    1385                 :          0 :         icmpv6_notify(skb, NDISC_REDIRECT, 0, 0);
    1386                 :            : }
    1387                 :            : 
    1388                 :          0 : static void ndisc_fill_redirect_hdr_option(struct sk_buff *skb,
    1389                 :            :                                            struct sk_buff *orig_skb,
    1390                 :            :                                            int rd_len)
    1391                 :            : {
    1392                 :          0 :         u8 *opt = skb_put(skb, rd_len);
    1393                 :            : 
    1394                 :          0 :         memset(opt, 0, 8);
    1395                 :          0 :         *(opt++) = ND_OPT_REDIRECT_HDR;
    1396                 :          0 :         *(opt++) = (rd_len >> 3);
    1397                 :          0 :         opt += 6;
    1398                 :            : 
    1399                 :          0 :         memcpy(opt, ipv6_hdr(orig_skb), rd_len - 8);
    1400                 :          0 : }
    1401                 :            : 
    1402                 :          0 : void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
    1403                 :            : {
    1404                 :          0 :         struct net_device *dev = skb->dev;
    1405                 :            :         struct net *net = dev_net(dev);
    1406                 :          0 :         struct sock *sk = net->ipv6.ndisc_sk;
    1407                 :            :         int optlen = 0;
    1408                 :            :         struct inet_peer *peer;
    1409                 :            :         struct sk_buff *buff;
    1410                 :            :         struct rd_msg *msg;
    1411                 :            :         struct in6_addr saddr_buf;
    1412                 :            :         struct rt6_info *rt;
    1413                 :            :         struct dst_entry *dst;
    1414                 :            :         struct flowi6 fl6;
    1415                 :            :         int rd_len;
    1416                 :            :         u8 ha_buf[MAX_ADDR_LEN], *ha = NULL;
    1417                 :            :         bool ret;
    1418                 :            : 
    1419         [ #  # ]:          0 :         if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) {
    1420                 :            :                 ND_PRINTK(2, warn, "Redirect: no link-local address on %s\n",
    1421                 :            :                           dev->name);
    1422                 :          0 :                 return;
    1423                 :            :         }
    1424                 :            : 
    1425   [ #  #  #  # ]:          0 :         if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) &&
    1426                 :            :             ipv6_addr_type(target) != (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
    1427                 :            :                 ND_PRINTK(2, warn,
    1428                 :            :                           "Redirect: target address is not link-local unicast\n");
    1429                 :            :                 return;
    1430                 :            :         }
    1431                 :            : 
    1432                 :          0 :         icmpv6_flow_init(sk, &fl6, NDISC_REDIRECT,
    1433                 :          0 :                          &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex);
    1434                 :            : 
    1435                 :          0 :         dst = ip6_route_output(net, NULL, &fl6);
    1436         [ #  # ]:          0 :         if (dst->error) {
    1437                 :          0 :                 dst_release(dst);
    1438                 :          0 :                 return;
    1439                 :            :         }
    1440                 :          0 :         dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
    1441         [ #  # ]:          0 :         if (IS_ERR(dst))
    1442                 :            :                 return;
    1443                 :            : 
    1444                 :            :         rt = (struct rt6_info *) dst;
    1445                 :            : 
    1446         [ #  # ]:          0 :         if (rt->rt6i_flags & RTF_GATEWAY) {
    1447                 :            :                 ND_PRINTK(2, warn,
    1448                 :            :                           "Redirect: destination is not a neighbour\n");
    1449                 :            :                 goto release;
    1450                 :            :         }
    1451                 :          0 :         peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
    1452                 :          0 :         ret = inet_peer_xrlim_allow(peer, 1*HZ);
    1453         [ #  # ]:          0 :         if (peer)
    1454                 :          0 :                 inet_putpeer(peer);
    1455         [ #  # ]:          0 :         if (!ret)
    1456                 :            :                 goto release;
    1457                 :            : 
    1458         [ #  # ]:          0 :         if (dev->addr_len) {
    1459                 :            :                 struct neighbour *neigh = dst_neigh_lookup(skb_dst(skb), target);
    1460         [ #  # ]:          0 :                 if (!neigh) {
    1461                 :            :                         ND_PRINTK(2, warn,
    1462                 :            :                                   "Redirect: no neigh for target address\n");
    1463                 :            :                         goto release;
    1464                 :            :                 }
    1465                 :            : 
    1466                 :          0 :                 read_lock_bh(&neigh->lock);
    1467         [ #  # ]:          0 :                 if (neigh->nud_state & NUD_VALID) {
    1468                 :          0 :                         memcpy(ha_buf, neigh->ha, dev->addr_len);
    1469                 :          0 :                         read_unlock_bh(&neigh->lock);
    1470                 :            :                         ha = ha_buf;
    1471                 :            :                         optlen += ndisc_opt_addr_space(dev);
    1472                 :            :                 } else
    1473                 :          0 :                         read_unlock_bh(&neigh->lock);
    1474                 :            : 
    1475                 :            :                 neigh_release(neigh);
    1476                 :            :         }
    1477                 :            : 
    1478                 :          0 :         rd_len = min_t(unsigned int,
    1479                 :            :                        IPV6_MIN_MTU - sizeof(struct ipv6hdr) - sizeof(*msg) - optlen,
    1480                 :            :                        skb->len + 8);
    1481                 :          0 :         rd_len &= ~0x7;
    1482                 :          0 :         optlen += rd_len;
    1483                 :            : 
    1484                 :          0 :         buff = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
    1485         [ #  # ]:          0 :         if (!buff)
    1486                 :            :                 goto release;
    1487                 :            : 
    1488                 :          0 :         msg = (struct rd_msg *)skb_put(buff, sizeof(*msg));
    1489                 :          0 :         *msg = (struct rd_msg) {
    1490                 :            :                 .icmph = {
    1491                 :            :                         .icmp6_type = NDISC_REDIRECT,
    1492                 :            :                 },
    1493                 :          0 :                 .target = *target,
    1494                 :          0 :                 .dest = ipv6_hdr(skb)->daddr,
    1495                 :            :         };
    1496                 :            : 
    1497                 :            :         /*
    1498                 :            :          *      include target_address option
    1499                 :            :          */
    1500                 :            : 
    1501         [ #  # ]:          0 :         if (ha)
    1502                 :          0 :                 ndisc_fill_addr_option(buff, ND_OPT_TARGET_LL_ADDR, ha);
    1503                 :            : 
    1504                 :            :         /*
    1505                 :            :          *      build redirect option and copy skb over to the new packet.
    1506                 :            :          */
    1507                 :            : 
    1508         [ #  # ]:          0 :         if (rd_len)
    1509                 :          0 :                 ndisc_fill_redirect_hdr_option(buff, skb, rd_len);
    1510                 :            : 
    1511                 :            :         skb_dst_set(buff, dst);
    1512                 :          0 :         ndisc_send_skb(buff, &ipv6_hdr(skb)->saddr, &saddr_buf);
    1513                 :          0 :         return;
    1514                 :            : 
    1515                 :            : release:
    1516                 :          0 :         dst_release(dst);
    1517                 :            : }
    1518                 :            : 
    1519                 :          0 : static void pndisc_redo(struct sk_buff *skb)
    1520                 :            : {
    1521                 :          0 :         ndisc_recv_ns(skb);
    1522                 :          0 :         kfree_skb(skb);
    1523                 :          0 : }
    1524                 :            : 
    1525                 :          0 : static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
    1526                 :            : {
    1527                 :         93 :         struct inet6_dev *idev = __in6_dev_get(skb->dev);
    1528                 :            : 
    1529         [ +  - ]:         93 :         if (!idev)
    1530                 :            :                 return true;
    1531 [ -  + ][ #  # ]:         93 :         if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED &&
    1532                 :          0 :             idev->cnf.suppress_frag_ndisc) {
    1533         [ #  # ]:          0 :                 net_warn_ratelimited("Received fragmented ndisc packet. Carefully consider disabling suppress_frag_ndisc.\n");
    1534                 :            :                 return true;
    1535                 :            :         }
    1536                 :            :         return false;
    1537                 :            : }
    1538                 :            : 
    1539                 :          0 : int ndisc_rcv(struct sk_buff *skb)
    1540                 :            : {
    1541                 :            :         struct nd_msg *msg;
    1542                 :            : 
    1543         [ +  - ]:         93 :         if (ndisc_suppress_frag_ndisc(skb))
    1544                 :            :                 return 0;
    1545                 :            : 
    1546         [ +  - ]:         93 :         if (skb_linearize(skb))
    1547                 :            :                 return 0;
    1548                 :            : 
    1549                 :            :         msg = (struct nd_msg *)skb_transport_header(skb);
    1550                 :            : 
    1551                 :         93 :         __skb_push(skb, skb->data - skb_transport_header(skb));
    1552                 :            : 
    1553         [ +  - ]:         93 :         if (ipv6_hdr(skb)->hop_limit != 255) {
    1554                 :            :                 ND_PRINTK(2, warn, "NDISC: invalid hop-limit: %d\n",
    1555                 :            :                           ipv6_hdr(skb)->hop_limit);
    1556                 :            :                 return 0;
    1557                 :            :         }
    1558                 :            : 
    1559         [ +  - ]:         93 :         if (msg->icmph.icmp6_code != 0) {
    1560                 :            :                 ND_PRINTK(2, warn, "NDISC: invalid ICMPv6 code: %d\n",
    1561                 :            :                           msg->icmph.icmp6_code);
    1562                 :            :                 return 0;
    1563                 :            :         }
    1564                 :            : 
    1565                 :         93 :         memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
    1566                 :            : 
    1567   [ -  +  -  -  :         93 :         switch (msg->icmph.icmp6_type) {
                   -  - ]
    1568                 :            :         case NDISC_NEIGHBOUR_SOLICITATION:
    1569                 :          0 :                 ndisc_recv_ns(skb);
    1570                 :          0 :                 break;
    1571                 :            : 
    1572                 :            :         case NDISC_NEIGHBOUR_ADVERTISEMENT:
    1573                 :         93 :                 ndisc_recv_na(skb);
    1574                 :         93 :                 break;
    1575                 :            : 
    1576                 :            :         case NDISC_ROUTER_SOLICITATION:
    1577                 :          0 :                 ndisc_recv_rs(skb);
    1578                 :          0 :                 break;
    1579                 :            : 
    1580                 :            :         case NDISC_ROUTER_ADVERTISEMENT:
    1581                 :          0 :                 ndisc_router_discovery(skb);
    1582                 :          0 :                 break;
    1583                 :            : 
    1584                 :            :         case NDISC_REDIRECT:
    1585                 :          0 :                 ndisc_redirect_rcv(skb);
    1586                 :          0 :                 break;
    1587                 :            :         }
    1588                 :            : 
    1589                 :            :         return 0;
    1590                 :            : }
    1591                 :            : 
    1592                 :          0 : static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
    1593                 :            : {
    1594                 :            :         struct net_device *dev = netdev_notifier_info_to_dev(ptr);
    1595                 :            :         struct net *net = dev_net(dev);
    1596                 :            :         struct inet6_dev *idev;
    1597                 :            : 
    1598   [ #  #  #  # ]:          0 :         switch (event) {
    1599                 :            :         case NETDEV_CHANGEADDR:
    1600                 :          0 :                 neigh_changeaddr(&nd_tbl, dev);
    1601                 :          0 :                 fib6_run_gc(0, net, false);
    1602                 :            :                 idev = in6_dev_get(dev);
    1603         [ #  # ]:          0 :                 if (!idev)
    1604                 :            :                         break;
    1605         [ #  # ]:          0 :                 if (idev->cnf.ndisc_notify)
    1606                 :          0 :                         ndisc_send_unsol_na(dev);
    1607                 :            :                 in6_dev_put(idev);
    1608                 :            :                 break;
    1609                 :            :         case NETDEV_DOWN:
    1610                 :          0 :                 neigh_ifdown(&nd_tbl, dev);
    1611                 :          0 :                 fib6_run_gc(0, net, false);
    1612                 :          0 :                 break;
    1613                 :            :         case NETDEV_NOTIFY_PEERS:
    1614                 :          0 :                 ndisc_send_unsol_na(dev);
    1615                 :          0 :                 break;
    1616                 :            :         default:
    1617                 :            :                 break;
    1618                 :            :         }
    1619                 :            : 
    1620                 :          0 :         return NOTIFY_DONE;
    1621                 :            : }
    1622                 :            : 
    1623                 :            : static struct notifier_block ndisc_netdev_notifier = {
    1624                 :            :         .notifier_call = ndisc_netdev_event,
    1625                 :            : };
    1626                 :            : 
    1627                 :            : #ifdef CONFIG_SYSCTL
    1628                 :          0 : static void ndisc_warn_deprecated_sysctl(struct ctl_table *ctl,
    1629                 :            :                                          const char *func, const char *dev_name)
    1630                 :            : {
    1631                 :            :         static char warncomm[TASK_COMM_LEN];
    1632                 :            :         static int warned;
    1633 [ +  + ][ +  - ]:         16 :         if (strcmp(warncomm, current->comm) && warned < 5) {
    1634                 :          1 :                 strcpy(warncomm, current->comm);
    1635                 :          1 :                 pr_warn("process `%s' is using deprecated sysctl (%s) net.ipv6.neigh.%s.%s - use net.ipv6.neigh.%s.%s_ms instead\n",
    1636                 :            :                         warncomm, func,
    1637                 :            :                         dev_name, ctl->procname,
    1638                 :            :                         dev_name, ctl->procname);
    1639                 :          1 :                 warned++;
    1640                 :            :         }
    1641                 :          0 : }
    1642                 :            : 
    1643                 :          0 : int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
    1644                 :            : {
    1645                 :         32 :         struct net_device *dev = ctl->extra1;
    1646                 :            :         struct inet6_dev *idev;
    1647                 :            :         int ret;
    1648                 :            : 
    1649 [ +  + ][ +  + ]:         32 :         if ((strcmp(ctl->procname, "retrans_time") == 0) ||
    1650                 :         24 :             (strcmp(ctl->procname, "base_reachable_time") == 0))
    1651         [ +  + ]:         16 :                 ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default");
    1652                 :            : 
    1653         [ +  + ]:         32 :         if (strcmp(ctl->procname, "retrans_time") == 0)
    1654                 :          8 :                 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
    1655                 :            : 
    1656         [ +  + ]:         24 :         else if (strcmp(ctl->procname, "base_reachable_time") == 0)
    1657                 :          8 :                 ret = proc_dointvec_jiffies(ctl, write,
    1658                 :            :                                             buffer, lenp, ppos);
    1659                 :            : 
    1660 [ +  + ][ +  - ]:         16 :         else if ((strcmp(ctl->procname, "retrans_time_ms") == 0) ||
    1661                 :          8 :                  (strcmp(ctl->procname, "base_reachable_time_ms") == 0))
    1662                 :         16 :                 ret = proc_dointvec_ms_jiffies(ctl, write,
    1663                 :            :                                                buffer, lenp, ppos);
    1664                 :            :         else
    1665                 :            :                 ret = -1;
    1666                 :            : 
    1667         [ -  + ]:         32 :         if (write && ret == 0 && dev && (idev = in6_dev_get(dev)) != NULL) {
           [ #  #  #  # ]
    1668         [ #  # ]:          0 :                 if (ctl->data == &idev->nd_parms->base_reachable_time)
    1669                 :          0 :                         idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
    1670                 :          0 :                 idev->tstamp = jiffies;
    1671                 :          0 :                 inet6_ifinfo_notify(RTM_NEWLINK, idev);
    1672                 :            :                 in6_dev_put(idev);
    1673                 :            :         }
    1674                 :         32 :         return ret;
    1675                 :            : }
    1676                 :            : 
    1677                 :            : 
    1678                 :            : #endif
    1679                 :            : 
    1680                 :          0 : static int __net_init ndisc_net_init(struct net *net)
    1681                 :            : {
    1682                 :            :         struct ipv6_pinfo *np;
    1683                 :            :         struct sock *sk;
    1684                 :            :         int err;
    1685                 :            : 
    1686                 :          0 :         err = inet_ctl_sock_create(&sk, PF_INET6,
    1687                 :            :                                    SOCK_RAW, IPPROTO_ICMPV6, net);
    1688         [ #  # ]:          0 :         if (err < 0) {
    1689         [ #  # ]:          0 :                 ND_PRINTK(0, err,
    1690                 :            :                           "NDISC: Failed to initialize the control socket (err %d)\n",
    1691                 :            :                           err);
    1692                 :          0 :                 return err;
    1693                 :            :         }
    1694                 :            : 
    1695                 :          0 :         net->ipv6.ndisc_sk = sk;
    1696                 :            : 
    1697                 :            :         np = inet6_sk(sk);
    1698                 :          0 :         np->hop_limit = 255;
    1699                 :            :         /* Do not loopback ndisc messages */
    1700                 :          0 :         np->mc_loop = 0;
    1701                 :            : 
    1702                 :          0 :         return 0;
    1703                 :            : }
    1704                 :            : 
    1705                 :          0 : static void __net_exit ndisc_net_exit(struct net *net)
    1706                 :            : {
    1707                 :          0 :         inet_ctl_sock_destroy(net->ipv6.ndisc_sk);
    1708                 :          0 : }
    1709                 :            : 
    1710                 :            : static struct pernet_operations ndisc_net_ops = {
    1711                 :            :         .init = ndisc_net_init,
    1712                 :            :         .exit = ndisc_net_exit,
    1713                 :            : };
    1714                 :            : 
    1715                 :          0 : int __init ndisc_init(void)
    1716                 :            : {
    1717                 :            :         int err;
    1718                 :            : 
    1719                 :          0 :         err = register_pernet_subsys(&ndisc_net_ops);
    1720         [ #  # ]:          0 :         if (err)
    1721                 :            :                 return err;
    1722                 :            :         /*
    1723                 :            :          * Initialize the neighbour table
    1724                 :            :          */
    1725                 :          0 :         neigh_table_init(&nd_tbl);
    1726                 :            : 
    1727                 :            : #ifdef CONFIG_SYSCTL
    1728                 :          0 :         err = neigh_sysctl_register(NULL, &nd_tbl.parms, "ipv6",
    1729                 :            :                                     &ndisc_ifinfo_sysctl_change);
    1730         [ #  # ]:          0 :         if (err)
    1731                 :            :                 goto out_unregister_pernet;
    1732                 :            : out:
    1733                 :            : #endif
    1734                 :          0 :         return err;
    1735                 :            : 
    1736                 :            : #ifdef CONFIG_SYSCTL
    1737                 :            : out_unregister_pernet:
    1738                 :          0 :         unregister_pernet_subsys(&ndisc_net_ops);
    1739                 :          0 :         goto out;
    1740                 :            : #endif
    1741                 :            : }
    1742                 :            : 
    1743                 :          0 : int __init ndisc_late_init(void)
    1744                 :            : {
    1745                 :          0 :         return register_netdevice_notifier(&ndisc_netdev_notifier);
    1746                 :            : }
    1747                 :            : 
    1748                 :          0 : void ndisc_late_cleanup(void)
    1749                 :            : {
    1750                 :          0 :         unregister_netdevice_notifier(&ndisc_netdev_notifier);
    1751                 :          0 : }
    1752                 :            : 
    1753                 :          0 : void ndisc_cleanup(void)
    1754                 :            : {
    1755                 :            : #ifdef CONFIG_SYSCTL
    1756                 :          0 :         neigh_sysctl_unregister(&nd_tbl.parms);
    1757                 :            : #endif
    1758                 :          0 :         neigh_table_clear(&nd_tbl);
    1759                 :          0 :         unregister_pernet_subsys(&ndisc_net_ops);
    1760                 :          0 : }

Generated by: LCOV version 1.9