1 /* $NetBSD: raw_ip6.c,v 1.102 2009/01/03 03:43:23 yamt Exp $ */
2 /* $KAME: raw_ip6.c,v 1.82 2001/07/23 18:57:56 jinmei Exp $ */
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * Copyright (c) 1982, 1986, 1988, 1993
35 * The Regents of the University of California. All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94
64 #include <sys/cdefs.h>
65 __KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.102 2009/01/03 03:43:23 yamt Exp $");
67 #include "opt_ipsec.h"
69 #include <sys/param.h>
70 #include <sys/sysctl.h>
71 #include <sys/malloc.h>
73 #include <sys/socket.h>
74 #include <sys/protosw.h>
75 #include <sys/socketvar.h>
76 #include <sys/errno.h>
77 #include <sys/systm.h>
79 #include <sys/kauth.h>
82 #include <net/route.h>
83 #include <net/if_types.h>
84 #include <net/net_stats.h>
86 #include <netinet/in.h>
87 #include <netinet/in_var.h>
88 #include <netinet/ip6.h>
89 #include <netinet6/ip6_var.h>
90 #include <netinet6/ip6_private.h>
91 #include <netinet6/ip6_mroute.h>
92 #include <netinet/icmp6.h>
93 #include <netinet6/icmp6_private.h>
94 #include <netinet6/in6_pcb.h>
95 #include <netinet6/nd6.h>
96 #include <netinet6/ip6protosw.h>
97 #include <netinet6/scope6_var.h>
98 #include <netinet6/raw_ip6.h>
101 #include <netinet6/ipsec.h>
102 #include <netinet6/ipsec_private.h>
106 #include <netipsec/ipsec.h>
107 #include <netipsec/ipsec_var.h>
108 #include <netipsec/ipsec_private.h>
109 #include <netipsec/ipsec6.h>
113 #if defined(NFAITH) && 0 < NFAITH
114 #include <net/if_faith.h>
117 extern struct inpcbtable rawcbtable
;
118 struct inpcbtable raw6cbtable
;
119 #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
122 * Raw interface to IP6 protocol.
125 static percpu_t
*rip6stat_percpu
;
127 #define RIP6_STATINC(x) _NET_STATINC(rip6stat_percpu, x)
130 * Initialize raw connection block queue.
136 in6_pcbinit(&raw6cbtable
, 1, 1);
138 rip6stat_percpu
= percpu_alloc(sizeof(uint64_t) * RIP6_NSTATS
);
142 * Setup generic address and protocol structures
143 * for raw_input routine, then pass them along with
147 rip6_input(struct mbuf
**mp
, int *offp
, int proto
)
149 struct mbuf
*m
= *mp
;
150 struct ip6_hdr
*ip6
= mtod(m
, struct ip6_hdr
*);
151 struct inpcb_hdr
*inph
;
153 struct in6pcb
*last
= NULL
;
154 struct sockaddr_in6 rip6src
;
155 struct mbuf
*opts
= NULL
;
157 RIP6_STATINC(RIP6_STAT_IPACKETS
);
159 #if defined(NFAITH) && 0 < NFAITH
160 if (faithprefix(&ip6
->ip6_dst
)) {
161 /* send icmp6 host unreach? */
167 /* Be proactive about malicious use of IPv4 mapped address */
168 if (IN6_IS_ADDR_V4MAPPED(&ip6
->ip6_src
) ||
169 IN6_IS_ADDR_V4MAPPED(&ip6
->ip6_dst
)) {
175 sockaddr_in6_init(&rip6src
, &ip6
->ip6_src
, 0, 0, 0);
176 if (sa6_recoverscope(&rip6src
) != 0) {
177 /* XXX: should be impossible. */
182 CIRCLEQ_FOREACH(inph
, &raw6cbtable
.inpt_queue
, inph_queue
) {
183 in6p
= (struct in6pcb
*)inph
;
184 if (in6p
->in6p_af
!= AF_INET6
)
186 if (in6p
->in6p_ip6
.ip6_nxt
&&
187 in6p
->in6p_ip6
.ip6_nxt
!= proto
)
189 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
) &&
190 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
, &ip6
->ip6_dst
))
192 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
) &&
193 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
, &ip6
->ip6_src
))
195 if (in6p
->in6p_cksum
!= -1) {
196 RIP6_STATINC(RIP6_STAT_ISUM
);
197 if (in6_cksum(m
, proto
, *offp
,
198 m
->m_pkthdr
.len
- *offp
)) {
199 RIP6_STATINC(RIP6_STAT_BADSUM
);
208 * Check AH/ESP integrity.
210 if (ipsec6_in_reject(m
, last
)) {
211 IPSEC6_STATINC(IPSEC_STAT_IN_INVAL
);
212 /* do not inject data into pcb */
217 * Check AH/ESP integrity
219 if (!ipsec6_in_reject(m
,last
))
220 #endif /* FAST_IPSEC */
221 if ((n
= m_copy(m
, 0, (int)M_COPYALL
)) != NULL
) {
222 if (last
->in6p_flags
& IN6P_CONTROLOPTS
)
223 ip6_savecontrol(last
, &opts
, ip6
, n
);
224 /* strip intermediate headers */
226 if (sbappendaddr(&last
->in6p_socket
->so_rcv
,
227 (struct sockaddr
*)&rip6src
, n
, opts
) == 0) {
228 /* should notify about lost packet */
232 RIP6_STATINC(RIP6_STAT_FULLSOCK
);
234 sorwakeup(last
->in6p_socket
);
242 * Check AH/ESP integrity.
244 if (last
&& ipsec6_in_reject(m
, last
)) {
246 IPSEC6_STATINC(IPSEC_STAT_IN_INVAL
);
247 IP6_STATDEC(IP6_STAT_DELIVERED
);
248 /* do not inject data into pcb */
252 if (last
&& ipsec6_in_reject(m
, last
)) {
255 * XXX ipsec6_in_reject update stat if there is an error
256 * so we just need to update stats by hand in the case of last is
260 IPSEC6_STATINC(IPSEC_STAT_IN_POLVIO
);
261 IP6_STATDEC(IP6_STAT_DELIVERED
);
262 /* do not inject data into pcb */
264 #endif /* FAST_IPSEC */
266 if (last
->in6p_flags
& IN6P_CONTROLOPTS
)
267 ip6_savecontrol(last
, &opts
, ip6
, m
);
268 /* strip intermediate headers */
270 if (sbappendaddr(&last
->in6p_socket
->so_rcv
,
271 (struct sockaddr
*)&rip6src
, m
, opts
) == 0) {
275 RIP6_STATINC(RIP6_STAT_FULLSOCK
);
277 sorwakeup(last
->in6p_socket
);
279 RIP6_STATINC(RIP6_STAT_NOSOCK
);
280 if (m
->m_flags
& M_MCAST
)
281 RIP6_STATINC(RIP6_STAT_NOSOCKMCAST
);
282 if (proto
== IPPROTO_NONE
)
285 u_int8_t
*prvnxtp
= ip6_get_prevhdr(m
, *offp
); /* XXX */
286 in6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_protounknown
);
287 icmp6_error(m
, ICMP6_PARAM_PROB
,
288 ICMP6_PARAMPROB_NEXTHEADER
,
289 prvnxtp
- mtod(m
, u_int8_t
*));
291 IP6_STATDEC(IP6_STAT_DELIVERED
);
297 rip6_ctlinput(int cmd
, const struct sockaddr
*sa
, void *d
)
300 struct ip6ctlparam
*ip6cp
= NULL
;
301 const struct sockaddr_in6
*sa6_src
= NULL
;
303 void (*notify
)(struct in6pcb
*, int) = in6_rtchange
;
306 if (sa
->sa_family
!= AF_INET6
||
307 sa
->sa_len
!= sizeof(struct sockaddr_in6
))
310 if ((unsigned)cmd
>= PRC_NCMDS
)
312 if (PRC_IS_REDIRECT(cmd
))
313 notify
= in6_rtchange
, d
= NULL
;
314 else if (cmd
== PRC_HOSTDEAD
)
316 else if (cmd
== PRC_MSGSIZE
)
317 ; /* special code is present, see below */
318 else if (inet6ctlerrmap
[cmd
] == 0)
321 /* if the parameter is from icmp6, decode it. */
323 ip6cp
= (struct ip6ctlparam
*)d
;
324 ip6
= ip6cp
->ip6c_ip6
;
325 cmdarg
= ip6cp
->ip6c_cmdarg
;
326 sa6_src
= ip6cp
->ip6c_src
;
327 nxt
= ip6cp
->ip6c_nxt
;
335 if (ip6
&& cmd
== PRC_MSGSIZE
) {
336 const struct sockaddr_in6
*sa6
= (const struct sockaddr_in6
*)sa
;
341 * Check to see if we have a valid raw IPv6 socket
342 * corresponding to the address in the ICMPv6 message
343 * payload, and the protocol (ip6_nxt) meets the socket.
344 * XXX chase extension headers, or pass final nxt value
345 * from icmp6_notify_error()
348 in6p
= in6_pcblookup_connect(&raw6cbtable
, &sa6
->sin6_addr
, 0,
349 (const struct in6_addr
*)&sa6_src
->sin6_addr
, 0, 0);
353 * As the use of sendto(2) is fairly popular,
354 * we may want to allow non-connected pcb too.
355 * But it could be too weak against attacks...
356 * We should at least check if the local
357 * address (= s) is really ours.
359 in6p
= in6_pcblookup_bind(&raw6cbtable
,
360 &sa6
->sin6_addr
, 0, 0);
364 if (in6p
&& in6p
->in6p_ip6
.ip6_nxt
&&
365 in6p
->in6p_ip6
.ip6_nxt
== nxt
)
369 * Depending on the value of "valid" and routing table
370 * size (mtudisc_{hi,lo}wat), we will:
371 * - recalculate the new MTU and create the
372 * corresponding routing entry, or
373 * - ignore the MTU change notification.
375 icmp6_mtudisc_update((struct ip6ctlparam
*)d
, valid
);
378 * regardless of if we called icmp6_mtudisc_update(),
379 * we need to call in6_pcbnotify(), to notify path MTU
380 * change to the userland (RFC3542), because some
381 * unconnected sockets may share the same destination
382 * and want to know the path MTU.
386 (void) in6_pcbnotify(&raw6cbtable
, sa
, 0,
387 (const struct sockaddr
*)sa6_src
, 0, cmd
, cmdarg
, notify
);
392 * Generate IPv6 header and pass packet to ip6_output.
393 * Tack on options user may have setup with control call.
396 rip6_output(struct mbuf
*m
, struct socket
*so
, struct sockaddr_in6
*dstsock
,
397 struct mbuf
*control
)
399 struct in6_addr
*dst
;
402 u_int plen
= m
->m_pkthdr
.len
;
404 struct ip6_pktopts opt
, *optp
= NULL
;
405 struct ifnet
*oifp
= NULL
;
406 int type
, code
; /* for ICMPv6 output statistics only */
408 int scope_ambiguous
= 0;
409 struct in6_addr
*in6a
;
411 in6p
= sotoin6pcb(so
);
414 if (curlwp
&& !kauth_authorize_generic(curlwp
->l_cred
,
415 KAUTH_GENERIC_ISSUSER
, NULL
))
418 dst
= &dstsock
->sin6_addr
;
420 if ((error
= ip6_setpktopts(control
, &opt
,
421 in6p
->in6p_outputopts
,
422 priv
, so
->so_proto
->pr_protocol
)) != 0) {
427 optp
= in6p
->in6p_outputopts
;
430 * Check and convert scope zone ID into internal form.
431 * XXX: we may still need to determine the zone later.
433 if (!(so
->so_state
& SS_ISCONNECTED
)) {
434 if (dstsock
->sin6_scope_id
== 0 && !ip6_use_defzone
)
436 if ((error
= sa6_embedscope(dstsock
, ip6_use_defzone
)) != 0)
441 * For an ICMPv6 packet, we should know its type and code
442 * to update statistics.
444 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
) {
445 struct icmp6_hdr
*icmp6
;
446 if (m
->m_len
< sizeof(struct icmp6_hdr
) &&
447 (m
= m_pullup(m
, sizeof(struct icmp6_hdr
))) == NULL
) {
451 icmp6
= mtod(m
, struct icmp6_hdr
*);
452 type
= icmp6
->icmp6_type
;
453 code
= icmp6
->icmp6_code
;
459 M_PREPEND(m
, sizeof(*ip6
), M_DONTWAIT
);
464 ip6
= mtod(m
, struct ip6_hdr
*);
467 * Next header might not be ICMP6 but use its pseudo header anyway.
472 * Source address selection.
474 if ((in6a
= in6_selectsrc(dstsock
, optp
, in6p
->in6p_moptions
,
475 (struct route
*)&in6p
->in6p_route
, &in6p
->in6p_laddr
, &oifp
,
478 error
= EADDRNOTAVAIL
;
481 ip6
->ip6_src
= *in6a
;
483 if (oifp
&& scope_ambiguous
) {
485 * Application should provide a proper zone ID or the use of
486 * default zone IDs should be enabled. Unfortunately, some
487 * applications do not behave as it should, so we need a
488 * workaround. Even if an appropriate ID is not determined
489 * (when it's required), if we can determine the outgoing
490 * interface. determine the zone ID based on the interface.
492 error
= in6_setscope(&dstsock
->sin6_addr
, oifp
, NULL
);
496 ip6
->ip6_dst
= dstsock
->sin6_addr
;
498 /* fill in the rest of the IPv6 header fields */
499 ip6
->ip6_flow
= in6p
->in6p_flowinfo
& IPV6_FLOWINFO_MASK
;
500 ip6
->ip6_vfc
&= ~IPV6_VERSION_MASK
;
501 ip6
->ip6_vfc
|= IPV6_VERSION
;
502 /* ip6_plen will be filled in ip6_output, so not fill it here. */
503 ip6
->ip6_nxt
= in6p
->in6p_ip6
.ip6_nxt
;
504 ip6
->ip6_hlim
= in6_selecthlim(in6p
, oifp
);
506 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
||
507 in6p
->in6p_cksum
!= -1) {
511 /* compute checksum */
512 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
)
513 off
= offsetof(struct icmp6_hdr
, icmp6_cksum
);
515 off
= in6p
->in6p_cksum
;
516 if (plen
< off
+ 1) {
520 off
+= sizeof(struct ip6_hdr
);
523 m
= m_copyback_cow(m
, off
, sizeof(sum
), (void *)&sum
,
529 sum
= in6_cksum(m
, ip6
->ip6_nxt
, sizeof(*ip6
), plen
);
530 m
= m_copyback_cow(m
, off
, sizeof(sum
), (void *)&sum
,
538 error
= ip6_output(m
, optp
, &in6p
->in6p_route
, 0,
539 in6p
->in6p_moptions
, so
, &oifp
);
540 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
) {
542 icmp6_ifoutstat_inc(oifp
, type
, code
);
543 ICMP6_STATINC(ICMP6_STAT_OUTHIST
+ type
);
545 RIP6_STATINC(RIP6_STAT_OPACKETS
);
555 ip6_clearpktopts(&opt
, -1);
562 * Raw IPv6 socket option processing.
565 rip6_ctloutput(int op
, struct socket
*so
, struct sockopt
*sopt
)
569 if (sopt
->sopt_level
== SOL_SOCKET
&& sopt
->sopt_name
== SO_NOHEADER
) {
572 /* need to fiddle w/ opt(IPPROTO_IPV6, IPV6_CHECKSUM)? */
573 if (op
== PRCO_GETOPT
) {
575 error
= sockopt_set(sopt
, &optval
, sizeof(optval
));
576 } else if (op
== PRCO_SETOPT
) {
577 error
= sockopt_getint(sopt
, &optval
);
585 } else if (sopt
->sopt_level
!= IPPROTO_IPV6
)
586 return ip6_ctloutput(op
, so
, sopt
);
588 switch (sopt
->sopt_name
) {
596 if (op
== PRCO_SETOPT
)
597 error
= ip6_mrouter_set(so
, sopt
);
598 else if (op
== PRCO_GETOPT
)
599 error
= ip6_mrouter_get(so
, sopt
);
604 return ip6_raw_ctloutput(op
, so
, sopt
);
606 return ip6_ctloutput(op
, so
, sopt
);
612 extern u_long rip6_sendspace
;
613 extern u_long rip6_recvspace
;
616 rip6_usrreq(struct socket
*so
, int req
, struct mbuf
*m
,
617 struct mbuf
*nam
, struct mbuf
*control
, struct lwp
*l
)
619 struct in6pcb
*in6p
= sotoin6pcb(so
);
625 if (l
&& !kauth_authorize_generic(l
->l_cred
,
626 KAUTH_GENERIC_ISSUSER
, NULL
))
629 if (req
== PRU_CONTROL
)
630 return in6_control(so
, (u_long
)m
, (void *)nam
,
631 (struct ifnet
*)control
, l
);
633 if (req
== PRU_PURGEIF
) {
634 mutex_enter(softnet_lock
);
635 in6_pcbpurgeif0(&raw6cbtable
, (struct ifnet
*)control
);
636 in6_purgeif((struct ifnet
*)control
);
637 in6_pcbpurgeif(&raw6cbtable
, (struct ifnet
*)control
);
638 mutex_exit(softnet_lock
);
646 panic("rip6_attach");
652 error
= soreserve(so
, rip6_sendspace
, rip6_recvspace
);
657 if ((error
= in6_pcballoc(so
, &raw6cbtable
)) != 0) {
662 in6p
= sotoin6pcb(so
);
663 in6p
->in6p_ip6
.ip6_nxt
= (long)nam
;
664 in6p
->in6p_cksum
= -1;
666 in6p
->in6p_icmp6filt
= malloc(sizeof(struct icmp6_filter
),
668 if (in6p
->in6p_icmp6filt
== NULL
) {
673 ICMP6_FILTER_SETPASSALL(in6p
->in6p_icmp6filt
);
677 if ((so
->so_state
& SS_ISCONNECTED
) == 0) {
681 in6p
->in6p_faddr
= in6addr_any
;
682 so
->so_state
&= ~SS_ISCONNECTED
; /* XXX */
686 soisdisconnected(so
);
690 panic("rip6_detach");
691 if (so
== ip6_mrouter
)
694 if (in6p
->in6p_icmp6filt
!= NULL
) {
695 free(in6p
->in6p_icmp6filt
, M_PCB
);
696 in6p
->in6p_icmp6filt
= NULL
;
703 struct sockaddr_in6
*addr
= mtod(nam
, struct sockaddr_in6
*);
704 struct ifaddr
*ia
= NULL
;
706 if (nam
->m_len
!= sizeof(*addr
)) {
710 if (TAILQ_EMPTY(&ifnet
) || addr
->sin6_family
!= AF_INET6
) {
711 error
= EADDRNOTAVAIL
;
714 if ((error
= sa6_embedscope(addr
, ip6_use_defzone
)) != 0)
718 * we don't support mapped address here, it would confuse
721 if (IN6_IS_ADDR_V4MAPPED(&addr
->sin6_addr
)) {
722 error
= EADDRNOTAVAIL
;
725 if (!IN6_IS_ADDR_UNSPECIFIED(&addr
->sin6_addr
) &&
726 (ia
= ifa_ifwithaddr((struct sockaddr
*)addr
)) == 0) {
727 error
= EADDRNOTAVAIL
;
730 if (ia
&& ((struct in6_ifaddr
*)ia
)->ia6_flags
&
731 (IN6_IFF_ANYCAST
|IN6_IFF_NOTREADY
|
732 IN6_IFF_DETACHED
|IN6_IFF_DEPRECATED
)) {
733 error
= EADDRNOTAVAIL
;
736 in6p
->in6p_laddr
= addr
->sin6_addr
;
742 struct sockaddr_in6
*addr
= mtod(nam
, struct sockaddr_in6
*);
743 struct in6_addr
*in6a
= NULL
;
744 struct ifnet
*ifp
= NULL
;
745 int scope_ambiguous
= 0;
747 if (nam
->m_len
!= sizeof(*addr
)) {
751 if (TAILQ_EMPTY(&ifnet
)) {
752 error
= EADDRNOTAVAIL
;
755 if (addr
->sin6_family
!= AF_INET6
) {
756 error
= EAFNOSUPPORT
;
761 * Application should provide a proper zone ID or the use of
762 * default zone IDs should be enabled. Unfortunately, some
763 * applications do not behave as it should, so we need a
764 * workaround. Even if an appropriate ID is not determined,
765 * we'll see if we can determine the outgoing interface. If we
766 * can, determine the zone ID based on the interface below.
768 if (addr
->sin6_scope_id
== 0 && !ip6_use_defzone
)
770 if ((error
= sa6_embedscope(addr
, ip6_use_defzone
)) != 0)
773 /* Source address selection. XXX: need pcblookup? */
774 in6a
= in6_selectsrc(addr
, in6p
->in6p_outputopts
,
775 in6p
->in6p_moptions
, (struct route
*)&in6p
->in6p_route
,
776 &in6p
->in6p_laddr
, &ifp
, &error
);
779 error
= EADDRNOTAVAIL
;
783 if (ifp
&& scope_ambiguous
&&
784 (error
= in6_setscope(&addr
->sin6_addr
, ifp
, NULL
)) != 0) {
787 in6p
->in6p_laddr
= *in6a
;
788 in6p
->in6p_faddr
= addr
->sin6_addr
;
798 * Mark the connection as being incapable of futther input.
804 * Ship a packet out. The appropriate raw output
805 * routine handles any messaging necessary.
809 struct sockaddr_in6 tmp
;
810 struct sockaddr_in6
*dst
;
812 /* always copy sockaddr to avoid overwrites */
813 if (so
->so_state
& SS_ISCONNECTED
) {
819 sockaddr_in6_init(&tmp
, &in6p
->in6p_faddr
, 0, 0, 0);
826 if (nam
->m_len
!= sizeof(tmp
)) {
831 tmp
= *mtod(nam
, struct sockaddr_in6
*);
834 if (dst
->sin6_family
!= AF_INET6
) {
835 error
= EAFNOSUPPORT
;
839 error
= rip6_output(m
, so
, dst
, control
);
846 * stat: don't bother with a blocksize
861 in6_setsockaddr(in6p
, nam
);
865 in6_setpeeraddr(in6p
, nam
);
869 panic("rip6_usrreq");
877 sysctl_net_inet6_raw6_stats(SYSCTLFN_ARGS
)
880 return (NETSTAT_SYSCTL(rip6stat_percpu
, RIP6_NSTATS
));
883 SYSCTL_SETUP(sysctl_net_inet6_raw6_setup
, "sysctl net.inet6.raw6 subtree setup")
886 sysctl_createv(clog
, 0, NULL
, NULL
,
888 CTLTYPE_NODE
, "net", NULL
,
891 sysctl_createv(clog
, 0, NULL
, NULL
,
893 CTLTYPE_NODE
, "inet6", NULL
,
895 CTL_NET
, PF_INET6
, CTL_EOL
);
896 sysctl_createv(clog
, 0, NULL
, NULL
,
898 CTLTYPE_NODE
, "raw6",
899 SYSCTL_DESCR("Raw IPv6 settings"),
901 CTL_NET
, PF_INET6
, IPPROTO_RAW
, CTL_EOL
);
903 sysctl_createv(clog
, 0, NULL
, NULL
,
905 CTLTYPE_STRUCT
, "pcblist",
906 SYSCTL_DESCR("Raw IPv6 control block list"),
907 sysctl_inpcblist
, 0, &raw6cbtable
, 0,
908 CTL_NET
, PF_INET6
, IPPROTO_RAW
,
909 CTL_CREATE
, CTL_EOL
);
910 sysctl_createv(clog
, 0, NULL
, NULL
,
912 CTLTYPE_STRUCT
, "stats",
913 SYSCTL_DESCR("Raw IPv6 statistics"),
914 sysctl_net_inet6_raw6_stats
, 0, NULL
, 0,
915 CTL_NET
, PF_INET6
, IPPROTO_RAW
, RAW6CTL_STATS
,