]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet/udp_usrreq.c
xnu-792.18.15.tar.gz
[apple/xnu.git] / bsd / netinet / udp_usrreq.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
A
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University 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.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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
58 * SUCH DAMAGE.
59 *
60 * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
9bccf70c 61 * $FreeBSD: src/sys/netinet/udp_usrreq.c,v 1.64.2.13 2001/08/08 18:59:54 ghelmer Exp $
1c79356b
A
62 */
63
64#include <sys/param.h>
65#include <sys/systm.h>
66#include <sys/kernel.h>
67#include <sys/malloc.h>
68#include <sys/mbuf.h>
1c79356b 69#include <sys/domain.h>
1c79356b
A
70#include <sys/protosw.h>
71#include <sys/socket.h>
72#include <sys/socketvar.h>
73#include <sys/sysctl.h>
74#include <sys/syslog.h>
75
1c79356b 76#include <net/if.h>
91447636 77#include <net/if_types.h>
1c79356b
A
78#include <net/route.h>
79
80#include <netinet/in.h>
81#include <netinet/in_systm.h>
82#include <netinet/ip.h>
9bccf70c
A
83#if INET6
84#include <netinet/ip6.h>
85#endif
1c79356b
A
86#include <netinet/in_pcb.h>
87#include <netinet/in_var.h>
88#include <netinet/ip_var.h>
1c79356b 89#if INET6
1c79356b
A
90#include <netinet6/ip6_var.h>
91#endif
9bccf70c
A
92#include <netinet/ip_icmp.h>
93#include <netinet/icmp_var.h>
1c79356b
A
94#include <netinet/udp.h>
95#include <netinet/udp_var.h>
96#include <sys/kdebug.h>
97
98#if IPSEC
99#include <netinet6/ipsec.h>
9bccf70c 100extern int ipsec_bypass;
91447636 101extern lck_mtx_t *sadb_mutex;
1c79356b
A
102#endif /*IPSEC*/
103
104
105#define DBG_LAYER_IN_BEG NETDBG_CODE(DBG_NETUDP, 0)
106#define DBG_LAYER_IN_END NETDBG_CODE(DBG_NETUDP, 2)
107#define DBG_LAYER_OUT_BEG NETDBG_CODE(DBG_NETUDP, 1)
108#define DBG_LAYER_OUT_END NETDBG_CODE(DBG_NETUDP, 3)
109#define DBG_FNC_UDP_INPUT NETDBG_CODE(DBG_NETUDP, (5 << 8))
110#define DBG_FNC_UDP_OUTPUT NETDBG_CODE(DBG_NETUDP, (6 << 8) | 1)
111
1c79356b
A
112/*
113 * UDP protocol implementation.
114 * Per RFC 768, August, 1980.
115 */
116#ifndef COMPAT_42
117static int udpcksum = 1;
118#else
119static int udpcksum = 0; /* XXX */
120#endif
121SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW,
122 &udpcksum, 0, "");
123
9bccf70c 124int log_in_vain = 0;
1c79356b 125SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW,
9bccf70c
A
126 &log_in_vain, 0, "Log all incoming UDP packets");
127
128static int blackhole = 0;
129SYSCTL_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW,
130 &blackhole, 0, "Do not send port unreachables for refused connects");
1c79356b
A
131
132struct inpcbhead udb; /* from udp_var.h */
133#define udb6 udb /* for KAME src sync over BSD*'s */
134struct inpcbinfo udbinfo;
135
136#ifndef UDBHASHSIZE
137#define UDBHASHSIZE 16
138#endif
139
0b4e3aa0 140extern int apple_hwcksum_rx;
55e303ae
A
141extern int esp_udp_encap_port;
142extern u_long route_generation;
0b4e3aa0 143
91447636
A
144extern void ipfwsyslog( int level, char *format,...);
145
146extern int fw_verbose;
147
148#define log_in_vain_log( a ) { \
149 if ( (log_in_vain == 3 ) && (fw_verbose == 2)) { /* Apple logging, log to ipfw.log */ \
150 ipfwsyslog a ; \
151 } \
152 else log a ; \
153}
154
1c79356b
A
155struct udpstat udpstat; /* from udp_var.h */
156SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RD,
9bccf70c 157 &udpstat, udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)");
91447636
A
158SYSCTL_INT(_net_inet_udp, OID_AUTO, pcbcount, CTLFLAG_RD,
159 &udbinfo.ipi_count, 0, "Number of active PCBs");
1c79356b
A
160
161static struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET };
162#if INET6
163struct udp_in6 {
164 struct sockaddr_in6 uin6_sin;
165 u_char uin6_init_done : 1;
166} udp_in6 = {
167 { sizeof(udp_in6.uin6_sin), AF_INET6 },
168 0
169};
170struct udp_ip6 {
171 struct ip6_hdr uip6_ip6;
172 u_char uip6_init_done : 1;
173} udp_ip6;
174#endif /* INET6 */
175
91447636
A
176static void udp_append(struct inpcb *last, struct ip *ip,
177 struct mbuf *n, int off);
1c79356b 178#if INET6
91447636 179static void ip_2_ip6_hdr(struct ip6_hdr *ip6, struct ip *ip);
1c79356b
A
180#endif
181
91447636
A
182static int udp_detach(struct socket *so);
183static int udp_output(struct inpcb *, struct mbuf *, struct sockaddr *,
184 struct mbuf *, struct proc *);
185extern int ChkAddressOK( __uint32_t dstaddr, __uint32_t srcaddr );
1c79356b
A
186
187void
188udp_init()
189{
91447636
A
190 vm_size_t str_size;
191 struct inpcbinfo *pcbinfo;
192
1c79356b
A
193
194 LIST_INIT(&udb);
195 udbinfo.listhead = &udb;
196 udbinfo.hashbase = hashinit(UDBHASHSIZE, M_PCB, &udbinfo.hashmask);
197 udbinfo.porthashbase = hashinit(UDBHASHSIZE, M_PCB,
198 &udbinfo.porthashmask);
9bccf70c 199#ifdef __APPLE__
1c79356b 200 str_size = (vm_size_t) sizeof(struct inpcb);
9bccf70c 201 udbinfo.ipi_zone = (void *) zinit(str_size, 80000*str_size, 8192, "udpcb");
1c79356b 202
91447636
A
203 pcbinfo = &udbinfo;
204 /*
205 * allocate lock group attribute and group for udp pcb mutexes
206 */
207 pcbinfo->mtx_grp_attr = lck_grp_attr_alloc_init();
91447636
A
208
209 pcbinfo->mtx_grp = lck_grp_alloc_init("udppcb", pcbinfo->mtx_grp_attr);
210
211 pcbinfo->mtx_attr = lck_attr_alloc_init();
91447636
A
212
213 if ((pcbinfo->mtx = lck_rw_alloc_init(pcbinfo->mtx_grp, pcbinfo->mtx_attr)) == NULL)
214 return; /* pretty much dead if this fails... */
215
1c79356b 216 in_pcb_nat_init(&udbinfo, AF_INET, IPPROTO_UDP, SOCK_DGRAM);
9bccf70c
A
217#else
218 udbinfo.ipi_zone = zinit("udpcb", sizeof(struct inpcb), maxsockets,
219 ZONE_INTERRUPT, 0);
220#endif
1c79356b
A
221
222#if 0
9bccf70c 223 /* for pcb sharing testing only */
1c79356b
A
224 stat = in_pcb_new_share_client(&udbinfo, &fake_owner);
225 kprintf("udp_init in_pcb_new_share_client - stat = %d\n", stat);
226
227 laddr.s_addr = 0x11646464;
228 faddr.s_addr = 0x11646465;
229
230 lport = 1500;
231 in_pcb_grab_port(&udbinfo, 0, laddr, &lport, faddr, 1600, 0, fake_owner);
232 kprintf("udp_init in_pcb_grab_port - stat = %d\n", stat);
233
234 stat = in_pcb_rem_share_client(&udbinfo, fake_owner);
235 kprintf("udp_init in_pcb_rem_share_client - stat = %d\n", stat);
236
237 stat = in_pcb_new_share_client(&udbinfo, &fake_owner);
238 kprintf("udp_init in_pcb_new_share_client(2) - stat = %d\n", stat);
239
240 laddr.s_addr = 0x11646464;
241 faddr.s_addr = 0x11646465;
242
243 lport = 1500;
244 stat = in_pcb_grab_port(&udbinfo, 0, laddr, &lport, faddr, 1600, 0, fake_owner);
245 kprintf("udp_init in_pcb_grab_port(2) - stat = %d\n", stat);
246#endif
247}
248
249void
250udp_input(m, iphlen)
251 register struct mbuf *m;
252 int iphlen;
253{
254 register struct ip *ip;
255 register struct udphdr *uh;
256 register struct inpcb *inp;
257 struct mbuf *opts = 0;
1c79356b
A
258 int len;
259 struct ip save_ip;
260 struct sockaddr *append_sa;
91447636 261 struct inpcbinfo *pcbinfo = &udbinfo;
1c79356b
A
262
263 udpstat.udps_ipackets++;
1c79356b
A
264
265 KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_START, 0,0,0,0,0);
9bccf70c
A
266 if (m->m_pkthdr.csum_flags & CSUM_TCP_SUM16)
267 m->m_pkthdr.csum_flags = 0; /* invalidate hwcksum for UDP */
1c79356b
A
268
269 /*
270 * Strip IP options, if any; should skip this,
271 * make available to user, and use on returned packets,
272 * but we don't yet have a way to check the checksum
273 * with options still present.
274 */
275 if (iphlen > sizeof (struct ip)) {
276 ip_stripoptions(m, (struct mbuf *)0);
277 iphlen = sizeof(struct ip);
278 }
279
280 /*
281 * Get IP and UDP header together in first mbuf.
282 */
283 ip = mtod(m, struct ip *);
284 if (m->m_len < iphlen + sizeof(struct udphdr)) {
285 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
286 udpstat.udps_hdrops++;
287 KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
288 return;
289 }
290 ip = mtod(m, struct ip *);
291 }
292 uh = (struct udphdr *)((caddr_t)ip + iphlen);
293
9bccf70c
A
294 /* destination port of 0 is illegal, based on RFC768. */
295 if (uh->uh_dport == 0)
296 goto bad;
297
1c79356b
A
298 KERNEL_DEBUG(DBG_LAYER_IN_BEG, uh->uh_dport, uh->uh_sport,
299 ip->ip_src.s_addr, ip->ip_dst.s_addr, uh->uh_ulen);
300
301 /*
302 * Make mbuf data length reflect UDP length.
303 * If not enough data to reflect UDP length, drop.
304 */
305 len = ntohs((u_short)uh->uh_ulen);
306 if (ip->ip_len != len) {
307 if (len > ip->ip_len || len < sizeof(struct udphdr)) {
308 udpstat.udps_badlen++;
309 goto bad;
310 }
311 m_adj(m, len - ip->ip_len);
312 /* ip->ip_len = len; */
313 }
314 /*
315 * Save a copy of the IP header in case we want restore it
316 * for sending an ICMP error message in response.
317 */
318 save_ip = *ip;
319
320 /*
321 * Checksum extended UDP header and data.
322 */
323 if (uh->uh_sum) {
ac5ea4a9
A
324 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
325 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
326 uh->uh_sum = m->m_pkthdr.csum_data;
327 else
328 goto doudpcksum;
329 uh->uh_sum ^= 0xffff;
330 } else {
331 char b[9];
0b4e3aa0 332doudpcksum:
ac5ea4a9
A
333 *(uint32_t*)&b[0] = *(uint32_t*)&((struct ipovly *)ip)->ih_x1[0];
334 *(uint32_t*)&b[4] = *(uint32_t*)&((struct ipovly *)ip)->ih_x1[4];
335 *(uint8_t*)&b[8] = *(uint8_t*)&((struct ipovly *)ip)->ih_x1[8];
336
0b4e3aa0
A
337 bzero(((struct ipovly *)ip)->ih_x1, 9);
338 ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
339 uh->uh_sum = in_cksum(m, len + sizeof (struct ip));
ac5ea4a9
A
340
341 *(uint32_t*)&((struct ipovly *)ip)->ih_x1[0] = *(uint32_t*)&b[0];
342 *(uint32_t*)&((struct ipovly *)ip)->ih_x1[4] = *(uint32_t*)&b[4];
343 *(uint8_t*)&((struct ipovly *)ip)->ih_x1[8] = *(uint8_t*)&b[8];
0b4e3aa0 344 }
1c79356b
A
345 if (uh->uh_sum) {
346 udpstat.udps_badsum++;
347 m_freem(m);
348 KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
349 return;
350 }
351 }
9bccf70c
A
352#ifndef __APPLE__
353 else
354 udpstat.udps_nosum++;
355#endif
1c79356b
A
356
357 if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
358 in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
359 struct inpcb *last;
91447636 360 lck_rw_lock_shared(pcbinfo->mtx);
1c79356b
A
361 /*
362 * Deliver a multicast or broadcast datagram to *all* sockets
363 * for which the local and remote addresses and ports match
364 * those of the incoming datagram. This allows more than
365 * one process to receive multi/broadcasts on the same port.
366 * (This really ought to be done for unicast datagrams as
367 * well, but that would cause problems with existing
368 * applications that open both address-specific sockets and
369 * a wildcard socket listening to the same port -- they would
370 * end up receiving duplicates of every unicast datagram.
371 * Those applications open the multiple sockets to overcome an
372 * inadequacy of the UDP socket interface, but for backwards
373 * compatibility we avoid the problem here rather than
374 * fixing the interface. Maybe 4.5BSD will remedy this?)
375 */
376
91447636 377
1c79356b
A
378 /*
379 * Construct sockaddr format source address.
380 */
381 udp_in.sin_port = uh->uh_sport;
382 udp_in.sin_addr = ip->ip_src;
383 /*
384 * Locate pcb(s) for datagram.
385 * (Algorithm copied from raw_intr().)
386 */
387 last = NULL;
388#if INET6
389 udp_in6.uin6_init_done = udp_ip6.uip6_init_done = 0;
390#endif
391 LIST_FOREACH(inp, &udb, inp_list) {
9bccf70c
A
392#ifdef __APPLE__
393 /* Ignore nat/SharedIP dummy pcbs */
394 if (inp->inp_socket == &udbinfo.nat_dummy_socket)
395 continue;
396#endif
91447636 397 if (inp->inp_socket == NULL)
1c79356b 398 continue;
91447636
A
399 if (inp != sotoinpcb(inp->inp_socket))
400 panic("udp_input: bad so back ptr inp=%x\n", inp);
401#if INET6
402 if ((inp->inp_vflag & INP_IPV4) == 0)
403 continue;
1c79356b 404#endif
91447636
A
405 if (in_pcb_checkstate(inp, WNT_ACQUIRE, 0) == WNT_STOPUSING) {
406 continue;
407 }
408
409 udp_lock(inp->inp_socket, 1, 0);
410
411 if (in_pcb_checkstate(inp, WNT_RELEASE, 1) == WNT_STOPUSING) {
412 udp_unlock(inp->inp_socket, 1, 0);
1c79356b 413 continue;
91447636
A
414 }
415
416 if (inp->inp_lport != uh->uh_dport) {
417 udp_unlock(inp->inp_socket, 1, 0);
418 continue;
419 }
1c79356b
A
420 if (inp->inp_laddr.s_addr != INADDR_ANY) {
421 if (inp->inp_laddr.s_addr !=
91447636
A
422 ip->ip_dst.s_addr) {
423 udp_unlock(inp->inp_socket, 1, 0);
1c79356b 424 continue;
91447636 425 }
1c79356b
A
426 }
427 if (inp->inp_faddr.s_addr != INADDR_ANY) {
428 if (inp->inp_faddr.s_addr !=
429 ip->ip_src.s_addr ||
91447636
A
430 inp->inp_fport != uh->uh_sport) {
431 udp_unlock(inp->inp_socket, 1, 0);
1c79356b 432 continue;
91447636 433 }
1c79356b
A
434 }
435
436 if (last != NULL) {
437 struct mbuf *n;
1c79356b 438#if IPSEC
91447636 439 int skipit = 0;
1c79356b 440 /* check AH/ESP integrity. */
91447636
A
441 if (ipsec_bypass == 0) {
442 lck_mtx_lock(sadb_mutex);
443 if (ipsec4_in_reject_so(m, last->inp_socket)) {
444 ipsecstat.in_polvio++;
445 /* do not inject data to pcb */
446 skipit = 1;
447 }
448 lck_mtx_unlock(sadb_mutex);
449 }
450 if (skipit == 0)
1c79356b
A
451#endif /*IPSEC*/
452 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
9bccf70c
A
453 udp_append(last, ip, n,
454 iphlen +
455 sizeof(struct udphdr));
1c79356b 456 }
91447636 457 udp_unlock(last->inp_socket, 1, 0);
1c79356b
A
458 }
459 last = inp;
460 /*
461 * Don't look for additional matches if this one does
462 * not have either the SO_REUSEPORT or SO_REUSEADDR
463 * socket options set. This heuristic avoids searching
464 * through all pcbs in the common case of a non-shared
465 * port. It * assumes that an application will never
466 * clear these options after setting them.
467 */
468 if ((last->inp_socket->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0)
469 break;
470 }
91447636 471 lck_rw_done(pcbinfo->mtx);
1c79356b
A
472
473 if (last == NULL) {
474 /*
475 * No matching pcb found; discard datagram.
476 * (No need to send an ICMP Port Unreachable
477 * for a broadcast or multicast datgram.)
478 */
479 udpstat.udps_noportbcast++;
480 goto bad;
481 }
482#if IPSEC
1c79356b 483 /* check AH/ESP integrity. */
91447636
A
484 if (ipsec_bypass == 0 && m) {
485 lck_mtx_lock(sadb_mutex);
486 if (ipsec4_in_reject_so(m, last->inp_socket)) {
487 ipsecstat.in_polvio++;
488 lck_mtx_unlock(sadb_mutex);
489 udp_unlock(last->inp_socket, 1, 0);
490 goto bad;
491 }
492 lck_mtx_unlock(sadb_mutex);
1c79356b
A
493 }
494#endif /*IPSEC*/
9bccf70c 495 udp_append(last, ip, m, iphlen + sizeof(struct udphdr));
91447636 496 udp_unlock(last->inp_socket, 1, 0);
1c79356b
A
497 return;
498 }
55e303ae 499
91447636 500#if IPSEC
55e303ae
A
501 /*
502 * UDP to port 4500 with a payload where the first four bytes are
503 * not zero is a UDP encapsulated IPSec packet. Packets where
504 * the payload is one byte and that byte is 0xFF are NAT keepalive
505 * packets. Decapsulate the ESP packet and carry on with IPSec input
506 * or discard the NAT keep-alive.
507 */
508 if (ipsec_bypass == 0 && (esp_udp_encap_port & 0xFFFF) != 0 &&
509 uh->uh_dport == ntohs((u_short)esp_udp_encap_port)) {
510 int payload_len = len - sizeof(struct udphdr) > 4 ? 4 : len - sizeof(struct udphdr);
511 if (m->m_len < iphlen + sizeof(struct udphdr) + payload_len) {
512 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr) + payload_len)) == 0) {
513 udpstat.udps_hdrops++;
514 KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
515 return;
516 }
517 ip = mtod(m, struct ip *);
518 uh = (struct udphdr *)((caddr_t)ip + iphlen);
519 }
520 /* Check for NAT keepalive packet */
521 if (payload_len == 1 && *(u_int8_t*)((caddr_t)uh + sizeof(struct udphdr)) == 0xFF) {
522 m_freem(m);
523 KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
524 return;
525 }
526 else if (payload_len == 4 && *(u_int32_t*)((caddr_t)uh + sizeof(struct udphdr)) != 0) {
527 /* UDP encapsulated IPSec packet to pass through NAT */
528 size_t stripsiz;
529
530 stripsiz = sizeof(struct udphdr);
531
532 ip = mtod(m, struct ip *);
533 ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), iphlen);
534 m->m_data += stripsiz;
535 m->m_len -= stripsiz;
536 m->m_pkthdr.len -= stripsiz;
537 ip = mtod(m, struct ip *);
538 ip->ip_len = ip->ip_len - stripsiz;
539 ip->ip_p = IPPROTO_ESP;
540
541 KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
542 esp4_input(m, iphlen);
543 return;
544 }
545 }
91447636 546#endif
55e303ae 547
1c79356b
A
548 /*
549 * Locate pcb for datagram.
550 */
551 inp = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport,
552 ip->ip_dst, uh->uh_dport, 1, m->m_pkthdr.rcvif);
553 if (inp == NULL) {
554 if (log_in_vain) {
91447636
A
555 char buf[MAX_IPv4_STR_LEN];
556 char buf2[MAX_IPv4_STR_LEN];
557
558 /* check src and dst address */
559 if (log_in_vain != 3)
560 log(LOG_INFO,
561 "Connection attempt to UDP %s:%d from %s:%d\n",
562 inet_ntop(AF_INET, &ip->ip_dst, buf, sizeof(buf)),
563 ntohs(uh->uh_dport),
564 inet_ntop(AF_INET, &ip->ip_src, buf2, sizeof(buf2)),
565 ntohs(uh->uh_sport));
566 else if (!(m->m_flags & (M_BCAST | M_MCAST)) &&
567 ip->ip_dst.s_addr != ip->ip_src.s_addr)
568 log_in_vain_log((LOG_INFO,
569 "Stealth Mode connection attempt to UDP %s:%d from %s:%d\n",
570 inet_ntop(AF_INET, &ip->ip_dst, buf, sizeof(buf)),
571 ntohs(uh->uh_dport),
572 inet_ntop(AF_INET, &ip->ip_src, buf2, sizeof(buf2)),
573 ntohs(uh->uh_sport)))
1c79356b
A
574 }
575 udpstat.udps_noport++;
576 if (m->m_flags & (M_BCAST | M_MCAST)) {
577 udpstat.udps_noportbcast++;
578 goto bad;
579 }
1c79356b 580#if ICMP_BANDLIM
9bccf70c 581 if (badport_bandlim(BANDLIM_ICMP_UNREACH) < 0)
1c79356b
A
582 goto bad;
583#endif
9bccf70c 584 if (blackhole)
91447636
A
585 if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type != IFT_LOOP)
586 goto bad;
9bccf70c
A
587 *ip = save_ip;
588 ip->ip_len += iphlen;
1c79356b
A
589 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
590 KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
591 return;
592 }
91447636
A
593 udp_lock(inp->inp_socket, 1, 0);
594
595 if (in_pcb_checkstate(inp, WNT_RELEASE, 1) == WNT_STOPUSING) {
596 udp_unlock(inp->inp_socket, 1, 0);
1c79356b
A
597 goto bad;
598 }
91447636
A
599#if IPSEC
600 if (ipsec_bypass == 0 && inp != NULL) {
601 lck_mtx_lock(sadb_mutex);
602 if (ipsec4_in_reject_so(m, inp->inp_socket)) {
603 ipsecstat.in_polvio++;
604 lck_mtx_unlock(sadb_mutex);
605 udp_unlock(inp->inp_socket, 1, 0);
606 goto bad;
607 }
608 lck_mtx_unlock(sadb_mutex);
609 }
1c79356b
A
610#endif /*IPSEC*/
611
612 /*
613 * Construct sockaddr format source address.
614 * Stuff source address and datagram in user buffer.
615 */
616 udp_in.sin_port = uh->uh_sport;
617 udp_in.sin_addr = ip->ip_src;
618 if (inp->inp_flags & INP_CONTROLOPTS
619 || inp->inp_socket->so_options & SO_TIMESTAMP) {
620#if INET6
621 if (inp->inp_vflag & INP_IPV6) {
622 int savedflags;
623
624 ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip);
625 savedflags = inp->inp_flags;
626 inp->inp_flags &= ~INP_UNMAPPABLEOPTS;
9bccf70c 627 ip6_savecontrol(inp, &opts, &udp_ip6.uip6_ip6, m);
1c79356b
A
628 inp->inp_flags = savedflags;
629 } else
630#endif
631 ip_savecontrol(inp, &opts, ip, m);
632 }
9bccf70c 633 m_adj(m, iphlen + sizeof(struct udphdr));
1c79356b
A
634
635 KERNEL_DEBUG(DBG_LAYER_IN_END, uh->uh_dport, uh->uh_sport,
636 save_ip.ip_src.s_addr, save_ip.ip_dst.s_addr, uh->uh_ulen);
637
638#if INET6
639 if (inp->inp_vflag & INP_IPV6) {
640 in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin);
641 append_sa = (struct sockaddr *)&udp_in6;
1c79356b
A
642 } else
643#endif
644 append_sa = (struct sockaddr *)&udp_in;
91447636 645 if (sbappendaddr(&inp->inp_socket->so_rcv, append_sa, m, opts, NULL) == 0) {
1c79356b 646 udpstat.udps_fullsock++;
1c79356b 647 }
91447636
A
648 else {
649 sorwakeup(inp->inp_socket);
650 }
651 udp_unlock(inp->inp_socket, 1, 0);
1c79356b
A
652 KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
653 return;
654bad:
655 m_freem(m);
656 if (opts)
657 m_freem(opts);
658 KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
9bccf70c 659 return;
1c79356b
A
660}
661
662#if INET6
663static void
664ip_2_ip6_hdr(ip6, ip)
665 struct ip6_hdr *ip6;
666 struct ip *ip;
667{
668 bzero(ip6, sizeof(*ip6));
669
670 ip6->ip6_vfc = IPV6_VERSION;
671 ip6->ip6_plen = ip->ip_len;
672 ip6->ip6_nxt = ip->ip_p;
673 ip6->ip6_hlim = ip->ip_ttl;
674 ip6->ip6_src.s6_addr32[2] = ip6->ip6_dst.s6_addr32[2] =
675 IPV6_ADDR_INT32_SMP;
676 ip6->ip6_src.s6_addr32[3] = ip->ip_src.s_addr;
677 ip6->ip6_dst.s6_addr32[3] = ip->ip_dst.s_addr;
678}
679#endif
680
681/*
682 * subroutine of udp_input(), mainly for source code readability.
683 * caller must properly init udp_ip6 and udp_in6 beforehand.
684 */
685static void
686udp_append(last, ip, n, off)
687 struct inpcb *last;
688 struct ip *ip;
689 struct mbuf *n;
9bccf70c 690 int off;
1c79356b
A
691{
692 struct sockaddr *append_sa;
693 struct mbuf *opts = 0;
1c79356b
A
694
695 if (last->inp_flags & INP_CONTROLOPTS ||
696 last->inp_socket->so_options & SO_TIMESTAMP) {
697#if INET6
698 if (last->inp_vflag & INP_IPV6) {
699 int savedflags;
700
701 if (udp_ip6.uip6_init_done == 0) {
702 ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip);
703 udp_ip6.uip6_init_done = 1;
704 }
705 savedflags = last->inp_flags;
706 last->inp_flags &= ~INP_UNMAPPABLEOPTS;
9bccf70c 707 ip6_savecontrol(last, &opts, &udp_ip6.uip6_ip6, n);
1c79356b
A
708 last->inp_flags = savedflags;
709 } else
710#endif
711 ip_savecontrol(last, &opts, ip, n);
712 }
713#if INET6
714 if (last->inp_vflag & INP_IPV6) {
715 if (udp_in6.uin6_init_done == 0) {
716 in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin);
717 udp_in6.uin6_init_done = 1;
718 }
719 append_sa = (struct sockaddr *)&udp_in6.uin6_sin;
1c79356b
A
720 } else
721#endif
722 append_sa = (struct sockaddr *)&udp_in;
723 m_adj(n, off);
91447636 724 if (sbappendaddr(&last->inp_socket->so_rcv, append_sa, n, opts, NULL) == 0) {
1c79356b
A
725 udpstat.udps_fullsock++;
726 } else
727 sorwakeup(last->inp_socket);
728}
729
1c79356b
A
730/*
731 * Notify a udp user of an asynchronous error;
732 * just wake up so that he can collect error status.
733 */
734void
735udp_notify(inp, errno)
736 register struct inpcb *inp;
737 int errno;
738{
739 inp->inp_socket->so_error = errno;
740 sorwakeup(inp->inp_socket);
741 sowwakeup(inp->inp_socket);
742}
743
744void
745udp_ctlinput(cmd, sa, vip)
746 int cmd;
747 struct sockaddr *sa;
748 void *vip;
749{
9bccf70c
A
750 struct ip *ip = vip;
751 struct udphdr *uh;
91447636 752 void (*notify)(struct inpcb *, int) = udp_notify;
9bccf70c
A
753 struct in_addr faddr;
754 struct inpcb *inp;
9bccf70c
A
755
756 faddr = ((struct sockaddr_in *)sa)->sin_addr;
757 if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
758 return;
1c79356b 759
9bccf70c
A
760 if (PRC_IS_REDIRECT(cmd)) {
761 ip = 0;
762 notify = in_rtchange;
763 } else if (cmd == PRC_HOSTDEAD)
764 ip = 0;
765 else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0)
1c79356b
A
766 return;
767 if (ip) {
768 uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
9bccf70c
A
769 inp = in_pcblookup_hash(&udbinfo, faddr, uh->uh_dport,
770 ip->ip_src, uh->uh_sport, 0, NULL);
91447636
A
771 if (inp != NULL && inp->inp_socket != NULL) {
772 udp_lock(inp->inp_socket, 1, 0);
773 if (in_pcb_checkstate(inp, WNT_RELEASE, 1) == WNT_STOPUSING) {
774 udp_unlock(inp->inp_socket, 1, 0);
775 return;
776 }
9bccf70c 777 (*notify)(inp, inetctlerrmap[cmd]);
91447636
A
778 udp_unlock(inp->inp_socket, 1, 0);
779 }
1c79356b 780 } else
91447636 781 in_pcbnotifyall(&udbinfo, faddr, inetctlerrmap[cmd], notify);
1c79356b
A
782}
783
1c79356b
A
784static int
785udp_pcblist SYSCTL_HANDLER_ARGS
786{
91447636 787 int error, i, n;
1c79356b
A
788 struct inpcb *inp, **inp_list;
789 inp_gen_t gencnt;
790 struct xinpgen xig;
791
792 /*
793 * The process of preparing the TCB list is too time-consuming and
794 * resource-intensive to repeat twice on every request.
795 */
91447636
A
796 lck_rw_lock_exclusive(udbinfo.mtx);
797 if (req->oldptr == USER_ADDR_NULL) {
1c79356b
A
798 n = udbinfo.ipi_count;
799 req->oldidx = 2 * (sizeof xig)
800 + (n + n/8) * sizeof(struct xinpcb);
91447636 801 lck_rw_done(udbinfo.mtx);
1c79356b
A
802 return 0;
803 }
804
91447636
A
805 if (req->newptr != USER_ADDR_NULL) {
806 lck_rw_done(udbinfo.mtx);
1c79356b 807 return EPERM;
91447636 808 }
1c79356b
A
809
810 /*
811 * OK, now we're committed to doing something.
812 */
1c79356b
A
813 gencnt = udbinfo.ipi_gencnt;
814 n = udbinfo.ipi_count;
1c79356b 815
3a60a9f5 816 bzero(&xig, sizeof(xig));
1c79356b
A
817 xig.xig_len = sizeof xig;
818 xig.xig_count = n;
819 xig.xig_gen = gencnt;
820 xig.xig_sogen = so_gencnt;
821 error = SYSCTL_OUT(req, &xig, sizeof xig);
91447636
A
822 if (error) {
823 lck_rw_done(udbinfo.mtx);
1c79356b 824 return error;
91447636 825 }
9bccf70c
A
826 /*
827 * We are done if there is no pcb
828 */
91447636
A
829 if (n == 0) {
830 lck_rw_done(udbinfo.mtx);
9bccf70c 831 return 0;
91447636 832 }
1c79356b
A
833
834 inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK);
835 if (inp_list == 0) {
91447636 836 lck_rw_done(udbinfo.mtx);
1c79356b
A
837 return ENOMEM;
838 }
9bccf70c
A
839
840 for (inp = LIST_FIRST(udbinfo.listhead), i = 0; inp && i < n;
841 inp = LIST_NEXT(inp, inp_list)) {
91447636 842 if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD)
1c79356b
A
843 inp_list[i++] = inp;
844 }
1c79356b
A
845 n = i;
846
847 error = 0;
848 for (i = 0; i < n; i++) {
849 inp = inp_list[i];
91447636 850 if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD) {
1c79356b 851 struct xinpcb xi;
3a60a9f5
A
852
853 bzero(&xi, sizeof(xi));
1c79356b
A
854 xi.xi_len = sizeof xi;
855 /* XXX should avoid extra copy */
91447636 856 inpcb_to_compat(inp, &xi.xi_inp);
1c79356b
A
857 if (inp->inp_socket)
858 sotoxsocket(inp->inp_socket, &xi.xi_socket);
859 error = SYSCTL_OUT(req, &xi, sizeof xi);
860 }
861 }
862 if (!error) {
863 /*
864 * Give the user an updated idea of our state.
865 * If the generation differs from what we told
866 * her before, she knows that something happened
867 * while we were processing this request, and it
868 * might be necessary to retry.
869 */
3a60a9f5
A
870 bzero(&xig, sizeof(xig));
871 xig.xig_len = sizeof xig;
1c79356b
A
872 xig.xig_gen = udbinfo.ipi_gencnt;
873 xig.xig_sogen = so_gencnt;
874 xig.xig_count = udbinfo.ipi_count;
1c79356b
A
875 error = SYSCTL_OUT(req, &xig, sizeof xig);
876 }
877 FREE(inp_list, M_TEMP);
91447636 878 lck_rw_done(udbinfo.mtx);
1c79356b
A
879 return error;
880}
881
882SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
883 udp_pcblist, "S,xinpcb", "List of active UDP sockets");
884
885
886
91447636
A
887static __inline__ u_int16_t
888get_socket_id(struct socket * s)
889{
890 u_int16_t val;
891
892 if (s == NULL) {
893 return (0);
894 }
895 val = (u_int16_t)(((u_int32_t)s) / sizeof(struct socket));
896 if (val == 0) {
897 val = 0xffff;
898 }
899 return (val);
900}
901
1c79356b
A
902static int
903udp_output(inp, m, addr, control, p)
904 register struct inpcb *inp;
9bccf70c 905 struct mbuf *m;
1c79356b
A
906 struct sockaddr *addr;
907 struct mbuf *control;
908 struct proc *p;
909{
910 register struct udpiphdr *ui;
911 register int len = m->m_pkthdr.len;
91447636
A
912 struct sockaddr_in *sin, src;
913 struct in_addr origladdr, laddr, faddr;
914 u_short lport, fport;
915 struct sockaddr_in *ifaddr;
916 int error = 0, udp_dodisconnect = 0;
917
1c79356b
A
918
919 KERNEL_DEBUG(DBG_FNC_UDP_OUTPUT | DBG_FUNC_START, 0,0,0,0,0);
920
921 if (control)
922 m_freem(control); /* XXX */
923
924 KERNEL_DEBUG(DBG_LAYER_OUT_BEG, inp->inp_fport, inp->inp_lport,
925 inp->inp_laddr.s_addr, inp->inp_faddr.s_addr,
926 (htons((u_short)len + sizeof (struct udphdr))));
927
928 if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {
929 error = EMSGSIZE;
930 goto release;
931 }
932
55e303ae
A
933 /* If there was a routing change, discard cached route and check
934 * that we have a valid source address.
935 * Reacquire a new source address if INADDR_ANY was specified
936 */
937
91447636
A
938#if 1
939 lck_mtx_assert(inp->inpcb_mtx, LCK_MTX_ASSERT_OWNED);
940#endif
941
55e303ae 942 if (inp->inp_route.ro_rt && inp->inp_route.ro_rt->generation_id != route_generation) {
91447636 943 if (ifa_foraddr(inp->inp_laddr.s_addr) == 0) { /* src address is gone */
55e303ae
A
944 if (inp->inp_flags & INP_INADDR_ANY)
945 inp->inp_faddr.s_addr = INADDR_ANY; /* new src will be set later */
946 else {
947 error = EADDRNOTAVAIL;
948 goto release;
949 }
950 }
951 rtfree(inp->inp_route.ro_rt);
952 inp->inp_route.ro_rt = (struct rtentry *)0;
953 }
954
91447636
A
955 origladdr= laddr = inp->inp_laddr;
956 faddr = inp->inp_faddr;
957 lport = inp->inp_lport;
958 fport = inp->inp_fport;
959
1c79356b 960 if (addr) {
91447636
A
961 sin = (struct sockaddr_in *)addr;
962 if (faddr.s_addr != INADDR_ANY) {
1c79356b
A
963 error = EISCONN;
964 goto release;
965 }
91447636
A
966 if (lport == 0) {
967 /*
968 * In case we don't have a local port set, go through the full connect.
969 * We don't have a local port yet (ie, we can't be looked up),
970 * so it's not an issue if the input runs at the same time we do this.
971 */
972 error = in_pcbconnect(inp, addr, p);
973 if (error) {
974 goto release;
975 }
976 laddr = inp->inp_laddr;
977 lport = inp->inp_lport;
978 faddr = inp->inp_faddr;
979 fport = inp->inp_fport;
980 udp_dodisconnect = 1;
981 }
982 else {
983 /* Fast path case
984 * we have a full address and a local port.
985 * use those info to build the packet without changing the pcb
986 * and interfering with the input path. See 3851370
987 */
988 if (laddr.s_addr == INADDR_ANY) {
989 if ((error = in_pcbladdr(inp, addr, &ifaddr)) != 0)
990 goto release;
991 laddr = ifaddr->sin_addr;
992 inp->inp_flags |= INP_INADDR_ANY; /* from pcbconnect: remember we don't care about src addr.*/
993 }
994
995 faddr = sin->sin_addr;
996 fport = sin->sin_port;
1c79356b
A
997 }
998 } else {
91447636 999 if (faddr.s_addr == INADDR_ANY) {
1c79356b
A
1000 error = ENOTCONN;
1001 goto release;
1002 }
1003 }
55e303ae
A
1004
1005
1c79356b
A
1006 /*
1007 * Calculate data length and get a mbuf
1008 * for UDP and IP headers.
1009 */
1010 M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
1011 if (m == 0) {
1012 error = ENOBUFS;
55e303ae 1013 goto abort;
1c79356b
A
1014 }
1015
1016 /*
1017 * Fill in mbuf with extended UDP header
1018 * and addresses and length put into network format.
1019 */
1020 ui = mtod(m, struct udpiphdr *);
9bccf70c 1021 bzero(ui->ui_x1, sizeof(ui->ui_x1)); /* XXX still needed? */
1c79356b 1022 ui->ui_pr = IPPROTO_UDP;
91447636
A
1023 ui->ui_src = laddr;
1024 ui->ui_dst = faddr;
1025 ui->ui_sport = lport;
1026 ui->ui_dport = fport;
9bccf70c 1027 ui->ui_ulen = htons((u_short)len + sizeof(struct udphdr));
1c79356b
A
1028
1029 /*
9bccf70c 1030 * Set up checksum and output datagram.
1c79356b 1031 */
1c79356b 1032 if (udpcksum) {
9bccf70c
A
1033 ui->ui_sum = in_pseudo(ui->ui_src.s_addr, ui->ui_dst.s_addr,
1034 htons((u_short)len + sizeof(struct udphdr) + IPPROTO_UDP));
1035 m->m_pkthdr.csum_flags = CSUM_UDP;
1036 m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
1037 } else {
0b4e3aa0 1038 ui->ui_sum = 0;
9bccf70c 1039 }
1c79356b
A
1040 ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
1041 ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */
1042 ((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */
1043 udpstat.udps_opackets++;
1044
1045 KERNEL_DEBUG(DBG_LAYER_OUT_END, ui->ui_dport, ui->ui_sport,
1046 ui->ui_src.s_addr, ui->ui_dst.s_addr, ui->ui_ulen);
1047
1c79356b 1048#if IPSEC
9bccf70c
A
1049 if (ipsec_bypass == 0 && ipsec_setsocket(m, inp->inp_socket) != 0) {
1050 error = ENOBUFS;
55e303ae 1051 goto abort;
9bccf70c 1052 }
1c79356b 1053#endif /*IPSEC*/
91447636
A
1054 m->m_pkthdr.socket_id = get_socket_id(inp->inp_socket);
1055 error = ip_output_list(m, 0, inp->inp_options, &inp->inp_route,
9bccf70c 1056 (inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)),
1c79356b
A
1057 inp->inp_moptions);
1058
91447636 1059 if (udp_dodisconnect) {
1c79356b 1060 in_pcbdisconnect(inp);
91447636 1061 inp->inp_laddr = origladdr; /* XXX rehash? */
1c79356b
A
1062 }
1063 KERNEL_DEBUG(DBG_FNC_UDP_OUTPUT | DBG_FUNC_END, error, 0,0,0,0);
1064 return (error);
1065
55e303ae 1066abort:
91447636 1067 if (udp_dodisconnect) {
55e303ae 1068 in_pcbdisconnect(inp);
91447636 1069 inp->inp_laddr = origladdr; /* XXX rehash? */
55e303ae
A
1070 }
1071
1c79356b
A
1072release:
1073 m_freem(m);
1074 KERNEL_DEBUG(DBG_FNC_UDP_OUTPUT | DBG_FUNC_END, error, 0,0,0,0);
1075 return (error);
1076}
1077
1078u_long udp_sendspace = 9216; /* really max datagram size */
1079 /* 40 1K datagrams */
1080SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,
9bccf70c 1081 &udp_sendspace, 0, "Maximum outgoing UDP datagram size");
1c79356b 1082
9bccf70c 1083u_long udp_recvspace = 40 * (1024 +
1c79356b
A
1084#if INET6
1085 sizeof(struct sockaddr_in6)
9bccf70c 1086#else
1c79356b 1087 sizeof(struct sockaddr_in)
9bccf70c 1088#endif
1c79356b
A
1089 );
1090SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
9bccf70c 1091 &udp_recvspace, 0, "Maximum incoming UDP datagram size");
1c79356b
A
1092
1093static int
1094udp_abort(struct socket *so)
1095{
1096 struct inpcb *inp;
1c79356b
A
1097
1098 inp = sotoinpcb(so);
1099 if (inp == 0)
91447636 1100 panic("udp_abort: so=%x null inp\n", so); /* ??? possible? panic instead? */
1c79356b 1101 soisdisconnected(so);
1c79356b 1102 in_pcbdetach(inp);
1c79356b
A
1103 return 0;
1104}
1105
1106static int
1107udp_attach(struct socket *so, int proto, struct proc *p)
1108{
1109 struct inpcb *inp;
91447636 1110 int error;
1c79356b 1111
9bccf70c
A
1112 inp = sotoinpcb(so);
1113 if (inp != 0)
91447636 1114 panic ("udp_attach so=%x inp=%x\n", so, inp);
9bccf70c 1115
1c79356b 1116 error = in_pcballoc(so, &udbinfo, p);
1c79356b
A
1117 if (error)
1118 return error;
91447636
A
1119 error = soreserve(so, udp_sendspace, udp_recvspace);
1120 if (error)
1121 return error;
1c79356b
A
1122 inp = (struct inpcb *)so->so_pcb;
1123 inp->inp_vflag |= INP_IPV4;
1124 inp->inp_ip_ttl = ip_defttl;
1c79356b
A
1125 return 0;
1126}
1127
1128static int
1129udp_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
1130{
1131 struct inpcb *inp;
91447636 1132 int error;
1c79356b
A
1133
1134 inp = sotoinpcb(so);
1135 if (inp == 0)
1136 return EINVAL;
1c79356b 1137 error = in_pcbbind(inp, nam, p);
1c79356b
A
1138 return error;
1139}
1140
1141static int
1142udp_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
1143{
1144 struct inpcb *inp;
91447636 1145 int error;
1c79356b
A
1146
1147 inp = sotoinpcb(so);
1148 if (inp == 0)
1149 return EINVAL;
1150 if (inp->inp_faddr.s_addr != INADDR_ANY)
1151 return EISCONN;
1c79356b 1152 error = in_pcbconnect(inp, nam, p);
91447636 1153 if (error == 0)
1c79356b
A
1154 soisconnected(so);
1155 return error;
1156}
1157
1158static int
1159udp_detach(struct socket *so)
1160{
1161 struct inpcb *inp;
1c79356b
A
1162
1163 inp = sotoinpcb(so);
1164 if (inp == 0)
91447636 1165 panic("udp_detach: so=%x null inp\n", so); /* ??? possible? panic instead? */
1c79356b 1166 in_pcbdetach(inp);
91447636 1167 inp->inp_state = INPCB_STATE_DEAD;
1c79356b
A
1168 return 0;
1169}
1170
1171static int
1172udp_disconnect(struct socket *so)
1173{
1174 struct inpcb *inp;
1c79356b
A
1175
1176 inp = sotoinpcb(so);
1177 if (inp == 0)
1178 return EINVAL;
1179 if (inp->inp_faddr.s_addr == INADDR_ANY)
1180 return ENOTCONN;
1181
1c79356b
A
1182 in_pcbdisconnect(inp);
1183 inp->inp_laddr.s_addr = INADDR_ANY;
1c79356b
A
1184 so->so_state &= ~SS_ISCONNECTED; /* XXX */
1185 return 0;
1186}
1187
1188static int
1189udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1190 struct mbuf *control, struct proc *p)
1191{
1192 struct inpcb *inp;
1193
1194 inp = sotoinpcb(so);
1195 if (inp == 0) {
1196 m_freem(m);
1197 return EINVAL;
1198 }
1199 return udp_output(inp, m, addr, control, p);
1200}
1201
1202int
1203udp_shutdown(struct socket *so)
1204{
1205 struct inpcb *inp;
1206
1207 inp = sotoinpcb(so);
1208 if (inp == 0)
1209 return EINVAL;
1210 socantsendmore(so);
1211 return 0;
1212}
1213
1214struct pr_usrreqs udp_usrreqs = {
1215 udp_abort, pru_accept_notsupp, udp_attach, udp_bind, udp_connect,
1216 pru_connect2_notsupp, in_control, udp_detach, udp_disconnect,
1217 pru_listen_notsupp, in_setpeeraddr, pru_rcvd_notsupp,
1218 pru_rcvoob_notsupp, udp_send, pru_sense_null, udp_shutdown,
91447636 1219 in_setsockaddr, sosend, soreceive, pru_sopoll_notsupp
1c79356b
A
1220};
1221
91447636
A
1222
1223int
1224udp_lock(so, refcount, debug)
1225 struct socket *so;
1226 int refcount, debug;
1227{
1228 int lr_saved;
89b3af67
A
1229 if (debug == 0)
1230 lr_saved = (unsigned int) __builtin_return_address(0);
91447636 1231 else lr_saved = debug;
91447636
A
1232
1233 if (so->so_pcb) {
1234 lck_mtx_assert(((struct inpcb *)so->so_pcb)->inpcb_mtx, LCK_MTX_ASSERT_NOTOWNED);
1235 lck_mtx_lock(((struct inpcb *)so->so_pcb)->inpcb_mtx);
1236 }
89b3af67 1237 else
91447636 1238 panic("udp_lock: so=%x NO PCB! lr=%x\n", so, lr_saved);
91447636
A
1239
1240 if (refcount)
1241 so->so_usecount++;
1242
89b3af67
A
1243 so->lock_lr[so->next_lock_lr] = (void *)lr_saved;
1244 so->next_lock_lr = (so->next_lock_lr+1) % SO_LCKDBG_MAX;
91447636
A
1245 return (0);
1246}
1247
1248int
1249udp_unlock(so, refcount, debug)
1250 struct socket *so;
1251 int refcount;
1252 int debug;
1253{
1254 int lr_saved;
1255 struct inpcb *inp = sotoinpcb(so);
1256 struct inpcbinfo *pcbinfo = &udbinfo;
89b3af67
A
1257
1258 if (debug == 0)
1259 lr_saved = (unsigned int) __builtin_return_address(0);
91447636 1260 else lr_saved = debug;
89b3af67 1261
91447636
A
1262 if (refcount) {
1263 so->so_usecount--;
1264#if 0
1265 if (so->so_usecount == 0 && (inp->inp_wantcnt == WNT_STOPUSING)) {
1266 if (lck_rw_try_lock_exclusive(pcbinfo->mtx)) {
1267 in_pcbdispose(inp);
1268 lck_rw_done(pcbinfo->mtx);
1269 return(0);
1270 }
1271 }
1272#endif
1273 }
89b3af67 1274 if (so->so_pcb == NULL)
91447636 1275 panic("udp_unlock: so=%x NO PCB! lr=%x\n", so, lr_saved);
91447636
A
1276 else {
1277 lck_mtx_assert(((struct inpcb *)so->so_pcb)->inpcb_mtx, LCK_MTX_ASSERT_OWNED);
89b3af67
A
1278 so->unlock_lr[so->next_unlock_lr] = (void *)lr_saved;
1279 so->next_unlock_lr = (so->next_unlock_lr+1) % SO_LCKDBG_MAX;
91447636
A
1280 lck_mtx_unlock(((struct inpcb *)so->so_pcb)->inpcb_mtx);
1281 }
1282
1283
91447636
A
1284 return (0);
1285}
1286
1287lck_mtx_t *
1288udp_getlock(so, locktype)
1289 struct socket *so;
1290 int locktype;
1291{
1292 struct inpcb *inp = sotoinpcb(so);
1293
1294
1295 if (so->so_pcb)
1296 return(inp->inpcb_mtx);
1297 else {
1298 panic("udp_getlock: so=%x NULL so_pcb\n", so);
1299 return (so->so_proto->pr_domain->dom_mtx);
1300 }
1301}
1302
1303void
1304udp_slowtimo()
1305{
1306 struct inpcb *inp, *inpnxt;
1307 struct socket *so;
1308 struct inpcbinfo *pcbinfo = &udbinfo;
1309
1310 lck_rw_lock_exclusive(pcbinfo->mtx);
1311
1312 for (inp = udb.lh_first; inp != NULL; inp = inpnxt) {
1313 inpnxt = inp->inp_list.le_next;
1314
1315 /* Ignore nat/SharedIP dummy pcbs */
1316 if (inp->inp_socket == &udbinfo.nat_dummy_socket)
1317 continue;
1318
1319 if (inp->inp_wantcnt != WNT_STOPUSING)
1320 continue;
1321
1322 so = inp->inp_socket;
1323 if (!lck_mtx_try_lock(inp->inpcb_mtx)) /* skip if busy, no hurry for cleanup... */
1324 continue;
1325
1326 if (so->so_usecount == 0)
1327 in_pcbdispose(inp);
1328 else
1329 lck_mtx_unlock(inp->inpcb_mtx);
1330 }
1331 lck_rw_done(pcbinfo->mtx);
1332}
1333
1334int
1335ChkAddressOK( __uint32_t dstaddr, __uint32_t srcaddr )
1336{
1337 if ( dstaddr == srcaddr ){
1338 return 0;
1339 }
1340 return 1;
1341}
1342