udp_usrreq.c revision 1.76 1 /* $NetBSD: udp_usrreq.c,v 1.76 2001/05/08 10:15:14 itojun 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 <uvm/uvm_extern.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 #endif /*IPSEC*/
124
125 #ifdef IPKDB
126 #include <ipkdb/ipkdb.h>
127 #endif
128
129 /*
130 * UDP protocol implementation.
131 * Per RFC 768, August, 1980.
132 */
133 #ifndef COMPAT_42
134 int udpcksum = 1;
135 #else
136 int udpcksum = 0; /* XXX */
137 #endif
138
139 #ifdef INET
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 #endif
145 #ifdef INET6
146 static void udp6_sendup __P((struct mbuf *, int, struct sockaddr *,
147 struct socket *));
148 static int in6_mcmatch __P((struct in6pcb *, struct in6_addr *,
149 struct ifnet *));
150 static int udp6_realinput __P((int, struct sockaddr_in6 *,
151 struct sockaddr_in6 *, struct mbuf *, int));
152 #endif
153 #ifdef INET
154 static void udp_notify __P((struct inpcb *, int));
155 #endif
156
157 #ifndef UDBHASHSIZE
158 #define UDBHASHSIZE 128
159 #endif
160 int udbhashsize = UDBHASHSIZE;
161
162 void
163 udp_init()
164 {
165
166 #ifdef INET
167 in_pcbinit(&udbtable, udbhashsize, udbhashsize);
168 #endif
169 }
170
171 #ifndef UDP6
172 #ifdef INET
173 void
174 #if __STDC__
175 udp_input(struct mbuf *m, ...)
176 #else
177 udp_input(m, va_alist)
178 struct mbuf *m;
179 va_dcl
180 #endif
181 {
182 va_list ap;
183 struct sockaddr_in src, dst;
184 struct ip *ip;
185 struct udphdr *uh;
186 int iphlen, proto;
187 int len;
188 int n;
189
190 va_start(ap, m);
191 iphlen = va_arg(ap, int);
192 proto = va_arg(ap, int);
193 va_end(ap);
194
195 udpstat.udps_ipackets++;
196
197 #ifndef PULLDOWN_TEST
198 /*
199 * Strip IP options, if any; should skip this,
200 * make available to user, and use on returned packets,
201 * but we don't yet have a way to check the checksum
202 * with options still present.
203 */
204 if (iphlen > sizeof (struct ip)) {
205 ip_stripoptions(m, (struct mbuf *)0);
206 iphlen = sizeof(struct ip);
207 }
208 #else
209 /*
210 * we may enable the above code if we save and pass IPv4 options
211 * to the userland.
212 */
213 #endif
214
215 /*
216 * Get IP and UDP header together in first mbuf.
217 */
218 ip = mtod(m, struct ip *);
219 #ifndef PULLDOWN_TEST
220 if (m->m_len < iphlen + sizeof(struct udphdr)) {
221 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
222 udpstat.udps_hdrops++;
223 return;
224 }
225 ip = mtod(m, struct ip *);
226 }
227 uh = (struct udphdr *)((caddr_t)ip + iphlen);
228 #else
229 IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
230 if (uh == NULL) {
231 udpstat.udps_hdrops++;
232 return;
233 }
234 #endif
235
236 /* destination port of 0 is illegal, based on RFC768. */
237 if (uh->uh_dport == 0)
238 goto bad;
239
240 /*
241 * Make mbuf data length reflect UDP length.
242 * If not enough data to reflect UDP length, drop.
243 */
244 len = ntohs((u_int16_t)uh->uh_ulen);
245 if (ip->ip_len != iphlen + len) {
246 if (ip->ip_len < iphlen + len || len < sizeof(struct udphdr)) {
247 udpstat.udps_badlen++;
248 goto bad;
249 }
250 m_adj(m, iphlen + len - ip->ip_len);
251 }
252
253 /*
254 * Checksum extended UDP header and data.
255 */
256 if (uh->uh_sum) {
257 if (in4_cksum(m, IPPROTO_UDP, iphlen, len) != 0) {
258 udpstat.udps_badsum++;
259 m_freem(m);
260 return;
261 }
262 }
263
264 /* construct source and dst sockaddrs. */
265 bzero(&src, sizeof(src));
266 src.sin_family = AF_INET;
267 src.sin_len = sizeof(struct sockaddr_in);
268 bcopy(&ip->ip_src, &src.sin_addr, sizeof(src.sin_addr));
269 src.sin_port = uh->uh_sport;
270 bzero(&dst, sizeof(dst));
271 dst.sin_family = AF_INET;
272 dst.sin_len = sizeof(struct sockaddr_in);
273 bcopy(&ip->ip_dst, &dst.sin_addr, sizeof(dst.sin_addr));
274 dst.sin_port = uh->uh_dport;
275
276 n = udp4_realinput(&src, &dst, m, iphlen);
277 #ifdef INET6
278 if (IN_MULTICAST(ip->ip_dst.s_addr) || n == 0) {
279 struct sockaddr_in6 src6, dst6;
280
281 bzero(&src6, sizeof(src6));
282 src6.sin6_family = AF_INET6;
283 src6.sin6_len = sizeof(struct sockaddr_in6);
284 src6.sin6_addr.s6_addr[10] = src6.sin6_addr.s6_addr[11] = 0xff;
285 bcopy(&ip->ip_src, &src6.sin6_addr.s6_addr[12],
286 sizeof(ip->ip_src));
287 src6.sin6_port = uh->uh_sport;
288 bzero(&dst6, sizeof(dst6));
289 dst6.sin6_family = AF_INET6;
290 dst6.sin6_len = sizeof(struct sockaddr_in6);
291 dst6.sin6_addr.s6_addr[10] = dst6.sin6_addr.s6_addr[11] = 0xff;
292 bcopy(&ip->ip_dst, &dst6.sin6_addr.s6_addr[12],
293 sizeof(ip->ip_dst));
294 dst6.sin6_port = uh->uh_dport;
295
296 n += udp6_realinput(AF_INET, &src6, &dst6, m, iphlen);
297 }
298 #endif
299
300 if (n == 0) {
301 if (m->m_flags & (M_BCAST | M_MCAST)) {
302 udpstat.udps_noportbcast++;
303 goto bad;
304 }
305 udpstat.udps_noport++;
306 #ifdef IPKDB
307 if (checkipkdb(&ip->ip_src, uh->uh_sport, uh->uh_dport,
308 m, iphlen + sizeof(struct udphdr),
309 m->m_pkthdr.len - iphlen - sizeof(struct udphdr))) {
310 /*
311 * It was a debugger connect packet,
312 * just drop it now
313 */
314 goto bad;
315 }
316 #endif
317 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
318 m = NULL;
319 }
320
321 bad:
322 if (m)
323 m_freem(m);
324 }
325 #endif
326
327 #ifdef INET6
328 int
329 udp6_input(mp, offp, proto)
330 struct mbuf **mp;
331 int *offp, proto;
332 {
333 struct mbuf *m = *mp;
334 int off = *offp;
335 struct sockaddr_in6 src, dst;
336 struct ip6_hdr *ip6;
337 struct udphdr *uh;
338 u_int32_t plen, ulen;
339
340 #ifndef PULLDOWN_TEST
341 IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE);
342 #endif
343 ip6 = mtod(m, struct ip6_hdr *);
344
345 #if defined(NFAITH) && 0 < NFAITH
346 if (faithprefix(&ip6->ip6_dst)) {
347 /* send icmp6 host unreach? */
348 m_freem(m);
349 return IPPROTO_DONE;
350 }
351 #endif
352
353 udp6stat.udp6s_ipackets++;
354
355 /* check for jumbogram is done in ip6_input. we can trust pkthdr.len */
356 plen = m->m_pkthdr.len - off;
357 #ifndef PULLDOWN_TEST
358 uh = (struct udphdr *)((caddr_t)ip6 + off);
359 #else
360 IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udphdr));
361 if (uh == NULL) {
362 ip6stat.ip6s_tooshort++;
363 return IPPROTO_DONE;
364 }
365 #endif
366 ulen = ntohs((u_short)uh->uh_ulen);
367 /*
368 * RFC2675 section 4: jumbograms will have 0 in the UDP header field,
369 * iff payload length > 0xffff.
370 */
371 if (ulen == 0 && plen > 0xffff)
372 ulen = plen;
373
374 if (plen != ulen) {
375 udp6stat.udp6s_badlen++;
376 goto bad;
377 }
378
379 /* destination port of 0 is illegal, based on RFC768. */
380 if (uh->uh_dport == 0)
381 goto bad;
382
383 /* Be proactive about malicious use of IPv4 mapped address */
384 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
385 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
386 /* XXX stat */
387 goto bad;
388 }
389
390 /*
391 * Checksum extended UDP header and data.
392 */
393 if (uh->uh_sum == 0)
394 udp6stat.udp6s_nosum++;
395 else if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) {
396 udp6stat.udp6s_badsum++;
397 goto bad;
398 }
399
400 /*
401 * Construct source and dst sockaddrs.
402 * Note that ifindex (s6_addr16[1]) is already filled.
403 */
404 bzero(&src, sizeof(src));
405 src.sin6_family = AF_INET6;
406 src.sin6_len = sizeof(struct sockaddr_in6);
407 /* KAME hack: recover scopeid */
408 (void)in6_recoverscope(&src, &ip6->ip6_src, m->m_pkthdr.rcvif);
409 src.sin6_port = uh->uh_sport;
410 bzero(&dst, sizeof(dst));
411 dst.sin6_family = AF_INET6;
412 dst.sin6_len = sizeof(struct sockaddr_in6);
413 /* KAME hack: recover scopeid */
414 (void)in6_recoverscope(&dst, &ip6->ip6_dst, m->m_pkthdr.rcvif);
415 dst.sin6_port = uh->uh_dport;
416
417 if (udp6_realinput(AF_INET6, &src, &dst, m, off) == 0) {
418 if (m->m_flags & M_MCAST) {
419 udp6stat.udp6s_noportmcast++;
420 goto bad;
421 }
422 udp6stat.udp6s_noport++;
423 icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
424 m = NULL;
425 }
426
427 bad:
428 if (m)
429 m_freem(m);
430 return IPPROTO_DONE;
431 }
432 #endif
433
434 #ifdef INET
435 static void
436 udp4_sendup(m, off, src, so)
437 struct mbuf *m;
438 int off; /* offset of data portion */
439 struct sockaddr *src;
440 struct socket *so;
441 {
442 struct mbuf *opts = NULL;
443 struct mbuf *n;
444 struct inpcb *inp = NULL;
445 #ifdef INET6
446 struct in6pcb *in6p = NULL;
447 #endif
448
449 if (!so)
450 return;
451 switch (so->so_proto->pr_domain->dom_family) {
452 case AF_INET:
453 inp = sotoinpcb(so);
454 break;
455 #ifdef INET6
456 case AF_INET6:
457 in6p = sotoin6pcb(so);
458 break;
459 #endif
460 default:
461 return;
462 }
463
464 #ifdef IPSEC
465 /* check AH/ESP integrity. */
466 if (so != NULL && ipsec4_in_reject_so(m, so)) {
467 ipsecstat.in_polvio++;
468 return;
469 }
470 #endif /*IPSEC*/
471
472 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
473 if (inp && (inp->inp_flags & INP_CONTROLOPTS
474 || so->so_options & SO_TIMESTAMP)) {
475 struct ip *ip = mtod(n, struct ip *);
476 ip_savecontrol(inp, &opts, ip, n);
477 }
478
479 m_adj(n, off);
480 if (sbappendaddr(&so->so_rcv, src, n,
481 opts) == 0) {
482 m_freem(n);
483 if (opts)
484 m_freem(opts);
485 } else
486 sorwakeup(so);
487 }
488 }
489 #endif
490
491 #ifdef INET6
492 static void
493 udp6_sendup(m, off, src, so)
494 struct mbuf *m;
495 int off; /* offset of data portion */
496 struct sockaddr *src;
497 struct socket *so;
498 {
499 struct mbuf *opts = NULL;
500 struct mbuf *n;
501 struct in6pcb *in6p = NULL;
502
503 if (!so)
504 return;
505 if (so->so_proto->pr_domain->dom_family != AF_INET6)
506 return;
507 in6p = sotoin6pcb(so);
508
509 #ifdef IPSEC
510 /* check AH/ESP integrity. */
511 if (so != NULL && ipsec6_in_reject_so(m, so)) {
512 ipsec6stat.in_polvio++;
513 return;
514 }
515 #endif /*IPSEC*/
516
517 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
518 if (in6p && (in6p->in6p_flags & IN6P_CONTROLOPTS
519 || in6p->in6p_socket->so_options & SO_TIMESTAMP)) {
520 struct ip6_hdr *ip6 = mtod(n, struct ip6_hdr *);
521 ip6_savecontrol(in6p, &opts, ip6, n);
522 }
523
524 m_adj(n, off);
525 if (sbappendaddr(&so->so_rcv, src, n, opts) == 0) {
526 m_freem(n);
527 if (opts)
528 m_freem(opts);
529 udp6stat.udp6s_fullsock++;
530 } else
531 sorwakeup(so);
532 }
533 }
534 #endif
535
536 #ifdef INET
537 static int
538 udp4_realinput(src, dst, m, off)
539 struct sockaddr_in *src;
540 struct sockaddr_in *dst;
541 struct mbuf *m;
542 int off; /* offset of udphdr */
543 {
544 u_int16_t *sport, *dport;
545 int rcvcnt;
546 struct in_addr *src4, *dst4;
547 struct inpcb *inp;
548
549 rcvcnt = 0;
550 off += sizeof(struct udphdr); /* now, offset of payload */
551
552 if (src->sin_family != AF_INET || dst->sin_family != AF_INET)
553 goto bad;
554
555 src4 = &src->sin_addr;
556 sport = &src->sin_port;
557 dst4 = &dst->sin_addr;
558 dport = &dst->sin_port;
559
560 if (IN_MULTICAST(dst4->s_addr) ||
561 in_broadcast(*dst4, m->m_pkthdr.rcvif)) {
562 struct inpcb *last;
563 /*
564 * Deliver a multicast or broadcast datagram to *all* sockets
565 * for which the local and remote addresses and ports match
566 * those of the incoming datagram. This allows more than
567 * one process to receive multi/broadcasts on the same port.
568 * (This really ought to be done for unicast datagrams as
569 * well, but that would cause problems with existing
570 * applications that open both address-specific sockets and
571 * a wildcard socket listening to the same port -- they would
572 * end up receiving duplicates of every unicast datagram.
573 * Those applications open the multiple sockets to overcome an
574 * inadequacy of the UDP socket interface, but for backwards
575 * compatibility we avoid the problem here rather than
576 * fixing the interface. Maybe 4.5BSD will remedy this?)
577 */
578
579 /*
580 * KAME note: usually we drop udpiphdr from mbuf here.
581 * we need udpiphdr for IPsec processing so we do that later.
582 */
583 /*
584 * Locate pcb(s) for datagram.
585 */
586 for (inp = udbtable.inpt_queue.cqh_first;
587 inp != (struct inpcb *)&udbtable.inpt_queue;
588 inp = inp->inp_queue.cqe_next) {
589 if (inp->inp_lport != *dport)
590 continue;
591 if (!in_nullhost(inp->inp_laddr)) {
592 if (!in_hosteq(inp->inp_laddr, *dst4))
593 continue;
594 }
595 if (!in_nullhost(inp->inp_faddr)) {
596 if (!in_hosteq(inp->inp_faddr, *src4) ||
597 inp->inp_fport != *sport)
598 continue;
599 }
600
601 last = inp;
602 udp4_sendup(m, off, (struct sockaddr *)src,
603 inp->inp_socket);
604 rcvcnt++;
605
606 /*
607 * Don't look for additional matches if this one does
608 * not have either the SO_REUSEPORT or SO_REUSEADDR
609 * socket options set. This heuristic avoids searching
610 * through all pcbs in the common case of a non-shared
611 * port. It assumes that an application will never
612 * clear these options after setting them.
613 */
614 if ((inp->inp_socket->so_options &
615 (SO_REUSEPORT|SO_REUSEADDR)) == 0)
616 break;
617 }
618
619 #if 0
620 if (last == NULL) {
621 /*
622 * No matching pcb found; discard datagram.
623 * (No need to send an ICMP Port Unreachable
624 * for a broadcast or multicast datgram.)
625 */
626 udpstat.udps_noportbcast++;
627 goto bad;
628 }
629 #endif
630 } else {
631 /*
632 * Locate pcb for datagram.
633 */
634 inp = in_pcblookup_connect(&udbtable, *src4, *sport, *dst4, *dport);
635 if (inp == 0) {
636 ++udpstat.udps_pcbhashmiss;
637 inp = in_pcblookup_bind(&udbtable, *dst4, *dport);
638 if (inp == 0) {
639 #if 0
640 struct mbuf *n;
641
642 if (m->m_flags & (M_BCAST | M_MCAST)) {
643 udpstat.udps_noportbcast++;
644 goto bad;
645 }
646 udpstat.udps_noport++;
647 #ifdef IPKDB
648 if (checkipkdb(src4, *sport, *dport, m, off,
649 m->m_pkthdr.len - off)) {
650 /*
651 * It was a debugger connect packet,
652 * just drop it now
653 */
654 goto bad;
655 }
656 #endif
657 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
658 icmp_error(n, ICMP_UNREACH,
659 ICMP_UNREACH_PORT, 0, 0);
660 }
661 #endif
662 return rcvcnt;
663 }
664 }
665
666 udp4_sendup(m, off, (struct sockaddr *)src, inp->inp_socket);
667 rcvcnt++;
668 }
669
670 bad:
671 return rcvcnt;
672 }
673 #endif
674
675 #ifdef INET6
676 static int
677 in6_mcmatch(in6p, ia6, ifp)
678 struct in6pcb *in6p;
679 struct in6_addr *ia6;
680 struct ifnet *ifp;
681 {
682 struct ip6_moptions *im6o = in6p->in6p_moptions;
683 struct in6_multi_mship *imm;
684
685 if (im6o == NULL)
686 return 0;
687
688 for (imm = im6o->im6o_memberships.lh_first; imm != NULL;
689 imm = imm->i6mm_chain.le_next) {
690 if ((ifp == NULL ||
691 imm->i6mm_maddr->in6m_ifp == ifp) &&
692 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
693 ia6))
694 return 1;
695 }
696 return 0;
697 }
698
699 static int
700 udp6_realinput(af, src, dst, m, off)
701 int af; /* af on packet */
702 struct sockaddr_in6 *src;
703 struct sockaddr_in6 *dst;
704 struct mbuf *m;
705 int off; /* offset of udphdr */
706 {
707 u_int16_t *sport, *dport;
708 int rcvcnt;
709 struct in6_addr *src6, *dst6;
710 struct in_addr *dst4;
711 struct in6pcb *in6p;
712
713 rcvcnt = 0;
714 off += sizeof(struct udphdr); /* now, offset of payload */
715
716 if (af != AF_INET && af != AF_INET6)
717 goto bad;
718 if (src->sin6_family != AF_INET6 || dst->sin6_family != AF_INET6)
719 goto bad;
720
721 src6 = &src->sin6_addr;
722 sport = &src->sin6_port;
723 dst6 = &dst->sin6_addr;
724 dport = &dst->sin6_port;
725 dst4 = (struct in_addr *)&dst->sin6_addr.s6_addr32[12];
726
727 if (IN6_IS_ADDR_MULTICAST(dst6)
728 || (af == AF_INET && IN_MULTICAST(dst4->s_addr))) {
729 struct in6pcb *last;
730 /*
731 * Deliver a multicast or broadcast datagram to *all* sockets
732 * for which the local and remote addresses and ports match
733 * those of the incoming datagram. This allows more than
734 * one process to receive multi/broadcasts on the same port.
735 * (This really ought to be done for unicast datagrams as
736 * well, but that would cause problems with existing
737 * applications that open both address-specific sockets and
738 * a wildcard socket listening to the same port -- they would
739 * end up receiving duplicates of every unicast datagram.
740 * Those applications open the multiple sockets to overcome an
741 * inadequacy of the UDP socket interface, but for backwards
742 * compatibility we avoid the problem here rather than
743 * fixing the interface. Maybe 4.5BSD will remedy this?)
744 */
745
746 /*
747 * KAME note: usually we drop udpiphdr from mbuf here.
748 * we need udpiphdr for IPsec processing so we do that later.
749 */
750 /*
751 * Locate pcb(s) for datagram.
752 */
753 for (in6p = udb6.in6p_next; in6p != &udb6;
754 in6p = in6p->in6p_next) {
755 if (in6p->in6p_lport != *dport)
756 continue;
757 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
758 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, dst6)
759 && !in6_mcmatch(in6p, dst6, m->m_pkthdr.rcvif))
760 continue;
761 }
762 #ifndef INET6_BINDV6ONLY
763 else {
764 if (IN6_IS_ADDR_V4MAPPED(dst6)
765 && (in6p->in6p_flags & IN6P_BINDV6ONLY))
766 continue;
767 }
768 #endif
769 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
770 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, src6)
771 || in6p->in6p_fport != *sport)
772 continue;
773 }
774 #ifndef INET6_BINDV6ONLY
775 else {
776 if (IN6_IS_ADDR_V4MAPPED(src6)
777 && (in6p->in6p_flags & IN6P_BINDV6ONLY))
778 continue;
779 }
780 #endif
781
782 last = in6p;
783 udp6_sendup(m, off, (struct sockaddr *)src,
784 in6p->in6p_socket);
785 rcvcnt++;
786
787 /*
788 * Don't look for additional matches if this one does
789 * not have either the SO_REUSEPORT or SO_REUSEADDR
790 * socket options set. This heuristic avoids searching
791 * through all pcbs in the common case of a non-shared
792 * port. It assumes that an application will never
793 * clear these options after setting them.
794 */
795 if ((in6p->in6p_socket->so_options &
796 (SO_REUSEPORT|SO_REUSEADDR)) == 0)
797 break;
798 }
799
800 #if 0
801 if (last == NULL) {
802 /*
803 * No matching pcb found; discard datagram.
804 * (No need to send an ICMP Port Unreachable
805 * for a broadcast or multicast datgram.)
806 */
807 switch (af) {
808 case AF_INET:
809 udpstat.udps_noportbcast++;
810 break;
811 case AF_INET6:
812 udp6stat.udp6s_noportmcast++;
813 break;
814 }
815 goto bad;
816 }
817 #endif
818 } else {
819 /*
820 * Locate pcb for datagram.
821 */
822 in6p = in6_pcblookup_connect(&udb6, src6, *sport,
823 dst6, *dport, 0);
824 if (in6p == 0) {
825 ++udpstat.udps_pcbhashmiss;
826 in6p = in6_pcblookup_bind(&udb6, dst6, *dport, 0);
827 if (in6p == 0) {
828 #if 0
829 struct mbuf *n;
830 n = m_copy(m, 0, M_COPYALL);
831 switch (af) {
832 case AF_INET:
833 if (m->m_flags & (M_BCAST | M_MCAST)) {
834 udpstat.udps_noportbcast++;
835 goto bad;
836 }
837 udpstat.udps_noport++;
838 if (n != NULL)
839 icmp_error(n, ICMP_UNREACH,
840 ICMP_UNREACH_PORT, 0, 0);
841 break;
842 case AF_INET6:
843 if (m->m_flags & M_MCAST) {
844 udp6stat.udp6s_noportmcast++;
845 goto bad;
846 }
847 udp6stat.udp6s_noport++;
848 if (n != NULL)
849 icmp6_error(n, ICMP6_DST_UNREACH,
850 ICMP6_DST_UNREACH_NOPORT, 0);
851 break;
852 }
853 #endif
854
855 return rcvcnt;
856 }
857 }
858
859 udp6_sendup(m, off, (struct sockaddr *)src, in6p->in6p_socket);
860 rcvcnt++;
861 }
862
863 bad:
864 return rcvcnt;
865 }
866 #endif
867
868 #else /*UDP6*/
869
870 void
871 #if __STDC__
872 udp_input(struct mbuf *m, ...)
873 #else
874 udp_input(m, va_alist)
875 struct mbuf *m;
876 va_dcl
877 #endif
878 {
879 int proto;
880 struct ip *ip;
881 struct udphdr *uh;
882 struct inpcb *inp;
883 struct mbuf *opts = 0;
884 int len;
885 struct ip save_ip;
886 int iphlen;
887 va_list ap;
888 struct sockaddr_in udpsrc;
889 struct sockaddr *sa;
890
891 va_start(ap, m);
892 iphlen = va_arg(ap, int);
893 proto = va_arg(ap, int);
894 va_end(ap);
895
896 udpstat.udps_ipackets++;
897
898 /*
899 * Strip IP options, if any; should skip this,
900 * make available to user, and use on returned packets,
901 * but we don't yet have a way to check the checksum
902 * with options still present.
903 */
904 if (iphlen > sizeof (struct ip)) {
905 ip_stripoptions(m, (struct mbuf *)0);
906 iphlen = sizeof(struct ip);
907 }
908
909 /*
910 * Get IP and UDP header together in first mbuf.
911 */
912 ip = mtod(m, struct ip *);
913 if (m->m_len < iphlen + sizeof(struct udphdr)) {
914 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
915 udpstat.udps_hdrops++;
916 return;
917 }
918 ip = mtod(m, struct ip *);
919 }
920 uh = (struct udphdr *)((caddr_t)ip + iphlen);
921
922 /* destination port of 0 is illegal, based on RFC768. */
923 if (uh->uh_dport == 0)
924 goto bad;
925
926 /*
927 * Make mbuf data length reflect UDP length.
928 * If not enough data to reflect UDP length, drop.
929 */
930 len = ntohs((u_int16_t)uh->uh_ulen);
931 if (ip->ip_len != iphlen + len) {
932 if (ip->ip_len < iphlen + len || len < sizeof(struct udphdr)) {
933 udpstat.udps_badlen++;
934 goto bad;
935 }
936 m_adj(m, iphlen + len - ip->ip_len);
937 }
938 /*
939 * Save a copy of the IP header in case we want restore it
940 * for sending an ICMP error message in response.
941 */
942 save_ip = *ip;
943
944 /*
945 * Checksum extended UDP header and data.
946 */
947 if (uh->uh_sum) {
948 bzero(((struct ipovly *)ip)->ih_x1,
949 sizeof ((struct ipovly *)ip)->ih_x1);
950 ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
951 if (in_cksum(m, len + sizeof (struct ip)) != 0) {
952 udpstat.udps_badsum++;
953 m_freem(m);
954 return;
955 }
956 }
957
958 /*
959 * Construct sockaddr format source address.
960 */
961 udpsrc.sin_family = AF_INET;
962 udpsrc.sin_len = sizeof(struct sockaddr_in);
963 udpsrc.sin_addr = ip->ip_src;
964 udpsrc.sin_port = uh->uh_sport;
965 bzero((caddr_t)udpsrc.sin_zero, sizeof(udpsrc.sin_zero));
966
967 if (IN_MULTICAST(ip->ip_dst.s_addr) ||
968 in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
969 struct inpcb *last;
970 /*
971 * Deliver a multicast or broadcast datagram to *all* sockets
972 * for which the local and remote addresses and ports match
973 * those of the incoming datagram. This allows more than
974 * one process to receive multi/broadcasts on the same port.
975 * (This really ought to be done for unicast datagrams as
976 * well, but that would cause problems with existing
977 * applications that open both address-specific sockets and
978 * a wildcard socket listening to the same port -- they would
979 * end up receiving duplicates of every unicast datagram.
980 * Those applications open the multiple sockets to overcome an
981 * inadequacy of the UDP socket interface, but for backwards
982 * compatibility we avoid the problem here rather than
983 * fixing the interface. Maybe 4.5BSD will remedy this?)
984 */
985
986 iphlen += sizeof(struct udphdr);
987 /*
988 * KAME note: usually we drop udpiphdr from mbuf here.
989 * we need udpiphdr for IPsec processing so we do that later.
990 */
991 /*
992 * Locate pcb(s) for datagram.
993 * (Algorithm copied from raw_intr().)
994 */
995 last = NULL;
996 for (inp = udbtable.inpt_queue.cqh_first;
997 inp != (struct inpcb *)&udbtable.inpt_queue;
998 inp = inp->inp_queue.cqe_next) {
999 if (inp->inp_lport != uh->uh_dport)
1000 continue;
1001 if (!in_nullhost(inp->inp_laddr)) {
1002 if (!in_hosteq(inp->inp_laddr, ip->ip_dst))
1003 continue;
1004 }
1005 if (!in_nullhost(inp->inp_faddr)) {
1006 if (!in_hosteq(inp->inp_faddr, ip->ip_src) ||
1007 inp->inp_fport != uh->uh_sport)
1008 continue;
1009 }
1010
1011 if (last != NULL) {
1012 struct mbuf *n;
1013
1014 #ifdef IPSEC
1015 /* check AH/ESP integrity. */
1016 if (last != NULL && ipsec4_in_reject(m, last)) {
1017 ipsecstat.in_polvio++;
1018 /* do not inject data to pcb */
1019 } else
1020 #endif /*IPSEC*/
1021 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
1022 if (last->inp_flags & INP_CONTROLOPTS
1023 || last->inp_socket->so_options &
1024 SO_TIMESTAMP) {
1025 ip_savecontrol(last, &opts,
1026 ip, n);
1027 }
1028 m_adj(n, iphlen);
1029 sa = (struct sockaddr *)&udpsrc;
1030 if (sbappendaddr(
1031 &last->inp_socket->so_rcv,
1032 sa, n, opts) == 0) {
1033 m_freem(n);
1034 if (opts)
1035 m_freem(opts);
1036 } else
1037 sorwakeup(last->inp_socket);
1038 opts = 0;
1039 }
1040 }
1041 last = inp;
1042 /*
1043 * Don't look for additional matches if this one does
1044 * not have either the SO_REUSEPORT or SO_REUSEADDR
1045 * socket options set. This heuristic avoids searching
1046 * through all pcbs in the common case of a non-shared
1047 * port. It * assumes that an application will never
1048 * clear these options after setting them.
1049 */
1050 if ((last->inp_socket->so_options &
1051 (SO_REUSEPORT|SO_REUSEADDR)) == 0)
1052 break;
1053 }
1054
1055 if (last == NULL) {
1056 /*
1057 * No matching pcb found; discard datagram.
1058 * (No need to send an ICMP Port Unreachable
1059 * for a broadcast or multicast datgram.)
1060 */
1061 udpstat.udps_noportbcast++;
1062 goto bad;
1063 }
1064 #ifdef IPSEC
1065 /* check AH/ESP integrity. */
1066 if (last != NULL && ipsec4_in_reject(m, last)) {
1067 ipsecstat.in_polvio++;
1068 goto bad;
1069 }
1070 #endif /*IPSEC*/
1071 if (last->inp_flags & INP_CONTROLOPTS ||
1072 last->inp_socket->so_options & SO_TIMESTAMP)
1073 ip_savecontrol(last, &opts, ip, m);
1074 m->m_len -= iphlen;
1075 m->m_pkthdr.len -= iphlen;
1076 m->m_data += iphlen;
1077 sa = (struct sockaddr *)&udpsrc;
1078 if (sbappendaddr(&last->inp_socket->so_rcv, sa, m, opts) == 0) {
1079 udpstat.udps_fullsock++;
1080 goto bad;
1081 }
1082 sorwakeup(last->inp_socket);
1083 return;
1084 }
1085 /*
1086 * Locate pcb for datagram.
1087 */
1088 inp = in_pcblookup_connect(&udbtable, ip->ip_src, uh->uh_sport,
1089 ip->ip_dst, uh->uh_dport);
1090 if (inp == 0) {
1091 ++udpstat.udps_pcbhashmiss;
1092 inp = in_pcblookup_bind(&udbtable, ip->ip_dst, uh->uh_dport);
1093 if (inp == 0) {
1094 if (m->m_flags & (M_BCAST | M_MCAST)) {
1095 udpstat.udps_noportbcast++;
1096 goto bad;
1097 }
1098 udpstat.udps_noport++;
1099 *ip = save_ip;
1100 #ifdef IPKDB
1101 if (checkipkdb(&ip->ip_src,
1102 uh->uh_sport,
1103 uh->uh_dport,
1104 m,
1105 iphlen + sizeof(struct udphdr),
1106 len - sizeof(struct udphdr)))
1107 /* It was a debugger connect packet, just drop it now */
1108 goto bad;
1109 #endif
1110 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
1111 return;
1112 }
1113 }
1114 #ifdef IPSEC
1115 if (inp != NULL && ipsec4_in_reject(m, inp)) {
1116 ipsecstat.in_polvio++;
1117 goto bad;
1118 }
1119 #endif /*IPSEC*/
1120
1121 /*
1122 * Stuff source address and datagram in user buffer.
1123 */
1124 if (inp->inp_flags & INP_CONTROLOPTS ||
1125 inp->inp_socket->so_options & SO_TIMESTAMP)
1126 ip_savecontrol(inp, &opts, ip, m);
1127 iphlen += sizeof(struct udphdr);
1128 m->m_len -= iphlen;
1129 m->m_pkthdr.len -= iphlen;
1130 m->m_data += iphlen;
1131 sa = (struct sockaddr *)&udpsrc;
1132 if (sbappendaddr(&inp->inp_socket->so_rcv, sa, m, opts) == 0) {
1133 udpstat.udps_fullsock++;
1134 goto bad;
1135 }
1136 sorwakeup(inp->inp_socket);
1137 return;
1138 bad:
1139 m_freem(m);
1140 if (opts)
1141 m_freem(opts);
1142 }
1143 #endif /*UDP6*/
1144
1145 #ifdef INET
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 #endif
1485