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