1 /* $FreeBSD: src/sys/netinet6/udp6_usrreq.c,v 1.6.2.13 2003/01/24 05:11:35 sam Exp $ */
2 /* $KAME: udp6_usrreq.c,v 1.27 2001/05/21 05:45:10 jinmei Exp $ */
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * Copyright (c) 1982, 1986, 1989, 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. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * @(#)udp_var.h 8.1 (Berkeley) 6/10/93
65 #include "opt_inet6.h"
67 #include <sys/param.h>
68 #include <sys/kernel.h>
70 #include <sys/protosw.h>
71 #include <sys/socket.h>
72 #include <sys/socketvar.h>
73 #include <sys/sysctl.h>
74 #include <sys/errno.h>
76 #include <sys/systm.h>
77 #include <sys/syslog.h>
82 #include <sys/thread2.h>
83 #include <sys/socketvar2.h>
84 #include <sys/msgport2.h>
87 #include <net/route.h>
88 #include <net/if_types.h>
89 #include <net/netisr2.h>
91 #include <netinet/in.h>
92 #include <netinet/in_systm.h>
93 #include <netinet/ip.h>
94 #include <netinet/in_pcb.h>
95 #include <netinet/in_var.h>
96 #include <netinet/ip_var.h>
97 #include <netinet/udp.h>
98 #include <netinet/udp_var.h>
99 #include <netinet/ip6.h>
100 #include <netinet6/ip6_var.h>
101 #include <netinet6/in6_pcb.h>
102 #include <netinet/icmp6.h>
103 #include <netinet6/udp6_var.h>
104 #include <netinet6/ip6protosw.h>
107 * UDP protocol inplementation.
108 * Per RFC 768, August, 1980.
111 extern struct protosw inetsw
[];
112 static int in6_mcmatch (struct inpcb
*, struct in6_addr
*, struct ifnet
*);
115 in6_mcmatch(struct inpcb
*in6p
, struct in6_addr
*ia6
, struct ifnet
*ifp
)
117 struct ip6_moptions
*im6o
= in6p
->in6p_moptions
;
118 struct in6_multi_mship
*imm
;
123 for (imm
= im6o
->im6o_memberships
.lh_first
; imm
!= NULL
;
124 imm
= imm
->i6mm_chain
.le_next
) {
126 imm
->i6mm_maddr
->in6m_ifp
== ifp
) &&
127 IN6_ARE_ADDR_EQUAL(&imm
->i6mm_maddr
->in6m_addr
,
135 udp6_input(struct mbuf
**mp
, int *offp
, int proto
)
137 struct mbuf
*m
= *mp
;
141 struct mbuf
*opts
= NULL
;
144 struct sockaddr_in6 udp_in6
;
146 struct inpcbinfo
*pcbinfo
= &udbinfo
[0];
148 IP6_EXTHDR_CHECK(m
, off
, sizeof(struct udphdr
), IPPROTO_DONE
);
150 ip6
= mtod(m
, struct ip6_hdr
*);
152 udp_stat
.udps_ipackets
++;
154 plen
= ntohs(ip6
->ip6_plen
) - off
+ sizeof(*ip6
);
155 uh
= (struct udphdr
*)((caddr_t
)ip6
+ off
);
156 ulen
= ntohs((u_short
)uh
->uh_ulen
);
159 udp_stat
.udps_badlen
++;
164 * Checksum extended UDP header and data.
167 udp_stat
.udps_nosum
++;
168 else if (in6_cksum(m
, IPPROTO_UDP
, off
, ulen
) != 0) {
169 udp_stat
.udps_badsum
++;
173 if (IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
)) {
174 struct inpcb
*last
, *marker
;
177 * Deliver a multicast datagram to all sockets
178 * for which the local and remote addresses and ports match
179 * those of the incoming datagram. This allows more than
180 * one process to receive multicasts on the same port.
181 * (This really ought to be done for unicast datagrams as
182 * well, but that would cause problems with existing
183 * applications that open both address-specific sockets and
184 * a wildcard socket listening to the same port -- they would
185 * end up receiving duplicates of every unicast datagram.
186 * Those applications open the multiple sockets to overcome an
187 * inadequacy of the UDP socket interface, but for backwards
188 * compatibility we avoid the problem here rather than
189 * fixing the interface. Maybe 4.5BSD will remedy this?)
193 * In a case that laddr should be set to the link-local
194 * address (this happens in RIPng), the multicast address
195 * specified in the received packet does not match with
196 * laddr. To cure this situation, the matching is relaxed
197 * if the receiving interface is the same as one specified
198 * in the socket and if the destination multicast address
199 * matches one of the multicast groups specified in the socket.
203 * Construct sockaddr format source address.
205 init_sin6(&udp_in6
, m
); /* general init */
206 udp_in6
.sin6_port
= uh
->uh_sport
;
208 * KAME note: traditionally we dropped udpiphdr from mbuf here.
212 * Locate pcb(s) for datagram.
213 * (Algorithm copied from raw_intr().)
217 marker
= in_pcbmarker();
219 GET_PCBINFO_TOKEN(pcbinfo
);
221 LIST_INSERT_HEAD(&pcbinfo
->pcblisthead
, marker
, inp_list
);
222 while ((in6p
= LIST_NEXT(marker
, inp_list
)) != NULL
) {
223 LIST_REMOVE(marker
, inp_list
);
224 LIST_INSERT_AFTER(in6p
, marker
, inp_list
);
226 if (in6p
->inp_flags
& INP_PLACEMARKER
)
228 if (!INP_ISIPV6(in6p
))
230 if (in6p
->in6p_lport
!= uh
->uh_dport
)
232 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
)) {
233 if (!IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
,
235 !in6_mcmatch(in6p
, &ip6
->ip6_dst
,
239 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
)) {
240 if (!IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
,
242 in6p
->in6p_fport
!= uh
->uh_sport
)
249 if ((n
= m_copy(m
, 0, M_COPYALL
)) != NULL
) {
252 * m_copy(m, offset, ...) above.
253 * ssb_appendaddr() expects M_PKTHDR,
254 * and m_copy() will copy M_PKTHDR
255 * only if offset is 0.
257 so
= last
->in6p_socket
;
258 if ((last
->in6p_flags
& IN6P_CONTROLOPTS
) ||
259 (so
->so_options
& SO_TIMESTAMP
)) {
260 ip6_savecontrol(last
, &opts
,
263 m_adj(n
, off
+ sizeof(struct udphdr
));
264 lwkt_gettoken(&so
->so_rcv
.ssb_token
);
265 if (ssb_appendaddr(&so
->so_rcv
,
266 (struct sockaddr
*)&udp_in6
,
271 udp_stat
.udps_fullsock
++;
275 lwkt_reltoken(&so
->so_rcv
.ssb_token
);
281 * Don't look for additional matches if this one does
282 * not have either the SO_REUSEPORT or SO_REUSEADDR
283 * socket options set. This heuristic avoids searching
284 * through all pcbs in the common case of a non-shared
285 * port. It assumes that an application will never
286 * clear these options after setting them.
288 if ((last
->in6p_socket
->so_options
&
289 (SO_REUSEPORT
| SO_REUSEADDR
)) == 0)
292 LIST_REMOVE(marker
, inp_list
);
294 REL_PCBINFO_TOKEN(pcbinfo
);
298 * No matching pcb found; discard datagram.
299 * (No need to send an ICMP Port Unreachable
300 * for a broadcast or multicast datgram.)
302 udp_stat
.udps_noport
++;
303 udp_stat
.udps_noportmcast
++;
306 if (last
->in6p_flags
& IN6P_CONTROLOPTS
307 || last
->in6p_socket
->so_options
& SO_TIMESTAMP
)
308 ip6_savecontrol(last
, &opts
, ip6
, m
);
310 m_adj(m
, off
+ sizeof(struct udphdr
));
311 so
= last
->in6p_socket
;
312 lwkt_gettoken(&so
->so_rcv
.ssb_token
);
313 if (ssb_appendaddr(&so
->so_rcv
, (struct sockaddr
*)&udp_in6
,
315 udp_stat
.udps_fullsock
++;
316 lwkt_reltoken(&so
->so_rcv
.ssb_token
);
320 lwkt_reltoken(&so
->so_rcv
.ssb_token
);
324 * Locate pcb for datagram.
326 in6p
= in6_pcblookup_hash(pcbinfo
, &ip6
->ip6_src
, uh
->uh_sport
,
327 &ip6
->ip6_dst
, uh
->uh_dport
, 1,
331 char buf
[INET6_ADDRSTRLEN
];
333 strcpy(buf
, ip6_sprintf(&ip6
->ip6_dst
));
335 "Connection attempt to UDP [%s]:%d from [%s]:%d\n",
336 buf
, ntohs(uh
->uh_dport
),
337 ip6_sprintf(&ip6
->ip6_src
), ntohs(uh
->uh_sport
));
339 udp_stat
.udps_noport
++;
340 if (m
->m_flags
& M_MCAST
) {
341 kprintf("UDP6: M_MCAST is set in a unicast packet.\n");
342 udp_stat
.udps_noportmcast
++;
345 icmp6_error(m
, ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOPORT
, 0);
350 * Construct sockaddr format source address.
351 * Stuff source address and datagram in user buffer.
353 init_sin6(&udp_in6
, m
); /* general init */
354 udp_in6
.sin6_port
= uh
->uh_sport
;
355 if (in6p
->in6p_flags
& IN6P_CONTROLOPTS
356 || in6p
->in6p_socket
->so_options
& SO_TIMESTAMP
)
357 ip6_savecontrol(in6p
, &opts
, ip6
, m
);
358 m_adj(m
, off
+ sizeof(struct udphdr
));
359 so
= in6p
->in6p_socket
;
360 lwkt_gettoken(&so
->so_rcv
.ssb_token
);
361 if (ssb_appendaddr(&so
->so_rcv
, (struct sockaddr
*)&udp_in6
,
363 udp_stat
.udps_fullsock
++;
364 lwkt_reltoken(&so
->so_rcv
.ssb_token
);
368 lwkt_reltoken(&so
->so_rcv
.ssb_token
);
379 udp6_ctlinput(netmsg_t msg
)
381 int cmd
= msg
->ctlinput
.nm_cmd
;
382 struct sockaddr
*sa
= msg
->ctlinput
.nm_arg
;
383 void *d
= msg
->ctlinput
.nm_extra
;
388 struct ip6ctlparam
*ip6cp
= NULL
;
389 const struct sockaddr_in6
*sa6_src
= NULL
;
390 inp_notify_t notify
= udp_notify
;
391 struct udp_portonly
{
396 if (sa
->sa_family
!= AF_INET6
||
397 sa
->sa_len
!= sizeof(struct sockaddr_in6
))
400 if ((unsigned)cmd
>= PRC_NCMDS
)
402 if (PRC_IS_REDIRECT(cmd
))
403 notify
= in6_rtchange
, d
= NULL
;
404 else if (cmd
== PRC_HOSTDEAD
)
406 else if (inet6ctlerrmap
[cmd
] == 0)
409 /* if the parameter is from icmp6, decode it. */
411 ip6cp
= (struct ip6ctlparam
*)d
;
413 ip6
= ip6cp
->ip6c_ip6
;
414 off
= ip6cp
->ip6c_off
;
415 sa6_src
= ip6cp
->ip6c_src
;
424 * XXX: We assume that when IPV6 is non NULL,
425 * M and OFF are valid.
428 /* check if we can safely examine src and dst ports */
429 if (m
->m_pkthdr
.len
< off
+ sizeof(*uhp
))
432 bzero(&uh
, sizeof(uh
));
433 m_copydata(m
, off
, sizeof(*uhp
), (caddr_t
)&uh
);
435 in6_pcbnotify(&udbinfo
[0], sa
, uh
.uh_dport
,
436 (struct sockaddr
*)ip6cp
->ip6c_src
, uh
.uh_sport
,
439 in6_pcbnotify(&udbinfo
[0], sa
, 0,
440 (const struct sockaddr
*)sa6_src
, 0,
444 lwkt_replymsg(&msg
->ctlinput
.base
.lmsg
, 0);
448 udp6_getcred(SYSCTL_HANDLER_ARGS
)
450 struct sockaddr_in6 addrs
[2];
454 error
= priv_check(req
->td
, PRIV_ROOT
);
458 if (req
->newlen
!= sizeof(addrs
))
460 if (req
->oldlen
!= sizeof(struct ucred
))
462 error
= SYSCTL_IN(req
, addrs
, sizeof(addrs
));
466 inp
= in6_pcblookup_hash(&udbinfo
[0], &addrs
[1].sin6_addr
,
468 &addrs
[0].sin6_addr
, addrs
[0].sin6_port
,
470 if (!inp
|| !inp
->inp_socket
) {
474 error
= SYSCTL_OUT(req
, inp
->inp_socket
->so_cred
,
475 sizeof(struct ucred
));
482 SYSCTL_PROC(_net_inet6_udp6
, OID_AUTO
, getcred
, CTLTYPE_OPAQUE
|CTLFLAG_RW
,
484 udp6_getcred
, "S,ucred", "Get the ucred of a UDP6 connection");
487 * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
488 * will sofree() it when we return.
491 udp6_abort(netmsg_t msg
)
493 struct socket
*so
= msg
->abort
.base
.nm_so
;
499 soisdisconnected(so
);
506 lwkt_replymsg(&msg
->abort
.base
.lmsg
, error
);
510 udp6_attach(netmsg_t msg
)
512 struct socket
*so
= msg
->attach
.base
.nm_so
;
513 struct pru_attach_info
*ai
= msg
->attach
.nm_ai
;
523 if (so
->so_snd
.ssb_hiwat
== 0 || so
->so_rcv
.ssb_hiwat
== 0) {
524 error
= soreserve(so
, udp_sendspace
, udp_recvspace
,
530 error
= in_pcballoc(so
, &udbinfo
[0]);
534 inp
= (struct inpcb
*)so
->so_pcb
;
535 inp
->in6p_hops
= -1; /* use kernel default */
536 inp
->in6p_cksum
= -1; /* just to be sure */
539 * IPv4 TTL initialization is necessary for an IPv6 socket as well,
540 * because the socket may be bound to an IPv6 wildcard address,
541 * which may match an IPv4-mapped IPv6 address.
543 inp
->inp_ip_ttl
= ip_defttl
;
546 lwkt_replymsg(&msg
->attach
.base
.lmsg
, error
);
550 udp6_bind(netmsg_t msg
)
552 struct socket
*so
=msg
->bind
.base
.nm_so
;
553 struct sockaddr
*nam
= msg
->bind
.nm_nam
;
554 struct thread
*td
= msg
->bind
.nm_td
;
555 struct sockaddr_in6
*sin6_p
= (struct sockaddr_in6
*)nam
;
565 error
= in6_pcbbind(inp
, nam
, td
);
567 if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p
->sin6_addr
))
568 inp
->inp_flags
|= INP_WASBOUND_NOTANY
;
569 in_pcbinswildcardhash(inp
);
572 lwkt_replymsg(&msg
->bind
.base
.lmsg
, error
);
576 udp6_connect(netmsg_t msg
)
578 struct socket
*so
= msg
->connect
.base
.nm_so
;
579 struct sockaddr
*nam
= msg
->connect
.nm_nam
;
580 struct thread
*td
= msg
->connect
.nm_td
;
581 struct sockaddr_in6
*sin6_p
;
591 sin6_p
= (struct sockaddr_in6
*)nam
;
592 if (IN6_IS_ADDR_V4MAPPED(&sin6_p
->sin6_addr
)) {
593 error
= EADDRNOTAVAIL
;
597 if (!IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_faddr
)) {
601 if (inp
->inp_flags
& INP_WILDCARD
)
602 in_pcbremwildcardhash(inp
);
603 if (!prison_remote_ip(td
, nam
)) {
604 error
= EAFNOSUPPORT
; /* IPv4 only jail */
607 error
= in6_pcbconnect(inp
, nam
, td
);
610 } else if (error
== EAFNOSUPPORT
) { /* connection dissolved */
612 * Follow traditional BSD behavior and retain
613 * the local port binding. But, fix the old misbehavior
614 * of overwriting any previously bound local address.
616 if (!(inp
->inp_flags
& INP_WASBOUND_NOTANY
))
617 inp
->in6p_laddr
= kin6addr_any
;
618 in_pcbinswildcardhash(inp
);
621 lwkt_replymsg(&msg
->connect
.base
.lmsg
, error
);
625 udp6_detach(netmsg_t msg
)
627 struct socket
*so
= msg
->detach
.base
.nm_so
;
638 lwkt_replymsg(&msg
->detach
.base
.lmsg
, error
);
642 udp6_disconnect(netmsg_t msg
)
644 struct socket
*so
= msg
->disconnect
.base
.nm_so
;
654 if (IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_faddr
)) {
657 in6_pcbdisconnect(inp
);
658 soclrstate(so
, SS_ISCONNECTED
); /* XXX */
662 lwkt_replymsg(&msg
->disconnect
.base
.lmsg
, error
);
666 udp6_send(netmsg_t msg
)
668 struct socket
*so
= msg
->send
.base
.nm_so
;
669 struct mbuf
*m
= msg
->send
.nm_m
;
670 struct sockaddr
*addr
= msg
->send
.nm_addr
;
671 struct mbuf
*control
= msg
->send
.nm_control
;
672 struct thread
*td
= msg
->send
.nm_td
;
683 struct sockaddr_in6
*sin6
;
685 if (addr
->sa_len
!= sizeof(struct sockaddr_in6
)) {
689 if (addr
->sa_family
!= AF_INET6
) {
690 error
= EAFNOSUPPORT
;
694 sin6
= (struct sockaddr_in6
*)addr
;
695 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)) {
696 error
= EADDRNOTAVAIL
;
701 error
= udp6_output(inp
, m
, addr
, control
, td
);
702 lwkt_replymsg(&msg
->send
.base
.lmsg
, error
);
706 lwkt_replymsg(&msg
->send
.base
.lmsg
, error
);
709 struct pr_usrreqs udp6_usrreqs
= {
710 .pru_abort
= udp6_abort
,
711 .pru_accept
= pr_generic_notsupp
,
712 .pru_attach
= udp6_attach
,
713 .pru_bind
= udp6_bind
,
714 .pru_connect
= udp6_connect
,
715 .pru_connect2
= pr_generic_notsupp
,
716 .pru_control
= in6_control_dispatch
,
717 .pru_detach
= udp6_detach
,
718 .pru_disconnect
= udp6_disconnect
,
719 .pru_listen
= pr_generic_notsupp
,
720 .pru_peeraddr
= in6_setpeeraddr_dispatch
,
721 .pru_rcvd
= pr_generic_notsupp
,
722 .pru_rcvoob
= pr_generic_notsupp
,
723 .pru_send
= udp6_send
,
724 .pru_sense
= pru_sense_null
,
725 .pru_shutdown
= udp_shutdown
,
726 .pru_sockaddr
= in6_setsockaddr_dispatch
,
727 .pru_sosend
= sosend
,
728 .pru_soreceive
= soreceive