ndisc.c (6fd99094de2b83d1d4c8457f2c83483b2828e75a) ndisc.c (63159f29be1df7f93563a8a0f78c5e65fc844ed6)
1/*
2 * Neighbour Discovery for IPv6
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 * Mike Shaver <shaver@ingenia.com>
8 *

--- 70 unchanged lines hidden (view full) ---

79do { \
80 if (val <= ND_DEBUG) \
81 net_##level##_ratelimited(fmt, ##__VA_ARGS__); \
82} while (0)
83
84static u32 ndisc_hash(const void *pkey,
85 const struct net_device *dev,
86 __u32 *hash_rnd);
1/*
2 * Neighbour Discovery for IPv6
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 * Mike Shaver <shaver@ingenia.com>
8 *

--- 70 unchanged lines hidden (view full) ---

79do { \
80 if (val <= ND_DEBUG) \
81 net_##level##_ratelimited(fmt, ##__VA_ARGS__); \
82} while (0)
83
84static u32 ndisc_hash(const void *pkey,
85 const struct net_device *dev,
86 __u32 *hash_rnd);
87static bool ndisc_key_eq(const struct neighbour *neigh, const void *pkey);
87static int ndisc_constructor(struct neighbour *neigh);
88static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
89static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
90static int pndisc_constructor(struct pneigh_entry *n);
91static void pndisc_destructor(struct pneigh_entry *n);
92static void pndisc_redo(struct sk_buff *skb);
93
94static const struct neigh_ops ndisc_generic_ops = {

--- 17 unchanged lines hidden (view full) ---

112 .family = AF_INET6,
113 .output = neigh_direct_output,
114 .connected_output = neigh_direct_output,
115};
116
117struct neigh_table nd_tbl = {
118 .family = AF_INET6,
119 .key_len = sizeof(struct in6_addr),
88static int ndisc_constructor(struct neighbour *neigh);
89static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
90static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
91static int pndisc_constructor(struct pneigh_entry *n);
92static void pndisc_destructor(struct pneigh_entry *n);
93static void pndisc_redo(struct sk_buff *skb);
94
95static const struct neigh_ops ndisc_generic_ops = {

--- 17 unchanged lines hidden (view full) ---

113 .family = AF_INET6,
114 .output = neigh_direct_output,
115 .connected_output = neigh_direct_output,
116};
117
118struct neigh_table nd_tbl = {
119 .family = AF_INET6,
120 .key_len = sizeof(struct in6_addr),
121 .protocol = cpu_to_be16(ETH_P_IPV6),
120 .hash = ndisc_hash,
122 .hash = ndisc_hash,
123 .key_eq = ndisc_key_eq,
121 .constructor = ndisc_constructor,
122 .pconstructor = pndisc_constructor,
123 .pdestructor = pndisc_destructor,
124 .proxy_redo = pndisc_redo,
125 .id = "ndisc_cache",
126 .parms = {
127 .tbl = &nd_tbl,
128 .reachable_time = ND_REACHABLE_TIME,

--- 160 unchanged lines hidden (view full) ---

289
290static u32 ndisc_hash(const void *pkey,
291 const struct net_device *dev,
292 __u32 *hash_rnd)
293{
294 return ndisc_hashfn(pkey, dev, hash_rnd);
295}
296
124 .constructor = ndisc_constructor,
125 .pconstructor = pndisc_constructor,
126 .pdestructor = pndisc_destructor,
127 .proxy_redo = pndisc_redo,
128 .id = "ndisc_cache",
129 .parms = {
130 .tbl = &nd_tbl,
131 .reachable_time = ND_REACHABLE_TIME,

--- 160 unchanged lines hidden (view full) ---

292
293static u32 ndisc_hash(const void *pkey,
294 const struct net_device *dev,
295 __u32 *hash_rnd)
296{
297 return ndisc_hashfn(pkey, dev, hash_rnd);
298}
299
300static bool ndisc_key_eq(const struct neighbour *n, const void *pkey)
301{
302 return neigh_key_eq128(n, pkey);
303}
304
297static int ndisc_constructor(struct neighbour *neigh)
298{
299 struct in6_addr *addr = (struct in6_addr *)&neigh->primary_key;
300 struct net_device *dev = neigh->dev;
301 struct inet6_dev *in6_dev;
302 struct neigh_parms *parms;
303 bool is_multicast = ipv6_addr_is_multicast(addr);
304
305 in6_dev = in6_dev_get(dev);
305static int ndisc_constructor(struct neighbour *neigh)
306{
307 struct in6_addr *addr = (struct in6_addr *)&neigh->primary_key;
308 struct net_device *dev = neigh->dev;
309 struct inet6_dev *in6_dev;
310 struct neigh_parms *parms;
311 bool is_multicast = ipv6_addr_is_multicast(addr);
312
313 in6_dev = in6_dev_get(dev);
306 if (in6_dev == NULL) {
314 if (!in6_dev) {
307 return -EINVAL;
308 }
309
310 parms = in6_dev->nd_parms;
311 __neigh_parms_put(neigh->parms);
312 neigh->parms = neigh_parms_clone(parms);
313
314 neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST;

--- 28 unchanged lines hidden (view full) ---

343}
344
345static int pndisc_constructor(struct pneigh_entry *n)
346{
347 struct in6_addr *addr = (struct in6_addr *)&n->key;
348 struct in6_addr maddr;
349 struct net_device *dev = n->dev;
350
315 return -EINVAL;
316 }
317
318 parms = in6_dev->nd_parms;
319 __neigh_parms_put(neigh->parms);
320 neigh->parms = neigh_parms_clone(parms);
321
322 neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST;

--- 28 unchanged lines hidden (view full) ---

351}
352
353static int pndisc_constructor(struct pneigh_entry *n)
354{
355 struct in6_addr *addr = (struct in6_addr *)&n->key;
356 struct in6_addr maddr;
357 struct net_device *dev = n->dev;
358
351 if (dev == NULL || __in6_dev_get(dev) == NULL)
359 if (!dev || !__in6_dev_get(dev))
352 return -EINVAL;
353 addrconf_addr_solict_mult(addr, &maddr);
354 ipv6_dev_mc_inc(dev, &maddr);
355 return 0;
356}
357
358static void pndisc_destructor(struct pneigh_entry *n)
359{
360 struct in6_addr *addr = (struct in6_addr *)&n->key;
361 struct in6_addr maddr;
362 struct net_device *dev = n->dev;
363
360 return -EINVAL;
361 addrconf_addr_solict_mult(addr, &maddr);
362 ipv6_dev_mc_inc(dev, &maddr);
363 return 0;
364}
365
366static void pndisc_destructor(struct pneigh_entry *n)
367{
368 struct in6_addr *addr = (struct in6_addr *)&n->key;
369 struct in6_addr maddr;
370 struct net_device *dev = n->dev;
371
364 if (dev == NULL || __in6_dev_get(dev) == NULL)
372 if (!dev || !__in6_dev_get(dev))
365 return;
366 addrconf_addr_solict_mult(addr, &maddr);
367 ipv6_dev_mc_dec(dev, &maddr);
368}
369
370static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
371 int len)
372{

--- 174 unchanged lines hidden (view full) ---

547 const struct in6_addr *daddr, const struct in6_addr *saddr)
548{
549 struct sk_buff *skb;
550 struct in6_addr addr_buf;
551 int inc_opt = dev->addr_len;
552 int optlen = 0;
553 struct nd_msg *msg;
554
373 return;
374 addrconf_addr_solict_mult(addr, &maddr);
375 ipv6_dev_mc_dec(dev, &maddr);
376}
377
378static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
379 int len)
380{

--- 174 unchanged lines hidden (view full) ---

555 const struct in6_addr *daddr, const struct in6_addr *saddr)
556{
557 struct sk_buff *skb;
558 struct in6_addr addr_buf;
559 int inc_opt = dev->addr_len;
560 int optlen = 0;
561 struct nd_msg *msg;
562
555 if (saddr == NULL) {
563 if (!saddr) {
556 if (ipv6_get_lladdr(dev, &addr_buf,
557 (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)))
558 return;
559 saddr = &addr_buf;
560 }
561
562 if (ipv6_addr_any(saddr))
563 inc_opt = false;

--- 453 unchanged lines hidden (view full) ---

1017 struct nduseroptmsg *ndmsg;
1018 struct net *net = dev_net(ra->dev);
1019 int err;
1020 int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg)
1021 + (opt->nd_opt_len << 3));
1022 size_t msg_size = base_size + nla_total_size(sizeof(struct in6_addr));
1023
1024 skb = nlmsg_new(msg_size, GFP_ATOMIC);
564 if (ipv6_get_lladdr(dev, &addr_buf,
565 (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)))
566 return;
567 saddr = &addr_buf;
568 }
569
570 if (ipv6_addr_any(saddr))
571 inc_opt = false;

--- 453 unchanged lines hidden (view full) ---

1025 struct nduseroptmsg *ndmsg;
1026 struct net *net = dev_net(ra->dev);
1027 int err;
1028 int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg)
1029 + (opt->nd_opt_len << 3));
1030 size_t msg_size = base_size + nla_total_size(sizeof(struct in6_addr));
1031
1032 skb = nlmsg_new(msg_size, GFP_ATOMIC);
1025 if (skb == NULL) {
1033 if (!skb) {
1026 err = -ENOBUFS;
1027 goto errout;
1028 }
1029
1030 nlh = nlmsg_put(skb, 0, 0, RTM_NEWNDUSEROPT, base_size, 0);
1034 err = -ENOBUFS;
1035 goto errout;
1036 }
1037
1038 nlh = nlmsg_put(skb, 0, 0, RTM_NEWNDUSEROPT, base_size, 0);
1031 if (nlh == NULL) {
1039 if (!nlh) {
1032 goto nla_put_failure;
1033 }
1034
1035 ndmsg = nlmsg_data(nlh);
1036 ndmsg->nduseropt_family = AF_INET6;
1037 ndmsg->nduseropt_ifindex = ra->dev->ifindex;
1038 ndmsg->nduseropt_icmp_type = icmp6h->icmp6_type;
1039 ndmsg->nduseropt_icmp_code = icmp6h->icmp6_code;

--- 51 unchanged lines hidden (view full) ---

1091 }
1092#endif
1093
1094 /*
1095 * set the RA_RECV flag in the interface
1096 */
1097
1098 in6_dev = __in6_dev_get(skb->dev);
1040 goto nla_put_failure;
1041 }
1042
1043 ndmsg = nlmsg_data(nlh);
1044 ndmsg->nduseropt_family = AF_INET6;
1045 ndmsg->nduseropt_ifindex = ra->dev->ifindex;
1046 ndmsg->nduseropt_icmp_type = icmp6h->icmp6_type;
1047 ndmsg->nduseropt_icmp_code = icmp6h->icmp6_code;

--- 51 unchanged lines hidden (view full) ---

1099 }
1100#endif
1101
1102 /*
1103 * set the RA_RECV flag in the interface
1104 */
1105
1106 in6_dev = __in6_dev_get(skb->dev);
1099 if (in6_dev == NULL) {
1107 if (!in6_dev) {
1100 ND_PRINTK(0, err, "RA: can't find inet6 device for %s\n",
1101 skb->dev->name);
1102 return;
1103 }
1104
1105 if (!ndisc_parse_options(opt, optlen, &ndopts)) {
1106 ND_PRINTK(2, warn, "RA: invalid ND options\n");
1107 return;

--- 78 unchanged lines hidden (view full) ---

1186 }
1187 if (rt && lifetime == 0) {
1188 ip6_del_rt(rt);
1189 rt = NULL;
1190 }
1191
1192 ND_PRINTK(3, info, "RA: rt: %p lifetime: %d, for dev: %s\n",
1193 rt, lifetime, skb->dev->name);
1108 ND_PRINTK(0, err, "RA: can't find inet6 device for %s\n",
1109 skb->dev->name);
1110 return;
1111 }
1112
1113 if (!ndisc_parse_options(opt, optlen, &ndopts)) {
1114 ND_PRINTK(2, warn, "RA: invalid ND options\n");
1115 return;

--- 78 unchanged lines hidden (view full) ---

1194 }
1195 if (rt && lifetime == 0) {
1196 ip6_del_rt(rt);
1197 rt = NULL;
1198 }
1199
1200 ND_PRINTK(3, info, "RA: rt: %p lifetime: %d, for dev: %s\n",
1201 rt, lifetime, skb->dev->name);
1194 if (rt == NULL && lifetime) {
1202 if (!rt && lifetime) {
1195 ND_PRINTK(3, info, "RA: adding default router\n");
1196
1197 rt = rt6_add_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev, pref);
1203 ND_PRINTK(3, info, "RA: adding default router\n");
1204
1205 rt = rt6_add_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev, pref);
1198 if (rt == NULL) {
1206 if (!rt) {
1199 ND_PRINTK(0, err,
1200 "RA: %s failed to add default route\n",
1201 __func__);
1202 return;
1203 }
1204
1205 neigh = dst_neigh_lookup(&rt->dst, &ipv6_hdr(skb)->saddr);
1207 ND_PRINTK(0, err,
1208 "RA: %s failed to add default route\n",
1209 __func__);
1210 return;
1211 }
1212
1213 neigh = dst_neigh_lookup(&rt->dst, &ipv6_hdr(skb)->saddr);
1206 if (neigh == NULL) {
1214 if (!neigh) {
1207 ND_PRINTK(0, err,
1208 "RA: %s got default router without neighbour\n",
1209 __func__);
1210 ip6_rt_put(rt);
1211 return;
1212 }
1213 neigh->flags |= NTF_ROUTER;
1214 } else if (rt) {
1215 rt->rt6i_flags = (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
1216 }
1217
1218 if (rt)
1219 rt6_set_expires(rt, jiffies + (HZ * lifetime));
1220 if (ra_msg->icmph.icmp6_hop_limit) {
1215 ND_PRINTK(0, err,
1216 "RA: %s got default router without neighbour\n",
1217 __func__);
1218 ip6_rt_put(rt);
1219 return;
1220 }
1221 neigh->flags |= NTF_ROUTER;
1222 } else if (rt) {
1223 rt->rt6i_flags = (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
1224 }
1225
1226 if (rt)
1227 rt6_set_expires(rt, jiffies + (HZ * lifetime));
1228 if (ra_msg->icmph.icmp6_hop_limit) {
1221 /* Only set hop_limit on the interface if it is higher than
1222 * the current hop_limit.
1223 */
1224 if (in6_dev->cnf.hop_limit < ra_msg->icmph.icmp6_hop_limit) {
1225 in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
1226 } else {
1227 ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than current\n");
1228 }
1229 in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
1229 if (rt)
1230 dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
1231 ra_msg->icmph.icmp6_hop_limit);
1232 }
1233
1234skip_defrtr:
1235
1236 /*

--- 575 unchanged lines hidden ---
1230 if (rt)
1231 dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
1232 ra_msg->icmph.icmp6_hop_limit);
1233 }
1234
1235skip_defrtr:
1236
1237 /*

--- 575 unchanged lines hidden ---