Deleted Added
full compact
icmp6.c (180968) icmp6.c (181803)
1/*-
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

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

56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
61 */
62
63#include <sys/cdefs.h>
1/*-
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

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

56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
61 */
62
63#include <sys/cdefs.h>
64__FBSDID("$FreeBSD: head/sys/netinet6/icmp6.c 180968 2008-07-29 19:37:16Z rwatson $");
64__FBSDID("$FreeBSD: head/sys/netinet6/icmp6.c 181803 2008-08-17 23:27:27Z bz $");
65
66#include "opt_inet.h"
67#include "opt_inet6.h"
68#include "opt_ipsec.h"
69
70#include <sys/param.h>
71#include <sys/domain.h>
72#include <sys/kernel.h>
73#include <sys/lock.h>
74#include <sys/malloc.h>
75#include <sys/mbuf.h>
76#include <sys/protosw.h>
77#include <sys/signalvar.h>
78#include <sys/socket.h>
79#include <sys/socketvar.h>
80#include <sys/sx.h>
81#include <sys/syslog.h>
82#include <sys/systm.h>
83#include <sys/time.h>
65
66#include "opt_inet.h"
67#include "opt_inet6.h"
68#include "opt_ipsec.h"
69
70#include <sys/param.h>
71#include <sys/domain.h>
72#include <sys/kernel.h>
73#include <sys/lock.h>
74#include <sys/malloc.h>
75#include <sys/mbuf.h>
76#include <sys/protosw.h>
77#include <sys/signalvar.h>
78#include <sys/socket.h>
79#include <sys/socketvar.h>
80#include <sys/sx.h>
81#include <sys/syslog.h>
82#include <sys/systm.h>
83#include <sys/time.h>
84#include <sys/vimage.h>
84
85#include <net/if.h>
86#include <net/if_dl.h>
87#include <net/if_types.h>
88#include <net/route.h>
89
90#include <netinet/in.h>
91#include <netinet/in_pcb.h>

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

235icmp6_error(struct mbuf *m, int type, int code, int param)
236{
237 struct ip6_hdr *oip6, *nip6;
238 struct icmp6_hdr *icmp6;
239 u_int preplen;
240 int off;
241 int nxt;
242
85
86#include <net/if.h>
87#include <net/if_dl.h>
88#include <net/if_types.h>
89#include <net/route.h>
90
91#include <netinet/in.h>
92#include <netinet/in_pcb.h>

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

236icmp6_error(struct mbuf *m, int type, int code, int param)
237{
238 struct ip6_hdr *oip6, *nip6;
239 struct icmp6_hdr *icmp6;
240 u_int preplen;
241 int off;
242 int nxt;
243
243 icmp6stat.icp6s_error++;
244 V_icmp6stat.icp6s_error++;
244
245 /* count per-type-code statistics */
245
246 /* count per-type-code statistics */
246 icmp6_errcount(&icmp6stat.icp6s_outerrhist, type, code);
247 icmp6_errcount(&V_icmp6stat.icp6s_outerrhist, type, code);
247
248#ifdef M_DECRYPTED /*not openbsd*/
249 if (m->m_flags & M_DECRYPTED) {
248
249#ifdef M_DECRYPTED /*not openbsd*/
250 if (m->m_flags & M_DECRYPTED) {
250 icmp6stat.icp6s_canterror++;
251 V_icmp6stat.icp6s_canterror++;
251 goto freeit;
252 }
253#endif
254
255#ifndef PULLDOWN_TEST
256 IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), );
257#else
258 if (m->m_len < sizeof(struct ip6_hdr)) {

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

300
301#ifndef PULLDOWN_TEST
302 IP6_EXTHDR_CHECK(m, 0, off + sizeof(struct icmp6_hdr), );
303 icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
304#else
305 IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off,
306 sizeof(*icp));
307 if (icp == NULL) {
252 goto freeit;
253 }
254#endif
255
256#ifndef PULLDOWN_TEST
257 IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), );
258#else
259 if (m->m_len < sizeof(struct ip6_hdr)) {

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

301
302#ifndef PULLDOWN_TEST
303 IP6_EXTHDR_CHECK(m, 0, off + sizeof(struct icmp6_hdr), );
304 icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
305#else
306 IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off,
307 sizeof(*icp));
308 if (icp == NULL) {
308 icmp6stat.icp6s_tooshort++;
309 V_icmp6stat.icp6s_tooshort++;
309 return;
310 }
311#endif
312 if (icp->icmp6_type < ICMP6_ECHO_REQUEST ||
313 icp->icmp6_type == ND_REDIRECT) {
314 /*
315 * ICMPv6 error
316 * Special case: for redirect (which is
317 * informational) we must not send icmp6 error.
318 */
310 return;
311 }
312#endif
313 if (icp->icmp6_type < ICMP6_ECHO_REQUEST ||
314 icp->icmp6_type == ND_REDIRECT) {
315 /*
316 * ICMPv6 error
317 * Special case: for redirect (which is
318 * informational) we must not send icmp6 error.
319 */
319 icmp6stat.icp6s_canterror++;
320 V_icmp6stat.icp6s_canterror++;
320 goto freeit;
321 } else {
322 /* ICMPv6 informational - send the error */
323 }
324 } else {
325 /* non-ICMPv6 - send the error */
326 }
327
328 oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */
329
330 /* Finally, do rate limitation check. */
331 if (icmp6_ratelimit(&oip6->ip6_src, type, code)) {
321 goto freeit;
322 } else {
323 /* ICMPv6 informational - send the error */
324 }
325 } else {
326 /* non-ICMPv6 - send the error */
327 }
328
329 oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */
330
331 /* Finally, do rate limitation check. */
332 if (icmp6_ratelimit(&oip6->ip6_src, type, code)) {
332 icmp6stat.icp6s_toofreq++;
333 V_icmp6stat.icp6s_toofreq++;
333 goto freeit;
334 }
335
336 /*
337 * OK, ICMP6 can be generated.
338 */
339
340 if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN)

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

365 * icmp6_reflect() is designed to be in the input path.
366 * icmp6_error() can be called from both input and output path,
367 * and if we are in output path rcvif could contain bogus value.
368 * clear m->m_pkthdr.rcvif for safety, we should have enough scope
369 * information in ip header (nip6).
370 */
371 m->m_pkthdr.rcvif = NULL;
372
334 goto freeit;
335 }
336
337 /*
338 * OK, ICMP6 can be generated.
339 */
340
341 if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN)

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

366 * icmp6_reflect() is designed to be in the input path.
367 * icmp6_error() can be called from both input and output path,
368 * and if we are in output path rcvif could contain bogus value.
369 * clear m->m_pkthdr.rcvif for safety, we should have enough scope
370 * information in ip header (nip6).
371 */
372 m->m_pkthdr.rcvif = NULL;
373
373 icmp6stat.icp6s_outhist[type]++;
374 V_icmp6stat.icp6s_outhist[type]++;
374 icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */
375
376 return;
377
378 freeit:
379 /*
380 * If we can't tell whether or not we can generate ICMP6, free it.
381 */

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

403
404 /*
405 * Locate icmp6 structure in mbuf, and check
406 * that not corrupted and of at least minimum length
407 */
408
409 ip6 = mtod(m, struct ip6_hdr *);
410 if (icmp6len < sizeof(struct icmp6_hdr)) {
375 icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */
376
377 return;
378
379 freeit:
380 /*
381 * If we can't tell whether or not we can generate ICMP6, free it.
382 */

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

404
405 /*
406 * Locate icmp6 structure in mbuf, and check
407 * that not corrupted and of at least minimum length
408 */
409
410 ip6 = mtod(m, struct ip6_hdr *);
411 if (icmp6len < sizeof(struct icmp6_hdr)) {
411 icmp6stat.icp6s_tooshort++;
412 V_icmp6stat.icp6s_tooshort++;
412 goto freeit;
413 }
414
415 /*
416 * calculate the checksum
417 */
418#ifndef PULLDOWN_TEST
419 icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
420#else
421 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
422 if (icmp6 == NULL) {
413 goto freeit;
414 }
415
416 /*
417 * calculate the checksum
418 */
419#ifndef PULLDOWN_TEST
420 icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
421#else
422 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
423 if (icmp6 == NULL) {
423 icmp6stat.icp6s_tooshort++;
424 V_icmp6stat.icp6s_tooshort++;
424 return IPPROTO_DONE;
425 }
426#endif
427 code = icmp6->icmp6_code;
428
429 if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) {
430 nd6log((LOG_ERR,
431 "ICMP6 checksum error(%d|%x) %s\n",
432 icmp6->icmp6_type, sum,
433 ip6_sprintf(ip6bufs, &ip6->ip6_src)));
425 return IPPROTO_DONE;
426 }
427#endif
428 code = icmp6->icmp6_code;
429
430 if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) {
431 nd6log((LOG_ERR,
432 "ICMP6 checksum error(%d|%x) %s\n",
433 icmp6->icmp6_type, sum,
434 ip6_sprintf(ip6bufs, &ip6->ip6_src)));
434 icmp6stat.icp6s_checksum++;
435 V_icmp6stat.icp6s_checksum++;
435 goto freeit;
436 }
437
438 if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) {
439 /*
440 * Deliver very specific ICMP6 type only.
441 * This is important to deliver TOOBIG. Otherwise PMTUD
442 * will not work.
443 */
444 switch (icmp6->icmp6_type) {
445 case ICMP6_DST_UNREACH:
446 case ICMP6_PACKET_TOO_BIG:
447 case ICMP6_TIME_EXCEEDED:
448 break;
449 default:
450 goto freeit;
451 }
452 }
453
436 goto freeit;
437 }
438
439 if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) {
440 /*
441 * Deliver very specific ICMP6 type only.
442 * This is important to deliver TOOBIG. Otherwise PMTUD
443 * will not work.
444 */
445 switch (icmp6->icmp6_type) {
446 case ICMP6_DST_UNREACH:
447 case ICMP6_PACKET_TOO_BIG:
448 case ICMP6_TIME_EXCEEDED:
449 break;
450 default:
451 goto freeit;
452 }
453 }
454
454 icmp6stat.icp6s_inhist[icmp6->icmp6_type]++;
455 V_icmp6stat.icp6s_inhist[icmp6->icmp6_type]++;
455 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_msg);
456 if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK)
457 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);
458
459 switch (icmp6->icmp6_type) {
460 case ICMP6_DST_UNREACH:
461 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_dstunreach);
462 switch (code) {

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

580 nip6 = mtod(n, struct ip6_hdr *);
581 IP6_EXTHDR_GET(nicmp6, struct icmp6_hdr *, n, off,
582 sizeof(*nicmp6));
583 noff = off;
584 }
585 nicmp6->icmp6_type = ICMP6_ECHO_REPLY;
586 nicmp6->icmp6_code = 0;
587 if (n) {
456 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_msg);
457 if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK)
458 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);
459
460 switch (icmp6->icmp6_type) {
461 case ICMP6_DST_UNREACH:
462 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_dstunreach);
463 switch (code) {

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

581 nip6 = mtod(n, struct ip6_hdr *);
582 IP6_EXTHDR_GET(nicmp6, struct icmp6_hdr *, n, off,
583 sizeof(*nicmp6));
584 noff = off;
585 }
586 nicmp6->icmp6_type = ICMP6_ECHO_REPLY;
587 nicmp6->icmp6_code = 0;
588 if (n) {
588 icmp6stat.icp6s_reflect++;
589 icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]++;
589 V_icmp6stat.icp6s_reflect++;
590 V_icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]++;
590 icmp6_reflect(n, noff);
591 }
592 break;
593
594 case ICMP6_ECHO_REPLY:
595 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echoreply);
596 if (code != 0)
597 goto badcode;

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

626 /* XXX: these two are experimental. not officially defined. */
627 /* XXX: per-interface statistics? */
628 break; /* just pass it to applications */
629
630 case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */
631 {
632 enum { WRU, FQDN } mode;
633
591 icmp6_reflect(n, noff);
592 }
593 break;
594
595 case ICMP6_ECHO_REPLY:
596 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echoreply);
597 if (code != 0)
598 goto badcode;

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

627 /* XXX: these two are experimental. not officially defined. */
628 /* XXX: per-interface statistics? */
629 break; /* just pass it to applications */
630
631 case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */
632 {
633 enum { WRU, FQDN } mode;
634
634 if (!icmp6_nodeinfo)
635 if (!V_icmp6_nodeinfo)
635 break;
636
637 if (icmp6len == sizeof(struct icmp6_hdr) + 4)
638 mode = WRU;
639 else if (icmp6len >= sizeof(struct icmp6_nodeinfo))
640 mode = FQDN;
641 else
642 goto badlen;
643
636 break;
637
638 if (icmp6len == sizeof(struct icmp6_hdr) + 4)
639 mode = WRU;
640 else if (icmp6len >= sizeof(struct icmp6_nodeinfo))
641 mode = FQDN;
642 else
643 goto badlen;
644
644#define hostnamelen strlen(hostname)
645#define hostnamelen strlen(V_hostname)
645 if (mode == FQDN) {
646#ifndef PULLDOWN_TEST
647 IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_nodeinfo),
648 IPPROTO_DONE);
649#endif
650 n = m_copy(m, 0, M_COPYALL);
651 if (n)
652 n = ni6_input(n, off);
653 /* XXX meaningless if n == NULL */
654 noff = sizeof(struct ip6_hdr);
655 } else {
656 u_char *p;
657 int maxlen, maxhlen;
658
659 /*
660 * XXX: this combination of flags is pointless,
661 * but should we keep this for compatibility?
662 */
646 if (mode == FQDN) {
647#ifndef PULLDOWN_TEST
648 IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_nodeinfo),
649 IPPROTO_DONE);
650#endif
651 n = m_copy(m, 0, M_COPYALL);
652 if (n)
653 n = ni6_input(n, off);
654 /* XXX meaningless if n == NULL */
655 noff = sizeof(struct ip6_hdr);
656 } else {
657 u_char *p;
658 int maxlen, maxhlen;
659
660 /*
661 * XXX: this combination of flags is pointless,
662 * but should we keep this for compatibility?
663 */
663 if ((icmp6_nodeinfo & 5) != 5)
664 if ((V_icmp6_nodeinfo & 5) != 5)
664 break;
665
666 if (code != 0)
667 goto badcode;
668 maxlen = sizeof(*nip6) + sizeof(*nicmp6) + 4;
669 if (maxlen >= MCLBYTES) {
670 /* Give up remote */
671 break;

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

703 * Copy IPv6 and ICMPv6 only.
704 */
705 nip6 = mtod(n, struct ip6_hdr *);
706 bcopy(ip6, nip6, sizeof(struct ip6_hdr));
707 nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
708 bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
709 p = (u_char *)(nicmp6 + 1);
710 bzero(p, 4);
665 break;
666
667 if (code != 0)
668 goto badcode;
669 maxlen = sizeof(*nip6) + sizeof(*nicmp6) + 4;
670 if (maxlen >= MCLBYTES) {
671 /* Give up remote */
672 break;

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

704 * Copy IPv6 and ICMPv6 only.
705 */
706 nip6 = mtod(n, struct ip6_hdr *);
707 bcopy(ip6, nip6, sizeof(struct ip6_hdr));
708 nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
709 bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
710 p = (u_char *)(nicmp6 + 1);
711 bzero(p, 4);
711 bcopy(hostname, p + 4, maxhlen); /* meaningless TTL */
712 bcopy(V_hostname, p + 4, maxhlen); /* meaningless TTL */
712 mtx_unlock(&hostname_mtx);
713 noff = sizeof(struct ip6_hdr);
714 n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
715 sizeof(struct icmp6_hdr) + 4 + maxhlen;
716 nicmp6->icmp6_type = ICMP6_WRUREPLY;
717 nicmp6->icmp6_code = 0;
718 }
719#undef hostnamelen
720 if (n) {
713 mtx_unlock(&hostname_mtx);
714 noff = sizeof(struct ip6_hdr);
715 n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
716 sizeof(struct icmp6_hdr) + 4 + maxhlen;
717 nicmp6->icmp6_type = ICMP6_WRUREPLY;
718 nicmp6->icmp6_code = 0;
719 }
720#undef hostnamelen
721 if (n) {
721 icmp6stat.icp6s_reflect++;
722 icmp6stat.icp6s_outhist[ICMP6_WRUREPLY]++;
722 V_icmp6stat.icp6s_reflect++;
723 V_icmp6stat.icp6s_outhist[ICMP6_WRUREPLY]++;
723 icmp6_reflect(n, noff);
724 }
725 break;
726 }
727
728 case ICMP6_WRUREPLY:
729 if (code != 0)
730 goto badcode;

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

835 deliver:
836 if (icmp6_notify_error(&m, off, icmp6len, code)) {
837 /* In this case, m should've been freed. */
838 return (IPPROTO_DONE);
839 }
840 break;
841
842 badcode:
724 icmp6_reflect(n, noff);
725 }
726 break;
727 }
728
729 case ICMP6_WRUREPLY:
730 if (code != 0)
731 goto badcode;

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

836 deliver:
837 if (icmp6_notify_error(&m, off, icmp6len, code)) {
838 /* In this case, m should've been freed. */
839 return (IPPROTO_DONE);
840 }
841 break;
842
843 badcode:
843 icmp6stat.icp6s_badcode++;
844 V_icmp6stat.icp6s_badcode++;
844 break;
845
846 badlen:
845 break;
846
847 badlen:
847 icmp6stat.icp6s_badlen++;
848 V_icmp6stat.icp6s_badlen++;
848 break;
849 }
850
851 /* deliver the packet to appropriate sockets */
852 icmp6_rip6_input(&m, *offp);
853
854 return IPPROTO_DONE;
855

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

863{
864 struct mbuf *m = *mp;
865 struct icmp6_hdr *icmp6;
866 struct ip6_hdr *eip6;
867 u_int32_t notifymtu;
868 struct sockaddr_in6 icmp6src, icmp6dst;
869
870 if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
849 break;
850 }
851
852 /* deliver the packet to appropriate sockets */
853 icmp6_rip6_input(&m, *offp);
854
855 return IPPROTO_DONE;
856

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

864{
865 struct mbuf *m = *mp;
866 struct icmp6_hdr *icmp6;
867 struct ip6_hdr *eip6;
868 u_int32_t notifymtu;
869 struct sockaddr_in6 icmp6src, icmp6dst;
870
871 if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
871 icmp6stat.icp6s_tooshort++;
872 V_icmp6stat.icp6s_tooshort++;
872 goto freeit;
873 }
874#ifndef PULLDOWN_TEST
875 IP6_EXTHDR_CHECK(m, off,
876 sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr), -1);
877 icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
878#else
879 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
880 sizeof(*icmp6) + sizeof(struct ip6_hdr));
881 if (icmp6 == NULL) {
873 goto freeit;
874 }
875#ifndef PULLDOWN_TEST
876 IP6_EXTHDR_CHECK(m, off,
877 sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr), -1);
878 icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
879#else
880 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
881 sizeof(*icmp6) + sizeof(struct ip6_hdr));
882 if (icmp6 == NULL) {
882 icmp6stat.icp6s_tooshort++;
883 V_icmp6stat.icp6s_tooshort++;
883 return (-1);
884 }
885#endif
886 eip6 = (struct ip6_hdr *)(icmp6 + 1);
887
888 /* Detect the upper level protocol */
889 {
890 void (*ctlfunc)(int, struct sockaddr *, void *);

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

909#ifndef PULLDOWN_TEST
910 IP6_EXTHDR_CHECK(m, 0,
911 eoff + sizeof(struct ip6_ext), -1);
912 eh = (struct ip6_ext *)(mtod(m, caddr_t) + eoff);
913#else
914 IP6_EXTHDR_GET(eh, struct ip6_ext *, m,
915 eoff, sizeof(*eh));
916 if (eh == NULL) {
884 return (-1);
885 }
886#endif
887 eip6 = (struct ip6_hdr *)(icmp6 + 1);
888
889 /* Detect the upper level protocol */
890 {
891 void (*ctlfunc)(int, struct sockaddr *, void *);

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

910#ifndef PULLDOWN_TEST
911 IP6_EXTHDR_CHECK(m, 0,
912 eoff + sizeof(struct ip6_ext), -1);
913 eh = (struct ip6_ext *)(mtod(m, caddr_t) + eoff);
914#else
915 IP6_EXTHDR_GET(eh, struct ip6_ext *, m,
916 eoff, sizeof(*eh));
917 if (eh == NULL) {
917 icmp6stat.icp6s_tooshort++;
918 V_icmp6stat.icp6s_tooshort++;
918 return (-1);
919 }
920#endif
921
922 if (nxt == IPPROTO_AH)
923 eoff += (eh->ip6e_len + 2) << 2;
924 else
925 eoff += (eh->ip6e_len + 1) << 3;

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

937#ifndef PULLDOWN_TEST
938 IP6_EXTHDR_CHECK(m, 0, eoff + sizeof(*rth), -1);
939 rth = (struct ip6_rthdr *)
940 (mtod(m, caddr_t) + eoff);
941#else
942 IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m,
943 eoff, sizeof(*rth));
944 if (rth == NULL) {
919 return (-1);
920 }
921#endif
922
923 if (nxt == IPPROTO_AH)
924 eoff += (eh->ip6e_len + 2) << 2;
925 else
926 eoff += (eh->ip6e_len + 1) << 3;

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

938#ifndef PULLDOWN_TEST
939 IP6_EXTHDR_CHECK(m, 0, eoff + sizeof(*rth), -1);
940 rth = (struct ip6_rthdr *)
941 (mtod(m, caddr_t) + eoff);
942#else
943 IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m,
944 eoff, sizeof(*rth));
945 if (rth == NULL) {
945 icmp6stat.icp6s_tooshort++;
946 V_icmp6stat.icp6s_tooshort++;
946 return (-1);
947 }
948#endif
949 rthlen = (rth->ip6r_len + 1) << 3;
950 /*
951 * XXX: currently there is no
952 * officially defined type other
953 * than type-0.

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

963 IP6_EXTHDR_CHECK(m, 0, eoff + rthlen, -1);
964 rth0 = (struct ip6_rthdr0 *)
965 (mtod(m, caddr_t) + eoff);
966#else
967 IP6_EXTHDR_GET(rth0,
968 struct ip6_rthdr0 *, m,
969 eoff, rthlen);
970 if (rth0 == NULL) {
947 return (-1);
948 }
949#endif
950 rthlen = (rth->ip6r_len + 1) << 3;
951 /*
952 * XXX: currently there is no
953 * officially defined type other
954 * than type-0.

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

964 IP6_EXTHDR_CHECK(m, 0, eoff + rthlen, -1);
965 rth0 = (struct ip6_rthdr0 *)
966 (mtod(m, caddr_t) + eoff);
967#else
968 IP6_EXTHDR_GET(rth0,
969 struct ip6_rthdr0 *, m,
970 eoff, rthlen);
971 if (rth0 == NULL) {
971 icmp6stat.icp6s_tooshort++;
972 V_icmp6stat.icp6s_tooshort++;
972 return (-1);
973 }
974#endif
975 /* just ignore a bogus header */
976 if ((rth0->ip6r0_len % 2) == 0 &&
977 (hops = rth0->ip6r0_len/2))
978 finaldst = (struct in6_addr *)(rth0 + 1) + (hops - 1);
979 }

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

985 IP6_EXTHDR_CHECK(m, 0, eoff +
986 sizeof(struct ip6_frag), -1);
987 fh = (struct ip6_frag *)(mtod(m, caddr_t) +
988 eoff);
989#else
990 IP6_EXTHDR_GET(fh, struct ip6_frag *, m,
991 eoff, sizeof(*fh));
992 if (fh == NULL) {
973 return (-1);
974 }
975#endif
976 /* just ignore a bogus header */
977 if ((rth0->ip6r0_len % 2) == 0 &&
978 (hops = rth0->ip6r0_len/2))
979 finaldst = (struct in6_addr *)(rth0 + 1) + (hops - 1);
980 }

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

986 IP6_EXTHDR_CHECK(m, 0, eoff +
987 sizeof(struct ip6_frag), -1);
988 fh = (struct ip6_frag *)(mtod(m, caddr_t) +
989 eoff);
990#else
991 IP6_EXTHDR_GET(fh, struct ip6_frag *, m,
992 eoff, sizeof(*fh));
993 if (fh == NULL) {
993 icmp6stat.icp6s_tooshort++;
994 V_icmp6stat.icp6s_tooshort++;
994 return (-1);
995 }
996#endif
997 /*
998 * Data after a fragment header is meaningless
999 * unless it is the first fragment, but
1000 * we'll go to the notify label for path MTU
1001 * discovery.

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

1020 }
1021 notify:
1022#ifndef PULLDOWN_TEST
1023 icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
1024#else
1025 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
1026 sizeof(*icmp6) + sizeof(struct ip6_hdr));
1027 if (icmp6 == NULL) {
995 return (-1);
996 }
997#endif
998 /*
999 * Data after a fragment header is meaningless
1000 * unless it is the first fragment, but
1001 * we'll go to the notify label for path MTU
1002 * discovery.

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

1021 }
1022 notify:
1023#ifndef PULLDOWN_TEST
1024 icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
1025#else
1026 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
1027 sizeof(*icmp6) + sizeof(struct ip6_hdr));
1028 if (icmp6 == NULL) {
1028 icmp6stat.icp6s_tooshort++;
1029 V_icmp6stat.icp6s_tooshort++;
1029 return (-1);
1030 }
1031#endif
1032
1033 /*
1034 * retrieve parameters from the inner IPv6 header, and convert
1035 * them into sockaddr structures.
1036 * XXX: there is no guarantee that the source or destination

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

1124 bzero(&inc, sizeof(inc));
1125 inc.inc_flags = 1; /* IPv6 */
1126 inc.inc6_faddr = *dst;
1127 if (in6_setscope(&inc.inc6_faddr, m->m_pkthdr.rcvif, NULL))
1128 return;
1129
1130 if (mtu < tcp_maxmtu6(&inc, NULL)) {
1131 tcp_hc_updatemtu(&inc, mtu);
1030 return (-1);
1031 }
1032#endif
1033
1034 /*
1035 * retrieve parameters from the inner IPv6 header, and convert
1036 * them into sockaddr structures.
1037 * XXX: there is no guarantee that the source or destination

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

1125 bzero(&inc, sizeof(inc));
1126 inc.inc_flags = 1; /* IPv6 */
1127 inc.inc6_faddr = *dst;
1128 if (in6_setscope(&inc.inc6_faddr, m->m_pkthdr.rcvif, NULL))
1129 return;
1130
1131 if (mtu < tcp_maxmtu6(&inc, NULL)) {
1132 tcp_hc_updatemtu(&inc, mtu);
1132 icmp6stat.icp6s_pmtuchg++;
1133 V_icmp6stat.icp6s_pmtuchg++;
1133 }
1134}
1135
1136/*
1137 * Process a Node Information Query packet, based on
1138 * draft-ietf-ipngwg-icmp-name-lookups-07.
1139 *
1140 * Spec incompatibilities:
1141 * - IPv6 Subject address handling
1142 * - IPv4 Subject address handling support missing
1143 * - Proxy reply (answer even if it's not for me)
1144 * - joins NI group address at in6_ifattach() time only, does not cope
1145 * with hostname changes by sethostname(3)
1146 */
1134 }
1135}
1136
1137/*
1138 * Process a Node Information Query packet, based on
1139 * draft-ietf-ipngwg-icmp-name-lookups-07.
1140 *
1141 * Spec incompatibilities:
1142 * - IPv6 Subject address handling
1143 * - IPv4 Subject address handling support missing
1144 * - Proxy reply (answer even if it's not for me)
1145 * - joins NI group address at in6_ifattach() time only, does not cope
1146 * with hostname changes by sethostname(3)
1147 */
1147#define hostnamelen strlen(hostname)
1148#define hostnamelen strlen(V_hostname)
1148static struct mbuf *
1149ni6_input(struct mbuf *m, int off)
1150{
1151 struct icmp6_nodeinfo *ni6, *nni6;
1152 struct mbuf *n = NULL;
1153 u_int16_t qtype;
1154 int subjlen;
1155 int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);

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

1181 * - it's not very clear what "refuse" means; this implementation
1182 * simply drops it.
1183 * - it's not very easy to identify global-scope (unicast) addresses
1184 * since there are many prefixes for them. It should be safer
1185 * and in practice sufficient to check "all" but loopback and
1186 * link-local (note that site-local unicast was deprecated and
1187 * ULA is defined as global scope-wise)
1188 */
1149static struct mbuf *
1150ni6_input(struct mbuf *m, int off)
1151{
1152 struct icmp6_nodeinfo *ni6, *nni6;
1153 struct mbuf *n = NULL;
1154 u_int16_t qtype;
1155 int subjlen;
1156 int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);

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

1182 * - it's not very clear what "refuse" means; this implementation
1183 * simply drops it.
1184 * - it's not very easy to identify global-scope (unicast) addresses
1185 * since there are many prefixes for them. It should be safer
1186 * and in practice sufficient to check "all" but loopback and
1187 * link-local (note that site-local unicast was deprecated and
1188 * ULA is defined as global scope-wise)
1189 */
1189 if ((icmp6_nodeinfo & ICMP6_NODEINFO_GLOBALOK) == 0 &&
1190 if ((V_icmp6_nodeinfo & ICMP6_NODEINFO_GLOBALOK) == 0 &&
1190 !IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) &&
1191 !IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src))
1192 goto bad;
1193
1194 /*
1195 * Validate IPv6 destination address.
1196 *
1197 * The Responder must discard the Query without further processing

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

1203 if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
1204 goto bad;
1205 /* else it's a link-local multicast, fine */
1206 } else { /* unicast or anycast */
1207 if ((ia6 = ip6_getdstifaddr(m)) == NULL)
1208 goto bad; /* XXX impossible */
1209
1210 if ((ia6->ia6_flags & IN6_IFF_TEMPORARY) &&
1191 !IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) &&
1192 !IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src))
1193 goto bad;
1194
1195 /*
1196 * Validate IPv6 destination address.
1197 *
1198 * The Responder must discard the Query without further processing

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

1204 if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
1205 goto bad;
1206 /* else it's a link-local multicast, fine */
1207 } else { /* unicast or anycast */
1208 if ((ia6 = ip6_getdstifaddr(m)) == NULL)
1209 goto bad; /* XXX impossible */
1210
1211 if ((ia6->ia6_flags & IN6_IFF_TEMPORARY) &&
1211 !(icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK)) {
1212 !(V_icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK)) {
1212 nd6log((LOG_DEBUG, "ni6_input: ignore node info to "
1213 "a temporary address in %s:%d",
1214 __FILE__, __LINE__));
1215 goto bad;
1216 }
1217 }
1218
1219 /* validate query Subject field. */

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

1294 * - we are not sure if the node has FQDN as
1295 * hostname (returned by gethostname(3)).
1296 * - the code does wildcard match for truncated names.
1297 * however, we are not sure if we want to perform
1298 * wildcard match, if gethostname(3) side has
1299 * truncated hostname.
1300 */
1301 mtx_lock(&hostname_mtx);
1213 nd6log((LOG_DEBUG, "ni6_input: ignore node info to "
1214 "a temporary address in %s:%d",
1215 __FILE__, __LINE__));
1216 goto bad;
1217 }
1218 }
1219
1220 /* validate query Subject field. */

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

1295 * - we are not sure if the node has FQDN as
1296 * hostname (returned by gethostname(3)).
1297 * - the code does wildcard match for truncated names.
1298 * however, we are not sure if we want to perform
1299 * wildcard match, if gethostname(3) side has
1300 * truncated hostname.
1301 */
1302 mtx_lock(&hostname_mtx);
1302 n = ni6_nametodns(hostname, hostnamelen, 0);
1303 n = ni6_nametodns(V_hostname, hostnamelen, 0);
1303 mtx_unlock(&hostname_mtx);
1304 if (!n || n->m_next || n->m_len == 0)
1305 goto bad;
1306 IP6_EXTHDR_GET(subj, char *, m,
1307 off + sizeof(struct icmp6_nodeinfo), subjlen);
1308 if (subj == NULL)
1309 goto bad;
1310 if (!ni6_dnsmatch(subj, subjlen, mtod(n, const char *),

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

1320 goto bad;
1321 }
1322 break;
1323 }
1324
1325 /* refuse based on configuration. XXX ICMP6_NI_REFUSED? */
1326 switch (qtype) {
1327 case NI_QTYPE_FQDN:
1304 mtx_unlock(&hostname_mtx);
1305 if (!n || n->m_next || n->m_len == 0)
1306 goto bad;
1307 IP6_EXTHDR_GET(subj, char *, m,
1308 off + sizeof(struct icmp6_nodeinfo), subjlen);
1309 if (subj == NULL)
1310 goto bad;
1311 if (!ni6_dnsmatch(subj, subjlen, mtod(n, const char *),

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

1321 goto bad;
1322 }
1323 break;
1324 }
1325
1326 /* refuse based on configuration. XXX ICMP6_NI_REFUSED? */
1327 switch (qtype) {
1328 case NI_QTYPE_FQDN:
1328 if ((icmp6_nodeinfo & ICMP6_NODEINFO_FQDNOK) == 0)
1329 if ((V_icmp6_nodeinfo & ICMP6_NODEINFO_FQDNOK) == 0)
1329 goto bad;
1330 break;
1331 case NI_QTYPE_NODEADDR:
1332 case NI_QTYPE_IPV4ADDR:
1330 goto bad;
1331 break;
1332 case NI_QTYPE_NODEADDR:
1333 case NI_QTYPE_IPV4ADDR:
1333 if ((icmp6_nodeinfo & ICMP6_NODEINFO_NODEADDROK) == 0)
1334 if ((V_icmp6_nodeinfo & ICMP6_NODEINFO_NODEADDROK) == 0)
1334 goto bad;
1335 break;
1336 }
1337
1338 /* guess reply length */
1339 switch (qtype) {
1340 case NI_QTYPE_NOOP:
1341 break; /* no reply data */

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

1420 fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) +
1421 sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo));
1422 nni6->ni_flags = 0; /* XXX: meaningless TTL */
1423 fqdn->ni_fqdn_ttl = 0; /* ditto. */
1424 /*
1425 * XXX do we really have FQDN in variable "hostname"?
1426 */
1427 mtx_lock(&hostname_mtx);
1335 goto bad;
1336 break;
1337 }
1338
1339 /* guess reply length */
1340 switch (qtype) {
1341 case NI_QTYPE_NOOP:
1342 break; /* no reply data */

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

1421 fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) +
1422 sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo));
1423 nni6->ni_flags = 0; /* XXX: meaningless TTL */
1424 fqdn->ni_fqdn_ttl = 0; /* ditto. */
1425 /*
1426 * XXX do we really have FQDN in variable "hostname"?
1427 */
1428 mtx_lock(&hostname_mtx);
1428 n->m_next = ni6_nametodns(hostname, hostnamelen, oldfqdn);
1429 n->m_next = ni6_nametodns(V_hostname, hostnamelen, oldfqdn);
1429 mtx_unlock(&hostname_mtx);
1430 if (n->m_next == NULL)
1431 goto bad;
1432 /* XXX we assume that n->m_next is not a chain */
1433 if (n->m_next->m_next != NULL)
1434 goto bad;
1435 n->m_pkthdr.len += n->m_next->m_len;
1436 break;

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

1650 * XXX: we only support IPv6 subject address for
1651 * this Qtype.
1652 */
1653 return (0);
1654 }
1655 }
1656
1657 IFNET_RLOCK();
1430 mtx_unlock(&hostname_mtx);
1431 if (n->m_next == NULL)
1432 goto bad;
1433 /* XXX we assume that n->m_next is not a chain */
1434 if (n->m_next->m_next != NULL)
1435 goto bad;
1436 n->m_pkthdr.len += n->m_next->m_len;
1437 break;

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

1651 * XXX: we only support IPv6 subject address for
1652 * this Qtype.
1653 */
1654 return (0);
1655 }
1656 }
1657
1658 IFNET_RLOCK();
1658 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
1659 for (ifp = TAILQ_FIRST(&V_ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
1659 addrsofif = 0;
1660 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1661 if (ifa->ifa_addr->sa_family != AF_INET6)
1662 continue;
1663 ifa6 = (struct in6_ifaddr *)ifa;
1664
1665 if ((niflags & NI_NODEADDR_FLAG_ALL) == 0 &&
1666 IN6_ARE_ADDR_EQUAL(subj, &ifa6->ia_addr.sin6_addr))

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

1697 /*
1698 * check if anycast is okay.
1699 * XXX: just experimental. not in the spec.
1700 */
1701 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
1702 (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)
1703 continue; /* we need only unicast addresses */
1704 if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
1660 addrsofif = 0;
1661 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1662 if (ifa->ifa_addr->sa_family != AF_INET6)
1663 continue;
1664 ifa6 = (struct in6_ifaddr *)ifa;
1665
1666 if ((niflags & NI_NODEADDR_FLAG_ALL) == 0 &&
1667 IN6_ARE_ADDR_EQUAL(subj, &ifa6->ia_addr.sin6_addr))

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

1698 /*
1699 * check if anycast is okay.
1700 * XXX: just experimental. not in the spec.
1701 */
1702 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
1703 (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)
1704 continue; /* we need only unicast addresses */
1705 if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
1705 (icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
1706 (V_icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
1706 continue;
1707 }
1708 addrsofif++; /* count the address */
1709 }
1710 if (iffound) {
1711 *ifpp = ifp;
1712 IFNET_RUNLOCK();
1713 return (addrsofif);

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

1719
1720 return (addrs);
1721}
1722
1723static int
1724ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
1725 struct ifnet *ifp0, int resid)
1726{
1707 continue;
1708 }
1709 addrsofif++; /* count the address */
1710 }
1711 if (iffound) {
1712 *ifpp = ifp;
1713 IFNET_RUNLOCK();
1714 return (addrsofif);

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

1720
1721 return (addrs);
1722}
1723
1724static int
1725ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
1726 struct ifnet *ifp0, int resid)
1727{
1727 struct ifnet *ifp = ifp0 ? ifp0 : TAILQ_FIRST(&ifnet);
1728 struct ifnet *ifp = ifp0 ? ifp0 : TAILQ_FIRST(&V_ifnet);
1728 struct in6_ifaddr *ifa6;
1729 struct ifaddr *ifa;
1730 struct ifnet *ifp_dep = NULL;
1731 int copied = 0, allow_deprecated = 0;
1732 u_char *cp = (u_char *)(nni6 + 1);
1733 int niflags = ni6->ni_flags;
1734 u_int32_t ltime;
1735

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

1783 /*
1784 * check if anycast is okay.
1785 * XXX: just experimental. not in the spec.
1786 */
1787 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
1788 (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)
1789 continue;
1790 if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
1729 struct in6_ifaddr *ifa6;
1730 struct ifaddr *ifa;
1731 struct ifnet *ifp_dep = NULL;
1732 int copied = 0, allow_deprecated = 0;
1733 u_char *cp = (u_char *)(nni6 + 1);
1734 int niflags = ni6->ni_flags;
1735 u_int32_t ltime;
1736

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

1784 /*
1785 * check if anycast is okay.
1786 * XXX: just experimental. not in the spec.
1787 */
1788 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
1789 (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)
1790 continue;
1791 if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
1791 (icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
1792 (V_icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) {
1792 continue;
1793 }
1794
1795 /* now we can copy the address */
1796 if (resid < sizeof(struct in6_addr) +
1797 sizeof(u_int32_t)) {
1798 /*
1799 * We give up much more copy.

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

1890 fromsa.sin6_family = AF_INET6;
1891 fromsa.sin6_len = sizeof(struct sockaddr_in6);
1892 fromsa.sin6_addr = ip6->ip6_src;
1893 if (sa6_recoverscope(&fromsa)) {
1894 m_freem(m);
1895 return (IPPROTO_DONE);
1896 }
1897
1793 continue;
1794 }
1795
1796 /* now we can copy the address */
1797 if (resid < sizeof(struct in6_addr) +
1798 sizeof(u_int32_t)) {
1799 /*
1800 * We give up much more copy.

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

1891 fromsa.sin6_family = AF_INET6;
1892 fromsa.sin6_len = sizeof(struct sockaddr_in6);
1893 fromsa.sin6_addr = ip6->ip6_src;
1894 if (sa6_recoverscope(&fromsa)) {
1895 m_freem(m);
1896 return (IPPROTO_DONE);
1897 }
1898
1898 INP_INFO_RLOCK(&ripcbinfo);
1899 LIST_FOREACH(in6p, &ripcb, inp_list) {
1899 INP_INFO_RLOCK(&V_ripcbinfo);
1900 LIST_FOREACH(in6p, &V_ripcb, inp_list) {
1900 if ((in6p->inp_vflag & INP_IPV6) == 0)
1901 continue;
1902 if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6)
1903 continue;
1904 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
1905 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
1906 continue;
1907 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&

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

1968 } else
1969 sorwakeup_locked(last->in6p_socket);
1970 opts = NULL;
1971 }
1972 INP_RUNLOCK(last);
1973 }
1974 last = in6p;
1975 }
1901 if ((in6p->inp_vflag & INP_IPV6) == 0)
1902 continue;
1903 if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6)
1904 continue;
1905 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
1906 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
1907 continue;
1908 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&

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

1969 } else
1970 sorwakeup_locked(last->in6p_socket);
1971 opts = NULL;
1972 }
1973 INP_RUNLOCK(last);
1974 }
1975 last = in6p;
1976 }
1976 INP_INFO_RUNLOCK(&ripcbinfo);
1977 INP_INFO_RUNLOCK(&V_ripcbinfo);
1977 if (last) {
1978 if (last->in6p_flags & IN6P_CONTROLOPTS)
1979 ip6_savecontrol(last, m, &opts);
1980 /* strip intermediate headers */
1981 m_adj(m, off);
1982
1983 /* avoid using mbuf clusters if possible (see above) */
1984 if ((m->m_flags & M_EXT) && m->m_next == NULL &&

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

2006 if (opts)
2007 m_freem(opts);
2008 SOCKBUF_UNLOCK(&last->in6p_socket->so_rcv);
2009 } else
2010 sorwakeup_locked(last->in6p_socket);
2011 INP_RUNLOCK(last);
2012 } else {
2013 m_freem(m);
1978 if (last) {
1979 if (last->in6p_flags & IN6P_CONTROLOPTS)
1980 ip6_savecontrol(last, m, &opts);
1981 /* strip intermediate headers */
1982 m_adj(m, off);
1983
1984 /* avoid using mbuf clusters if possible (see above) */
1985 if ((m->m_flags & M_EXT) && m->m_next == NULL &&

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

2007 if (opts)
2008 m_freem(opts);
2009 SOCKBUF_UNLOCK(&last->in6p_socket->so_rcv);
2010 } else
2011 sorwakeup_locked(last->in6p_socket);
2012 INP_RUNLOCK(last);
2013 } else {
2014 m_freem(m);
2014 ip6stat.ip6s_delivered--;
2015 V_ip6stat.ip6s_delivered--;
2015 }
2016 return IPPROTO_DONE;
2017}
2018
2019/*
2020 * Reflect the ip6 packet back to the source.
2021 * OFF points to the icmp6 header, counted from the top of the mbuf.
2022 */

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

2150 ip6->ip6_vfc |= IPV6_VERSION;
2151 ip6->ip6_nxt = IPPROTO_ICMPV6;
2152 if (outif)
2153 ip6->ip6_hlim = ND_IFINFO(outif)->chlim;
2154 else if (m->m_pkthdr.rcvif) {
2155 /* XXX: This may not be the outgoing interface */
2156 ip6->ip6_hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
2157 } else
2016 }
2017 return IPPROTO_DONE;
2018}
2019
2020/*
2021 * Reflect the ip6 packet back to the source.
2022 * OFF points to the icmp6 header, counted from the top of the mbuf.
2023 */

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

2151 ip6->ip6_vfc |= IPV6_VERSION;
2152 ip6->ip6_nxt = IPPROTO_ICMPV6;
2153 if (outif)
2154 ip6->ip6_hlim = ND_IFINFO(outif)->chlim;
2155 else if (m->m_pkthdr.rcvif) {
2156 /* XXX: This may not be the outgoing interface */
2157 ip6->ip6_hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
2158 } else
2158 ip6->ip6_hlim = ip6_defhlim;
2159 ip6->ip6_hlim = V_ip6_defhlim;
2159
2160 icmp6->icmp6_cksum = 0;
2161 icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
2162 sizeof(struct ip6_hdr), plen);
2163
2164 /*
2165 * XXX option handling
2166 */

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

2223 return;
2224
2225 ifp = m->m_pkthdr.rcvif;
2226
2227 if (!ifp)
2228 return;
2229
2230 /* XXX if we are router, we don't update route by icmp6 redirect */
2160
2161 icmp6->icmp6_cksum = 0;
2162 icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
2163 sizeof(struct ip6_hdr), plen);
2164
2165 /*
2166 * XXX option handling
2167 */

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

2224 return;
2225
2226 ifp = m->m_pkthdr.rcvif;
2227
2228 if (!ifp)
2229 return;
2230
2231 /* XXX if we are router, we don't update route by icmp6 redirect */
2231 if (ip6_forwarding)
2232 if (V_ip6_forwarding)
2232 goto freeit;
2233 goto freeit;
2233 if (!icmp6_rediraccept)
2234 if (!V_icmp6_rediraccept)
2234 goto freeit;
2235
2236#ifndef PULLDOWN_TEST
2237 IP6_EXTHDR_CHECK(m, off, icmp6len,);
2238 nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off);
2239#else
2240 IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len);
2241 if (nd_rd == NULL) {
2235 goto freeit;
2236
2237#ifndef PULLDOWN_TEST
2238 IP6_EXTHDR_CHECK(m, off, icmp6len,);
2239 nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off);
2240#else
2241 IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len);
2242 if (nd_rd == NULL) {
2242 icmp6stat.icp6s_tooshort++;
2243 V_icmp6stat.icp6s_tooshort++;
2243 return;
2244 }
2245#endif
2246 redtgt6 = nd_rd->nd_rd_target;
2247 reddst6 = nd_rd->nd_rd_dst;
2248
2249 if (in6_setscope(&redtgt6, m->m_pkthdr.rcvif, NULL) ||
2250 in6_setscope(&reddst6, m->m_pkthdr.rcvif, NULL)) {

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

2397#endif /* IPSEC */
2398 }
2399
2400 freeit:
2401 m_freem(m);
2402 return;
2403
2404 bad:
2244 return;
2245 }
2246#endif
2247 redtgt6 = nd_rd->nd_rd_target;
2248 reddst6 = nd_rd->nd_rd_dst;
2249
2250 if (in6_setscope(&redtgt6, m->m_pkthdr.rcvif, NULL) ||
2251 in6_setscope(&reddst6, m->m_pkthdr.rcvif, NULL)) {

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

2398#endif /* IPSEC */
2399 }
2400
2401 freeit:
2402 m_freem(m);
2403 return;
2404
2405 bad:
2405 icmp6stat.icp6s_badredirect++;
2406 V_icmp6stat.icp6s_badredirect++;
2406 m_freem(m);
2407}
2408
2409void
2410icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
2411{
2412 struct ifnet *ifp; /* my outgoing interface */
2413 struct in6_addr *ifp_ll6;
2414 struct in6_addr *router_ll6;
2415 struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */
2416 struct mbuf *m = NULL; /* newly allocated one */
2417 struct ip6_hdr *ip6; /* m as struct ip6_hdr */
2418 struct nd_redirect *nd_rd;
2419 size_t maxlen;
2420 u_char *p;
2421 struct ifnet *outif = NULL;
2422 struct sockaddr_in6 src_sa;
2423
2407 m_freem(m);
2408}
2409
2410void
2411icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
2412{
2413 struct ifnet *ifp; /* my outgoing interface */
2414 struct in6_addr *ifp_ll6;
2415 struct in6_addr *router_ll6;
2416 struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */
2417 struct mbuf *m = NULL; /* newly allocated one */
2418 struct ip6_hdr *ip6; /* m as struct ip6_hdr */
2419 struct nd_redirect *nd_rd;
2420 size_t maxlen;
2421 u_char *p;
2422 struct ifnet *outif = NULL;
2423 struct sockaddr_in6 src_sa;
2424
2424 icmp6_errcount(&icmp6stat.icp6s_outerrhist, ND_REDIRECT, 0);
2425 icmp6_errcount(&V_icmp6stat.icp6s_outerrhist, ND_REDIRECT, 0);
2425
2426 /* if we are not router, we don't send icmp6 redirect */
2426
2427 /* if we are not router, we don't send icmp6 redirect */
2427 if (!ip6_forwarding)
2428 if (!V_ip6_forwarding)
2428 goto fail;
2429
2430 /* sanity check */
2431 if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp))
2432 goto fail;
2433
2434 /*
2435 * Address check:

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

2671 sizeof(*ip6), ntohs(ip6->ip6_plen));
2672
2673 /* send the packet to outside... */
2674 ip6_output(m, NULL, NULL, 0, NULL, &outif, NULL);
2675 if (outif) {
2676 icmp6_ifstat_inc(outif, ifs6_out_msg);
2677 icmp6_ifstat_inc(outif, ifs6_out_redirect);
2678 }
2429 goto fail;
2430
2431 /* sanity check */
2432 if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp))
2433 goto fail;
2434
2435 /*
2436 * Address check:

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

2672 sizeof(*ip6), ntohs(ip6->ip6_plen));
2673
2674 /* send the packet to outside... */
2675 ip6_output(m, NULL, NULL, 0, NULL, &outif, NULL);
2676 if (outif) {
2677 icmp6_ifstat_inc(outif, ifs6_out_msg);
2678 icmp6_ifstat_inc(outif, ifs6_out_redirect);
2679 }
2679 icmp6stat.icp6s_outhist[ND_REDIRECT]++;
2680 V_icmp6stat.icp6s_outhist[ND_REDIRECT]++;
2680
2681 return;
2682
2683fail:
2684 if (m)
2685 m_freem(m);
2686 if (m0)
2687 m_freem(m0);

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

2775icmp6_ratelimit(const struct in6_addr *dst, const int type,
2776 const int code)
2777{
2778 int ret;
2779
2780 ret = 0; /* okay to send */
2781
2782 /* PPS limit */
2681
2682 return;
2683
2684fail:
2685 if (m)
2686 m_freem(m);
2687 if (m0)
2688 m_freem(m0);

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

2776icmp6_ratelimit(const struct in6_addr *dst, const int type,
2777 const int code)
2778{
2779 int ret;
2780
2781 ret = 0; /* okay to send */
2782
2783 /* PPS limit */
2783 if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count,
2784 icmp6errppslim)) {
2784 if (!ppsratecheck(&V_icmp6errppslim_last, &V_icmp6errpps_count,
2785 V_icmp6errppslim)) {
2785 /* The packet is subject to rate limit */
2786 ret++;
2787 }
2788
2789 return ret;
2790}
2786 /* The packet is subject to rate limit */
2787 ret++;
2788 }
2789
2790 return ret;
2791}