2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * $FreeBSD: src/sys/netinet6/raw_ip6.c,v 1.7.2.7 2003/01/24 05:11:35 sam Exp $
33 * Copyright (c) 1982, 1986, 1988, 1993
34 * The Regents of the University of California. All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
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
60 * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94
63 #include "opt_inet6.h"
65 #include <sys/param.h>
66 #include <sys/malloc.h>
70 #include <sys/socket.h>
72 #include <sys/protosw.h>
73 #include <sys/socketvar.h>
74 #include <sys/errno.h>
75 #include <sys/systm.h>
77 #include <sys/thread2.h>
78 #include <sys/socketvar2.h>
79 #include <sys/msgport2.h>
82 #include <net/route.h>
83 #include <net/if_types.h>
85 #include <netinet/in.h>
86 #include <netinet/in_var.h>
87 #include <netinet/in_systm.h>
88 #include <netinet/ip6.h>
89 #include <netinet6/ip6_var.h>
90 #include <netinet6/ip6_mroute.h>
91 #include <netinet/icmp6.h>
92 #include <netinet/in_pcb.h>
93 #include <netinet6/in6_pcb.h>
94 #include <netinet6/nd6.h>
95 #include <netinet6/ip6protosw.h>
96 #ifdef ENABLE_DEFAULT_SCOPE
97 #include <netinet6/scope6_var.h>
99 #include <netinet6/raw_ip6.h>
101 #include <machine/stdarg.h>
103 #define satosin6(sa) ((struct sockaddr_in6 *)(sa))
104 #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
107 * Raw interface to IP6 protocol.
110 extern struct inpcbinfo ripcbinfo
;
111 extern u_long rip_sendspace
;
112 extern u_long rip_recvspace
;
114 struct rip6stat rip6stat
;
117 * Setup generic address and protocol structures
118 * for raw_input routine, then pass them along with
122 rip6_input(struct mbuf
**mp
, int *offp
, int proto
)
124 struct mbuf
*m
= *mp
;
125 struct ip6_hdr
*ip6
= mtod(m
, struct ip6_hdr
*);
127 struct inpcb
*last
= NULL
;
128 struct mbuf
*opts
= NULL
;
129 struct sockaddr_in6 rip6src
;
131 rip6stat
.rip6s_ipackets
++;
133 init_sin6(&rip6src
, m
); /* general init */
135 LIST_FOREACH(in6p
, &ripcbinfo
.pcblisthead
, inp_list
) {
136 if (in6p
->in6p_flags
& INP_PLACEMARKER
)
138 if (!INP_ISIPV6(in6p
))
140 if (in6p
->in6p_ip6_nxt
&&
141 in6p
->in6p_ip6_nxt
!= proto
)
143 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
) &&
144 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
, &ip6
->ip6_dst
))
146 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
) &&
147 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
, &ip6
->ip6_src
))
149 if (in6p
->in6p_cksum
!= -1) {
150 rip6stat
.rip6s_isum
++;
151 if (in6_cksum(m
, ip6
->ip6_nxt
, *offp
,
152 m
->m_pkthdr
.len
- *offp
)) {
153 rip6stat
.rip6s_badsum
++;
158 struct mbuf
*n
= m_copy(m
, 0, (int)M_COPYALL
);
163 so
= last
->in6p_socket
;
164 if ((last
->in6p_flags
& IN6P_CONTROLOPTS
) ||
165 (so
->so_options
& SO_TIMESTAMP
)) {
166 ip6_savecontrol(last
, &opts
, ip6
, n
);
168 /* strip intermediate headers */
170 lwkt_gettoken(&so
->so_rcv
.ssb_token
);
171 if (ssb_appendaddr(&so
->so_rcv
,
172 (struct sockaddr
*)&rip6src
,
177 rip6stat
.rip6s_fullsock
++;
182 lwkt_reltoken(&so
->so_rcv
.ssb_token
);
191 so
= last
->in6p_socket
;
192 if ((last
->in6p_flags
& IN6P_CONTROLOPTS
) ||
193 (so
->so_options
& SO_TIMESTAMP
)) {
194 ip6_savecontrol(last
, &opts
, ip6
, m
);
196 /* strip intermediate headers */
198 lwkt_gettoken(&so
->so_rcv
.ssb_token
);
199 if (ssb_appendaddr(&so
->so_rcv
, (struct sockaddr
*)&rip6src
,
204 rip6stat
.rip6s_fullsock
++;
209 lwkt_reltoken(&so
->so_rcv
.ssb_token
);
211 rip6stat
.rip6s_nosock
++;
212 if (m
->m_flags
& M_MCAST
)
213 rip6stat
.rip6s_nosockmcast
++;
214 if (proto
== IPPROTO_NONE
)
217 char *prvnxtp
= ip6_get_prevhdr(m
, *offp
); /* XXX */
218 icmp6_error(m
, ICMP6_PARAM_PROB
,
219 ICMP6_PARAMPROB_NEXTHEADER
,
220 prvnxtp
- mtod(m
, char *));
222 ip6stat
.ip6s_delivered
--;
228 rip6_ctlinput(netmsg_t msg
)
230 int cmd
= msg
->ctlinput
.nm_cmd
;
231 struct sockaddr
*sa
= msg
->ctlinput
.nm_arg
;
232 void *d
= msg
->ctlinput
.nm_extra
;
233 struct ip6ctlparam
*ip6cp
= NULL
;
234 const struct sockaddr_in6
*sa6_src
= NULL
;
235 inp_notify_t notify
= in6_rtchange
;
237 if (sa
->sa_family
!= AF_INET6
||
238 sa
->sa_len
!= sizeof(struct sockaddr_in6
))
241 if ((unsigned)cmd
>= PRC_NCMDS
)
243 if (PRC_IS_REDIRECT(cmd
))
244 notify
= in6_rtchange
, d
= NULL
;
245 else if (cmd
== PRC_HOSTDEAD
)
247 else if (inet6ctlerrmap
[cmd
] == 0)
250 /* if the parameter is from icmp6, decode it. */
252 ip6cp
= (struct ip6ctlparam
*)d
;
253 sa6_src
= ip6cp
->ip6c_src
;
258 in6_pcbnotify(&ripcbinfo
, sa
, 0,
259 (const struct sockaddr
*)sa6_src
, 0, cmd
, 0, notify
);
261 lwkt_replymsg(&msg
->ctlinput
.base
.lmsg
, 0);
265 * Generate IPv6 header and pass packet to ip6_output.
266 * Tack on options user may have setup with control call.
269 rip6_output(struct mbuf
*m
, struct socket
*so
, ...)
271 struct sockaddr_in6
*dstsock
;
272 struct mbuf
*control
;
273 struct in6_addr
*dst
;
276 u_int plen
= m
->m_pkthdr
.len
;
278 struct ip6_pktopts opt
, *optp
= NULL
;
279 struct ifnet
*oifp
= NULL
;
280 int type
= 0, code
= 0; /* for ICMPv6 output statistics only */
285 dstsock
= __va_arg(ap
, struct sockaddr_in6
*);
286 control
= __va_arg(ap
, struct mbuf
*);
289 if (IN6_IS_ADDR_V4MAPPED(&dstsock
->sin6_addr
)) {
290 error
= EADDRNOTAVAIL
;
297 if (so
->so_cred
->cr_uid
== 0)
299 dst
= &dstsock
->sin6_addr
;
301 if ((error
= ip6_setpktoptions(control
, &opt
,
302 in6p
->in6p_outputopts
,
303 so
->so_proto
->pr_protocol
, priv
)) != 0)
307 optp
= in6p
->in6p_outputopts
;
310 * For an ICMPv6 packet, we should know its type and code
311 * to update statistics.
313 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
) {
314 struct icmp6_hdr
*icmp6
;
315 if (m
->m_len
< sizeof(struct icmp6_hdr
) &&
316 (m
= m_pullup(m
, sizeof(struct icmp6_hdr
))) == NULL
) {
320 icmp6
= mtod(m
, struct icmp6_hdr
*);
321 type
= icmp6
->icmp6_type
;
322 code
= icmp6
->icmp6_code
;
325 M_PREPEND(m
, sizeof(*ip6
), M_WAITOK
);
326 ip6
= mtod(m
, struct ip6_hdr
*);
329 * Next header might not be ICMP6 but use its pseudo header anyway.
334 * If the scope of the destination is link-local, embed the interface
335 * index in the address.
337 * XXX advanced-api value overrides sin6_scope_id
339 if (IN6_IS_SCOPE_LINKLOCAL(&ip6
->ip6_dst
)) {
340 struct in6_pktinfo
*pi
;
343 * XXX Boundary check is assumed to be already done in
344 * ip6_setpktoptions().
346 if (optp
&& (pi
= optp
->ip6po_pktinfo
) && pi
->ipi6_ifindex
) {
347 ip6
->ip6_dst
.s6_addr16
[1] = htons(pi
->ipi6_ifindex
);
348 oifp
= ifindex2ifnet
[pi
->ipi6_ifindex
];
349 } else if (IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
) &&
350 in6p
->in6p_moptions
&&
351 in6p
->in6p_moptions
->im6o_multicast_ifp
) {
352 oifp
= in6p
->in6p_moptions
->im6o_multicast_ifp
;
353 ip6
->ip6_dst
.s6_addr16
[1] = htons(oifp
->if_index
);
354 } else if (dstsock
->sin6_scope_id
) {
356 if (dstsock
->sin6_scope_id
< 0 ||
357 if_index
< dstsock
->sin6_scope_id
) {
358 error
= ENXIO
; /* XXX EINVAL? */
361 ip6
->ip6_dst
.s6_addr16
[1] =
362 htons(dstsock
->sin6_scope_id
& 0xffff); /* XXX */
367 * Source address selection.
370 struct in6_addr
*in6a
;
372 if ((in6a
= in6_selectsrc(dstsock
, optp
, in6p
->in6p_moptions
,
373 &in6p
->in6p_route
, &in6p
->in6p_laddr
, &error
, NULL
))
376 error
= EADDRNOTAVAIL
;
379 ip6
->ip6_src
= *in6a
;
380 if (in6p
->in6p_route
.ro_rt
)
381 oifp
= ifindex2ifnet
[in6p
->in6p_route
.ro_rt
->rt_ifp
->if_index
];
383 ip6
->ip6_flow
= (ip6
->ip6_flow
& ~IPV6_FLOWINFO_MASK
) |
384 (in6p
->in6p_flowinfo
& IPV6_FLOWINFO_MASK
);
385 ip6
->ip6_vfc
= (ip6
->ip6_vfc
& ~IPV6_VERSION_MASK
) |
386 (IPV6_VERSION
& IPV6_VERSION_MASK
);
387 /* ip6_plen will be filled in ip6_output, so not fill it here. */
388 ip6
->ip6_nxt
= in6p
->in6p_ip6_nxt
;
389 ip6
->ip6_hlim
= in6_selecthlim(in6p
, oifp
);
391 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
||
392 in6p
->in6p_cksum
!= -1) {
397 /* compute checksum */
398 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
)
399 off
= offsetof(struct icmp6_hdr
, icmp6_cksum
);
401 off
= in6p
->in6p_cksum
;
402 if (plen
< off
+ 1) {
406 off
+= sizeof(struct ip6_hdr
);
409 while (n
&& n
->m_len
<= off
) {
415 p
= (u_int16_t
*)(mtod(n
, caddr_t
) + off
);
417 *p
= in6_cksum(m
, ip6
->ip6_nxt
, sizeof(*ip6
), plen
);
420 error
= ip6_output(m
, optp
, &in6p
->in6p_route
, 0,
421 in6p
->in6p_moptions
, &oifp
, in6p
);
422 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
) {
424 icmp6_ifoutstat_inc(oifp
, type
, code
);
425 icmp6stat
.icp6s_outhist
[type
]++;
427 rip6stat
.rip6s_opackets
++;
436 if (optp
== &opt
&& optp
->ip6po_rthdr
&& optp
->ip6po_route
.ro_rt
)
437 RTFREE(optp
->ip6po_route
.ro_rt
);
440 ip6_clearpktopts(optp
, -1);
447 * Raw IPv6 socket option processing.
450 rip6_ctloutput(netmsg_t msg
)
452 struct socket
*so
= msg
->ctloutput
.base
.nm_so
;
453 struct sockopt
*sopt
= msg
->ctloutput
.nm_sopt
;
456 if (sopt
->sopt_level
== IPPROTO_ICMPV6
) {
458 * XXX: is it better to call icmp6_ctloutput() directly
461 icmp6_ctloutput(msg
);
462 /* msg invalid now */
465 if (sopt
->sopt_level
!= IPPROTO_IPV6
) {
472 switch (sopt
->sopt_dir
) {
474 switch (sopt
->sopt_name
) {
482 error
= ip6_mrouter_get(so
, sopt
);
485 error
= ip6_raw_ctloutput(so
, sopt
);
488 error
= ip6_ctloutput(so
, sopt
);
494 switch (sopt
->sopt_name
) {
502 error
= ip6_mrouter_set(so
, sopt
);
505 error
= ip6_raw_ctloutput(so
, sopt
);
508 error
= ip6_ctloutput(so
, sopt
);
514 lwkt_replymsg(&msg
->ctloutput
.base
.lmsg
, error
);
518 rip6_attach(netmsg_t msg
)
520 struct socket
*so
= msg
->attach
.base
.nm_so
;
521 int proto
= msg
->attach
.nm_proto
;
522 struct pru_attach_info
*ai
= msg
->attach
.nm_ai
;
528 panic("rip6_attach");
529 error
= priv_check_cred(ai
->p_ucred
, PRIV_NETINET_RAW
, NULL_CRED_OKAY
);
533 error
= soreserve(so
, rip_sendspace
, rip_recvspace
, ai
->sb_rlimit
);
537 error
= in_pcballoc(so
, &ripcbinfo
);
541 inp
= (struct inpcb
*)so
->so_pcb
;
542 inp
->in6p_ip6_nxt
= (long)proto
;
543 inp
->in6p_hops
= -1; /* use kernel default */
544 inp
->in6p_cksum
= -1;
545 inp
->in6p_icmp6filt
= kmalloc(sizeof(struct icmp6_filter
), M_PCB
,
547 if (inp
->in6p_icmp6filt
!= NULL
)
548 ICMP6_FILTER_SETPASSALL(inp
->in6p_icmp6filt
);
551 lwkt_replymsg(&msg
->attach
.base
.lmsg
, error
);
555 rip6_detach(netmsg_t msg
)
557 struct socket
*so
= msg
->detach
.base
.nm_so
;
562 panic("rip6_detach");
564 if (so
== ip6_mrouter
)
566 if (inp
->in6p_icmp6filt
) {
567 kfree(inp
->in6p_icmp6filt
, M_PCB
);
568 inp
->in6p_icmp6filt
= NULL
;
571 lwkt_replymsg(&msg
->detach
.base
.lmsg
, 0);
575 * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
576 * will sofree() it when we return.
579 rip6_abort(netmsg_t msg
)
581 soisdisconnected(msg
->abort
.base
.nm_so
);
583 /* msg invalid now */
587 rip6_disconnect(netmsg_t msg
)
589 struct socket
*so
= msg
->disconnect
.base
.nm_so
;
590 struct inpcb
*inp
= so
->so_pcb
;
592 if (so
->so_state
& SS_ISCONNECTED
) {
593 inp
->in6p_faddr
= kin6addr_any
;
596 /* msg invalid now */
600 lwkt_replymsg(&msg
->disconnect
.base
.lmsg
, ENOTCONN
);
604 rip6_bind(netmsg_t msg
)
606 struct socket
*so
= msg
->bind
.base
.nm_so
;
607 struct sockaddr
*nam
= msg
->bind
.nm_nam
;
608 struct inpcb
*inp
= so
->so_pcb
;
609 struct sockaddr_in6
*addr
= (struct sockaddr_in6
*)nam
;
610 struct ifaddr
*ia
= NULL
;
613 if (nam
->sa_len
!= sizeof(*addr
)) {
617 if (ifnet_array_isempty() || addr
->sin6_family
!= AF_INET6
) {
618 error
= EADDRNOTAVAIL
;
621 if (IN6_IS_ADDR_V4MAPPED(&addr
->sin6_addr
)) {
622 error
= EADDRNOTAVAIL
;
625 #ifdef ENABLE_DEFAULT_SCOPE
626 if (addr
->sin6_scope_id
== 0) { /* not change if specified */
627 addr
->sin6_scope_id
= scope6_addr2default(&addr
->sin6_addr
);
630 if (!IN6_IS_ADDR_UNSPECIFIED(&addr
->sin6_addr
) &&
631 (ia
= ifa_ifwithaddr((struct sockaddr
*)addr
)) == NULL
) {
632 error
= EADDRNOTAVAIL
;
636 ((struct in6_ifaddr
*)ia
)->ia6_flags
&
637 (IN6_IFF_ANYCAST
|IN6_IFF_NOTREADY
|
638 IN6_IFF_DETACHED
|IN6_IFF_DEPRECATED
)) {
639 error
= EADDRNOTAVAIL
;
642 inp
->in6p_laddr
= addr
->sin6_addr
;
645 lwkt_replymsg(&msg
->bind
.base
.lmsg
, error
);
649 rip6_connect(netmsg_t msg
)
651 struct socket
*so
= msg
->connect
.base
.nm_so
;
652 struct sockaddr
*nam
= msg
->connect
.nm_nam
;
653 struct inpcb
*inp
= so
->so_pcb
;
654 struct sockaddr_in6
*addr
= (struct sockaddr_in6
*)nam
;
655 struct in6_addr
*in6a
= NULL
;
657 #ifdef ENABLE_DEFAULT_SCOPE
658 struct sockaddr_in6 tmp
;
661 if (nam
->sa_len
!= sizeof(*addr
)) {
665 if (ifnet_array_isempty()) {
666 error
= EADDRNOTAVAIL
;
669 if (addr
->sin6_family
!= AF_INET6
) {
670 error
= EAFNOSUPPORT
;
673 if (IN6_IS_ADDR_V4MAPPED(&addr
->sin6_addr
)) {
674 error
= EADDRNOTAVAIL
;
677 #ifdef ENABLE_DEFAULT_SCOPE
678 if (addr
->sin6_scope_id
== 0) { /* not change if specified */
679 /* avoid overwrites */
682 addr
->sin6_scope_id
= scope6_addr2default(&addr
->sin6_addr
);
685 /* Source address selection. XXX: need pcblookup? */
686 in6a
= in6_selectsrc(addr
, inp
->in6p_outputopts
,
687 inp
->in6p_moptions
, &inp
->in6p_route
,
688 &inp
->in6p_laddr
, &error
, NULL
);
691 error
= EADDRNOTAVAIL
;
693 inp
->in6p_laddr
= *in6a
;
694 inp
->in6p_faddr
= addr
->sin6_addr
;
699 lwkt_replymsg(&msg
->connect
.base
.lmsg
, error
);
703 rip6_shutdown(netmsg_t msg
)
705 socantsendmore(msg
->shutdown
.base
.nm_so
);
706 lwkt_replymsg(&msg
->shutdown
.base
.lmsg
, 0);
710 rip6_send(netmsg_t msg
)
712 struct socket
*so
= msg
->send
.base
.nm_so
;
713 struct mbuf
*m
= msg
->send
.nm_m
;
714 struct sockaddr
*nam
= msg
->send
.nm_addr
;
715 struct mbuf
*control
= msg
->send
.nm_control
;
716 struct inpcb
*inp
= so
->so_pcb
;
717 struct sockaddr_in6 tmp
;
718 struct sockaddr_in6
*dst
;
721 /* always copy sockaddr to avoid overwrites */
722 if (so
->so_state
& SS_ISCONNECTED
) {
729 bzero(&tmp
, sizeof(tmp
));
730 tmp
.sin6_family
= AF_INET6
;
731 tmp
.sin6_len
= sizeof(struct sockaddr_in6
);
732 bcopy(&inp
->in6p_faddr
, &tmp
.sin6_addr
,
733 sizeof(struct in6_addr
));
741 tmp
= *(struct sockaddr_in6
*)nam
;
744 #ifdef ENABLE_DEFAULT_SCOPE
745 if (dst
->sin6_scope_id
== 0) { /* not change if specified */
746 dst
->sin6_scope_id
= scope6_addr2default(&dst
->sin6_addr
);
749 error
= rip6_output(m
, so
, dst
, control
);
751 lwkt_replymsg(&msg
->send
.base
.lmsg
, error
);
754 struct pr_usrreqs rip6_usrreqs
= {
755 .pru_abort
= rip6_abort
,
756 .pru_accept
= pr_generic_notsupp
,
757 .pru_attach
= rip6_attach
,
758 .pru_bind
= rip6_bind
,
759 .pru_connect
= rip6_connect
,
760 .pru_connect2
= pr_generic_notsupp
,
761 .pru_control
= in6_control_dispatch
,
762 .pru_detach
= rip6_detach
,
763 .pru_disconnect
= rip6_disconnect
,
764 .pru_listen
= pr_generic_notsupp
,
765 .pru_peeraddr
= in6_setpeeraddr_dispatch
,
766 .pru_rcvd
= pr_generic_notsupp
,
767 .pru_rcvoob
= pr_generic_notsupp
,
768 .pru_send
= rip6_send
,
769 .pru_sense
= pru_sense_null
,
770 .pru_shutdown
= rip6_shutdown
,
771 .pru_sockaddr
= in6_setsockaddr_dispatch
,
772 .pru_sosend
= sosend
,
773 .pru_soreceive
= soreceive