1 2 /* 3 * ng_ksocket.c 4 * 5 * Copyright (c) 1996-1999 Whistle Communications, Inc. 6 * All rights reserved. 7 * 8 * Subject to the following obligations and disclaimer of warranty, use and 9 * redistribution of this software, in source or object code forms, with or 10 * without modifications are expressly permitted by Whistle Communications; 11 * provided, however, that: 12 * 1. Any and all reproductions of the source or object code must include the 13 * copyright notice above and the following disclaimer of warranties; and 14 * 2. No rights are granted, in any manner or form, to use Whistle 15 * Communications, Inc. trademarks, including the mark "WHISTLE 16 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 17 * such appears in the above copyright notice or in the software. 18 * 19 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 20 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 21 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 22 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 24 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 25 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 26 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 27 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 28 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 29 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 30 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 31 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 35 * OF SUCH DAMAGE. 36 * 37 * Author: Archie Cobbs <archie@freebsd.org> 38 * 39 * $FreeBSD: src/sys/netgraph/ng_ksocket.c,v 1.5.2.14 2003/08/24 08:24:38 hsu Exp $ 40 * $Whistle: ng_ksocket.c,v 1.1 1999/11/16 20:04:40 archie Exp $ 41 */ 42 43 /* 44 * Kernel socket node type. This node type is basically a kernel-mode 45 * version of a socket... kindof like the reverse of the socket node type. 46 */ 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/kernel.h> 51 #include <sys/mbuf.h> 52 #include <sys/proc.h> 53 #include <sys/malloc.h> 54 #include <sys/ctype.h> 55 #include <sys/protosw.h> 56 #include <sys/errno.h> 57 #include <sys/fcntl.h> 58 #include <sys/socket.h> 59 #include <sys/socketvar.h> 60 #include <sys/socketops.h> 61 #include <sys/uio.h> 62 #include <sys/un.h> 63 64 #include <sys/thread2.h> 65 #include <sys/socketvar2.h> 66 67 #include <netgraph/ng_message.h> 68 #include <netgraph/netgraph.h> 69 #include <netgraph/ng_parse.h> 70 #include "ng_ksocket.h" 71 72 #include <netinet/in.h> 73 74 #define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0)) 75 #define SADATA_OFFSET (OFFSETOF(struct sockaddr, sa_data)) 76 77 /* Node private data */ 78 struct ng_ksocket_private { 79 node_p node; 80 hook_p hook; 81 struct socket *so; 82 LIST_HEAD(, ng_ksocket_private) embryos; 83 LIST_ENTRY(ng_ksocket_private) siblings; 84 u_int32_t flags; 85 u_int32_t response_token; 86 char response_addr[NG_PATHSIZ]; 87 }; 88 typedef struct ng_ksocket_private *priv_p; 89 90 /* Flags for priv_p */ 91 #define KSF_CONNECTING 0x00000001 /* Waiting for connection complete */ 92 #define KSF_ACCEPTING 0x00000002 /* Waiting for accept complete */ 93 #define KSF_EOFSEEN 0x00000004 /* Have sent 0-length EOF mbuf */ 94 #define KSF_CLONED 0x00000008 /* Cloned from an accepting socket */ 95 #define KSF_EMBRYONIC 0x00000010 /* Cloned node with no hooks yet */ 96 #define KSF_SENDING 0x00000020 /* Sending on socket */ 97 98 /* Internal commands which we send to ourselves */ 99 #define NGM_KSOCKET_INTERNAL_COOKIE (NGM_KSOCKET_COOKIE + 1) 100 101 enum { 102 NGM_KSOCKET_INTERNAL_UPCALL = 1 103 }; 104 105 /* Netgraph node methods */ 106 static ng_constructor_t ng_ksocket_constructor; 107 static ng_rcvmsg_t ng_ksocket_rcvmsg; 108 static ng_shutdown_t ng_ksocket_rmnode; 109 static ng_newhook_t ng_ksocket_newhook; 110 static ng_rcvdata_t ng_ksocket_rcvdata; 111 static ng_disconnect_t ng_ksocket_disconnect; 112 113 /* Alias structure */ 114 struct ng_ksocket_alias { 115 const char *name; 116 const int value; 117 const int family; 118 }; 119 120 /* Protocol family aliases */ 121 static const struct ng_ksocket_alias ng_ksocket_families[] = { 122 { "local", PF_LOCAL }, 123 { "inet", PF_INET }, 124 { "inet6", PF_INET6 }, 125 { "atm", PF_ATM }, 126 { NULL, -1 }, 127 }; 128 129 /* Socket type aliases */ 130 static const struct ng_ksocket_alias ng_ksocket_types[] = { 131 { "stream", SOCK_STREAM }, 132 { "dgram", SOCK_DGRAM }, 133 { "raw", SOCK_RAW }, 134 { "rdm", SOCK_RDM }, 135 { "seqpacket", SOCK_SEQPACKET }, 136 { NULL, -1 }, 137 }; 138 139 /* Protocol aliases */ 140 static const struct ng_ksocket_alias ng_ksocket_protos[] = { 141 { "ip", IPPROTO_IP, PF_INET }, 142 { "raw", IPPROTO_RAW, PF_INET }, 143 { "icmp", IPPROTO_ICMP, PF_INET }, 144 { "igmp", IPPROTO_IGMP, PF_INET }, 145 { "tcp", IPPROTO_TCP, PF_INET }, 146 { "udp", IPPROTO_UDP, PF_INET }, 147 { "gre", IPPROTO_GRE, PF_INET }, 148 { "esp", IPPROTO_ESP, PF_INET }, 149 { "ah", IPPROTO_AH, PF_INET }, 150 { "swipe", IPPROTO_SWIPE, PF_INET }, 151 { "encap", IPPROTO_ENCAP, PF_INET }, 152 { "divert", IPPROTO_DIVERT, PF_INET }, 153 { "pim", IPPROTO_PIM, PF_INET }, 154 { NULL, -1 }, 155 }; 156 157 /* Helper functions */ 158 static int ng_ksocket_check_accept(priv_p); 159 static void ng_ksocket_finish_accept(priv_p, struct ng_mesg **); 160 static void ng_ksocket_incoming(struct socket *so, void *arg, int waitflag); 161 static int ng_ksocket_parse(const struct ng_ksocket_alias *aliases, 162 const char *s, int family); 163 164 /************************************************************************ 165 STRUCT SOCKADDR PARSE TYPE 166 ************************************************************************/ 167 168 /* Get the length of the data portion of a generic struct sockaddr */ 169 static int 170 ng_parse_generic_sockdata_getLength(const struct ng_parse_type *type, 171 const u_char *start, const u_char *buf) 172 { 173 const struct sockaddr *sa; 174 175 sa = (const struct sockaddr *)(buf - SADATA_OFFSET); 176 return (sa->sa_len < SADATA_OFFSET) ? 0 : sa->sa_len - SADATA_OFFSET; 177 } 178 179 /* Type for the variable length data portion of a generic struct sockaddr */ 180 static const struct ng_parse_type ng_ksocket_generic_sockdata_type = { 181 &ng_parse_bytearray_type, 182 &ng_parse_generic_sockdata_getLength 183 }; 184 185 /* Type for a generic struct sockaddr */ 186 static const struct ng_parse_struct_field 187 ng_parse_generic_sockaddr_type_fields[] = { 188 { "len", &ng_parse_uint8_type }, 189 { "family", &ng_parse_uint8_type }, 190 { "data", &ng_ksocket_generic_sockdata_type }, 191 { NULL } 192 }; 193 static const struct ng_parse_type ng_ksocket_generic_sockaddr_type = { 194 &ng_parse_struct_type, 195 &ng_parse_generic_sockaddr_type_fields 196 }; 197 198 /* Convert a struct sockaddr from ASCII to binary. If its a protocol 199 family that we specially handle, do that, otherwise defer to the 200 generic parse type ng_ksocket_generic_sockaddr_type. */ 201 static int 202 ng_ksocket_sockaddr_parse(const struct ng_parse_type *type, 203 const char *s, int *off, const u_char *const start, 204 u_char *const buf, int *buflen) 205 { 206 struct sockaddr *const sa = (struct sockaddr *)buf; 207 enum ng_parse_token tok; 208 char fambuf[32]; 209 int family, len; 210 char *t; 211 212 /* If next token is a left curly brace, use generic parse type */ 213 if ((tok = ng_parse_get_token(s, off, &len)) == T_LBRACE) { 214 return (*ng_ksocket_generic_sockaddr_type.supertype->parse) 215 (&ng_ksocket_generic_sockaddr_type, 216 s, off, start, buf, buflen); 217 } 218 219 /* Get socket address family followed by a slash */ 220 while (isspace(s[*off])) 221 (*off)++; 222 if ((t = index(s + *off, '/')) == NULL) 223 return (EINVAL); 224 if ((len = t - (s + *off)) > sizeof(fambuf) - 1) 225 return (EINVAL); 226 strncpy(fambuf, s + *off, len); 227 fambuf[len] = '\0'; 228 *off += len + 1; 229 if ((family = ng_ksocket_parse(ng_ksocket_families, fambuf, 0)) == -1) 230 return (EINVAL); 231 232 /* Set family */ 233 if (*buflen < SADATA_OFFSET) 234 return (ERANGE); 235 sa->sa_family = family; 236 237 /* Set family-specific data and length */ 238 switch (sa->sa_family) { 239 case PF_LOCAL: /* Get pathname */ 240 { 241 const int pathoff = OFFSETOF(struct sockaddr_un, sun_path); 242 struct sockaddr_un *const sun = (struct sockaddr_un *)sa; 243 int toklen, pathlen; 244 char *path; 245 246 if ((path = ng_get_string_token(s, off, &toklen)) == NULL) 247 return (EINVAL); 248 pathlen = strlen(path); 249 if (pathlen > SOCK_MAXADDRLEN) { 250 kfree(path, M_NETGRAPH); 251 return (E2BIG); 252 } 253 if (*buflen < pathoff + pathlen) { 254 kfree(path, M_NETGRAPH); 255 return (ERANGE); 256 } 257 *off += toklen; 258 bcopy(path, sun->sun_path, pathlen); 259 sun->sun_len = pathoff + pathlen; 260 kfree(path, M_NETGRAPH); 261 break; 262 } 263 264 case PF_INET: /* Get an IP address with optional port */ 265 { 266 struct sockaddr_in *const sin = (struct sockaddr_in *)sa; 267 int i; 268 269 /* Parse this: <ipaddress>[:port] */ 270 for (i = 0; i < 4; i++) { 271 u_long val; 272 char *eptr; 273 274 val = strtoul(s + *off, &eptr, 10); 275 if (val > 0xff || eptr == s + *off) 276 return (EINVAL); 277 *off += (eptr - (s + *off)); 278 ((u_char *)&sin->sin_addr)[i] = (u_char)val; 279 if (i < 3) { 280 if (s[*off] != '.') 281 return (EINVAL); 282 (*off)++; 283 } else if (s[*off] == ':') { 284 (*off)++; 285 val = strtoul(s + *off, &eptr, 10); 286 if (val > 0xffff || eptr == s + *off) 287 return (EINVAL); 288 *off += (eptr - (s + *off)); 289 sin->sin_port = htons(val); 290 } else 291 sin->sin_port = 0; 292 } 293 bzero(&sin->sin_zero, sizeof(sin->sin_zero)); 294 sin->sin_len = sizeof(*sin); 295 break; 296 } 297 298 #if 0 299 case PF_INET6: 300 #endif 301 302 default: 303 return (EINVAL); 304 } 305 306 /* Done */ 307 *buflen = sa->sa_len; 308 return (0); 309 } 310 311 /* Convert a struct sockaddr from binary to ASCII */ 312 static int 313 ng_ksocket_sockaddr_unparse(const struct ng_parse_type *type, 314 const u_char *data, int *off, char *cbuf, int cbuflen) 315 { 316 const struct sockaddr *sa = (const struct sockaddr *)(data + *off); 317 int slen = 0; 318 319 /* Output socket address, either in special or generic format */ 320 switch (sa->sa_family) { 321 case PF_LOCAL: 322 { 323 const int pathoff = OFFSETOF(struct sockaddr_un, sun_path); 324 const struct sockaddr_un *sun = (const struct sockaddr_un *)sa; 325 const int pathlen = sun->sun_len - pathoff; 326 char pathbuf[SOCK_MAXADDRLEN + 1]; 327 char *pathtoken; 328 329 bcopy(sun->sun_path, pathbuf, pathlen); 330 pathbuf[pathlen] = '\0'; 331 if ((pathtoken = ng_encode_string(pathbuf)) == NULL) 332 return (ENOMEM); 333 slen += ksnprintf(cbuf, cbuflen, "local/%s", pathtoken); 334 kfree(pathtoken, M_NETGRAPH); 335 if (slen >= cbuflen) 336 return (ERANGE); 337 *off += sun->sun_len; 338 return (0); 339 } 340 341 case PF_INET: 342 { 343 const struct sockaddr_in *sin = (const struct sockaddr_in *)sa; 344 345 slen += ksnprintf(cbuf, cbuflen, "inet/%d.%d.%d.%d", 346 ((const u_char *)&sin->sin_addr)[0], 347 ((const u_char *)&sin->sin_addr)[1], 348 ((const u_char *)&sin->sin_addr)[2], 349 ((const u_char *)&sin->sin_addr)[3]); 350 if (sin->sin_port != 0) { 351 slen += ksnprintf(cbuf + strlen(cbuf), 352 cbuflen - strlen(cbuf), ":%d", 353 (u_int)ntohs(sin->sin_port)); 354 } 355 if (slen >= cbuflen) 356 return (ERANGE); 357 *off += sizeof(*sin); 358 return(0); 359 } 360 361 #if 0 362 case PF_INET6: 363 #endif 364 365 default: 366 return (*ng_ksocket_generic_sockaddr_type.supertype->unparse) 367 (&ng_ksocket_generic_sockaddr_type, 368 data, off, cbuf, cbuflen); 369 } 370 } 371 372 /* Parse type for struct sockaddr */ 373 static const struct ng_parse_type ng_ksocket_sockaddr_type = { 374 NULL, 375 NULL, 376 NULL, 377 &ng_ksocket_sockaddr_parse, 378 &ng_ksocket_sockaddr_unparse, 379 NULL /* no such thing as a default struct sockaddr */ 380 }; 381 382 /************************************************************************ 383 STRUCT NG_KSOCKET_SOCKOPT PARSE TYPE 384 ************************************************************************/ 385 386 /* Get length of the struct ng_ksocket_sockopt value field, which is the 387 just the excess of the message argument portion over the length of 388 the struct ng_ksocket_sockopt. */ 389 static int 390 ng_parse_sockoptval_getLength(const struct ng_parse_type *type, 391 const u_char *start, const u_char *buf) 392 { 393 static const int offset = OFFSETOF(struct ng_ksocket_sockopt, value); 394 const struct ng_ksocket_sockopt *sopt; 395 const struct ng_mesg *msg; 396 397 sopt = (const struct ng_ksocket_sockopt *)(buf - offset); 398 msg = (const struct ng_mesg *)((const u_char *)sopt - sizeof(*msg)); 399 return msg->header.arglen - sizeof(*sopt); 400 } 401 402 /* Parse type for the option value part of a struct ng_ksocket_sockopt 403 XXX Eventually, we should handle the different socket options specially. 404 XXX This would avoid byte order problems, eg an integer value of 1 is 405 XXX going to be "[1]" for little endian or "[3=1]" for big endian. */ 406 static const struct ng_parse_type ng_ksocket_sockoptval_type = { 407 &ng_parse_bytearray_type, 408 &ng_parse_sockoptval_getLength 409 }; 410 411 /* Parse type for struct ng_ksocket_sockopt */ 412 static const struct ng_parse_struct_field ng_ksocket_sockopt_type_fields[] 413 = NG_KSOCKET_SOCKOPT_INFO(&ng_ksocket_sockoptval_type); 414 static const struct ng_parse_type ng_ksocket_sockopt_type = { 415 &ng_parse_struct_type, 416 &ng_ksocket_sockopt_type_fields 417 }; 418 419 /* Parse type for struct ng_ksocket_accept */ 420 static const struct ng_parse_struct_field ng_ksocket_accept_type_fields[] 421 = NGM_KSOCKET_ACCEPT_INFO; 422 static const struct ng_parse_type ng_ksocket_accept_type = { 423 &ng_parse_struct_type, 424 &ng_ksocket_accept_type_fields 425 }; 426 427 /* List of commands and how to convert arguments to/from ASCII */ 428 static const struct ng_cmdlist ng_ksocket_cmds[] = { 429 { 430 NGM_KSOCKET_COOKIE, 431 NGM_KSOCKET_BIND, 432 "bind", 433 &ng_ksocket_sockaddr_type, 434 NULL 435 }, 436 { 437 NGM_KSOCKET_COOKIE, 438 NGM_KSOCKET_LISTEN, 439 "listen", 440 &ng_parse_int32_type, 441 NULL 442 }, 443 { 444 NGM_KSOCKET_COOKIE, 445 NGM_KSOCKET_ACCEPT, 446 "accept", 447 NULL, 448 &ng_ksocket_accept_type 449 }, 450 { 451 NGM_KSOCKET_COOKIE, 452 NGM_KSOCKET_CONNECT, 453 "connect", 454 &ng_ksocket_sockaddr_type, 455 &ng_parse_int32_type 456 }, 457 { 458 NGM_KSOCKET_COOKIE, 459 NGM_KSOCKET_GETNAME, 460 "getname", 461 NULL, 462 &ng_ksocket_sockaddr_type 463 }, 464 { 465 NGM_KSOCKET_COOKIE, 466 NGM_KSOCKET_GETPEERNAME, 467 "getpeername", 468 NULL, 469 &ng_ksocket_sockaddr_type 470 }, 471 { 472 NGM_KSOCKET_COOKIE, 473 NGM_KSOCKET_SETOPT, 474 "setopt", 475 &ng_ksocket_sockopt_type, 476 NULL 477 }, 478 { 479 NGM_KSOCKET_COOKIE, 480 NGM_KSOCKET_GETOPT, 481 "getopt", 482 &ng_ksocket_sockopt_type, 483 &ng_ksocket_sockopt_type 484 }, 485 486 /* Internal commands */ 487 { 488 NGM_KSOCKET_INTERNAL_COOKIE, 489 NGM_KSOCKET_INTERNAL_UPCALL, 490 "upcall", 491 NULL, 492 NULL 493 }, 494 { 0 } 495 }; 496 497 /* Node type descriptor */ 498 static struct ng_type ng_ksocket_typestruct = { 499 NG_VERSION, 500 NG_KSOCKET_NODE_TYPE, 501 NULL, 502 ng_ksocket_constructor, 503 ng_ksocket_rcvmsg, 504 ng_ksocket_rmnode, 505 ng_ksocket_newhook, 506 NULL, 507 NULL, 508 ng_ksocket_rcvdata, 509 ng_ksocket_rcvdata, 510 ng_ksocket_disconnect, 511 ng_ksocket_cmds 512 }; 513 NETGRAPH_INIT(ksocket, &ng_ksocket_typestruct); 514 515 #define ERROUT(x) do { error = (x); goto done; } while (0) 516 517 /************************************************************************ 518 NETGRAPH NODE STUFF 519 ************************************************************************/ 520 521 /* 522 * Node type constructor 523 */ 524 static int 525 ng_ksocket_constructor(node_p *nodep) 526 { 527 priv_p priv; 528 int error; 529 530 /* Allocate private structure */ 531 priv = kmalloc(sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO); 532 if (priv == NULL) 533 return (ENOMEM); 534 535 /* Call generic node constructor */ 536 if ((error = ng_make_node_common(&ng_ksocket_typestruct, nodep))) { 537 kfree(priv, M_NETGRAPH); 538 return (error); 539 } 540 (*nodep)->private = priv; 541 priv->node = *nodep; 542 LIST_INIT(&priv->embryos); 543 544 /* Done */ 545 return (0); 546 } 547 548 /* 549 * Give our OK for a hook to be added. The hook name is of the 550 * form "<family>/<type>/<proto>" where the three components may 551 * be decimal numbers or else aliases from the above lists. 552 * 553 * Connecting a hook amounts to opening the socket. Disconnecting 554 * the hook closes the socket and destroys the node as well. 555 */ 556 static int 557 ng_ksocket_newhook(node_p node, hook_p hook, const char *name0) 558 { 559 struct thread *td = curthread->td_proc ? curthread : &thread0; /* XXX broken */ 560 const priv_p priv = node->private; 561 struct ng_mesg *msg; 562 char *s1, *s2, name[NG_HOOKSIZ]; 563 int family, type, protocol, error; 564 565 /* Check if we're already connected */ 566 if (priv->hook != NULL) 567 return (EISCONN); 568 569 if (priv->flags & KSF_CLONED) { 570 if (priv->flags & KSF_EMBRYONIC) { 571 /* Remove ourselves from our parent's embryo list */ 572 LIST_REMOVE(priv, siblings); 573 priv->flags &= ~KSF_EMBRYONIC; 574 } 575 } else { 576 /* Extract family, type, and protocol from hook name */ 577 ksnprintf(name, sizeof(name), "%s", name0); 578 s1 = name; 579 if ((s2 = index(s1, '/')) == NULL) 580 return (EINVAL); 581 *s2++ = '\0'; 582 family = ng_ksocket_parse(ng_ksocket_families, s1, 0); 583 if (family == -1) 584 return (EINVAL); 585 s1 = s2; 586 if ((s2 = index(s1, '/')) == NULL) 587 return (EINVAL); 588 *s2++ = '\0'; 589 type = ng_ksocket_parse(ng_ksocket_types, s1, 0); 590 if (type == -1) 591 return (EINVAL); 592 s1 = s2; 593 protocol = ng_ksocket_parse(ng_ksocket_protos, s1, family); 594 if (protocol == -1) 595 return (EINVAL); 596 597 /* Create the socket */ 598 error = socreate(family, &priv->so, type, protocol, td); 599 if (error != 0) 600 return (error); 601 602 /* XXX call soreserve() ? */ 603 604 /* Add our hook for incoming data and other events */ 605 priv->so->so_upcallarg = (caddr_t)node; 606 priv->so->so_upcall = ng_ksocket_incoming; 607 atomic_set_int(&priv->so->so_rcv.ssb_flags, SSB_UPCALL); 608 atomic_set_int(&priv->so->so_snd.ssb_flags, SSB_UPCALL); 609 } 610 611 /* OK */ 612 priv->hook = hook; 613 614 /* 615 * On a cloned socket we may have already received one or more 616 * upcalls which we couldn't handle without a hook. Handle 617 * those now. We cannot call the upcall function directly 618 * from here, because until this function has returned our 619 * hook isn't connected. So we queue a message to ourselves 620 * which will cause the upcall function to be called a bit 621 * later. 622 */ 623 if (priv->flags & KSF_CLONED) { 624 NG_MKMESSAGE(msg, NGM_KSOCKET_INTERNAL_COOKIE, 625 NGM_KSOCKET_INTERNAL_UPCALL, 0, M_NOWAIT); 626 if (msg != NULL) 627 ng_queue_msg(node, msg, ".:"); 628 } 629 630 return (0); 631 } 632 633 /* 634 * Receive a control message 635 */ 636 static int 637 ng_ksocket_rcvmsg(node_p node, struct ng_mesg *msg, 638 const char *raddr, struct ng_mesg **rptr) 639 { 640 struct thread *td = curthread->td_proc ? curthread : &thread0; /* XXX broken */ 641 const priv_p priv = node->private; 642 struct socket *const so = priv->so; 643 struct ng_mesg *resp = NULL; 644 int error = 0; 645 646 switch (msg->header.typecookie) { 647 case NGM_KSOCKET_COOKIE: 648 switch (msg->header.cmd) { 649 case NGM_KSOCKET_BIND: 650 { 651 struct sockaddr *const sa 652 = (struct sockaddr *)msg->data; 653 654 /* Sanity check */ 655 if (msg->header.arglen < SADATA_OFFSET 656 || msg->header.arglen < sa->sa_len) 657 ERROUT(EINVAL); 658 if (so == NULL) 659 ERROUT(ENXIO); 660 661 /* Bind */ 662 error = sobind(so, sa, td); 663 break; 664 } 665 case NGM_KSOCKET_LISTEN: 666 { 667 /* Sanity check */ 668 if (msg->header.arglen != sizeof(int32_t)) 669 ERROUT(EINVAL); 670 if (so == NULL) 671 ERROUT(ENXIO); 672 673 /* Listen */ 674 error = solisten(so, *((int32_t *)msg->data), td); 675 break; 676 } 677 678 case NGM_KSOCKET_ACCEPT: 679 { 680 /* Sanity check */ 681 if (msg->header.arglen != 0) 682 ERROUT(EINVAL); 683 if (so == NULL) 684 ERROUT(ENXIO); 685 686 /* Make sure the socket is capable of accepting */ 687 if (!(so->so_options & SO_ACCEPTCONN)) 688 ERROUT(EINVAL); 689 if (priv->flags & KSF_ACCEPTING) 690 ERROUT(EALREADY); 691 692 error = ng_ksocket_check_accept(priv); 693 if (error != 0 && error != EWOULDBLOCK) 694 ERROUT(error); 695 696 /* 697 * If a connection is already complete, take it. 698 * Otherwise let the upcall function deal with 699 * the connection when it comes in. 700 */ 701 priv->response_token = msg->header.token; 702 strcpy(priv->response_addr, raddr); 703 if (error == 0) { 704 ng_ksocket_finish_accept(priv, 705 rptr != NULL ? &resp : NULL); 706 } else 707 priv->flags |= KSF_ACCEPTING; 708 break; 709 } 710 711 case NGM_KSOCKET_CONNECT: 712 { 713 struct sockaddr *const sa 714 = (struct sockaddr *)msg->data; 715 716 /* Sanity check */ 717 if (msg->header.arglen < SADATA_OFFSET 718 || msg->header.arglen < sa->sa_len) 719 ERROUT(EINVAL); 720 if (so == NULL) 721 ERROUT(ENXIO); 722 723 /* Do connect */ 724 if ((so->so_state & SS_ISCONNECTING) != 0) 725 ERROUT(EALREADY); 726 if ((error = soconnect(so, sa, td, TRUE)) != 0) { 727 soclrstate(so, SS_ISCONNECTING); 728 ERROUT(error); 729 } 730 if ((so->so_state & SS_ISCONNECTING) != 0) { 731 /* We will notify the sender when we connect */ 732 priv->response_token = msg->header.token; 733 strcpy(priv->response_addr, raddr); 734 priv->flags |= KSF_CONNECTING; 735 ERROUT(EINPROGRESS); 736 } 737 break; 738 } 739 740 case NGM_KSOCKET_GETNAME: 741 case NGM_KSOCKET_GETPEERNAME: 742 { 743 struct sockaddr *sa = NULL; 744 int len; 745 746 /* Sanity check */ 747 if (msg->header.arglen != 0) 748 ERROUT(EINVAL); 749 if (so == NULL) 750 ERROUT(ENXIO); 751 752 /* Get function */ 753 if (msg->header.cmd == NGM_KSOCKET_GETPEERNAME) { 754 if ((so->so_state 755 & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) 756 ERROUT(ENOTCONN); 757 error = so_pru_peeraddr(so, &sa); 758 } else 759 error = so_pru_sockaddr(so, &sa); 760 761 /* Get local or peer address */ 762 if (error != 0) 763 goto bail; 764 len = (sa == NULL) ? 0 : sa->sa_len; 765 766 /* Send it back in a response */ 767 NG_MKRESPONSE(resp, msg, len, M_NOWAIT); 768 if (resp == NULL) { 769 error = ENOMEM; 770 goto bail; 771 } 772 bcopy(sa, resp->data, len); 773 774 bail: 775 /* Cleanup */ 776 if (sa != NULL) 777 kfree(sa, M_SONAME); 778 break; 779 } 780 781 case NGM_KSOCKET_GETOPT: 782 { 783 struct ng_ksocket_sockopt *ksopt = 784 (struct ng_ksocket_sockopt *)msg->data; 785 struct sockopt sopt; 786 787 /* Sanity check */ 788 if (msg->header.arglen != sizeof(*ksopt)) 789 ERROUT(EINVAL); 790 if (so == NULL) 791 ERROUT(ENXIO); 792 793 /* Get response with room for option value */ 794 NG_MKRESPONSE(resp, msg, sizeof(*ksopt) 795 + NG_KSOCKET_MAX_OPTLEN, M_NOWAIT); 796 if (resp == NULL) 797 ERROUT(ENOMEM); 798 799 /* Get socket option, and put value in the response */ 800 sopt.sopt_dir = SOPT_GET; 801 sopt.sopt_level = ksopt->level; 802 sopt.sopt_name = ksopt->name; 803 sopt.sopt_td = NULL; 804 sopt.sopt_valsize = NG_KSOCKET_MAX_OPTLEN; 805 ksopt = (struct ng_ksocket_sockopt *)resp->data; 806 sopt.sopt_val = ksopt->value; 807 if ((error = sogetopt(so, &sopt)) != 0) { 808 kfree(resp, M_NETGRAPH); 809 resp = NULL; 810 break; 811 } 812 813 /* Set actual value length */ 814 resp->header.arglen = sizeof(*ksopt) 815 + sopt.sopt_valsize; 816 break; 817 } 818 819 case NGM_KSOCKET_SETOPT: 820 { 821 struct ng_ksocket_sockopt *const ksopt = 822 (struct ng_ksocket_sockopt *)msg->data; 823 const int valsize = msg->header.arglen - sizeof(*ksopt); 824 struct sockopt sopt; 825 826 /* Sanity check */ 827 if (valsize < 0) 828 ERROUT(EINVAL); 829 if (so == NULL) 830 ERROUT(ENXIO); 831 832 /* Set socket option */ 833 sopt.sopt_dir = SOPT_SET; 834 sopt.sopt_level = ksopt->level; 835 sopt.sopt_name = ksopt->name; 836 sopt.sopt_val = ksopt->value; 837 sopt.sopt_valsize = valsize; 838 sopt.sopt_td = NULL; 839 error = sosetopt(so, &sopt); 840 break; 841 } 842 843 default: 844 error = EINVAL; 845 break; 846 } 847 break; 848 case NGM_KSOCKET_INTERNAL_COOKIE: 849 switch (msg->header.cmd) { 850 case NGM_KSOCKET_INTERNAL_UPCALL: 851 if (so == NULL) 852 ERROUT(ENXIO); 853 (*priv->so->so_upcall)(so, so->so_upcallarg, M_NOWAIT); 854 break; 855 default: 856 error = EINVAL; 857 break; 858 } 859 break; 860 default: 861 error = EINVAL; 862 break; 863 } 864 if (rptr) 865 *rptr = resp; 866 else if (resp) 867 kfree(resp, M_NETGRAPH); 868 869 done: 870 kfree(msg, M_NETGRAPH); 871 return (error); 872 } 873 874 /* 875 * Receive incoming data on our hook. Send it out the socket. 876 */ 877 static int 878 ng_ksocket_rcvdata(hook_p hook, struct mbuf *m, meta_p meta) 879 { 880 struct thread *td = curthread->td_proc ? curthread : &thread0; /* XXX broken */ 881 const node_p node = hook->node; 882 const priv_p priv = node->private; 883 struct socket *const so = priv->so; 884 struct sockaddr *sa = NULL; 885 int error; 886 887 /* Avoid reentrantly sending on the socket */ 888 if ((priv->flags & KSF_SENDING) != 0) { 889 NG_FREE_DATA(m, meta); 890 return (EDEADLK); 891 } 892 893 /* If any meta info, look for peer socket address */ 894 if (meta != NULL) { 895 struct meta_field_header *field; 896 897 /* Look for peer socket address */ 898 for (field = &meta->options[0]; 899 (caddr_t)field < (caddr_t)meta + meta->used_len; 900 field = (struct meta_field_header *) 901 ((caddr_t)field + field->len)) { 902 if (field->cookie != NGM_KSOCKET_COOKIE 903 || field->type != NG_KSOCKET_META_SOCKADDR) 904 continue; 905 sa = (struct sockaddr *)field->data; 906 break; 907 } 908 } 909 910 /* Send packet */ 911 priv->flags |= KSF_SENDING; 912 error = so_pru_sosend(so, sa, NULL, m, NULL, 0, td); 913 priv->flags &= ~KSF_SENDING; 914 915 /* Clean up and exit */ 916 NG_FREE_META(meta); 917 return (error); 918 } 919 920 /* 921 * Destroy node 922 */ 923 static int 924 ng_ksocket_rmnode(node_p node) 925 { 926 const priv_p priv = node->private; 927 priv_p embryo; 928 929 /* Close our socket (if any) */ 930 if (priv->so != NULL) { 931 priv->so->so_upcall = NULL; 932 atomic_clear_int(&priv->so->so_rcv.ssb_flags, SSB_UPCALL); 933 atomic_clear_int(&priv->so->so_snd.ssb_flags, SSB_UPCALL); 934 soclose(priv->so, FNONBLOCK); 935 priv->so = NULL; 936 } 937 938 /* If we are an embryo, take ourselves out of the parent's list */ 939 if (priv->flags & KSF_EMBRYONIC) { 940 LIST_REMOVE(priv, siblings); 941 priv->flags &= ~KSF_EMBRYONIC; 942 } 943 944 /* Remove any embryonic children we have */ 945 while (!LIST_EMPTY(&priv->embryos)) { 946 embryo = LIST_FIRST(&priv->embryos); 947 ng_rmnode(embryo->node); 948 } 949 950 /* Take down netgraph node */ 951 node->flags |= NG_INVALID; 952 ng_cutlinks(node); 953 ng_unname(node); 954 bzero(priv, sizeof(*priv)); 955 kfree(priv, M_NETGRAPH); 956 node->private = NULL; 957 ng_unref(node); /* let the node escape */ 958 return (0); 959 } 960 961 /* 962 * Hook disconnection 963 */ 964 static int 965 ng_ksocket_disconnect(hook_p hook) 966 { 967 KASSERT(hook->node->numhooks == 0, 968 ("%s: numhooks=%d?", __func__, hook->node->numhooks)); 969 ng_rmnode(hook->node); 970 return (0); 971 } 972 973 /************************************************************************ 974 HELPER STUFF 975 ************************************************************************/ 976 977 /* 978 * When incoming data is appended to the socket, we get notified here. 979 * This is also called whenever a significant event occurs for the socket. 980 */ 981 static void 982 ng_ksocket_incoming(struct socket *so, void *arg, int waitflag) 983 { 984 const node_p node = arg; 985 const priv_p priv = node->private; 986 struct ng_mesg *response; 987 int error; 988 989 crit_enter(); 990 991 /* Sanity check */ 992 if ((node->flags & NG_INVALID) != 0) { 993 crit_exit(); 994 return; 995 } 996 KASSERT(so == priv->so, ("%s: wrong socket", __func__)); 997 998 /* Check whether a pending connect operation has completed */ 999 if (priv->flags & KSF_CONNECTING) { 1000 if ((error = so->so_error) != 0) { 1001 so->so_error = 0; 1002 soclrstate(so, SS_ISCONNECTING); 1003 } 1004 if (!(so->so_state & SS_ISCONNECTING)) { 1005 NG_MKMESSAGE(response, NGM_KSOCKET_COOKIE, 1006 NGM_KSOCKET_CONNECT, sizeof(int32_t), waitflag); 1007 if (response != NULL) { 1008 response->header.flags |= NGF_RESP; 1009 response->header.token = priv->response_token; 1010 *(int32_t *)response->data = error; 1011 /* 1012 * XXX We use ng_queue_msg here because we are 1013 * being called from deep in the bowels of the TCP 1014 * stack. Is this right, or should we let the 1015 * receiver of the message worry about that? 1016 */ 1017 ng_queue_msg(node, response, 1018 priv->response_addr); 1019 } 1020 priv->flags &= ~KSF_CONNECTING; 1021 } 1022 } 1023 1024 /* Check whether a pending accept operation has completed */ 1025 if (priv->flags & KSF_ACCEPTING) { 1026 error = ng_ksocket_check_accept(priv); 1027 if (error != EWOULDBLOCK) 1028 priv->flags &= ~KSF_ACCEPTING; 1029 if (error == 0) 1030 ng_ksocket_finish_accept(priv, NULL); 1031 } 1032 1033 /* 1034 * If we don't have a hook, we must handle data events later. When 1035 * the hook gets created and is connected, this upcall function 1036 * will be called again. 1037 */ 1038 if (priv->hook == NULL) { 1039 crit_exit(); 1040 return; 1041 } 1042 1043 /* Read and forward available mbuf's */ 1044 while (1) { 1045 struct sockaddr *sa = NULL; 1046 struct sockbuf sio; 1047 meta_p meta = NULL; 1048 struct mbuf *n; 1049 int flags; 1050 1051 sbinit(&sio, 1000000000); 1052 flags = MSG_DONTWAIT; 1053 1054 /* Try to get next packet from socket */ 1055 error = so_pru_soreceive(so, 1056 ((so->so_state & SS_ISCONNECTED) ? NULL : &sa), 1057 NULL, &sio, NULL, &flags); 1058 if (error) 1059 break; 1060 1061 /* See if we got anything */ 1062 if (sio.sb_mb == NULL) { 1063 if (sa != NULL) 1064 kfree(sa, M_SONAME); 1065 break; 1066 } 1067 1068 /* Don't trust the various socket layers to get the 1069 packet header and length correct (eg. kern/15175) */ 1070 sio.sb_mb->m_pkthdr.len = 0; 1071 for (n = sio.sb_mb; n != NULL; n = n->m_next) 1072 sio.sb_mb->m_pkthdr.len += n->m_len; 1073 1074 /* Put peer's socket address (if any) into a meta info blob */ 1075 if (sa != NULL) { 1076 struct meta_field_header *mhead; 1077 u_int len; 1078 1079 len = sizeof(*meta) + sizeof(*mhead) + sa->sa_len; 1080 meta = kmalloc(len, M_NETGRAPH, M_NOWAIT); 1081 if (meta == NULL) { 1082 kfree(sa, M_SONAME); 1083 goto sendit; 1084 } 1085 mhead = &meta->options[0]; 1086 bzero(meta, sizeof(*meta)); 1087 bzero(mhead, sizeof(*mhead)); 1088 meta->allocated_len = len; 1089 meta->used_len = len; 1090 mhead->cookie = NGM_KSOCKET_COOKIE; 1091 mhead->type = NG_KSOCKET_META_SOCKADDR; 1092 mhead->len = sizeof(*mhead) + sa->sa_len; 1093 bcopy(sa, mhead->data, sa->sa_len); 1094 kfree(sa, M_SONAME); 1095 } 1096 sendit: /* Forward data with optional peer sockaddr as meta info */ 1097 NG_SEND_DATA(error, priv->hook, sio.sb_mb, meta); 1098 } 1099 1100 /* 1101 * If the peer has closed the connection, forward a 0-length mbuf 1102 * to indicate end-of-file. 1103 */ 1104 if (so->so_state & SS_CANTRCVMORE && !(priv->flags & KSF_EOFSEEN)) { 1105 struct mbuf *m; 1106 1107 MGETHDR(m, waitflag, MT_DATA); 1108 if (m != NULL) { 1109 m->m_len = m->m_pkthdr.len = 0; 1110 NG_SEND_DATA_ONLY(error, priv->hook, m); 1111 } 1112 priv->flags |= KSF_EOFSEEN; 1113 } 1114 1115 crit_exit(); 1116 } 1117 1118 /* 1119 * Check for a completed incoming connection and return 0 if one is found. 1120 * Otherwise return the appropriate error code. 1121 */ 1122 static int 1123 ng_ksocket_check_accept(priv_p priv) 1124 { 1125 struct socket *const head = priv->so; 1126 int error; 1127 1128 lwkt_gettoken(&head->so_rcv.ssb_token); 1129 if ((error = head->so_error) != 0) { 1130 head->so_error = 0; 1131 lwkt_reltoken(&head->so_rcv.ssb_token); 1132 return error; 1133 } 1134 if (TAILQ_EMPTY(&head->so_comp)) { 1135 if (head->so_state & SS_CANTRCVMORE) 1136 error = ECONNABORTED; 1137 else 1138 error = EWOULDBLOCK; 1139 } 1140 lwkt_reltoken(&head->so_rcv.ssb_token); 1141 return error; 1142 } 1143 1144 /* 1145 * Handle the first completed incoming connection, assumed to be already 1146 * on the socket's so_comp queue. 1147 */ 1148 static void 1149 ng_ksocket_finish_accept(priv_p priv, struct ng_mesg **rptr) 1150 { 1151 struct socket *const head = priv->so; 1152 struct socket *so; 1153 struct sockaddr *sa = NULL; 1154 struct ng_mesg *resp; 1155 struct ng_ksocket_accept *resp_data; 1156 node_p node2; 1157 priv_p priv2; 1158 int len; 1159 1160 lwkt_getpooltoken(head); 1161 so = TAILQ_FIRST(&head->so_comp); 1162 if (so == NULL) { /* Should never happen */ 1163 lwkt_relpooltoken(head); 1164 return; 1165 } 1166 TAILQ_REMOVE(&head->so_comp, so, so_list); 1167 head->so_qlen--; 1168 soclrstate(so, SS_COMP); 1169 so->so_head = NULL; 1170 soreference(so); 1171 1172 lwkt_relpooltoken(head); 1173 1174 /* XXX KNOTE(&head->so_rcv.ssb_sel.si_note, 0); */ 1175 1176 soaccept(so, &sa); 1177 1178 len = OFFSETOF(struct ng_ksocket_accept, addr); 1179 if (sa != NULL) 1180 len += sa->sa_len; 1181 1182 NG_MKMESSAGE(resp, NGM_KSOCKET_COOKIE, NGM_KSOCKET_ACCEPT, len, 1183 M_NOWAIT); 1184 if (resp == NULL) { 1185 soclose(so, FNONBLOCK); 1186 goto out; 1187 } 1188 resp->header.flags |= NGF_RESP; 1189 resp->header.token = priv->response_token; 1190 1191 /* Clone a ksocket node to wrap the new socket */ 1192 if (ng_ksocket_constructor(&node2) != 0) { 1193 kfree(resp, M_NETGRAPH); 1194 soclose(so, FNONBLOCK); 1195 goto out; 1196 } 1197 priv2 = (priv_p)node2->private; 1198 priv2->so = so; 1199 priv2->flags |= KSF_CLONED | KSF_EMBRYONIC; 1200 1201 /* 1202 * Insert the cloned node into a list of embryonic children 1203 * on the parent node. When a hook is created on the cloned 1204 * node it will be removed from this list. When the parent 1205 * is destroyed it will destroy any embryonic children it has. 1206 */ 1207 LIST_INSERT_HEAD(&priv->embryos, priv2, siblings); 1208 1209 so->so_upcallarg = (caddr_t)node2; 1210 so->so_upcall = ng_ksocket_incoming; 1211 atomic_set_int(&so->so_rcv.ssb_flags, SSB_UPCALL); 1212 atomic_set_int(&so->so_snd.ssb_flags, SSB_UPCALL); 1213 1214 /* Fill in the response data and send it or return it to the caller */ 1215 resp_data = (struct ng_ksocket_accept *)resp->data; 1216 resp_data->nodeid = node2->ID; 1217 if (sa != NULL) 1218 bcopy(sa, &resp_data->addr, sa->sa_len); 1219 if (rptr != NULL) 1220 *rptr = resp; 1221 else 1222 ng_queue_msg(priv->node, resp, priv->response_addr); 1223 1224 out: 1225 if (sa != NULL) 1226 kfree(sa, M_SONAME); 1227 } 1228 1229 /* 1230 * Parse out either an integer value or an alias. 1231 */ 1232 static int 1233 ng_ksocket_parse(const struct ng_ksocket_alias *aliases, 1234 const char *s, int family) 1235 { 1236 int k, val; 1237 char *eptr; 1238 1239 /* Try aliases */ 1240 for (k = 0; aliases[k].name != NULL; k++) { 1241 if (strcmp(s, aliases[k].name) == 0 1242 && aliases[k].family == family) 1243 return aliases[k].value; 1244 } 1245 1246 /* Try parsing as a number */ 1247 val = (int)strtoul(s, &eptr, 10); 1248 if (val < 0 || *eptr != '\0') 1249 return (-1); 1250 return (val); 1251 } 1252 1253