Home | History | Annotate | Line # | Download | only in netinet6
udp6_usrreq.c revision 1.6
      1 /*	$NetBSD: udp6_usrreq.c,v 1.6 1999/07/30 10:35:38 itojun Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the project nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * Copyright (c) 1982, 1986, 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 #include "opt_ipsec.h"
     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 
     82 #include <net/if.h>
     83 #include <net/route.h>
     84 #include <net/if_types.h>
     85 
     86 #include <netinet/in.h>
     87 #include <netinet/in_var.h>
     88 #include <netinet6/ip6.h>
     89 #include <netinet6/in6_pcb.h>
     90 #include <netinet6/ip6_var.h>
     91 #include <netinet6/icmp6.h>
     92 #include <netinet6/udp6.h>
     93 #include <netinet6/udp6_var.h>
     94 
     95 #ifdef IPSEC
     96 #include <netinet6/ipsec.h>
     97 #endif /*IPSEC*/
     98 
     99 #include "faith.h"
    100 
    101 /*
    102  * UDP protocol inplementation.
    103  * Per RFC 768, August, 1980.
    104  */
    105 
    106 struct	in6pcb *udp6_last_in6pcb = &udb6;
    107 
    108 static	int in6_mcmatch __P((struct in6pcb *, struct in6_addr *, struct ifnet *));
    109 static	void udp6_detach __P((struct in6pcb *));
    110 static	void udp6_notify __P((struct in6pcb *, int));
    111 
    112 void
    113 udp6_init()
    114 {
    115 	udb6.in6p_next = udb6.in6p_prev = &udb6;
    116 }
    117 
    118 static int
    119 in6_mcmatch(in6p, ia6, ifp)
    120 	struct in6pcb *in6p;
    121 	register struct in6_addr *ia6;
    122 	struct ifnet *ifp;
    123 {
    124 	struct ip6_moptions *im6o = in6p->in6p_moptions;
    125 	struct in6_multi_mship *imm;
    126 
    127 	if (im6o == NULL)
    128 		return 0;
    129 
    130 	for (imm = im6o->im6o_memberships.lh_first; imm != NULL;
    131 	     imm = imm->i6mm_chain.le_next) {
    132 		if ((ifp == NULL ||
    133 		     imm->i6mm_maddr->in6m_ifp == ifp) &&
    134 		    IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
    135 				       ia6))
    136 			return 1;
    137 	}
    138 	return 0;
    139 }
    140 
    141 int
    142 udp6_input(mp, offp, proto)
    143 	struct mbuf **mp;
    144 	int *offp, proto;
    145 {
    146 	struct mbuf *m = *mp;
    147 	register struct ip6_hdr *ip6;
    148 	register struct udphdr *uh;
    149 	register struct in6pcb *in6p;
    150 	struct	mbuf *opts = 0;
    151 	int off = *offp;
    152 	int plen, ulen;
    153 	struct sockaddr_in6 udp_in6;
    154 
    155 #if defined(NFAITH) && 0 < NFAITH
    156 	if (m->m_pkthdr.rcvif) {
    157 		if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
    158 			/* send icmp6 host unreach? */
    159 			m_freem(m);
    160 			return IPPROTO_DONE;
    161 		}
    162 	}
    163 #endif
    164 	udp6stat.udp6s_ipackets++;
    165 
    166 	IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE);
    167 
    168 	ip6 = mtod(m, struct ip6_hdr *);
    169 	plen = ntohs(ip6->ip6_plen) - off + sizeof(*ip6);
    170 	uh = (struct udphdr *)((caddr_t)ip6 + off);
    171 	ulen = ntohs((u_short)uh->uh_ulen);
    172 
    173 	if (plen != ulen) {
    174 		udp6stat.udp6s_badlen++;
    175 		goto bad;
    176 	}
    177 
    178 	/*
    179 	 * Checksum extended UDP header and data.
    180 	 */
    181 	if (uh->uh_sum == 0)
    182 		udp6stat.udp6s_nosum++;
    183 	else if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) {
    184 		udp6stat.udp6s_badsum++;
    185 		goto bad;
    186 	}
    187 
    188 	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
    189 		struct	in6pcb *last;
    190 
    191 		/*
    192 		 * Deliver a multicast datagram to all sockets
    193 		 * for which the local and remote addresses and ports match
    194 		 * those of the incoming datagram.  This allows more than
    195 		 * one process to receive multicasts on the same port.
    196 		 * (This really ought to be done for unicast datagrams as
    197 		 * well, but that would cause problems with existing
    198 		 * applications that open both address-specific sockets and
    199 		 * a wildcard socket listening to the same port -- they would
    200 		 * end up receiving duplicates of every unicast datagram.
    201 		 * Those applications open the multiple sockets to overcome an
    202 		 * inadequacy of the UDP socket interface, but for backwards
    203 		 * compatibility we avoid the problem here rather than
    204 		 * fixing the interface.  Maybe 4.5BSD will remedy this?)
    205 		 */
    206 
    207 		/*
    208 		 * In a case that laddr should be set to the link-local
    209 		 * address (this happens in RIPng), the multicast address
    210 		 * specified in the received packet does not match with
    211 		 * laddr. To cure this situation, the matching is relaxed
    212 		 * if the receiving interface is the same as one specified
    213 		 * in the socket and if the destination multicast address
    214 		 * matches one of the multicast groups specified in the socket.
    215 		 */
    216 
    217 		/*
    218 		 * Construct sockaddr format source address.
    219 		 */
    220 		bzero(&udp_in6, sizeof(udp_in6));
    221 		udp_in6.sin6_len = sizeof(struct sockaddr_in6);
    222 		udp_in6.sin6_family = AF_INET6;
    223 		udp_in6.sin6_port = uh->uh_sport;
    224 		udp_in6.sin6_addr = ip6->ip6_src;
    225 		if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr))
    226 			udp_in6.sin6_addr.s6_addr16[1] = 0;
    227 		if (m->m_pkthdr.rcvif) {
    228 			if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr)) {
    229 				udp_in6.sin6_scope_id =
    230 					m->m_pkthdr.rcvif->if_index;
    231 			} else
    232 				udp_in6.sin6_scope_id = 0;
    233 		} else
    234 			udp_in6.sin6_scope_id = 0;
    235 		/*
    236 		 * KAME note: usually we drop udphdr from mbuf here.
    237 		 * We need udphdr for IPsec processing so we do that later.
    238 		 */
    239 
    240 		/*
    241 		 * Locate pcb(s) for datagram.
    242 		 * (Algorithm copied from raw_intr().)
    243 		 */
    244 		last = NULL;
    245 		for (in6p = udb6.in6p_next;
    246 		     in6p != &udb6;
    247 		     in6p = in6p->in6p_next) {
    248 			if (in6p->in6p_lport != uh->uh_dport)
    249 				continue;
    250 			if (!IN6_IS_ADDR_ANY(&in6p->in6p_laddr)) {
    251 				if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr,
    252 							&ip6->ip6_dst) &&
    253 				    !in6_mcmatch(in6p, &ip6->ip6_dst,
    254 						 m->m_pkthdr.rcvif))
    255 					continue;
    256 			}
    257 			if (!IN6_IS_ADDR_ANY(&in6p->in6p_faddr)) {
    258 				if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr,
    259 							&ip6->ip6_src) ||
    260 				   in6p->in6p_fport != uh->uh_sport)
    261 					continue;
    262 			}
    263 
    264 			if (last != NULL) {
    265 				struct	mbuf *n;
    266 
    267 #ifdef IPSEC
    268 				/*
    269 				 * Check AH/ESP integrity.
    270 				 */
    271 				if (last != NULL && ipsec6_in_reject(m, last)) {
    272 					ipsec6stat.in_polvio++;
    273 					/* do not inject data into pcb */
    274 				} else
    275 #endif /*IPSEC*/
    276 				if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
    277 					/*
    278 					 * KAME NOTE: do not
    279 					 * m_copy(m, offset, ...) above.
    280 					 * sbappendaddr() expects M_PKTHDR,
    281 					 * and m_copy() will copy M_PKTHDR
    282 					 * only if offset is 0.
    283 					 */
    284 					if (last->in6p_flags & IN6P_CONTROLOPTS) {
    285 						ip6_savecontrol(last, &opts,
    286 								ip6, n);
    287 					}
    288 
    289 					m_adj(m, off + sizeof(struct udphdr));
    290 					if (sbappendaddr(&last->in6p_socket->so_rcv,
    291 							(struct sockaddr *)&udp_in6,
    292 							n, opts) == 0) {
    293 						m_freem(n);
    294 						if (opts)
    295 							m_freem(opts);
    296 						udp6stat.udp6s_fullsock++;
    297 					} else
    298 						sorwakeup(last->in6p_socket);
    299 					opts = 0;
    300 				}
    301 			}
    302 			last = in6p;
    303 			/*
    304 			 * Don't look for additional matches if this one does
    305 			 * not have either the SO_REUSEPORT or SO_REUSEADDR
    306 			 * socket options set.  This heuristic avoids searching
    307 			 * through all pcbs in the common case of a non-shared
    308 			 * port.  It assumes that an application will never
    309 			 * clear these options after setting them.
    310 			 */
    311 			if ((last->in6p_socket->so_options &
    312 			     (SO_REUSEPORT|SO_REUSEADDR)) == 0)
    313 				break;
    314 		}
    315 
    316 		if (last == NULL) {
    317 			/*
    318 			 * No matching pcb found; discard datagram.
    319 			 * (No need to send an ICMP Port Unreachable
    320 			 * for a broadcast or multicast datgram.)
    321 			 */
    322 			udp6stat.udp6s_noport++;
    323 			udp6stat.udp6s_noportmcast++;
    324 			goto bad;
    325 		}
    326 #ifdef IPSEC
    327 		/*
    328 		 * Check AH/ESP integrity.
    329 		 */
    330 		if (last != NULL && ipsec6_in_reject(m, last)) {
    331 			ipsec6stat.in_polvio++;
    332 			goto bad;
    333 		}
    334 #endif /*IPSEC*/
    335 		if (last->in6p_flags & IN6P_CONTROLOPTS)
    336 			ip6_savecontrol(last, &opts, ip6, m);
    337 
    338 		m_adj(m, off + sizeof(struct udphdr));
    339 		if (sbappendaddr(&last->in6p_socket->so_rcv,
    340 				(struct sockaddr *)&udp_in6,
    341 				m, opts) == 0) {
    342 			udp6stat.udp6s_fullsock++;
    343 			goto bad;
    344 		}
    345 		sorwakeup(last->in6p_socket);
    346 		return IPPROTO_DONE;
    347 	}
    348 	/*
    349 	 * Locate pcb for datagram.
    350 	 */
    351 	in6p = udp6_last_in6pcb;
    352 	if (in6p->in6p_lport != uh->uh_dport ||
    353 	   in6p->in6p_fport != uh->uh_sport ||
    354 	   !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src) ||
    355 	   !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) {
    356 		in6p = in6_pcblookup(&udb6,
    357 				     &ip6->ip6_src, uh->uh_sport,
    358 				     &ip6->ip6_dst, uh->uh_dport,
    359 				     IN6PLOOKUP_WILDCARD);
    360 		if (in6p)
    361 			udp6_last_in6pcb = in6p;
    362 		udp6stat.udp6ps_pcbcachemiss++;
    363 	}
    364 	if (in6p == 0) {
    365 		udp6stat.udp6s_noport++;
    366 		if (m->m_flags & M_MCAST) {
    367 			printf("UDP6: M_MCAST is set in a unicast packet.\n");
    368 			udp6stat.udp6s_noportmcast++;
    369 			goto bad;
    370 		}
    371 		icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
    372 		return IPPROTO_DONE;
    373 	}
    374 #ifdef IPSEC
    375 	/*
    376 	 * Check AH/ESP integrity.
    377 	 */
    378 	if (in6p != NULL && ipsec6_in_reject(m, in6p)) {
    379 		ipsec6stat.in_polvio++;
    380 		goto bad;
    381 	}
    382 #endif /*IPSEC*/
    383 
    384 	/*
    385 	 * Construct sockaddr format source address.
    386 	 * Stuff source address and datagram in user buffer.
    387 	 */
    388 	bzero(&udp_in6, sizeof(udp_in6));
    389 	udp_in6.sin6_len = sizeof(struct sockaddr_in6);
    390 	udp_in6.sin6_family = AF_INET6;
    391 	udp_in6.sin6_port = uh->uh_sport;
    392 	udp_in6.sin6_addr = ip6->ip6_src;
    393 	if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr))
    394 		udp_in6.sin6_addr.s6_addr16[1] = 0;
    395 	if (m->m_pkthdr.rcvif) {
    396 		if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr))
    397 			udp_in6.sin6_scope_id = m->m_pkthdr.rcvif->if_index;
    398 		else
    399 			udp_in6.sin6_scope_id = 0;
    400 	} else
    401 		udp_in6.sin6_scope_id = 0;
    402 	if (in6p->in6p_flags & IN6P_CONTROLOPTS)
    403 		ip6_savecontrol(in6p, &opts, ip6, m);
    404 
    405 	m_adj(m, off + sizeof(struct udphdr));
    406 	if (sbappendaddr(&in6p->in6p_socket->so_rcv,
    407 			(struct sockaddr *)&udp_in6,
    408 			m, opts) == 0) {
    409 		udp6stat.udp6s_fullsock++;
    410 		goto bad;
    411 	}
    412 	sorwakeup(in6p->in6p_socket);
    413 	return IPPROTO_DONE;
    414 bad:
    415 	if (m)
    416 		m_freem(m);
    417 	if (opts)
    418 		m_freem(opts);
    419 	return IPPROTO_DONE;
    420 }
    421 
    422 /*
    423  * Notify a udp user of an asynchronous error;
    424  * just wake up so tat he can collect error status.
    425  */
    426 static	void
    427 udp6_notify(in6p, errno)
    428 	register struct in6pcb *in6p;
    429 	int errno;
    430 {
    431 	in6p->in6p_socket->so_error = errno;
    432 	sorwakeup(in6p->in6p_socket);
    433 	sowwakeup(in6p->in6p_socket);
    434 }
    435 
    436 void
    437 udp6_ctlinput(cmd, sa, ip6, m, off)
    438 	int cmd;
    439 	struct sockaddr *sa;
    440 	register struct ip6_hdr *ip6;
    441 	struct mbuf *m;
    442 	int off;
    443 {
    444 	register struct udphdr *uhp;
    445 	struct udphdr uh;
    446 
    447 #if 0
    448 	if (cmd == PRC_IFNEWADDR)
    449 		in6_mrejoin(&udb6);
    450 	else
    451 #endif
    452 	if (!PRC_IS_REDIRECT(cmd) &&
    453 	    ((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
    454 		return;
    455 	if (ip6) {
    456 		/*
    457 		 * XXX: We assume that when IPV6 is non NULL,
    458 		 * M and OFF are valid.
    459 		 */
    460 		if (m->m_len < off + sizeof(uh)) {
    461 			/*
    462 			 * this should be rare case,
    463 			 * so we compromise on this copy...
    464 			 */
    465 			m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
    466 			uhp = &uh;
    467 		} else
    468 			uhp = (struct udphdr *)(mtod(m, caddr_t) + off);
    469 		(void) in6_pcbnotify(&udb6, sa, uhp->uh_dport, &ip6->ip6_src,
    470 					uhp->uh_sport, cmd, udp6_notify);
    471 	} else {
    472 		(void) in6_pcbnotify(&udb6, sa, 0, &zeroin6_addr, 0, cmd,
    473 					udp6_notify);
    474 	}
    475 }
    476 
    477 int
    478 udp6_output(in6p, m, addr6, control)
    479 	register struct in6pcb *in6p;
    480 	register struct mbuf *m;
    481 	struct mbuf *addr6, *control;
    482 {
    483 	register int ulen = m->m_pkthdr.len;
    484 	int plen = sizeof(struct udphdr) + ulen;
    485 	struct ip6_hdr *ip6;
    486 	struct udphdr *udp6;
    487 	struct	in6_addr laddr6;
    488 	int s = 0, error = 0;
    489 	struct ip6_pktopts opt, *stickyopt = in6p->in6p_outputopts;
    490 	int priv = 0;
    491 	struct proc *p = curproc;	/* XXX */
    492 
    493 	if (p && !suser(p->p_ucred, &p->p_acflag))
    494 		priv = 1;
    495 	if (control) {
    496 		if ((error = ip6_setpktoptions(control, &opt, priv)) != 0)
    497 			goto release;
    498 		in6p->in6p_outputopts = &opt;
    499 	}
    500 
    501 	if (addr6) {
    502 		laddr6 = in6p->in6p_laddr;
    503 		if (!IN6_IS_ADDR_ANY(&in6p->in6p_faddr)) {
    504 			error = EISCONN;
    505 			goto release;
    506 		}
    507 		/*
    508 		 * Must block input while temporarily connected.
    509 		 */
    510 		s = splsoftnet();
    511 		error = in6_pcbconnect(in6p, addr6);
    512 		if (error) {
    513 			splx(s);
    514 			goto release;
    515 		}
    516 	} else {
    517 		if (IN6_IS_ADDR_ANY(&in6p->in6p_faddr)) {
    518 			error = ENOTCONN;
    519 			goto release;
    520 		}
    521 	}
    522 	/*
    523 	 * Calculate data length and get a mbuf
    524 	 * for UDP and IP6 headers.
    525 	 */
    526 	M_PREPEND(m, sizeof(struct ip6_hdr) + sizeof(struct udphdr), M_DONTWAIT);
    527 	if (m == 0) {
    528 		error = ENOBUFS;
    529 		goto release;
    530 	}
    531 
    532 	/*
    533 	 * Stuff checksum and output datagram.
    534 	 */
    535 	ip6 = mtod(m, struct ip6_hdr *);
    536 	ip6->ip6_flow	= in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK;
    537 	ip6->ip6_vfc 	= IPV6_VERSION;
    538 #if 0				/* ip6_plen will be filled in ip6_output. */
    539 	ip6->ip6_plen	= htons((u_short)plen);
    540 #endif
    541 	ip6->ip6_nxt	= IPPROTO_UDP;
    542 	ip6->ip6_hlim	= in6p->in6p_ip6.ip6_hlim; /* XXX */
    543 	ip6->ip6_src	= in6p->in6p_laddr;
    544 	ip6->ip6_dst	= in6p->in6p_faddr;
    545 
    546 	udp6 = (struct udphdr *)(ip6 + 1);
    547 	udp6->uh_sport = in6p->in6p_lport;
    548 	udp6->uh_dport = in6p->in6p_fport;
    549 	udp6->uh_ulen  = htons((u_short)plen);
    550 	udp6->uh_sum   = 0;
    551 
    552 	if ((udp6->uh_sum = in6_cksum(m, IPPROTO_UDP,
    553 					sizeof(struct ip6_hdr), plen)) == 0) {
    554 		udp6->uh_sum = 0xffff;
    555 	}
    556 
    557 	udp6stat.udp6s_opackets++;
    558 
    559 #ifdef IPSEC
    560 	m->m_pkthdr.rcvif = (struct ifnet *)in6p->in6p_socket;
    561 #endif /*IPSEC*/
    562 	error = ip6_output(m, in6p->in6p_outputopts, &in6p->in6p_route,
    563 			    0, in6p->in6p_moptions);
    564 
    565 	if (addr6) {
    566 		in6_pcbdisconnect(in6p);
    567 		in6p->in6p_laddr = laddr6;
    568 		splx(s);
    569 	}
    570 	goto releaseopt;
    571 
    572 release:
    573 	m_freem(m);
    574 
    575 releaseopt:
    576 	if (control) {
    577 		in6p->in6p_outputopts = stickyopt;
    578 		m_freem(control);
    579 	}
    580 	return(error);
    581 }
    582 
    583 extern	int udp6_sendspace;
    584 extern	int udp6_recvspace;
    585 
    586 int
    587 udp6_usrreq(so, req, m, addr6, control, p)
    588 	struct socket *so;
    589 	int req;
    590 	struct mbuf *m, *addr6, *control;
    591 	struct proc *p;
    592 {
    593 	struct	in6pcb *in6p = sotoin6pcb(so);
    594 	int	error = 0;
    595 	int	s;
    596 
    597 	/*
    598 	 * MAPPED_ADDR implementation info:
    599 	 *  Mapped addr support for PRU_CONTROL is not necessary.
    600 	 *  Because typical user of PRU_CONTROL is such as ifconfig,
    601 	 *  and they don't associate any addr to their socket.  Then
    602 	 *  socket family is only hint about the PRU_CONTROL'ed address
    603 	 *  family, especially when getting addrs from kernel.
    604 	 *  So AF_INET socket need to be used to control AF_INET addrs,
    605 	 *  and AF_INET6 socket for AF_INET6 addrs.
    606 	 */
    607 	if (req == PRU_CONTROL)
    608 		return(in6_control(so, (u_long)m, (caddr_t)addr6,
    609 				   (struct ifnet *)control, p));
    610 
    611 	if (in6p == NULL && req != PRU_ATTACH) {
    612 		error = EINVAL;
    613 		goto release;
    614 	}
    615 
    616 	switch (req) {
    617 	case PRU_ATTACH:
    618 		/*
    619 		 * MAPPED_ADDR implementation spec:
    620 		 *  Always attach for IPv6,
    621 		 *  and only when necessary for IPv4.
    622 		 */
    623 		if (in6p != NULL) {
    624 			error = EINVAL;
    625 			break;
    626 		}
    627 		s = splsoftnet();
    628 		error = in6_pcballoc(so, &udb6);
    629 		splx(s);
    630 		if (error)
    631 			break;
    632 		error = soreserve(so, udp6_sendspace, udp6_recvspace);
    633 		if (error)
    634 			break;
    635 		in6p = sotoin6pcb(so);
    636 		in6p->in6p_ip6.ip6_hlim = ip6_defhlim;
    637 		in6p->in6p_cksum = -1;	/* just to be sure */
    638 #ifdef IPSEC
    639 		error = ipsec_init_policy(&in6p->in6p_sp);
    640 #endif /*IPSEC*/
    641 		break;
    642 
    643 	case PRU_DETACH:
    644 		udp6_detach(in6p);
    645 		break;
    646 
    647 	case PRU_BIND:
    648 		s = splsoftnet();
    649 		error = in6_pcbbind(in6p, addr6);
    650 		splx(s);
    651 		break;
    652 
    653 	case PRU_LISTEN:
    654 		error = EOPNOTSUPP;
    655 		break;
    656 
    657 	case PRU_CONNECT:
    658 		if (!IN6_IS_ADDR_ANY(&in6p->in6p_faddr)) {
    659 			error = EISCONN;
    660 			break;
    661 		}
    662 		s = splsoftnet();
    663 		error = in6_pcbconnect(in6p, addr6);
    664 		if (ip6_auto_flowlabel) {
    665 			in6p->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
    666 			in6p->in6p_flowinfo |=
    667 				(htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
    668 		}
    669 		splx(s);
    670 		if (error == 0)
    671 			soisconnected(so);
    672 		break;
    673 
    674 	case PRU_CONNECT2:
    675 		error = EOPNOTSUPP;
    676 		break;
    677 
    678 	case PRU_ACCEPT:
    679 		error = EOPNOTSUPP;
    680 		break;
    681 
    682 	case PRU_DISCONNECT:
    683 		if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
    684 			error = ENOTCONN;
    685 			break;
    686 		}
    687 		s = splsoftnet();
    688 		in6_pcbdisconnect(in6p);
    689 		bzero((caddr_t)&in6p->in6p_laddr, sizeof(in6p->in6p_laddr));
    690 		splx(s);
    691 		so->so_state &= ~SS_ISCONNECTED;		/* XXX */
    692 		break;
    693 
    694 	case PRU_SHUTDOWN:
    695 		socantsendmore(so);
    696 		break;
    697 
    698 	case PRU_SEND:
    699 		return(udp6_output(in6p, m, addr6, control));
    700 
    701 	case PRU_ABORT:
    702 		soisdisconnected(so);
    703 		udp6_detach(in6p);
    704 		break;
    705 
    706 	case PRU_SOCKADDR:
    707 		in6_setsockaddr(in6p, addr6);
    708 		break;
    709 
    710 	case PRU_PEERADDR:
    711 		in6_setpeeraddr(in6p, addr6);
    712 		break;
    713 
    714 	case PRU_SENSE:
    715 		/*
    716 		 * stat: don't bother with a blocksize
    717 		 */
    718 		return(0);
    719 
    720 	case PRU_SENDOOB:
    721 	case PRU_FASTTIMO:
    722 	case PRU_SLOWTIMO:
    723 	case PRU_PROTORCV:
    724 	case PRU_PROTOSEND:
    725 		error = EOPNOTSUPP;
    726 		break;
    727 
    728 	case PRU_RCVD:
    729 	case PRU_RCVOOB:
    730 		return(EOPNOTSUPP);	/* do not free mbuf's */
    731 
    732 	default:
    733 		panic("udp6_usrreq");
    734 	}
    735 
    736 release:
    737 	if (control) {
    738 		printf("udp control data unexpectedly retained\n");
    739 		m_freem(control);
    740 	}
    741 	if (m)
    742 		m_freem(m);
    743 	return(error);
    744 }
    745 
    746 static void
    747 udp6_detach(in6p)
    748 	struct in6pcb *in6p;
    749 {
    750 	int	s = splsoftnet();
    751 
    752 	if (in6p == udp6_last_in6pcb)
    753 		udp6_last_in6pcb = &udb6;
    754 	in6_pcbdetach(in6p);
    755 	splx(s);
    756 }
    757 
    758 #ifdef __bsdi__
    759 int *udp6_sysvars[] = UDP6CTL_VARS;
    760 
    761 int
    762 udp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
    763 	int	*name;
    764 	u_int	namelen;
    765 	void	*oldp;
    766 	size_t	*oldlenp;
    767 	void	*newp;
    768 	size_t	newlen;
    769 {
    770 	if (name[0] >= UDP6CTL_MAXID)
    771 		return (EOPNOTSUPP);
    772 	switch (name[0]) {
    773 	case UDP6CTL_STATS:
    774 		return sysctl_rdtrunc(oldp, oldlenp, newp, &udp6stat,
    775 		    sizeof(udp6stat));
    776 
    777 	default:
    778 		return (sysctl_int_arr(udp6_sysvars, name, namelen,
    779 		    oldp, oldlenp, newp, newlen));
    780 	}
    781 }
    782 #endif /*__bsdi__*/
    783 
    784 #ifdef __NetBSD__
    785 #include <vm/vm.h>
    786 #include <sys/sysctl.h>
    787 
    788 int
    789 udp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
    790 	int *name;
    791 	u_int namelen;
    792 	void *oldp;
    793 	size_t *oldlenp;
    794 	void *newp;
    795 	size_t newlen;
    796 {
    797 	/* All sysctl names at this level are terminal. */
    798 	if (namelen != 1)
    799 		return ENOTDIR;
    800 
    801 	switch (name[0]) {
    802 
    803 	case UDP6CTL_SENDMAX:
    804 		return sysctl_int(oldp, oldlenp, newp, newlen,
    805 		    &udp6_sendspace);
    806 	case UDP6CTL_RECVSPACE:
    807 		return sysctl_int(oldp, oldlenp, newp, newlen,
    808 		    &udp6_recvspace);
    809 	default:
    810 		return ENOPROTOOPT;
    811 	}
    812 	/* NOTREACHED */
    813 }
    814 #endif
    815