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 $
30 * $DragonFly: src/sys/netinet6/raw_ip6.c,v 1.26 2008/05/17 20:33:36 dillon Exp $
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. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the University of
48 * California, Berkeley and its contributors.
49 * 4. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94
68 #include "opt_ipsec.h"
69 #include "opt_inet6.h"
71 #include <sys/param.h>
72 #include <sys/malloc.h>
75 #include <sys/socket.h>
77 #include <sys/protosw.h>
78 #include <sys/socketvar.h>
79 #include <sys/errno.h>
80 #include <sys/systm.h>
81 #include <sys/thread2.h>
84 #include <net/route.h>
85 #include <net/if_types.h>
87 #include <netinet/in.h>
88 #include <netinet/in_var.h>
89 #include <netinet/in_systm.h>
90 #include <netinet/ip6.h>
91 #include <netinet6/ip6_var.h>
92 #include <netinet6/ip6_mroute.h>
93 #include <netinet/icmp6.h>
94 #include <netinet/in_pcb.h>
95 #include <netinet6/in6_pcb.h>
96 #include <netinet6/nd6.h>
97 #include <netinet6/ip6protosw.h>
98 #ifdef ENABLE_DEFAULT_SCOPE
99 #include <netinet6/scope6_var.h>
101 #include <netinet6/raw_ip6.h>
104 #include <netinet6/ipsec.h>
105 #include <netinet6/ipsec6.h>
109 #include <netproto/ipsec/ipsec.h>
110 #include <netproto/ipsec/ipsec6.h>
111 #endif /* FAST_IPSEC */
113 #include <machine/stdarg.h>
115 #define satosin6(sa) ((struct sockaddr_in6 *)(sa))
116 #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
119 * Raw interface to IP6 protocol.
122 extern struct inpcbinfo ripcbinfo
;
123 extern u_long rip_sendspace
;
124 extern u_long rip_recvspace
;
126 struct rip6stat rip6stat
;
129 * Setup generic address and protocol structures
130 * for raw_input routine, then pass them along with
134 rip6_input(struct mbuf
**mp
, int *offp
, int proto
)
136 struct mbuf
*m
= *mp
;
137 struct ip6_hdr
*ip6
= mtod(m
, struct ip6_hdr
*);
139 struct inpcb
*last
= 0;
140 struct mbuf
*opts
= NULL
;
141 struct sockaddr_in6 rip6src
;
143 rip6stat
.rip6s_ipackets
++;
145 if (faithprefix_p
!= NULL
&& (*faithprefix_p
)(&ip6
->ip6_dst
)) {
146 /* XXX send icmp6 host/port unreach? */
151 init_sin6(&rip6src
, m
); /* general init */
153 LIST_FOREACH(in6p
, &ripcbinfo
.pcblisthead
, inp_list
) {
154 if (in6p
->in6p_flags
& INP_PLACEMARKER
)
156 if (!(in6p
->in6p_vflag
& INP_IPV6
))
158 if (in6p
->in6p_ip6_nxt
&&
159 in6p
->in6p_ip6_nxt
!= proto
)
161 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
) &&
162 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
, &ip6
->ip6_dst
))
164 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
) &&
165 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
, &ip6
->ip6_src
))
167 if (in6p
->in6p_cksum
!= -1) {
168 rip6stat
.rip6s_isum
++;
169 if (in6_cksum(m
, ip6
->ip6_nxt
, *offp
,
170 m
->m_pkthdr
.len
- *offp
)) {
171 rip6stat
.rip6s_badsum
++;
176 struct mbuf
*n
= m_copy(m
, 0, (int)M_COPYALL
);
180 * Check AH/ESP integrity.
182 if (n
&& ipsec6_in_reject_so(n
, last
->inp_socket
)) {
184 ipsec6stat
.in_polvio
++;
185 /* do not inject data into pcb */
190 * Check AH/ESP integrity.
192 if (n
&& ipsec6_in_reject(n
, last
)) {
194 /* do not inject data into pcb */
196 #endif /*FAST_IPSEC*/
198 if (last
->in6p_flags
& IN6P_CONTROLOPTS
||
199 last
->in6p_socket
->so_options
& SO_TIMESTAMP
)
200 ip6_savecontrol(last
, &opts
, ip6
, n
);
201 /* strip intermediate headers */
203 if (ssb_appendaddr(&last
->in6p_socket
->so_rcv
,
204 (struct sockaddr
*)&rip6src
,
209 rip6stat
.rip6s_fullsock
++;
211 sorwakeup(last
->in6p_socket
);
219 * Check AH/ESP integrity.
221 if (last
&& ipsec6_in_reject_so(m
, last
->inp_socket
)) {
223 ipsec6stat
.in_polvio
++;
224 ip6stat
.ip6s_delivered
--;
225 /* do not inject data into pcb */
230 * Check AH/ESP integrity.
232 if (last
&& ipsec6_in_reject(m
, last
)) {
234 ip6stat
.ip6s_delivered
--;
235 /* do not inject data into pcb */
237 #endif /*FAST_IPSEC*/
239 if (last
->in6p_flags
& IN6P_CONTROLOPTS
||
240 last
->in6p_socket
->so_options
& SO_TIMESTAMP
)
241 ip6_savecontrol(last
, &opts
, ip6
, m
);
242 /* strip intermediate headers */
244 if (ssb_appendaddr(&last
->in6p_socket
->so_rcv
,
245 (struct sockaddr
*)&rip6src
, m
, opts
) == 0) {
249 rip6stat
.rip6s_fullsock
++;
251 sorwakeup(last
->in6p_socket
);
253 rip6stat
.rip6s_nosock
++;
254 if (m
->m_flags
& M_MCAST
)
255 rip6stat
.rip6s_nosockmcast
++;
256 if (proto
== IPPROTO_NONE
)
259 char *prvnxtp
= ip6_get_prevhdr(m
, *offp
); /* XXX */
260 icmp6_error(m
, ICMP6_PARAM_PROB
,
261 ICMP6_PARAMPROB_NEXTHEADER
,
262 prvnxtp
- mtod(m
, char *));
264 ip6stat
.ip6s_delivered
--;
270 rip6_ctlinput(int cmd
, struct sockaddr
*sa
, void *d
)
275 struct ip6ctlparam
*ip6cp
= NULL
;
276 const struct sockaddr_in6
*sa6_src
= NULL
;
277 void (*notify
) (struct inpcb
*, int) = in6_rtchange
;
279 if (sa
->sa_family
!= AF_INET6
||
280 sa
->sa_len
!= sizeof(struct sockaddr_in6
))
283 if ((unsigned)cmd
>= PRC_NCMDS
)
285 if (PRC_IS_REDIRECT(cmd
))
286 notify
= in6_rtchange
, d
= NULL
;
287 else if (cmd
== PRC_HOSTDEAD
)
289 else if (inet6ctlerrmap
[cmd
] == 0)
292 /* if the parameter is from icmp6, decode it. */
294 ip6cp
= (struct ip6ctlparam
*)d
;
296 ip6
= ip6cp
->ip6c_ip6
;
297 off
= ip6cp
->ip6c_off
;
298 sa6_src
= ip6cp
->ip6c_src
;
305 in6_pcbnotify(&ripcbinfo
.pcblisthead
, sa
, 0,
306 (const struct sockaddr
*)sa6_src
, 0, cmd
, 0, notify
);
310 * Generate IPv6 header and pass packet to ip6_output.
311 * Tack on options user may have setup with control call.
314 rip6_output(struct mbuf
*m
, struct socket
*so
, ...)
316 struct sockaddr_in6
*dstsock
;
317 struct mbuf
*control
;
318 struct in6_addr
*dst
;
321 u_int plen
= m
->m_pkthdr
.len
;
323 struct ip6_pktopts opt
, *optp
= 0;
324 struct ifnet
*oifp
= NULL
;
325 int type
= 0, code
= 0; /* for ICMPv6 output statistics only */
330 dstsock
= __va_arg(ap
, struct sockaddr_in6
*);
331 control
= __va_arg(ap
, struct mbuf
*);
337 if (so
->so_cred
->cr_uid
== 0)
339 dst
= &dstsock
->sin6_addr
;
341 if ((error
= ip6_setpktoptions(control
, &opt
, priv
, 0)) != 0)
345 optp
= in6p
->in6p_outputopts
;
348 * For an ICMPv6 packet, we should know its type and code
349 * to update statistics.
351 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
) {
352 struct icmp6_hdr
*icmp6
;
353 if (m
->m_len
< sizeof(struct icmp6_hdr
) &&
354 (m
= m_pullup(m
, sizeof(struct icmp6_hdr
))) == NULL
) {
358 icmp6
= mtod(m
, struct icmp6_hdr
*);
359 type
= icmp6
->icmp6_type
;
360 code
= icmp6
->icmp6_code
;
363 M_PREPEND(m
, sizeof(*ip6
), MB_WAIT
);
364 ip6
= mtod(m
, struct ip6_hdr
*);
367 * Next header might not be ICMP6 but use its pseudo header anyway.
372 * If the scope of the destination is link-local, embed the interface
373 * index in the address.
375 * XXX advanced-api value overrides sin6_scope_id
377 if (IN6_IS_SCOPE_LINKLOCAL(&ip6
->ip6_dst
)) {
378 struct in6_pktinfo
*pi
;
381 * XXX Boundary check is assumed to be already done in
382 * ip6_setpktoptions().
384 if (optp
&& (pi
= optp
->ip6po_pktinfo
) && pi
->ipi6_ifindex
) {
385 ip6
->ip6_dst
.s6_addr16
[1] = htons(pi
->ipi6_ifindex
);
386 oifp
= ifindex2ifnet
[pi
->ipi6_ifindex
];
387 } else if (IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
) &&
388 in6p
->in6p_moptions
&&
389 in6p
->in6p_moptions
->im6o_multicast_ifp
) {
390 oifp
= in6p
->in6p_moptions
->im6o_multicast_ifp
;
391 ip6
->ip6_dst
.s6_addr16
[1] = htons(oifp
->if_index
);
392 } else if (dstsock
->sin6_scope_id
) {
394 if (dstsock
->sin6_scope_id
< 0
395 || if_index
< dstsock
->sin6_scope_id
) {
396 error
= ENXIO
; /* XXX EINVAL? */
399 ip6
->ip6_dst
.s6_addr16
[1]
400 = htons(dstsock
->sin6_scope_id
& 0xffff);/*XXX*/
405 * Source address selection.
408 struct in6_addr
*in6a
;
410 if ((in6a
= in6_selectsrc(dstsock
, optp
,
414 &error
, NULL
)) == NULL
) {
416 error
= EADDRNOTAVAIL
;
419 ip6
->ip6_src
= *in6a
;
420 if (in6p
->in6p_route
.ro_rt
)
421 oifp
= ifindex2ifnet
[in6p
->in6p_route
.ro_rt
->rt_ifp
->if_index
];
423 ip6
->ip6_flow
= (ip6
->ip6_flow
& ~IPV6_FLOWINFO_MASK
) |
424 (in6p
->in6p_flowinfo
& IPV6_FLOWINFO_MASK
);
425 ip6
->ip6_vfc
= (ip6
->ip6_vfc
& ~IPV6_VERSION_MASK
) |
426 (IPV6_VERSION
& IPV6_VERSION_MASK
);
427 /* ip6_plen will be filled in ip6_output, so not fill it here. */
428 ip6
->ip6_nxt
= in6p
->in6p_ip6_nxt
;
429 ip6
->ip6_hlim
= in6_selecthlim(in6p
, oifp
);
431 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
||
432 in6p
->in6p_cksum
!= -1) {
437 /* compute checksum */
438 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
)
439 off
= offsetof(struct icmp6_hdr
, icmp6_cksum
);
441 off
= in6p
->in6p_cksum
;
442 if (plen
< off
+ 1) {
446 off
+= sizeof(struct ip6_hdr
);
449 while (n
&& n
->m_len
<= off
) {
455 p
= (u_int16_t
*)(mtod(n
, caddr_t
) + off
);
457 *p
= in6_cksum(m
, ip6
->ip6_nxt
, sizeof(*ip6
), plen
);
460 error
= ip6_output(m
, optp
, &in6p
->in6p_route
, 0,
461 in6p
->in6p_moptions
, &oifp
, in6p
);
462 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
) {
464 icmp6_ifoutstat_inc(oifp
, type
, code
);
465 icmp6stat
.icp6s_outhist
[type
]++;
467 rip6stat
.rip6s_opackets
++;
476 if (optp
== &opt
&& optp
->ip6po_rthdr
&& optp
->ip6po_route
.ro_rt
)
477 RTFREE(optp
->ip6po_route
.ro_rt
);
480 ip6_clearpktopts(optp
, 0, -1);
487 * Raw IPv6 socket option processing.
490 rip6_ctloutput(struct socket
*so
, struct sockopt
*sopt
)
494 if (sopt
->sopt_level
== IPPROTO_ICMPV6
)
496 * XXX: is it better to call icmp6_ctloutput() directly
499 return (icmp6_ctloutput(so
, sopt
));
500 else if (sopt
->sopt_level
!= IPPROTO_IPV6
)
505 switch (sopt
->sopt_dir
) {
507 switch (sopt
->sopt_name
) {
515 error
= ip6_mrouter_get(so
, sopt
);
518 error
= ip6_ctloutput(so
, sopt
);
524 switch (sopt
->sopt_name
) {
532 error
= ip6_mrouter_set(so
, sopt
);
535 error
= ip6_ctloutput(so
, sopt
);
545 rip6_attach(struct socket
*so
, int proto
, struct pru_attach_info
*ai
)
551 if (jailed(ai
->p_ucred
) && jail_allow_raw_sockets
)
552 flag
= NULL_CRED_OKAY
| PRISON_ROOT
;
554 flag
= NULL_CRED_OKAY
;
558 panic("rip6_attach");
559 if ((error
= suser_cred(ai
->p_ucred
, flag
)) != 0)
562 error
= soreserve(so
, rip_sendspace
, rip_recvspace
, ai
->sb_rlimit
);
566 error
= in_pcballoc(so
, &ripcbinfo
);
570 inp
= (struct inpcb
*)so
->so_pcb
;
571 inp
->inp_vflag
|= INP_IPV6
;
572 inp
->in6p_ip6_nxt
= (long)proto
;
573 inp
->in6p_hops
= -1; /* use kernel default */
574 inp
->in6p_cksum
= -1;
575 MALLOC(inp
->in6p_icmp6filt
, struct icmp6_filter
*,
576 sizeof(struct icmp6_filter
), M_PCB
, M_NOWAIT
);
577 if (inp
->in6p_icmp6filt
!= NULL
)
578 ICMP6_FILTER_SETPASSALL(inp
->in6p_icmp6filt
);
583 rip6_detach(struct socket
*so
)
589 panic("rip6_detach");
591 if (so
== ip6_mrouter
)
593 if (inp
->in6p_icmp6filt
) {
594 FREE(inp
->in6p_icmp6filt
, M_PCB
);
595 inp
->in6p_icmp6filt
= NULL
;
602 rip6_abort(struct socket
*so
)
604 soisdisconnected(so
);
605 return rip6_detach(so
);
609 rip6_disconnect(struct socket
*so
)
611 struct inpcb
*inp
= so
->so_pcb
;
613 if (!(so
->so_state
& SS_ISCONNECTED
))
615 inp
->in6p_faddr
= kin6addr_any
;
616 return rip6_abort(so
);
620 rip6_bind(struct socket
*so
, struct sockaddr
*nam
, struct thread
*td
)
622 struct inpcb
*inp
= so
->so_pcb
;
623 struct sockaddr_in6
*addr
= (struct sockaddr_in6
*)nam
;
624 struct ifaddr
*ia
= NULL
;
626 if (nam
->sa_len
!= sizeof(*addr
))
629 if (TAILQ_EMPTY(&ifnet
) || addr
->sin6_family
!= AF_INET6
)
630 return EADDRNOTAVAIL
;
631 #ifdef ENABLE_DEFAULT_SCOPE
632 if (addr
->sin6_scope_id
== 0) { /* not change if specified */
633 addr
->sin6_scope_id
= scope6_addr2default(&addr
->sin6_addr
);
636 if (!IN6_IS_ADDR_UNSPECIFIED(&addr
->sin6_addr
) &&
637 (ia
= ifa_ifwithaddr((struct sockaddr
*)addr
)) == NULL
)
638 return EADDRNOTAVAIL
;
640 ((struct in6_ifaddr
*)ia
)->ia6_flags
&
641 (IN6_IFF_ANYCAST
|IN6_IFF_NOTREADY
|
642 IN6_IFF_DETACHED
|IN6_IFF_DEPRECATED
)) {
643 return (EADDRNOTAVAIL
);
645 inp
->in6p_laddr
= addr
->sin6_addr
;
650 rip6_connect(struct socket
*so
, struct sockaddr
*nam
, struct thread
*td
)
652 struct inpcb
*inp
= so
->so_pcb
;
653 struct sockaddr_in6
*addr
= (struct sockaddr_in6
*)nam
;
654 struct in6_addr
*in6a
= NULL
;
656 #ifdef ENABLE_DEFAULT_SCOPE
657 struct sockaddr_in6 tmp
;
660 if (nam
->sa_len
!= sizeof(*addr
))
662 if (TAILQ_EMPTY(&ifnet
))
663 return EADDRNOTAVAIL
;
664 if (addr
->sin6_family
!= AF_INET6
)
666 #ifdef ENABLE_DEFAULT_SCOPE
667 if (addr
->sin6_scope_id
== 0) { /* not change if specified */
668 /* avoid overwrites */
671 addr
->sin6_scope_id
= scope6_addr2default(&addr
->sin6_addr
);
674 /* Source address selection. XXX: need pcblookup? */
675 in6a
= in6_selectsrc(addr
, inp
->in6p_outputopts
,
676 inp
->in6p_moptions
, &inp
->in6p_route
,
677 &inp
->in6p_laddr
, &error
, NULL
);
679 return (error
? error
: EADDRNOTAVAIL
);
680 inp
->in6p_laddr
= *in6a
;
681 inp
->in6p_faddr
= addr
->sin6_addr
;
687 rip6_shutdown(struct socket
*so
)
694 rip6_send(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*nam
,
695 struct mbuf
*control
, struct thread
*td
)
697 struct inpcb
*inp
= so
->so_pcb
;
698 struct sockaddr_in6 tmp
;
699 struct sockaddr_in6
*dst
;
701 /* always copy sockaddr to avoid overwrites */
702 if (so
->so_state
& SS_ISCONNECTED
) {
708 bzero(&tmp
, sizeof(tmp
));
709 tmp
.sin6_family
= AF_INET6
;
710 tmp
.sin6_len
= sizeof(struct sockaddr_in6
);
711 bcopy(&inp
->in6p_faddr
, &tmp
.sin6_addr
,
712 sizeof(struct in6_addr
));
719 tmp
= *(struct sockaddr_in6
*)nam
;
722 #ifdef ENABLE_DEFAULT_SCOPE
723 if (dst
->sin6_scope_id
== 0) { /* not change if specified */
724 dst
->sin6_scope_id
= scope6_addr2default(&dst
->sin6_addr
);
727 return rip6_output(m
, so
, dst
, control
);
730 struct pr_usrreqs rip6_usrreqs
= {
731 .pru_abort
= rip6_abort
,
732 .pru_accept
= pru_accept_notsupp
,
733 .pru_attach
= rip6_attach
,
734 .pru_bind
= rip6_bind
,
735 .pru_connect
= rip6_connect
,
736 .pru_connect2
= pru_connect2_notsupp
,
737 .pru_control
= in6_control
,
738 .pru_detach
= rip6_detach
,
739 .pru_disconnect
= rip6_disconnect
,
740 .pru_listen
= pru_listen_notsupp
,
741 .pru_peeraddr
= in6_setpeeraddr
,
742 .pru_rcvd
= pru_rcvd_notsupp
,
743 .pru_rcvoob
= pru_rcvoob_notsupp
,
744 .pru_send
= rip6_send
,
745 .pru_sense
= pru_sense_null
,
746 .pru_shutdown
= rip6_shutdown
,
747 .pru_sockaddr
= in6_setsockaddr
,
748 .pru_sosend
= sosend
,
749 .pru_soreceive
= soreceive
,