2 * Copyright (c) 2004 Jeffrey M. Hsu. All rights reserved.
3 * Copyright (c) 2004 The DragonFly Project. All rights reserved.
5 * This code is derived from software contributed to The DragonFly 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 DragonFly Project nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific, prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
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_usrreq.c 8.6 (Berkeley) 5/23/95
67 * $FreeBSD: src/sys/netinet/udp_usrreq.c,v 1.64.2.18 2003/01/24 05:11:34 sam Exp $
68 * $DragonFly: src/sys/netinet/udp_usrreq.c,v 1.47 2008/11/11 10:46:58 sephe Exp $
71 #include "opt_ipsec.h"
72 #include "opt_inet6.h"
74 #include <sys/param.h>
75 #include <sys/systm.h>
76 #include <sys/kernel.h>
77 #include <sys/malloc.h>
79 #include <sys/domain.h>
81 #include <sys/protosw.h>
82 #include <sys/socket.h>
83 #include <sys/socketvar.h>
84 #include <sys/sysctl.h>
85 #include <sys/syslog.h>
86 #include <sys/thread2.h>
87 #include <sys/in_cksum.h>
89 #include <machine/stdarg.h>
91 #include <vm/vm_zone.h>
94 #include <net/route.h>
95 #include <net/netmsg2.h>
97 #include <netinet/in.h>
98 #include <netinet/in_systm.h>
99 #include <netinet/ip.h>
101 #include <netinet/ip6.h>
103 #include <netinet/in_pcb.h>
104 #include <netinet/in_var.h>
105 #include <netinet/ip_var.h>
107 #include <netinet6/ip6_var.h>
109 #include <netinet/ip_icmp.h>
110 #include <netinet/icmp_var.h>
111 #include <netinet/udp.h>
112 #include <netinet/udp_var.h>
115 #include <netproto/ipsec/ipsec.h>
119 #include <netinet6/ipsec.h>
122 int udp_mpsafe_proto
= 0;
123 TUNABLE_INT("net.inet.udp.mpsafe_proto", &udp_mpsafe_proto
);
125 int udp_mpsafe_thread
= 0;
126 TUNABLE_INT("net.inet.udp.mpsafe_thread", &udp_mpsafe_thread
);
127 SYSCTL_INT(_net_inet_udp
, OID_AUTO
, mpsafe_thread
, CTLFLAG_RW
,
128 &udp_mpsafe_thread
, 0,
129 "0:BGL, 1:Adaptive BGL, 2:No BGL(experimental)");
132 * UDP protocol implementation.
133 * Per RFC 768, August, 1980.
136 static int udpcksum
= 1;
138 static int udpcksum
= 0; /* XXX */
140 SYSCTL_INT(_net_inet_udp
, UDPCTL_CHECKSUM
, checksum
, CTLFLAG_RW
,
144 SYSCTL_INT(_net_inet_udp
, OID_AUTO
, log_in_vain
, CTLFLAG_RW
,
145 &log_in_vain
, 0, "Log all incoming UDP packets");
147 static int blackhole
= 0;
148 SYSCTL_INT(_net_inet_udp
, OID_AUTO
, blackhole
, CTLFLAG_RW
,
149 &blackhole
, 0, "Do not send port unreachables for refused connects");
151 static int strict_mcast_mship
= 1;
152 SYSCTL_INT(_net_inet_udp
, OID_AUTO
, strict_mcast_mship
, CTLFLAG_RW
,
153 &strict_mcast_mship
, 0, "Only send multicast to member sockets");
155 struct inpcbinfo udbinfo
;
158 #define UDBHASHSIZE 16
161 struct udpstat udpstat
; /* from udp_var.h */
162 SYSCTL_STRUCT(_net_inet_udp
, UDPCTL_STATS
, stats
, CTLFLAG_RW
,
163 &udpstat
, udpstat
, "UDP statistics (struct udpstat, netinet/udp_var.h)");
165 static struct sockaddr_in udp_in
= { sizeof udp_in
, AF_INET
};
168 struct sockaddr_in6 uin6_sin
;
169 u_char uin6_init_done
: 1;
171 { sizeof udp_in6
.uin6_sin
, AF_INET6
},
175 struct ip6_hdr uip6_ip6
;
176 u_char uip6_init_done
: 1;
180 static void udp_append (struct inpcb
*last
, struct ip
*ip
,
181 struct mbuf
*n
, int off
);
183 static void ip_2_ip6_hdr (struct ip6_hdr
*ip6
, struct ip
*ip
);
186 static int udp_detach (struct socket
*so
);
187 static int udp_output (struct inpcb
*, struct mbuf
*, struct sockaddr
*,
188 struct mbuf
*, struct thread
*);
193 in_pcbinfo_init(&udbinfo
);
194 udbinfo
.hashbase
= hashinit(UDBHASHSIZE
, M_PCB
, &udbinfo
.hashmask
);
195 udbinfo
.porthashbase
= hashinit(UDBHASHSIZE
, M_PCB
,
196 &udbinfo
.porthashmask
);
197 udbinfo
.wildcardhashbase
= hashinit(UDBHASHSIZE
, M_PCB
,
198 &udbinfo
.wildcardhashmask
);
199 udbinfo
.ipi_zone
= zinit("udpcb", sizeof(struct inpcb
), maxsockets
,
205 * Check multicast packets to make sure they are only sent to sockets with
206 * multicast memberships for the packet's destination address and arrival
207 * interface. Multicast packets to multicast-unaware sockets are also
210 * Returns 0 if the packet is acceptable, -1 if it is not.
213 check_multicast_membership(struct ip
*ip
, struct inpcb
*inp
, struct mbuf
*m
)
216 struct ip_moptions
*mopt
;
218 if (strict_mcast_mship
== 0 ||
219 !IN_MULTICAST(ntohl(ip
->ip_dst
.s_addr
))) {
222 mopt
= inp
->inp_moptions
;
225 for (mshipno
= 0; mshipno
<= mopt
->imo_num_memberships
; ++mshipno
) {
226 struct in_multi
*maddr
= mopt
->imo_membership
[mshipno
];
228 if (ip
->ip_dst
.s_addr
== maddr
->inm_addr
.s_addr
&&
229 m
->m_pkthdr
.rcvif
== maddr
->inm_ifp
) {
237 udp_input(struct mbuf
*m
, ...)
243 struct mbuf
*opts
= NULL
;
246 struct sockaddr
*append_sa
;
250 off
= __va_arg(ap
, int);
251 proto
= __va_arg(ap
, int);
255 udpstat
.udps_ipackets
++;
258 * Strip IP options, if any; should skip this,
259 * make available to user, and use on returned packets,
260 * but we don't yet have a way to check the checksum
261 * with options still present.
263 if (iphlen
> sizeof(struct ip
)) {
265 iphlen
= sizeof(struct ip
);
269 * IP and UDP headers are together in first mbuf.
270 * Already checked and pulled up in ip_demux().
272 KASSERT(m
->m_len
>= iphlen
+ sizeof(struct udphdr
),
273 ("UDP header not in one mbuf"));
275 ip
= mtod(m
, struct ip
*);
276 uh
= (struct udphdr
*)((caddr_t
)ip
+ iphlen
);
278 /* destination port of 0 is illegal, based on RFC768. */
279 if (uh
->uh_dport
== 0)
283 * Make mbuf data length reflect UDP length.
284 * If not enough data to reflect UDP length, drop.
286 len
= ntohs((u_short
)uh
->uh_ulen
);
287 if (ip
->ip_len
!= len
) {
288 if (len
> ip
->ip_len
|| len
< sizeof(struct udphdr
)) {
289 udpstat
.udps_badlen
++;
292 m_adj(m
, len
- ip
->ip_len
);
293 /* ip->ip_len = len; */
296 * Save a copy of the IP header in case we want restore it
297 * for sending an ICMP error message in response.
302 * Checksum extended UDP header and data.
305 if (m
->m_pkthdr
.csum_flags
& CSUM_DATA_VALID
) {
306 if (m
->m_pkthdr
.csum_flags
& CSUM_PSEUDO_HDR
)
307 uh
->uh_sum
= m
->m_pkthdr
.csum_data
;
309 uh
->uh_sum
= in_pseudo(ip
->ip_src
.s_addr
,
310 ip
->ip_dst
.s_addr
, htonl((u_short
)len
+
311 m
->m_pkthdr
.csum_data
+ IPPROTO_UDP
));
312 uh
->uh_sum
^= 0xffff;
316 bcopy(((struct ipovly
*)ip
)->ih_x1
, b
, 9);
317 bzero(((struct ipovly
*)ip
)->ih_x1
, 9);
318 ((struct ipovly
*)ip
)->ih_len
= uh
->uh_ulen
;
319 uh
->uh_sum
= in_cksum(m
, len
+ sizeof(struct ip
));
320 bcopy(b
, ((struct ipovly
*)ip
)->ih_x1
, 9);
323 udpstat
.udps_badsum
++;
328 udpstat
.udps_nosum
++;
330 if (IN_MULTICAST(ntohl(ip
->ip_dst
.s_addr
)) ||
331 in_broadcast(ip
->ip_dst
, m
->m_pkthdr
.rcvif
)) {
335 * Deliver a multicast or broadcast datagram to *all* sockets
336 * for which the local and remote addresses and ports match
337 * those of the incoming datagram. This allows more than
338 * one process to receive multi/broadcasts on the same port.
339 * (This really ought to be done for unicast datagrams as
340 * well, but that would cause problems with existing
341 * applications that open both address-specific sockets and
342 * a wildcard socket listening to the same port -- they would
343 * end up receiving duplicates of every unicast datagram.
344 * Those applications open the multiple sockets to overcome an
345 * inadequacy of the UDP socket interface, but for backwards
346 * compatibility we avoid the problem here rather than
347 * fixing the interface. Maybe 4.5BSD will remedy this?)
351 * Construct sockaddr format source address.
353 udp_in
.sin_port
= uh
->uh_sport
;
354 udp_in
.sin_addr
= ip
->ip_src
;
356 * Locate pcb(s) for datagram.
357 * (Algorithm copied from raw_intr().)
361 udp_in6
.uin6_init_done
= udp_ip6
.uip6_init_done
= 0;
363 LIST_FOREACH(inp
, &udbinfo
.pcblisthead
, inp_list
) {
364 if (inp
->inp_flags
& INP_PLACEMARKER
)
367 if (!(inp
->inp_vflag
& INP_IPV4
))
370 if (inp
->inp_lport
!= uh
->uh_dport
)
372 if (inp
->inp_laddr
.s_addr
!= INADDR_ANY
) {
373 if (inp
->inp_laddr
.s_addr
!=
377 if (inp
->inp_faddr
.s_addr
!= INADDR_ANY
) {
378 if (inp
->inp_faddr
.s_addr
!=
380 inp
->inp_fport
!= uh
->uh_sport
)
384 if (check_multicast_membership(ip
, inp
, m
) < 0)
391 /* check AH/ESP integrity. */
392 if (ipsec4_in_reject_so(m
, last
->inp_socket
))
393 ipsecstat
.in_polvio
++;
394 /* do not inject data to pcb */
398 /* check AH/ESP integrity. */
399 if (ipsec4_in_reject(m
, last
))
402 #endif /*FAST_IPSEC*/
403 if ((n
= m_copypacket(m
, MB_DONTWAIT
)) != NULL
)
404 udp_append(last
, ip
, n
,
406 sizeof(struct udphdr
));
410 * Don't look for additional matches if this one does
411 * not have either the SO_REUSEPORT or SO_REUSEADDR
412 * socket options set. This heuristic avoids searching
413 * through all pcbs in the common case of a non-shared
414 * port. It * assumes that an application will never
415 * clear these options after setting them.
417 if (!(last
->inp_socket
->so_options
&
418 (SO_REUSEPORT
| SO_REUSEADDR
)))
424 * No matching pcb found; discard datagram.
425 * (No need to send an ICMP Port Unreachable
426 * for a broadcast or multicast datgram.)
428 udpstat
.udps_noportbcast
++;
432 /* check AH/ESP integrity. */
433 if (ipsec4_in_reject_so(m
, last
->inp_socket
)) {
434 ipsecstat
.in_polvio
++;
439 /* check AH/ESP integrity. */
440 if (ipsec4_in_reject(m
, last
))
442 #endif /*FAST_IPSEC*/
443 udp_append(last
, ip
, m
, iphlen
+ sizeof(struct udphdr
));
447 * Locate pcb for datagram.
449 inp
= in_pcblookup_hash(&udbinfo
, ip
->ip_src
, uh
->uh_sport
,
450 ip
->ip_dst
, uh
->uh_dport
, 1, m
->m_pkthdr
.rcvif
);
453 char buf
[sizeof "aaa.bbb.ccc.ddd"];
455 strcpy(buf
, inet_ntoa(ip
->ip_dst
));
457 "Connection attempt to UDP %s:%d from %s:%d\n",
458 buf
, ntohs(uh
->uh_dport
), inet_ntoa(ip
->ip_src
),
459 ntohs(uh
->uh_sport
));
461 udpstat
.udps_noport
++;
462 if (m
->m_flags
& (M_BCAST
| M_MCAST
)) {
463 udpstat
.udps_noportbcast
++;
469 if (badport_bandlim(BANDLIM_ICMP_UNREACH
) < 0)
473 ip
->ip_len
+= iphlen
;
474 icmp_error(m
, ICMP_UNREACH
, ICMP_UNREACH_PORT
, 0, 0);
478 if (ipsec4_in_reject_so(m
, inp
->inp_socket
)) {
479 ipsecstat
.in_polvio
++;
484 if (ipsec4_in_reject(m
, inp
))
486 #endif /*FAST_IPSEC*/
488 * Check the minimum TTL for socket.
490 if (ip
->ip_ttl
< inp
->inp_ip_minttl
)
494 * Construct sockaddr format source address.
495 * Stuff source address and datagram in user buffer.
497 udp_in
.sin_port
= uh
->uh_sport
;
498 udp_in
.sin_addr
= ip
->ip_src
;
499 if ((inp
->inp_flags
& INP_CONTROLOPTS
) ||
500 (inp
->inp_socket
->so_options
& SO_TIMESTAMP
)) {
502 if (inp
->inp_vflag
& INP_IPV6
) {
505 ip_2_ip6_hdr(&udp_ip6
.uip6_ip6
, ip
);
506 savedflags
= inp
->inp_flags
;
507 inp
->inp_flags
&= ~INP_UNMAPPABLEOPTS
;
508 ip6_savecontrol(inp
, &opts
, &udp_ip6
.uip6_ip6
, m
);
509 inp
->inp_flags
= savedflags
;
512 ip_savecontrol(inp
, &opts
, ip
, m
);
514 m_adj(m
, iphlen
+ sizeof(struct udphdr
));
516 if (inp
->inp_vflag
& INP_IPV6
) {
517 in6_sin_2_v4mapsin6(&udp_in
, &udp_in6
.uin6_sin
);
518 append_sa
= (struct sockaddr
*)&udp_in6
;
521 append_sa
= (struct sockaddr
*)&udp_in
;
522 if (ssb_appendaddr(&inp
->inp_socket
->so_rcv
, append_sa
, m
, opts
) == 0) {
523 udpstat
.udps_fullsock
++;
526 sorwakeup(inp
->inp_socket
);
537 ip_2_ip6_hdr(struct ip6_hdr
*ip6
, struct ip
*ip
)
539 bzero(ip6
, sizeof *ip6
);
541 ip6
->ip6_vfc
= IPV6_VERSION
;
542 ip6
->ip6_plen
= ip
->ip_len
;
543 ip6
->ip6_nxt
= ip
->ip_p
;
544 ip6
->ip6_hlim
= ip
->ip_ttl
;
545 ip6
->ip6_src
.s6_addr32
[2] = ip6
->ip6_dst
.s6_addr32
[2] =
547 ip6
->ip6_src
.s6_addr32
[3] = ip
->ip_src
.s_addr
;
548 ip6
->ip6_dst
.s6_addr32
[3] = ip
->ip_dst
.s_addr
;
553 * subroutine of udp_input(), mainly for source code readability.
554 * caller must properly init udp_ip6 and udp_in6 beforehand.
557 udp_append(struct inpcb
*last
, struct ip
*ip
, struct mbuf
*n
, int off
)
559 struct sockaddr
*append_sa
;
560 struct mbuf
*opts
= NULL
;
562 if (last
->inp_flags
& INP_CONTROLOPTS
||
563 last
->inp_socket
->so_options
& SO_TIMESTAMP
) {
565 if (last
->inp_vflag
& INP_IPV6
) {
568 if (udp_ip6
.uip6_init_done
== 0) {
569 ip_2_ip6_hdr(&udp_ip6
.uip6_ip6
, ip
);
570 udp_ip6
.uip6_init_done
= 1;
572 savedflags
= last
->inp_flags
;
573 last
->inp_flags
&= ~INP_UNMAPPABLEOPTS
;
574 ip6_savecontrol(last
, &opts
, &udp_ip6
.uip6_ip6
, n
);
575 last
->inp_flags
= savedflags
;
578 ip_savecontrol(last
, &opts
, ip
, n
);
581 if (last
->inp_vflag
& INP_IPV6
) {
582 if (udp_in6
.uin6_init_done
== 0) {
583 in6_sin_2_v4mapsin6(&udp_in
, &udp_in6
.uin6_sin
);
584 udp_in6
.uin6_init_done
= 1;
586 append_sa
= (struct sockaddr
*)&udp_in6
.uin6_sin
;
589 append_sa
= (struct sockaddr
*)&udp_in
;
591 if (ssb_appendaddr(&last
->inp_socket
->so_rcv
, append_sa
, n
, opts
) == 0) {
595 udpstat
.udps_fullsock
++;
597 sorwakeup(last
->inp_socket
);
601 * Notify a udp user of an asynchronous error;
602 * just wake up so that he can collect error status.
605 udp_notify(struct inpcb
*inp
, int error
)
607 inp
->inp_socket
->so_error
= error
;
608 sorwakeup(inp
->inp_socket
);
609 sowwakeup(inp
->inp_socket
);
612 struct netmsg_udp_notify
{
613 struct netmsg nm_nmsg
;
614 void (*nm_notify
)(struct inpcb
*, int);
615 struct in_addr nm_faddr
;
620 udp_notifyall_oncpu(struct netmsg
*netmsg
)
622 struct netmsg_udp_notify
*nmsg
= (struct netmsg_udp_notify
*)netmsg
;
625 in_pcbnotifyall(&udbinfo
.pcblisthead
, nmsg
->nm_faddr
, nmsg
->nm_arg
,
628 nextcpu
= mycpuid
+ 1;
629 if (nextcpu
< ncpus2
)
630 lwkt_forwardmsg(udp_cport(nextcpu
), &netmsg
->nm_lmsg
);
632 lwkt_replymsg(&netmsg
->nm_lmsg
, 0);
636 udp_rtchange(struct inpcb
*inp
, int err
)
639 /* XXX Nuke this, once UDP inpcbs are CPU localized */
640 if (inp
->inp_route
.ro_rt
&& inp
->inp_route
.ro_rt
->rt_cpuid
== mycpuid
) {
641 rtfree(inp
->inp_route
.ro_rt
);
642 inp
->inp_route
.ro_rt
= NULL
;
644 * A new route can be allocated the next time
645 * output is attempted.
649 in_rtchange(inp
, err
);
654 udp_ctlinput(int cmd
, struct sockaddr
*sa
, void *vip
)
658 void (*notify
) (struct inpcb
*, int) = udp_notify
;
659 struct in_addr faddr
;
662 faddr
= ((struct sockaddr_in
*)sa
)->sin_addr
;
663 if (sa
->sa_family
!= AF_INET
|| faddr
.s_addr
== INADDR_ANY
)
666 if (PRC_IS_REDIRECT(cmd
)) {
668 notify
= udp_rtchange
;
669 } else if (cmd
== PRC_HOSTDEAD
)
671 else if ((unsigned)cmd
>= PRC_NCMDS
|| inetctlerrmap
[cmd
] == 0)
675 uh
= (struct udphdr
*)((caddr_t
)ip
+ (ip
->ip_hl
<< 2));
676 inp
= in_pcblookup_hash(&udbinfo
, faddr
, uh
->uh_dport
,
677 ip
->ip_src
, uh
->uh_sport
, 0, NULL
);
678 if (inp
!= NULL
&& inp
->inp_socket
!= NULL
)
679 (*notify
)(inp
, inetctlerrmap
[cmd
]);
681 } else if (PRC_IS_REDIRECT(cmd
)) {
682 struct netmsg_udp_notify nmsg
;
684 KKASSERT(&curthread
->td_msgport
== cpu_portfn(0));
685 netmsg_init(&nmsg
.nm_nmsg
, &curthread
->td_msgport
, 0,
686 udp_notifyall_oncpu
);
687 nmsg
.nm_faddr
= faddr
;
688 nmsg
.nm_arg
= inetctlerrmap
[cmd
];
689 nmsg
.nm_notify
= notify
;
691 lwkt_domsg(udp_cport(0), &nmsg
.nm_nmsg
.nm_lmsg
, 0);
694 * XXX We should forward msg upon PRC_HOSTHEAD and ip == NULL,
695 * once UDP inpcbs are CPU localized
697 KKASSERT(&curthread
->td_msgport
== udp_cport(0));
698 in_pcbnotifyall(&udbinfo
.pcblisthead
, faddr
, inetctlerrmap
[cmd
],
703 SYSCTL_PROC(_net_inet_udp
, UDPCTL_PCBLIST
, pcblist
, CTLFLAG_RD
, &udbinfo
, 0,
704 in_pcblist_global
, "S,xinpcb", "List of active UDP sockets");
707 udp_getcred(SYSCTL_HANDLER_ARGS
)
709 struct sockaddr_in addrs
[2];
713 error
= suser(req
->td
);
716 error
= SYSCTL_IN(req
, addrs
, sizeof addrs
);
720 inp
= in_pcblookup_hash(&udbinfo
, addrs
[1].sin_addr
, addrs
[1].sin_port
,
721 addrs
[0].sin_addr
, addrs
[0].sin_port
, 1, NULL
);
722 if (inp
== NULL
|| inp
->inp_socket
== NULL
) {
726 error
= SYSCTL_OUT(req
, inp
->inp_socket
->so_cred
, sizeof(struct ucred
));
732 SYSCTL_PROC(_net_inet_udp
, OID_AUTO
, getcred
, CTLTYPE_OPAQUE
|CTLFLAG_RW
,
733 0, 0, udp_getcred
, "S,ucred", "Get the ucred of a UDP connection");
736 udp_output(struct inpcb
*inp
, struct mbuf
*m
, struct sockaddr
*dstaddr
,
737 struct mbuf
*control
, struct thread
*td
)
740 int len
= m
->m_pkthdr
.len
;
741 struct sockaddr_in
*sin
; /* really is initialized before use */
742 int error
= 0, lport_any
= 0;
744 if (len
+ sizeof(struct udpiphdr
) > IP_MAXPACKET
) {
749 if (inp
->inp_lport
== 0) { /* unbound socket */
750 error
= in_pcbbind(inp
, (struct sockaddr
*)NULL
, td
);
753 in_pcbinswildcardhash(inp
);
757 if (dstaddr
!= NULL
) { /* destination address specified */
758 if (inp
->inp_faddr
.s_addr
!= INADDR_ANY
) {
759 /* already connected */
763 sin
= (struct sockaddr_in
*)dstaddr
;
764 if (!prison_remote_ip(td
, (struct sockaddr
*)&sin
)) {
765 error
= EAFNOSUPPORT
; /* IPv6 only jail */
769 if (inp
->inp_faddr
.s_addr
== INADDR_ANY
) {
770 /* no destination specified and not already connected */
778 * Calculate data length and get a mbuf
779 * for UDP and IP headers.
781 M_PREPEND(m
, sizeof(struct udpiphdr
), MB_DONTWAIT
);
788 * Fill in mbuf with extended UDP header
789 * and addresses and length put into network format.
791 ui
= mtod(m
, struct udpiphdr
*);
792 bzero(ui
->ui_x1
, sizeof ui
->ui_x1
); /* XXX still needed? */
793 ui
->ui_pr
= IPPROTO_UDP
;
796 * Set destination address.
798 if (dstaddr
!= NULL
) { /* use specified destination */
799 ui
->ui_dst
= sin
->sin_addr
;
800 ui
->ui_dport
= sin
->sin_port
;
801 } else { /* use connected destination */
802 ui
->ui_dst
= inp
->inp_faddr
;
803 ui
->ui_dport
= inp
->inp_fport
;
807 * Set source address.
809 if (inp
->inp_laddr
.s_addr
== INADDR_ANY
) {
810 struct sockaddr_in
*if_sin
;
812 if (dstaddr
== NULL
) {
814 * connect() had (or should have) failed because
815 * the interface had no IP address, but the
816 * application proceeded to call send() anyways.
822 /* Look up outgoing interface. */
823 if ((error
= in_pcbladdr(inp
, dstaddr
, &if_sin
, td
)))
825 ui
->ui_src
= if_sin
->sin_addr
; /* use address of interface */
827 ui
->ui_src
= inp
->inp_laddr
; /* use non-null bound address */
829 ui
->ui_sport
= inp
->inp_lport
;
830 KASSERT(inp
->inp_lport
!= 0, ("inp lport should have been bound"));
832 ui
->ui_ulen
= htons((u_short
)len
+ sizeof(struct udphdr
));
835 * Set up checksum and output datagram.
838 ui
->ui_sum
= in_pseudo(ui
->ui_src
.s_addr
, ui
->ui_dst
.s_addr
,
839 htons((u_short
)len
+ sizeof(struct udphdr
) + IPPROTO_UDP
));
840 m
->m_pkthdr
.csum_flags
= CSUM_UDP
;
841 m
->m_pkthdr
.csum_data
= offsetof(struct udphdr
, uh_sum
);
845 ((struct ip
*)ui
)->ip_len
= sizeof(struct udpiphdr
) + len
;
846 ((struct ip
*)ui
)->ip_ttl
= inp
->inp_ip_ttl
; /* XXX */
847 ((struct ip
*)ui
)->ip_tos
= inp
->inp_ip_tos
; /* XXX */
848 udpstat
.udps_opackets
++;
850 error
= ip_output(m
, inp
->inp_options
, &inp
->inp_route
,
851 (inp
->inp_socket
->so_options
& (SO_DONTROUTE
| SO_BROADCAST
)) |
853 inp
->inp_moptions
, inp
);
856 * If this is the first data gram sent on an unbound and unconnected
857 * UDP socket, lport will be changed in this function. If target
858 * CPU after this lport changing is no longer the current CPU, then
859 * free the route entry allocated on the current CPU.
862 if (udp_addrcpu(inp
->inp_faddr
.s_addr
, inp
->inp_fport
,
863 inp
->inp_laddr
.s_addr
, inp
->inp_lport
) != mycpuid
) {
864 struct route
*ro
= &inp
->inp_route
;
866 if (ro
->ro_rt
!= NULL
)
868 bzero(ro
, sizeof(*ro
));
878 u_long udp_sendspace
= 9216; /* really max datagram size */
879 /* 40 1K datagrams */
880 SYSCTL_INT(_net_inet_udp
, UDPCTL_MAXDGRAM
, maxdgram
, CTLFLAG_RW
,
881 &udp_sendspace
, 0, "Maximum outgoing UDP datagram size");
883 u_long udp_recvspace
= 40 * (1024 +
885 sizeof(struct sockaddr_in6
)
887 sizeof(struct sockaddr_in
)
890 SYSCTL_INT(_net_inet_udp
, UDPCTL_RECVSPACE
, recvspace
, CTLFLAG_RW
,
891 &udp_recvspace
, 0, "Maximum incoming UDP datagram size");
894 udp_abort(struct socket
*so
)
900 return EINVAL
; /* ??? possible? panic instead? */
901 soisdisconnected(so
);
909 udp_attach(struct socket
*so
, int proto
, struct pru_attach_info
*ai
)
918 error
= soreserve(so
, udp_sendspace
, udp_recvspace
, ai
->sb_rlimit
);
922 error
= in_pcballoc(so
, &udbinfo
);
927 inp
= (struct inpcb
*)so
->so_pcb
;
928 inp
->inp_vflag
|= INP_IPV4
;
929 inp
->inp_ip_ttl
= ip_defttl
;
934 udp_bind(struct socket
*so
, struct sockaddr
*nam
, struct thread
*td
)
936 struct sockaddr_in
*sin
= (struct sockaddr_in
*)nam
;
944 error
= in_pcbbind(inp
, nam
, td
);
947 if (sin
->sin_addr
.s_addr
!= INADDR_ANY
)
948 inp
->inp_flags
|= INP_WASBOUND_NOTANY
;
949 in_pcbinswildcardhash(inp
);
955 udp_connect(struct socket
*so
, struct sockaddr
*nam
, struct thread
*td
)
963 if (inp
->inp_faddr
.s_addr
!= INADDR_ANY
)
967 if (td
->td_proc
&& td
->td_proc
->p_ucred
->cr_prison
!= NULL
&&
968 inp
->inp_laddr
.s_addr
== INADDR_ANY
) {
969 error
= in_pcbbind(inp
, NULL
, td
);
972 if (!prison_remote_ip(td
, nam
))
973 return(EAFNOSUPPORT
); /* IPv6 only jail */
974 if (inp
->inp_flags
& INP_WILDCARD
)
975 in_pcbremwildcardhash(inp
);
976 error
= in_pcbconnect(inp
, nam
, td
);
983 * Make sure that the new target CPU is same as current CPU,
984 * if it is not, then we will have to free the route entry
985 * allocated on the current CPU.
987 if (udp_addrcpu(inp
->inp_faddr
.s_addr
, inp
->inp_fport
,
988 inp
->inp_laddr
.s_addr
, inp
->inp_lport
) != mycpuid
) {
989 struct route
*ro
= &inp
->inp_route
;
991 if (ro
->ro_rt
!= NULL
)
993 bzero(ro
, sizeof(*ro
));
995 } else if (error
== EAFNOSUPPORT
) { /* connection dissolved */
997 * Follow traditional BSD behavior and retain
998 * the local port binding. But, fix the old misbehavior
999 * of overwriting any previously bound local address.
1001 if (!(inp
->inp_flags
& INP_WASBOUND_NOTANY
))
1002 inp
->inp_laddr
.s_addr
= INADDR_ANY
;
1003 in_pcbinswildcardhash(inp
);
1009 udp_detach(struct socket
*so
)
1023 udp_disconnect(struct socket
*so
)
1031 if (inp
->inp_faddr
.s_addr
== INADDR_ANY
)
1035 in_pcbdisconnect(inp
);
1037 so
->so_state
&= ~SS_ISCONNECTED
; /* XXX */
1039 ro
= &inp
->inp_route
;
1040 if (ro
->ro_rt
!= NULL
)
1042 bzero(ro
, sizeof(*ro
));
1048 udp_send(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*addr
,
1049 struct mbuf
*control
, struct thread
*td
)
1058 return udp_output(inp
, m
, addr
, control
, td
);
1062 udp_shutdown(struct socket
*so
)
1073 struct pr_usrreqs udp_usrreqs
= {
1074 .pru_abort
= udp_abort
,
1075 .pru_accept
= pru_accept_notsupp
,
1076 .pru_attach
= udp_attach
,
1077 .pru_bind
= udp_bind
,
1078 .pru_connect
= udp_connect
,
1079 .pru_connect2
= pru_connect2_notsupp
,
1080 .pru_control
= in_control
,
1081 .pru_detach
= udp_detach
,
1082 .pru_disconnect
= udp_disconnect
,
1083 .pru_listen
= pru_listen_notsupp
,
1084 .pru_peeraddr
= in_setpeeraddr
,
1085 .pru_rcvd
= pru_rcvd_notsupp
,
1086 .pru_rcvoob
= pru_rcvoob_notsupp
,
1087 .pru_send
= udp_send
,
1088 .pru_sense
= pru_sense_null
,
1089 .pru_shutdown
= udp_shutdown
,
1090 .pru_sockaddr
= in_setsockaddr
,
1091 .pru_sosend
= sosendudp
,
1092 .pru_soreceive
= soreceive
,
1093 .pru_sopoll
= sopoll