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>
82 #include <sys/protosw.h>
83 #include <sys/socket.h>
84 #include <sys/socketvar.h>
85 #include <sys/sysctl.h>
86 #include <sys/syslog.h>
87 #include <sys/thread2.h>
88 #include <sys/in_cksum.h>
90 #include <machine/stdarg.h>
92 #include <vm/vm_zone.h>
95 #include <net/route.h>
96 #include <net/netmsg2.h>
98 #include <netinet/in.h>
99 #include <netinet/in_systm.h>
100 #include <netinet/ip.h>
102 #include <netinet/ip6.h>
104 #include <netinet/in_pcb.h>
105 #include <netinet/in_var.h>
106 #include <netinet/ip_var.h>
108 #include <netinet6/ip6_var.h>
110 #include <netinet/ip_icmp.h>
111 #include <netinet/icmp_var.h>
112 #include <netinet/udp.h>
113 #include <netinet/udp_var.h>
116 #include <netproto/ipsec/ipsec.h>
120 #include <netinet6/ipsec.h>
123 int udp_mpsafe_proto
= 0;
124 TUNABLE_INT("net.inet.udp.mpsafe_proto", &udp_mpsafe_proto
);
126 int udp_mpsafe_thread
= NETMSG_SERVICE_ADAPTIVE
;
127 TUNABLE_INT("net.inet.udp.mpsafe_thread", &udp_mpsafe_thread
);
128 SYSCTL_INT(_net_inet_udp
, OID_AUTO
, mpsafe_thread
, CTLFLAG_RW
,
129 &udp_mpsafe_thread
, 0,
130 "0:BGL, 1:Adaptive BGL, 2:No BGL(experimental)");
133 * UDP protocol implementation.
134 * Per RFC 768, August, 1980.
137 static int udpcksum
= 1;
139 static int udpcksum
= 0; /* XXX */
141 SYSCTL_INT(_net_inet_udp
, UDPCTL_CHECKSUM
, checksum
, CTLFLAG_RW
,
145 SYSCTL_INT(_net_inet_udp
, OID_AUTO
, log_in_vain
, CTLFLAG_RW
,
146 &log_in_vain
, 0, "Log all incoming UDP packets");
148 static int blackhole
= 0;
149 SYSCTL_INT(_net_inet_udp
, OID_AUTO
, blackhole
, CTLFLAG_RW
,
150 &blackhole
, 0, "Do not send port unreachables for refused connects");
152 static int strict_mcast_mship
= 1;
153 SYSCTL_INT(_net_inet_udp
, OID_AUTO
, strict_mcast_mship
, CTLFLAG_RW
,
154 &strict_mcast_mship
, 0, "Only send multicast to member sockets");
156 struct inpcbinfo udbinfo
;
159 #define UDBHASHSIZE 16
162 struct udpstat udpstat
; /* from udp_var.h */
163 SYSCTL_STRUCT(_net_inet_udp
, UDPCTL_STATS
, stats
, CTLFLAG_RW
,
164 &udpstat
, udpstat
, "UDP statistics (struct udpstat, netinet/udp_var.h)");
166 static struct sockaddr_in udp_in
= { sizeof udp_in
, AF_INET
};
169 struct sockaddr_in6 uin6_sin
;
170 u_char uin6_init_done
: 1;
172 { sizeof udp_in6
.uin6_sin
, AF_INET6
},
176 struct ip6_hdr uip6_ip6
;
177 u_char uip6_init_done
: 1;
181 static void udp_append (struct inpcb
*last
, struct ip
*ip
,
182 struct mbuf
*n
, int off
);
184 static void ip_2_ip6_hdr (struct ip6_hdr
*ip6
, struct ip
*ip
);
187 static int udp_detach (struct socket
*so
);
188 static int udp_output (struct inpcb
*, struct mbuf
*, struct sockaddr
*,
189 struct mbuf
*, struct thread
*);
194 in_pcbinfo_init(&udbinfo
);
195 udbinfo
.hashbase
= hashinit(UDBHASHSIZE
, M_PCB
, &udbinfo
.hashmask
);
196 udbinfo
.porthashbase
= hashinit(UDBHASHSIZE
, M_PCB
,
197 &udbinfo
.porthashmask
);
198 udbinfo
.wildcardhashbase
= hashinit(UDBHASHSIZE
, M_PCB
,
199 &udbinfo
.wildcardhashmask
);
200 udbinfo
.ipi_zone
= zinit("udpcb", sizeof(struct inpcb
), maxsockets
,
206 * Check multicast packets to make sure they are only sent to sockets with
207 * multicast memberships for the packet's destination address and arrival
208 * interface. Multicast packets to multicast-unaware sockets are also
211 * Returns 0 if the packet is acceptable, -1 if it is not.
214 check_multicast_membership(struct ip
*ip
, struct inpcb
*inp
, struct mbuf
*m
)
217 struct ip_moptions
*mopt
;
219 if (strict_mcast_mship
== 0 ||
220 !IN_MULTICAST(ntohl(ip
->ip_dst
.s_addr
))) {
223 mopt
= inp
->inp_moptions
;
226 for (mshipno
= 0; mshipno
<= mopt
->imo_num_memberships
; ++mshipno
) {
227 struct in_multi
*maddr
= mopt
->imo_membership
[mshipno
];
229 if (ip
->ip_dst
.s_addr
== maddr
->inm_addr
.s_addr
&&
230 m
->m_pkthdr
.rcvif
== maddr
->inm_ifp
) {
238 udp_input(struct mbuf
*m
, ...)
244 struct mbuf
*opts
= NULL
;
247 struct sockaddr
*append_sa
;
251 off
= __va_arg(ap
, int);
252 proto
= __va_arg(ap
, int);
256 udpstat
.udps_ipackets
++;
259 * Strip IP options, if any; should skip this,
260 * make available to user, and use on returned packets,
261 * but we don't yet have a way to check the checksum
262 * with options still present.
264 if (iphlen
> sizeof(struct ip
)) {
266 iphlen
= sizeof(struct ip
);
270 * IP and UDP headers are together in first mbuf.
271 * Already checked and pulled up in ip_demux().
273 KASSERT(m
->m_len
>= iphlen
+ sizeof(struct udphdr
),
274 ("UDP header not in one mbuf"));
276 ip
= mtod(m
, struct ip
*);
277 uh
= (struct udphdr
*)((caddr_t
)ip
+ iphlen
);
279 /* destination port of 0 is illegal, based on RFC768. */
280 if (uh
->uh_dport
== 0)
284 * Make mbuf data length reflect UDP length.
285 * If not enough data to reflect UDP length, drop.
287 len
= ntohs((u_short
)uh
->uh_ulen
);
288 if (ip
->ip_len
!= len
) {
289 if (len
> ip
->ip_len
|| len
< sizeof(struct udphdr
)) {
290 udpstat
.udps_badlen
++;
293 m_adj(m
, len
- ip
->ip_len
);
294 /* ip->ip_len = len; */
297 * Save a copy of the IP header in case we want restore it
298 * for sending an ICMP error message in response.
303 * Checksum extended UDP header and data.
306 if (m
->m_pkthdr
.csum_flags
& CSUM_DATA_VALID
) {
307 if (m
->m_pkthdr
.csum_flags
& CSUM_PSEUDO_HDR
)
308 uh
->uh_sum
= m
->m_pkthdr
.csum_data
;
310 uh
->uh_sum
= in_pseudo(ip
->ip_src
.s_addr
,
311 ip
->ip_dst
.s_addr
, htonl((u_short
)len
+
312 m
->m_pkthdr
.csum_data
+ IPPROTO_UDP
));
313 uh
->uh_sum
^= 0xffff;
317 bcopy(((struct ipovly
*)ip
)->ih_x1
, b
, 9);
318 bzero(((struct ipovly
*)ip
)->ih_x1
, 9);
319 ((struct ipovly
*)ip
)->ih_len
= uh
->uh_ulen
;
320 uh
->uh_sum
= in_cksum(m
, len
+ sizeof(struct ip
));
321 bcopy(b
, ((struct ipovly
*)ip
)->ih_x1
, 9);
324 udpstat
.udps_badsum
++;
329 udpstat
.udps_nosum
++;
331 if (IN_MULTICAST(ntohl(ip
->ip_dst
.s_addr
)) ||
332 in_broadcast(ip
->ip_dst
, m
->m_pkthdr
.rcvif
)) {
336 * Deliver a multicast or broadcast datagram to *all* sockets
337 * for which the local and remote addresses and ports match
338 * those of the incoming datagram. This allows more than
339 * one process to receive multi/broadcasts on the same port.
340 * (This really ought to be done for unicast datagrams as
341 * well, but that would cause problems with existing
342 * applications that open both address-specific sockets and
343 * a wildcard socket listening to the same port -- they would
344 * end up receiving duplicates of every unicast datagram.
345 * Those applications open the multiple sockets to overcome an
346 * inadequacy of the UDP socket interface, but for backwards
347 * compatibility we avoid the problem here rather than
348 * fixing the interface. Maybe 4.5BSD will remedy this?)
352 * Construct sockaddr format source address.
354 udp_in
.sin_port
= uh
->uh_sport
;
355 udp_in
.sin_addr
= ip
->ip_src
;
357 * Locate pcb(s) for datagram.
358 * (Algorithm copied from raw_intr().)
362 udp_in6
.uin6_init_done
= udp_ip6
.uip6_init_done
= 0;
364 LIST_FOREACH(inp
, &udbinfo
.pcblisthead
, inp_list
) {
365 if (inp
->inp_flags
& INP_PLACEMARKER
)
368 if (!(inp
->inp_vflag
& INP_IPV4
))
371 if (inp
->inp_lport
!= uh
->uh_dport
)
373 if (inp
->inp_laddr
.s_addr
!= INADDR_ANY
) {
374 if (inp
->inp_laddr
.s_addr
!=
378 if (inp
->inp_faddr
.s_addr
!= INADDR_ANY
) {
379 if (inp
->inp_faddr
.s_addr
!=
381 inp
->inp_fport
!= uh
->uh_sport
)
385 if (check_multicast_membership(ip
, inp
, m
) < 0)
392 /* check AH/ESP integrity. */
393 if (ipsec4_in_reject_so(m
, last
->inp_socket
))
394 ipsecstat
.in_polvio
++;
395 /* do not inject data to pcb */
399 /* check AH/ESP integrity. */
400 if (ipsec4_in_reject(m
, last
))
403 #endif /*FAST_IPSEC*/
404 if ((n
= m_copypacket(m
, MB_DONTWAIT
)) != NULL
)
405 udp_append(last
, ip
, n
,
407 sizeof(struct udphdr
));
411 * Don't look for additional matches if this one does
412 * not have either the SO_REUSEPORT or SO_REUSEADDR
413 * socket options set. This heuristic avoids searching
414 * through all pcbs in the common case of a non-shared
415 * port. It * assumes that an application will never
416 * clear these options after setting them.
418 if (!(last
->inp_socket
->so_options
&
419 (SO_REUSEPORT
| SO_REUSEADDR
)))
425 * No matching pcb found; discard datagram.
426 * (No need to send an ICMP Port Unreachable
427 * for a broadcast or multicast datgram.)
429 udpstat
.udps_noportbcast
++;
433 /* check AH/ESP integrity. */
434 if (ipsec4_in_reject_so(m
, last
->inp_socket
)) {
435 ipsecstat
.in_polvio
++;
440 /* check AH/ESP integrity. */
441 if (ipsec4_in_reject(m
, last
))
443 #endif /*FAST_IPSEC*/
444 udp_append(last
, ip
, m
, iphlen
+ sizeof(struct udphdr
));
448 * Locate pcb for datagram.
450 inp
= in_pcblookup_hash(&udbinfo
, ip
->ip_src
, uh
->uh_sport
,
451 ip
->ip_dst
, uh
->uh_dport
, 1, m
->m_pkthdr
.rcvif
);
454 char buf
[sizeof "aaa.bbb.ccc.ddd"];
456 strcpy(buf
, inet_ntoa(ip
->ip_dst
));
458 "Connection attempt to UDP %s:%d from %s:%d\n",
459 buf
, ntohs(uh
->uh_dport
), inet_ntoa(ip
->ip_src
),
460 ntohs(uh
->uh_sport
));
462 udpstat
.udps_noport
++;
463 if (m
->m_flags
& (M_BCAST
| M_MCAST
)) {
464 udpstat
.udps_noportbcast
++;
470 if (badport_bandlim(BANDLIM_ICMP_UNREACH
) < 0)
474 ip
->ip_len
+= iphlen
;
475 icmp_error(m
, ICMP_UNREACH
, ICMP_UNREACH_PORT
, 0, 0);
479 if (ipsec4_in_reject_so(m
, inp
->inp_socket
)) {
480 ipsecstat
.in_polvio
++;
485 if (ipsec4_in_reject(m
, inp
))
487 #endif /*FAST_IPSEC*/
489 * Check the minimum TTL for socket.
491 if (ip
->ip_ttl
< inp
->inp_ip_minttl
)
495 * Construct sockaddr format source address.
496 * Stuff source address and datagram in user buffer.
498 udp_in
.sin_port
= uh
->uh_sport
;
499 udp_in
.sin_addr
= ip
->ip_src
;
500 if ((inp
->inp_flags
& INP_CONTROLOPTS
) ||
501 (inp
->inp_socket
->so_options
& SO_TIMESTAMP
)) {
503 if (inp
->inp_vflag
& INP_IPV6
) {
506 ip_2_ip6_hdr(&udp_ip6
.uip6_ip6
, ip
);
507 savedflags
= inp
->inp_flags
;
508 inp
->inp_flags
&= ~INP_UNMAPPABLEOPTS
;
509 ip6_savecontrol(inp
, &opts
, &udp_ip6
.uip6_ip6
, m
);
510 inp
->inp_flags
= savedflags
;
513 ip_savecontrol(inp
, &opts
, ip
, m
);
515 m_adj(m
, iphlen
+ sizeof(struct udphdr
));
517 if (inp
->inp_vflag
& INP_IPV6
) {
518 in6_sin_2_v4mapsin6(&udp_in
, &udp_in6
.uin6_sin
);
519 append_sa
= (struct sockaddr
*)&udp_in6
;
522 append_sa
= (struct sockaddr
*)&udp_in
;
523 if (ssb_appendaddr(&inp
->inp_socket
->so_rcv
, append_sa
, m
, opts
) == 0) {
524 udpstat
.udps_fullsock
++;
527 sorwakeup(inp
->inp_socket
);
538 ip_2_ip6_hdr(struct ip6_hdr
*ip6
, struct ip
*ip
)
540 bzero(ip6
, sizeof *ip6
);
542 ip6
->ip6_vfc
= IPV6_VERSION
;
543 ip6
->ip6_plen
= ip
->ip_len
;
544 ip6
->ip6_nxt
= ip
->ip_p
;
545 ip6
->ip6_hlim
= ip
->ip_ttl
;
546 ip6
->ip6_src
.s6_addr32
[2] = ip6
->ip6_dst
.s6_addr32
[2] =
548 ip6
->ip6_src
.s6_addr32
[3] = ip
->ip_src
.s_addr
;
549 ip6
->ip6_dst
.s6_addr32
[3] = ip
->ip_dst
.s_addr
;
554 * subroutine of udp_input(), mainly for source code readability.
555 * caller must properly init udp_ip6 and udp_in6 beforehand.
558 udp_append(struct inpcb
*last
, struct ip
*ip
, struct mbuf
*n
, int off
)
560 struct sockaddr
*append_sa
;
561 struct mbuf
*opts
= NULL
;
563 if (last
->inp_flags
& INP_CONTROLOPTS
||
564 last
->inp_socket
->so_options
& SO_TIMESTAMP
) {
566 if (last
->inp_vflag
& INP_IPV6
) {
569 if (udp_ip6
.uip6_init_done
== 0) {
570 ip_2_ip6_hdr(&udp_ip6
.uip6_ip6
, ip
);
571 udp_ip6
.uip6_init_done
= 1;
573 savedflags
= last
->inp_flags
;
574 last
->inp_flags
&= ~INP_UNMAPPABLEOPTS
;
575 ip6_savecontrol(last
, &opts
, &udp_ip6
.uip6_ip6
, n
);
576 last
->inp_flags
= savedflags
;
579 ip_savecontrol(last
, &opts
, ip
, n
);
582 if (last
->inp_vflag
& INP_IPV6
) {
583 if (udp_in6
.uin6_init_done
== 0) {
584 in6_sin_2_v4mapsin6(&udp_in
, &udp_in6
.uin6_sin
);
585 udp_in6
.uin6_init_done
= 1;
587 append_sa
= (struct sockaddr
*)&udp_in6
.uin6_sin
;
590 append_sa
= (struct sockaddr
*)&udp_in
;
592 if (ssb_appendaddr(&last
->inp_socket
->so_rcv
, append_sa
, n
, opts
) == 0) {
596 udpstat
.udps_fullsock
++;
598 sorwakeup(last
->inp_socket
);
602 * Notify a udp user of an asynchronous error;
603 * just wake up so that he can collect error status.
606 udp_notify(struct inpcb
*inp
, int error
)
608 inp
->inp_socket
->so_error
= error
;
609 sorwakeup(inp
->inp_socket
);
610 sowwakeup(inp
->inp_socket
);
613 struct netmsg_udp_notify
{
614 struct netmsg nm_nmsg
;
615 void (*nm_notify
)(struct inpcb
*, int);
616 struct in_addr nm_faddr
;
621 udp_notifyall_oncpu(struct netmsg
*netmsg
)
623 struct netmsg_udp_notify
*nmsg
= (struct netmsg_udp_notify
*)netmsg
;
626 in_pcbnotifyall(&udbinfo
.pcblisthead
, nmsg
->nm_faddr
, nmsg
->nm_arg
,
629 nextcpu
= mycpuid
+ 1;
630 if (nextcpu
< ncpus2
)
631 lwkt_forwardmsg(udp_cport(nextcpu
), &netmsg
->nm_lmsg
);
633 lwkt_replymsg(&netmsg
->nm_lmsg
, 0);
637 udp_rtchange(struct inpcb
*inp
, int err
)
640 /* XXX Nuke this, once UDP inpcbs are CPU localized */
641 if (inp
->inp_route
.ro_rt
&& inp
->inp_route
.ro_rt
->rt_cpuid
== mycpuid
) {
642 rtfree(inp
->inp_route
.ro_rt
);
643 inp
->inp_route
.ro_rt
= NULL
;
645 * A new route can be allocated the next time
646 * output is attempted.
650 in_rtchange(inp
, err
);
655 udp_ctlinput(int cmd
, struct sockaddr
*sa
, void *vip
)
659 void (*notify
) (struct inpcb
*, int) = udp_notify
;
660 struct in_addr faddr
;
663 faddr
= ((struct sockaddr_in
*)sa
)->sin_addr
;
664 if (sa
->sa_family
!= AF_INET
|| faddr
.s_addr
== INADDR_ANY
)
667 if (PRC_IS_REDIRECT(cmd
)) {
669 notify
= udp_rtchange
;
670 } else if (cmd
== PRC_HOSTDEAD
)
672 else if ((unsigned)cmd
>= PRC_NCMDS
|| inetctlerrmap
[cmd
] == 0)
676 uh
= (struct udphdr
*)((caddr_t
)ip
+ (ip
->ip_hl
<< 2));
677 inp
= in_pcblookup_hash(&udbinfo
, faddr
, uh
->uh_dport
,
678 ip
->ip_src
, uh
->uh_sport
, 0, NULL
);
679 if (inp
!= NULL
&& inp
->inp_socket
!= NULL
)
680 (*notify
)(inp
, inetctlerrmap
[cmd
]);
682 } else if (PRC_IS_REDIRECT(cmd
)) {
683 struct netmsg_udp_notify nmsg
;
685 KKASSERT(&curthread
->td_msgport
== cpu_portfn(0));
686 netmsg_init(&nmsg
.nm_nmsg
, &curthread
->td_msgport
, 0,
687 udp_notifyall_oncpu
);
688 nmsg
.nm_faddr
= faddr
;
689 nmsg
.nm_arg
= inetctlerrmap
[cmd
];
690 nmsg
.nm_notify
= notify
;
692 lwkt_domsg(udp_cport(0), &nmsg
.nm_nmsg
.nm_lmsg
, 0);
695 * XXX We should forward msg upon PRC_HOSTHEAD and ip == NULL,
696 * once UDP inpcbs are CPU localized
698 KKASSERT(&curthread
->td_msgport
== udp_cport(0));
699 in_pcbnotifyall(&udbinfo
.pcblisthead
, faddr
, inetctlerrmap
[cmd
],
704 SYSCTL_PROC(_net_inet_udp
, UDPCTL_PCBLIST
, pcblist
, CTLFLAG_RD
, &udbinfo
, 0,
705 in_pcblist_global
, "S,xinpcb", "List of active UDP sockets");
708 udp_getcred(SYSCTL_HANDLER_ARGS
)
710 struct sockaddr_in addrs
[2];
714 error
= priv_check(req
->td
, PRIV_ROOT
);
717 error
= SYSCTL_IN(req
, addrs
, sizeof addrs
);
721 inp
= in_pcblookup_hash(&udbinfo
, addrs
[1].sin_addr
, addrs
[1].sin_port
,
722 addrs
[0].sin_addr
, addrs
[0].sin_port
, 1, NULL
);
723 if (inp
== NULL
|| inp
->inp_socket
== NULL
) {
727 error
= SYSCTL_OUT(req
, inp
->inp_socket
->so_cred
, sizeof(struct ucred
));
733 SYSCTL_PROC(_net_inet_udp
, OID_AUTO
, getcred
, CTLTYPE_OPAQUE
|CTLFLAG_RW
,
734 0, 0, udp_getcred
, "S,ucred", "Get the ucred of a UDP connection");
737 udp_output(struct inpcb
*inp
, struct mbuf
*m
, struct sockaddr
*dstaddr
,
738 struct mbuf
*control
, struct thread
*td
)
741 int len
= m
->m_pkthdr
.len
;
742 struct sockaddr_in
*sin
; /* really is initialized before use */
743 int error
= 0, lport_any
= 0;
745 if (len
+ sizeof(struct udpiphdr
) > IP_MAXPACKET
) {
750 if (inp
->inp_lport
== 0) { /* unbound socket */
751 error
= in_pcbbind(inp
, NULL
, td
);
754 in_pcbinswildcardhash(inp
);
758 if (dstaddr
!= NULL
) { /* destination address specified */
759 if (inp
->inp_faddr
.s_addr
!= INADDR_ANY
) {
760 /* already connected */
764 sin
= (struct sockaddr_in
*)dstaddr
;
765 if (!prison_remote_ip(td
, (struct sockaddr
*)&sin
)) {
766 error
= EAFNOSUPPORT
; /* IPv6 only jail */
770 if (inp
->inp_faddr
.s_addr
== INADDR_ANY
) {
771 /* no destination specified and not already connected */
779 * Calculate data length and get a mbuf
780 * for UDP and IP headers.
782 M_PREPEND(m
, sizeof(struct udpiphdr
), MB_DONTWAIT
);
789 * Fill in mbuf with extended UDP header
790 * and addresses and length put into network format.
792 ui
= mtod(m
, struct udpiphdr
*);
793 bzero(ui
->ui_x1
, sizeof ui
->ui_x1
); /* XXX still needed? */
794 ui
->ui_pr
= IPPROTO_UDP
;
797 * Set destination address.
799 if (dstaddr
!= NULL
) { /* use specified destination */
800 ui
->ui_dst
= sin
->sin_addr
;
801 ui
->ui_dport
= sin
->sin_port
;
802 } else { /* use connected destination */
803 ui
->ui_dst
= inp
->inp_faddr
;
804 ui
->ui_dport
= inp
->inp_fport
;
808 * Set source address.
810 if (inp
->inp_laddr
.s_addr
== INADDR_ANY
) {
811 struct sockaddr_in
*if_sin
;
813 if (dstaddr
== NULL
) {
815 * connect() had (or should have) failed because
816 * the interface had no IP address, but the
817 * application proceeded to call send() anyways.
823 /* Look up outgoing interface. */
824 if ((error
= in_pcbladdr(inp
, dstaddr
, &if_sin
, td
)))
826 ui
->ui_src
= if_sin
->sin_addr
; /* use address of interface */
828 ui
->ui_src
= inp
->inp_laddr
; /* use non-null bound address */
830 ui
->ui_sport
= inp
->inp_lport
;
831 KASSERT(inp
->inp_lport
!= 0, ("inp lport should have been bound"));
833 ui
->ui_ulen
= htons((u_short
)len
+ sizeof(struct udphdr
));
836 * Set up checksum and output datagram.
839 ui
->ui_sum
= in_pseudo(ui
->ui_src
.s_addr
, ui
->ui_dst
.s_addr
,
840 htons((u_short
)len
+ sizeof(struct udphdr
) + IPPROTO_UDP
));
841 m
->m_pkthdr
.csum_flags
= CSUM_UDP
;
842 m
->m_pkthdr
.csum_data
= offsetof(struct udphdr
, uh_sum
);
846 ((struct ip
*)ui
)->ip_len
= sizeof(struct udpiphdr
) + len
;
847 ((struct ip
*)ui
)->ip_ttl
= inp
->inp_ip_ttl
; /* XXX */
848 ((struct ip
*)ui
)->ip_tos
= inp
->inp_ip_tos
; /* XXX */
849 udpstat
.udps_opackets
++;
851 error
= ip_output(m
, inp
->inp_options
, &inp
->inp_route
,
852 (inp
->inp_socket
->so_options
& (SO_DONTROUTE
| SO_BROADCAST
)) |
854 inp
->inp_moptions
, inp
);
857 * If this is the first data gram sent on an unbound and unconnected
858 * UDP socket, lport will be changed in this function. If target
859 * CPU after this lport changing is no longer the current CPU, then
860 * free the route entry allocated on the current CPU.
863 if (udp_addrcpu(inp
->inp_faddr
.s_addr
, inp
->inp_fport
,
864 inp
->inp_laddr
.s_addr
, inp
->inp_lport
) != mycpuid
) {
865 struct route
*ro
= &inp
->inp_route
;
867 if (ro
->ro_rt
!= NULL
)
869 bzero(ro
, sizeof(*ro
));
879 u_long udp_sendspace
= 9216; /* really max datagram size */
880 /* 40 1K datagrams */
881 SYSCTL_INT(_net_inet_udp
, UDPCTL_MAXDGRAM
, maxdgram
, CTLFLAG_RW
,
882 &udp_sendspace
, 0, "Maximum outgoing UDP datagram size");
884 u_long udp_recvspace
= 40 * (1024 +
886 sizeof(struct sockaddr_in6
)
888 sizeof(struct sockaddr_in
)
891 SYSCTL_INT(_net_inet_udp
, UDPCTL_RECVSPACE
, recvspace
, CTLFLAG_RW
,
892 &udp_recvspace
, 0, "Maximum incoming UDP datagram size");
895 udp_abort(struct socket
*so
)
901 return EINVAL
; /* ??? possible? panic instead? */
902 soisdisconnected(so
);
910 udp_attach(struct socket
*so
, int proto
, struct pru_attach_info
*ai
)
919 error
= soreserve(so
, udp_sendspace
, udp_recvspace
, ai
->sb_rlimit
);
923 error
= in_pcballoc(so
, &udbinfo
);
928 inp
= (struct inpcb
*)so
->so_pcb
;
929 inp
->inp_vflag
|= INP_IPV4
;
930 inp
->inp_ip_ttl
= ip_defttl
;
935 udp_bind(struct socket
*so
, struct sockaddr
*nam
, struct thread
*td
)
937 struct sockaddr_in
*sin
= (struct sockaddr_in
*)nam
;
945 error
= in_pcbbind(inp
, nam
, td
);
948 if (sin
->sin_addr
.s_addr
!= INADDR_ANY
)
949 inp
->inp_flags
|= INP_WASBOUND_NOTANY
;
950 in_pcbinswildcardhash(inp
);
956 udp_connect(struct socket
*so
, struct sockaddr
*nam
, struct thread
*td
)
964 if (inp
->inp_faddr
.s_addr
!= INADDR_ANY
)
968 if (td
->td_proc
&& td
->td_proc
->p_ucred
->cr_prison
!= NULL
&&
969 inp
->inp_laddr
.s_addr
== INADDR_ANY
) {
970 error
= in_pcbbind(inp
, NULL
, td
);
973 if (!prison_remote_ip(td
, nam
))
974 return(EAFNOSUPPORT
); /* IPv6 only jail */
975 if (inp
->inp_flags
& INP_WILDCARD
)
976 in_pcbremwildcardhash(inp
);
977 error
= in_pcbconnect(inp
, nam
, td
);
984 * Make sure that the new target CPU is same as current CPU,
985 * if it is not, then we will have to free the route entry
986 * allocated on the current CPU.
988 if (udp_addrcpu(inp
->inp_faddr
.s_addr
, inp
->inp_fport
,
989 inp
->inp_laddr
.s_addr
, inp
->inp_lport
) != mycpuid
) {
990 struct route
*ro
= &inp
->inp_route
;
992 if (ro
->ro_rt
!= NULL
)
994 bzero(ro
, sizeof(*ro
));
996 } else if (error
== EAFNOSUPPORT
) { /* connection dissolved */
998 * Follow traditional BSD behavior and retain
999 * the local port binding. But, fix the old misbehavior
1000 * of overwriting any previously bound local address.
1002 if (!(inp
->inp_flags
& INP_WASBOUND_NOTANY
))
1003 inp
->inp_laddr
.s_addr
= INADDR_ANY
;
1004 in_pcbinswildcardhash(inp
);
1010 udp_detach(struct socket
*so
)
1024 udp_disconnect(struct socket
*so
)
1032 if (inp
->inp_faddr
.s_addr
== INADDR_ANY
)
1036 in_pcbdisconnect(inp
);
1038 so
->so_state
&= ~SS_ISCONNECTED
; /* XXX */
1040 ro
= &inp
->inp_route
;
1041 if (ro
->ro_rt
!= NULL
)
1043 bzero(ro
, sizeof(*ro
));
1049 udp_send(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*addr
,
1050 struct mbuf
*control
, struct thread
*td
)
1059 return udp_output(inp
, m
, addr
, control
, td
);
1063 udp_shutdown(struct socket
*so
)
1074 struct pr_usrreqs udp_usrreqs
= {
1075 .pru_abort
= udp_abort
,
1076 .pru_accept
= pru_accept_notsupp
,
1077 .pru_attach
= udp_attach
,
1078 .pru_bind
= udp_bind
,
1079 .pru_connect
= udp_connect
,
1080 .pru_connect2
= pru_connect2_notsupp
,
1081 .pru_control
= in_control
,
1082 .pru_detach
= udp_detach
,
1083 .pru_disconnect
= udp_disconnect
,
1084 .pru_listen
= pru_listen_notsupp
,
1085 .pru_peeraddr
= in_setpeeraddr
,
1086 .pru_rcvd
= pru_rcvd_notsupp
,
1087 .pru_rcvoob
= pru_rcvoob_notsupp
,
1088 .pru_send
= udp_send
,
1089 .pru_sense
= pru_sense_null
,
1090 .pru_shutdown
= udp_shutdown
,
1091 .pru_sockaddr
= in_setsockaddr
,
1092 .pru_sosend
= sosendudp
,
1093 .pru_soreceive
= soreceive
,
1094 .pru_sopoll
= sopoll