1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Based on net/ipv6/ndisc.c
4 * Authors:
5 * Pedro Roque <roque@di.fc.ul.pt>
6 * Mike Shaver <shaver@ingenia.com>
7 *
8 * Changes:
9 *
10 * Alexey I. Froloff : RFC6106 (DNSSL) support
11 * Pierre Ynard : export userland ND options
12 * through netlink (RDNSS support)
13 * Lars Fenneberg : fixed MTU setting on receipt
14 * of an RA.
15 * Janos Farkas : kmalloc failure checks
16 * Alexey Kuznetsov : state machine reworked
17 * and moved to net/core.
18 * Pekka Savola : RFC2461 validation
19 * YOSHIFUJI Hideaki @USAGI : Verify ND options properly
20 *
21 * Neighbour Discovery for NewIP
22 * Linux NewIP INET implementation
23 */
24 #define pr_fmt(fmt) KBUILD_MODNAME ": [%s:%d] " fmt, __func__, __LINE__
25
26 #include <net/sock.h>
27 #include <net/nip.h>
28 #include <net/nip_udp.h>
29 #include <net/protocol.h>
30 #include <net/nndisc.h>
31 #include <net/nip_route.h>
32 #include <net/addrconf.h>
33 #include <net/nip_fib.h>
34 #include <net/netlink.h>
35 #include <net/flow.h>
36 #include <net/inet_common.h>
37 #include <net/nip_addrconf.h>
38 #include <linux/module.h>
39 #include <linux/errno.h>
40 #include <linux/types.h>
41 #include <linux/socket.h>
42 #include <linux/sockios.h>
43 #include <linux/net.h>
44 #include <linux/route.h>
45 #include <linux/init.h>
46 #include <linux/rcupdate.h>
47 #include <linux/nip.h>
48 #include <linux/nip_icmp.h>
49 #include <linux/jhash.h>
50 #include <linux/rtnetlink.h>
51 #include <linux/newip_route.h>
52 #include <linux/netfilter.h>
53 #include "nip_hdr.h"
54 #include "nip_checksum.h"
55 #include "tcp_nip_parameter.h"
56
57 /* NUD_INCOMPLETE
58 * The neighbor request packet has been sent but no response has been received
59 * NUD_REACHABLE
60 * Reachable: Indicates that the neighbor is reachable
61 * NUD_STAL
62 * Idle state, which has not been confirmed for a long time,
63 * and the idle time exceeds the rated time
64 * NUD_DELAY
65 * If the acknowledgment time expires but the idle time does not exceed the rated time,
66 * you need to obtain the acknowledgment packet
67 * NUD_PROBE
68 * After NUD_DELAY does not receive confirmation for a long time, ARP request messages are sent
69 * NUD_FAILED
70 * The neighbor is unreachable
71 * NUD_NOARP
72 * Indicates the status of the neighbor that does not need the ARP status change
73 * NUD_PERMANENT
74 * Indicates that the status of the neighbor item is permanent and does not need to change
75 * NUD_NONE
76 * Initialization status of the neighbor item
77 */
78 static void nndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
79
80 static u32 nndisc_hash(const void *pkey,
81 const struct net_device *dev, __u32 *hash_rnd);
82 static bool nndisc_key_eq(const struct neighbour *neigh, const void *pkey);
83 static int nndisc_constructor(struct neighbour *neigh);
84
nndisc_error_report(struct neighbour * neigh,struct sk_buff * skb)85 static void nndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
86 {
87 kfree_skb(skb);
88 }
89
nndisc_generic_error_report(struct neighbour * neigh,struct sk_buff * skb)90 static void nndisc_generic_error_report(struct neighbour *neigh, struct sk_buff *skb)
91 {
92 }
93
94 static const struct neigh_ops nndisc_generic_ops = {
95 .family = AF_NINET,
96 .solicit = nndisc_solicit,
97 .output = neigh_resolve_output,
98 .connected_output = neigh_connected_output,
99 .error_report = nndisc_generic_error_report,
100 };
101
102 static const struct neigh_ops nndisc_hh_ops = {
103 .family = AF_NINET,
104 .solicit = nndisc_solicit,
105 .error_report = nndisc_error_report,
106 .output = neigh_resolve_output,
107 .connected_output = neigh_resolve_output,
108 };
109
110 static const struct neigh_ops nndisc_direct_ops = {
111 .family = AF_NINET,
112 .output = neigh_direct_output,
113 .connected_output = neigh_direct_output,
114 };
115
116 #define NIP_NEIGH_MCAST_PROBES 4
117 #define NIP_NEIGH_UCAST_PROBES 4
118 #define NIP_NEIGH_DELAY_PROBE_TIME (5 * HZ)
119 #define NIP_NEIGH_GC_STALETIME (60 * HZ)
120 #define NIP_NEIGH_QUEUE_LEN_BYTES (64 * 1024)
121 #define NIP_NEIGH_PROXY_QLEN 64
122 #define NIP_NEIGH_ANYCAST_DELAY (1 * HZ)
123 #define NIP_NEIGH_PROXY_DELAY ((8 * HZ) / 10)
124 #define NIP_NEIGH_GC_INTERVAL (30 * HZ)
125 #define NIP_NEIGH_GC_THRESH_1 128
126 #define NIP_NEIGH_GC_THRESH_2 512
127 #define NIP_NEIGH_GC_THRESH_3 1024
128
nndisc_proxy_redo(struct sk_buff * skb)129 static void nndisc_proxy_redo(struct sk_buff *skb)
130 {
131 }
132
nndisc_is_multicast(const void * pkey)133 static int nndisc_is_multicast(const void *pkey)
134 {
135 return -EINVAL;
136 }
137
138 struct neigh_table nnd_tbl = {
139 .family = AF_NINET,
140 .key_len = sizeof(struct nip_addr),
141 .protocol = cpu_to_be16(ETH_P_NEWIP),
142 .hash = nndisc_hash,
143 .key_eq = nndisc_key_eq,
144 .constructor = nndisc_constructor,
145 .proxy_redo = nndisc_proxy_redo,
146 .is_multicast = nndisc_is_multicast,
147 .id = "nndisc_cache",
148 .parms = {
149 .tbl = &nnd_tbl,
150 .reachable_time = ND_REACHABLE_TIME,
151 .data = {
152 [NEIGH_VAR_MCAST_PROBES] = NIP_NEIGH_MCAST_PROBES,
153 [NEIGH_VAR_UCAST_PROBES] = NIP_NEIGH_UCAST_PROBES,
154 [NEIGH_VAR_RETRANS_TIME] = ND_RETRANS_TIMER,
155 [NEIGH_VAR_BASE_REACHABLE_TIME] = ND_REACHABLE_TIME,
156 [NEIGH_VAR_DELAY_PROBE_TIME] = NIP_NEIGH_DELAY_PROBE_TIME,
157 [NEIGH_VAR_GC_STALETIME] = NIP_NEIGH_GC_STALETIME,
158 [NEIGH_VAR_QUEUE_LEN_BYTES] = NIP_NEIGH_QUEUE_LEN_BYTES,
159 [NEIGH_VAR_PROXY_QLEN] = NIP_NEIGH_PROXY_QLEN,
160 [NEIGH_VAR_ANYCAST_DELAY] = NIP_NEIGH_ANYCAST_DELAY,
161 [NEIGH_VAR_PROXY_DELAY] = NIP_NEIGH_PROXY_DELAY,
162 },
163 },
164 .gc_interval = NIP_NEIGH_GC_INTERVAL,
165 .gc_thresh1 = NIP_NEIGH_GC_THRESH_1,
166 .gc_thresh2 = NIP_NEIGH_GC_THRESH_2,
167 .gc_thresh3 = NIP_NEIGH_GC_THRESH_3,
168 };
169
nndisc_hash(const void * pkey,const struct net_device * dev,__u32 * hash_rnd)170 static u32 nndisc_hash(const void *pkey,
171 const struct net_device *dev, __u32 *hash_rnd)
172 {
173 return nndisc_hashfn(pkey, dev, hash_rnd);
174 }
175
nndisc_key_eq(const struct neighbour * neigh,const void * pkey)176 static bool nndisc_key_eq(const struct neighbour *neigh, const void *pkey)
177 {
178 return neigh_key_eq800(neigh, pkey);
179 }
180
nndisc_constructor(struct neighbour * neigh)181 static int nndisc_constructor(struct neighbour *neigh)
182 {
183 struct nip_addr *addr = (struct nip_addr *)&neigh->primary_key;
184 struct net_device *dev = neigh->dev;
185 struct ninet_dev *nin_dev;
186 struct neigh_parms *parms;
187 bool is_broadcast = (bool)nip_addr_eq(addr, &nip_broadcast_addr_arp);
188
189 nin_dev = nin_dev_get(dev);
190 if (!nin_dev)
191 return -EINVAL;
192
193 parms = nin_dev->nd_parms;
194 __neigh_parms_put(neigh->parms);
195 neigh->parms = neigh_parms_clone(parms);
196 neigh->type = RTN_UNICAST;
197 if (!dev->header_ops) {
198 neigh->nud_state = NUD_NOARP;
199 neigh->ops = &nndisc_direct_ops;
200 neigh->output = neigh_direct_output;
201 } else {
202 if (is_broadcast ||
203 (dev->flags & IFF_POINTOPOINT)) {
204 neigh->nud_state = NUD_NOARP;
205 memcpy(neigh->ha, dev->broadcast, dev->addr_len);
206 } else if (dev->flags & (IFF_NOARP | IFF_LOOPBACK)) {
207 neigh->nud_state = NUD_NOARP;
208 memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
209 if (dev->flags & IFF_LOOPBACK)
210 neigh->type = RTN_LOCAL;
211 }
212
213 if (dev->header_ops->cache)
214 neigh->ops = &nndisc_hh_ops;
215 else
216 neigh->ops = &nndisc_generic_ops;
217
218 if (neigh->nud_state & NUD_VALID)
219 neigh->output = neigh->ops->connected_output;
220 else
221 neigh->output = neigh->ops->output;
222 }
223
224 nin_dev_put(nin_dev);
225
226 return 0;
227 }
228
nip_insert_nndisc_send_checksum(struct sk_buff * skb,u_short checksum)229 void nip_insert_nndisc_send_checksum(struct sk_buff *skb, u_short checksum)
230 {
231 #define NNDISC_CHECKSUM_BIAS 2
232 *(__u16 *)(skb_transport_header(skb) + NNDISC_CHECKSUM_BIAS) =
233 htons(checksum);
234 }
235
nip_get_nndisc_send_checksum(struct sk_buff * skb,struct nip_hdr_encap * head,int payload_len)236 unsigned short nip_get_nndisc_send_checksum(struct sk_buff *skb,
237 struct nip_hdr_encap *head,
238 int payload_len)
239 {
240 struct nip_pseudo_header nph = {0};
241
242 nph.nexthdr = head->nexthdr;
243 nph.saddr = head->saddr;
244 nph.daddr = head->daddr;
245 nph.check_len = htons(payload_len);
246 return nip_check_sum_build(skb_transport_header(skb),
247 payload_len, &nph);
248 }
249
nip_get_nndisc_rcv_checksum(struct sk_buff * skb,const u_char * transport_tail)250 bool nip_get_nndisc_rcv_checksum(struct sk_buff *skb,
251 const u_char *transport_tail)
252 {
253 struct nip_pseudo_header nph = {0};
254 unsigned short check_len = (unsigned short)(transport_tail - (skb_transport_header(skb)));
255
256 nph.nexthdr = nipcb(skb)->nexthdr;
257 nph.saddr = nipcb(skb)->srcaddr;
258 nph.daddr = nipcb(skb)->dstaddr;
259 nph.check_len = htons(check_len);
260
261 return nip_check_sum_parse(skb_transport_header(skb), check_len, &nph)
262 == 0xffff ? true : false;
263 }
264
nndisc_payload_ns_pack(const struct nip_addr * solicit,struct sk_buff * skb)265 static void nndisc_payload_ns_pack(const struct nip_addr *solicit,
266 struct sk_buff *skb)
267 {
268 struct nnd_msg *msg = (struct nnd_msg *)skb->data;
269 u_char *p = msg->data;
270
271 memset(&msg->icmph, 0, sizeof(msg->icmph));
272 msg->icmph.nip_icmp_type = NIP_ARP_NS;
273 msg->icmph.nip_icmp_cksum = 0;
274 p = build_nip_addr(solicit, p);
275 }
276
nndisc_dst_alloc(struct net_device * dev)277 static struct dst_entry *nndisc_dst_alloc(struct net_device *dev)
278 {
279 struct nip_rt_info *rt;
280 struct net *net = dev_net(dev);
281
282 rt = nip_dst_alloc(net, dev, 0);
283 if (!rt)
284 return NULL;
285
286 rt->dst.flags |= DST_HOST;
287 rt->dst.input = nip_input;
288 rt->dst.output = nip_output;
289 atomic_set(&rt->dst.__refcnt, 1);
290
291 return &rt->dst;
292 }
293
get_ns_payload_len(const struct nip_addr * solicit)294 static int get_ns_payload_len(const struct nip_addr *solicit)
295 {
296 return sizeof(struct nip_icmp_hdr) + get_nip_addr_len(solicit);
297 }
298
nndisc_send_skb(struct net_device * dev,struct sk_buff * skb,struct nip_hdr_encap * head,const int payload_len)299 static int nndisc_send_skb(struct net_device *dev,
300 struct sk_buff *skb, struct nip_hdr_encap *head,
301 const int payload_len)
302 {
303 int ret = 0;
304 struct sock *sk = NULL;
305 struct dst_entry *dst = NULL;
306 u_short checksum = 0;
307
308 /* skip transport hdr */
309 skb_reserve(skb, payload_len);
310
311 /* set skb->data to point network header */
312 skb->data = skb_network_header(skb);
313 skb->len = head->hdr_buf_pos + payload_len;
314
315 dst = nndisc_dst_alloc(dev);
316 if (!dst) {
317 kfree_skb(skb);
318 return -ENOMEM;
319 }
320 /* add check sum */
321 checksum = nip_get_nndisc_send_checksum(skb, head, payload_len);
322 nip_insert_nndisc_send_checksum(skb, checksum);
323
324 skb_dst_set(skb, dst);
325 ret = dst_output(dev_net(skb->dev), sk, skb);
326 return ret;
327 }
328
nndisc_alloc_skb(struct net_device * dev,struct nip_hdr_encap * head,int payload_len)329 static struct sk_buff *nndisc_alloc_skb(struct net_device *dev,
330 struct nip_hdr_encap *head, int payload_len)
331 {
332 struct sk_buff *skb = NULL;
333 int len = NIP_ETH_HDR_LEN + NIP_HDR_MAX + payload_len;
334
335 skb = alloc_skb(len, 0);
336 if (!skb)
337 /* If you add log here, there will be an alarm:
338 * WARNING: Possible unnecessary 'out of memory' message
339 */
340 return skb;
341
342 skb->protocol = htons(ETH_P_NEWIP);
343 skb->ip_summed = CHECKSUM_NONE;
344 skb->csum = 0;
345 skb->dev = dev;
346 memset(nipcb(skb), 0, sizeof(struct ninet_skb_parm));
347
348 nipcb(skb)->dstaddr = head->daddr;
349 nipcb(skb)->srcaddr = head->saddr;
350 nipcb(skb)->nexthdr = head->nexthdr;
351 /* reserve space for hardware header */
352 skb_reserve(skb, NIP_ETH_HDR_LEN);
353 skb_reset_network_header(skb);
354
355 /* build nwk header */
356 head->hdr_buf = (unsigned char *)skb->data;
357 nip_hdr_comm_encap(head);
358 head->total_len = head->hdr_buf_pos + payload_len;
359 nip_update_total_len(head, htons(head->total_len));
360 skb_reserve(skb, head->hdr_buf_pos);
361 skb_reset_transport_header(skb);
362 return skb;
363 }
364
nndisc_send_ns(struct net_device * dev,const struct nip_addr * solicit,const struct nip_addr * daddr,const struct nip_addr * saddr)365 static void nndisc_send_ns(struct net_device *dev,
366 const struct nip_addr *solicit,
367 const struct nip_addr *daddr,
368 const struct nip_addr *saddr)
369 {
370 int ret;
371 struct sk_buff *skb;
372 int payload_len = get_ns_payload_len(solicit);
373 struct nip_hdr_encap head = {0};
374
375 head.saddr = *saddr;
376 head.daddr = *daddr;
377 head.ttl = NIP_ARP_DEFAULT_TTL;
378 head.nexthdr = IPPROTO_NIP_ICMP;
379
380 skb = nndisc_alloc_skb(dev, &head, payload_len);
381 if (!skb)
382 /* If you add log here, there will be an alarm:
383 * WARNING: Possible unnecessary 'out of memory' message
384 */
385 return;
386 /* build ns header */
387 nndisc_payload_ns_pack(solicit, skb);
388
389 ret = nndisc_send_skb(dev, skb, &head, payload_len);
390 if (ret)
391 nip_dbg("dst output fail");
392 }
393
__send_ns_packet(__u8 nud_state,struct net_device * dev,const struct nip_addr * target,const struct nip_addr * saddr)394 static void __send_ns_packet(__u8 nud_state, struct net_device *dev,
395 const struct nip_addr *target, const struct nip_addr *saddr)
396 {
397 if (nud_state & NUD_VALID) {
398 nndisc_send_ns(dev, target, target, saddr);
399 nip_dbg("unicast ns");
400 } else {
401 nndisc_send_ns(dev, target, &nip_broadcast_addr_arp, saddr);
402 nip_dbg("multicast ns");
403 }
404 }
405
nndisc_solicit(struct neighbour * neigh,struct sk_buff * skb)406 static void nndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
407 {
408 struct net_device *dev = neigh->dev;
409 struct nip_addr *target = (struct nip_addr *)&neigh->primary_key;
410 struct ninet_dev *idev;
411
412 /* Obtain the NewIP address from the current dev as
413 * the source address of the request packet
414 */
415 rcu_read_lock();
416 idev = __nin_dev_get(dev);
417 if (!idev) {
418 nip_dbg("idev don't exist");
419 rcu_read_unlock();
420 return;
421 }
422 read_lock_bh(&idev->lock);
423 if (!list_empty(&idev->addr_list)) {
424 struct ninet_ifaddr *ifp;
425
426 list_for_each_entry(ifp, &idev->addr_list, if_list) {
427 __send_ns_packet(neigh->nud_state, dev, target, &ifp->addr);
428 }
429 }
430 read_unlock_bh(&idev->lock);
431 rcu_read_unlock();
432 }
433
build_na_hdr(u_char * smac,u_char mac_len,struct sk_buff * skb)434 static void build_na_hdr(u_char *smac, u_char mac_len, struct sk_buff *skb)
435 {
436 struct nnd_msg *msg = (struct nnd_msg *)skb->data;
437 u_char *p = msg->data;
438
439 memset(&msg->icmph, 0, sizeof(msg->icmph));
440 msg->icmph.nip_icmp_type = NIP_ARP_NA;
441 msg->icmph.nip_icmp_cksum = 0;
442 *p = mac_len;
443 p++;
444 memcpy(p, smac, mac_len);
445 }
446
get_na_payload_len(struct net_device * dev)447 static int get_na_payload_len(struct net_device *dev)
448 {
449 /* Icmp Header Length
450 * Number of bytes in the MAC address length field
451 * MAC Address Length
452 */
453 return sizeof(struct nip_icmp_hdr) + 1 + dev->addr_len;
454 }
455
nndisc_send_na(struct net_device * dev,const struct nip_addr * daddr,const struct nip_addr * saddr)456 static void nndisc_send_na(struct net_device *dev,
457 const struct nip_addr *daddr,
458 const struct nip_addr *saddr)
459 {
460 int ret;
461 struct sk_buff *skb = NULL;
462 int payload_len = get_na_payload_len(dev);
463 u_char *smac = dev->dev_addr;
464 struct nip_hdr_encap head = {0};
465
466 head.saddr = *saddr;
467 head.daddr = *daddr;
468 head.ttl = NIP_ARP_DEFAULT_TTL;
469 head.nexthdr = IPPROTO_NIP_ICMP;
470
471 skb = nndisc_alloc_skb(dev, &head, payload_len);
472 if (!skb)
473 /* If you add log here, there will be an alarm:
474 * WARNING: Possible unnecessary 'out of memory' message
475 */
476 return;
477 /* build na header */
478 build_na_hdr(smac, dev->addr_len, skb);
479
480 ret = nndisc_send_skb(dev, skb, &head, payload_len);
481 if (ret)
482 nip_dbg("dst output fail");
483 }
484
nip_addr_local(struct net_device * dev,struct nip_addr * addr)485 bool nip_addr_local(struct net_device *dev, struct nip_addr *addr)
486 {
487 struct ninet_dev *idev;
488 bool ret = false;
489
490 rcu_read_lock();
491 idev = __nin_dev_get(dev);
492 if (!idev)
493 goto out;
494
495 read_lock_bh(&idev->lock);
496 if (!list_empty(&idev->addr_list)) {
497 struct ninet_ifaddr *ifp;
498
499 list_for_each_entry(ifp, &idev->addr_list, if_list) {
500 if (nip_addr_eq(addr, &ifp->addr)) {
501 ret = true;
502 break;
503 }
504 }
505 }
506 read_unlock_bh(&idev->lock);
507 out:
508 rcu_read_unlock();
509 return ret;
510 }
511
nndisc_rcv_ns(struct sk_buff * skb)512 int nndisc_rcv_ns(struct sk_buff *skb)
513 {
514 struct nnd_msg *msg;
515 u_char *p;
516 u_char *lladdr;
517 struct nip_addr addr = {0};
518 struct neighbour *neigh;
519 struct ethhdr *eth;
520 struct net_device *dev = skb->dev;
521 int err = 0;
522 struct nip_buff nbuf;
523
524 if (!pskb_may_pull(skb, sizeof(struct nnd_msg))) {
525 nip_dbg("invalid ns packet");
526 err = -EFAULT;
527 goto out;
528 }
529
530 msg = (struct nnd_msg *)skb->data;
531 nbuf.data = msg->data;
532 nbuf.remaining_len = skb->len - sizeof(struct nip_icmp_hdr);
533
534 p = decode_nip_addr(&nbuf, &addr);
535 if (!p) {
536 nip_dbg("failure when decode source address");
537 err = -EFAULT;
538 goto out;
539 }
540
541 if (nip_addr_invalid(&addr)) {
542 nip_dbg("icmp hdr addr invalid, bitlen=%u", addr.bitlen);
543 err = -EFAULT;
544 goto out;
545 }
546
547 if (!nip_addr_local(dev, &addr)) {
548 err = -ENXIO;
549 goto out;
550 }
551
552 eth = (struct ethhdr *)skb_mac_header(skb);
553 lladdr = eth->h_source;
554
555 /* checksum parse */
556 if (!nip_get_nndisc_rcv_checksum(skb, nbuf.data)) {
557 nip_dbg("ns ICMP checksum failed, drop the packet");
558 err = -EINVAL;
559 goto out;
560 }
561
562 neigh = __neigh_lookup(&nnd_tbl, &nipcb(skb)->srcaddr, dev, lladdr || !dev->addr_len);
563 if (neigh) {
564 neigh_update(neigh, lladdr, NUD_STALE, NEIGH_UPDATE_F_OVERRIDE, 0);
565 neigh_release(neigh);
566 }
567
568 nndisc_send_na(dev, &nipcb(skb)->srcaddr, &addr);
569 out:
570 kfree_skb(skb);
571 return err;
572 }
573
nndisc_rcv_na(struct sk_buff * skb)574 int nndisc_rcv_na(struct sk_buff *skb)
575 {
576 struct nnd_msg *msg;
577 u_char *p;
578 u_char len;
579 u8 lladdr[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
580 struct net_device *dev = skb->dev;
581 struct neighbour *neigh;
582
583 if (!pskb_may_pull(skb, sizeof(struct nnd_msg))) {
584 nip_dbg("invalid na packet");
585 kfree_skb(skb);
586 return -EINVAL;
587 }
588
589 msg = (struct nnd_msg *)skb->data;
590 p = msg->data;
591 if (skb->len - sizeof(struct nip_icmp_hdr) < sizeof(unsigned char)) {
592 nip_dbg("invalid msg data");
593 kfree_skb(skb);
594 return -EINVAL;
595 }
596 len = *p;
597 if (len > MAX_ADDR_LEN) {
598 nip_dbg("invalid length, drop the packet(len=%u)", len);
599 kfree_skb(skb);
600 return 0;
601 }
602
603 p++;
604 memset(lladdr, 0, ALIGN(MAX_ADDR_LEN, sizeof(unsigned long)));
605 if (skb->len - sizeof(struct nip_icmp_hdr) - sizeof(unsigned char) < len) {
606 nip_dbg("invalid msg data");
607 kfree_skb(skb);
608 return -EINVAL;
609 }
610 memcpy(lladdr, p, len);
611
612 if (!nip_get_nndisc_rcv_checksum(skb, p + len)) {
613 nip_dbg("na ICMP checksum failed, drop the packet");
614 kfree_skb(skb);
615 return 0;
616 }
617
618 neigh = neigh_lookup(&nnd_tbl, &nipcb(skb)->srcaddr, dev);
619 if (neigh) {
620 neigh_update(neigh, lladdr, NUD_REACHABLE, NEIGH_UPDATE_F_OVERRIDE, 0);
621 neigh_release(neigh);
622 kfree_skb(skb);
623 return 0;
624 }
625 kfree_skb(skb);
626 return -EFAULT;
627 }
628
nndisc_rcv(struct sk_buff * skb)629 int nndisc_rcv(struct sk_buff *skb)
630 {
631 int ret = 0;
632 struct nip_icmp_hdr *hdr = nip_icmp_header(skb);
633 u8 type = hdr->nip_icmp_type;
634
635 switch (type) {
636 case NIP_ARP_NS:
637 ret = nndisc_rcv_ns(skb);
638 break;
639 case NIP_ARP_NA:
640 ret = nndisc_rcv_na(skb);
641 break;
642 default:
643 nip_dbg("nd packet type error");
644 }
645
646 return ret;
647 }
648
nndisc_init(void)649 int __init nndisc_init(void)
650 {
651 neigh_table_init(NEIGH_NND_TABLE, &nnd_tbl);
652 return 0;
653 }
654