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