2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 /* $FreeBSD: src/sys/netinet6/udp6_usrreq.c,v 1.6.2.6 2001/07/29 19:32:40 ume Exp $ */
30 /* $KAME: udp6_usrreq.c,v 1.27 2001/05/21 05:45:10 jinmei Exp $ */
33 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
34 * 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 project 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 PROJECT 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 PROJECT 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
62 * Copyright (c) 1982, 1986, 1989, 1993
63 * The Regents of the University of California. All rights reserved.
65 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions
68 * 1. Redistributions of source code must retain the above copyright
69 * notice, this list of conditions and the following disclaimer.
70 * 2. Redistributions in binary form must reproduce the above copyright
71 * notice, this list of conditions and the following disclaimer in the
72 * documentation and/or other materials provided with the distribution.
73 * 3. All advertising materials mentioning features or use of this software
74 * must display the following acknowledgement:
75 * This product includes software developed by the University of
76 * California, Berkeley and its contributors.
77 * 4. Neither the name of the University nor the names of its contributors
78 * may be used to endorse or promote products derived from this software
79 * without specific prior written permission.
81 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
82 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
84 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
85 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
86 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
87 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
88 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
89 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
90 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
93 * @(#)udp_var.h 8.1 (Berkeley) 6/10/93
96 #include <sys/param.h>
97 #include <sys/kernel.h>
98 #include <sys/malloc.h>
100 #include <sys/protosw.h>
101 #include <sys/socket.h>
102 #include <sys/socketvar.h>
103 #include <sys/sysctl.h>
104 #include <sys/errno.h>
105 #include <sys/stat.h>
106 #include <sys/systm.h>
107 #include <sys/syslog.h>
108 #include <sys/proc.h>
109 #include <sys/kauth.h>
112 #include <net/route.h>
113 #include <net/if_types.h>
114 #include <net/ntstat.h>
116 #include <netinet/in.h>
117 #include <netinet/in_systm.h>
118 #include <netinet/ip.h>
119 #include <netinet/in_pcb.h>
120 #include <netinet/in_var.h>
121 #include <netinet/ip_var.h>
122 #include <netinet/udp.h>
123 #include <netinet/udp_var.h>
124 #include <netinet/ip6.h>
125 #include <netinet6/ip6_var.h>
126 #include <netinet6/in6_pcb.h>
127 #include <netinet/icmp6.h>
128 #include <netinet6/udp6_var.h>
129 #include <netinet6/ip6protosw.h>
132 #include <netinet6/ipsec.h>
133 #include <netinet6/ipsec6.h>
134 extern int ipsec_bypass
;
138 * UDP protocol inplementation.
139 * Per RFC 768, August, 1980.
142 extern struct protosw inetsw
[];
143 static int udp6_detach(struct socket
*so
);
144 static void udp6_append(struct inpcb
*, struct ip6_hdr
*,
145 struct sockaddr_in6
*, struct mbuf
*, int);
147 extern void ipfwsyslog( int level
, const char *format
,...);
148 extern int fw_verbose
;
151 #define log_in_vain_log( a ) { \
152 if ( (log_in_vain == 3 ) && (fw_verbose == 2)) { /* Apple logging, log to ipfw.log */ \
158 #define log_in_vain_log( a ) { log a; }
162 * subroutine of udp6_input(), mainly for source code readability.
165 udp6_append(struct inpcb
*last
, __unused
struct ip6_hdr
*ip6
,
166 struct sockaddr_in6
*udp_in6
, struct mbuf
*n
, int off
)
168 struct mbuf
*opts
= NULL
;
171 if (mac_inpcb_check_deliver(last
, n
, AF_INET6
, SOCK_DGRAM
) != 0) {
176 if ((last
->in6p_flags
& IN6P_CONTROLOPTS
) != 0 ||
177 (last
->in6p_socket
->so_options
& SO_TIMESTAMP
) != 0 ||
178 (last
->in6p_socket
->so_options
& SO_TIMESTAMP_MONOTONIC
) != 0) {
179 ret
= ip6_savecontrol(last
, n
, &opts
);
188 locked_add_64(&last
->inp_stat
->rxpackets
, 1);
189 locked_add_64(&last
->inp_stat
->rxbytes
, n
->m_pkthdr
.len
);
191 so_recv_data_stat(last
->in6p_socket
, n
, 0);
192 if (sbappendaddr(&last
->in6p_socket
->so_rcv
,
193 (struct sockaddr
*)udp_in6
, n
, opts
, NULL
) == 0)
194 udpstat
.udps_fullsock
++;
196 sorwakeup(last
->in6p_socket
);
205 #pragma unused(proto)
206 struct mbuf
*m
= *mp
;
208 register struct ip6_hdr
*ip6
;
209 register struct udphdr
*uh
;
210 register struct inpcb
*in6p
;
211 struct mbuf
*opts
= NULL
;
213 int plen
, ulen
, ret
= 0;
214 struct sockaddr_in6 udp_in6
;
215 struct inpcbinfo
*pcbinfo
= &udbinfo
;
216 struct sockaddr_in6 fromsa
;
218 IP6_EXTHDR_CHECK(m
, off
, sizeof(struct udphdr
), return IPPROTO_DONE
);
220 /* Expect 32-bit aligned data pointer on strict-align platforms */
221 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m
);
223 ifp
= m
->m_pkthdr
.rcvif
;
224 ip6
= mtod(m
, struct ip6_hdr
*);
226 udpstat
.udps_ipackets
++;
228 plen
= ntohs(ip6
->ip6_plen
) - off
+ sizeof(*ip6
);
229 uh
= (struct udphdr
*)(void *)((caddr_t
)ip6
+ off
);
230 ulen
= ntohs((u_short
)uh
->uh_ulen
);
233 udpstat
.udps_badlen
++;
235 if (ifp
->if_udp_stat
!= NULL
)
236 atomic_add_64(&ifp
->if_udp_stat
->badlength
, 1);
241 /* destination port of 0 is illegal, based on RFC768. */
242 if (uh
->uh_dport
== 0) {
244 if (ifp
->if_udp_stat
!= NULL
)
245 atomic_add_64(&ifp
->if_udp_stat
->port0
, 1);
251 * Checksum extended UDP header and data.
254 if ((apple_hwcksum_rx
!= 0) && (m
->m_pkthdr
.csum_flags
& CSUM_DATA_VALID
)) {
255 uh
->uh_sum
= m
->m_pkthdr
.csum_data
;
256 uh
->uh_sum
^= 0xffff;
259 if (in6_cksum(m
, IPPROTO_UDP
, off
, ulen
) != 0) {
260 udpstat
.udps_badsum
++;
262 if (ifp
->if_udp_stat
!= NULL
)
263 atomic_add_64(&ifp
->if_udp_stat
->badchksum
, 1);
271 udpstat
.udps_nosum
++;
275 * Construct sockaddr format source address.
277 init_sin6(&fromsa
, m
);
278 fromsa
.sin6_port
= uh
->uh_sport
;
281 if (IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
)) {
282 int reuse_sock
= 0, mcast_delivered
= 0;
283 struct ip6_moptions
*imo
;
284 struct mbuf
*n
= NULL
;
287 * Deliver a multicast datagram to all sockets
288 * for which the local and remote addresses and ports match
289 * those of the incoming datagram. This allows more than
290 * one process to receive multicasts on the same port.
291 * (This really ought to be done for unicast datagrams as
292 * well, but that would cause problems with existing
293 * applications that open both address-specific sockets and
294 * a wildcard socket listening to the same port -- they would
295 * end up receiving duplicates of every unicast datagram.
296 * Those applications open the multiple sockets to overcome an
297 * inadequacy of the UDP socket interface, but for backwards
298 * compatibility we avoid the problem here rather than
299 * fixing the interface. Maybe 4.5BSD will remedy this?)
303 * In a case that laddr should be set to the link-local
304 * address (this happens in RIPng), the multicast address
305 * specified in the received packet does not match with
306 * laddr. To cure this situation, the matching is relaxed
307 * if the receiving interface is the same as one specified
308 * in the socket and if the destination multicast address
309 * matches one of the multicast groups specified in the socket.
313 * Construct sockaddr format source address.
315 init_sin6(&udp_in6
, m
); /* general init */
316 udp_in6
.sin6_port
= uh
->uh_sport
;
318 * KAME note: usually we drop udphdr from mbuf here.
319 * We need udphdr for IPsec processing so we do that later.
323 * Locate pcb(s) for datagram.
324 * (Algorithm copied from raw_intr().)
326 lck_rw_lock_shared(pcbinfo
->mtx
);
328 LIST_FOREACH(in6p
, &udb
, inp_list
) {
330 if ((in6p
->inp_vflag
& INP_IPV6
) == 0)
333 if (ip6_restrictrecvif
&& ifp
!= NULL
&&
334 (ifp
->if_eflags
& IFEF_RESTRICTED_RECV
) &&
335 !(in6p
->in6p_flags
& IN6P_RECV_ANYIF
))
338 if (in_pcb_checkstate(in6p
, WNT_ACQUIRE
, 0) == WNT_STOPUSING
)
341 udp_lock(in6p
->in6p_socket
, 1, 0);
343 if (in_pcb_checkstate(in6p
, WNT_RELEASE
, 1) == WNT_STOPUSING
) {
344 udp_unlock(in6p
->in6p_socket
, 1, 0);
347 if (in6p
->in6p_lport
!= uh
->uh_dport
) {
348 udp_unlock(in6p
->in6p_socket
, 1, 0);
353 * Handle socket delivery policy for any-source
354 * and source-specific multicast. [RFC3678]
356 imo
= in6p
->in6p_moptions
;
357 if (imo
&& IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
)) {
358 struct sockaddr_in6 mcaddr
;
362 bzero(&mcaddr
, sizeof(struct sockaddr_in6
));
363 mcaddr
.sin6_len
= sizeof(struct sockaddr_in6
);
364 mcaddr
.sin6_family
= AF_INET6
;
365 mcaddr
.sin6_addr
= ip6
->ip6_dst
;
367 blocked
= im6o_mc_filter(imo
, ifp
,
368 (struct sockaddr
*)&mcaddr
,
369 (struct sockaddr
*)&fromsa
);
371 if (blocked
!= MCAST_PASS
) {
372 udp_unlock(in6p
->in6p_socket
, 1, 0);
376 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
)) {
377 if (!IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
,
379 in6p
->in6p_fport
!= uh
->uh_sport
) {
380 udp_unlock(in6p
->in6p_socket
, 1, 0);
385 reuse_sock
= in6p
->inp_socket
->so_options
&
386 (SO_REUSEPORT
| SO_REUSEADDR
);
391 /* Check AH/ESP integrity. */
392 if (ipsec_bypass
== 0) {
393 if (ipsec6_in_reject_so(m
, in6p
->inp_socket
)) {
394 IPSEC_STAT_INCREMENT(ipsec6stat
.in_polvio
);
395 /* do not inject data to pcb */
404 * m_copy(m, offset, ...) below.
405 * sbappendaddr() expects M_PKTHDR,
406 * and m_copy() will copy M_PKTHDR
407 * only if offset is 0.
410 n
= m_copy(m
, 0, M_COPYALL
);
411 udp6_append(in6p
, ip6
, &udp_in6
, m
,
412 off
+ sizeof (struct udphdr
));
415 udp_unlock(in6p
->in6p_socket
, 1, 0);
418 * Don't look for additional matches if this one does
419 * not have either the SO_REUSEPORT or SO_REUSEADDR
420 * socket options set. This heuristic avoids searching
421 * through all pcbs in the common case of a non-shared
422 * port. It assumes that an application will never
423 * clear these options after setting them.
425 if (reuse_sock
== 0 || ((m
= n
) == NULL
))
429 * Expect 32-bit aligned data pointer on strict-align
432 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m
);
435 * Recompute IP and UDP header pointers for new mbuf
437 ip6
= mtod(m
, struct ip6_hdr
*);
438 uh
= (struct udphdr
*)(void *)((caddr_t
)ip6
+ off
);
440 lck_rw_done(pcbinfo
->mtx
);
442 if (mcast_delivered
== 0) {
444 * No matching pcb found; discard datagram.
445 * (No need to send an ICMP Port Unreachable
446 * for a broadcast or multicast datgram.)
448 udpstat
.udps_noport
++;
450 udpstat
.udps_noportmcast
++;
452 if (ifp
->if_udp_stat
!= NULL
)
453 atomic_add_64(&ifp
->if_udp_stat
->port_unreach
, 1);
458 if (reuse_sock
!= 0) /* free the extra copy of mbuf */
463 * Locate pcb for datagram.
465 in6p
= in6_pcblookup_hash(&udbinfo
, &ip6
->ip6_src
, uh
->uh_sport
,
466 &ip6
->ip6_dst
, uh
->uh_dport
, 1,
470 if (ifp
->if_udp_stat
!= NULL
)
471 atomic_add_64(&ifp
->if_udp_stat
->port_unreach
, 1);
474 char buf
[INET6_ADDRSTRLEN
];
476 strlcpy(buf
, ip6_sprintf(&ip6
->ip6_dst
), sizeof(buf
));
477 if (log_in_vain
!= 3)
479 "Connection attempt to UDP %s:%d from %s:%d\n",
480 buf
, ntohs(uh
->uh_dport
),
481 ip6_sprintf(&ip6
->ip6_src
), ntohs(uh
->uh_sport
));
482 else if (!(m
->m_flags
& (M_BCAST
| M_MCAST
)) &&
483 !IN6_ARE_ADDR_EQUAL(&ip6
->ip6_dst
, &ip6
->ip6_src
))
484 log_in_vain_log((LOG_INFO
,
485 "Connection attempt to UDP %s:%d from %s:%d\n",
486 buf
, ntohs(uh
->uh_dport
),
487 ip6_sprintf(&ip6
->ip6_src
), ntohs(uh
->uh_sport
)));
489 udpstat
.udps_noport
++;
490 if (m
->m_flags
& M_MCAST
) {
491 printf("UDP6: M_MCAST is set in a unicast packet.\n");
493 udpstat
.udps_noportmcast
++;
495 if (ifp
->if_udp_stat
!= NULL
)
496 atomic_add_64(&ifp
->if_udp_stat
->badmcast
, 1);
500 icmp6_error(m
, ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOPORT
, 0);
505 * Check AH/ESP integrity.
507 if (ipsec_bypass
== 0) {
508 if (ipsec6_in_reject_so(m
, in6p
->in6p_socket
)) {
509 IPSEC_STAT_INCREMENT(ipsec6stat
.in_polvio
);
510 in_pcb_checkstate(in6p
, WNT_RELEASE
, 0);
512 if (ifp
->if_udp_stat
!= NULL
)
513 atomic_add_64(&ifp
->if_udp_stat
->badipsec
, 1);
521 * Construct sockaddr format source address.
522 * Stuff source address and datagram in user buffer.
524 udp_lock(in6p
->in6p_socket
, 1, 0);
526 if (in_pcb_checkstate(in6p
, WNT_RELEASE
, 1) == WNT_STOPUSING
) {
527 udp_unlock(in6p
->in6p_socket
, 1, 0);
529 if (ifp
->if_udp_stat
!= NULL
)
530 atomic_add_64(&ifp
->if_udp_stat
->cleanup
, 1);
535 init_sin6(&udp_in6
, m
); /* general init */
536 udp_in6
.sin6_port
= uh
->uh_sport
;
537 if ((in6p
->in6p_flags
& IN6P_CONTROLOPTS
) != 0 ||
538 (in6p
->in6p_socket
->so_options
& SO_TIMESTAMP
) != 0 ||
539 (in6p
->in6p_socket
->so_options
& SO_TIMESTAMP_MONOTONIC
) != 0) {
540 ret
= ip6_savecontrol(in6p
, m
, &opts
);
542 udp_unlock(in6p
->in6p_socket
, 1, 0);
546 m_adj(m
, off
+ sizeof(struct udphdr
));
548 locked_add_64(&in6p
->inp_stat
->rxpackets
, 1);
549 locked_add_64(&in6p
->inp_stat
->rxbytes
, m
->m_pkthdr
.len
);
551 so_recv_data_stat(in6p
->in6p_socket
, m
, 0);
552 if (sbappendaddr(&in6p
->in6p_socket
->so_rcv
,
553 (struct sockaddr
*)&udp_in6
,
554 m
, opts
, NULL
) == 0) {
557 udpstat
.udps_fullsock
++;
558 udp_unlock(in6p
->in6p_socket
, 1, 0);
561 sorwakeup(in6p
->in6p_socket
);
562 udp_unlock(in6p
->in6p_socket
, 1, 0);
582 struct ip6ctlparam
*ip6cp
= NULL
;
583 const struct sockaddr_in6
*sa6_src
= NULL
;
584 void (*notify
)(struct inpcb
*, int) = udp_notify
;
585 struct udp_portonly
{
590 if (sa
->sa_family
!= AF_INET6
||
591 sa
->sa_len
!= sizeof(struct sockaddr_in6
))
594 if ((unsigned)cmd
>= PRC_NCMDS
)
596 if (PRC_IS_REDIRECT(cmd
))
597 notify
= in6_rtchange
, d
= NULL
;
598 else if (cmd
== PRC_HOSTDEAD
)
600 else if (inet6ctlerrmap
[cmd
] == 0)
603 /* if the parameter is from icmp6, decode it. */
605 ip6cp
= (struct ip6ctlparam
*)d
;
607 ip6
= ip6cp
->ip6c_ip6
;
608 off
= ip6cp
->ip6c_off
;
609 sa6_src
= ip6cp
->ip6c_src
;
618 * XXX: We assume that when IPV6 is non NULL,
619 * M and OFF are valid.
622 /* check if we can safely examine src and dst ports */
623 if (m
->m_pkthdr
.len
< off
+ sizeof(*uhp
))
626 bzero(&uh
, sizeof(uh
));
627 m_copydata(m
, off
, sizeof(*uhp
), (caddr_t
)&uh
);
629 (void) in6_pcbnotify(&udbinfo
, sa
, uh
.uh_dport
,
630 (struct sockaddr
*)ip6cp
->ip6c_src
,
631 uh
.uh_sport
, cmd
, NULL
, notify
);
633 (void) in6_pcbnotify(&udbinfo
, sa
, 0, (struct sockaddr
*)&sa6_src
,
634 0, cmd
, NULL
, notify
);
639 udp6_getcred SYSCTL_HANDLER_ARGS
641 struct sockaddr_in6 addrs
[2];
645 error
= proc_suser(req
->p
);
649 if (req
->newlen
!= sizeof(addrs
))
651 if (req
->oldlen
!= sizeof(*(kauth_cred_t
)0))
653 error
= SYSCTL_IN(req
, addrs
, sizeof(addrs
));
657 inp
= in6_pcblookup_hash(&udbinfo
, &addrs
[1].sin6_addr
,
659 &addrs
[0].sin6_addr
, addrs
[0].sin6_port
,
661 if (!inp
|| !inp
->inp_socket
|| !inp
->inp_socket
->so_cred
) {
666 * XXX This should not be copying out a credential!!!! This
667 * XXX is an opaque type, and is not intended to be introspected,
668 * XXX and the size of this structure *WILL* change as planned MACF
669 * XXX and kauth changes go forward.
671 error
= SYSCTL_OUT(req
, inp
->inp_socket
->so_cred
->pc_ucred
,
672 sizeof(*(kauth_cred_t
)0));
679 SYSCTL_PROC(_net_inet6_udp6
, OID_AUTO
, getcred
, CTLTYPE_OPAQUE
|CTLFLAG_RW
,
681 udp6_getcred
, "S,ucred", "Get the ucred of a UDP6 connection");
685 udp6_abort(struct socket
*so
)
691 return EINVAL
; /* ??? possible? panic instead? */
692 soisdisconnected(so
);
698 udp6_attach(struct socket
*so
, __unused
int proto
, struct proc
*p
)
707 error
= in_pcballoc(so
, &udbinfo
, p
);
711 if (so
->so_snd
.sb_hiwat
== 0 || so
->so_rcv
.sb_hiwat
== 0) {
712 error
= soreserve(so
, udp_sendspace
, udp_recvspace
);
716 inp
= (struct inpcb
*)so
->so_pcb
;
717 inp
->inp_vflag
|= INP_IPV6
;
718 if (ip6_mapped_addr_on
)
719 inp
->inp_vflag
|= INP_IPV4
;
720 inp
->in6p_hops
= -1; /* use kernel default */
721 inp
->in6p_cksum
= -1; /* just to be sure */
724 * IPv4 TTL initialization is necessary for an IPv6 socket as well,
725 * because the socket may be bound to an IPv6 wildcard address,
726 * which may match an IPv4-mapped IPv6 address.
728 inp
->inp_ip_ttl
= ip_defttl
;
730 nstat_udp_new_pcb(inp
);
735 udp6_bind(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
744 inp
->inp_vflag
&= ~INP_IPV4
;
745 inp
->inp_vflag
|= INP_IPV6
;
746 if ((inp
->inp_flags
& IN6P_IPV6_V6ONLY
) == 0) {
747 struct sockaddr_in6
*sin6_p
;
749 sin6_p
= (struct sockaddr_in6
*)(void *)nam
;
751 if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p
->sin6_addr
))
752 inp
->inp_vflag
|= INP_IPV4
;
753 else if (IN6_IS_ADDR_V4MAPPED(&sin6_p
->sin6_addr
)) {
754 struct sockaddr_in sin
;
756 in6_sin6_2_sin(&sin
, sin6_p
);
757 inp
->inp_vflag
|= INP_IPV4
;
758 inp
->inp_vflag
&= ~INP_IPV6
;
759 error
= in_pcbbind(inp
, (struct sockaddr
*)&sin
, p
);
764 error
= in6_pcbbind(inp
, nam
, p
);
769 udp6_connect(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
778 if ((inp
->inp_flags
& IN6P_IPV6_V6ONLY
) == 0) {
779 struct sockaddr_in6
*sin6_p
;
781 sin6_p
= (struct sockaddr_in6
*)(void *)nam
;
782 if (IN6_IS_ADDR_V4MAPPED(&sin6_p
->sin6_addr
)) {
783 struct sockaddr_in sin
;
785 if (inp
->inp_faddr
.s_addr
!= INADDR_ANY
)
787 in6_sin6_2_sin(&sin
, sin6_p
);
788 error
= in_pcbconnect(inp
, (struct sockaddr
*)&sin
, p
, NULL
);
790 inp
->inp_vflag
|= INP_IPV4
;
791 inp
->inp_vflag
&= ~INP_IPV6
;
798 if (!IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_faddr
))
800 error
= in6_pcbconnect(inp
, nam
, p
);
802 if (ip6_mapped_addr_on
|| (inp
->inp_flags
& IN6P_IPV6_V6ONLY
) == 0) { /* should be non mapped addr */
803 inp
->inp_vflag
&= ~INP_IPV4
;
804 inp
->inp_vflag
|= INP_IPV6
;
807 if (inp
->inp_flowhash
== 0)
808 inp
->inp_flowhash
= inp_calc_flowhash(inp
);
814 udp6_detach(struct socket
*so
)
826 udp6_disconnect(struct socket
*so
)
834 if (inp
->inp_vflag
& INP_IPV4
) {
835 struct pr_usrreqs
*pru
;
837 pru
= ip_protox
[IPPROTO_UDP
]->pr_usrreqs
;
838 return ((*pru
->pru_disconnect
)(so
));
841 if (IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_faddr
))
844 in6_pcbdisconnect(inp
);
846 /* reset flow-controlled state, just in case */
847 inp_reset_fc_state(inp
);
849 inp
->in6p_laddr
= in6addr_any
;
850 inp
->in6p_last_outifp
= NULL
;
851 so
->so_state
&= ~SS_ISCONNECTED
; /* XXX */
856 udp6_send(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*addr
,
857 struct mbuf
*control
, struct proc
*p
)
869 if (addr
->sa_len
!= sizeof(struct sockaddr_in6
)) {
873 if (addr
->sa_family
!= AF_INET6
) {
874 error
= EAFNOSUPPORT
;
879 if (ip6_mapped_addr_on
|| (inp
->inp_flags
& IN6P_IPV6_V6ONLY
) == 0) {
881 struct sockaddr_in6
*sin6
= 0;
884 hasv4addr
= (inp
->inp_vflag
& INP_IPV4
);
886 sin6
= (struct sockaddr_in6
*)(void *)addr
;
887 hasv4addr
= IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)
891 struct pr_usrreqs
*pru
;
894 in6_sin6_2_sin_in_sock(addr
);
895 pru
= ip_protox
[IPPROTO_UDP
]->pr_usrreqs
;
896 error
= ((*pru
->pru_send
)(so
, flags
, m
, addr
, control
,
898 /* addr will just be freed in sendit(). */
903 return udp6_output(inp
, m
, addr
, control
, p
);
910 struct pr_usrreqs udp6_usrreqs
= {
911 udp6_abort
, pru_accept_notsupp
, udp6_attach
, udp6_bind
, udp6_connect
,
912 pru_connect2_notsupp
, in6_control
, udp6_detach
, udp6_disconnect
,
913 pru_listen_notsupp
, in6_mapped_peeraddr
, pru_rcvd_notsupp
,
914 pru_rcvoob_notsupp
, udp6_send
, pru_sense_null
, udp_shutdown
,
915 in6_mapped_sockaddr
, sosend
, soreceive
, pru_sopoll_notsupp