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

Generated by: LCOV version 1.9