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 --- |