udp_usrreq.c revision 1.66.4.6 1 /* $NetBSD: udp_usrreq.c,v 1.66.4.6 2004/04/12 04:58:25 jmc Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
34 * The Regents of the University of California. All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
65 */
66
67 #include "opt_ipsec.h"
68 #include "opt_ipkdb.h"
69
70 #include <sys/param.h>
71 #include <sys/malloc.h>
72 #include <sys/mbuf.h>
73 #include <sys/protosw.h>
74 #include <sys/socket.h>
75 #include <sys/socketvar.h>
76 #include <sys/errno.h>
77 #include <sys/stat.h>
78 #include <sys/systm.h>
79 #include <sys/proc.h>
80 #include <sys/domain.h>
81
82 #include <vm/vm.h>
83 #include <sys/sysctl.h>
84
85 #include <net/if.h>
86 #include <net/route.h>
87
88 #include <netinet/in.h>
89 #include <netinet/in_systm.h>
90 #include <netinet/in_var.h>
91 #include <netinet/ip.h>
92 #include <netinet/in_pcb.h>
93 #include <netinet/ip_var.h>
94 #include <netinet/ip_icmp.h>
95 #include <netinet/udp.h>
96 #include <netinet/udp_var.h>
97
98 #ifdef INET6
99 #include <netinet/ip6.h>
100 #include <netinet/icmp6.h>
101 #include <netinet6/ip6_var.h>
102 #include <netinet6/in6_pcb.h>
103 #include <netinet6/udp6_var.h>
104 #endif
105
106 #ifdef PULLDOWN_TEST
107 #ifndef INET6
108 /* always need ip6.h for IP6_EXTHDR_GET */
109 #include <netinet/ip6.h>
110 #endif
111 #endif
112
113 #include "faith.h"
114 #if defined(NFAITH) && NFAITH > 0
115 #include <net/if_faith.h>
116 #endif
117
118 #include <machine/stdarg.h>
119
120 #ifdef IPSEC
121 #include <netinet6/ipsec.h>
122 #include <netkey/key.h>
123 #include <netkey/key_debug.h>
124 #endif /*IPSEC*/
125
126 #ifdef IPKDB
127 #include <ipkdb/ipkdb.h>
128 #endif
129
130 /*
131 * UDP protocol implementation.
132 * Per RFC 768, August, 1980.
133 */
134 #ifndef COMPAT_42
135 int udpcksum = 1;
136 #else
137 int udpcksum = 0; /* XXX */
138 #endif
139
140 static void udp4_sendup __P((struct mbuf *, int, struct sockaddr *,
141 struct socket *));
142 static int udp4_realinput __P((struct sockaddr_in *, struct sockaddr_in *,
143 struct mbuf *, int));
144 #ifdef INET6
145 static void udp6_sendup __P((struct mbuf *, int, struct sockaddr *,
146 struct socket *));
147 static int in6_mcmatch __P((struct in6pcb *, struct in6_addr *,
148 struct ifnet *));
149 static int udp6_realinput __P((int, struct sockaddr_in6 *,
150 struct sockaddr_in6 *, struct mbuf *, int));
151 #endif
152 static void udp_notify __P((struct inpcb *, int));
153
154 #ifndef UDBHASHSIZE
155 #define UDBHASHSIZE 128
156 #endif
157 int udbhashsize = UDBHASHSIZE;
158
159 void
160 udp_init()
161 {
162
163 in_pcbinit(&udbtable, udbhashsize, udbhashsize);
164 }
165
166 #ifndef UDP6
167 void
168 #if __STDC__
169 udp_input(struct mbuf *m, ...)
170 #else
171 udp_input(m, va_alist)
172 struct mbuf *m;
173 va_dcl
174 #endif
175 {
176 va_list ap;
177 struct sockaddr_in src, dst;
178 struct ip *ip;
179 struct udphdr *uh;
180 int iphlen, proto;
181 int len;
182 int n;
183
184 va_start(ap, m);
185 iphlen = va_arg(ap, int);
186 proto = va_arg(ap, int);
187 va_end(ap);
188
189 udpstat.udps_ipackets++;
190
191 #ifndef PULLDOWN_TEST
192 /*
193 * Strip IP options, if any; should skip this,
194 * make available to user, and use on returned packets,
195 * but we don't yet have a way to check the checksum
196 * with options still present.
197 */
198 if (iphlen > sizeof (struct ip)) {
199 ip_stripoptions(m, (struct mbuf *)0);
200 iphlen = sizeof(struct ip);
201 }
202 #else
203 /*
204 * we may enable the above code if we save and pass IPv4 options
205 * to the userland.
206 */
207 #endif
208
209 /*
210 * Get IP and UDP header together in first mbuf.
211 */
212 ip = mtod(m, struct ip *);
213 #ifndef PULLDOWN_TEST
214 if (m->m_len < iphlen + sizeof(struct udphdr)) {
215 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
216 udpstat.udps_hdrops++;
217 return;
218 }
219 ip = mtod(m, struct ip *);
220 }
221 uh = (struct udphdr *)((caddr_t)ip + iphlen);
222 #else
223 IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
224 if (uh == NULL) {
225 udpstat.udps_hdrops++;
226 return;
227 }
228 #endif
229
230 /* destination port of 0 is illegal, based on RFC768. */
231 if (uh->uh_dport == 0)
232 goto bad;
233
234 /*
235 * Make mbuf data length reflect UDP length.
236 * If not enough data to reflect UDP length, drop.
237 */
238 len = ntohs((u_int16_t)uh->uh_ulen);
239 if (ip->ip_len != iphlen + len) {
240 if (ip->ip_len < iphlen + len || len < sizeof(struct udphdr)) {
241 udpstat.udps_badlen++;
242 goto bad;
243 }
244 m_adj(m, iphlen + len - ip->ip_len);
245 }
246
247 /*
248 * Checksum extended UDP header and data.
249 */
250 if (uh->uh_sum) {
251 if (in4_cksum(m, IPPROTO_UDP, iphlen, len) != 0) {
252 udpstat.udps_badsum++;
253 m_freem(m);
254 return;
255 }
256 }
257
258 /* construct source and dst sockaddrs. */
259 bzero(&src, sizeof(src));
260 src.sin_family = AF_INET;
261 src.sin_len = sizeof(struct sockaddr_in);
262 bcopy(&ip->ip_src, &src.sin_addr, sizeof(src.sin_addr));
263 src.sin_port = uh->uh_sport;
264 bzero(&dst, sizeof(dst));
265 dst.sin_family = AF_INET;
266 dst.sin_len = sizeof(struct sockaddr_in);
267 bcopy(&ip->ip_dst, &dst.sin_addr, sizeof(dst.sin_addr));
268 dst.sin_port = uh->uh_dport;
269
270 n = udp4_realinput(&src, &dst, m, iphlen);
271 #ifdef INET6
272 if (IN_MULTICAST(ip->ip_dst.s_addr) || n == 0) {
273 struct sockaddr_in6 src6, dst6;
274
275 bzero(&src6, sizeof(src6));
276 src6.sin6_family = AF_INET6;
277 src6.sin6_len = sizeof(struct sockaddr_in6);
278 src6.sin6_addr.s6_addr[10] = src6.sin6_addr.s6_addr[11] = 0xff;
279 bcopy(&ip->ip_src, &src6.sin6_addr.s6_addr[12],
280 sizeof(ip->ip_src));
281 src6.sin6_port = uh->uh_sport;
282 bzero(&dst6, sizeof(dst6));
283 dst6.sin6_family = AF_INET6;
284 dst6.sin6_len = sizeof(struct sockaddr_in6);
285 dst6.sin6_addr.s6_addr[10] = dst6.sin6_addr.s6_addr[11] = 0xff;
286 bcopy(&ip->ip_dst, &dst6.sin6_addr.s6_addr[12],
287 sizeof(ip->ip_dst));
288 dst6.sin6_port = uh->uh_dport;
289
290 n += udp6_realinput(AF_INET, &src6, &dst6, m, iphlen);
291 }
292 #endif
293
294 if (n == 0) {
295 if (m->m_flags & (M_BCAST | M_MCAST)) {
296 udpstat.udps_noportbcast++;
297 goto bad;
298 }
299 udpstat.udps_noport++;
300 #ifdef IPKDB
301 if (checkipkdb(&ip->ip_src, uh->uh_sport, uh->uh_dport,
302 m, iphlen + sizeof(struct udphdr),
303 m->m_pkthdr.len - iphlen - sizeof(struct udphdr))) {
304 /*
305 * It was a debugger connect packet,
306 * just drop it now
307 */
308 goto bad;
309 }
310 #endif
311 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
312 m = NULL;
313 }
314
315 bad:
316 if (m)
317 m_freem(m);
318 }
319
320 #ifdef INET6
321 int
322 udp6_input(mp, offp, proto)
323 struct mbuf **mp;
324 int *offp, proto;
325 {
326 struct mbuf *m = *mp;
327 int off = *offp;
328 struct sockaddr_in6 src, dst;
329 struct ip6_hdr *ip6;
330 struct udphdr *uh;
331 u_int32_t plen, ulen;
332
333 #ifndef PULLDOWN_TEST
334 IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE);
335 #endif
336 ip6 = mtod(m, struct ip6_hdr *);
337
338 #if defined(NFAITH) && 0 < NFAITH
339 if (faithprefix(&ip6->ip6_dst)) {
340 /* send icmp6 host unreach? */
341 m_freem(m);
342 return IPPROTO_DONE;
343 }
344 #endif
345
346 udp6stat.udp6s_ipackets++;
347
348 /* check for jumbogram is done in ip6_input. we can trust pkthdr.len */
349 plen = m->m_pkthdr.len - off;
350 #ifndef PULLDOWN_TEST
351 uh = (struct udphdr *)((caddr_t)ip6 + off);
352 #else
353 IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udphdr));
354 if (uh == NULL) {
355 ip6stat.ip6s_tooshort++;
356 return IPPROTO_DONE;
357 }
358 #endif
359 ulen = ntohs((u_short)uh->uh_ulen);
360 if (ulen == 0 && plen > 0xffff)
361 ulen = plen;
362
363 if (plen != ulen) {
364 udp6stat.udp6s_badlen++;
365 goto bad;
366 }
367
368 /* destination port of 0 is illegal, based on RFC768. */
369 if (uh->uh_dport == 0)
370 goto bad;
371
372 /* Be proactive about malicious use of IPv4 mapped address */
373 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
374 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
375 /* XXX stat */
376 goto bad;
377 }
378
379 /*
380 * Checksum extended UDP header and data.
381 */
382 if (uh->uh_sum == 0) {
383 udp6stat.udp6s_nosum++;
384 goto bad;
385 }
386 if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) {
387 udp6stat.udp6s_badsum++;
388 goto bad;
389 }
390
391 /*
392 * Construct source and dst sockaddrs.
393 * Note that ifindex (s6_addr16[1]) is already filled.
394 */
395 bzero(&src, sizeof(src));
396 src.sin6_family = AF_INET6;
397 src.sin6_len = sizeof(struct sockaddr_in6);
398 bcopy(&ip6->ip6_src, &src.sin6_addr, sizeof(src.sin6_addr));
399 if (IN6_IS_SCOPE_LINKLOCAL(&src.sin6_addr))
400 src.sin6_addr.s6_addr16[1] = 0;
401 if (m->m_pkthdr.rcvif) {
402 if (IN6_IS_SCOPE_LINKLOCAL(&src.sin6_addr))
403 src.sin6_scope_id = m->m_pkthdr.rcvif->if_index;
404 else
405 src.sin6_scope_id = 0;
406 }
407 src.sin6_port = uh->uh_sport;
408 bzero(&dst, sizeof(dst));
409 dst.sin6_family = AF_INET6;
410 dst.sin6_len = sizeof(struct sockaddr_in6);
411 bcopy(&ip6->ip6_dst, &dst.sin6_addr, sizeof(dst.sin6_addr));
412 if (IN6_IS_SCOPE_LINKLOCAL(&dst.sin6_addr))
413 dst.sin6_addr.s6_addr16[1] = 0;
414 if (m->m_pkthdr.rcvif) {
415 if (IN6_IS_SCOPE_LINKLOCAL(&dst.sin6_addr))
416 dst.sin6_scope_id = m->m_pkthdr.rcvif->if_index;
417 else
418 dst.sin6_scope_id = 0;
419 }
420 dst.sin6_port = uh->uh_dport;
421
422 if (udp6_realinput(AF_INET6, &src, &dst, m, off) == 0) {
423 if (m->m_flags & M_MCAST) {
424 udp6stat.udp6s_noportmcast++;
425 goto bad;
426 }
427 udp6stat.udp6s_noport++;
428 icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
429 m = NULL;
430 }
431
432 bad:
433 if (m)
434 m_freem(m);
435 return IPPROTO_DONE;
436 }
437 #endif
438
439 static void
440 udp4_sendup(m, off, src, so)
441 struct mbuf *m;
442 int off; /* offset of data portion */
443 struct sockaddr *src;
444 struct socket *so;
445 {
446 struct mbuf *opts = NULL;
447 struct mbuf *n;
448 struct inpcb *inp = NULL;
449 #ifdef INET6
450 struct in6pcb *in6p = NULL;
451 #endif
452
453 if (!so)
454 return;
455 switch (so->so_proto->pr_domain->dom_family) {
456 case AF_INET:
457 inp = sotoinpcb(so);
458 break;
459 #ifdef INET6
460 case AF_INET6:
461 in6p = sotoin6pcb(so);
462 break;
463 #endif
464 default:
465 return;
466 }
467
468 #ifdef IPSEC
469 /* check AH/ESP integrity. */
470 if (so != NULL && ipsec4_in_reject_so(m, so)) {
471 ipsecstat.in_polvio++;
472 return;
473 }
474 #endif /*IPSEC*/
475
476 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
477 if (inp && (inp->inp_flags & INP_CONTROLOPTS
478 || so->so_options & SO_TIMESTAMP)) {
479 struct ip *ip = mtod(n, struct ip *);
480 ip_savecontrol(inp, &opts, ip, n);
481 }
482
483 m_adj(n, off);
484 if (sbappendaddr(&so->so_rcv, src, n,
485 opts) == 0) {
486 m_freem(n);
487 if (opts)
488 m_freem(opts);
489 } else
490 sorwakeup(so);
491 }
492 }
493
494 #ifdef INET6
495 static void
496 udp6_sendup(m, off, src, so)
497 struct mbuf *m;
498 int off; /* offset of data portion */
499 struct sockaddr *src;
500 struct socket *so;
501 {
502 struct mbuf *opts = NULL;
503 struct mbuf *n;
504 struct in6pcb *in6p = NULL;
505
506 if (!so)
507 return;
508 if (so->so_proto->pr_domain->dom_family != AF_INET6)
509 return;
510 in6p = sotoin6pcb(so);
511
512 #ifdef IPSEC
513 /* check AH/ESP integrity. */
514 if (so != NULL && ipsec6_in_reject_so(m, so)) {
515 ipsec6stat.in_polvio++;
516 return;
517 }
518 #endif /*IPSEC*/
519
520 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
521 if (in6p && (in6p->in6p_flags & IN6P_CONTROLOPTS
522 || in6p->in6p_socket->so_options & SO_TIMESTAMP)) {
523 struct ip6_hdr *ip6 = mtod(n, struct ip6_hdr *);
524 ip6_savecontrol(in6p, &opts, ip6, n);
525 }
526
527 m_adj(n, off);
528 if (sbappendaddr(&so->so_rcv, src, n, opts) == 0) {
529 m_freem(n);
530 if (opts)
531 m_freem(opts);
532 udp6stat.udp6s_fullsock++;
533 } else
534 sorwakeup(so);
535 }
536 }
537 #endif
538
539 static int
540 udp4_realinput(src, dst, m, off)
541 struct sockaddr_in *src;
542 struct sockaddr_in *dst;
543 struct mbuf *m;
544 int off; /* offset of udphdr */
545 {
546 u_int16_t *sport, *dport;
547 int rcvcnt;
548 struct in_addr *src4, *dst4;
549 struct inpcb *inp;
550
551 rcvcnt = 0;
552 off += sizeof(struct udphdr); /* now, offset of payload */
553
554 if (src->sin_family != AF_INET || dst->sin_family != AF_INET)
555 goto bad;
556
557 src4 = &src->sin_addr;
558 sport = &src->sin_port;
559 dst4 = &dst->sin_addr;
560 dport = &dst->sin_port;
561
562 if (IN_MULTICAST(dst4->s_addr) ||
563 in_broadcast(*dst4, m->m_pkthdr.rcvif)) {
564 struct inpcb *last;
565 /*
566 * Deliver a multicast or broadcast datagram to *all* sockets
567 * for which the local and remote addresses and ports match
568 * those of the incoming datagram. This allows more than
569 * one process to receive multi/broadcasts on the same port.
570 * (This really ought to be done for unicast datagrams as
571 * well, but that would cause problems with existing
572 * applications that open both address-specific sockets and
573 * a wildcard socket listening to the same port -- they would
574 * end up receiving duplicates of every unicast datagram.
575 * Those applications open the multiple sockets to overcome an
576 * inadequacy of the UDP socket interface, but for backwards
577 * compatibility we avoid the problem here rather than
578 * fixing the interface. Maybe 4.5BSD will remedy this?)
579 */
580
581 /*
582 * KAME note: usually we drop udpiphdr from mbuf here.
583 * we need udpiphdr for iPsec processing so we do that later.
584 */
585 /*
586 * Locate pcb(s) for datagram.
587 */
588 for (inp = udbtable.inpt_queue.cqh_first;
589 inp != (struct inpcb *)&udbtable.inpt_queue;
590 inp = inp->inp_queue.cqe_next) {
591 if (inp->inp_lport != *dport)
592 continue;
593 if (!in_nullhost(inp->inp_laddr)) {
594 if (!in_hosteq(inp->inp_laddr, *dst4))
595 continue;
596 }
597 if (!in_nullhost(inp->inp_faddr)) {
598 if (!in_hosteq(inp->inp_faddr, *src4) ||
599 inp->inp_fport != *sport)
600 continue;
601 }
602
603 last = inp;
604 udp4_sendup(m, off, (struct sockaddr *)src,
605 inp->inp_socket);
606 rcvcnt++;
607
608 /*
609 * Don't look for additional matches if this one does
610 * not have either the SO_REUSEPORT or SO_REUSEADDR
611 * socket options set. This heuristic avoids searching
612 * through all pcbs in the common case of a non-shared
613 * port. It assumes that an application will never
614 * clear these options after setting them.
615 */
616 if ((inp->inp_socket->so_options &
617 (SO_REUSEPORT|SO_REUSEADDR)) == 0)
618 break;
619 }
620
621 #if 0
622 if (last == NULL) {
623 /*
624 * No matching pcb found; discard datagram.
625 * (No need to send an ICMP Port Unreachable
626 * for a broadcast or multicast datgram.)
627 */
628 udpstat.udps_noportbcast++;
629 goto bad;
630 }
631 #endif
632 } else {
633 /*
634 * Locate pcb for datagram.
635 */
636 inp = in_pcblookup_connect(&udbtable, *src4, *sport, *dst4, *dport);
637 if (inp == 0) {
638 ++udpstat.udps_pcbhashmiss;
639 inp = in_pcblookup_bind(&udbtable, *dst4, *dport);
640 if (inp == 0) {
641 #if 0
642 struct mbuf *n;
643
644 if (m->m_flags & (M_BCAST | M_MCAST)) {
645 udpstat.udps_noportbcast++;
646 goto bad;
647 }
648 udpstat.udps_noport++;
649 #ifdef IPKDB
650 if (checkipkdb(src4, *sport, *dport, m, off,
651 m->m_pkthdr.len - off)) {
652 /*
653 * It was a debugger connect packet,
654 * just drop it now
655 */
656 goto bad;
657 }
658 #endif
659 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
660 icmp_error(n, ICMP_UNREACH,
661 ICMP_UNREACH_PORT, 0, 0);
662 }
663 #endif
664 return rcvcnt;
665 }
666 }
667
668 udp4_sendup(m, off, (struct sockaddr *)src, inp->inp_socket);
669 rcvcnt++;
670 }
671
672 bad:
673 return rcvcnt;
674 }
675
676 #ifdef INET6
677 static int
678 in6_mcmatch(in6p, ia6, ifp)
679 struct in6pcb *in6p;
680 struct in6_addr *ia6;
681 struct ifnet *ifp;
682 {
683 struct ip6_moptions *im6o = in6p->in6p_moptions;
684 struct in6_multi_mship *imm;
685
686 if (im6o == NULL)
687 return 0;
688
689 for (imm = im6o->im6o_memberships.lh_first; imm != NULL;
690 imm = imm->i6mm_chain.le_next) {
691 if ((ifp == NULL ||
692 imm->i6mm_maddr->in6m_ifp == ifp) &&
693 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
694 ia6))
695 return 1;
696 }
697 return 0;
698 }
699
700 static int
701 udp6_realinput(af, src, dst, m, off)
702 int af; /* af on packet */
703 struct sockaddr_in6 *src;
704 struct sockaddr_in6 *dst;
705 struct mbuf *m;
706 int off; /* offset of udphdr */
707 {
708 u_int16_t *sport, *dport;
709 int rcvcnt;
710 struct in6_addr *src6, *dst6;
711 struct in_addr *dst4;
712 struct in6pcb *in6p;
713
714 rcvcnt = 0;
715 off += sizeof(struct udphdr); /* now, offset of payload */
716
717 if (af != AF_INET && af != AF_INET6)
718 goto bad;
719 if (src->sin6_family != AF_INET6 || dst->sin6_family != AF_INET6)
720 goto bad;
721
722 src6 = &src->sin6_addr;
723 sport = &src->sin6_port;
724 dst6 = &dst->sin6_addr;
725 dport = &dst->sin6_port;
726 dst4 = (struct in_addr *)&dst->sin6_addr.s6_addr32[12];
727
728 if (IN6_IS_ADDR_MULTICAST(dst6)
729 || (af == AF_INET && IN_MULTICAST(dst4->s_addr))) {
730 struct in6pcb *last;
731 /*
732 * Deliver a multicast or broadcast datagram to *all* sockets
733 * for which the local and remote addresses and ports match
734 * those of the incoming datagram. This allows more than
735 * one process to receive multi/broadcasts on the same port.
736 * (This really ought to be done for unicast datagrams as
737 * well, but that would cause problems with existing
738 * applications that open both address-specific sockets and
739 * a wildcard socket listening to the same port -- they would
740 * end up receiving duplicates of every unicast datagram.
741 * Those applications open the multiple sockets to overcome an
742 * inadequacy of the UDP socket interface, but for backwards
743 * compatibility we avoid the problem here rather than
744 * fixing the interface. Maybe 4.5BSD will remedy this?)
745 */
746
747 /*
748 * KAME note: usually we drop udpiphdr from mbuf here.
749 * we need udpiphdr for iPsec processing so we do that later.
750 */
751 /*
752 * Locate pcb(s) for datagram.
753 */
754 for (in6p = udb6.in6p_next; in6p != &udb6;
755 in6p = in6p->in6p_next) {
756 if (in6p->in6p_lport != *dport)
757 continue;
758 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
759 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, dst6)
760 && !in6_mcmatch(in6p, dst6, m->m_pkthdr.rcvif))
761 continue;
762 }
763 #ifndef INET6_BINDV6ONLY
764 else {
765 if (IN6_IS_ADDR_V4MAPPED(dst6)
766 && (in6p->in6p_flags & IN6P_BINDV6ONLY))
767 continue;
768 }
769 #endif
770 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
771 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, src6)
772 || in6p->in6p_fport != *sport)
773 continue;
774 }
775 #ifndef INET6_BINDV6ONLY
776 else {
777 if (IN6_IS_ADDR_V4MAPPED(src6)
778 && (in6p->in6p_flags & IN6P_BINDV6ONLY))
779 continue;
780 }
781 #endif
782
783 last = in6p;
784 udp6_sendup(m, off, (struct sockaddr *)src,
785 in6p->in6p_socket);
786 rcvcnt++;
787
788 /*
789 * Don't look for additional matches if this one does
790 * not have either the SO_REUSEPORT or SO_REUSEADDR
791 * socket options set. This heuristic avoids searching
792 * through all pcbs in the common case of a non-shared
793 * port. It assumes that an application will never
794 * clear these options after setting them.
795 */
796 if ((in6p->in6p_socket->so_options &
797 (SO_REUSEPORT|SO_REUSEADDR)) == 0)
798 break;
799 }
800
801 #if 0
802 if (last == NULL) {
803 /*
804 * No matching pcb found; discard datagram.
805 * (No need to send an ICMP Port Unreachable
806 * for a broadcast or multicast datgram.)
807 */
808 switch (af) {
809 case AF_INET:
810 udpstat.udps_noportbcast++;
811 break;
812 case AF_INET6:
813 udp6stat.udp6s_noportmcast++;
814 break;
815 }
816 goto bad;
817 }
818 #endif
819 } else {
820 /*
821 * Locate pcb for datagram.
822 */
823 in6p = in6_pcblookup_connect(&udb6, src6, *sport,
824 dst6, *dport, 0);
825 if (in6p == 0) {
826 ++udpstat.udps_pcbhashmiss;
827 in6p = in6_pcblookup_bind(&udb6, dst6, *dport, 0);
828 if (in6p == 0) {
829 #if 0
830 struct mbuf *n;
831 n = m_copy(m, 0, M_COPYALL);
832 switch (af) {
833 case AF_INET:
834 if (m->m_flags & (M_BCAST | M_MCAST)) {
835 udpstat.udps_noportbcast++;
836 goto bad;
837 }
838 udpstat.udps_noport++;
839 if (n != NULL)
840 icmp_error(n, ICMP_UNREACH,
841 ICMP_UNREACH_PORT, 0, 0);
842 break;
843 case AF_INET6:
844 if (m->m_flags & M_MCAST) {
845 udp6stat.udp6s_noportmcast++;
846 goto bad;
847 }
848 udp6stat.udp6s_noport++;
849 if (n != NULL)
850 icmp6_error(n, ICMP6_DST_UNREACH,
851 ICMP6_DST_UNREACH_NOPORT, 0);
852 break;
853 }
854 #endif
855
856 return rcvcnt;
857 }
858 }
859
860 udp6_sendup(m, off, (struct sockaddr *)src, in6p->in6p_socket);
861 rcvcnt++;
862 }
863
864 bad:
865 return rcvcnt;
866 }
867 #endif
868
869 #else /*UDP6*/
870
871 void
872 #if __STDC__
873 udp_input(struct mbuf *m, ...)
874 #else
875 udp_input(m, va_alist)
876 struct mbuf *m;
877 va_dcl
878 #endif
879 {
880 int proto;
881 struct ip *ip;
882 struct udphdr *uh;
883 struct inpcb *inp;
884 struct mbuf *opts = 0;
885 int len;
886 struct ip save_ip;
887 int iphlen;
888 va_list ap;
889 struct sockaddr_in udpsrc;
890 struct sockaddr *sa;
891
892 va_start(ap, m);
893 iphlen = va_arg(ap, int);
894 proto = va_arg(ap, int);
895 va_end(ap);
896
897 udpstat.udps_ipackets++;
898
899 /*
900 * Strip IP options, if any; should skip this,
901 * make available to user, and use on returned packets,
902 * but we don't yet have a way to check the checksum
903 * with options still present.
904 */
905 if (iphlen > sizeof (struct ip)) {
906 ip_stripoptions(m, (struct mbuf *)0);
907 iphlen = sizeof(struct ip);
908 }
909
910 /*
911 * Get IP and UDP header together in first mbuf.
912 */
913 ip = mtod(m, struct ip *);
914 if (m->m_len < iphlen + sizeof(struct udphdr)) {
915 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
916 udpstat.udps_hdrops++;
917 return;
918 }
919 ip = mtod(m, struct ip *);
920 }
921 uh = (struct udphdr *)((caddr_t)ip + iphlen);
922
923 /* destination port of 0 is illegal, based on RFC768. */
924 if (uh->uh_dport == 0)
925 goto bad;
926
927 /*
928 * Make mbuf data length reflect UDP length.
929 * If not enough data to reflect UDP length, drop.
930 */
931 len = ntohs((u_int16_t)uh->uh_ulen);
932 if (ip->ip_len != iphlen + len) {
933 if (ip->ip_len < iphlen + len || len < sizeof(struct udphdr)) {
934 udpstat.udps_badlen++;
935 goto bad;
936 }
937 m_adj(m, iphlen + len - ip->ip_len);
938 }
939 /*
940 * Save a copy of the IP header in case we want restore it
941 * for sending an ICMP error message in response.
942 */
943 save_ip = *ip;
944
945 /*
946 * Checksum extended UDP header and data.
947 */
948 if (uh->uh_sum) {
949 bzero(((struct ipovly *)ip)->ih_x1,
950 sizeof ((struct ipovly *)ip)->ih_x1);
951 ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
952 if (in_cksum(m, len + sizeof (struct ip)) != 0) {
953 udpstat.udps_badsum++;
954 m_freem(m);
955 return;
956 }
957 }
958
959 /*
960 * Construct sockaddr format source address.
961 */
962 udpsrc.sin_family = AF_INET;
963 udpsrc.sin_len = sizeof(struct sockaddr_in);
964 udpsrc.sin_addr = ip->ip_src;
965 udpsrc.sin_port = uh->uh_sport;
966 bzero((caddr_t)udpsrc.sin_zero, sizeof(udpsrc.sin_zero));
967
968 if (IN_MULTICAST(ip->ip_dst.s_addr) ||
969 in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
970 struct inpcb *last;
971 /*
972 * Deliver a multicast or broadcast datagram to *all* sockets
973 * for which the local and remote addresses and ports match
974 * those of the incoming datagram. This allows more than
975 * one process to receive multi/broadcasts on the same port.
976 * (This really ought to be done for unicast datagrams as
977 * well, but that would cause problems with existing
978 * applications that open both address-specific sockets and
979 * a wildcard socket listening to the same port -- they would
980 * end up receiving duplicates of every unicast datagram.
981 * Those applications open the multiple sockets to overcome an
982 * inadequacy of the UDP socket interface, but for backwards
983 * compatibility we avoid the problem here rather than
984 * fixing the interface. Maybe 4.5BSD will remedy this?)
985 */
986
987 iphlen += sizeof(struct udphdr);
988 /*
989 * KAME note: usually we drop udpiphdr from mbuf here.
990 * we need udpiphdr for iPsec processing so we do that later.
991 */
992 /*
993 * Locate pcb(s) for datagram.
994 * (Algorithm copied from raw_intr().)
995 */
996 last = NULL;
997 for (inp = udbtable.inpt_queue.cqh_first;
998 inp != (struct inpcb *)&udbtable.inpt_queue;
999 inp = inp->inp_queue.cqe_next) {
1000 if (inp->inp_lport != uh->uh_dport)
1001 continue;
1002 if (!in_nullhost(inp->inp_laddr)) {
1003 if (!in_hosteq(inp->inp_laddr, ip->ip_dst))
1004 continue;
1005 }
1006 if (!in_nullhost(inp->inp_faddr)) {
1007 if (!in_hosteq(inp->inp_faddr, ip->ip_src) ||
1008 inp->inp_fport != uh->uh_sport)
1009 continue;
1010 }
1011
1012 if (last != NULL) {
1013 struct mbuf *n;
1014
1015 #ifdef IPSEC
1016 /* check AH/ESP integrity. */
1017 if (last != NULL && ipsec4_in_reject(m, last)) {
1018 ipsecstat.in_polvio++;
1019 /* do not inject data to pcb */
1020 } else
1021 #endif /*IPSEC*/
1022 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
1023 if (last->inp_flags & INP_CONTROLOPTS
1024 || last->inp_socket->so_options &
1025 SO_TIMESTAMP) {
1026 ip_savecontrol(last, &opts,
1027 ip, n);
1028 }
1029 m_adj(n, iphlen);
1030 sa = (struct sockaddr *)&udpsrc;
1031 if (sbappendaddr(
1032 &last->inp_socket->so_rcv,
1033 sa, n, opts) == 0) {
1034 m_freem(n);
1035 if (opts)
1036 m_freem(opts);
1037 } else
1038 sorwakeup(last->inp_socket);
1039 opts = 0;
1040 }
1041 }
1042 last = inp;
1043 /*
1044 * Don't look for additional matches if this one does
1045 * not have either the SO_REUSEPORT or SO_REUSEADDR
1046 * socket options set. This heuristic avoids searching
1047 * through all pcbs in the common case of a non-shared
1048 * port. It * assumes that an application will never
1049 * clear these options after setting them.
1050 */
1051 if ((last->inp_socket->so_options &
1052 (SO_REUSEPORT|SO_REUSEADDR)) == 0)
1053 break;
1054 }
1055
1056 if (last == NULL) {
1057 /*
1058 * No matching pcb found; discard datagram.
1059 * (No need to send an ICMP Port Unreachable
1060 * for a broadcast or multicast datgram.)
1061 */
1062 udpstat.udps_noportbcast++;
1063 goto bad;
1064 }
1065 #ifdef IPSEC
1066 /* check AH/ESP integrity. */
1067 if (last != NULL && ipsec4_in_reject(m, last)) {
1068 ipsecstat.in_polvio++;
1069 goto bad;
1070 }
1071 #endif /*IPSEC*/
1072 if (last->inp_flags & INP_CONTROLOPTS ||
1073 last->inp_socket->so_options & SO_TIMESTAMP)
1074 ip_savecontrol(last, &opts, ip, m);
1075 m->m_len -= iphlen;
1076 m->m_pkthdr.len -= iphlen;
1077 m->m_data += iphlen;
1078 sa = (struct sockaddr *)&udpsrc;
1079 if (sbappendaddr(&last->inp_socket->so_rcv, sa, m, opts) == 0) {
1080 udpstat.udps_fullsock++;
1081 goto bad;
1082 }
1083 sorwakeup(last->inp_socket);
1084 return;
1085 }
1086 /*
1087 * Locate pcb for datagram.
1088 */
1089 inp = in_pcblookup_connect(&udbtable, ip->ip_src, uh->uh_sport,
1090 ip->ip_dst, uh->uh_dport);
1091 if (inp == 0) {
1092 ++udpstat.udps_pcbhashmiss;
1093 inp = in_pcblookup_bind(&udbtable, ip->ip_dst, uh->uh_dport);
1094 if (inp == 0) {
1095 if (m->m_flags & (M_BCAST | M_MCAST)) {
1096 udpstat.udps_noportbcast++;
1097 goto bad;
1098 }
1099 udpstat.udps_noport++;
1100 *ip = save_ip;
1101 #ifdef IPKDB
1102 if (checkipkdb(&ip->ip_src,
1103 uh->uh_sport,
1104 uh->uh_dport,
1105 m,
1106 iphlen + sizeof(struct udphdr),
1107 len - sizeof(struct udphdr)))
1108 /* It was a debugger connect packet, just drop it now */
1109 goto bad;
1110 #endif
1111 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
1112 return;
1113 }
1114 }
1115 #ifdef IPSEC
1116 if (inp != NULL && ipsec4_in_reject(m, inp)) {
1117 ipsecstat.in_polvio++;
1118 goto bad;
1119 }
1120 #endif /*IPSEC*/
1121
1122 /*
1123 * Stuff source address and datagram in user buffer.
1124 */
1125 if (inp->inp_flags & INP_CONTROLOPTS ||
1126 inp->inp_socket->so_options & SO_TIMESTAMP)
1127 ip_savecontrol(inp, &opts, ip, m);
1128 iphlen += sizeof(struct udphdr);
1129 m->m_len -= iphlen;
1130 m->m_pkthdr.len -= iphlen;
1131 m->m_data += iphlen;
1132 sa = (struct sockaddr *)&udpsrc;
1133 if (sbappendaddr(&inp->inp_socket->so_rcv, sa, m, opts) == 0) {
1134 udpstat.udps_fullsock++;
1135 goto bad;
1136 }
1137 sorwakeup(inp->inp_socket);
1138 return;
1139 bad:
1140 m_freem(m);
1141 if (opts)
1142 m_freem(opts);
1143 }
1144 #endif /*UDP6*/
1145
1146 /*
1147 * Notify a udp user of an asynchronous error;
1148 * just wake up so that he can collect error status.
1149 */
1150 static void
1151 udp_notify(inp, errno)
1152 struct inpcb *inp;
1153 int errno;
1154 {
1155
1156 inp->inp_socket->so_error = errno;
1157 sorwakeup(inp->inp_socket);
1158 sowwakeup(inp->inp_socket);
1159 }
1160
1161 void *
1162 udp_ctlinput(cmd, sa, v)
1163 int cmd;
1164 struct sockaddr *sa;
1165 void *v;
1166 {
1167 struct ip *ip = v;
1168 struct udphdr *uh;
1169 void (*notify) __P((struct inpcb *, int)) = udp_notify;
1170 int errno;
1171
1172 if (sa->sa_family != AF_INET
1173 || sa->sa_len != sizeof(struct sockaddr_in))
1174 return NULL;
1175 if ((unsigned)cmd >= PRC_NCMDS)
1176 return NULL;
1177 errno = inetctlerrmap[cmd];
1178 if (PRC_IS_REDIRECT(cmd))
1179 notify = in_rtchange, ip = 0;
1180 else if (cmd == PRC_HOSTDEAD)
1181 ip = 0;
1182 else if (errno == 0)
1183 return NULL;
1184 if (ip) {
1185 uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
1186 in_pcbnotify(&udbtable, satosin(sa)->sin_addr, uh->uh_dport,
1187 ip->ip_src, uh->uh_sport, errno, notify);
1188
1189 /* XXX mapped address case */
1190 } else
1191 in_pcbnotifyall(&udbtable, satosin(sa)->sin_addr, errno,
1192 notify);
1193 return NULL;
1194 }
1195
1196 int
1197 #if __STDC__
1198 udp_output(struct mbuf *m, ...)
1199 #else
1200 udp_output(m, va_alist)
1201 struct mbuf *m;
1202 va_dcl
1203 #endif
1204 {
1205 struct inpcb *inp;
1206 struct udpiphdr *ui;
1207 int len = m->m_pkthdr.len;
1208 int error = 0;
1209 va_list ap;
1210
1211 va_start(ap, m);
1212 inp = va_arg(ap, struct inpcb *);
1213 va_end(ap);
1214
1215 /*
1216 * Calculate data length and get a mbuf
1217 * for UDP and IP headers.
1218 */
1219 M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
1220 if (m == 0) {
1221 error = ENOBUFS;
1222 goto release;
1223 }
1224
1225 /*
1226 * Compute the packet length of the IP header, and
1227 * punt if the length looks bogus.
1228 */
1229 if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) {
1230 error = EMSGSIZE;
1231 goto release;
1232 }
1233
1234 /*
1235 * Fill in mbuf with extended UDP header
1236 * and addresses and length put into network format.
1237 */
1238 ui = mtod(m, struct udpiphdr *);
1239 bzero(ui->ui_x1, sizeof ui->ui_x1);
1240 ui->ui_pr = IPPROTO_UDP;
1241 ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr));
1242 ui->ui_src = inp->inp_laddr;
1243 ui->ui_dst = inp->inp_faddr;
1244 ui->ui_sport = inp->inp_lport;
1245 ui->ui_dport = inp->inp_fport;
1246 ui->ui_ulen = ui->ui_len;
1247
1248 /*
1249 * Stuff checksum and output datagram.
1250 */
1251 ui->ui_sum = 0;
1252 if (udpcksum) {
1253 if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
1254 ui->ui_sum = 0xffff;
1255 }
1256 ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
1257 ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */
1258 ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */
1259 udpstat.udps_opackets++;
1260
1261 #ifdef IPSEC
1262 if (ipsec_setsocket(m, inp->inp_socket) != 0) {
1263 error = ENOBUFS;
1264 goto release;
1265 }
1266 #endif /*IPSEC*/
1267
1268 return (ip_output(m, inp->inp_options, &inp->inp_route,
1269 inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
1270 inp->inp_moptions));
1271
1272 release:
1273 m_freem(m);
1274 return (error);
1275 }
1276
1277 int udp_sendspace = 9216; /* really max datagram size */
1278 int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
1279 /* 40 1K datagrams */
1280
1281 /*ARGSUSED*/
1282 int
1283 udp_usrreq(so, req, m, nam, control, p)
1284 struct socket *so;
1285 int req;
1286 struct mbuf *m, *nam, *control;
1287 struct proc *p;
1288 {
1289 struct inpcb *inp;
1290 int s;
1291 int error = 0;
1292
1293 if (req == PRU_CONTROL)
1294 return (in_control(so, (long)m, (caddr_t)nam,
1295 (struct ifnet *)control, p));
1296
1297 if (req == PRU_PURGEIF) {
1298 in_purgeif((struct ifnet *)control);
1299 in_pcbpurgeif(&udbtable, (struct ifnet *)control);
1300 return (0);
1301 }
1302
1303 s = splsoftnet();
1304 inp = sotoinpcb(so);
1305 #ifdef DIAGNOSTIC
1306 if (req != PRU_SEND && req != PRU_SENDOOB && control)
1307 panic("udp_usrreq: unexpected control mbuf");
1308 #endif
1309 if (inp == 0 && req != PRU_ATTACH) {
1310 error = EINVAL;
1311 goto release;
1312 }
1313
1314 /*
1315 * Note: need to block udp_input while changing
1316 * the udp pcb queue and/or pcb addresses.
1317 */
1318 switch (req) {
1319
1320 case PRU_ATTACH:
1321 if (inp != 0) {
1322 error = EISCONN;
1323 break;
1324 }
1325 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
1326 error = soreserve(so, udp_sendspace, udp_recvspace);
1327 if (error)
1328 break;
1329 }
1330 error = in_pcballoc(so, &udbtable);
1331 if (error)
1332 break;
1333 inp = sotoinpcb(so);
1334 inp->inp_ip.ip_ttl = ip_defttl;
1335 #ifdef IPSEC
1336 error = ipsec_init_policy(so, &inp->inp_sp);
1337 if (error != 0) {
1338 in_pcbdetach(inp);
1339 break;
1340 }
1341 #endif /*IPSEC*/
1342 break;
1343
1344 case PRU_DETACH:
1345 in_pcbdetach(inp);
1346 break;
1347
1348 case PRU_BIND:
1349 error = in_pcbbind(inp, nam, p);
1350 break;
1351
1352 case PRU_LISTEN:
1353 error = EOPNOTSUPP;
1354 break;
1355
1356 case PRU_CONNECT:
1357 error = in_pcbconnect(inp, nam);
1358 if (error)
1359 break;
1360 soisconnected(so);
1361 break;
1362
1363 case PRU_CONNECT2:
1364 error = EOPNOTSUPP;
1365 break;
1366
1367 case PRU_DISCONNECT:
1368 /*soisdisconnected(so);*/
1369 so->so_state &= ~SS_ISCONNECTED; /* XXX */
1370 in_pcbdisconnect(inp);
1371 inp->inp_laddr = zeroin_addr; /* XXX */
1372 in_pcbstate(inp, INP_BOUND); /* XXX */
1373 break;
1374
1375 case PRU_SHUTDOWN:
1376 socantsendmore(so);
1377 break;
1378
1379 case PRU_RCVD:
1380 error = EOPNOTSUPP;
1381 break;
1382
1383 case PRU_SEND:
1384 if (control && control->m_len) {
1385 m_freem(control);
1386 m_freem(m);
1387 error = EINVAL;
1388 break;
1389 }
1390 {
1391 struct in_addr laddr; /* XXX */
1392
1393 if (nam) {
1394 laddr = inp->inp_laddr; /* XXX */
1395 if ((so->so_state & SS_ISCONNECTED) != 0) {
1396 error = EISCONN;
1397 goto die;
1398 }
1399 error = in_pcbconnect(inp, nam);
1400 if (error) {
1401 die:
1402 m_freem(m);
1403 break;
1404 }
1405 } else {
1406 if ((so->so_state & SS_ISCONNECTED) == 0) {
1407 error = ENOTCONN;
1408 goto die;
1409 }
1410 }
1411 error = udp_output(m, inp);
1412 if (nam) {
1413 in_pcbdisconnect(inp);
1414 inp->inp_laddr = laddr; /* XXX */
1415 in_pcbstate(inp, INP_BOUND); /* XXX */
1416 }
1417 }
1418 break;
1419
1420 case PRU_SENSE:
1421 /*
1422 * stat: don't bother with a blocksize.
1423 */
1424 splx(s);
1425 return (0);
1426
1427 case PRU_RCVOOB:
1428 error = EOPNOTSUPP;
1429 break;
1430
1431 case PRU_SENDOOB:
1432 m_freem(control);
1433 m_freem(m);
1434 error = EOPNOTSUPP;
1435 break;
1436
1437 case PRU_SOCKADDR:
1438 in_setsockaddr(inp, nam);
1439 break;
1440
1441 case PRU_PEERADDR:
1442 in_setpeeraddr(inp, nam);
1443 break;
1444
1445 default:
1446 panic("udp_usrreq");
1447 }
1448
1449 release:
1450 splx(s);
1451 return (error);
1452 }
1453
1454 /*
1455 * Sysctl for udp variables.
1456 */
1457 int
1458 udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
1459 int *name;
1460 u_int namelen;
1461 void *oldp;
1462 size_t *oldlenp;
1463 void *newp;
1464 size_t newlen;
1465 {
1466 /* All sysctl names at this level are terminal. */
1467 if (namelen != 1)
1468 return (ENOTDIR);
1469
1470 switch (name[0]) {
1471 case UDPCTL_CHECKSUM:
1472 return (sysctl_int(oldp, oldlenp, newp, newlen, &udpcksum));
1473 case UDPCTL_SENDSPACE:
1474 return (sysctl_int(oldp, oldlenp, newp, newlen,
1475 &udp_sendspace));
1476 case UDPCTL_RECVSPACE:
1477 return (sysctl_int(oldp, oldlenp, newp, newlen,
1478 &udp_recvspace));
1479 default:
1480 return (ENOPROTOOPT);
1481 }
1482 /* NOTREACHED */
1483 }
1484