1 /* $KAME: udp6_usrreq.c,v 1.25 2000/04/04 11:18:10 itojun Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Copyright (c) 1982, 1986, 1989, 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. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * @(#)udp_var.h 8.1 (Berkeley) 6/10/93
70 #include <sys/param.h>
71 #include <sys/kernel.h>
72 #include <sys/malloc.h>
74 #include <sys/protosw.h>
75 #include <sys/socket.h>
76 #include <sys/socketvar.h>
77 #include <sys/sysctl.h>
78 #include <sys/errno.h>
80 #include <sys/systm.h>
81 #include <sys/syslog.h>
85 #include <net/route.h>
86 #include <net/if_types.h>
88 #include <netinet/in.h>
89 #include <netinet/in_systm.h>
90 #include <netinet/ip.h>
91 #include <netinet/in_pcb.h>
92 #include <netinet/in_var.h>
93 #include <netinet/ip_var.h>
94 #include <netinet/udp.h>
95 #include <netinet/udp_var.h>
96 #include <netinet/ip6.h>
97 #include <netinet6/ip6_var.h>
98 #include <netinet6/in6_pcb.h>
99 #include <netinet/icmp6.h>
100 #include <netinet6/udp6_var.h>
101 #include <netinet6/ip6protosw.h>
104 #include <netinet6/ipsec.h>
110 * UDP protocol inplementation.
111 * Per RFC 768, August, 1980.
114 extern struct protosw inetsw
[];
115 static int in6_mcmatch
__P((struct inpcb
*, struct in6_addr
*, struct ifnet
*));
116 static int udp6_detach
__P((struct socket
*so
));
119 in6_mcmatch(in6p
, ia6
, ifp
)
121 register struct in6_addr
*ia6
;
124 struct ip6_moptions
*im6o
= in6p
->in6p_moptions
;
125 struct in6_multi_mship
*imm
;
130 for (imm
= im6o
->im6o_memberships
.lh_first
; imm
!= NULL
;
131 imm
= imm
->i6mm_chain
.le_next
) {
133 imm
->i6mm_maddr
->in6m_ifp
== ifp
) &&
134 IN6_ARE_ADDR_EQUAL(&imm
->i6mm_maddr
->in6m_addr
,
142 udp6_input(mp
, offp
, proto
)
146 struct mbuf
*m
= *mp
;
147 register struct ip6_hdr
*ip6
;
148 register struct udphdr
*uh
;
149 register struct inpcb
*in6p
;
150 struct ip6_recvpktopts opts
;
153 struct sockaddr_in6 udp_in6
;
155 #if defined(NFAITH) && 0 < NFAITH
156 if (m
->m_pkthdr
.rcvif
) {
157 if (m
->m_pkthdr
.rcvif
->if_type
== IFT_FAITH
) {
158 /* XXX send icmp6 host/port unreach? */
164 udpstat
.udps_ipackets
++;
165 bzero(&opts
, sizeof(opts
));
167 IP6_EXTHDR_CHECK(m
, off
, sizeof(struct udphdr
), IPPROTO_DONE
);
169 ip6
= mtod(m
, struct ip6_hdr
*);
170 plen
= ntohs(ip6
->ip6_plen
) - off
+ sizeof(*ip6
);
171 uh
= (struct udphdr
*)((caddr_t
)ip6
+ off
);
172 ulen
= ntohs((u_short
)uh
->uh_ulen
);
175 udpstat
.udps_badlen
++;
180 * Checksum extended UDP header and data.
182 // if (uh->uh_sum == 0)
183 // udpstat.udps_nosum++;
184 else if (in6_cksum(m
, IPPROTO_UDP
, off
, ulen
) != 0) {
185 udpstat
.udps_badsum
++;
189 if (IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
)) {
193 * Deliver a multicast datagram to all sockets
194 * for which the local and remote addresses and ports match
195 * those of the incoming datagram. This allows more than
196 * one process to receive multicasts on the same port.
197 * (This really ought to be done for unicast datagrams as
198 * well, but that would cause problems with existing
199 * applications that open both address-specific sockets and
200 * a wildcard socket listening to the same port -- they would
201 * end up receiving duplicates of every unicast datagram.
202 * Those applications open the multiple sockets to overcome an
203 * inadequacy of the UDP socket interface, but for backwards
204 * compatibility we avoid the problem here rather than
205 * fixing the interface. Maybe 4.5BSD will remedy this?)
209 * In a case that laddr should be set to the link-local
210 * address (this happens in RIPng), the multicast address
211 * specified in the received packet does not match with
212 * laddr. To cure this situation, the matching is relaxed
213 * if the receiving interface is the same as one specified
214 * in the socket and if the destination multicast address
215 * matches one of the multicast groups specified in the socket.
219 * Construct sockaddr format source address.
221 init_sin6(&udp_in6
, m
); /* general init */
222 udp_in6
.sin6_port
= uh
->uh_sport
;
224 * KAME note: usually we drop udphdr from mbuf here.
225 * We need udphdr for IPsec processing so we do that later.
229 * Locate pcb(s) for datagram.
230 * (Algorithm copied from raw_intr().)
233 LIST_FOREACH(in6p
, &udb
, inp_list
) {
234 if ((in6p
->inp_vflag
& INP_IPV6
) == 0)
236 if (in6p
->in6p_lport
!= uh
->uh_dport
)
238 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
)) {
239 if (!IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
,
241 !in6_mcmatch(in6p
, &ip6
->ip6_dst
,
245 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
)) {
246 if (!IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
,
248 in6p
->in6p_fport
!= uh
->uh_sport
)
257 * Check AH/ESP integrity.
259 if (ipsec6_in_reject_so(m
, last
->inp_socket
))
260 ipsec6stat
.in_polvio
++;
261 /* do not inject data into pcb */
264 if ((n
= m_copy(m
, 0, M_COPYALL
)) != NULL
) {
267 * m_copy(m, offset, ...) above.
268 * sbappendaddr() expects M_PKTHDR,
269 * and m_copy() will copy M_PKTHDR
270 * only if offset is 0.
272 if (last
->in6p_flags
& IN6P_CONTROLOPTS
273 || last
->in6p_socket
->so_options
& SO_TIMESTAMP
)
274 ip6_savecontrol(last
, ip6
, n
,
277 m_adj(n
, off
+ sizeof(struct udphdr
));
278 if (sbappendaddr(&last
->in6p_socket
->so_rcv
,
279 (struct sockaddr
*)&udp_in6
,
280 n
, opts
.head
) == 0) {
284 udpstat
.udps_fullsock
++;
286 sorwakeup(last
->in6p_socket
);
287 bzero(&opts
, sizeof(opts
));
292 * Don't look for additional matches if this one does
293 * not have either the SO_REUSEPORT or SO_REUSEADDR
294 * socket options set. This heuristic avoids searching
295 * through all pcbs in the common case of a non-shared
296 * port. It assumes that an application will never
297 * clear these options after setting them.
299 if ((last
->in6p_socket
->so_options
&
300 (SO_REUSEPORT
|SO_REUSEADDR
)) == 0)
306 * No matching pcb found; discard datagram.
307 * (No need to send an ICMP Port Unreachable
308 * for a broadcast or multicast datgram.)
310 udpstat
.udps_noport
++;
311 // udpstat.udps_noportmcast++;
316 * Check AH/ESP integrity.
318 if (ipsec6_in_reject_so(m
, last
->inp_socket
)) {
319 ipsec6stat
.in_polvio
++;
323 if (last
->in6p_flags
& IN6P_CONTROLOPTS
324 || last
->in6p_socket
->so_options
& SO_TIMESTAMP
)
325 ip6_savecontrol(last
, ip6
, m
, &opts
, NULL
);
327 m_adj(m
, off
+ sizeof(struct udphdr
));
328 if (sbappendaddr(&last
->in6p_socket
->so_rcv
,
329 (struct sockaddr
*)&udp_in6
,
330 m
, opts
.head
) == 0) {
331 udpstat
.udps_fullsock
++;
334 sorwakeup(last
->in6p_socket
);
338 * Locate pcb for datagram.
340 in6p
= in6_pcblookup_hash(&udbinfo
, &ip6
->ip6_src
, uh
->uh_sport
,
341 &ip6
->ip6_dst
, uh
->uh_dport
, 1,
345 char buf
[INET6_ADDRSTRLEN
];
347 strcpy(buf
, ip6_sprintf(&ip6
->ip6_dst
));
349 "Connection attempt to UDP %s:%d from %s:%d\n",
350 buf
, ntohs(uh
->uh_dport
),
351 ip6_sprintf(&ip6
->ip6_src
), ntohs(uh
->uh_sport
));
353 udpstat
.udps_noport
++;
354 if (m
->m_flags
& M_MCAST
) {
355 printf("UDP6: M_MCAST is set in a unicast packet.\n");
356 // udpstat.udps_noportmcast++;
359 icmp6_error(m
, ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOPORT
, 0);
364 * Check AH/ESP integrity.
366 if (ipsec6_in_reject_so(m
, in6p
->in6p_socket
)) {
367 ipsec6stat
.in_polvio
++;
373 * Construct sockaddr format source address.
374 * Stuff source address and datagram in user buffer.
376 init_sin6(&udp_in6
, m
); /* general init */
377 udp_in6
.sin6_port
= uh
->uh_sport
;
378 if (in6p
->in6p_flags
& IN6P_CONTROLOPTS
379 || in6p
->in6p_socket
->so_options
& SO_TIMESTAMP
)
380 ip6_savecontrol(in6p
, ip6
, m
, &opts
, NULL
);
381 m_adj(m
, off
+ sizeof(struct udphdr
));
382 if (sbappendaddr(&in6p
->in6p_socket
->so_rcv
,
383 (struct sockaddr
*)&udp_in6
,
384 m
, opts
.head
) == 0) {
385 udpstat
.udps_fullsock
++;
388 sorwakeup(in6p
->in6p_socket
);
399 udp6_ctlinput(cmd
, sa
, d
)
404 register struct udphdr
*uhp
;
406 struct sockaddr_in6 sa6
;
410 void (*notify
) __P((struct inpcb
*, int)) = udp_notify
;
412 if (sa
->sa_family
!= AF_INET6
||
413 sa
->sa_len
!= sizeof(struct sockaddr_in6
))
416 if ((unsigned)cmd
>= PRC_NCMDS
)
418 if (PRC_IS_REDIRECT(cmd
))
419 notify
= in6_rtchange
, d
= NULL
;
420 else if (cmd
== PRC_HOSTDEAD
)
422 else if (inet6ctlerrmap
[cmd
] == 0)
425 /* if the parameter is from icmp6, decode it. */
427 struct ip6ctlparam
*ip6cp
= (struct ip6ctlparam
*)d
;
429 ip6
= ip6cp
->ip6c_ip6
;
430 off
= ip6cp
->ip6c_off
;
436 /* translate addresses into internal form */
437 sa6
= *(struct sockaddr_in6
*)sa
;
438 if (IN6_IS_ADDR_LINKLOCAL(&sa6
.sin6_addr
) && m
&& m
->m_pkthdr
.rcvif
)
439 sa6
.sin6_addr
.s6_addr16
[1] = htons(m
->m_pkthdr
.rcvif
->if_index
);
443 * XXX: We assume that when IPV6 is non NULL,
444 * M and OFF are valid.
448 /* translate addresses into internal form */
449 memcpy(&s
, &ip6
->ip6_src
, sizeof(s
));
450 if (IN6_IS_ADDR_LINKLOCAL(&s
))
451 s
.s6_addr16
[1] = htons(m
->m_pkthdr
.rcvif
->if_index
);
453 if (m
->m_len
< off
+ sizeof(uh
)) {
455 * this should be rare case,
456 * so we compromise on this copy...
458 m_copydata(m
, off
, sizeof(uh
), (caddr_t
)&uh
);
461 uhp
= (struct udphdr
*)(mtod(m
, caddr_t
) + off
);
462 (void) in6_pcbnotify(&udb
, (struct sockaddr
*)&sa6
,
464 uhp
->uh_sport
, cmd
, notify
);
466 (void) in6_pcbnotify(&udb
, (struct sockaddr
*)&sa6
, 0,
467 &zeroin6_addr
, 0, cmd
, notify
);
471 udp6_getcred SYSCTL_HANDLER_ARGS
473 struct sockaddr_in6 addrs
[2];
477 error
= suser(req
->p
->p_ucred
, &req
->p
->p_acflag
);
481 if (req
->newlen
!= sizeof(addrs
))
483 if (req
->oldlen
!= sizeof(struct ucred
))
485 error
= SYSCTL_IN(req
, addrs
, sizeof(addrs
));
489 inp
= in6_pcblookup_hash(&udbinfo
, &addrs
[1].sin6_addr
,
491 &addrs
[0].sin6_addr
, addrs
[0].sin6_port
,
493 if (!inp
|| !inp
->inp_socket
|| !inp
->inp_socket
->so_cred
) {
497 error
= SYSCTL_OUT(req
, inp
->inp_socket
->so_cred
->pc_ucred
,
498 sizeof(struct ucred
));
505 SYSCTL_PROC(_net_inet6_udp6
, OID_AUTO
, getcred
, CTLTYPE_OPAQUE
|CTLFLAG_RW
,
507 udp6_getcred
, "S,ucred", "Get the ucred of a UDP6 connection");
510 udp6_output(in6p
, m
, addr6
, control
, p
)
511 register struct inpcb
*in6p
;
512 register struct mbuf
*m
;
513 struct sockaddr
*addr6
;
514 struct mbuf
*control
;
517 register int ulen
= m
->m_pkthdr
.len
;
518 int plen
= sizeof(struct udphdr
) + ulen
;
521 struct in6_addr laddr6
;
522 int s
= 0, error
= 0;
523 struct ip6_pktopts opt
, *stickyopt
= in6p
->in6p_outputopts
;
527 if (error
= ip6_setpktoptions(control
, &opt
,
529 suser(p
->p_ucred
, &p
->p_acflag
), 0))
531 in6p
->in6p_outputopts
= &opt
;
535 laddr6
= in6p
->in6p_laddr
;
536 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
)) {
541 * Must block input while temporarily connected.
545 * XXX: the user might want to overwrite the local address
546 * via an ancillary data.
548 bzero(&in6p
->in6p_laddr
, sizeof(struct in6_addr
));
549 error
= in6_pcbconnect(in6p
, addr6
, p
);
555 if (IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
)) {
561 * Calculate data length and get a mbuf
562 * for UDP and IP6 headers.
564 M_PREPEND(m
, sizeof(struct ip6_hdr
) + sizeof(struct udphdr
),
574 * Stuff checksum and output datagram.
576 ip6
= mtod(m
, struct ip6_hdr
*);
577 ip6
->ip6_flow
= in6p
->in6p_flowinfo
& IPV6_FLOWINFO_MASK
;
578 ip6
->ip6_vfc
|= IPV6_VERSION
;
579 #if 0 /* ip6_plen will be filled in ip6_output. */
580 ip6
->ip6_plen
= htons((u_short
)plen
);
582 ip6
->ip6_nxt
= IPPROTO_UDP
;
583 ip6
->ip6_hlim
= in6_selecthlim(in6p
,
584 in6p
->in6p_route
.ro_rt
?
585 in6p
->in6p_route
.ro_rt
->rt_ifp
:
587 ip6
->ip6_src
= in6p
->in6p_laddr
;
588 ip6
->ip6_dst
= in6p
->in6p_faddr
;
590 udp6
= (struct udphdr
*)(ip6
+ 1);
591 udp6
->uh_sport
= in6p
->in6p_lport
;
592 udp6
->uh_dport
= in6p
->in6p_fport
;
593 udp6
->uh_ulen
= htons((u_short
)plen
);
596 if ((udp6
->uh_sum
= in6_cksum(m
, IPPROTO_UDP
,
597 sizeof(struct ip6_hdr
), plen
)) == 0) {
598 udp6
->uh_sum
= 0xffff;
602 if (in6p
->in6p_flags
& IN6P_MINMTU
)
603 flags
|= IPV6_MINMTU
;
605 udpstat
.udps_opackets
++;
608 ipsec_setsocket(m
, in6p
->in6p_socket
);
610 error
= ip6_output(m
, in6p
->in6p_outputopts
, &in6p
->in6p_route
,
611 flags
, in6p
->in6p_moptions
, NULL
);
614 in6_pcbdisconnect(in6p
);
615 in6p
->in6p_laddr
= laddr6
;
625 ip6_clearpktopts(in6p
->in6p_outputopts
, 0, -1);
626 in6p
->in6p_outputopts
= stickyopt
;
633 udp6_abort(struct socket
*so
)
640 return EINVAL
; /* ??? possible? panic instead? */
641 soisdisconnected(so
);
649 udp6_attach(struct socket
*so
, int proto
, struct proc
*p
)
658 if (so
->so_snd
.sb_hiwat
== 0 || so
->so_rcv
.sb_hiwat
== 0) {
659 error
= soreserve(so
, udp_sendspace
, udp_recvspace
);
664 error
= in_pcballoc(so
, &udbinfo
, p
);
668 inp
= (struct inpcb
*)so
->so_pcb
;
669 inp
->inp_vflag
|= INP_IPV6
;
670 inp
->in6p_hops
= -1; /* use kernel default */
671 inp
->in6p_cksum
= -1; /* just to be sure */
673 error
= ipsec_init_policy(so
, &inp
->in6p_sp
);
683 udp6_bind(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
692 inp
->inp_vflag
&= ~INP_IPV4
;
693 inp
->inp_vflag
|= INP_IPV6
;
694 if (ip6_mapped_addr_on
&& (inp
->inp_flags
& IN6P_BINDV6ONLY
) == 0) {
695 struct sockaddr_in6
*sin6_p
;
697 sin6_p
= (struct sockaddr_in6
*)nam
;
699 if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p
->sin6_addr
))
700 inp
->inp_vflag
|= INP_IPV4
;
701 else if (IN6_IS_ADDR_V4MAPPED(&sin6_p
->sin6_addr
)) {
702 struct sockaddr_in sin
;
704 in6_sin6_2_sin(&sin
, sin6_p
);
705 inp
->inp_vflag
|= INP_IPV4
;
706 inp
->inp_vflag
&= ~INP_IPV6
;
708 error
= in_pcbbind(inp
, (struct sockaddr
*)&sin
, p
);
715 error
= in6_pcbbind(inp
, nam
, p
);
721 udp6_connect(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
730 if (ip6_mapped_addr_on
) {
731 struct sockaddr_in6
*sin6_p
;
733 sin6_p
= (struct sockaddr_in6
*)nam
;
734 if (IN6_IS_ADDR_V4MAPPED(&sin6_p
->sin6_addr
)) {
735 struct sockaddr_in sin
;
737 if (inp
->inp_faddr
.s_addr
!= INADDR_ANY
)
739 in6_sin6_2_sin(&sin
, sin6_p
);
741 error
= in_pcbconnect(inp
, (struct sockaddr
*)&sin
, p
);
744 inp
->inp_vflag
|= INP_IPV4
;
745 inp
->inp_vflag
&= ~INP_IPV6
;
752 if (!IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_faddr
))
755 error
= in6_pcbconnect(inp
, nam
, p
);
756 if (ip6_auto_flowlabel
) {
757 inp
->in6p_flowinfo
&= ~IPV6_FLOWLABEL_MASK
;
758 inp
->in6p_flowinfo
|=
759 (htonl(ip6_flow_seq
++) & IPV6_FLOWLABEL_MASK
);
763 if (ip6_mapped_addr_on
) { /* should be non mapped addr */
764 inp
->inp_vflag
&= ~INP_IPV4
;
765 inp
->inp_vflag
|= INP_IPV6
;
773 udp6_detach(struct socket
*so
)
788 udp6_disconnect(struct socket
*so
)
797 if (inp
->inp_vflag
& INP_IPV4
) {
798 struct pr_usrreqs
*pru
;
800 pru
= ip_protox
[IPPROTO_UDP
]->pr_usrreqs
;
801 return ((*pru
->pru_disconnect
)(so
));
804 if (IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_faddr
))
808 in6_pcbdisconnect(inp
);
809 inp
->in6p_laddr
= in6addr_any
;
811 so
->so_state
&= ~SS_ISCONNECTED
; /* XXX */
816 udp6_send(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*addr
,
817 struct mbuf
*control
, struct proc
*p
)
827 if (ip6_mapped_addr_on
) {
829 struct sockaddr_in6
*sin6
= 0;
832 hasv4addr
= (inp
->inp_vflag
& INP_IPV4
);
834 sin6
= (struct sockaddr_in6
*)addr
;
835 hasv4addr
= IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)
839 struct pr_usrreqs
*pru
;
843 in6_sin6_2_sin_in_sock(addr
);
844 pru
= ip_protox
[IPPROTO_UDP
]->pr_usrreqs
;
845 error
= ((*pru
->pru_send
)(so
, flags
, m
, addr
, control
,
847 /* addr will just be freed in sendit(). */
852 return udp6_output(inp
, m
, addr
, control
, p
);
855 struct pr_usrreqs udp6_usrreqs
= {
856 udp6_abort
, pru_accept_notsupp
, udp6_attach
, udp6_bind
, udp6_connect
,
857 pru_connect2_notsupp
, in6_control
, udp6_detach
, udp6_disconnect
,
858 pru_listen_notsupp
, in6_mapped_peeraddr
, pru_rcvd_notsupp
,
859 pru_rcvoob_notsupp
, udp6_send
, pru_sense_null
, udp_shutdown
,
860 in6_mapped_sockaddr
, sosend
, soreceive
, sopoll