1 /* $NetBSD: udp6_usrreq.c,v 1.56 2003/08/07 16:33:30 agc Exp $ */ 2 /* $KAME: udp6_usrreq.c,v 1.86 2001/05/27 17:33:00 itojun Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * 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 project 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 PROJECT 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 PROJECT 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 33 /* 34 * Copyright (c) 1982, 1986, 1989, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 * 61 * @(#)udp_var.h 8.1 (Berkeley) 6/10/93 62 */ 63 64 #include <sys/cdefs.h> 65 __KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.c,v 1.56 2003/08/07 16:33:30 agc Exp $"); 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 #include <sys/proc.h> 79 #include <sys/syslog.h> 80 #include <sys/sysctl.h> 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 <netinet/in_systm.h> 89 #include <netinet/ip.h> 90 #include <netinet/ip_var.h> 91 #include <netinet/in_pcb.h> 92 #include <netinet/udp.h> 93 #include <netinet/udp_var.h> 94 #include <netinet/ip6.h> 95 #include <netinet6/ip6_var.h> 96 #include <netinet6/in6_pcb.h> 97 #include <netinet/icmp6.h> 98 #include <netinet6/udp6_var.h> 99 #include <netinet6/ip6protosw.h> 100 101 #ifdef IPSEC 102 #include <netinet6/ipsec.h> 103 #endif /* IPSEC */ 104 105 #include "faith.h" 106 #if defined(NFAITH) && NFAITH > 0 107 #include <net/if_faith.h> 108 #endif 109 110 /* 111 * UDP protocol inplementation. 112 * Per RFC 768, August, 1980. 113 */ 114 115 struct in6pcb udb6; 116 struct in6pcb *udp6_last_in6pcb = &udb6; 117 struct udp6stat udp6stat; 118 119 static void udp6_detach __P((struct in6pcb *)); 120 static void udp6_notify __P((struct in6pcb *, int)); 121 122 void 123 udp6_init() 124 { 125 udb6.in6p_next = udb6.in6p_prev = &udb6; 126 } 127 128 /* 129 * Notify a udp user of an asynchronous error; 130 * just wake up so that he can collect error status. 131 */ 132 static void 133 udp6_notify(in6p, errno) 134 struct in6pcb *in6p; 135 int errno; 136 { 137 in6p->in6p_socket->so_error = errno; 138 sorwakeup(in6p->in6p_socket); 139 sowwakeup(in6p->in6p_socket); 140 } 141 142 void 143 udp6_ctlinput(cmd, sa, d) 144 int cmd; 145 struct sockaddr *sa; 146 void *d; 147 { 148 struct udphdr uh; 149 struct ip6_hdr *ip6; 150 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; 151 struct mbuf *m; 152 int off; 153 void *cmdarg; 154 struct ip6ctlparam *ip6cp = NULL; 155 const struct sockaddr_in6 *sa6_src = NULL; 156 void (*notify) __P((struct in6pcb *, int)) = udp6_notify; 157 struct udp_portonly { 158 u_int16_t uh_sport; 159 u_int16_t uh_dport; 160 } *uhp; 161 162 if (sa->sa_family != AF_INET6 || 163 sa->sa_len != sizeof(struct sockaddr_in6)) 164 return; 165 166 if ((unsigned)cmd >= PRC_NCMDS) 167 return; 168 if (PRC_IS_REDIRECT(cmd)) 169 notify = in6_rtchange, d = NULL; 170 else if (cmd == PRC_HOSTDEAD) 171 d = NULL; 172 else if (cmd == PRC_MSGSIZE) { 173 /* special code is present, see below */ 174 notify = in6_rtchange; 175 } 176 else if (inet6ctlerrmap[cmd] == 0) 177 return; 178 179 /* if the parameter is from icmp6, decode it. */ 180 if (d != NULL) { 181 ip6cp = (struct ip6ctlparam *)d; 182 m = ip6cp->ip6c_m; 183 ip6 = ip6cp->ip6c_ip6; 184 off = ip6cp->ip6c_off; 185 cmdarg = ip6cp->ip6c_cmdarg; 186 sa6_src = ip6cp->ip6c_src; 187 } else { 188 m = NULL; 189 ip6 = NULL; 190 cmdarg = NULL; 191 sa6_src = &sa6_any; 192 } 193 194 if (ip6) { 195 /* 196 * XXX: We assume that when IPV6 is non NULL, 197 * M and OFF are valid. 198 */ 199 200 /* check if we can safely examine src and dst ports */ 201 if (m->m_pkthdr.len < off + sizeof(*uhp)) { 202 if (cmd == PRC_MSGSIZE) 203 icmp6_mtudisc_update((struct ip6ctlparam *)d, 0); 204 return; 205 } 206 207 bzero(&uh, sizeof(uh)); 208 m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh); 209 210 if (cmd == PRC_MSGSIZE) { 211 int valid = 0; 212 213 /* 214 * Check to see if we have a valid UDP socket 215 * corresponding to the address in the ICMPv6 message 216 * payload. 217 */ 218 if (in6_pcblookup_connect(&udb6, &sa6->sin6_addr, 219 uh.uh_dport, (struct in6_addr *)&sa6_src->sin6_addr, 220 uh.uh_sport, 0)) 221 valid++; 222 #if 0 223 /* 224 * As the use of sendto(2) is fairly popular, 225 * we may want to allow non-connected pcb too. 226 * But it could be too weak against attacks... 227 * We should at least check if the local address (= s) 228 * is really ours. 229 */ 230 else if (in6_pcblookup_bind(&udb6, &sa6->sin6_addr, 231 uh.uh_dport, 0)) 232 valid++; 233 #endif 234 235 /* 236 * Depending on the value of "valid" and routing table 237 * size (mtudisc_{hi,lo}wat), we will: 238 * - recalculate the new MTU and create the 239 * corresponding routing entry, or 240 * - ignore the MTU change notification. 241 */ 242 icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); 243 244 /* 245 * regardless of if we called icmp6_mtudisc_update(), 246 * we need to call in6_pcbnotify(), to notify path 247 * MTU change to the userland (2292bis-02), because 248 * some unconnected sockets may share the same 249 * destination and want to know the path MTU. 250 */ 251 } 252 253 (void) in6_pcbnotify(&udb6, sa, uh.uh_dport, 254 (struct sockaddr *)sa6_src, uh.uh_sport, cmd, cmdarg, 255 notify); 256 } else { 257 (void) in6_pcbnotify(&udb6, sa, 0, (struct sockaddr *)sa6_src, 258 0, cmd, cmdarg, notify); 259 } 260 } 261 262 extern int udp6_sendspace; 263 extern int udp6_recvspace; 264 265 int 266 udp6_usrreq(so, req, m, addr6, control, p) 267 struct socket *so; 268 int req; 269 struct mbuf *m, *addr6, *control; 270 struct proc *p; 271 { 272 struct in6pcb *in6p = sotoin6pcb(so); 273 int error = 0; 274 int s; 275 276 /* 277 * MAPPED_ADDR implementation info: 278 * Mapped addr support for PRU_CONTROL is not necessary. 279 * Because typical user of PRU_CONTROL is such as ifconfig, 280 * and they don't associate any addr to their socket. Then 281 * socket family is only hint about the PRU_CONTROL'ed address 282 * family, especially when getting addrs from kernel. 283 * So AF_INET socket need to be used to control AF_INET addrs, 284 * and AF_INET6 socket for AF_INET6 addrs. 285 */ 286 if (req == PRU_CONTROL) 287 return (in6_control(so, (u_long)m, (caddr_t)addr6, 288 (struct ifnet *)control, p)); 289 290 if (req == PRU_PURGEIF) { 291 in6_pcbpurgeif0(&udb6, (struct ifnet *)control); 292 in6_purgeif((struct ifnet *)control); 293 in6_pcbpurgeif(&udb6, (struct ifnet *)control); 294 return (0); 295 } 296 297 if (in6p == NULL && req != PRU_ATTACH) { 298 error = EINVAL; 299 goto release; 300 } 301 302 switch (req) { 303 case PRU_ATTACH: 304 /* 305 * MAPPED_ADDR implementation spec: 306 * Always attach for IPv6, 307 * and only when necessary for IPv4. 308 */ 309 if (in6p != NULL) { 310 error = EINVAL; 311 break; 312 } 313 s = splsoftnet(); 314 error = in6_pcballoc(so, &udb6); 315 splx(s); 316 if (error) 317 break; 318 error = soreserve(so, udp6_sendspace, udp6_recvspace); 319 if (error) 320 break; 321 in6p = sotoin6pcb(so); 322 in6p->in6p_cksum = -1; /* just to be sure */ 323 break; 324 325 case PRU_DETACH: 326 udp6_detach(in6p); 327 break; 328 329 case PRU_BIND: 330 s = splsoftnet(); 331 error = in6_pcbbind(in6p, addr6, p); 332 splx(s); 333 break; 334 335 case PRU_LISTEN: 336 error = EOPNOTSUPP; 337 break; 338 339 case PRU_CONNECT: 340 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 341 error = EISCONN; 342 break; 343 } 344 s = splsoftnet(); 345 error = in6_pcbconnect(in6p, addr6); 346 if (ip6_auto_flowlabel) { 347 in6p->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK; 348 in6p->in6p_flowinfo |= 349 (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK); 350 } 351 splx(s); 352 if (error == 0) 353 soisconnected(so); 354 break; 355 356 case PRU_CONNECT2: 357 error = EOPNOTSUPP; 358 break; 359 360 case PRU_ACCEPT: 361 error = EOPNOTSUPP; 362 break; 363 364 case PRU_DISCONNECT: 365 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 366 error = ENOTCONN; 367 break; 368 } 369 s = splsoftnet(); 370 in6_pcbdisconnect(in6p); 371 bzero((caddr_t)&in6p->in6p_laddr, sizeof(in6p->in6p_laddr)); 372 splx(s); 373 so->so_state &= ~SS_ISCONNECTED; /* XXX */ 374 break; 375 376 case PRU_SHUTDOWN: 377 socantsendmore(so); 378 break; 379 380 case PRU_SEND: 381 return (udp6_output(in6p, m, addr6, control, p)); 382 383 case PRU_ABORT: 384 soisdisconnected(so); 385 udp6_detach(in6p); 386 break; 387 388 case PRU_SOCKADDR: 389 in6_setsockaddr(in6p, addr6); 390 break; 391 392 case PRU_PEERADDR: 393 in6_setpeeraddr(in6p, addr6); 394 break; 395 396 case PRU_SENSE: 397 /* 398 * stat: don't bother with a blocksize 399 */ 400 return (0); 401 402 case PRU_SENDOOB: 403 case PRU_FASTTIMO: 404 case PRU_SLOWTIMO: 405 case PRU_PROTORCV: 406 case PRU_PROTOSEND: 407 error = EOPNOTSUPP; 408 break; 409 410 case PRU_RCVD: 411 case PRU_RCVOOB: 412 return (EOPNOTSUPP); /* do not free mbuf's */ 413 414 default: 415 panic("udp6_usrreq"); 416 } 417 418 release: 419 if (control) 420 m_freem(control); 421 if (m) 422 m_freem(m); 423 return (error); 424 } 425 426 static void 427 udp6_detach(in6p) 428 struct in6pcb *in6p; 429 { 430 int s = splsoftnet(); 431 432 if (in6p == udp6_last_in6pcb) 433 udp6_last_in6pcb = &udb6; 434 in6_pcbdetach(in6p); 435 splx(s); 436 } 437 438 int 439 udp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 440 int *name; 441 u_int namelen; 442 void *oldp; 443 size_t *oldlenp; 444 void *newp; 445 size_t newlen; 446 { 447 /* All sysctl names at this level are terminal. */ 448 if (namelen != 1) 449 return ENOTDIR; 450 451 switch (name[0]) { 452 453 case UDP6CTL_SENDSPACE: 454 return sysctl_int(oldp, oldlenp, newp, newlen, 455 &udp6_sendspace); 456 case UDP6CTL_RECVSPACE: 457 return sysctl_int(oldp, oldlenp, newp, newlen, 458 &udp6_recvspace); 459 default: 460 return ENOPROTOOPT; 461 } 462 /* NOTREACHED */ 463 } 464