1 /* $FreeBSD: src/sys/netinet6/udp6_usrreq.c,v 1.6.2.13 2003/01/24 05:11:35 sam Exp $ */
2 /* $DragonFly: src/sys/netinet6/udp6_usrreq.c,v 1.26 2007/04/22 01:13:14 dillon Exp $ */
3 /* $KAME: udp6_usrreq.c,v 1.27 2001/05/21 05:45:10 jinmei Exp $ */
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * Copyright (c) 1982, 1986, 1989, 1993
36 * The Regents of the University of California. All rights reserved.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * @(#)udp_var.h 8.1 (Berkeley) 6/10/93
70 #include "opt_inet6.h"
71 #include "opt_ipsec.h"
73 #include <sys/param.h>
74 #include <sys/kernel.h>
76 #include <sys/protosw.h>
77 #include <sys/socket.h>
78 #include <sys/socketvar.h>
79 #include <sys/sysctl.h>
80 #include <sys/errno.h>
82 #include <sys/systm.h>
83 #include <sys/syslog.h>
86 #include <sys/thread2.h>
89 #include <net/route.h>
90 #include <net/if_types.h>
92 #include <netinet/in.h>
93 #include <netinet/in_systm.h>
94 #include <netinet/ip.h>
95 #include <netinet/in_pcb.h>
96 #include <netinet/in_var.h>
97 #include <netinet/ip_var.h>
98 #include <netinet/udp.h>
99 #include <netinet/udp_var.h>
100 #include <netinet/ip6.h>
101 #include <netinet6/ip6_var.h>
102 #include <netinet6/in6_pcb.h>
103 #include <netinet/icmp6.h>
104 #include <netinet6/udp6_var.h>
105 #include <netinet6/ip6protosw.h>
108 #include <netinet6/ipsec.h>
109 #include <netinet6/ipsec6.h>
113 #include <netproto/ipsec/ipsec.h>
114 #include <netproto/ipsec/ipsec6.h>
115 #endif /* FAST_IPSEC */
118 * UDP protocol inplementation.
119 * Per RFC 768, August, 1980.
122 extern struct protosw inetsw
[];
123 static int in6_mcmatch (struct inpcb
*, struct in6_addr
*, struct ifnet
*);
124 static int udp6_detach (struct socket
*so
);
127 in6_mcmatch(struct inpcb
*in6p
, struct in6_addr
*ia6
, struct ifnet
*ifp
)
129 struct ip6_moptions
*im6o
= in6p
->in6p_moptions
;
130 struct in6_multi_mship
*imm
;
135 for (imm
= im6o
->im6o_memberships
.lh_first
; imm
!= NULL
;
136 imm
= imm
->i6mm_chain
.le_next
) {
138 imm
->i6mm_maddr
->in6m_ifp
== ifp
) &&
139 IN6_ARE_ADDR_EQUAL(&imm
->i6mm_maddr
->in6m_addr
,
147 udp6_input(struct mbuf
**mp
, int *offp
, int proto
)
149 struct mbuf
*m
= *mp
;
153 struct mbuf
*opts
= NULL
;
156 struct sockaddr_in6 udp_in6
;
158 IP6_EXTHDR_CHECK(m
, off
, sizeof(struct udphdr
), IPPROTO_DONE
);
160 ip6
= mtod(m
, struct ip6_hdr
*);
162 if (faithprefix_p
!= NULL
&& (*faithprefix_p
)(&ip6
->ip6_dst
)) {
163 /* XXX send icmp6 host/port unreach? */
168 udpstat
.udps_ipackets
++;
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.
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: traditionally we dropped udpiphdr 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
, &udbinfo
.pcblisthead
, inp_list
) {
234 if (in6p
->inp_flags
& INP_PLACEMARKER
)
236 if (!(in6p
->inp_vflag
& INP_IPV6
))
238 if (in6p
->in6p_lport
!= uh
->uh_dport
)
240 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
)) {
241 if (!IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
,
243 !in6_mcmatch(in6p
, &ip6
->ip6_dst
,
247 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
)) {
248 if (!IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
,
250 in6p
->in6p_fport
!= uh
->uh_sport
)
259 * Check AH/ESP integrity.
261 if (ipsec6_in_reject_so(m
, last
->inp_socket
))
262 ipsec6stat
.in_polvio
++;
263 /* do not inject data into pcb */
268 * Check AH/ESP integrity.
270 if (ipsec6_in_reject(m
, last
))
273 #endif /* FAST_IPSEC */
274 if ((n
= m_copy(m
, 0, M_COPYALL
)) != NULL
) {
277 * m_copy(m, offset, ...) above.
278 * ssb_appendaddr() expects M_PKTHDR,
279 * and m_copy() will copy M_PKTHDR
280 * only if offset is 0.
282 if (last
->in6p_flags
& IN6P_CONTROLOPTS
283 || last
->in6p_socket
->so_options
& SO_TIMESTAMP
)
284 ip6_savecontrol(last
, &opts
,
287 m_adj(n
, off
+ sizeof(struct udphdr
));
288 if (ssb_appendaddr(&last
->in6p_socket
->so_rcv
,
289 (struct sockaddr
*)&udp_in6
,
294 udpstat
.udps_fullsock
++;
296 sorwakeup(last
->in6p_socket
);
302 * Don't look for additional matches if this one does
303 * not have either the SO_REUSEPORT or SO_REUSEADDR
304 * socket options set. This heuristic avoids searching
305 * through all pcbs in the common case of a non-shared
306 * port. It assumes that an application will never
307 * clear these options after setting them.
309 if ((last
->in6p_socket
->so_options
&
310 (SO_REUSEPORT
| SO_REUSEADDR
)) == 0)
316 * No matching pcb found; discard datagram.
317 * (No need to send an ICMP Port Unreachable
318 * for a broadcast or multicast datgram.)
320 udpstat
.udps_noport
++;
321 udpstat
.udps_noportmcast
++;
326 * Check AH/ESP integrity.
328 if (ipsec6_in_reject_so(m
, last
->inp_socket
)) {
329 ipsec6stat
.in_polvio
++;
335 * Check AH/ESP integrity.
337 if (ipsec6_in_reject(m
, last
)) {
340 #endif /* FAST_IPSEC */
341 if (last
->in6p_flags
& IN6P_CONTROLOPTS
342 || last
->in6p_socket
->so_options
& SO_TIMESTAMP
)
343 ip6_savecontrol(last
, &opts
, ip6
, m
);
345 m_adj(m
, off
+ sizeof(struct udphdr
));
346 if (ssb_appendaddr(&last
->in6p_socket
->so_rcv
,
347 (struct sockaddr
*)&udp_in6
,
349 udpstat
.udps_fullsock
++;
352 sorwakeup(last
->in6p_socket
);
356 * Locate pcb for datagram.
358 in6p
= in6_pcblookup_hash(&udbinfo
, &ip6
->ip6_src
, uh
->uh_sport
,
359 &ip6
->ip6_dst
, uh
->uh_dport
, 1,
363 char buf
[INET6_ADDRSTRLEN
];
365 strcpy(buf
, ip6_sprintf(&ip6
->ip6_dst
));
367 "Connection attempt to UDP [%s]:%d from [%s]:%d\n",
368 buf
, ntohs(uh
->uh_dport
),
369 ip6_sprintf(&ip6
->ip6_src
), ntohs(uh
->uh_sport
));
371 udpstat
.udps_noport
++;
372 if (m
->m_flags
& M_MCAST
) {
373 kprintf("UDP6: M_MCAST is set in a unicast packet.\n");
374 udpstat
.udps_noportmcast
++;
377 icmp6_error(m
, ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOPORT
, 0);
382 * Check AH/ESP integrity.
384 if (ipsec6_in_reject_so(m
, in6p
->in6p_socket
)) {
385 ipsec6stat
.in_polvio
++;
391 * Check AH/ESP integrity.
393 if (ipsec6_in_reject(m
, in6p
)) {
396 #endif /* FAST_IPSEC */
399 * Construct sockaddr format source address.
400 * Stuff source address and datagram in user buffer.
402 init_sin6(&udp_in6
, m
); /* general init */
403 udp_in6
.sin6_port
= uh
->uh_sport
;
404 if (in6p
->in6p_flags
& IN6P_CONTROLOPTS
405 || in6p
->in6p_socket
->so_options
& SO_TIMESTAMP
)
406 ip6_savecontrol(in6p
, &opts
, ip6
, m
);
407 m_adj(m
, off
+ sizeof(struct udphdr
));
408 if (ssb_appendaddr(&in6p
->in6p_socket
->so_rcv
,
409 (struct sockaddr
*)&udp_in6
,
411 udpstat
.udps_fullsock
++;
414 sorwakeup(in6p
->in6p_socket
);
425 udp6_ctlinput(int cmd
, struct sockaddr
*sa
, void *d
)
431 struct ip6ctlparam
*ip6cp
= NULL
;
432 const struct sockaddr_in6
*sa6_src
= NULL
;
433 void (*notify
) (struct inpcb
*, int) = udp_notify
;
434 struct udp_portonly
{
439 if (sa
->sa_family
!= AF_INET6
||
440 sa
->sa_len
!= sizeof(struct sockaddr_in6
))
443 if ((unsigned)cmd
>= PRC_NCMDS
)
445 if (PRC_IS_REDIRECT(cmd
))
446 notify
= in6_rtchange
, d
= NULL
;
447 else if (cmd
== PRC_HOSTDEAD
)
449 else if (inet6ctlerrmap
[cmd
] == 0)
452 /* if the parameter is from icmp6, decode it. */
454 ip6cp
= (struct ip6ctlparam
*)d
;
456 ip6
= ip6cp
->ip6c_ip6
;
457 off
= ip6cp
->ip6c_off
;
458 sa6_src
= ip6cp
->ip6c_src
;
467 * XXX: We assume that when IPV6 is non NULL,
468 * M and OFF are valid.
471 /* check if we can safely examine src and dst ports */
472 if (m
->m_pkthdr
.len
< off
+ sizeof(*uhp
))
475 bzero(&uh
, sizeof(uh
));
476 m_copydata(m
, off
, sizeof(*uhp
), (caddr_t
)&uh
);
478 in6_pcbnotify(&udbinfo
.pcblisthead
, sa
, uh
.uh_dport
,
479 (struct sockaddr
*)ip6cp
->ip6c_src
, uh
.uh_sport
,
482 in6_pcbnotify(&udbinfo
.pcblisthead
, sa
, 0,
483 (const struct sockaddr
*)sa6_src
, 0,
488 udp6_getcred(SYSCTL_HANDLER_ARGS
)
490 struct sockaddr_in6 addrs
[2];
494 error
= priv_check(req
->td
, PRIV_ROOT
);
498 if (req
->newlen
!= sizeof(addrs
))
500 if (req
->oldlen
!= sizeof(struct ucred
))
502 error
= SYSCTL_IN(req
, addrs
, sizeof(addrs
));
506 inp
= in6_pcblookup_hash(&udbinfo
, &addrs
[1].sin6_addr
,
508 &addrs
[0].sin6_addr
, addrs
[0].sin6_port
,
510 if (!inp
|| !inp
->inp_socket
) {
514 error
= SYSCTL_OUT(req
, inp
->inp_socket
->so_cred
,
515 sizeof(struct ucred
));
522 SYSCTL_PROC(_net_inet6_udp6
, OID_AUTO
, getcred
, CTLTYPE_OPAQUE
|CTLFLAG_RW
,
524 udp6_getcred
, "S,ucred", "Get the ucred of a UDP6 connection");
527 udp6_abort(struct socket
*so
)
533 return EINVAL
; /* ??? possible? panic instead? */
534 soisdisconnected(so
);
542 udp6_attach(struct socket
*so
, int proto
, struct pru_attach_info
*ai
)
551 if (so
->so_snd
.ssb_hiwat
== 0 || so
->so_rcv
.ssb_hiwat
== 0) {
552 error
= soreserve(so
, udp_sendspace
, udp_recvspace
,
558 error
= in_pcballoc(so
, &udbinfo
);
562 so
->so_port
= udp_soport_attach(so
);
563 inp
= (struct inpcb
*)so
->so_pcb
;
564 inp
->inp_vflag
|= INP_IPV6
;
566 inp
->inp_vflag
|= INP_IPV4
;
567 inp
->in6p_hops
= -1; /* use kernel default */
568 inp
->in6p_cksum
= -1; /* just to be sure */
571 * IPv4 TTL initialization is necessary for an IPv6 socket as well,
572 * because the socket may be bound to an IPv6 wildcard address,
573 * which may match an IPv4-mapped IPv6 address.
575 inp
->inp_ip_ttl
= ip_defttl
;
580 udp6_bind(struct socket
*so
, struct sockaddr
*nam
, struct thread
*td
)
582 struct sockaddr_in6
*sin6_p
= (struct sockaddr_in6
*)nam
;
590 inp
->inp_vflag
&= ~INP_IPV4
;
591 inp
->inp_vflag
|= INP_IPV6
;
592 if (!(inp
->inp_flags
& IN6P_IPV6_V6ONLY
)) {
593 if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p
->sin6_addr
))
594 inp
->inp_vflag
|= INP_IPV4
;
595 else if (IN6_IS_ADDR_V4MAPPED(&sin6_p
->sin6_addr
)) {
596 struct sockaddr_in sin
;
598 in6_sin6_2_sin(&sin
, sin6_p
);
599 inp
->inp_vflag
|= INP_IPV4
;
600 inp
->inp_vflag
&= ~INP_IPV6
;
602 error
= in_pcbbind(inp
, (struct sockaddr
*)&sin
, td
);
609 error
= in6_pcbbind(inp
, nam
, td
);
612 if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p
->sin6_addr
))
613 inp
->inp_flags
|= INP_WASBOUND_NOTANY
;
614 in_pcbinswildcardhash(inp
);
620 udp6_connect(struct socket
*so
, struct sockaddr
*nam
, struct thread
*td
)
629 if (!(inp
->inp_flags
& IN6P_IPV6_V6ONLY
)) {
630 struct sockaddr_in6
*sin6_p
;
632 sin6_p
= (struct sockaddr_in6
*)nam
;
633 if (IN6_IS_ADDR_V4MAPPED(&sin6_p
->sin6_addr
)) {
634 struct sockaddr_in sin
;
636 if (inp
->inp_faddr
.s_addr
!= INADDR_ANY
)
638 in6_sin6_2_sin(&sin
, sin6_p
);
640 error
= in_pcbconnect(inp
, (struct sockaddr
*)&sin
, td
);
643 inp
->inp_vflag
|= INP_IPV4
;
644 inp
->inp_vflag
&= ~INP_IPV6
;
650 if (!IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_faddr
))
652 if (inp
->inp_flags
& INP_WILDCARD
)
653 in_pcbremwildcardhash(inp
);
654 if (!prison_remote_ip(td
, nam
))
655 return(EAFNOSUPPORT
); /* IPv4 only jail */
657 error
= in6_pcbconnect(inp
, nam
, td
);
660 if (!ip6_v6only
) { /* should be non mapped addr */
661 inp
->inp_vflag
&= ~INP_IPV4
;
662 inp
->inp_vflag
|= INP_IPV6
;
664 /* sosetport(so, port); here, see udp v4 code */
666 } else if (error
== EAFNOSUPPORT
) { /* connection dissolved */
668 * Follow traditional BSD behavior and retain
669 * the local port binding. But, fix the old misbehavior
670 * of overwriting any previously bound local address.
672 if (!(inp
->inp_flags
& INP_WASBOUND_NOTANY
))
673 inp
->in6p_laddr
= kin6addr_any
;
674 in_pcbinswildcardhash(inp
);
680 udp6_detach(struct socket
*so
)
694 udp6_disconnect(struct socket
*so
)
702 if (inp
->inp_vflag
& INP_IPV4
) {
703 const struct pr_usrreqs
*pru
;
705 pru
= inetsw
[ip_protox
[IPPROTO_UDP
]].pr_usrreqs
;
706 return ((*pru
->pru_disconnect
)(so
));
709 if (IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_faddr
))
713 in6_pcbdisconnect(inp
);
715 so
->so_state
&= ~SS_ISCONNECTED
; /* XXX */
720 udp6_send(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*addr
,
721 struct mbuf
*control
, struct thread
*td
)
733 if (addr
->sa_len
!= sizeof(struct sockaddr_in6
)) {
737 if (addr
->sa_family
!= AF_INET6
) {
738 error
= EAFNOSUPPORT
;
745 struct sockaddr_in6
*sin6
= 0;
748 hasv4addr
= (inp
->inp_vflag
& INP_IPV4
);
750 sin6
= (struct sockaddr_in6
*)addr
;
751 hasv4addr
= IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)
755 const struct pr_usrreqs
*pru
;
758 in6_sin6_2_sin_in_sock(addr
);
759 pru
= inetsw
[ip_protox
[IPPROTO_UDP
]].pr_usrreqs
;
760 error
= ((*pru
->pru_send
)(so
, flags
, m
, addr
,
762 /* addr will just be freed in sendit(). */
767 return udp6_output(inp
, m
, addr
, control
, td
);
774 struct pr_usrreqs udp6_usrreqs
= {
775 .pru_abort
= udp6_abort
,
776 .pru_accept
= pru_accept_notsupp
,
777 .pru_attach
= udp6_attach
,
778 .pru_bind
= udp6_bind
,
779 .pru_connect
= udp6_connect
,
780 .pru_connect2
= pru_connect2_notsupp
,
781 .pru_control
= in6_control
,
782 .pru_detach
= udp6_detach
,
783 .pru_disconnect
= udp6_disconnect
,
784 .pru_listen
= pru_listen_notsupp
,
785 .pru_peeraddr
= in6_mapped_peeraddr
,
786 .pru_rcvd
= pru_rcvd_notsupp
,
787 .pru_rcvoob
= pru_rcvoob_notsupp
,
788 .pru_send
= udp6_send
,
789 .pru_sense
= pru_sense_null
,
790 .pru_shutdown
= udp_shutdown
,
791 .pru_sockaddr
= in6_mapped_sockaddr
,
792 .pru_sosend
= sosend
,
793 .pru_soreceive
= soreceive
,