udp6_usrreq.c revision 1.1.2.3 1 /*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 /*
31 * Copyright (c) 1982, 1986, 1989, 1993
32 * The Regents of the University of California. All rights reserved.
33 *
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
36 * are met:
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 * 3. All advertising materials mentioning features or use of this software
43 * must display the following acknowledgement:
44 * This product includes software developed by the University of
45 * California, Berkeley and its contributors.
46 * 4. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 *
62 * @(#)udp_var.h 8.1 (Berkeley) 6/10/93
63 */
64
65 #ifdef __NetBSD__ /*XXX*/
66 #include "opt_ipsec.h"
67 #endif
68
69 #include <sys/param.h>
70 #include <sys/malloc.h>
71 #include <sys/mbuf.h>
72 #include <sys/protosw.h>
73 #include <sys/socket.h>
74 #include <sys/socketvar.h>
75 #include <sys/errno.h>
76 #include <sys/stat.h>
77 #include <sys/systm.h>
78 #ifdef __NetBSD__
79 #include <sys/proc.h>
80 #endif
81 #include <sys/syslog.h>
82
83 #include <net/if.h>
84 #include <net/route.h>
85 #include <net/if_types.h>
86
87 #include <netinet/in.h>
88 #include <netinet/in_var.h>
89 #include <netinet/in_systm.h>
90 #include <netinet/ip.h>
91 #include <netinet/ip_var.h>
92 #include <netinet/in_pcb.h>
93 #include <netinet/udp.h>
94 #include <netinet/udp_var.h>
95 #include <netinet6/ip6.h>
96 #include <netinet6/in6_pcb.h>
97 #include <netinet6/ip6_var.h>
98 #include <netinet6/icmp6.h>
99 #include <netinet6/udp6_var.h>
100 #include <netinet6/ip6protosw.h>
101
102 #ifdef IPSEC
103 #include <netinet6/ipsec.h>
104 #endif /*IPSEC*/
105
106 #include "faith.h"
107
108 /*
109 * UDP protocol inplementation.
110 * Per RFC 768, August, 1980.
111 */
112
113 struct in6pcb *udp6_last_in6pcb = &udb6;
114
115 #ifndef __NetBSD__
116 static int in6_mcmatch __P((struct in6pcb *, struct in6_addr *, struct ifnet *));
117 #endif
118 static void udp6_detach __P((struct in6pcb *));
119 static void udp6_notify __P((struct in6pcb *, int));
120
121 #ifdef __FreeBSD__
122 extern int udp_log_in_vain;
123 #endif
124
125 void
126 udp6_init()
127 {
128 udb6.in6p_next = udb6.in6p_prev = &udb6;
129 }
130
131 #ifndef __NetBSD__
132 static int
133 in6_mcmatch(in6p, ia6, ifp)
134 struct in6pcb *in6p;
135 register struct in6_addr *ia6;
136 struct ifnet *ifp;
137 {
138 struct ip6_moptions *im6o = in6p->in6p_moptions;
139 struct in6_multi_mship *imm;
140
141 if (im6o == NULL)
142 return 0;
143
144 for (imm = im6o->im6o_memberships.lh_first; imm != NULL;
145 imm = imm->i6mm_chain.le_next) {
146 if ((ifp == NULL ||
147 imm->i6mm_maddr->in6m_ifp == ifp) &&
148 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
149 ia6))
150 return 1;
151 }
152 return 0;
153 }
154
155 int
156 udp6_input(mp, offp, proto)
157 struct mbuf **mp;
158 int *offp, proto;
159 {
160 struct mbuf *m = *mp;
161 register struct ip6_hdr *ip6;
162 register struct udphdr *uh;
163 register struct in6pcb *in6p;
164 struct mbuf *opts = 0;
165 int off = *offp;
166 u_int32_t plen, ulen;
167 struct sockaddr_in6 udp_in6;
168
169 #if defined(NFAITH) && 0 < NFAITH
170 if (m->m_pkthdr.rcvif) {
171 if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
172 /* send icmp6 host unreach? */
173 m_freem(m);
174 return IPPROTO_DONE;
175 }
176 }
177 #endif
178 udp6stat.udp6s_ipackets++;
179
180 ip6 = mtod(m, struct ip6_hdr *);
181 /* check for jumbogram is done in ip6_input. we can trust pkthdr.len */
182 plen = m->m_pkthdr.len - off;
183 #ifndef PULLDOWN_TEST
184 IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE);
185 uh = (struct udphdr *)((caddr_t)ip6 + off);
186 #else
187 IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udhpdr));
188 if (uh == NULL) {
189 udp6stat.udp6s_hdrops++;
190 return IPPROTO_DONE;
191 }
192 #endif
193 ulen = ntohs((u_short)uh->uh_ulen);
194 if (ulen == 0 && plen > 0xffff) /* jumbogram */
195 ulen = plen;
196
197 if (plen != ulen) {
198 udp6stat.udp6s_badlen++;
199 goto bad;
200 }
201
202 /*
203 * Checksum extended UDP header and data.
204 */
205 if (uh->uh_sum == 0)
206 udp6stat.udp6s_nosum++;
207 else if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) {
208 udp6stat.udp6s_badsum++;
209 goto bad;
210 }
211
212 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
213 struct in6pcb *last;
214
215 /*
216 * Deliver a multicast datagram to all sockets
217 * for which the local and remote addresses and ports match
218 * those of the incoming datagram. This allows more than
219 * one process to receive multicasts on the same port.
220 * (This really ought to be done for unicast datagrams as
221 * well, but that would cause problems with existing
222 * applications that open both address-specific sockets and
223 * a wildcard socket listening to the same port -- they would
224 * end up receiving duplicates of every unicast datagram.
225 * Those applications open the multiple sockets to overcome an
226 * inadequacy of the UDP socket interface, but for backwards
227 * compatibility we avoid the problem here rather than
228 * fixing the interface. Maybe 4.5BSD will remedy this?)
229 */
230
231 /*
232 * In a case that laddr should be set to the link-local
233 * address (this happens in RIPng), the multicast address
234 * specified in the received packet does not match with
235 * laddr. To cure this situation, the matching is relaxed
236 * if the receiving interface is the same as one specified
237 * in the socket and if the destination multicast address
238 * matches one of the multicast groups specified in the socket.
239 */
240
241 /*
242 * Construct sockaddr format source address.
243 */
244 bzero(&udp_in6, sizeof(udp_in6));
245 udp_in6.sin6_len = sizeof(struct sockaddr_in6);
246 udp_in6.sin6_family = AF_INET6;
247 udp_in6.sin6_port = uh->uh_sport;
248 udp_in6.sin6_addr = ip6->ip6_src;
249 if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr))
250 udp_in6.sin6_addr.s6_addr16[1] = 0;
251 if (m->m_pkthdr.rcvif) {
252 if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr)) {
253 udp_in6.sin6_scope_id =
254 m->m_pkthdr.rcvif->if_index;
255 } else
256 udp_in6.sin6_scope_id = 0;
257 } else
258 udp_in6.sin6_scope_id = 0;
259 /*
260 * KAME note: usually we drop udphdr from mbuf here.
261 * We need udphdr for IPsec processing so we do that later.
262 */
263
264 /*
265 * Locate pcb(s) for datagram.
266 * (Algorithm copied from raw_intr().)
267 */
268 last = NULL;
269 for (in6p = udb6.in6p_next;
270 in6p != &udb6;
271 in6p = in6p->in6p_next) {
272 if (in6p->in6p_lport != uh->uh_dport)
273 continue;
274 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
275 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr,
276 &ip6->ip6_dst) &&
277 !in6_mcmatch(in6p, &ip6->ip6_dst,
278 m->m_pkthdr.rcvif))
279 continue;
280 }
281 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
282 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr,
283 &ip6->ip6_src) ||
284 in6p->in6p_fport != uh->uh_sport)
285 continue;
286 }
287
288 if (last != NULL) {
289 struct mbuf *n;
290
291 #ifdef IPSEC
292 /*
293 * Check AH/ESP integrity.
294 */
295 if (last != NULL && ipsec6_in_reject(m, last)) {
296 ipsec6stat.in_polvio++;
297 /* do not inject data into pcb */
298 } else
299 #endif /*IPSEC*/
300 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
301 /*
302 * KAME NOTE: do not
303 * m_copy(m, offset, ...) above.
304 * sbappendaddr() expects M_PKTHDR,
305 * and m_copy() will copy M_PKTHDR
306 * only if offset is 0.
307 */
308 if (last->in6p_flags & IN6P_CONTROLOPTS
309 #ifdef SO_TIMESTAMP
310 || last->in6p_socket->so_options & SO_TIMESTAMP
311 #endif
312 ) {
313 ip6_savecontrol(last, &opts,
314 ip6, n);
315 }
316
317 m_adj(n, off + sizeof(struct udphdr));
318 if (sbappendaddr(&last->in6p_socket->so_rcv,
319 (struct sockaddr *)&udp_in6,
320 n, opts) == 0) {
321 m_freem(n);
322 if (opts)
323 m_freem(opts);
324 udp6stat.udp6s_fullsock++;
325 } else
326 sorwakeup(last->in6p_socket);
327 opts = 0;
328 }
329 }
330 last = in6p;
331 /*
332 * Don't look for additional matches if this one does
333 * not have either the SO_REUSEPORT or SO_REUSEADDR
334 * socket options set. This heuristic avoids searching
335 * through all pcbs in the common case of a non-shared
336 * port. It assumes that an application will never
337 * clear these options after setting them.
338 */
339 if ((last->in6p_socket->so_options &
340 (SO_REUSEPORT|SO_REUSEADDR)) == 0)
341 break;
342 }
343
344 if (last == NULL) {
345 /*
346 * No matching pcb found; discard datagram.
347 * (No need to send an ICMP Port Unreachable
348 * for a broadcast or multicast datgram.)
349 */
350 udp6stat.udp6s_noport++;
351 udp6stat.udp6s_noportmcast++;
352 goto bad;
353 }
354 #ifdef IPSEC
355 /*
356 * Check AH/ESP integrity.
357 */
358 if (last != NULL && ipsec6_in_reject(m, last)) {
359 ipsec6stat.in_polvio++;
360 goto bad;
361 }
362 #endif /*IPSEC*/
363 if (last->in6p_flags & IN6P_CONTROLOPTS
364 #ifdef SO_TIMESTAMP
365 || last->in6p_socket->so_options & SO_TIMESTAMP
366 #endif
367 ) {
368 ip6_savecontrol(last, &opts, ip6, m);
369 }
370
371 m_adj(m, off + sizeof(struct udphdr));
372 if (sbappendaddr(&last->in6p_socket->so_rcv,
373 (struct sockaddr *)&udp_in6,
374 m, opts) == 0) {
375 udp6stat.udp6s_fullsock++;
376 goto bad;
377 }
378 sorwakeup(last->in6p_socket);
379 return IPPROTO_DONE;
380 }
381 /*
382 * Locate pcb for datagram.
383 */
384 in6p = udp6_last_in6pcb;
385 if (in6p->in6p_lport != uh->uh_dport ||
386 in6p->in6p_fport != uh->uh_sport ||
387 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src) ||
388 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) {
389 in6p = in6_pcblookup(&udb6,
390 &ip6->ip6_src, uh->uh_sport,
391 &ip6->ip6_dst, uh->uh_dport,
392 IN6PLOOKUP_WILDCARD);
393 if (in6p)
394 udp6_last_in6pcb = in6p;
395 udp6stat.udp6ps_pcbcachemiss++;
396 }
397 if (in6p == 0) {
398 #ifdef __FreeBSD__
399 if (udp_log_in_vain) {
400 char buf[INET6_ADDRSTRLEN];
401
402 strcpy(buf, ip6_sprintf(&ip6->ip6_dst));
403 log(LOG_INFO,
404 "Connection attempt to UDP %s:%d from %s:%d\n",
405 buf, ntohs(uh->uh_dport),
406 ip6_sprintf(&ip6->ip6_src), ntohs(uh->uh_sport));
407 }
408 #endif
409 udp6stat.udp6s_noport++;
410 if (m->m_flags & M_MCAST) {
411 printf("UDP6: M_MCAST is set in a unicast packet.\n");
412 udp6stat.udp6s_noportmcast++;
413 goto bad;
414 }
415 icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
416 return IPPROTO_DONE;
417 }
418 #ifdef IPSEC
419 /*
420 * Check AH/ESP integrity.
421 */
422 if (in6p != NULL && ipsec6_in_reject(m, in6p)) {
423 ipsec6stat.in_polvio++;
424 goto bad;
425 }
426 #endif /*IPSEC*/
427
428 /*
429 * Construct sockaddr format source address.
430 * Stuff source address and datagram in user buffer.
431 */
432 bzero(&udp_in6, sizeof(udp_in6));
433 udp_in6.sin6_len = sizeof(struct sockaddr_in6);
434 udp_in6.sin6_family = AF_INET6;
435 udp_in6.sin6_port = uh->uh_sport;
436 udp_in6.sin6_addr = ip6->ip6_src;
437 if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr))
438 udp_in6.sin6_addr.s6_addr16[1] = 0;
439 if (m->m_pkthdr.rcvif) {
440 if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr))
441 udp_in6.sin6_scope_id = m->m_pkthdr.rcvif->if_index;
442 else
443 udp_in6.sin6_scope_id = 0;
444 } else
445 udp_in6.sin6_scope_id = 0;
446 if (in6p->in6p_flags & IN6P_CONTROLOPTS
447 #ifdef SO_TIMESTAMP
448 || in6p->in6p_socket->so_options & SO_TIMESTAMP
449 #endif
450 ) {
451 ip6_savecontrol(in6p, &opts, ip6, m);
452 }
453
454 m_adj(m, off + sizeof(struct udphdr));
455 if (sbappendaddr(&in6p->in6p_socket->so_rcv,
456 (struct sockaddr *)&udp_in6,
457 m, opts) == 0) {
458 udp6stat.udp6s_fullsock++;
459 goto bad;
460 }
461 sorwakeup(in6p->in6p_socket);
462 return IPPROTO_DONE;
463 bad:
464 if (m)
465 m_freem(m);
466 if (opts)
467 m_freem(opts);
468 return IPPROTO_DONE;
469 }
470 #endif
471
472 /*
473 * Notify a udp user of an asynchronous error;
474 * just wake up so tat he can collect error status.
475 */
476 static void
477 udp6_notify(in6p, errno)
478 register struct in6pcb *in6p;
479 int errno;
480 {
481 in6p->in6p_socket->so_error = errno;
482 sorwakeup(in6p->in6p_socket);
483 sowwakeup(in6p->in6p_socket);
484 }
485
486 void
487 udp6_ctlinput(cmd, sa, d)
488 int cmd;
489 struct sockaddr *sa;
490 void *d;
491 {
492 register struct udphdr *uhp;
493 struct udphdr uh;
494 struct sockaddr_in6 sa6;
495 register struct ip6_hdr *ip6;
496 struct mbuf *m;
497 int off;
498
499 if (sa->sa_family != AF_INET6 ||
500 sa->sa_len != sizeof(struct sockaddr_in6))
501 return;
502
503 #if 0
504 if (cmd == PRC_IFNEWADDR)
505 in6_mrejoin(&udb6);
506 } else
507 #endif
508 if (!PRC_IS_REDIRECT(cmd) &&
509 ((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
510 return;
511
512 /* if the parameter is from icmp6, decode it. */
513 if (d != NULL) {
514 struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
515 m = ip6cp->ip6c_m;
516 ip6 = ip6cp->ip6c_ip6;
517 off = ip6cp->ip6c_off;
518 } else {
519 m = NULL;
520 ip6 = NULL;
521 }
522
523 /* translate addresses into internal form */
524 sa6 = *(struct sockaddr_in6 *)sa;
525 if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr))
526 sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
527
528 if (ip6) {
529 /*
530 * XXX: We assume that when IPV6 is non NULL,
531 * M and OFF are valid.
532 */
533 struct in6_addr s;
534
535 /* translate addresses into internal form */
536 memcpy(&s, &ip6->ip6_src, sizeof(s));
537 if (IN6_IS_ADDR_LINKLOCAL(&s))
538 s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
539
540 if (m->m_len < off + sizeof(uh)) {
541 /*
542 * this should be rare case,
543 * so we compromise on this copy...
544 */
545 m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
546 uhp = &uh;
547 } else
548 uhp = (struct udphdr *)(mtod(m, caddr_t) + off);
549 (void) in6_pcbnotify(&udb6, (struct sockaddr *)&sa6,
550 uhp->uh_dport, &s,
551 uhp->uh_sport, cmd, udp6_notify);
552 } else {
553 (void) in6_pcbnotify(&udb6, (struct sockaddr *)&sa6, 0,
554 &zeroin6_addr, 0, cmd, udp6_notify);
555 }
556 }
557
558 int
559 udp6_output(in6p, m, addr6, control)
560 register struct in6pcb *in6p;
561 register struct mbuf *m;
562 struct mbuf *addr6, *control;
563 {
564 register u_int32_t ulen = m->m_pkthdr.len;
565 u_int32_t plen = sizeof(struct udphdr) + ulen;
566 struct ip6_hdr *ip6;
567 struct udphdr *udp6;
568 struct in6_addr *laddr, *faddr;
569 u_short fport;
570 int error = 0;
571 struct ip6_pktopts opt, *stickyopt = in6p->in6p_outputopts;
572 int priv;
573 #if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
574 struct proc *p = curproc; /* XXX */
575 #endif
576 int af, hlen;
577 #ifdef __NetBSD__
578 struct ip *ip;
579 #endif
580
581 priv = 0;
582 #if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
583 if (p && !suser(p->p_ucred, &p->p_acflag))
584 priv = 1;
585 #else
586 if ((in6p->in6p_socket->so_state & SS_PRIV) != 0)
587 priv = 1;
588 #endif
589 if (control) {
590 if ((error = ip6_setpktoptions(control, &opt, priv)) != 0)
591 goto release;
592 in6p->in6p_outputopts = &opt;
593 }
594
595 if (addr6) {
596 /*
597 * IPv4 version of udp_output calls in_pcbconnect in this case,
598 * which needs splnet and affects performance.
599 * Since we saw no essential reason for calling in_pcbconnect,
600 * we get rid of such kind of logic, and call in6_selectsrc
601 * and In6_pcbsetport in order to fill in the local address
602 * and the local port.
603 */
604 struct sockaddr_in6 *sin6 = mtod(addr6, struct sockaddr_in6 *);
605
606 if (addr6->m_len != sizeof(*sin6)) {
607 error = EINVAL;
608 goto release;
609 }
610 if (sin6->sin6_family != AF_INET6) {
611 error = EAFNOSUPPORT;
612 goto release;
613 }
614 if (sin6->sin6_port == 0) {
615 error = EADDRNOTAVAIL;
616 goto release;
617 }
618
619 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
620 error = EISCONN;
621 goto release;
622 }
623
624 faddr = &sin6->sin6_addr;
625 fport = sin6->sin6_port; /* allow 0 port */
626 /*
627 * If the scope of the destination is link-local,
628 * embed the interface
629 * index in the address.
630 *
631 * XXX advanced-api value overrides sin6_scope_id
632 */
633 if (IN6_IS_ADDR_LINKLOCAL(faddr) ||
634 IN6_IS_ADDR_MC_LINKLOCAL(faddr)) {
635 struct ip6_pktopts *optp = in6p->in6p_outputopts;
636 struct in6_pktinfo *pi = NULL;
637 struct ifnet *oifp = NULL;
638 struct ip6_moptions *mopt = NULL;
639
640 /*
641 * XXX Boundary check is assumed to be already done in
642 * ip6_setpktoptions().
643 */
644 if (optp && (pi = optp->ip6po_pktinfo) &&
645 pi->ipi6_ifindex) {
646 faddr->s6_addr16[1] = htons(pi->ipi6_ifindex);
647 oifp = ifindex2ifnet[pi->ipi6_ifindex];
648 }
649 else if (IN6_IS_ADDR_MULTICAST(faddr) &&
650 (mopt = in6p->in6p_moptions) &&
651 mopt->im6o_multicast_ifp) {
652 oifp = mopt->im6o_multicast_ifp;
653 faddr->s6_addr16[1] = oifp->if_index;
654 } else if (sin6->sin6_scope_id) {
655 /* boundary check */
656 if (sin6->sin6_scope_id < 0
657 || if_index < sin6->sin6_scope_id) {
658 error = ENXIO; /* XXX EINVAL? */
659 goto release;
660 }
661 /* XXX */
662 faddr->s6_addr16[1] =
663 htons(sin6->sin6_scope_id & 0xffff);
664 }
665 }
666
667 if (!IN6_IS_ADDR_V4MAPPED(faddr)) {
668 laddr = in6_selectsrc(sin6, in6p->in6p_outputopts,
669 in6p->in6p_moptions,
670 &in6p->in6p_route,
671 &in6p->in6p_laddr, &error);
672 } else
673 laddr = &in6p->in6p_laddr; /*XXX*/
674 if (laddr == NULL) {
675 if (error == 0)
676 error = EADDRNOTAVAIL;
677 goto release;
678 }
679 if (in6p->in6p_lport == 0 &&
680 (error = in6_pcbsetport(laddr, in6p)) != 0)
681 goto release;
682 } else {
683 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
684 error = ENOTCONN;
685 goto release;
686 }
687 laddr = &in6p->in6p_laddr;
688 faddr = &in6p->in6p_faddr;
689 fport = in6p->in6p_fport;
690 }
691
692 if (!IN6_IS_ADDR_V4MAPPED(faddr)) {
693 af = AF_INET6;
694 hlen = sizeof(struct ip6_hdr);
695 } else {
696 af = AF_INET;
697 hlen = sizeof(struct ip);
698 }
699
700 /*
701 * Calculate data length and get a mbuf
702 * for UDP and IP6 headers.
703 */
704 M_PREPEND(m, hlen + sizeof(struct udphdr), M_DONTWAIT);
705 if (m == 0) {
706 error = ENOBUFS;
707 goto release;
708 }
709
710 /*
711 * Stuff checksum and output datagram.
712 */
713 udp6 = (struct udphdr *)(mtod(m, caddr_t) + hlen);
714 udp6->uh_sport = in6p->in6p_lport; /* lport is always set in the PCB */
715 udp6->uh_dport = fport;
716 if (plen <= 0xffff)
717 udp6->uh_ulen = htons((u_short)plen);
718 else
719 udp6->uh_ulen = 0;
720 udp6->uh_sum = 0;
721
722 switch (af) {
723 case AF_INET6:
724 ip6 = mtod(m, struct ip6_hdr *);
725 ip6->ip6_flow = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK;
726 ip6->ip6_vfc = IPV6_VERSION;
727 #if 0 /* ip6_plen will be filled in ip6_output. */
728 ip6->ip6_plen = htons((u_short)plen);
729 #endif
730 ip6->ip6_nxt = IPPROTO_UDP;
731 ip6->ip6_hlim = in6_selecthlim(in6p,
732 in6p->in6p_route.ro_rt ?
733 in6p->in6p_route.ro_rt->rt_ifp : NULL);
734 ip6->ip6_src = *laddr;
735 ip6->ip6_dst = *faddr;
736
737 if ((udp6->uh_sum = in6_cksum(m, IPPROTO_UDP,
738 sizeof(struct ip6_hdr), plen)) == 0) {
739 udp6->uh_sum = 0xffff;
740 }
741
742 udp6stat.udp6s_opackets++;
743 #ifdef IPSEC
744 m->m_pkthdr.rcvif = (struct ifnet *)in6p->in6p_socket;
745 #endif /*IPSEC*/
746 error = ip6_output(m, in6p->in6p_outputopts, &in6p->in6p_route,
747 0, in6p->in6p_moptions, NULL);
748 break;
749 #ifdef __NetBSD__
750 case AF_INET:
751 /* can't transmit jumbogram over IPv4 */
752 if (plen > 0xffff) {
753 error = EMSGSIZE;
754 goto release;
755 }
756
757 ip = mtod(m, struct ip *);
758
759 ip->ip_len = plen;
760 ip->ip_p = IPPROTO_UDP;
761 ip->ip_ttl = in6p->in6p_hops; /*XXX*/
762 ip->ip_tos = 0; /*XXX*/
763 bcopy(&laddr->s6_addr[12], &ip->ip_src, sizeof(ip->ip_src));
764 bcopy(&faddr->s6_addr[12], &ip->ip_dst, sizeof(ip->ip_dst));
765
766 udp6->uh_sum = 0;
767 if ((udp6->uh_sum = in_cksum(m, ulen)) == 0)
768 udp6->uh_sum = 0xffff;
769
770 udpstat.udps_opackets++;
771 #ifdef IPSEC
772 m->m_pkthdr.rcvif = NULL; /*XXX*/
773 #endif /*IPSEC*/
774 error = ip_output(m, NULL, &in6p->in6p_route, 0 /*XXX*/);
775 #else
776 error = EAFNOSUPPORT;
777 goto release;
778 #endif
779 break;
780 }
781 goto releaseopt;
782
783 release:
784 m_freem(m);
785
786 releaseopt:
787 if (control) {
788 in6p->in6p_outputopts = stickyopt;
789 m_freem(control);
790 }
791 return(error);
792 }
793
794 extern int udp6_sendspace;
795 extern int udp6_recvspace;
796
797 int
798 #if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
799 udp6_usrreq(so, req, m, addr6, control, p)
800 struct socket *so;
801 int req;
802 struct mbuf *m, *addr6, *control;
803 struct proc *p;
804 #else
805 udp6_usrreq(so, req, m, addr6, control)
806 struct socket *so;
807 int req;
808 struct mbuf *m, *addr6, *control;
809 #endif
810 {
811 struct in6pcb *in6p = sotoin6pcb(so);
812 int error = 0;
813 int s;
814
815 /*
816 * MAPPED_ADDR implementation info:
817 * Mapped addr support for PRU_CONTROL is not necessary.
818 * Because typical user of PRU_CONTROL is such as ifconfig,
819 * and they don't associate any addr to their socket. Then
820 * socket family is only hint about the PRU_CONTROL'ed address
821 * family, especially when getting addrs from kernel.
822 * So AF_INET socket need to be used to control AF_INET addrs,
823 * and AF_INET6 socket for AF_INET6 addrs.
824 */
825 if (req == PRU_CONTROL)
826 return(in6_control(so, (u_long)m, (caddr_t)addr6,
827 (struct ifnet *)control
828 #if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
829 , p
830 #endif
831 ));
832
833 if (in6p == NULL && req != PRU_ATTACH) {
834 error = EINVAL;
835 goto release;
836 }
837
838 switch (req) {
839 case PRU_ATTACH:
840 /*
841 * MAPPED_ADDR implementation spec:
842 * Always attach for IPv6,
843 * and only when necessary for IPv4.
844 */
845 if (in6p != NULL) {
846 error = EINVAL;
847 break;
848 }
849 #ifdef __NetBSD__
850 s = splsoftnet();
851 #else
852 s = splnet();
853 #endif
854 error = in6_pcballoc(so, &udb6);
855 splx(s);
856 if (error)
857 break;
858 error = soreserve(so, udp6_sendspace, udp6_recvspace);
859 if (error)
860 break;
861 in6p = sotoin6pcb(so);
862 in6p->in6p_cksum = -1; /* just to be sure */
863 #ifdef IPSEC
864 error = ipsec_init_policy(so, &in6p->in6p_sp);
865 if (error != 0) {
866 in6_pcbdetach(in6p);
867 break;
868 }
869 #endif /*IPSEC*/
870 break;
871
872 case PRU_DETACH:
873 udp6_detach(in6p);
874 break;
875
876 case PRU_BIND:
877 #ifdef __NetBSD__
878 s = splsoftnet();
879 #else
880 s = splnet();
881 #endif
882 error = in6_pcbbind(in6p, addr6);
883 splx(s);
884 break;
885
886 case PRU_LISTEN:
887 error = EOPNOTSUPP;
888 break;
889
890 case PRU_CONNECT:
891 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
892 error = EISCONN;
893 break;
894 }
895 #ifdef __NetBSD__
896 s = splsoftnet();
897 #else
898 s = splnet();
899 #endif
900 error = in6_pcbconnect(in6p, addr6);
901 if (ip6_auto_flowlabel) {
902 in6p->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
903 in6p->in6p_flowinfo |=
904 (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
905 }
906 splx(s);
907 if (error == 0)
908 soisconnected(so);
909 break;
910
911 case PRU_CONNECT2:
912 error = EOPNOTSUPP;
913 break;
914
915 case PRU_ACCEPT:
916 error = EOPNOTSUPP;
917 break;
918
919 case PRU_DISCONNECT:
920 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
921 error = ENOTCONN;
922 break;
923 }
924 #ifdef __NetBSD__
925 s = splsoftnet();
926 #else
927 s = splnet();
928 #endif
929 in6_pcbdisconnect(in6p);
930 bzero((caddr_t)&in6p->in6p_laddr, sizeof(in6p->in6p_laddr));
931 splx(s);
932 so->so_state &= ~SS_ISCONNECTED; /* XXX */
933 break;
934
935 case PRU_SHUTDOWN:
936 socantsendmore(so);
937 break;
938
939 case PRU_SEND:
940 return(udp6_output(in6p, m, addr6, control));
941
942 case PRU_ABORT:
943 soisdisconnected(so);
944 udp6_detach(in6p);
945 break;
946
947 case PRU_SOCKADDR:
948 in6_setsockaddr(in6p, addr6);
949 break;
950
951 case PRU_PEERADDR:
952 in6_setpeeraddr(in6p, addr6);
953 break;
954
955 case PRU_SENSE:
956 /*
957 * stat: don't bother with a blocksize
958 */
959 return(0);
960
961 case PRU_SENDOOB:
962 case PRU_FASTTIMO:
963 case PRU_SLOWTIMO:
964 case PRU_PROTORCV:
965 case PRU_PROTOSEND:
966 error = EOPNOTSUPP;
967 break;
968
969 case PRU_RCVD:
970 case PRU_RCVOOB:
971 return(EOPNOTSUPP); /* do not free mbuf's */
972
973 default:
974 panic("udp6_usrreq");
975 }
976
977 release:
978 if (control) {
979 printf("udp control data unexpectedly retained\n");
980 m_freem(control);
981 }
982 if (m)
983 m_freem(m);
984 return(error);
985 }
986
987 static void
988 udp6_detach(in6p)
989 struct in6pcb *in6p;
990 {
991 #ifdef __NetBSD__
992 int s = splsoftnet();
993 #else
994 int s = splnet();
995 #endif
996
997 if (in6p == udp6_last_in6pcb)
998 udp6_last_in6pcb = &udb6;
999 in6_pcbdetach(in6p);
1000 splx(s);
1001 }
1002
1003 #ifdef __bsdi__
1004 int *udp6_sysvars[] = UDP6CTL_VARS;
1005
1006 int
1007 udp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
1008 int *name;
1009 u_int namelen;
1010 void *oldp;
1011 size_t *oldlenp;
1012 void *newp;
1013 size_t newlen;
1014 {
1015 if (name[0] >= UDP6CTL_MAXID)
1016 return (EOPNOTSUPP);
1017 switch (name[0]) {
1018 case UDP6CTL_STATS:
1019 return sysctl_rdtrunc(oldp, oldlenp, newp, &udp6stat,
1020 sizeof(udp6stat));
1021
1022 default:
1023 return (sysctl_int_arr(udp6_sysvars, name, namelen,
1024 oldp, oldlenp, newp, newlen));
1025 }
1026 }
1027 #endif /*__bsdi__*/
1028
1029 #ifdef __NetBSD__
1030 #include <vm/vm.h>
1031 #include <sys/sysctl.h>
1032
1033 int
1034 udp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
1035 int *name;
1036 u_int namelen;
1037 void *oldp;
1038 size_t *oldlenp;
1039 void *newp;
1040 size_t newlen;
1041 {
1042 /* All sysctl names at this level are terminal. */
1043 if (namelen != 1)
1044 return ENOTDIR;
1045
1046 switch (name[0]) {
1047
1048 case UDP6CTL_SENDMAX:
1049 return sysctl_int(oldp, oldlenp, newp, newlen,
1050 &udp6_sendspace);
1051 case UDP6CTL_RECVSPACE:
1052 return sysctl_int(oldp, oldlenp, newp, newlen,
1053 &udp6_recvspace);
1054 default:
1055 return ENOPROTOOPT;
1056 }
1057 /* NOTREACHED */
1058 }
1059 #endif
1060