1 /* $NetBSD: udp6_usrreq.c,v 1.91 2012/06/22 14:54:35 christos 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.91 2012/06/22 14:54:35 christos Exp $"); 66 67 #include "opt_inet.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/domain.h> 81 #include <sys/sysctl.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 <netinet/ip6.h> 96 #include <netinet6/ip6_var.h> 97 #include <netinet6/in6_pcb.h> 98 #include <netinet/icmp6.h> 99 #include <netinet6/udp6_var.h> 100 #include <netinet6/udp6_private.h> 101 #include <netinet6/ip6protosw.h> 102 #include <netinet/in_offload.h> 103 104 #include "faith.h" 105 #if defined(NFAITH) && NFAITH > 0 106 #include <net/if_faith.h> 107 #endif 108 109 /* 110 * UDP protocol implementation. 111 * Per RFC 768, August, 1980. 112 */ 113 114 extern struct inpcbtable udbtable; 115 116 percpu_t *udp6stat_percpu; 117 118 static void udp6_notify(struct in6pcb *, int); 119 static void sysctl_net_inet6_udp6_setup(struct sysctllog **); 120 121 void 122 udp6_init(void) 123 { 124 125 sysctl_net_inet6_udp6_setup(NULL); 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(struct in6pcb *in6p, int errno) 134 { 135 in6p->in6p_socket->so_error = errno; 136 sorwakeup(in6p->in6p_socket); 137 sowwakeup(in6p->in6p_socket); 138 } 139 140 void * 141 udp6_ctlinput(int cmd, const struct sockaddr *sa, void *d) 142 { 143 struct udphdr uh; 144 struct ip6_hdr *ip6; 145 const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *)sa; 146 struct mbuf *m; 147 int off; 148 void *cmdarg; 149 struct ip6ctlparam *ip6cp = NULL; 150 const struct sockaddr_in6 *sa6_src = NULL; 151 void (*notify)(struct in6pcb *, int) = udp6_notify; 152 struct udp_portonly { 153 u_int16_t uh_sport; 154 u_int16_t uh_dport; 155 } *uhp; 156 157 if (sa->sa_family != AF_INET6 || 158 sa->sa_len != sizeof(struct sockaddr_in6)) 159 return NULL; 160 161 if ((unsigned)cmd >= PRC_NCMDS) 162 return NULL; 163 if (PRC_IS_REDIRECT(cmd)) 164 notify = in6_rtchange, d = NULL; 165 else if (cmd == PRC_HOSTDEAD) 166 d = NULL; 167 else if (cmd == PRC_MSGSIZE) { 168 /* special code is present, see below */ 169 notify = in6_rtchange; 170 } 171 else if (inet6ctlerrmap[cmd] == 0) 172 return NULL; 173 174 /* if the parameter is from icmp6, decode it. */ 175 if (d != NULL) { 176 ip6cp = (struct ip6ctlparam *)d; 177 m = ip6cp->ip6c_m; 178 ip6 = ip6cp->ip6c_ip6; 179 off = ip6cp->ip6c_off; 180 cmdarg = ip6cp->ip6c_cmdarg; 181 sa6_src = ip6cp->ip6c_src; 182 } else { 183 m = NULL; 184 ip6 = NULL; 185 cmdarg = NULL; 186 sa6_src = &sa6_any; 187 off = 0; 188 } 189 190 if (ip6) { 191 /* 192 * XXX: We assume that when IPV6 is non NULL, 193 * M and OFF are valid. 194 */ 195 196 /* check if we can safely examine src and dst ports */ 197 if (m->m_pkthdr.len < off + sizeof(*uhp)) { 198 if (cmd == PRC_MSGSIZE) 199 icmp6_mtudisc_update((struct ip6ctlparam *)d, 0); 200 return NULL; 201 } 202 203 memset(&uh, 0, sizeof(uh)); 204 m_copydata(m, off, sizeof(*uhp), (void *)&uh); 205 206 if (cmd == PRC_MSGSIZE) { 207 int valid = 0; 208 209 /* 210 * Check to see if we have a valid UDP socket 211 * corresponding to the address in the ICMPv6 message 212 * payload. 213 */ 214 if (in6_pcblookup_connect(&udbtable, &sa6->sin6_addr, 215 uh.uh_dport, (const struct in6_addr *)&sa6_src->sin6_addr, 216 uh.uh_sport, 0, 0)) 217 valid++; 218 #if 0 219 /* 220 * As the use of sendto(2) is fairly popular, 221 * we may want to allow non-connected pcb too. 222 * But it could be too weak against attacks... 223 * We should at least check if the local address (= s) 224 * is really ours. 225 */ 226 else if (in6_pcblookup_bind(&udbtable, &sa6->sin6_addr, 227 uh.uh_dport, 0)) 228 valid++; 229 #endif 230 231 /* 232 * Depending on the value of "valid" and routing table 233 * size (mtudisc_{hi,lo}wat), we will: 234 * - recalculate the new MTU and create the 235 * corresponding routing entry, or 236 * - ignore the MTU change notification. 237 */ 238 icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); 239 240 /* 241 * regardless of if we called 242 * icmp6_mtudisc_update(), we need to call 243 * in6_pcbnotify(), to notify path MTU change 244 * to the userland (RFC3542), because some 245 * unconnected sockets may share the same 246 * destination and want to know the path MTU. 247 */ 248 } 249 250 (void) in6_pcbnotify(&udbtable, sa, uh.uh_dport, 251 (const struct sockaddr *)sa6_src, uh.uh_sport, cmd, cmdarg, 252 notify); 253 } else { 254 (void) in6_pcbnotify(&udbtable, sa, 0, 255 (const struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify); 256 } 257 return NULL; 258 } 259 260 int 261 udp6_ctloutput(int op, struct socket *so, struct sockopt *sopt) 262 { 263 int s; 264 int error = 0; 265 int family; 266 267 family = so->so_proto->pr_domain->dom_family; 268 269 s = splsoftnet(); 270 switch (family) { 271 #ifdef INET 272 case PF_INET: 273 if (sopt->sopt_level != IPPROTO_UDP) { 274 error = ip_ctloutput(op, so, sopt); 275 goto end; 276 } 277 break; 278 #endif 279 #ifdef INET6 280 case PF_INET6: 281 if (sopt->sopt_level != IPPROTO_UDP) { 282 error = ip6_ctloutput(op, so, sopt); 283 goto end; 284 } 285 break; 286 #endif 287 default: 288 error = EAFNOSUPPORT; 289 goto end; 290 } 291 error = EINVAL; 292 293 end: 294 splx(s); 295 return error; 296 } 297 298 299 extern int udp6_sendspace; 300 extern int udp6_recvspace; 301 302 int 303 udp6_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr6, 304 struct mbuf *control, struct lwp *l) 305 { 306 struct in6pcb *in6p = sotoin6pcb(so); 307 int error = 0; 308 int s; 309 310 /* 311 * MAPPED_ADDR implementation info: 312 * Mapped addr support for PRU_CONTROL is not necessary. 313 * Because typical user of PRU_CONTROL is such as ifconfig, 314 * and they don't associate any addr to their socket. Then 315 * socket family is only hint about the PRU_CONTROL'ed address 316 * family, especially when getting addrs from kernel. 317 * So AF_INET socket need to be used to control AF_INET addrs, 318 * and AF_INET6 socket for AF_INET6 addrs. 319 */ 320 if (req == PRU_CONTROL) 321 return in6_control(so, (u_long)m, (void *)addr6, 322 (struct ifnet *)control, l); 323 324 if (req == PRU_PURGEIF) { 325 mutex_enter(softnet_lock); 326 in6_pcbpurgeif0(&udbtable, (struct ifnet *)control); 327 in6_purgeif((struct ifnet *)control); 328 in6_pcbpurgeif(&udbtable, (struct ifnet *)control); 329 mutex_exit(softnet_lock); 330 return 0; 331 } 332 333 if (req == PRU_ATTACH) 334 sosetlock(so); 335 else if (in6p == NULL) { 336 error = EINVAL; 337 goto release; 338 } 339 340 switch (req) { 341 case PRU_ATTACH: 342 /* 343 * MAPPED_ADDR implementation spec: 344 * Always attach for IPv6, 345 * and only when necessary for IPv4. 346 */ 347 if (in6p != NULL) { 348 error = EINVAL; 349 break; 350 } 351 s = splsoftnet(); 352 error = in6_pcballoc(so, &udbtable); 353 splx(s); 354 if (error) 355 break; 356 error = soreserve(so, udp6_sendspace, udp6_recvspace); 357 if (error) 358 break; 359 in6p = sotoin6pcb(so); 360 in6p->in6p_cksum = -1; /* just to be sure */ 361 break; 362 363 case PRU_DETACH: 364 in6_pcbdetach(in6p); 365 break; 366 367 case PRU_BIND: 368 s = splsoftnet(); 369 error = in6_pcbbind(in6p, addr6, l); 370 splx(s); 371 break; 372 373 case PRU_CONNECT: 374 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 375 error = EISCONN; 376 break; 377 } 378 s = splsoftnet(); 379 error = in6_pcbconnect(in6p, addr6, l); 380 splx(s); 381 if (error == 0) 382 soisconnected(so); 383 break; 384 385 case PRU_DISCONNECT: 386 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 387 error = ENOTCONN; 388 break; 389 } 390 s = splsoftnet(); 391 in6_pcbdisconnect(in6p); 392 memset((void *)&in6p->in6p_laddr, 0, sizeof(in6p->in6p_laddr)); 393 splx(s); 394 so->so_state &= ~SS_ISCONNECTED; /* XXX */ 395 in6_pcbstate(in6p, IN6P_BOUND); /* XXX */ 396 break; 397 398 case PRU_SHUTDOWN: 399 socantsendmore(so); 400 break; 401 402 case PRU_SEND: 403 s = splsoftnet(); 404 error = udp6_output(in6p, m, addr6, control, l); 405 splx(s); 406 return error; 407 408 case PRU_ABORT: 409 soisdisconnected(so); 410 in6_pcbdetach(in6p); 411 break; 412 413 case PRU_SOCKADDR: 414 in6_setsockaddr(in6p, addr6); 415 break; 416 417 case PRU_PEERADDR: 418 in6_setpeeraddr(in6p, addr6); 419 break; 420 421 case PRU_SENSE: 422 /* 423 * stat: don't bother with a blocksize 424 */ 425 return 0; 426 427 case PRU_LISTEN: 428 case PRU_CONNECT2: 429 case PRU_ACCEPT: 430 case PRU_SENDOOB: 431 case PRU_FASTTIMO: 432 case PRU_SLOWTIMO: 433 case PRU_PROTORCV: 434 case PRU_PROTOSEND: 435 error = EOPNOTSUPP; 436 break; 437 438 case PRU_RCVD: 439 case PRU_RCVOOB: 440 return EOPNOTSUPP; /* do not free mbuf's */ 441 442 default: 443 panic("udp6_usrreq"); 444 } 445 446 release: 447 if (control != NULL) 448 m_freem(control); 449 if (m != NULL) 450 m_freem(m); 451 return error; 452 } 453 454 static int 455 sysctl_net_inet6_udp6_stats(SYSCTLFN_ARGS) 456 { 457 458 return (NETSTAT_SYSCTL(udp6stat_percpu, UDP6_NSTATS)); 459 } 460 461 static void 462 sysctl_net_inet6_udp6_setup(struct sysctllog **clog) 463 { 464 sysctl_createv(clog, 0, NULL, NULL, 465 CTLFLAG_PERMANENT, 466 CTLTYPE_NODE, "net", NULL, 467 NULL, 0, NULL, 0, 468 CTL_NET, CTL_EOL); 469 sysctl_createv(clog, 0, NULL, NULL, 470 CTLFLAG_PERMANENT, 471 CTLTYPE_NODE, "inet6", NULL, 472 NULL, 0, NULL, 0, 473 CTL_NET, PF_INET6, CTL_EOL); 474 sysctl_createv(clog, 0, NULL, NULL, 475 CTLFLAG_PERMANENT, 476 CTLTYPE_NODE, "udp6", 477 SYSCTL_DESCR("UDPv6 related settings"), 478 NULL, 0, NULL, 0, 479 CTL_NET, PF_INET6, IPPROTO_UDP, CTL_EOL); 480 481 sysctl_createv(clog, 0, NULL, NULL, 482 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 483 CTLTYPE_INT, "sendspace", 484 SYSCTL_DESCR("Default UDP send buffer size"), 485 NULL, 0, &udp6_sendspace, 0, 486 CTL_NET, PF_INET6, IPPROTO_UDP, UDP6CTL_SENDSPACE, 487 CTL_EOL); 488 sysctl_createv(clog, 0, NULL, NULL, 489 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 490 CTLTYPE_INT, "recvspace", 491 SYSCTL_DESCR("Default UDP receive buffer size"), 492 NULL, 0, &udp6_recvspace, 0, 493 CTL_NET, PF_INET6, IPPROTO_UDP, UDP6CTL_RECVSPACE, 494 CTL_EOL); 495 sysctl_createv(clog, 0, NULL, NULL, 496 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 497 CTLTYPE_INT, "do_loopback_cksum", 498 SYSCTL_DESCR("Perform UDP checksum on loopback"), 499 NULL, 0, &udp_do_loopback_cksum, 0, 500 CTL_NET, PF_INET6, IPPROTO_UDP, UDP6CTL_LOOPBACKCKSUM, 501 CTL_EOL); 502 sysctl_createv(clog, 0, NULL, NULL, 503 CTLFLAG_PERMANENT, 504 CTLTYPE_STRUCT, "pcblist", 505 SYSCTL_DESCR("UDP protocol control block list"), 506 sysctl_inpcblist, 0, &udbtable, 0, 507 CTL_NET, PF_INET6, IPPROTO_UDP, CTL_CREATE, 508 CTL_EOL); 509 sysctl_createv(clog, 0, NULL, NULL, 510 CTLFLAG_PERMANENT, 511 CTLTYPE_STRUCT, "stats", 512 SYSCTL_DESCR("UDPv6 statistics"), 513 sysctl_net_inet6_udp6_stats, 0, NULL, 0, 514 CTL_NET, PF_INET6, IPPROTO_UDP, UDP6CTL_STATS, 515 CTL_EOL); 516 } 517 518 void 519 udp6_statinc(u_int stat) 520 { 521 522 KASSERT(stat < UDP6_NSTATS); 523 UDP6_STATINC(stat); 524 } 525