ndisc.c revision 3b00944c5c73c49ef52bf17b66557c43c1d945fe
10a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg/* 25484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg * Neighbour Discovery for IPv6 35484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg * Linux INET6 implementation 40a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * 50a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * Authors: 60a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * Pedro Roque <roque@di.fc.ul.pt> 70a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * Mike Shaver <shaver@ingenia.com> 80a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * 90a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * This program is free software; you can redistribute it and/or 100a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * modify it under the terms of the GNU General Public License 110a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * as published by the Free Software Foundation; either version 120a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * 2 of the License, or (at your option) any later version. 130a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg */ 140a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 150a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg/* 16888d04dfbe7e09f930fdaafb257cce2c54c9c3f3Felix Fietkau * Changes: 17078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg * 18e8db0be1245de16a6cc6365506abc392c3c212d4Jean Pihet * Pierre Ynard : export userland ND options 19df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa * through netlink (RDNSS support) 205a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo * Lars Fenneberg : fixed MTU setting on receipt 21bc3b2d7fb9b014d75ebb79ba371a763dbab5e8cfPaul Gortmaker * of an RA. 220a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * Janos Farkas : kmalloc failure checks 230a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * Alexey Kuznetsov : state machine reworked 240a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * and moved to net/core. 252448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg * Pekka Savola : RFC2461 validation 265484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg * YOSHIFUJI Hideaki @USAGI : Verify ND options properly 270a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg */ 280a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 290a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg/* Set to 3 to get tracing... */ 303f892b61a8cf6a85bc389c8d13209d686a4f6403Stanislaw Gruszka#define ND_DEBUG 1 310a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 325484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#define ND_PRINTK(fmt, args...) do { if (net_ratelimit()) { printk(fmt, ## args); } } while(0) 33c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg#define ND_NOPRINTK(x...) do { ; } while(0) 345484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#define ND_PRINTK0 ND_PRINTK 350c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg#define ND_PRINTK1 ND_NOPRINTK 360c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg#define ND_PRINTK2 ND_NOPRINTK 375b112d3d098c97b867cc580f590395cd1e72f18cJohannes Berg#define ND_PRINTK3 ND_NOPRINTK 385b112d3d098c97b867cc580f590395cd1e72f18cJohannes Berg#if ND_DEBUG >= 1 395484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#undef ND_PRINTK1 405484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#define ND_PRINTK1 ND_PRINTK 41ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#endif 42ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#if ND_DEBUG >= 2 43ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#undef ND_PRINTK2 44ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#define ND_PRINTK2 ND_PRINTK 45ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#endif 46ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#if ND_DEBUG >= 3 47ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#undef ND_PRINTK3 48ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#define ND_PRINTK3 ND_PRINTK 49ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#endif 50ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo 51ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/module.h> 52ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/errno.h> 53ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/types.h> 54ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/socket.h> 55ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/sockios.h> 56ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/sched.h> 57ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/net.h> 58c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg#include <linux/in6.h> 595484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#include <linux/route.h> 605484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#include <linux/init.h> 61d45c41722a3eca639ced2c4c93665ced229b1da9Emmanuel Grumbach#include <linux/rcupdate.h> 625484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#ifdef CONFIG_SYSCTL 63d45c41722a3eca639ced2c4c93665ced229b1da9Emmanuel Grumbach#include <linux/sysctl.h> 645484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#endif 65d45c41722a3eca639ced2c4c93665ced229b1da9Emmanuel Grumbach 660c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg#include <linux/if_addr.h> 67c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg#include <linux/if_arp.h> 68f0b058b61711ebf5be94d6865ca7b2c259b71d37Stanislaw Gruszka#include <linux/ipv6.h> 692a5193119269062608582418deba7af82844159aJohannes Berg#include <linux/icmpv6.h> 702a5193119269062608582418deba7af82844159aJohannes Berg#include <linux/jhash.h> 7177965c970d7da9c9b6349ff2b1d9adecf54c403bJohannes Berg 722a5193119269062608582418deba7af82844159aJohannes Berg#include <net/sock.h> 7377965c970d7da9c9b6349ff2b1d9adecf54c403bJohannes Berg#include <net/snmp.h> 742a5193119269062608582418deba7af82844159aJohannes Berg 752a5193119269062608582418deba7af82844159aJohannes Berg#include <net/ipv6.h> 760c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg#include <net/protocol.h> 770c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg#include <net/ndisc.h> 780c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg#include <net/ip6_route.h> 7900d3f14cf9f12c21428121026a5e1d5f65926447Johannes Berg#include <net/addrconf.h> 8000d3f14cf9f12c21428121026a5e1d5f65926447Johannes Berg#include <net/icmp.h> 810c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg 825484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#include <net/netlink.h> 83ef429dadf33feeb150098dbe84ccaa877e3261f6Johannes Berg#include <linux/rtnetlink.h> 84ef429dadf33feeb150098dbe84ccaa877e3261f6Johannes Berg 85ef429dadf33feeb150098dbe84ccaa877e3261f6Johannes Berg#include <net/flow.h> 86ef429dadf33feeb150098dbe84ccaa877e3261f6Johannes Berg#include <net/ip6_checksum.h> 878c358bcd097fa1f63e57fb82525ba52f4a537bfaJohannes Berg#include <linux/proc_fs.h> 88fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart 89fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart#include <linux/netfilter.h> 90fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart#include <linux/netfilter_ipv6.h> 91fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart 92fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic struct socket *ndisc_socket; 93fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart 94fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic u32 ndisc_hash(const void *pkey, const struct net_device *dev); 95fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic int ndisc_constructor(struct neighbour *neigh); 96fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb); 97fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb); 98fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic int pndisc_constructor(struct pneigh_entry *n); 99fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic void pndisc_destructor(struct pneigh_entry *n); 1005484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Bergstatic void pndisc_redo(struct sk_buff *skb); 101fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart 102fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic struct neigh_ops ndisc_generic_ops = { 103fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .family = AF_INET6, 1045484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg .solicit = ndisc_solicit, 1053db1cd5c05f35fb43eb134df6f321de4e63141f2Rusty Russell .error_report = ndisc_error_report, 106fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .output = neigh_resolve_output, 107fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .connected_output = neigh_connected_output, 1085484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg .hh_output = dev_queue_xmit, 1095484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg .queue_xmit = dev_queue_xmit, 110f0b058b61711ebf5be94d6865ca7b2c259b71d37Stanislaw Gruszka}; 111fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart 112fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic struct neigh_ops ndisc_hh_ops = { 113fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .family = AF_INET6, 114fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .solicit = ndisc_solicit, 115fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .error_report = ndisc_error_report, 116fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .output = neigh_resolve_output, 117fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .connected_output = neigh_resolve_output, 118fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .hh_output = dev_queue_xmit, 119fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .queue_xmit = dev_queue_xmit, 120fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart}; 121fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart 122fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart 123fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic struct neigh_ops ndisc_direct_ops = { 124fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .family = AF_INET6, 125fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .output = dev_queue_xmit, 126fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .connected_output = dev_queue_xmit, 127fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .hh_output = dev_queue_xmit, 128fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .queue_xmit = dev_queue_xmit, 129fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart}; 130fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart 131fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstruct neigh_table nd_tbl = { 132fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .family = AF_INET6, 133fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .entry_size = sizeof(struct neighbour) + sizeof(struct in6_addr), 1345484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg .key_len = sizeof(struct in6_addr), 1355484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg .hash = ndisc_hash, 136fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .constructor = ndisc_constructor, 137fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .pconstructor = pndisc_constructor, 138fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .pdestructor = pndisc_destructor, 139fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .proxy_redo = pndisc_redo, 140fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .id = "ndisc_cache", 141fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .parms = { 142fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart .tbl = &nd_tbl, 1435484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg .base_reachable_time = 30 * HZ, 1445484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg .retrans_time = 1 * HZ, 1455484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg .gc_staletime = 60 * HZ, 1460a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg .reachable_time = 30 * HZ, 147d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg .delay_probe_time = 5 * HZ, 14898c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg .queue_len = 3, 149f1d58c2521eb160178b2151d6326d8dc5d7c8560Johannes Berg .ucast_probes = 3, 150d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg .mcast_probes = 3, 151d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg .anycast_delay = 1 * HZ, 152c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg .proxy_delay = (8 * HZ) / 10, 15398c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg .proxy_qlen = 64, 15498c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg }, 15598c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg .gc_interval = 30 * HZ, 156d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg .gc_thresh1 = 128, 15798c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg .gc_thresh2 = 512, 15898c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg .gc_thresh3 = 1024, 159d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg}; 160d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg 161d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg/* ND options */ 162d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Bergstruct ndisc_options { 16398c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX]; 164d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg#ifdef CONFIG_IPV6_ROUTE_INFO 165d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg struct nd_opt_hdr *nd_opts_ri; 16698c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg struct nd_opt_hdr *nd_opts_ri_end; 167d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg#endif 168d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg struct nd_opt_hdr *nd_useropts; 16998c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg struct nd_opt_hdr *nd_useropts_end; 170d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg}; 17198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 172d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg#define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR] 173d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg#define nd_opts_tgt_lladdr nd_opt_array[ND_OPT_TARGET_LL_ADDR] 174d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg#define nd_opts_pi nd_opt_array[ND_OPT_PREFIX_INFO] 17598c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg#define nd_opts_pi_end nd_opt_array[__ND_OPT_PREFIX_INFO_END] 17698c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg#define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR] 17798c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg#define nd_opts_mtu nd_opt_array[ND_OPT_MTU] 178d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg 17998c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg#define NDISC_OPT_SPACE(len) (((len)+2+7)&~7) 18098c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 18198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg/* 182d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg * Return the padding between the option length and the start of the 18398c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg * link addr. Currently only IP-over-InfiniBand needs this, although 18498c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg * if RFC 3831 IPv6-over-Fibre Channel is ever implemented it may 18598c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg * also need a pad of 2. 186d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg */ 18798c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Bergstatic int ndisc_addr_option_pad(unsigned short type) 18898c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg{ 18998c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg switch (type) { 1900172bb75073e11a5aa9d8a953bdaefb8709f00c8Johannes Berg case ARPHRD_INFINIBAND: return 2; 19198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg default: return 0; 19298c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg } 193d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg} 19498c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 195d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Bergstatic inline int ndisc_opt_addr_space(struct net_device *dev) 19698c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg{ 197d45c41722a3eca639ced2c4c93665ced229b1da9Emmanuel Grumbach return NDISC_OPT_SPACE(dev->addr_len + ndisc_addr_option_pad(dev->type)); 198d048e503a2b01e771ee87921c24d89d7ec3f0c2fJouni Malinen} 199d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg 20098c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Bergstatic u8 *ndisc_fill_addr_option(u8 *opt, int type, void *data, int data_len, 20198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg unsigned short addr_type) 2024d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg{ 2034d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg int space = NDISC_OPT_SPACE(data_len); 2044d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg int pad = ndisc_addr_option_pad(addr_type); 2054d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg 2064d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg opt[0] = type; 2074d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg opt[1] = space>>3; 2084d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg 2094d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg memset(opt + 2, 0, pad); 2104d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg opt += pad; 2114d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg space -= pad; 2124d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg 2134d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg memcpy(opt+2, data, data_len); 2144d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg data_len += 2; 2154d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg opt += data_len; 2164d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg if ((space -= data_len) > 0) 2174d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg memset(opt, 0, space); 2184d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg return opt + space; 2194d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg} 2204d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg 2214d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Bergstatic struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur, 2224d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg struct nd_opt_hdr *end) 2234d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg{ 2244d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg int type; 2254d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg if (!cur || !end || cur >= end) 2264d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg return NULL; 2274d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg type = cur->nd_opt_type; 2284d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg do { 229c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg cur = ((void *)cur) + (cur->nd_opt_len << 3); 2308ee3108075c9e9e2701493a245a754b8b0db8e57Johannes Berg } while(cur < end && cur->nd_opt_type != type); 23185a237fe308405ee38eb9c6733571c49902ec229Johannes Berg return (cur <= end && cur->nd_opt_type == type ? cur : NULL); 2324d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg} 233dcd83976bea3ae3bc0822ed26cf200d9d6203121Johannes Berg 2344d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Bergstatic inline int ndisc_is_useropt(struct nd_opt_hdr *opt) 2354d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg{ 2364d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg return (opt->nd_opt_type == ND_OPT_RDNSS); 2374d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg} 238d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg 239e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszkastatic struct nd_opt_hdr *ndisc_next_useropt(struct nd_opt_hdr *cur, 2400a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct nd_opt_hdr *end) 2410a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg{ 2420a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (!cur || !end || cur >= end) 243e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka return NULL; 2445bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg do { 2456d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg cur = ((void *)cur) + (cur->nd_opt_len << 3); 2466d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg } while(cur < end && !ndisc_is_useropt(cur)); 2476d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg return (cur <= end && ndisc_is_useropt(cur) ? cur : NULL); 2486d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg} 2496d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg 2506d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Bergstatic struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, 2516d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg struct ndisc_options *ndopts) 2526d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg{ 2535bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)opt; 254e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka 255d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg if (!nd_opt || opt_len < 0 || !ndopts) 256de95a54b1aebe5592cae971ca5e5d9ec6a381a17Johannes Berg return NULL; 2574d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg memset(ndopts, 0, sizeof(*ndopts)); 258e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg while (opt_len) { 259e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg int l; 260e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg if (opt_len < sizeof(struct nd_opt_hdr)) 261e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg return NULL; 262e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg l = nd_opt->nd_opt_len << 3; 263e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg if (opt_len < l || l == 0) 264e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg return NULL; 2656eb11a9a311a0f7e5b9b66c18f7498a26c9ec206Stanislaw Gruszka switch (nd_opt->nd_opt_type) { 266d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg case ND_OPT_SOURCE_LL_ADDR: 2674d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg case ND_OPT_TARGET_LL_ADDR: 2684d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg case ND_OPT_MTU: 2694d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg case ND_OPT_REDIRECT_HDR: 2704d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) { 271f3b85252f081581a8f257545ed748062dce7798bJohannes Berg ND_PRINTK2(KERN_WARNING 2725ba63533bbf653631faab60f6988506160ec6ba4Johannes Berg "%s(): duplicated ND6 option found: type=%d\n", 2732a5193119269062608582418deba7af82844159aJohannes Berg __FUNCTION__, 2742a5193119269062608582418deba7af82844159aJohannes Berg nd_opt->nd_opt_type); 2753aa569c3fedbd0d16041d08bf6e89b8c43aee650Johannes Berg } else { 2762a5193119269062608582418deba7af82844159aJohannes Berg ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt; 277fbe9c429f195111bbf7f1630efa19aee295fd8e7Helmut Schaa } 27858905ca5b11a0ff3860f55b789cbbf052f7158a7Johannes Berg break; 279f3b85252f081581a8f257545ed748062dce7798bJohannes Berg case ND_OPT_PREFIX_INFO: 28007ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg ndopts->nd_opts_pi_end = nd_opt; 28107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg if (!ndopts->nd_opt_array[nd_opt->nd_opt_type]) 282a0daa0e7592ada797d6835f11529097aabc27ad2Luis R. Rodriguez ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt; 283e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka break; 284e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka#ifdef CONFIG_IPV6_ROUTE_INFO 285e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka case ND_OPT_ROUTE_INFO: 286aacde9ee45225f7e0b90960f479aef83c66bfdc0Stanislaw Gruszka ndopts->nd_opts_ri_end = nd_opt; 287e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka if (!ndopts->nd_opts_ri) 2880a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg ndopts->nd_opts_ri = nd_opt; 2895cff20e6c5a6591a79d3b027af222870f52bb550Johannes Berg break; 290e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka#endif 2910a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg default: 292469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (ndisc_is_useropt(nd_opt)) { 293472dbc45dc1966284de72d7de15690c17ed2cf33Johannes Berg ndopts->nd_useropts_end = nd_opt; 2942eb278e083549f4eb29838037004054b3b55df62Johannes Berg if (!ndopts->nd_useropts) 2950a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg ndopts->nd_useropts = nd_opt; 2968789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg } else { 2978789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg /* 2988789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg * Unknown options must be silently ignored, 2998789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg * to accommodate future extension to the 3008789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg * protocol. 3018789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg */ 3028789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg ND_PRINTK2(KERN_NOTICE 3038789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg "%s(): ignored unsupported option; type=%d, len=%d\n", 3048789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg __FUNCTION__, 3058789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg nd_opt->nd_opt_type, nd_opt->nd_opt_len); 3068789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg } 3078789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg } 3080a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg opt_len -= l; 3090a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg nd_opt = ((void *)nd_opt) + l; 310f3b85252f081581a8f257545ed748062dce7798bJohannes Berg } 311f3b85252f081581a8f257545ed748062dce7798bJohannes Berg return ndopts; 312fe57d9f5c0a2c1ef97ba8cdc42cfda5743f287b8Johannes Berg} 313fe57d9f5c0a2c1ef97ba8cdc42cfda5743f287b8Johannes Berg 314fe57d9f5c0a2c1ef97ba8cdc42cfda5743f287b8Johannes Bergstatic inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p, 315fe57d9f5c0a2c1ef97ba8cdc42cfda5743f287b8Johannes Berg struct net_device *dev) 316f3b85252f081581a8f257545ed748062dce7798bJohannes Berg{ 317f3b85252f081581a8f257545ed748062dce7798bJohannes Berg u8 *lladdr = (u8 *)(p + 1); 318f3b85252f081581a8f257545ed748062dce7798bJohannes Berg int lladdrlen = p->nd_opt_len << 3; 319f3b85252f081581a8f257545ed748062dce7798bJohannes Berg int prepad = ndisc_addr_option_pad(dev->type); 320f3b85252f081581a8f257545ed748062dce7798bJohannes Berg if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad)) 321f3b85252f081581a8f257545ed748062dce7798bJohannes Berg return NULL; 322f3b85252f081581a8f257545ed748062dce7798bJohannes Berg return (lladdr + prepad); 323f3b85252f081581a8f257545ed748062dce7798bJohannes Berg} 324f3b85252f081581a8f257545ed748062dce7798bJohannes Berg 325f3b85252f081581a8f257545ed748062dce7798bJohannes Bergint ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir) 326f3b85252f081581a8f257545ed748062dce7798bJohannes Berg{ 327f3b85252f081581a8f257545ed748062dce7798bJohannes Berg switch (dev->type) { 328f3b85252f081581a8f257545ed748062dce7798bJohannes Berg case ARPHRD_ETHER: 3292448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg case ARPHRD_IEEE802: /* Not sure. Check it later. --ANK */ 330f3b85252f081581a8f257545ed748062dce7798bJohannes Berg case ARPHRD_FDDI: 331de312db345f9770b64ff39ef5a7f86f6358e93ccRajkumar Manoharan ipv6_eth_mc_map(addr, buf); 332977923b00c79185c11b4b47664f5ffa4c3820438Helmut Schaa return 0; 333f3b85252f081581a8f257545ed748062dce7798bJohannes Berg case ARPHRD_IEEE802_TR: 334f3b85252f081581a8f257545ed748062dce7798bJohannes Berg ipv6_tr_mc_map(addr,buf); 335aacde9ee45225f7e0b90960f479aef83c66bfdc0Stanislaw Gruszka return 0; 336a80f7c0b088187c8471b441d461e937991870661Johannes Berg case ARPHRD_ARCNET: 3379c35d7d2368f54313b988a01c408e5cf863ffd9eSeth Forshee ipv6_arcnet_mc_map(addr, buf); 3389c35d7d2368f54313b988a01c408e5cf863ffd9eSeth Forshee return 0; 3399c35d7d2368f54313b988a01c408e5cf863ffd9eSeth Forshee case ARPHRD_INFINIBAND: 3403ac64beecd27400d12cc7afb4108eef26c499f6aJohannes Berg ipv6_ib_mc_map(addr, dev->broadcast, buf); 341f3b85252f081581a8f257545ed748062dce7798bJohannes Berg return 0; 34259bdf3b0fe7a183f18ce94696259c4c76abb4568Ben Greear default: 34359bdf3b0fe7a183f18ce94696259c4c76abb4568Ben Greear if (dir) { 34459bdf3b0fe7a183f18ce94696259c4c76abb4568Ben Greear memcpy(buf, dev->broadcast, dev->addr_len); 34542935ecaf4e784d0815afa9a7e5fe7e141157ca3Luis R. Rodriguez return 0; 34607ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg } 347f3b85252f081581a8f257545ed748062dce7798bJohannes Berg } 348f3b85252f081581a8f257545ed748062dce7798bJohannes Berg return -EINVAL; 349f3b85252f081581a8f257545ed748062dce7798bJohannes Berg} 350f3b85252f081581a8f257545ed748062dce7798bJohannes Berg 351133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw GruszkaEXPORT_SYMBOL(ndisc_mc_map); 352133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka 353133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszkastatic u32 ndisc_hash(const void *pkey, const struct net_device *dev) 3542eb278e083549f4eb29838037004054b3b55df62Johannes Berg{ 355133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka const u32 *p32 = pkey; 356133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka u32 addr_hash, i; 357133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka 358133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka addr_hash = 0; 359133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka for (i = 0; i < (sizeof(struct in6_addr) / sizeof(u32)); i++) 360133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka addr_hash ^= *p32++; 361133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka 362133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka return jhash_2words(addr_hash, dev->ifindex, nd_tbl.hash_rnd); 363133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka} 364133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka 365133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszkastatic int ndisc_constructor(struct neighbour *neigh) 366133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka{ 367133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka struct in6_addr *addr = (struct in6_addr*)&neigh->primary_key; 368133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka struct net_device *dev = neigh->dev; 369133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka struct inet6_dev *in6_dev; 370133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka struct neigh_parms *parms; 371133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka int is_multicast = ipv6_addr_is_multicast(addr); 372e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg 373e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg rcu_read_lock(); 374e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg in6_dev = in6_dev_get(dev); 375e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg if (in6_dev == NULL) { 376133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka rcu_read_unlock(); 377133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka return -EINVAL; 378133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka } 379133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka 380133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka parms = in6_dev->nd_parms; 381f3b85252f081581a8f257545ed748062dce7798bJohannes Berg __neigh_parms_put(neigh->parms); 3828a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear neigh->parms = neigh_parms_clone(parms); 3838a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear rcu_read_unlock(); 3848a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear 3858a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST; 386e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg if (!dev->header_ops) { 3878a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear neigh->nud_state = NUD_NOARP; 3886c17b77b67587b9f9e3070fb89fe98cef3187131Seth Forshee neigh->ops = &ndisc_direct_ops; 3896c17b77b67587b9f9e3070fb89fe98cef3187131Seth Forshee neigh->output = neigh->ops->queue_xmit; 3906c17b77b67587b9f9e3070fb89fe98cef3187131Seth Forshee } else { 3916c17b77b67587b9f9e3070fb89fe98cef3187131Seth Forshee if (is_multicast) { 3926c17b77b67587b9f9e3070fb89fe98cef3187131Seth Forshee neigh->nud_state = NUD_NOARP; 3938a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear ndisc_mc_map(addr, neigh->ha, dev, 1); 394e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg } else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) { 395316b6b5df77db801d62ec381cfae0c38ff84252cPeter Senna Tschudin neigh->nud_state = NUD_NOARP; 396e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg memcpy(neigh->ha, dev->dev_addr, dev->addr_len); 3978a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear if (dev->flags&IFF_LOOPBACK) 3988a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear neigh->type = RTN_LOCAL; 3998a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear } else if (dev->flags&IFF_POINTOPOINT) { 4008a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear neigh->nud_state = NUD_NOARP; 4018a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear memcpy(neigh->ha, dev->broadcast, dev->addr_len); 4028a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear } 4038a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear if (dev->header_ops->cache) 4046c17b77b67587b9f9e3070fb89fe98cef3187131Seth Forshee neigh->ops = &ndisc_hh_ops; 4058a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear else 4068a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear neigh->ops = &ndisc_generic_ops; 4078a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear if (neigh->nud_state&NUD_VALID) 4088a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear neigh->output = neigh->ops->connected_output; 4098a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear else 4108a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear neigh->output = neigh->ops->output; 4118a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear } 4128a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear in6_dev_put(in6_dev); 4138a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear return 0; 414f3b85252f081581a8f257545ed748062dce7798bJohannes Berg} 415f3b85252f081581a8f257545ed748062dce7798bJohannes Berg 416f3b85252f081581a8f257545ed748062dce7798bJohannes Bergstatic int pndisc_constructor(struct pneigh_entry *n) 417f3b85252f081581a8f257545ed748062dce7798bJohannes Berg{ 418f3b85252f081581a8f257545ed748062dce7798bJohannes Berg struct in6_addr *addr = (struct in6_addr*)&n->key; 419f3b85252f081581a8f257545ed748062dce7798bJohannes Berg struct in6_addr maddr; 420e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka struct net_device *dev = n->dev; 421e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka 422f3b85252f081581a8f257545ed748062dce7798bJohannes Berg if (dev == NULL || __in6_dev_get(dev) == NULL) 423f3b85252f081581a8f257545ed748062dce7798bJohannes Berg return -EINVAL; 424f3b85252f081581a8f257545ed748062dce7798bJohannes Berg addrconf_addr_solict_mult(addr, &maddr); 425133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka ipv6_dev_mc_inc(dev, &maddr); 4266e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville return 0; 427c0ce77b8323c1a0d4eeef97caf16c0ea971222a9Johannes Berg} 428e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg 429c0ce77b8323c1a0d4eeef97caf16c0ea971222a9Johannes Bergstatic void pndisc_destructor(struct pneigh_entry *n) 430c0ce77b8323c1a0d4eeef97caf16c0ea971222a9Johannes Berg{ 431c0ce77b8323c1a0d4eeef97caf16c0ea971222a9Johannes Berg struct in6_addr *addr = (struct in6_addr*)&n->key; 432f3b85252f081581a8f257545ed748062dce7798bJohannes Berg struct in6_addr maddr; 433f3b85252f081581a8f257545ed748062dce7798bJohannes Berg struct net_device *dev = n->dev; 434f3b85252f081581a8f257545ed748062dce7798bJohannes Berg 435c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg if (dev == NULL || __in6_dev_get(dev) == NULL) 436c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg return; 437c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg addrconf_addr_solict_mult(addr, &maddr); 4384d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg ipv6_dev_mc_dec(dev, &maddr); 4394d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg} 4404d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg 441c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg/* 4424d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg * Send a Neighbour Advertisement 443f3b85252f081581a8f257545ed748062dce7798bJohannes Berg */ 444f3b85252f081581a8f257545ed748062dce7798bJohannes Bergstatic void __ndisc_send(struct net_device *dev, 4454d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg struct neighbour *neigh, 4464d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg struct in6_addr *daddr, struct in6_addr *saddr, 4474d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg struct icmp6hdr *icmp6h, struct in6_addr *target, 4484d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg int llinfo) 4494d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg{ 4504d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg struct flowi fl; 451cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler struct dst_entry *dst; 4524d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg struct sock *sk = ndisc_socket->sk; 4534d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg struct sk_buff *skb; 4546e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville struct icmp6hdr *hdr; 4556e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville struct inet6_dev *idev; 4566e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville int len; 4576e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville int err; 4586e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville u8 *opt, type; 4596e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville 4606e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville type = icmp6h->icmp6_type; 4616e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville 462f3b85252f081581a8f257545ed748062dce7798bJohannes Berg icmpv6_flow_init(ndisc_socket->sk, &fl, type, 463f3b85252f081581a8f257545ed748062dce7798bJohannes Berg saddr, daddr, dev->ifindex); 464f3b85252f081581a8f257545ed748062dce7798bJohannes Berg 465e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg dst = icmp6_dst_alloc(dev, neigh, daddr); 466f3b85252f081581a8f257545ed748062dce7798bJohannes Berg if (!dst) 4678a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear return; 468fbe9c429f195111bbf7f1630efa19aee295fd8e7Helmut Schaa 4698a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear err = xfrm_lookup(&dst, &fl, NULL, 0); 47055de908ab292c03f1eb280f51170ddb9c6b57e31Johannes Berg if (err < 0) 4719b8648704358e42f9865cd6de7cedb5ac0db67e7Johannes Berg return; 4729b8648704358e42f9865cd6de7cedb5ac0db67e7Johannes Berg 4739b8648704358e42f9865cd6de7cedb5ac0db67e7Johannes Berg if (!dev->addr_len) 4748a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear llinfo = 0; 4758a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear 4768a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear len = sizeof(struct icmp6hdr) + (target ? sizeof(*target) : 0); 4778a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear if (llinfo) 4788a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear len += ndisc_opt_addr_space(dev); 4798a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear 4808a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear skb = sock_alloc_send_skb(sk, 4818a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear (MAX_HEADER + sizeof(struct ipv6hdr) + 4828a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear len + LL_RESERVED_SPACE(dev)), 4838a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear 1, &err); 4848a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear if (!skb) { 4858a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear ND_PRINTK0(KERN_ERR 4868a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear "ICMPv6 ND: %s() failed to allocate an skb.\n", 4878a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear __FUNCTION__); 4888a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear dst_release(dst); 4898a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear return; 4908a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear } 4918a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear 4928a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear skb_reserve(skb, LL_RESERVED_SPACE(dev)); 4938a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len); 4948a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear 4958a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear skb->transport_header = skb->tail; 4968a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear skb_put(skb, len); 4978a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear 4988a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear hdr = (struct icmp6hdr *)skb_transport_header(skb); 4998a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear memcpy(hdr, icmp6h, sizeof(*hdr)); 5008a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear 5018a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear opt = skb_transport_header(skb) + sizeof(struct icmp6hdr); 5028a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear if (target) { 5038a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear ipv6_addr_copy((struct in6_addr *)opt, target); 5048a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear opt += sizeof(*target); 505fbe9c429f195111bbf7f1630efa19aee295fd8e7Helmut Schaa } 5068a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear 5076e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville if (llinfo) 5085cff20e6c5a6591a79d3b027af222870f52bb550Johannes Berg ndisc_fill_addr_option(opt, llinfo, dev->dev_addr, 509f3b85252f081581a8f257545ed748062dce7798bJohannes Berg dev->addr_len, dev->type); 5104d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg 5114d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg hdr->icmp6_cksum = csum_ipv6_magic(saddr, daddr, len, 512a060bbfe4ee95d115e8f9705a66894ac34e2c475Johannes Berg IPPROTO_ICMPV6, 5134d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg csum_partial((__u8 *) hdr, 514f3b85252f081581a8f257545ed748062dce7798bJohannes Berg len, 0)); 515f3b85252f081581a8f257545ed748062dce7798bJohannes Berg 516f3b85252f081581a8f257545ed748062dce7798bJohannes Berg skb->dst = dst; 5174d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg 5184d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg idev = in6_dev_get(dst->dev); 519fbe9c429f195111bbf7f1630efa19aee295fd8e7Helmut Schaa IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); 520f3b85252f081581a8f257545ed748062dce7798bJohannes Berg 5215cff20e6c5a6591a79d3b027af222870f52bb550Johannes Berg err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, 5225cff20e6c5a6591a79d3b027af222870f52bb550Johannes Berg dst_output); 523f3b85252f081581a8f257545ed748062dce7798bJohannes Berg if (!err) { 524e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg ICMP6MSGOUT_INC_STATS(idev, type); 525f3b85252f081581a8f257545ed748062dce7798bJohannes Berg ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); 526f3b85252f081581a8f257545ed748062dce7798bJohannes Berg } 527f3b85252f081581a8f257545ed748062dce7798bJohannes Berg 528f3b85252f081581a8f257545ed748062dce7798bJohannes Berg if (likely(idev != NULL)) 529f3b85252f081581a8f257545ed748062dce7798bJohannes Berg in6_dev_put(idev); 530df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa} 531df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa 532df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaastatic void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, 533df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa struct in6_addr *daddr, struct in6_addr *solicited_addr, 534df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa int router, int solicited, int override, int inc_opt) 535df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa{ 536df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa struct in6_addr tmpaddr; 537df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa struct inet6_ifaddr *ifp; 538df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa struct in6_addr *src_addr; 539df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa struct icmp6hdr icmp6h = { 540df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT, 541df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa }; 542e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka 543e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka /* for anycast or proxy, solicited_addr != src_addr */ 5447d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa ifp = ipv6_get_ifaddr(&init_net, solicited_addr, dev, 1); 545142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa if (ifp) { 546df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa src_addr = solicited_addr; 547df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa if (ifp->flags & IFA_F_OPTIMISTIC) 548142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa override = 0; 549df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa in6_ifa_put(ifp); 550cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler } else { 551142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr)) 552df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa return; 553df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa src_addr = &tmpaddr; 554df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa } 555df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa 556df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa icmp6h.icmp6_router = router; 557142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa icmp6h.icmp6_solicited = solicited; 558142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa icmp6h.icmp6_override = override; 5599607e6b66a0d25ca63b70d54a4283fa13d8f7c9dJohannes Berg 560142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa __ndisc_send(dev, neigh, daddr, src_addr, 561142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa &icmp6h, solicited_addr, 562142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa inc_opt ? ND_OPT_TARGET_LL_ADDR : 0); 563142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa} 564142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa 565df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaavoid ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, 566df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa struct in6_addr *solicit, 567df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa struct in6_addr *daddr, struct in6_addr *saddr) 568df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa{ 569df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa struct in6_addr addr_buf; 570142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa struct icmp6hdr icmp6h = { 571142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa .icmp6_type = NDISC_NEIGHBOUR_SOLICITATION, 572142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa }; 573142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa 574142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa if (saddr == NULL) { 575b23b025fe246f3acc2988eb6d400df34c27cb8aeBen Greear if (ipv6_get_lladdr(dev, &addr_buf, 576b23b025fe246f3acc2988eb6d400df34c27cb8aeBen Greear (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC))) 577a80f7c0b088187c8471b441d461e937991870661Johannes Berg return; 57807ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg saddr = &addr_buf; 57907ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg } 58007ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg 58107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg __ndisc_send(dev, neigh, daddr, saddr, 5823f892b61a8cf6a85bc389c8d13209d686a4f6403Stanislaw Gruszka &icmp6h, solicit, 583a80f7c0b088187c8471b441d461e937991870661Johannes Berg !ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0); 584a80f7c0b088187c8471b441d461e937991870661Johannes Berg} 58507ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg 5863f892b61a8cf6a85bc389c8d13209d686a4f6403Stanislaw Gruszkavoid ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, 5873f892b61a8cf6a85bc389c8d13209d686a4f6403Stanislaw Gruszka struct in6_addr *daddr) 588142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa{ 589cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler struct icmp6hdr icmp6h = { 590cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler .icmp6_type = NDISC_ROUTER_SOLICITATION, 591cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler }; 592cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler int send_sllao = dev->addr_len; 593cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler 5943f892b61a8cf6a85bc389c8d13209d686a4f6403Stanislaw Gruszka#ifdef CONFIG_IPV6_OPTIMISTIC_DAD 595cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler /* 596cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler * According to section 2.2 of RFC 4429, we must not 597cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler * send router solicitations with a sllao from 598cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler * optimistic addresses, but we may send the solicitation 599cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler * if we don't include the sllao. So here we check 600cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler * if our address is optimistic, and if so, we 601142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa * suppress the inclusion of the sllao. 60207ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg */ 603142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa if (send_sllao) { 604142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa struct inet6_ifaddr *ifp = ipv6_get_ifaddr(&init_net, saddr, 6052fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa dev, 1); 6062fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa if (ifp) { 6072fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa if (ifp->flags & IFA_F_OPTIMISTIC) { 6082fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa send_sllao = 0; 6092fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa } 6102fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa in6_ifa_put(ifp); 6117d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa } else { 6127d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa send_sllao = 0; 6137d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa } 614584991dccfd347cd2e1675ab262998f6c335d3c0Johannes Berg } 615b23b025fe246f3acc2988eb6d400df34c27cb8aeBen Greear#endif 61607ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg __ndisc_send(dev, NULL, daddr, saddr, 61707ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg &icmp6h, NULL, 6187d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa send_sllao ? ND_OPT_SOURCE_LL_ADDR : 0); 6197d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa} 6207d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa 6217d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa 6220ee9c13c7c92581ab005d80795cf65897213b249Helmut Schaastatic void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb) 6230ee9c13c7c92581ab005d80795cf65897213b249Helmut Schaa{ 6240ee9c13c7c92581ab005d80795cf65897213b249Helmut Schaa /* 6252fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa * "The sender MUST return an ICMP 6260ee9c13c7c92581ab005d80795cf65897213b249Helmut Schaa * destination unreachable" 6277d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa */ 6287d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa dst_link_failure(skb); 6297d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa kfree_skb(skb); 6307d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa} 6317d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa 6327d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa/* Called with locked neigh: either read or both */ 6337d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa 6347d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaastatic void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) 6357d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa{ 6367d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa struct in6_addr *saddr = NULL; 6377d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa struct in6_addr mcaddr; 6387d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa struct net_device *dev = neigh->dev; 6397d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa struct in6_addr *target = (struct in6_addr *)&neigh->primary_key; 6407d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa int probes = atomic_read(&neigh->probes); 641977923b00c79185c11b4b47664f5ffa4c3820438Helmut Schaa 6422fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa if (skb && ipv6_chk_addr(&init_net, &ipv6_hdr(skb)->saddr, dev, 1)) 6437d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa saddr = &ipv6_hdr(skb)->saddr; 6447d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa 6452fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa if ((probes -= neigh->parms->ucast_probes) < 0) { 6467d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa if (!(neigh->nud_state & NUD_VALID)) { 647977923b00c79185c11b4b47664f5ffa4c3820438Helmut Schaa ND_PRINTK1(KERN_DEBUG 6487d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa "%s(): trying to ucast probe in NUD_INVALID: " 6497d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa NIP6_FMT "\n", 65007ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg __FUNCTION__, 65107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg NIP6(*target)); 65207ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg } 65307ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg ndisc_send_ns(dev, neigh, target, target, saddr); 65407ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg } else if ((probes -= neigh->parms->app_probes) < 0) { 65507ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg#ifdef CONFIG_ARPD 65607ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg neigh_app_ns(neigh); 657aacde9ee45225f7e0b90960f479aef83c66bfdc0Stanislaw Gruszka#endif 658aacde9ee45225f7e0b90960f479aef83c66bfdc0Stanislaw Gruszka } else { 65907ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg addrconf_addr_solict_mult(target, &mcaddr); 66007ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg ndisc_send_ns(dev, NULL, target, &mcaddr, saddr); 66107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg } 66207ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg} 66307ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg 66407ef03ee8b280a536b38ccfe512b9556996f0492Johannes Bergstatic void ndisc_recv_ns(struct sk_buff *skb) 66507ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg{ 66607ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); 66707ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; 668aacde9ee45225f7e0b90960f479aef83c66bfdc0Stanislaw Gruszka struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; 66907ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg u8 *lladdr = NULL; 67007ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg u32 ndoptlen = skb->tail - (skb->transport_header + 67107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg offsetof(struct nd_msg, opt)); 67207ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg struct ndisc_options ndopts; 67307ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg struct net_device *dev = skb->dev; 67407ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg struct inet6_ifaddr *ifp; 67507ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg struct inet6_dev *idev = NULL; 67607ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg struct neighbour *neigh; 67707ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg struct pneigh_entry *pneigh = NULL; 67807ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg int dad = ipv6_addr_any(saddr); 67907ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg int inc; 680de2ee84db6a0201278e35590821cd014cb71830aMohammed Shafi Shajakhan int is_router; 68107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg 68207ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg if (ipv6_addr_is_multicast(&msg->target)) { 683c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg ND_PRINTK2(KERN_WARNING 6840a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg "ICMPv6 NS: multicast target address"); 6850a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return; 6860a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 687d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg 6880a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* 689d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg * RFC2461 7.1.1: 6900a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * DAD has to be destined for solicited node multicast address. 691259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka */ 6928789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg if (dad && 693e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg !(daddr->s6_addr32[0] == htonl(0xff020000) && 694e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg daddr->s6_addr32[1] == htonl(0x00000000) && 695d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg daddr->s6_addr32[2] == htonl(0x00000001) && 6968a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear daddr->s6_addr [12] == 0xff )) { 6978a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear ND_PRINTK2(KERN_WARNING 6988a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear "ICMPv6 NS: bad DAD packet (wrong destination)\n"); 6998a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear return; 7008a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear } 7018a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear 702259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) { 7038789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg ND_PRINTK2(KERN_WARNING 704259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka "ICMPv6 NS: invalid ND options\n"); 7058789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg return; 7068789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg } 707259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka 708259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka if (ndopts.nd_opts_src_lladdr) { 709f3b85252f081581a8f257545ed748062dce7798bJohannes Berg lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, dev); 710fbe9c429f195111bbf7f1630efa19aee295fd8e7Helmut Schaa if (!lladdr) { 711f3b85252f081581a8f257545ed748062dce7798bJohannes Berg ND_PRINTK2(KERN_WARNING 712f3b85252f081581a8f257545ed748062dce7798bJohannes Berg "ICMPv6 NS: invalid link-layer address length\n"); 713f3b85252f081581a8f257545ed748062dce7798bJohannes Berg return; 714f3b85252f081581a8f257545ed748062dce7798bJohannes Berg } 715e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg 716f3b85252f081581a8f257545ed748062dce7798bJohannes Berg /* RFC2461 7.1.1: 717f3b85252f081581a8f257545ed748062dce7798bJohannes Berg * If the IP source address is the unspecified address, 718259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka * there MUST NOT be source link-layer address option 7193aed49ef17c7bc8397420529ac976fe058818e3dStanislaw Gruszka * in the message. 7203aed49ef17c7bc8397420529ac976fe058818e3dStanislaw Gruszka */ 721259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka if (dad) { 722259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka ND_PRINTK2(KERN_WARNING 723259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka "ICMPv6 NS: bad DAD packet (link-layer address option)\n"); 724259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka return; 725f3b85252f081581a8f257545ed748062dce7798bJohannes Berg } 726f3b85252f081581a8f257545ed748062dce7798bJohannes Berg } 7275bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg 7285bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg inc = ipv6_addr_is_multicast(daddr); 7295bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg 7309607e6b66a0d25ca63b70d54a4283fa13d8f7c9dJohannes Berg if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1)) != NULL) { 731259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka 732259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) { 733f3b85252f081581a8f257545ed748062dce7798bJohannes Berg if (dad) { 7340a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (dev->type == ARPHRD_IEEE802_TR) { 735f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa const unsigned char *sadr; 736f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa sadr = skb_mac_header(skb); 737f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa if (((sadr[8] ^ dev->dev_addr[0]) & 0x7f) == 0 && 738f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa sadr[9] == dev->dev_addr[1] && 739f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa sadr[10] == dev->dev_addr[2] && 740c29acf201007a6d73223f864f52406eb5ba19933Rajkumar Manoharan sadr[11] == dev->dev_addr[3] && 741c29acf201007a6d73223f864f52406eb5ba19933Rajkumar Manoharan sadr[12] == dev->dev_addr[4] && 742c29acf201007a6d73223f864f52406eb5ba19933Rajkumar Manoharan sadr[13] == dev->dev_addr[5]) { 743c29acf201007a6d73223f864f52406eb5ba19933Rajkumar Manoharan /* looped-back to us */ 744c29acf201007a6d73223f864f52406eb5ba19933Rajkumar Manoharan goto out; 745977923b00c79185c11b4b47664f5ffa4c3820438Helmut Schaa } 7462fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa } 747e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka 748e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka /* 749e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka * We are colliding with another node 750e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka * who is doing DAD 751e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka * so fail our DAD process 752e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka */ 753f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa addrconf_dad_failure(ifp); 7542fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa return; 7552fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa } else { 7562fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa /* 757f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa * This is not a dad solicitation. 758f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa * If we are an optimistic node, 759f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa * we should respond. 76007ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg * Otherwise, we should ignore it. 76107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg */ 762142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa if (!(ifp->flags & IFA_F_OPTIMISTIC)) 76307ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg goto out; 76407ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg } 765142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa } 766cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler 767cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler idev = ifp->idev; 768cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler } else { 769f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa idev = in6_dev_get(dev); 770f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa if (!idev) { 7710a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* XXX: count this drop? */ 77242935ecaf4e784d0815afa9a7e5fe7e141157ca3Luis R. Rodriguez return; 773d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg } 774259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka 775259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka if (ipv6_chk_acast_addr(dev, &msg->target) || 776e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka (idev->cnf.forwarding && 777d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && 778259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka (pneigh = pneigh_lookup(&nd_tbl, &init_net, 779259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka &msg->target, dev, 0)) != NULL)) { 7800a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && 7810a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg skb->pkt_type != PACKET_HOST && 782f3b85252f081581a8f257545ed748062dce7798bJohannes Berg inc != 0 && 783f3b85252f081581a8f257545ed748062dce7798bJohannes Berg idev->nd_parms->proxy_delay != 0) { 7840a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* 785f3b85252f081581a8f257545ed748062dce7798bJohannes Berg * for anycast or proxy, 786de95a54b1aebe5592cae971ca5e5d9ec6a381a17Johannes Berg * sender should delay its response 787a1699b75a1db31a1da2f0fc610ee696d02a19280Johannes Berg * by a random time between 0 and 788f3b85252f081581a8f257545ed748062dce7798bJohannes Berg * MAX_ANYCAST_DELAY_TIME seconds. 789a1699b75a1db31a1da2f0fc610ee696d02a19280Johannes Berg * (RFC2461) -- yoshfuji 7900a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg */ 791f3b85252f081581a8f257545ed748062dce7798bJohannes Berg struct sk_buff *n = skb_clone(skb, GFP_ATOMIC); 7920a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (n) 7930a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg pneigh_enqueue(&nd_tbl, idev->nd_parms, n); 79434bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka goto out; 79534bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka } 79634bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka } else 7970a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg goto out; 7980a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 799f3b85252f081581a8f257545ed748062dce7798bJohannes Berg 800fb63bc41772259701a827e9a6117219a7393554fGertjan van Wingerde is_router = !!(pneigh ? pneigh->flags & NTF_ROUTER : idev->cnf.forwarding); 8012a5193119269062608582418deba7af82844159aJohannes Berg 802a1699b75a1db31a1da2f0fc610ee696d02a19280Johannes Berg if (dad) { 8030a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct in6_addr maddr; 804f3b85252f081581a8f257545ed748062dce7798bJohannes Berg 805f3b85252f081581a8f257545ed748062dce7798bJohannes Berg ipv6_addr_all_nodes(&maddr); 806f3b85252f081581a8f257545ed748062dce7798bJohannes Berg ndisc_send_na(dev, NULL, &maddr, &msg->target, 8079116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg is_router, 0, (ifp != NULL), 1); 808be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg goto out; 809be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg } 81034bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka 81134bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka if (inc) 812be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_mcast); 813be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg else 814be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_ucast); 815be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg 81634bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka /* 81734bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka * update / create cache entry 81834bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka * for the source address 81934bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka */ 820be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg neigh = __neigh_lookup(&nd_tbl, saddr, dev, 82134bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka !inc || lladdr || !dev->addr_len); 82234bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka if (neigh) 82334bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka neigh_update(neigh, lladdr, NUD_STALE, 82434bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka NEIGH_UPDATE_F_WEAK_OVERRIDE| 82534bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka NEIGH_UPDATE_F_OVERRIDE); 82634bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka if (neigh || !dev->header_ops) { 82734bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka ndisc_send_na(dev, neigh, saddr, &msg->target, 828be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg is_router, 829be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg 1, (ifp != NULL && inc), inc); 830be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg if (neigh) 83134bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka neigh_release(neigh); 83234bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka } 83334bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka 83434bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszkaout: 835be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg if (ifp) 83634bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka in6_ifa_put(ifp); 83734bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka else 83834bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka in6_dev_put(idev); 83934bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka 840be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg return; 841be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg} 842be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg 843be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Bergstatic void ndisc_recv_na(struct sk_buff *skb) 844be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg{ 845be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); 8465ba63533bbf653631faab60f6988506160ec6ba4Johannes Berg struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; 8475ba63533bbf653631faab60f6988506160ec6ba4Johannes Berg struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; 8489116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg u8 *lladdr = NULL; 8495ba63533bbf653631faab60f6988506160ec6ba4Johannes Berg u32 ndoptlen = skb->tail - (skb->transport_header + 850f3b85252f081581a8f257545ed748062dce7798bJohannes Berg offsetof(struct nd_msg, opt)); 851a1699b75a1db31a1da2f0fc610ee696d02a19280Johannes Berg struct ndisc_options ndopts; 852f3b85252f081581a8f257545ed748062dce7798bJohannes Berg struct net_device *dev = skb->dev; 8530a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct inet6_ifaddr *ifp; 8545bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg struct neighbour *neigh; 8554136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka 8564136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka if (skb->len < sizeof(struct nd_msg)) { 8574136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka ND_PRINTK2(KERN_WARNING 8585bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg "ICMPv6 NA: packet too short\n"); 8595bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg return; 8605bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg } 861b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller 8624136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka if (ipv6_addr_is_multicast(&msg->target)) { 8634136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka ND_PRINTK2(KERN_WARNING 8644136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka "ICMPv6 NA: target address is multicast.\n"); 8654136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka return; 8664136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka } 8674136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka 8684136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka if (ipv6_addr_is_multicast(daddr) && 8694136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka msg->icmph.icmp6_solicited) { 8704136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka ND_PRINTK2(KERN_WARNING 8714136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka "ICMPv6 NA: solicited NA is multicasted.\n"); 8724136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka return; 873b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller } 874b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller 875b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) { 8765bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg ND_PRINTK2(KERN_WARNING 8774136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka "ICMPv6 NS: invalid ND option\n"); 878a1699b75a1db31a1da2f0fc610ee696d02a19280Johannes Berg return; 879b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller } 880b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller if (ndopts.nd_opts_tgt_lladdr) { 881b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, dev); 882b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller if (!lladdr) { 883b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller ND_PRINTK2(KERN_WARNING 884e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg "ICMPv6 NA: invalid link-layer address length\n"); 885e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg return; 886e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg } 887b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller } 8884136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1))) { 889b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller if (ifp->flags & IFA_F_TENTATIVE) { 890b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller addrconf_dad_failure(ifp); 891b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller return; 892b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller } 893b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller /* What should we make now? The advertisement 894b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller is invalid, but ndisc specs say nothing 895b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller about it. It could be misconfiguration, or 896b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller an smart proxy agent tries to help us :-) 897b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller */ 898b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller ND_PRINTK1(KERN_WARNING 899d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg "ICMPv6 NA: someone advertises our address on %s!\n", 9005bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg ifp->idev->dev->name); 90179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho in6_ifa_put(ifp); 90279f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho return; 90379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho } 90479f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho neigh = neigh_lookup(&nd_tbl, &msg->target, dev); 90579f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho 906bca1e29fb54c51856dda6772d488d41b10ed91daDavid Spinadel if (neigh) { 907c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg u8 old_flags = neigh->flags; 908c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg 909c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg if (neigh->nud_state & NUD_FAILED) 910c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg goto out; 91179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho 9125260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg /* 91379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho * Don't update the neighbor cache entry on a proxy NA from 9145260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg * ourselves because either the proxied node is off link or it 91579f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho * has already sent a NA to us. 91679f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho */ 91779f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) && 91879f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp && 91979f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho pneigh_lookup(&nd_tbl, &init_net, &msg->target, dev, 0)) { 92079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho /* XXX: idev->cnf.prixy_ndp */ 92179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho goto out; 92279f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho } 92379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho 92479f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho neigh_update(neigh, lladdr, 925d811b3d5566f1441b321a1219c260124b209e0bdArik Nemtsov msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE, 926d811b3d5566f1441b321a1219c260124b209e0bdArik Nemtsov NEIGH_UPDATE_F_WEAK_OVERRIDE| 927d811b3d5566f1441b321a1219c260124b209e0bdArik Nemtsov (msg->icmph.icmp6_override ? NEIGH_UPDATE_F_OVERRIDE : 0)| 928c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg NEIGH_UPDATE_F_OVERRIDE_ISROUTER| 92930dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg (msg->icmph.icmp6_router ? NEIGH_UPDATE_F_ISROUTER : 0)); 93079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho 93179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho if ((old_flags & ~neigh->flags) & NTF_ROUTER) { 93279f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho /* 93379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho * Change: router to host 93430dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg */ 93530dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg struct rt6_info *rt; 936c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg rt = rt6_get_dflt_router(saddr, dev); 937c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg if (rt) 93879f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho ip6_del_rt(rt); 93979f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho } 94030dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg 94130dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Bergout: 9425260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg neigh_release(neigh); 94379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho } 94479f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho} 94579f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho 94630dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Bergstatic void ndisc_recv_rs(struct sk_buff *skb) 94779f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho{ 9485260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg struct rs_msg *rs_msg = (struct rs_msg *)skb_transport_header(skb); 94979f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho unsigned long ndoptlen = skb->len - sizeof(*rs_msg); 95079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho struct neighbour *neigh; 95179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho struct inet6_dev *idev; 95285a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; 95379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho struct ndisc_options ndopts; 95479f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho u8 *lladdr = NULL; 95530dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg 95679f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho if (skb->len < sizeof(*rs_msg)) 9575260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg return; 95879f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho 95979f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho idev = in6_dev_get(skb->dev); 96079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho if (!idev) { 96179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho if (net_ratelimit()) 96279f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho ND_PRINTK1("ICMP6 RS: can't find in6 device\n"); 96379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho return; 96430dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg } 96585a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho 96630dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg /* Don't accept RS if we're not in router mode */ 96779f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho if (!idev->cnf.forwarding) 9685260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg goto out; 96979f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho 97079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho /* 97179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho * Don't update NCE if src = ::; 97279f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho * this implies that the source node has no ip address assigned yet. 97379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho */ 97479f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho if (ipv6_addr_any(saddr)) 97579f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho goto out; 97679f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho 97779f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho /* Parse ND options */ 97879f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho if (!ndisc_parse_options(rs_msg->opt, ndoptlen, &ndopts)) { 97979f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho if (net_ratelimit()) 98079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho ND_PRINTK2("ICMP6 NS: invalid ND option, ignored\n"); 98179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho goto out; 98279f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho } 98385a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho 98485a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho if (ndopts.nd_opts_src_lladdr) { 98585a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, 98685a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho skb->dev); 98785a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho if (!lladdr) 98885a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho goto out; 98985a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho } 99085a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho 9915260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev, 1); 99285a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho if (neigh) { 99385a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho neigh_update(neigh, lladdr, NUD_STALE, 99485a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho NEIGH_UPDATE_F_WEAK_OVERRIDE| 99585a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho NEIGH_UPDATE_F_OVERRIDE| 9965260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg NEIGH_UPDATE_F_OVERRIDE_ISROUTER); 99785a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho neigh_release(neigh); 99885a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho } 99985a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelhoout: 100085a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho in6_dev_put(idev); 100185a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho} 100285a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho 100379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelhostatic void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) 100479f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho{ 100579f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho struct icmp6hdr *icmp6h = (struct icmp6hdr *)skb_transport_header(ra); 100679f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho struct sk_buff *skb; 100779f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho struct nlmsghdr *nlh; 100879f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho struct nduseroptmsg *ndmsg; 100985a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho int err; 101079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg) 101179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho + (opt->nd_opt_len << 3)); 1012 size_t msg_size = base_size + nla_total_size(sizeof(struct in6_addr)); 1013 1014 skb = nlmsg_new(msg_size, GFP_ATOMIC); 1015 if (skb == NULL) { 1016 err = -ENOBUFS; 1017 goto errout; 1018 } 1019 1020 nlh = nlmsg_put(skb, 0, 0, RTM_NEWNDUSEROPT, base_size, 0); 1021 if (nlh == NULL) { 1022 goto nla_put_failure; 1023 } 1024 1025 ndmsg = nlmsg_data(nlh); 1026 ndmsg->nduseropt_family = AF_INET6; 1027 ndmsg->nduseropt_ifindex = ra->dev->ifindex; 1028 ndmsg->nduseropt_icmp_type = icmp6h->icmp6_type; 1029 ndmsg->nduseropt_icmp_code = icmp6h->icmp6_code; 1030 ndmsg->nduseropt_opts_len = opt->nd_opt_len << 3; 1031 1032 memcpy(ndmsg + 1, opt, opt->nd_opt_len << 3); 1033 1034 NLA_PUT(skb, NDUSEROPT_SRCADDR, sizeof(struct in6_addr), 1035 &ipv6_hdr(ra)->saddr); 1036 nlmsg_end(skb, nlh); 1037 1038 err = rtnl_notify(skb, &init_net, 0, RTNLGRP_ND_USEROPT, NULL, 1039 GFP_ATOMIC); 1040 if (err < 0) 1041 goto errout; 1042 1043 return; 1044 1045nla_put_failure: 1046 nlmsg_free(skb); 1047 err = -EMSGSIZE; 1048errout: 1049 rtnl_set_sk_err(&init_net, RTNLGRP_ND_USEROPT, err); 1050} 1051 1052static void ndisc_router_discovery(struct sk_buff *skb) 1053{ 1054 struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb); 1055 struct neighbour *neigh = NULL; 1056 struct inet6_dev *in6_dev; 1057 struct rt6_info *rt = NULL; 1058 int lifetime; 1059 struct ndisc_options ndopts; 1060 int optlen; 1061 unsigned int pref = 0; 1062 1063 __u8 * opt = (__u8 *)(ra_msg + 1); 1064 1065 optlen = (skb->tail - skb->transport_header) - sizeof(struct ra_msg); 1066 1067 if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { 1068 ND_PRINTK2(KERN_WARNING 1069 "ICMPv6 RA: source address is not link-local.\n"); 1070 return; 1071 } 1072 if (optlen < 0) { 1073 ND_PRINTK2(KERN_WARNING 1074 "ICMPv6 RA: packet too short\n"); 1075 return; 1076 } 1077 1078 /* 1079 * set the RA_RECV flag in the interface 1080 */ 1081 1082 in6_dev = in6_dev_get(skb->dev); 1083 if (in6_dev == NULL) { 1084 ND_PRINTK0(KERN_ERR 1085 "ICMPv6 RA: can't find inet6 device for %s.\n", 1086 skb->dev->name); 1087 return; 1088 } 1089 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) { 1090 in6_dev_put(in6_dev); 1091 return; 1092 } 1093 1094 if (!ndisc_parse_options(opt, optlen, &ndopts)) { 1095 in6_dev_put(in6_dev); 1096 ND_PRINTK2(KERN_WARNING 1097 "ICMP6 RA: invalid ND options\n"); 1098 return; 1099 } 1100 1101 if (in6_dev->if_flags & IF_RS_SENT) { 1102 /* 1103 * flag that an RA was received after an RS was sent 1104 * out on this interface. 1105 */ 1106 in6_dev->if_flags |= IF_RA_RCVD; 1107 } 1108 1109 /* 1110 * Remember the managed/otherconf flags from most recently 1111 * received RA message (RFC 2462) -- yoshfuji 1112 */ 1113 in6_dev->if_flags = (in6_dev->if_flags & ~(IF_RA_MANAGED | 1114 IF_RA_OTHERCONF)) | 1115 (ra_msg->icmph.icmp6_addrconf_managed ? 1116 IF_RA_MANAGED : 0) | 1117 (ra_msg->icmph.icmp6_addrconf_other ? 1118 IF_RA_OTHERCONF : 0); 1119 1120 if (!in6_dev->cnf.accept_ra_defrtr) 1121 goto skip_defrtr; 1122 1123 lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); 1124 1125#ifdef CONFIG_IPV6_ROUTER_PREF 1126 pref = ra_msg->icmph.icmp6_router_pref; 1127 /* 10b is handled as if it were 00b (medium) */ 1128 if (pref == ICMPV6_ROUTER_PREF_INVALID || 1129 !in6_dev->cnf.accept_ra_rtr_pref) 1130 pref = ICMPV6_ROUTER_PREF_MEDIUM; 1131#endif 1132 1133 rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev); 1134 1135 if (rt) 1136 neigh = rt->rt6i_nexthop; 1137 1138 if (rt && lifetime == 0) { 1139 neigh_clone(neigh); 1140 ip6_del_rt(rt); 1141 rt = NULL; 1142 } 1143 1144 if (rt == NULL && lifetime) { 1145 ND_PRINTK3(KERN_DEBUG 1146 "ICMPv6 RA: adding default router.\n"); 1147 1148 rt = rt6_add_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev, pref); 1149 if (rt == NULL) { 1150 ND_PRINTK0(KERN_ERR 1151 "ICMPv6 RA: %s() failed to add default route.\n", 1152 __FUNCTION__); 1153 in6_dev_put(in6_dev); 1154 return; 1155 } 1156 1157 neigh = rt->rt6i_nexthop; 1158 if (neigh == NULL) { 1159 ND_PRINTK0(KERN_ERR 1160 "ICMPv6 RA: %s() got default router without neighbour.\n", 1161 __FUNCTION__); 1162 dst_release(&rt->u.dst); 1163 in6_dev_put(in6_dev); 1164 return; 1165 } 1166 neigh->flags |= NTF_ROUTER; 1167 } else if (rt) { 1168 rt->rt6i_flags |= (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); 1169 } 1170 1171 if (rt) 1172 rt->rt6i_expires = jiffies + (HZ * lifetime); 1173 1174 if (ra_msg->icmph.icmp6_hop_limit) { 1175 in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; 1176 if (rt) 1177 rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit; 1178 } 1179 1180skip_defrtr: 1181 1182 /* 1183 * Update Reachable Time and Retrans Timer 1184 */ 1185 1186 if (in6_dev->nd_parms) { 1187 unsigned long rtime = ntohl(ra_msg->retrans_timer); 1188 1189 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) { 1190 rtime = (rtime*HZ)/1000; 1191 if (rtime < HZ/10) 1192 rtime = HZ/10; 1193 in6_dev->nd_parms->retrans_time = rtime; 1194 in6_dev->tstamp = jiffies; 1195 inet6_ifinfo_notify(RTM_NEWLINK, in6_dev); 1196 } 1197 1198 rtime = ntohl(ra_msg->reachable_time); 1199 if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/(3*HZ)) { 1200 rtime = (rtime*HZ)/1000; 1201 1202 if (rtime < HZ/10) 1203 rtime = HZ/10; 1204 1205 if (rtime != in6_dev->nd_parms->base_reachable_time) { 1206 in6_dev->nd_parms->base_reachable_time = rtime; 1207 in6_dev->nd_parms->gc_staletime = 3 * rtime; 1208 in6_dev->nd_parms->reachable_time = neigh_rand_reach_time(rtime); 1209 in6_dev->tstamp = jiffies; 1210 inet6_ifinfo_notify(RTM_NEWLINK, in6_dev); 1211 } 1212 } 1213 } 1214 1215 /* 1216 * Process options. 1217 */ 1218 1219 if (!neigh) 1220 neigh = __neigh_lookup(&nd_tbl, &ipv6_hdr(skb)->saddr, 1221 skb->dev, 1); 1222 if (neigh) { 1223 u8 *lladdr = NULL; 1224 if (ndopts.nd_opts_src_lladdr) { 1225 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, 1226 skb->dev); 1227 if (!lladdr) { 1228 ND_PRINTK2(KERN_WARNING 1229 "ICMPv6 RA: invalid link-layer address length\n"); 1230 goto out; 1231 } 1232 } 1233 neigh_update(neigh, lladdr, NUD_STALE, 1234 NEIGH_UPDATE_F_WEAK_OVERRIDE| 1235 NEIGH_UPDATE_F_OVERRIDE| 1236 NEIGH_UPDATE_F_OVERRIDE_ISROUTER| 1237 NEIGH_UPDATE_F_ISROUTER); 1238 } 1239 1240#ifdef CONFIG_IPV6_ROUTE_INFO 1241 if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) { 1242 struct nd_opt_hdr *p; 1243 for (p = ndopts.nd_opts_ri; 1244 p; 1245 p = ndisc_next_option(p, ndopts.nd_opts_ri_end)) { 1246 if (((struct route_info *)p)->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen) 1247 continue; 1248 rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3, 1249 &ipv6_hdr(skb)->saddr); 1250 } 1251 } 1252#endif 1253 1254 if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) { 1255 struct nd_opt_hdr *p; 1256 for (p = ndopts.nd_opts_pi; 1257 p; 1258 p = ndisc_next_option(p, ndopts.nd_opts_pi_end)) { 1259 addrconf_prefix_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3); 1260 } 1261 } 1262 1263 if (ndopts.nd_opts_mtu) { 1264 __be32 n; 1265 u32 mtu; 1266 1267 memcpy(&n, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu)); 1268 mtu = ntohl(n); 1269 1270 if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) { 1271 ND_PRINTK2(KERN_WARNING 1272 "ICMPv6 RA: invalid mtu: %d\n", 1273 mtu); 1274 } else if (in6_dev->cnf.mtu6 != mtu) { 1275 in6_dev->cnf.mtu6 = mtu; 1276 1277 if (rt) 1278 rt->u.dst.metrics[RTAX_MTU-1] = mtu; 1279 1280 rt6_mtu_change(skb->dev, mtu); 1281 } 1282 } 1283 1284 if (ndopts.nd_useropts) { 1285 struct nd_opt_hdr *p; 1286 for (p = ndopts.nd_useropts; 1287 p; 1288 p = ndisc_next_useropt(p, ndopts.nd_useropts_end)) { 1289 ndisc_ra_useropt(skb, p); 1290 } 1291 } 1292 1293 if (ndopts.nd_opts_tgt_lladdr || ndopts.nd_opts_rh) { 1294 ND_PRINTK2(KERN_WARNING 1295 "ICMPv6 RA: invalid RA options"); 1296 } 1297out: 1298 if (rt) 1299 dst_release(&rt->u.dst); 1300 else if (neigh) 1301 neigh_release(neigh); 1302 in6_dev_put(in6_dev); 1303} 1304 1305static void ndisc_redirect_rcv(struct sk_buff *skb) 1306{ 1307 struct inet6_dev *in6_dev; 1308 struct icmp6hdr *icmph; 1309 struct in6_addr *dest; 1310 struct in6_addr *target; /* new first hop to destination */ 1311 struct neighbour *neigh; 1312 int on_link = 0; 1313 struct ndisc_options ndopts; 1314 int optlen; 1315 u8 *lladdr = NULL; 1316 1317 if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { 1318 ND_PRINTK2(KERN_WARNING 1319 "ICMPv6 Redirect: source address is not link-local.\n"); 1320 return; 1321 } 1322 1323 optlen = skb->tail - skb->transport_header; 1324 optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); 1325 1326 if (optlen < 0) { 1327 ND_PRINTK2(KERN_WARNING 1328 "ICMPv6 Redirect: packet too short\n"); 1329 return; 1330 } 1331 1332 icmph = icmp6_hdr(skb); 1333 target = (struct in6_addr *) (icmph + 1); 1334 dest = target + 1; 1335 1336 if (ipv6_addr_is_multicast(dest)) { 1337 ND_PRINTK2(KERN_WARNING 1338 "ICMPv6 Redirect: destination address is multicast.\n"); 1339 return; 1340 } 1341 1342 if (ipv6_addr_equal(dest, target)) { 1343 on_link = 1; 1344 } else if (ipv6_addr_type(target) != 1345 (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) { 1346 ND_PRINTK2(KERN_WARNING 1347 "ICMPv6 Redirect: target address is not link-local unicast.\n"); 1348 return; 1349 } 1350 1351 in6_dev = in6_dev_get(skb->dev); 1352 if (!in6_dev) 1353 return; 1354 if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) { 1355 in6_dev_put(in6_dev); 1356 return; 1357 } 1358 1359 /* RFC2461 8.1: 1360 * The IP source address of the Redirect MUST be the same as the current 1361 * first-hop router for the specified ICMP Destination Address. 1362 */ 1363 1364 if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) { 1365 ND_PRINTK2(KERN_WARNING 1366 "ICMPv6 Redirect: invalid ND options\n"); 1367 in6_dev_put(in6_dev); 1368 return; 1369 } 1370 if (ndopts.nd_opts_tgt_lladdr) { 1371 lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, 1372 skb->dev); 1373 if (!lladdr) { 1374 ND_PRINTK2(KERN_WARNING 1375 "ICMPv6 Redirect: invalid link-layer address length\n"); 1376 in6_dev_put(in6_dev); 1377 return; 1378 } 1379 } 1380 1381 neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1); 1382 if (neigh) { 1383 rt6_redirect(dest, &ipv6_hdr(skb)->daddr, 1384 &ipv6_hdr(skb)->saddr, neigh, lladdr, 1385 on_link); 1386 neigh_release(neigh); 1387 } 1388 in6_dev_put(in6_dev); 1389} 1390 1391void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, 1392 struct in6_addr *target) 1393{ 1394 struct sock *sk = ndisc_socket->sk; 1395 int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); 1396 struct sk_buff *buff; 1397 struct icmp6hdr *icmph; 1398 struct in6_addr saddr_buf; 1399 struct in6_addr *addrp; 1400 struct net_device *dev; 1401 struct rt6_info *rt; 1402 struct dst_entry *dst; 1403 struct inet6_dev *idev; 1404 struct flowi fl; 1405 u8 *opt; 1406 int rd_len; 1407 int err; 1408 int hlen; 1409 u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; 1410 1411 dev = skb->dev; 1412 1413 if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) { 1414 ND_PRINTK2(KERN_WARNING 1415 "ICMPv6 Redirect: no link-local address on %s\n", 1416 dev->name); 1417 return; 1418 } 1419 1420 if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) && 1421 ipv6_addr_type(target) != (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) { 1422 ND_PRINTK2(KERN_WARNING 1423 "ICMPv6 Redirect: target address is not link-local unicast.\n"); 1424 return; 1425 } 1426 1427 icmpv6_flow_init(ndisc_socket->sk, &fl, NDISC_REDIRECT, 1428 &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex); 1429 1430 dst = ip6_route_output(NULL, &fl); 1431 if (dst == NULL) 1432 return; 1433 1434 err = xfrm_lookup(&dst, &fl, NULL, 0); 1435 if (err) 1436 return; 1437 1438 rt = (struct rt6_info *) dst; 1439 1440 if (rt->rt6i_flags & RTF_GATEWAY) { 1441 ND_PRINTK2(KERN_WARNING 1442 "ICMPv6 Redirect: destination is not a neighbour.\n"); 1443 dst_release(dst); 1444 return; 1445 } 1446 if (!xrlim_allow(dst, 1*HZ)) { 1447 dst_release(dst); 1448 return; 1449 } 1450 1451 if (dev->addr_len) { 1452 read_lock_bh(&neigh->lock); 1453 if (neigh->nud_state & NUD_VALID) { 1454 memcpy(ha_buf, neigh->ha, dev->addr_len); 1455 read_unlock_bh(&neigh->lock); 1456 ha = ha_buf; 1457 len += ndisc_opt_addr_space(dev); 1458 } else 1459 read_unlock_bh(&neigh->lock); 1460 } 1461 1462 rd_len = min_t(unsigned int, 1463 IPV6_MIN_MTU-sizeof(struct ipv6hdr)-len, skb->len + 8); 1464 rd_len &= ~0x7; 1465 len += rd_len; 1466 1467 buff = sock_alloc_send_skb(sk, 1468 (MAX_HEADER + sizeof(struct ipv6hdr) + 1469 len + LL_RESERVED_SPACE(dev)), 1470 1, &err); 1471 if (buff == NULL) { 1472 ND_PRINTK0(KERN_ERR 1473 "ICMPv6 Redirect: %s() failed to allocate an skb.\n", 1474 __FUNCTION__); 1475 dst_release(dst); 1476 return; 1477 } 1478 1479 hlen = 0; 1480 1481 skb_reserve(buff, LL_RESERVED_SPACE(dev)); 1482 ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr, 1483 IPPROTO_ICMPV6, len); 1484 1485 skb_set_transport_header(buff, skb_tail_pointer(buff) - buff->data); 1486 skb_put(buff, len); 1487 icmph = icmp6_hdr(buff); 1488 1489 memset(icmph, 0, sizeof(struct icmp6hdr)); 1490 icmph->icmp6_type = NDISC_REDIRECT; 1491 1492 /* 1493 * copy target and destination addresses 1494 */ 1495 1496 addrp = (struct in6_addr *)(icmph + 1); 1497 ipv6_addr_copy(addrp, target); 1498 addrp++; 1499 ipv6_addr_copy(addrp, &ipv6_hdr(skb)->daddr); 1500 1501 opt = (u8*) (addrp + 1); 1502 1503 /* 1504 * include target_address option 1505 */ 1506 1507 if (ha) 1508 opt = ndisc_fill_addr_option(opt, ND_OPT_TARGET_LL_ADDR, ha, 1509 dev->addr_len, dev->type); 1510 1511 /* 1512 * build redirect option and copy skb over to the new packet. 1513 */ 1514 1515 memset(opt, 0, 8); 1516 *(opt++) = ND_OPT_REDIRECT_HDR; 1517 *(opt++) = (rd_len >> 3); 1518 opt += 6; 1519 1520 memcpy(opt, ipv6_hdr(skb), rd_len - 8); 1521 1522 icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &ipv6_hdr(skb)->saddr, 1523 len, IPPROTO_ICMPV6, 1524 csum_partial((u8 *) icmph, len, 0)); 1525 1526 buff->dst = dst; 1527 idev = in6_dev_get(dst->dev); 1528 IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); 1529 err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev, 1530 dst_output); 1531 if (!err) { 1532 ICMP6MSGOUT_INC_STATS(idev, NDISC_REDIRECT); 1533 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); 1534 } 1535 1536 if (likely(idev != NULL)) 1537 in6_dev_put(idev); 1538} 1539 1540static void pndisc_redo(struct sk_buff *skb) 1541{ 1542 ndisc_recv_ns(skb); 1543 kfree_skb(skb); 1544} 1545 1546int ndisc_rcv(struct sk_buff *skb) 1547{ 1548 struct nd_msg *msg; 1549 1550 if (!pskb_may_pull(skb, skb->len)) 1551 return 0; 1552 1553 msg = (struct nd_msg *)skb_transport_header(skb); 1554 1555 __skb_push(skb, skb->data - skb_transport_header(skb)); 1556 1557 if (ipv6_hdr(skb)->hop_limit != 255) { 1558 ND_PRINTK2(KERN_WARNING 1559 "ICMPv6 NDISC: invalid hop-limit: %d\n", 1560 ipv6_hdr(skb)->hop_limit); 1561 return 0; 1562 } 1563 1564 if (msg->icmph.icmp6_code != 0) { 1565 ND_PRINTK2(KERN_WARNING 1566 "ICMPv6 NDISC: invalid ICMPv6 code: %d\n", 1567 msg->icmph.icmp6_code); 1568 return 0; 1569 } 1570 1571 memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb)); 1572 1573 switch (msg->icmph.icmp6_type) { 1574 case NDISC_NEIGHBOUR_SOLICITATION: 1575 ndisc_recv_ns(skb); 1576 break; 1577 1578 case NDISC_NEIGHBOUR_ADVERTISEMENT: 1579 ndisc_recv_na(skb); 1580 break; 1581 1582 case NDISC_ROUTER_SOLICITATION: 1583 ndisc_recv_rs(skb); 1584 break; 1585 1586 case NDISC_ROUTER_ADVERTISEMENT: 1587 ndisc_router_discovery(skb); 1588 break; 1589 1590 case NDISC_REDIRECT: 1591 ndisc_redirect_rcv(skb); 1592 break; 1593 } 1594 1595 return 0; 1596} 1597 1598static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) 1599{ 1600 struct net_device *dev = ptr; 1601 1602 if (dev->nd_net != &init_net) 1603 return NOTIFY_DONE; 1604 1605 switch (event) { 1606 case NETDEV_CHANGEADDR: 1607 neigh_changeaddr(&nd_tbl, dev); 1608 fib6_run_gc(~0UL); 1609 break; 1610 case NETDEV_DOWN: 1611 neigh_ifdown(&nd_tbl, dev); 1612 fib6_run_gc(~0UL); 1613 break; 1614 default: 1615 break; 1616 } 1617 1618 return NOTIFY_DONE; 1619} 1620 1621static struct notifier_block ndisc_netdev_notifier = { 1622 .notifier_call = ndisc_netdev_event, 1623}; 1624 1625#ifdef CONFIG_SYSCTL 1626static void ndisc_warn_deprecated_sysctl(struct ctl_table *ctl, 1627 const char *func, const char *dev_name) 1628{ 1629 static char warncomm[TASK_COMM_LEN]; 1630 static int warned; 1631 if (strcmp(warncomm, current->comm) && warned < 5) { 1632 strcpy(warncomm, current->comm); 1633 printk(KERN_WARNING 1634 "process `%s' is using deprecated sysctl (%s) " 1635 "net.ipv6.neigh.%s.%s; " 1636 "Use net.ipv6.neigh.%s.%s_ms " 1637 "instead.\n", 1638 warncomm, func, 1639 dev_name, ctl->procname, 1640 dev_name, ctl->procname); 1641 warned++; 1642 } 1643} 1644 1645int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * filp, void __user *buffer, size_t *lenp, loff_t *ppos) 1646{ 1647 struct net_device *dev = ctl->extra1; 1648 struct inet6_dev *idev; 1649 int ret; 1650 1651 if ((strcmp(ctl->procname, "retrans_time") == 0) || 1652 (strcmp(ctl->procname, "base_reachable_time") == 0)) 1653 ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default"); 1654 1655 if (strcmp(ctl->procname, "retrans_time") == 0) 1656 ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); 1657 1658 else if (strcmp(ctl->procname, "base_reachable_time") == 0) 1659 ret = proc_dointvec_jiffies(ctl, write, 1660 filp, buffer, lenp, ppos); 1661 1662 else if ((strcmp(ctl->procname, "retrans_time_ms") == 0) || 1663 (strcmp(ctl->procname, "base_reachable_time_ms") == 0)) 1664 ret = proc_dointvec_ms_jiffies(ctl, write, 1665 filp, buffer, lenp, ppos); 1666 else 1667 ret = -1; 1668 1669 if (write && ret == 0 && dev && (idev = in6_dev_get(dev)) != NULL) { 1670 if (ctl->data == &idev->nd_parms->base_reachable_time) 1671 idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time); 1672 idev->tstamp = jiffies; 1673 inet6_ifinfo_notify(RTM_NEWLINK, idev); 1674 in6_dev_put(idev); 1675 } 1676 return ret; 1677} 1678 1679static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name, 1680 int nlen, void __user *oldval, 1681 size_t __user *oldlenp, 1682 void __user *newval, size_t newlen) 1683{ 1684 struct net_device *dev = ctl->extra1; 1685 struct inet6_dev *idev; 1686 int ret; 1687 1688 if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME || 1689 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME) 1690 ndisc_warn_deprecated_sysctl(ctl, "procfs", dev ? dev->name : "default"); 1691 1692 switch (ctl->ctl_name) { 1693 case NET_NEIGH_REACHABLE_TIME: 1694 ret = sysctl_jiffies(ctl, name, nlen, 1695 oldval, oldlenp, newval, newlen); 1696 break; 1697 case NET_NEIGH_RETRANS_TIME_MS: 1698 case NET_NEIGH_REACHABLE_TIME_MS: 1699 ret = sysctl_ms_jiffies(ctl, name, nlen, 1700 oldval, oldlenp, newval, newlen); 1701 break; 1702 default: 1703 ret = 0; 1704 } 1705 1706 if (newval && newlen && ret > 0 && 1707 dev && (idev = in6_dev_get(dev)) != NULL) { 1708 if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME || 1709 ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS) 1710 idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time); 1711 idev->tstamp = jiffies; 1712 inet6_ifinfo_notify(RTM_NEWLINK, idev); 1713 in6_dev_put(idev); 1714 } 1715 1716 return ret; 1717} 1718 1719#endif 1720 1721int __init ndisc_init(void) 1722{ 1723 struct ipv6_pinfo *np; 1724 struct sock *sk; 1725 int err; 1726 1727 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket); 1728 if (err < 0) { 1729 ND_PRINTK0(KERN_ERR 1730 "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n", 1731 err); 1732 ndisc_socket = NULL; /* For safety. */ 1733 return err; 1734 } 1735 1736 sk = ndisc_socket->sk; 1737 np = inet6_sk(sk); 1738 sk->sk_allocation = GFP_ATOMIC; 1739 np->hop_limit = 255; 1740 /* Do not loopback ndisc messages */ 1741 np->mc_loop = 0; 1742 sk->sk_prot->unhash(sk); 1743 1744 /* 1745 * Initialize the neighbour table 1746 */ 1747 1748 neigh_table_init(&nd_tbl); 1749 1750#ifdef CONFIG_SYSCTL 1751 neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH, 1752 "ipv6", 1753 &ndisc_ifinfo_sysctl_change, 1754 &ndisc_ifinfo_sysctl_strategy); 1755#endif 1756 1757 register_netdevice_notifier(&ndisc_netdev_notifier); 1758 return 0; 1759} 1760 1761void ndisc_cleanup(void) 1762{ 1763 unregister_netdevice_notifier(&ndisc_netdev_notifier); 1764#ifdef CONFIG_SYSCTL 1765 neigh_sysctl_unregister(&nd_tbl.parms); 1766#endif 1767 neigh_table_clear(&nd_tbl); 1768 sock_release(ndisc_socket); 1769 ndisc_socket = NULL; /* For safety. */ 1770} 1771