1 /* $OpenBSD: udp_usrreq.c,v 1.100 2004/04/14 05:34:15 itojun Exp $ */
2 /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
3
4 /*
5 * Copyright (c) 1982, 1986, 1988, 1990, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
33 *
34 * NRL grants permission for redistribution and use in source and binary
35 * forms, with or without modification, of the software and documentation
36 * created at NRL provided that the following conditions are met:
37 *
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 * must display the following acknowledgements:
45 * This product includes software developed by the University of
46 * California, Berkeley and its contributors.
47 * This product includes software developed at the Information
48 * Technology Division, US Naval Research Laboratory.
49 * 4. Neither the name of the NRL nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
52 *
53 * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
54 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
56 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR
57 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
59 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
60 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
61 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
62 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 *
65 * The views and conclusions contained in the software and documentation
66 * are those of the authors and should not be interpreted as representing
67 * official policies, either expressed or implied, of the US Naval
68 * Research Laboratory (NRL).
69 */
70
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/mbuf.h>
74 #include <sys/protosw.h>
75 #include <sys/socket.h>
76 #include <sys/socketvar.h>
77 #include <sys/sysctl.h>
78
79 #include <net/if.h>
80 #include <net/route.h>
81
82 #include <netinet/in.h>
83 #include <netinet/in_systm.h>
84 #include <netinet/in_var.h>
85 #include <netinet/ip.h>
86 #include <netinet/in_pcb.h>
87 #include <netinet/ip_var.h>
88 #include <netinet/ip_icmp.h>
89 #include <netinet/udp.h>
90 #include <netinet/udp_var.h>
91
92 #ifdef IPSEC
93 #include <netinet/ip_ipsp.h>
94 #include <netinet/ip_esp.h>
95 #endif
96
97 #ifdef INET6
98 #ifndef INET
99 #include <netinet/in.h>
100 #endif
101 #include <netinet6/ip6protosw.h>
102
103 extern int ip6_defhlim;
104 #endif /* INET6 */
105
106 /*
107 * UDP protocol implementation.
108 * Per RFC 768, August, 1980.
109 */
110 int udpcksum = 1;
111
112 u_int udp_sendspace = 9216; /* really max datagram size */
113 u_int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
114 /* 40 1K datagrams */
115
116 int *udpctl_vars[UDPCTL_MAXID] = UDPCTL_VARS;
117
118 struct inpcbtable udbtable;
119 struct udpstat udpstat;
120
121 static void udp_detach(struct inpcb *);
122 static void udp_notify(struct inpcb *, int);
123 static struct mbuf *udp_saveopt(caddr_t, int, int);
124
125 #ifndef UDBHASHSIZE
126 #define UDBHASHSIZE 128
127 #endif
128 int udbhashsize = UDBHASHSIZE;
129
130 /* from in_pcb.c */
131 extern struct baddynamicports baddynamicports;
132
133 void
udp_init()134 udp_init()
135 {
136 in_pcbinit(&udbtable, udbhashsize);
137 }
138
139 #ifdef INET6
140 int
udp6_input(mp,offp,proto)141 udp6_input(mp, offp, proto)
142 struct mbuf **mp;
143 int *offp, proto;
144 {
145 struct mbuf *m = *mp;
146
147 #if defined(NFAITH) && 0 < NFAITH
148 if (m->m_pkthdr.rcvif) {
149 if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
150 /* XXX send icmp6 host/port unreach? */
151 m_freem(m);
152 return IPPROTO_DONE;
153 }
154 }
155 #endif
156
157 udp_input(m, *offp, proto);
158 return IPPROTO_DONE;
159 }
160 #endif
161
162 void
udp_input(struct mbuf * m,...)163 udp_input(struct mbuf *m, ...)
164 {
165 struct ip *ip;
166 struct udphdr *uh;
167 struct inpcb *inp;
168 struct mbuf *opts = 0;
169 struct ip save_ip;
170 int iphlen, len;
171 va_list ap;
172 u_int16_t savesum;
173 union {
174 struct sockaddr sa;
175 struct sockaddr_in sin;
176 #ifdef INET6
177 struct sockaddr_in6 sin6;
178 #endif /* INET6 */
179 } srcsa, dstsa;
180 #ifdef INET6
181 struct ip6_hdr *ip6;
182 #endif /* INET6 */
183 #ifdef IPSEC
184 struct m_tag *mtag;
185 struct tdb_ident *tdbi;
186 struct tdb *tdb;
187 int error, s;
188 #endif /* IPSEC */
189
190 va_start(ap, m);
191 iphlen = va_arg(ap, int);
192 va_end(ap);
193
194 udpstat.udps_ipackets++;
195
196 switch (mtod(m, struct ip *)->ip_v) {
197 case 4:
198 ip = mtod(m, struct ip *);
199 #ifdef INET6
200 ip6 = NULL;
201 #endif /* INET6 */
202 srcsa.sa.sa_family = AF_INET;
203 break;
204 #ifdef INET6
205 case 6:
206 ip = NULL;
207 ip6 = mtod(m, struct ip6_hdr *);
208 srcsa.sa.sa_family = AF_INET6;
209 break;
210 #endif /* INET6 */
211 default:
212 goto bad;
213 }
214
215 IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
216 if (!uh) {
217 udpstat.udps_hdrops++;
218 return;
219 }
220
221 /* Check for illegal destination port 0 */
222 if (uh->uh_dport == 0) {
223 udpstat.udps_noport++;
224 goto bad;
225 }
226
227 /*
228 * Make mbuf data length reflect UDP length.
229 * If not enough data to reflect UDP length, drop.
230 */
231 len = ntohs((u_int16_t)uh->uh_ulen);
232 if (ip) {
233 if (m->m_pkthdr.len - iphlen != len) {
234 if (len > (m->m_pkthdr.len - iphlen) ||
235 len < sizeof(struct udphdr)) {
236 udpstat.udps_badlen++;
237 goto bad;
238 }
239 m_adj(m, len - (m->m_pkthdr.len - iphlen));
240 }
241 }
242 #ifdef INET6
243 else if (ip6) {
244 /* jumbograms */
245 if (len == 0 && m->m_pkthdr.len - iphlen > 0xffff)
246 len = m->m_pkthdr.len - iphlen;
247 if (len != m->m_pkthdr.len - iphlen) {
248 udpstat.udps_badlen++;
249 goto bad;
250 }
251 }
252 #endif
253 else /* shouldn't happen */
254 goto bad;
255
256 /*
257 * Save a copy of the IP header in case we want restore it
258 * for sending an ICMP error message in response.
259 */
260 if (ip)
261 save_ip = *ip;
262
263 /*
264 * Checksum extended UDP header and data.
265 * from W.R.Stevens: check incoming udp cksums even if
266 * udpcksum is not set.
267 */
268 savesum = uh->uh_sum;
269 #ifdef INET6
270 if (ip6) {
271 /* Be proactive about malicious use of IPv4 mapped address */
272 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
273 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
274 /* XXX stat */
275 goto bad;
276 }
277
278 /*
279 * In IPv6, the UDP checksum is ALWAYS used.
280 */
281 if (uh->uh_sum == 0) {
282 udpstat.udps_nosum++;
283 goto bad;
284 }
285 if ((uh->uh_sum = in6_cksum(m, IPPROTO_UDP, iphlen, len))) {
286 udpstat.udps_badsum++;
287 goto bad;
288 }
289 } else
290 #endif /* INET6 */
291 if (uh->uh_sum) {
292 if ((m->m_pkthdr.csum & M_UDP_CSUM_IN_OK) == 0) {
293 if (m->m_pkthdr.csum & M_UDP_CSUM_IN_BAD) {
294 udpstat.udps_badsum++;
295 udpstat.udps_inhwcsum++;
296 m_freem(m);
297 return;
298 }
299
300 if ((uh->uh_sum = in4_cksum(m, IPPROTO_UDP,
301 iphlen, len))) {
302 udpstat.udps_badsum++;
303 m_freem(m);
304 return;
305 }
306 } else {
307 m->m_pkthdr.csum &= ~M_UDP_CSUM_IN_OK;
308 udpstat.udps_inhwcsum++;
309 }
310 } else
311 udpstat.udps_nosum++;
312
313 #ifdef IPSEC
314 if (udpencap_enable && udpencap_port &&
315 uh->uh_dport == htons(udpencap_port)) {
316 u_int32_t spi;
317 int skip = iphlen + sizeof(struct udphdr);
318
319 if (m->m_pkthdr.len - skip < sizeof(u_int32_t)) {
320 /* packet too short */
321 m_freem(m);
322 return;
323 }
324 m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi);
325 /*
326 * decapsulate if the SPI is not zero, otherwise pass
327 * to userland
328 */
329 if (spi != 0) {
330 if ((m = m_pullup2(m, skip)) == NULL) {
331 udpstat.udps_hdrops++;
332 return;
333 }
334
335 /* remove the UDP header */
336 bcopy(mtod(m, u_char *),
337 mtod(m, u_char *) + sizeof(struct udphdr), iphlen);
338 m_adj(m, sizeof(struct udphdr));
339 skip -= sizeof(struct udphdr);
340
341 espstat.esps_udpencin++;
342 ipsec_common_input(m, skip, offsetof(struct ip, ip_p),
343 srcsa.sa.sa_family, IPPROTO_ESP, 1);
344 return;
345 }
346 }
347 #endif
348
349 switch (srcsa.sa.sa_family) {
350 case AF_INET:
351 bzero(&srcsa, sizeof(struct sockaddr_in));
352 srcsa.sin.sin_len = sizeof(struct sockaddr_in);
353 srcsa.sin.sin_family = AF_INET;
354 srcsa.sin.sin_port = uh->uh_sport;
355 srcsa.sin.sin_addr = ip->ip_src;
356
357 bzero(&dstsa, sizeof(struct sockaddr_in));
358 dstsa.sin.sin_len = sizeof(struct sockaddr_in);
359 dstsa.sin.sin_family = AF_INET;
360 dstsa.sin.sin_port = uh->uh_dport;
361 dstsa.sin.sin_addr = ip->ip_dst;
362 break;
363 #ifdef INET6
364 case AF_INET6:
365 bzero(&srcsa, sizeof(struct sockaddr_in6));
366 srcsa.sin6.sin6_len = sizeof(struct sockaddr_in6);
367 srcsa.sin6.sin6_family = AF_INET6;
368 srcsa.sin6.sin6_port = uh->uh_sport;
369 #if 0 /*XXX inbound flowinfo */
370 srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ip6->ip6_flow;
371 #endif
372 /* KAME hack: recover scopeid */
373 (void)in6_recoverscope(&srcsa.sin6, &ip6->ip6_src,
374 m->m_pkthdr.rcvif);
375
376 bzero(&dstsa, sizeof(struct sockaddr_in6));
377 dstsa.sin6.sin6_len = sizeof(struct sockaddr_in6);
378 dstsa.sin6.sin6_family = AF_INET6;
379 dstsa.sin6.sin6_port = uh->uh_dport;
380 /* KAME hack: recover scopeid */
381 (void)in6_recoverscope(&dstsa.sin6, &ip6->ip6_dst,
382 m->m_pkthdr.rcvif);
383 break;
384 #endif /* INET6 */
385 }
386
387 #ifdef INET6
388 if ((ip6 && IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) ||
389 (ip && IN_MULTICAST(ip->ip_dst.s_addr)) ||
390 (ip && in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))) {
391 #else /* INET6 */
392 if (IN_MULTICAST(ip->ip_dst.s_addr) ||
393 in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
394 #endif /* INET6 */
395 struct socket *last;
396 /*
397 * Deliver a multicast or broadcast datagram to *all* sockets
398 * for which the local and remote addresses and ports match
399 * those of the incoming datagram. This allows more than
400 * one process to receive multi/broadcasts on the same port.
401 * (This really ought to be done for unicast datagrams as
402 * well, but that would cause problems with existing
403 * applications that open both address-specific sockets and
404 * a wildcard socket listening to the same port -- they would
405 * end up receiving duplicates of every unicast datagram.
406 * Those applications open the multiple sockets to overcome an
407 * inadequacy of the UDP socket interface, but for backwards
408 * compatibility we avoid the problem here rather than
409 * fixing the interface. Maybe 4.5BSD will remedy this?)
410 */
411
412 iphlen += sizeof(struct udphdr);
413
414 /*
415 * Locate pcb(s) for datagram.
416 * (Algorithm copied from raw_intr().)
417 */
418 last = NULL;
419 CIRCLEQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue) {
420 #ifdef INET6
421 /* don't accept it if AF does not match */
422 if (ip6 && !(inp->inp_flags & INP_IPV6))
423 continue;
424 if (!ip6 && (inp->inp_flags & INP_IPV6))
425 continue;
426 #endif
427 if (inp->inp_lport != uh->uh_dport)
428 continue;
429 #ifdef INET6
430 if (ip6) {
431 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6))
432 if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6,
433 &ip6->ip6_dst))
434 continue;
435 } else
436 #endif /* INET6 */
437 if (inp->inp_laddr.s_addr != INADDR_ANY) {
438 if (inp->inp_laddr.s_addr !=
439 ip->ip_dst.s_addr)
440 continue;
441 }
442 #ifdef INET6
443 if (ip6) {
444 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
445 if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6,
446 &ip6->ip6_src) ||
447 inp->inp_fport != uh->uh_sport)
448 continue;
449 } else
450 #endif /* INET6 */
451 if (inp->inp_faddr.s_addr != INADDR_ANY) {
452 if (inp->inp_faddr.s_addr !=
453 ip->ip_src.s_addr ||
454 inp->inp_fport != uh->uh_sport)
455 continue;
456 }
457
458 if (last != NULL) {
459 struct mbuf *n;
460
461 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
462 opts = NULL;
463 #ifdef INET6
464 if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS))
465 ip6_savecontrol(inp, &opts, ip6, n);
466 #endif /* INET6 */
467 m_adj(n, iphlen);
468 if (sbappendaddr(&last->so_rcv,
469 &srcsa.sa, n, opts) == 0) {
470 m_freem(n);
471 if (opts)
472 m_freem(opts);
473 udpstat.udps_fullsock++;
474 } else
475 sorwakeup(last);
476 opts = NULL;
477 }
478 }
479 last = inp->inp_socket;
480 /*
481 * Don't look for additional matches if this one does
482 * not have either the SO_REUSEPORT or SO_REUSEADDR
483 * socket options set. This heuristic avoids searching
484 * through all pcbs in the common case of a non-shared
485 * port. It * assumes that an application will never
486 * clear these options after setting them.
487 */
488 if ((last->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0)
489 break;
490 }
491
492 if (last == NULL) {
493 /*
494 * No matching pcb found; discard datagram.
495 * (No need to send an ICMP Port Unreachable
496 * for a broadcast or multicast datgram.)
497 */
498 udpstat.udps_noportbcast++;
499 goto bad;
500 }
501
502 opts = NULL;
503 #ifdef INET6
504 if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS))
505 ip6_savecontrol(inp, &opts, ip6, m);
506 #endif /* INET6 */
507 m_adj(m, iphlen);
508 if (sbappendaddr(&last->so_rcv,
509 &srcsa.sa, m, opts) == 0) {
510 udpstat.udps_fullsock++;
511 goto bad;
512 }
513 sorwakeup(last);
514 return;
515 }
516 /*
517 * Locate pcb for datagram.
518 */
519 #ifdef INET6
520 if (ip6)
521 inp = in6_pcbhashlookup(&udbtable, &ip6->ip6_src, uh->uh_sport,
522 &ip6->ip6_dst, uh->uh_dport);
523 else
524 #endif /* INET6 */
525 inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport,
526 ip->ip_dst, uh->uh_dport);
527 if (inp == 0) {
528 ++udpstat.udps_pcbhashmiss;
529 #ifdef INET6
530 if (ip6) {
531 inp = in6_pcblookup_listen(&udbtable,
532 &ip6->ip6_dst, uh->uh_dport, m_tag_find(m,
533 PACKET_TAG_PF_TRANSLATE_LOCALHOST, NULL) != NULL);
534 } else
535 #endif /* INET6 */
536 inp = in_pcblookup_listen(&udbtable,
537 ip->ip_dst, uh->uh_dport, m_tag_find(m,
538 PACKET_TAG_PF_TRANSLATE_LOCALHOST, NULL) != NULL);
539 if (inp == 0) {
540 udpstat.udps_noport++;
541 if (m->m_flags & (M_BCAST | M_MCAST)) {
542 udpstat.udps_noportbcast++;
543 goto bad;
544 }
545 #ifdef INET6
546 if (ip6) {
547 uh->uh_sum = savesum;
548 icmp6_error(m, ICMP6_DST_UNREACH,
549 ICMP6_DST_UNREACH_NOPORT,0);
550 } else
551 #endif /* INET6 */
552 {
553 *ip = save_ip;
554 uh->uh_sum = savesum;
555 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT,
556 0, 0);
557 }
558 return;
559 }
560 }
561
562 #ifdef IPSEC
563 mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
564 s = splnet();
565 if (mtag != NULL) {
566 tdbi = (struct tdb_ident *)(mtag + 1);
567 tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);
568 } else
569 tdb = NULL;
570 ipsp_spd_lookup(m, srcsa.sa.sa_family, iphlen, &error,
571 IPSP_DIRECTION_IN, tdb, inp);
572 if (error) {
573 splx(s);
574 goto bad;
575 }
576
577 /* Latch SA only if the socket is connected */
578 if (inp->inp_tdb_in != tdb &&
579 (inp->inp_socket->so_state & SS_ISCONNECTED)) {
580 if (tdb) {
581 tdb_add_inp(tdb, inp, 1);
582 if (inp->inp_ipo == NULL) {
583 inp->inp_ipo = ipsec_add_policy(inp,
584 srcsa.sa.sa_family, IPSP_DIRECTION_OUT);
585 if (inp->inp_ipo == NULL) {
586 splx(s);
587 goto bad;
588 }
589 }
590 if (inp->inp_ipo->ipo_dstid == NULL &&
591 tdb->tdb_srcid != NULL) {
592 inp->inp_ipo->ipo_dstid = tdb->tdb_srcid;
593 tdb->tdb_srcid->ref_count++;
594 }
595 if (inp->inp_ipsec_remotecred == NULL &&
596 tdb->tdb_remote_cred != NULL) {
597 inp->inp_ipsec_remotecred =
598 tdb->tdb_remote_cred;
599 tdb->tdb_remote_cred->ref_count++;
600 }
601 if (inp->inp_ipsec_remoteauth == NULL &&
602 tdb->tdb_remote_auth != NULL) {
603 inp->inp_ipsec_remoteauth =
604 tdb->tdb_remote_auth;
605 tdb->tdb_remote_auth->ref_count++;
606 }
607 } else { /* Just reset */
608 TAILQ_REMOVE(&inp->inp_tdb_in->tdb_inp_in, inp,
609 inp_tdb_in_next);
610 inp->inp_tdb_in = NULL;
611 }
612 }
613 splx(s);
614 #endif /*IPSEC */
615
616 opts = NULL;
617 #ifdef INET6
618 if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS))
619 ip6_savecontrol(inp, &opts, ip6, m);
620 #endif /* INET6 */
621 if (ip && (inp->inp_flags & INP_CONTROLOPTS)) {
622 struct mbuf **mp = &opts;
623
624 if (inp->inp_flags & INP_RECVDSTADDR) {
625 *mp = udp_saveopt((caddr_t) &ip->ip_dst,
626 sizeof(struct in_addr), IP_RECVDSTADDR);
627 if (*mp)
628 mp = &(*mp)->m_next;
629 }
630 #ifdef notyet
631 /* options were tossed above */
632 if (inp->inp_flags & INP_RECVOPTS) {
633 *mp = udp_saveopt((caddr_t) opts_deleted_above,
634 sizeof(struct in_addr), IP_RECVOPTS);
635 if (*mp)
636 mp = &(*mp)->m_next;
637 }
638 /* ip_srcroute doesn't do what we want here, need to fix */
639 if (inp->inp_flags & INP_RECVRETOPTS) {
640 *mp = udp_saveopt((caddr_t) ip_srcroute(),
641 sizeof(struct in_addr), IP_RECVRETOPTS);
642 if (*mp)
643 mp = &(*mp)->m_next;
644 }
645 #endif
646 }
647 iphlen += sizeof(struct udphdr);
648 m_adj(m, iphlen);
649 if (sbappendaddr(&inp->inp_socket->so_rcv, &srcsa.sa, m, opts) == 0) {
650 udpstat.udps_fullsock++;
651 goto bad;
652 }
653 sorwakeup(inp->inp_socket);
654 return;
655 bad:
656 m_freem(m);
657 if (opts)
658 m_freem(opts);
659 }
660
661 /*
662 * Create a "control" mbuf containing the specified data
663 * with the specified type for presentation with a datagram.
664 */
665 struct mbuf *
666 udp_saveopt(p, size, type)
667 caddr_t p;
668 int size;
669 int type;
670 {
671 struct cmsghdr *cp;
672 struct mbuf *m;
673
674 if ((m = m_get(M_DONTWAIT, MT_CONTROL)) == NULL)
675 return ((struct mbuf *) NULL);
676 cp = (struct cmsghdr *) mtod(m, struct cmsghdr *);
677 bcopy(p, CMSG_DATA(cp), size);
678 size = CMSG_LEN(size);
679 m->m_len = size;
680 cp->cmsg_len = size;
681 cp->cmsg_level = IPPROTO_IP;
682 cp->cmsg_type = type;
683 return (m);
684 }
685
686 /*
687 * Notify a udp user of an asynchronous error;
688 * just wake up so that he can collect error status.
689 */
690 static void
691 udp_notify(inp, errno)
692 struct inpcb *inp;
693 int errno;
694 {
695 inp->inp_socket->so_error = errno;
696 sorwakeup(inp->inp_socket);
697 sowwakeup(inp->inp_socket);
698 }
699
700 #ifdef INET6
701 void
702 udp6_ctlinput(cmd, sa, d)
703 int cmd;
704 struct sockaddr *sa;
705 void *d;
706 {
707 struct udphdr uh;
708 struct sockaddr_in6 sa6;
709 struct ip6_hdr *ip6;
710 struct mbuf *m;
711 int off;
712 void *cmdarg;
713 struct ip6ctlparam *ip6cp = NULL;
714 struct udp_portonly {
715 u_int16_t uh_sport;
716 u_int16_t uh_dport;
717 } *uhp;
718 void (*notify)(struct inpcb *, int) = udp_notify;
719
720 if (sa == NULL)
721 return;
722 if (sa->sa_family != AF_INET6 ||
723 sa->sa_len != sizeof(struct sockaddr_in6))
724 return;
725
726 if ((unsigned)cmd >= PRC_NCMDS)
727 return;
728 if (PRC_IS_REDIRECT(cmd))
729 notify = in_rtchange, d = NULL;
730 else if (cmd == PRC_HOSTDEAD)
731 d = NULL;
732 else if (cmd == PRC_MSGSIZE)
733 ; /* special code is present, see below */
734 else if (inet6ctlerrmap[cmd] == 0)
735 return;
736
737 /* if the parameter is from icmp6, decode it. */
738 if (d != NULL) {
739 ip6cp = (struct ip6ctlparam *)d;
740 m = ip6cp->ip6c_m;
741 ip6 = ip6cp->ip6c_ip6;
742 off = ip6cp->ip6c_off;
743 cmdarg = ip6cp->ip6c_cmdarg;
744 } else {
745 m = NULL;
746 ip6 = NULL;
747 cmdarg = NULL;
748 /* XXX: translate addresses into internal form */
749 sa6 = *(struct sockaddr_in6 *)sa;
750 #ifndef SCOPEDROUTING
751 if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL, NULL)) {
752 /* should be impossible */
753 return;
754 }
755 #endif
756 }
757
758 if (ip6cp && ip6cp->ip6c_finaldst) {
759 bzero(&sa6, sizeof(sa6));
760 sa6.sin6_family = AF_INET6;
761 sa6.sin6_len = sizeof(sa6);
762 sa6.sin6_addr = *ip6cp->ip6c_finaldst;
763 /* XXX: assuming M is valid in this case */
764 sa6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
765 ip6cp->ip6c_finaldst);
766 #ifndef SCOPEDROUTING
767 if (in6_embedscope(ip6cp->ip6c_finaldst, &sa6, NULL, NULL)) {
768 /* should be impossible */
769 return;
770 }
771 #endif
772 } else {
773 /* XXX: translate addresses into internal form */
774 sa6 = *(struct sockaddr_in6 *)sa;
775 #ifndef SCOPEDROUTING
776 if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL, NULL)) {
777 /* should be impossible */
778 return;
779 }
780 #endif
781 }
782
783 if (ip6) {
784 /*
785 * XXX: We assume that when IPV6 is non NULL,
786 * M and OFF are valid.
787 */
788 struct sockaddr_in6 sa6_src;
789
790 /* check if we can safely examine src and dst ports */
791 if (m->m_pkthdr.len < off + sizeof(*uhp))
792 return;
793
794 bzero(&uh, sizeof(uh));
795 m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh);
796
797 bzero(&sa6_src, sizeof(sa6_src));
798 sa6_src.sin6_family = AF_INET6;
799 sa6_src.sin6_len = sizeof(sa6_src);
800 sa6_src.sin6_addr = ip6->ip6_src;
801 sa6_src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
802 &ip6->ip6_src);
803 #ifndef SCOPEDROUTING
804 if (in6_embedscope(&sa6_src.sin6_addr, &sa6_src, NULL, NULL)) {
805 /* should be impossible */
806 return;
807 }
808 #endif
809
810 if (cmd == PRC_MSGSIZE) {
811 int valid = 0;
812
813 /*
814 * Check to see if we have a valid UDP socket
815 * corresponding to the address in the ICMPv6 message
816 * payload.
817 */
818 if (in6_pcbhashlookup(&udbtable, &sa6.sin6_addr,
819 uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport))
820 valid = 1;
821 #if 0
822 /*
823 * As the use of sendto(2) is fairly popular,
824 * we may want to allow non-connected pcb too.
825 * But it could be too weak against attacks...
826 * We should at least check if the local address (= s)
827 * is really ours.
828 */
829 else if (in6_pcblookup_listen(&udbtable,
830 &sa6_src.sin6_addr, uh.uh_sport, 0);
831 valid = 1;
832 #endif
833
834 /*
835 * Depending on the value of "valid" and routing table
836 * size (mtudisc_{hi,lo}wat), we will:
837 * - recalcurate the new MTU and create the
838 * corresponding routing entry, or
839 * - ignore the MTU change notification.
840 */
841 icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
842
843 /*
844 * regardless of if we called icmp6_mtudisc_update(),
845 * we need to call in6_pcbnotify(), to notify path
846 * MTU change to the userland (2292bis-02), because
847 * some unconnected sockets may share the same
848 * destination and want to know the path MTU.
849 */
850 }
851
852 (void) in6_pcbnotify(&udbtable, (struct sockaddr *)&sa6,
853 uh.uh_dport, (struct sockaddr *)&sa6_src,
854 uh.uh_sport, cmd, cmdarg, notify);
855 } else {
856 (void) in6_pcbnotify(&udbtable, (struct sockaddr *)&sa6, 0,
857 (struct sockaddr *)&sa6_any, 0, cmd, cmdarg, notify);
858 }
859 }
860 #endif
861
862 void *
863 udp_ctlinput(cmd, sa, v)
864 int cmd;
865 struct sockaddr *sa;
866 void *v;
867 {
868 struct ip *ip = v;
869 struct udphdr *uhp;
870 extern int inetctlerrmap[];
871 void (*notify)(struct inpcb *, int) = udp_notify;
872 int errno;
873
874 if (sa == NULL)
875 return NULL;
876 if (sa->sa_family != AF_INET ||
877 sa->sa_len != sizeof(struct sockaddr_in))
878 return NULL;
879
880 if ((unsigned)cmd >= PRC_NCMDS)
881 return NULL;
882 errno = inetctlerrmap[cmd];
883 if (PRC_IS_REDIRECT(cmd))
884 notify = in_rtchange, ip = 0;
885 else if (cmd == PRC_HOSTDEAD)
886 ip = 0;
887 else if (errno == 0)
888 return NULL;
889 if (ip) {
890 uhp = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
891 (void) in_pcbnotify(&udbtable, sa, uhp->uh_dport, ip->ip_src,
892 uhp->uh_sport, errno, notify);
893 } else
894 in_pcbnotifyall(&udbtable, sa, errno, notify);
895 return NULL;
896 }
897
898 int
899 udp_output(struct mbuf *m, ...)
900 {
901 struct inpcb *inp;
902 struct mbuf *addr, *control;
903 struct udpiphdr *ui;
904 int len = m->m_pkthdr.len;
905 struct in_addr laddr;
906 int s = 0, error = 0;
907 va_list ap;
908 int pcbflags = 0;
909
910 va_start(ap, m);
911 inp = va_arg(ap, struct inpcb *);
912 addr = va_arg(ap, struct mbuf *);
913 control = va_arg(ap, struct mbuf *);
914 va_end(ap);
915
916 #ifdef DIAGNOSTIC
917 if ((inp->inp_flags & INP_IPV6) != 0)
918 panic("IPv6 inpcb to udp_output");
919 #endif
920
921 /*
922 * Compute the packet length of the IP header, and
923 * punt if the length looks bogus.
924 */
925 if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) {
926 error = EMSGSIZE;
927 goto release;
928 }
929
930 if (addr) {
931 /*
932 * Save current PCB flags because they may change during
933 * temporary connection.
934 */
935 pcbflags = inp->inp_flags;
936
937 laddr = inp->inp_laddr;
938 if (inp->inp_faddr.s_addr != INADDR_ANY) {
939 error = EISCONN;
940 goto release;
941 }
942 /*
943 * Must block input while temporarily connected.
944 */
945 s = splsoftnet();
946 error = in_pcbconnect(inp, addr);
947 if (error) {
948 splx(s);
949 goto release;
950 }
951 } else {
952 if (inp->inp_faddr.s_addr == INADDR_ANY) {
953 error = ENOTCONN;
954 goto release;
955 }
956 }
957 /*
958 * Calculate data length and get a mbuf
959 * for UDP and IP headers.
960 */
961 M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
962 if (m == 0) {
963 error = ENOBUFS;
964 goto bail;
965 }
966
967 /*
968 * Fill in mbuf with extended UDP header
969 * and addresses and length put into network format.
970 */
971 ui = mtod(m, struct udpiphdr *);
972 bzero(ui->ui_x1, sizeof ui->ui_x1);
973 ui->ui_pr = IPPROTO_UDP;
974 ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr));
975 ui->ui_src = inp->inp_laddr;
976 ui->ui_dst = inp->inp_faddr;
977 ui->ui_sport = inp->inp_lport;
978 ui->ui_dport = inp->inp_fport;
979 ui->ui_ulen = ui->ui_len;
980
981 /*
982 * Compute the pseudo-header checksum; defer further checksumming
983 * until ip_output() or hardware (if it exists).
984 */
985 if (udpcksum) {
986 m->m_pkthdr.csum |= M_UDPV4_CSUM_OUT;
987 ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr,
988 ui->ui_dst.s_addr, htons((u_int16_t)len +
989 sizeof (struct udphdr) + IPPROTO_UDP));
990 } else
991 ui->ui_sum = 0;
992 ((struct ip *)ui)->ip_len = htons(sizeof (struct udpiphdr) + len);
993 ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl;
994 ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos;
995
996 udpstat.udps_opackets++;
997 error = ip_output(m, inp->inp_options, &inp->inp_route,
998 inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
999 inp->inp_moptions, inp, (void *)NULL);
1000
1001 bail:
1002 if (addr) {
1003 in_pcbdisconnect(inp);
1004 inp->inp_flags = pcbflags;
1005 inp->inp_laddr = laddr;
1006 splx(s);
1007 }
1008 if (control)
1009 m_freem(control);
1010 return (error);
1011
1012 release:
1013 m_freem(m);
1014 if (control)
1015 m_freem(control);
1016 return (error);
1017 }
1018
1019 #ifdef INET6
1020 /*ARGSUSED*/
1021 int
1022 udp6_usrreq(so, req, m, addr, control, p)
1023 struct socket *so;
1024 int req;
1025 struct mbuf *m, *addr, *control;
1026 struct proc *p;
1027 {
1028
1029 return udp_usrreq(so, req, m, addr, control);
1030 }
1031 #endif
1032
1033 /*ARGSUSED*/
1034 int
1035 udp_usrreq(so, req, m, addr, control)
1036 struct socket *so;
1037 int req;
1038 struct mbuf *m, *addr, *control;
1039 {
1040 struct inpcb *inp = sotoinpcb(so);
1041 int error = 0;
1042 int s;
1043
1044 if (req == PRU_CONTROL) {
1045 #ifdef INET6
1046 if (inp->inp_flags & INP_IPV6)
1047 return (in6_control(so, (u_long)m, (caddr_t)addr,
1048 (struct ifnet *)control, 0));
1049 else
1050 #endif /* INET6 */
1051 return (in_control(so, (u_long)m, (caddr_t)addr,
1052 (struct ifnet *)control));
1053 }
1054 if (inp == NULL && req != PRU_ATTACH) {
1055 error = EINVAL;
1056 goto release;
1057 }
1058 /*
1059 * Note: need to block udp_input while changing
1060 * the udp pcb queue and/or pcb addresses.
1061 */
1062 switch (req) {
1063
1064 case PRU_ATTACH:
1065 if (inp != NULL) {
1066 error = EINVAL;
1067 break;
1068 }
1069 s = splsoftnet();
1070 error = in_pcballoc(so, &udbtable);
1071 splx(s);
1072 if (error)
1073 break;
1074 error = soreserve(so, udp_sendspace, udp_recvspace);
1075 if (error)
1076 break;
1077 #ifdef INET6
1078 if (((struct inpcb *)so->so_pcb)->inp_flags & INP_IPV6)
1079 ((struct inpcb *) so->so_pcb)->inp_ipv6.ip6_hlim =
1080 ip6_defhlim;
1081 else
1082 #endif /* INET6 */
1083 ((struct inpcb *) so->so_pcb)->inp_ip.ip_ttl = ip_defttl;
1084 break;
1085
1086 case PRU_DETACH:
1087 udp_detach(inp);
1088 break;
1089
1090 case PRU_BIND:
1091 s = splsoftnet();
1092 #ifdef INET6
1093 if (inp->inp_flags & INP_IPV6)
1094 error = in6_pcbbind(inp, addr);
1095 else
1096 #endif
1097 error = in_pcbbind(inp, addr);
1098 splx(s);
1099 break;
1100
1101 case PRU_LISTEN:
1102 error = EOPNOTSUPP;
1103 break;
1104
1105 case PRU_CONNECT:
1106 #ifdef INET6
1107 if (inp->inp_flags & INP_IPV6) {
1108 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) {
1109 error = EISCONN;
1110 break;
1111 }
1112 s = splsoftnet();
1113 error = in6_pcbconnect(inp, addr);
1114 splx(s);
1115 } else
1116 #endif /* INET6 */
1117 {
1118 if (inp->inp_faddr.s_addr != INADDR_ANY) {
1119 error = EISCONN;
1120 break;
1121 }
1122 s = splsoftnet();
1123 error = in_pcbconnect(inp, addr);
1124 splx(s);
1125 }
1126
1127 if (error == 0)
1128 soisconnected(so);
1129 break;
1130
1131 case PRU_CONNECT2:
1132 error = EOPNOTSUPP;
1133 break;
1134
1135 case PRU_ACCEPT:
1136 error = EOPNOTSUPP;
1137 break;
1138
1139 case PRU_DISCONNECT:
1140 #ifdef INET6
1141 if (inp->inp_flags & INP_IPV6) {
1142 if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) {
1143 error = ENOTCONN;
1144 break;
1145 }
1146 } else
1147 #endif /* INET6 */
1148 {
1149 if (inp->inp_faddr.s_addr == INADDR_ANY) {
1150 error = ENOTCONN;
1151 break;
1152 }
1153 }
1154
1155 s = splsoftnet();
1156 in_pcbdisconnect(inp);
1157 #ifdef INET6
1158 if (inp->inp_flags & INP_IPV6)
1159 inp->inp_laddr6 = in6addr_any;
1160 else
1161 #endif /* INET6 */
1162 inp->inp_laddr.s_addr = INADDR_ANY;
1163
1164 splx(s);
1165 so->so_state &= ~SS_ISCONNECTED; /* XXX */
1166 break;
1167
1168 case PRU_SHUTDOWN:
1169 socantsendmore(so);
1170 break;
1171
1172 case PRU_SEND:
1173 #ifdef INET6
1174 if (inp->inp_flags & INP_IPV6)
1175 return (udp6_output(inp, m, addr, control));
1176 else
1177 return (udp_output(m, inp, addr, control));
1178 #else
1179 return (udp_output(m, inp, addr, control));
1180 #endif
1181
1182 case PRU_ABORT:
1183 soisdisconnected(so);
1184 udp_detach(inp);
1185 break;
1186
1187 case PRU_SOCKADDR:
1188 #ifdef INET6
1189 if (inp->inp_flags & INP_IPV6)
1190 in6_setsockaddr(inp, addr);
1191 else
1192 #endif /* INET6 */
1193 in_setsockaddr(inp, addr);
1194 break;
1195
1196 case PRU_PEERADDR:
1197 #ifdef INET6
1198 if (inp->inp_flags & INP_IPV6)
1199 in6_setpeeraddr(inp, addr);
1200 else
1201 #endif /* INET6 */
1202 in_setpeeraddr(inp, addr);
1203 break;
1204
1205 case PRU_SENSE:
1206 /*
1207 * stat: don't bother with a blocksize.
1208 */
1209 /*
1210 * Perhaps Path MTU might be returned for a connected
1211 * UDP socket in this case.
1212 */
1213 return (0);
1214
1215 case PRU_SENDOOB:
1216 case PRU_FASTTIMO:
1217 case PRU_SLOWTIMO:
1218 case PRU_PROTORCV:
1219 case PRU_PROTOSEND:
1220 error = EOPNOTSUPP;
1221 break;
1222
1223 case PRU_RCVD:
1224 case PRU_RCVOOB:
1225 return (EOPNOTSUPP); /* do not free mbuf's */
1226
1227 default:
1228 panic("udp_usrreq");
1229 }
1230
1231 release:
1232 if (control) {
1233 m_freem(control);
1234 }
1235 if (m)
1236 m_freem(m);
1237 return (error);
1238 }
1239
1240 static void
1241 udp_detach(inp)
1242 struct inpcb *inp;
1243 {
1244 int s = splsoftnet();
1245
1246 in_pcbdetach(inp);
1247 splx(s);
1248 }
1249
1250 /*
1251 * Sysctl for udp variables.
1252 */
1253 int
1254 udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
1255 int *name;
1256 u_int namelen;
1257 void *oldp;
1258 size_t *oldlenp;
1259 void *newp;
1260 size_t newlen;
1261 {
1262 /* All sysctl names at this level are terminal. */
1263 if (namelen != 1)
1264 return (ENOTDIR);
1265
1266 switch (name[0]) {
1267 case UDPCTL_BADDYNAMIC:
1268 return (sysctl_struct(oldp, oldlenp, newp, newlen,
1269 baddynamicports.udp, sizeof(baddynamicports.udp)));
1270 default:
1271 if (name[0] < UDPCTL_MAXID)
1272 return (sysctl_int_arr(udpctl_vars, name, namelen,
1273 oldp, oldlenp, newp, newlen));
1274 return (ENOPROTOOPT);
1275 }
1276 /* NOTREACHED */
1277 }
1278