1 /* 2 * ng_ksocket.c 3 */ 4 5 /*- 6 * Copyright (c) 1996-1999 Whistle Communications, Inc. 7 * All rights reserved. 8 * 9 * Subject to the following obligations and disclaimer of warranty, use and 10 * redistribution of this software, in source or object code forms, with or 11 * without modifications are expressly permitted by Whistle Communications; 12 * provided, however, that: 13 * 1. Any and all reproductions of the source or object code must include the 14 * copyright notice above and the following disclaimer of warranties; and 15 * 2. No rights are granted, in any manner or form, to use Whistle 16 * Communications, Inc. trademarks, including the mark "WHISTLE 17 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 18 * such appears in the above copyright notice or in the software. 19 * 20 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 21 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 22 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 23 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 25 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 26 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 27 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 28 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 29 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 30 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 31 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 32 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 36 * OF SUCH DAMAGE. 37 * 38 * Author: Archie Cobbs <archie@freebsd.org> 39 * $Whistle: ng_ksocket.c,v 1.1 1999/11/16 20:04:40 archie Exp $ 40 */ 41 42 /* 43 * Kernel socket node type. This node type is basically a kernel-mode 44 * version of a socket... kindof like the reverse of the socket node type. 45 */ 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/kernel.h> 50 #include <sys/mbuf.h> 51 #include <sys/proc.h> 52 #include <sys/malloc.h> 53 #include <sys/ctype.h> 54 #include <sys/protosw.h> 55 #include <sys/errno.h> 56 #include <sys/socket.h> 57 #include <sys/socketvar.h> 58 #include <sys/uio.h> 59 #include <sys/un.h> 60 61 #include <net/if.h> 62 #include <net/if_var.h> 63 64 #include <netgraph/ng_message.h> 65 #include <netgraph/netgraph.h> 66 #include <netgraph/ng_parse.h> 67 #include <netgraph/ng_ksocket.h> 68 69 #include <netinet/in.h> 70 #include <netinet/ip.h> 71 72 #include <netinet6/scope6_var.h> 73 74 #ifdef NG_SEPARATE_MALLOC 75 static MALLOC_DEFINE(M_NETGRAPH_KSOCKET, "netgraph_ksock", 76 "netgraph ksock node"); 77 #else 78 #define M_NETGRAPH_KSOCKET M_NETGRAPH 79 #endif 80 81 #define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0)) 82 #define SADATA_OFFSET (OFFSETOF(struct sockaddr, sa_data)) 83 84 /* Node private data */ 85 struct ng_ksocket_private { 86 node_p node; 87 hook_p hook; 88 struct socket *so; 89 int fn_sent; /* FN call on incoming event was sent */ 90 LIST_HEAD(, ng_ksocket_private) embryos; 91 LIST_ENTRY(ng_ksocket_private) siblings; 92 u_int32_t flags; 93 u_int32_t response_token; 94 ng_ID_t response_addr; 95 }; 96 typedef struct ng_ksocket_private *priv_p; 97 98 /* Flags for priv_p */ 99 #define KSF_CONNECTING 0x00000001 /* Waiting for connection complete */ 100 #define KSF_ACCEPTING 0x00000002 /* Waiting for accept complete */ 101 #define KSF_EOFSEEN 0x00000004 /* Have sent 0-length EOF mbuf */ 102 #define KSF_CLONED 0x00000008 /* Cloned from an accepting socket */ 103 #define KSF_EMBRYONIC 0x00000010 /* Cloned node with no hooks yet */ 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_shutdown; 109 static ng_newhook_t ng_ksocket_newhook; 110 static ng_rcvdata_t ng_ksocket_rcvdata; 111 static ng_connect_t ng_ksocket_connect; 112 static ng_disconnect_t ng_ksocket_disconnect; 113 114 /* Alias structure */ 115 struct ng_ksocket_alias { 116 const char *name; 117 const int value; 118 const int family; 119 }; 120 121 /* Protocol family aliases */ 122 static const struct ng_ksocket_alias ng_ksocket_families[] = { 123 { "local", PF_LOCAL }, 124 { "inet", PF_INET }, 125 { "inet6", PF_INET6 }, 126 { "atm", PF_ATM }, 127 { "divert", PF_DIVERT }, 128 { NULL, -1 }, 129 }; 130 131 /* Socket type aliases */ 132 static const struct ng_ksocket_alias ng_ksocket_types[] = { 133 { "stream", SOCK_STREAM }, 134 { "dgram", SOCK_DGRAM }, 135 { "raw", SOCK_RAW }, 136 { "rdm", SOCK_RDM }, 137 { "seqpacket", SOCK_SEQPACKET }, 138 { NULL, -1 }, 139 }; 140 141 /* Protocol aliases */ 142 static const struct ng_ksocket_alias ng_ksocket_protos[] = { 143 { "ip", IPPROTO_IP, PF_INET }, 144 { "raw", IPPROTO_RAW, PF_INET }, 145 { "icmp", IPPROTO_ICMP, PF_INET }, 146 { "igmp", IPPROTO_IGMP, PF_INET }, 147 { "tcp", IPPROTO_TCP, PF_INET }, 148 { "udp", IPPROTO_UDP, PF_INET }, 149 { "gre", IPPROTO_GRE, PF_INET }, 150 { "esp", IPPROTO_ESP, PF_INET }, 151 { "ah", IPPROTO_AH, PF_INET }, 152 { "swipe", IPPROTO_SWIPE, PF_INET }, 153 { "encap", IPPROTO_ENCAP, PF_INET }, 154 { "pim", IPPROTO_PIM, PF_INET }, 155 { "ip6", IPPROTO_IPV6, PF_INET6 }, 156 { "raw6", IPPROTO_RAW, PF_INET6 }, 157 { "icmp6", IPPROTO_ICMPV6, PF_INET6 }, 158 { "igmp6", IPPROTO_IGMP, PF_INET6 }, 159 { "tcp6", IPPROTO_TCP, PF_INET6 }, 160 { "udp6", IPPROTO_UDP, PF_INET6 }, 161 { "gre6", IPPROTO_GRE, PF_INET6 }, 162 { "esp6", IPPROTO_ESP, PF_INET6 }, 163 { "ah6", IPPROTO_AH, PF_INET6 }, 164 { "swipe6", IPPROTO_SWIPE, PF_INET6 }, 165 { "encap6", IPPROTO_ENCAP, PF_INET6 }, 166 { "divert6", IPPROTO_DIVERT, PF_INET6 }, 167 { "pim6", IPPROTO_PIM, PF_INET6 }, 168 { NULL, -1 }, 169 }; 170 171 /* Helper functions */ 172 static int ng_ksocket_accept(priv_p); 173 static int ng_ksocket_listen_upcall(struct socket *so, void *arg, 174 int waitflag); 175 static void ng_ksocket_listen_upcall2(node_p node, hook_p hook, 176 void *arg1, int arg2); 177 static int ng_ksocket_incoming(struct socket *so, void *arg, int waitflag); 178 static int ng_ksocket_parse(const struct ng_ksocket_alias *aliases, 179 const char *s, int family); 180 static void ng_ksocket_incoming2(node_p node, hook_p hook, 181 void *arg1, int arg2); 182 183 /************************************************************************ 184 STRUCT SOCKADDR PARSE TYPE 185 ************************************************************************/ 186 187 /* Get the length of the data portion of a generic struct sockaddr */ 188 static int 189 ng_parse_generic_sockdata_getLength(const struct ng_parse_type *type, 190 const u_char *start, const u_char *buf) 191 { 192 const struct sockaddr *sa; 193 194 sa = (const struct sockaddr *)(buf - SADATA_OFFSET); 195 return (sa->sa_len < SADATA_OFFSET) ? 0 : sa->sa_len - SADATA_OFFSET; 196 } 197 198 /* Type for the variable length data portion of a generic struct sockaddr */ 199 static const struct ng_parse_type ng_ksocket_generic_sockdata_type = { 200 &ng_parse_bytearray_type, 201 &ng_parse_generic_sockdata_getLength 202 }; 203 204 /* Type for a generic struct sockaddr */ 205 static const struct ng_parse_struct_field 206 ng_parse_generic_sockaddr_type_fields[] = { 207 { "len", &ng_parse_uint8_type }, 208 { "family", &ng_parse_uint8_type }, 209 { "data", &ng_ksocket_generic_sockdata_type }, 210 { NULL } 211 }; 212 static const struct ng_parse_type ng_ksocket_generic_sockaddr_type = { 213 &ng_parse_struct_type, 214 &ng_parse_generic_sockaddr_type_fields 215 }; 216 217 /* Convert a struct sockaddr from ASCII to binary. If its a protocol 218 family that we specially handle, do that, otherwise defer to the 219 generic parse type ng_ksocket_generic_sockaddr_type. */ 220 static int 221 ng_ksocket_sockaddr_parse(const struct ng_parse_type *type, 222 const char *s, int *off, const u_char *const start, 223 u_char *const buf, int *buflen) 224 { 225 struct sockaddr *const sa = (struct sockaddr *)buf; 226 enum ng_parse_token tok; 227 char fambuf[32]; 228 int family, len; 229 char *t; 230 231 /* If next token is a left curly brace, use generic parse type */ 232 if ((tok = ng_parse_get_token(s, off, &len)) == T_LBRACE) { 233 return (*ng_ksocket_generic_sockaddr_type.supertype->parse) 234 (&ng_ksocket_generic_sockaddr_type, 235 s, off, start, buf, buflen); 236 } 237 238 /* Get socket address family followed by a slash */ 239 while (isspace(s[*off])) 240 (*off)++; 241 if ((t = strchr(s + *off, '/')) == NULL) 242 return (EINVAL); 243 if ((len = t - (s + *off)) > sizeof(fambuf) - 1) 244 return (EINVAL); 245 strncpy(fambuf, s + *off, len); 246 fambuf[len] = '\0'; 247 *off += len + 1; 248 if ((family = ng_ksocket_parse(ng_ksocket_families, fambuf, 0)) == -1) 249 return (EINVAL); 250 251 /* Set family */ 252 if (*buflen < SADATA_OFFSET) 253 return (ERANGE); 254 sa->sa_family = family; 255 256 /* Set family-specific data and length */ 257 switch (sa->sa_family) { 258 case PF_LOCAL: /* Get pathname */ 259 { 260 const int pathoff = OFFSETOF(struct sockaddr_un, sun_path); 261 struct sockaddr_un *const sun = (struct sockaddr_un *)sa; 262 int toklen, pathlen; 263 char *path; 264 265 if ((path = ng_get_string_token(s, off, &toklen, NULL)) == NULL) 266 return (EINVAL); 267 pathlen = strlen(path); 268 if (pathlen > SOCK_MAXADDRLEN) { 269 free(path, M_NETGRAPH_KSOCKET); 270 return (E2BIG); 271 } 272 if (*buflen < pathoff + pathlen) { 273 free(path, M_NETGRAPH_KSOCKET); 274 return (ERANGE); 275 } 276 *off += toklen; 277 bcopy(path, sun->sun_path, pathlen); 278 sun->sun_len = pathoff + pathlen; 279 free(path, M_NETGRAPH_KSOCKET); 280 break; 281 } 282 283 case PF_INET: /* Get an IP address with optional port */ 284 { 285 struct sockaddr_in *const sin = (struct sockaddr_in *)sa; 286 int i; 287 288 /* Parse this: <ipaddress>[:port] */ 289 for (i = 0; i < 4; i++) { 290 u_long val; 291 char *eptr; 292 293 val = strtoul(s + *off, &eptr, 10); 294 if (val > 0xff || eptr == s + *off) 295 return (EINVAL); 296 *off += (eptr - (s + *off)); 297 ((u_char *)&sin->sin_addr)[i] = (u_char)val; 298 if (i < 3) { 299 if (s[*off] != '.') 300 return (EINVAL); 301 (*off)++; 302 } else if (s[*off] == ':') { 303 (*off)++; 304 val = strtoul(s + *off, &eptr, 10); 305 if (val > 0xffff || eptr == s + *off) 306 return (EINVAL); 307 *off += (eptr - (s + *off)); 308 sin->sin_port = htons(val); 309 } else 310 sin->sin_port = 0; 311 } 312 bzero(&sin->sin_zero, sizeof(sin->sin_zero)); 313 sin->sin_len = sizeof(*sin); 314 break; 315 } 316 317 case PF_INET6: 318 { 319 struct sockaddr_in6 *const sin6 = (struct sockaddr_in6 *)sa; 320 char *eptr; 321 char addr[INET6_ADDRSTRLEN]; 322 char ifname[16]; 323 u_long port; 324 bool hasifname = true; 325 326 /* RFC 3986 Section 3.2.2, Validate IP literal within square brackets. */ 327 if (s[*off] == '[' && (strstr(&s[*off], "]"))) 328 (*off)++; 329 else 330 return (EINVAL); 331 if ((eptr = strstr(&s[*off], "%")) == NULL) { 332 hasifname = false; 333 eptr = strstr(&s[*off], "]"); 334 } 335 snprintf(addr, eptr - (s + *off) + 1, "%s", &s[*off]); 336 *off += (eptr - (s + *off)); 337 if (!inet_pton(AF_INET6, addr, &sin6->sin6_addr)) 338 return (EINVAL); 339 340 if (hasifname) { 341 uint16_t scope; 342 343 eptr = strstr(&s[*off], "]"); 344 (*off)++; 345 snprintf(ifname, eptr - (s + *off) + 1, "%s", &s[*off]); 346 *off += (eptr - (s + *off)); 347 348 if (sin6->sin6_addr.s6_addr16[0] != IPV6_ADDR_INT16_ULL) 349 return (EINVAL); 350 scope = in6_getscope(&sin6->sin6_addr); 351 sin6->sin6_scope_id = 352 in6_getscopezone(ifunit(ifname), scope); 353 } 354 355 (*off)++; 356 if (s[*off] == ':') { 357 (*off)++; 358 port = strtoul(s + *off, &eptr, 10); 359 if (port > 0xffff || eptr == s + *off) 360 return (EINVAL); 361 *off += (eptr - (s + *off)); 362 sin6->sin6_port = htons(port); 363 } else 364 sin6->sin6_port = 0; 365 366 sin6->sin6_len = sizeof(*sin6); 367 break; 368 } 369 370 default: 371 return (EINVAL); 372 } 373 374 /* Done */ 375 *buflen = sa->sa_len; 376 return (0); 377 } 378 379 /* Convert a struct sockaddr from binary to ASCII */ 380 static int 381 ng_ksocket_sockaddr_unparse(const struct ng_parse_type *type, 382 const u_char *data, int *off, char *cbuf, int cbuflen) 383 { 384 const struct sockaddr *sa = (const struct sockaddr *)(data + *off); 385 int slen = 0; 386 387 /* Output socket address, either in special or generic format */ 388 switch (sa->sa_family) { 389 case PF_LOCAL: 390 { 391 const int pathoff = OFFSETOF(struct sockaddr_un, sun_path); 392 const struct sockaddr_un *sun = (const struct sockaddr_un *)sa; 393 const int pathlen = sun->sun_len - pathoff; 394 char pathbuf[SOCK_MAXADDRLEN + 1]; 395 char *pathtoken; 396 397 bcopy(sun->sun_path, pathbuf, pathlen); 398 if ((pathtoken = ng_encode_string(pathbuf, pathlen)) == NULL) 399 return (ENOMEM); 400 slen += snprintf(cbuf, cbuflen, "local/%s", pathtoken); 401 free(pathtoken, M_NETGRAPH_KSOCKET); 402 if (slen >= cbuflen) 403 return (ERANGE); 404 *off += sun->sun_len; 405 return (0); 406 } 407 408 case PF_INET: 409 { 410 const struct sockaddr_in *sin = (const struct sockaddr_in *)sa; 411 412 slen += snprintf(cbuf, cbuflen, "inet/%d.%d.%d.%d", 413 ((const u_char *)&sin->sin_addr)[0], 414 ((const u_char *)&sin->sin_addr)[1], 415 ((const u_char *)&sin->sin_addr)[2], 416 ((const u_char *)&sin->sin_addr)[3]); 417 if (sin->sin_port != 0) { 418 slen += snprintf(cbuf + strlen(cbuf), 419 cbuflen - strlen(cbuf), ":%d", 420 (u_int)ntohs(sin->sin_port)); 421 } 422 if (slen >= cbuflen) 423 return (ERANGE); 424 *off += sizeof(*sin); 425 return(0); 426 } 427 428 case PF_INET6: 429 { 430 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; 431 char addr[INET6_ADDRSTRLEN]; 432 433 inet_ntop(AF_INET6, &sin6->sin6_addr, addr, INET6_ADDRSTRLEN); 434 slen += snprintf(cbuf, cbuflen, "inet6/[%s]", addr); 435 436 if (sin6->sin6_port != 0) { 437 slen += snprintf(cbuf + strlen(cbuf), 438 cbuflen - strlen(cbuf), ":%d", 439 (u_int)ntohs(sin6->sin6_port)); 440 } 441 if (slen >= cbuflen) 442 return (ERANGE); 443 *off += sizeof(*sin6); 444 return(0); 445 } 446 447 default: 448 return (*ng_ksocket_generic_sockaddr_type.supertype->unparse) 449 (&ng_ksocket_generic_sockaddr_type, 450 data, off, cbuf, cbuflen); 451 } 452 } 453 454 /* Parse type for struct sockaddr */ 455 static const struct ng_parse_type ng_ksocket_sockaddr_type = { 456 NULL, 457 NULL, 458 NULL, 459 &ng_ksocket_sockaddr_parse, 460 &ng_ksocket_sockaddr_unparse, 461 NULL /* no such thing as a default struct sockaddr */ 462 }; 463 464 /************************************************************************ 465 STRUCT NG_KSOCKET_SOCKOPT PARSE TYPE 466 ************************************************************************/ 467 468 /* Get length of the struct ng_ksocket_sockopt value field, which is the 469 just the excess of the message argument portion over the length of 470 the struct ng_ksocket_sockopt. */ 471 static int 472 ng_parse_sockoptval_getLength(const struct ng_parse_type *type, 473 const u_char *start, const u_char *buf) 474 { 475 static const int offset = OFFSETOF(struct ng_ksocket_sockopt, value); 476 const struct ng_ksocket_sockopt *sopt; 477 const struct ng_mesg *msg; 478 479 sopt = (const struct ng_ksocket_sockopt *)(buf - offset); 480 msg = (const struct ng_mesg *)((const u_char *)sopt - sizeof(*msg)); 481 return msg->header.arglen - sizeof(*sopt); 482 } 483 484 /* Parse type for the option value part of a struct ng_ksocket_sockopt 485 XXX Eventually, we should handle the different socket options specially. 486 XXX This would avoid byte order problems, eg an integer value of 1 is 487 XXX going to be "[1]" for little endian or "[3=1]" for big endian. */ 488 static const struct ng_parse_type ng_ksocket_sockoptval_type = { 489 &ng_parse_bytearray_type, 490 &ng_parse_sockoptval_getLength 491 }; 492 493 /* Parse type for struct ng_ksocket_sockopt */ 494 static const struct ng_parse_struct_field ng_ksocket_sockopt_type_fields[] 495 = NG_KSOCKET_SOCKOPT_INFO(&ng_ksocket_sockoptval_type); 496 static const struct ng_parse_type ng_ksocket_sockopt_type = { 497 &ng_parse_struct_type, 498 &ng_ksocket_sockopt_type_fields 499 }; 500 501 /* Parse type for struct ng_ksocket_accept */ 502 static const struct ng_parse_struct_field ng_ksocket_accept_type_fields[] 503 = NGM_KSOCKET_ACCEPT_INFO; 504 static const struct ng_parse_type ng_ksocket_accept_type = { 505 &ng_parse_struct_type, 506 &ng_ksocket_accept_type_fields 507 }; 508 509 /* List of commands and how to convert arguments to/from ASCII */ 510 static const struct ng_cmdlist ng_ksocket_cmds[] = { 511 { 512 NGM_KSOCKET_COOKIE, 513 NGM_KSOCKET_BIND, 514 "bind", 515 &ng_ksocket_sockaddr_type, 516 NULL 517 }, 518 { 519 NGM_KSOCKET_COOKIE, 520 NGM_KSOCKET_LISTEN, 521 "listen", 522 &ng_parse_int32_type, 523 NULL 524 }, 525 { 526 NGM_KSOCKET_COOKIE, 527 NGM_KSOCKET_ACCEPT, 528 "accept", 529 NULL, 530 &ng_ksocket_accept_type 531 }, 532 { 533 NGM_KSOCKET_COOKIE, 534 NGM_KSOCKET_CONNECT, 535 "connect", 536 &ng_ksocket_sockaddr_type, 537 &ng_parse_int32_type 538 }, 539 { 540 NGM_KSOCKET_COOKIE, 541 NGM_KSOCKET_GETNAME, 542 "getname", 543 NULL, 544 &ng_ksocket_sockaddr_type 545 }, 546 { 547 NGM_KSOCKET_COOKIE, 548 NGM_KSOCKET_GETPEERNAME, 549 "getpeername", 550 NULL, 551 &ng_ksocket_sockaddr_type 552 }, 553 { 554 NGM_KSOCKET_COOKIE, 555 NGM_KSOCKET_SETOPT, 556 "setopt", 557 &ng_ksocket_sockopt_type, 558 NULL 559 }, 560 { 561 NGM_KSOCKET_COOKIE, 562 NGM_KSOCKET_GETOPT, 563 "getopt", 564 &ng_ksocket_sockopt_type, 565 &ng_ksocket_sockopt_type 566 }, 567 { 0 } 568 }; 569 570 /* Node type descriptor */ 571 static struct ng_type ng_ksocket_typestruct = { 572 .version = NG_ABI_VERSION, 573 .name = NG_KSOCKET_NODE_TYPE, 574 .constructor = ng_ksocket_constructor, 575 .rcvmsg = ng_ksocket_rcvmsg, 576 .shutdown = ng_ksocket_shutdown, 577 .newhook = ng_ksocket_newhook, 578 .connect = ng_ksocket_connect, 579 .rcvdata = ng_ksocket_rcvdata, 580 .disconnect = ng_ksocket_disconnect, 581 .cmdlist = ng_ksocket_cmds, 582 }; 583 NETGRAPH_INIT(ksocket, &ng_ksocket_typestruct); 584 585 #define ERROUT(x) do { error = (x); goto done; } while (0) 586 587 /************************************************************************ 588 NETGRAPH NODE STUFF 589 ************************************************************************/ 590 591 /* 592 * Node type constructor 593 * The NODE part is assumed to be all set up. 594 * There is already a reference to the node for us. 595 */ 596 static int 597 ng_ksocket_constructor(node_p node) 598 { 599 priv_p priv; 600 601 /* Allocate private structure */ 602 priv = malloc(sizeof(*priv), M_NETGRAPH_KSOCKET, M_NOWAIT | M_ZERO); 603 if (priv == NULL) 604 return (ENOMEM); 605 606 LIST_INIT(&priv->embryos); 607 /* cross link them */ 608 priv->node = node; 609 NG_NODE_SET_PRIVATE(node, priv); 610 611 /* Done */ 612 return (0); 613 } 614 615 /* 616 * Give our OK for a hook to be added. The hook name is of the 617 * form "<family>/<type>/<proto>" where the three components may 618 * be decimal numbers or else aliases from the above lists. 619 * 620 * Connecting a hook amounts to opening the socket. Disconnecting 621 * the hook closes the socket and destroys the node as well. 622 */ 623 static int 624 ng_ksocket_newhook(node_p node, hook_p hook, const char *name0) 625 { 626 struct thread *td = curthread; /* XXX broken */ 627 const priv_p priv = NG_NODE_PRIVATE(node); 628 char *s1, *s2, name[NG_HOOKSIZ]; 629 int family, type, protocol, error; 630 631 /* Check if we're already connected */ 632 if (priv->hook != NULL) 633 return (EISCONN); 634 635 if (priv->flags & KSF_CLONED) { 636 if (priv->flags & KSF_EMBRYONIC) { 637 /* Remove ourselves from our parent's embryo list */ 638 LIST_REMOVE(priv, siblings); 639 priv->flags &= ~KSF_EMBRYONIC; 640 } 641 } else { 642 /* Extract family, type, and protocol from hook name */ 643 snprintf(name, sizeof(name), "%s", name0); 644 s1 = name; 645 if ((s2 = strchr(s1, '/')) == NULL) 646 return (EINVAL); 647 *s2++ = '\0'; 648 family = ng_ksocket_parse(ng_ksocket_families, s1, 0); 649 if (family == -1) 650 return (EINVAL); 651 s1 = s2; 652 if ((s2 = strchr(s1, '/')) == NULL) 653 return (EINVAL); 654 *s2++ = '\0'; 655 type = ng_ksocket_parse(ng_ksocket_types, s1, 0); 656 if (type == -1) 657 return (EINVAL); 658 s1 = s2; 659 protocol = ng_ksocket_parse(ng_ksocket_protos, s1, family); 660 if (protocol == -1) 661 return (EINVAL); 662 663 /* Create the socket */ 664 error = socreate(family, &priv->so, type, protocol, 665 td->td_ucred, td); 666 if (error != 0) 667 return (error); 668 669 /* XXX call soreserve() ? */ 670 } 671 672 /* OK */ 673 priv->hook = hook; 674 675 /* 676 * In case of misconfigured routing a packet may reenter 677 * ksocket node recursively. Decouple stack to avoid possible 678 * panics about sleeping with locks held. 679 */ 680 NG_HOOK_FORCE_QUEUE(hook); 681 682 return(0); 683 } 684 685 static int 686 ng_ksocket_connect(hook_p hook) 687 { 688 node_p node = NG_HOOK_NODE(hook); 689 const priv_p priv = NG_NODE_PRIVATE(node); 690 struct socket *const so = priv->so; 691 692 /* Add our hook for incoming data and other events */ 693 SOCK_RECVBUF_LOCK(so); 694 soupcall_set(priv->so, SO_RCV, ng_ksocket_incoming, node); 695 SOCK_RECVBUF_UNLOCK(so); 696 SOCK_SENDBUF_LOCK(so); 697 soupcall_set(priv->so, SO_SND, ng_ksocket_incoming, node); 698 SOCK_SENDBUF_UNLOCK(so); 699 SOCK_LOCK(priv->so); 700 priv->so->so_state |= SS_NBIO; 701 SOCK_UNLOCK(priv->so); 702 /* 703 * --Original comment-- 704 * On a cloned socket we may have already received one or more 705 * upcalls which we couldn't handle without a hook. Handle 706 * those now. 707 * We cannot call the upcall function directly 708 * from here, because until this function has returned our 709 * hook isn't connected. 710 * 711 * ---meta comment for -current --- 712 * XXX This is dubius. 713 * Upcalls between the time that the hook was 714 * first created and now (on another processesor) will 715 * be earlier on the queue than the request to finalise the hook. 716 * By the time the hook is finalised, 717 * The queued upcalls will have happened and the code 718 * will have discarded them because of a lack of a hook. 719 * (socket not open). 720 * 721 * This is a bad byproduct of the complicated way in which hooks 722 * are now created (3 daisy chained async events). 723 * 724 * Since we are a netgraph operation 725 * We know that we hold a lock on this node. This forces the 726 * request we make below to be queued rather than implemented 727 * immediately which will cause the upcall function to be called a bit 728 * later. 729 * However, as we will run any waiting queued operations immediately 730 * after doing this one, if we have not finalised the other end 731 * of the hook, those queued operations will fail. 732 */ 733 if (priv->flags & KSF_CLONED) { 734 ng_send_fn(node, NULL, &ng_ksocket_incoming2, so, M_NOWAIT); 735 } 736 737 return (0); 738 } 739 740 /* 741 * Receive a control message 742 */ 743 static int 744 ng_ksocket_rcvmsg(node_p node, item_p item, hook_p lasthook) 745 { 746 struct thread *td = curthread; /* XXX broken */ 747 const priv_p priv = NG_NODE_PRIVATE(node); 748 struct socket *const so = priv->so; 749 struct ng_mesg *resp = NULL; 750 int error = 0; 751 struct ng_mesg *msg; 752 753 NGI_GET_MSG(item, msg); 754 switch (msg->header.typecookie) { 755 case NGM_KSOCKET_COOKIE: 756 switch (msg->header.cmd) { 757 case NGM_KSOCKET_BIND: 758 { 759 struct sockaddr *const sa 760 = (struct sockaddr *)msg->data; 761 762 /* Sanity check */ 763 if (msg->header.arglen < SADATA_OFFSET 764 || msg->header.arglen < sa->sa_len) 765 ERROUT(EINVAL); 766 if (so == NULL) 767 ERROUT(ENXIO); 768 769 /* Bind */ 770 error = sobind(so, sa, td); 771 break; 772 } 773 case NGM_KSOCKET_LISTEN: 774 { 775 /* Sanity check */ 776 if (msg->header.arglen != sizeof(int32_t)) 777 ERROUT(EINVAL); 778 if (so == NULL) 779 ERROUT(ENXIO); 780 781 /* Listen */ 782 so->so_state |= SS_NBIO; 783 error = solisten(so, *((int32_t *)msg->data), td); 784 if (error == 0) { 785 SOLISTEN_LOCK(so); 786 solisten_upcall_set(so, 787 ng_ksocket_listen_upcall, priv); 788 SOLISTEN_UNLOCK(so); 789 } 790 break; 791 } 792 793 case NGM_KSOCKET_ACCEPT: 794 { 795 /* Sanity check */ 796 if (msg->header.arglen != 0) 797 ERROUT(EINVAL); 798 if (so == NULL) 799 ERROUT(ENXIO); 800 801 /* Make sure the socket is capable of accepting */ 802 if (!(so->so_options & SO_ACCEPTCONN)) 803 ERROUT(EINVAL); 804 if (priv->flags & KSF_ACCEPTING) 805 ERROUT(EALREADY); 806 807 /* 808 * If a connection is already complete, take it. 809 * Otherwise let the upcall function deal with 810 * the connection when it comes in. Don't return 811 * EWOULDBLOCK, per ng_ksocket(4) documentation. 812 */ 813 error = ng_ksocket_accept(priv); 814 if (error == EWOULDBLOCK) 815 error = 0; 816 if (error != 0) 817 ERROUT(error); 818 819 priv->response_token = msg->header.token; 820 priv->response_addr = NGI_RETADDR(item); 821 break; 822 } 823 824 case NGM_KSOCKET_CONNECT: 825 { 826 struct sockaddr *const sa 827 = (struct sockaddr *)msg->data; 828 829 /* Sanity check */ 830 if (msg->header.arglen < SADATA_OFFSET 831 || msg->header.arglen < sa->sa_len) 832 ERROUT(EINVAL); 833 if (so == NULL) 834 ERROUT(ENXIO); 835 836 /* Do connect */ 837 if ((so->so_state & SS_ISCONNECTING) != 0) 838 ERROUT(EALREADY); 839 if ((error = soconnect(so, sa, td)) != 0) { 840 so->so_state &= ~SS_ISCONNECTING; 841 ERROUT(error); 842 } 843 if ((so->so_state & SS_ISCONNECTING) != 0) { 844 /* We will notify the sender when we connect */ 845 priv->response_token = msg->header.token; 846 priv->response_addr = NGI_RETADDR(item); 847 priv->flags |= KSF_CONNECTING; 848 ERROUT(EINPROGRESS); 849 } 850 break; 851 } 852 853 case NGM_KSOCKET_GETNAME: 854 case NGM_KSOCKET_GETPEERNAME: 855 { 856 int (*func)(struct socket *so, struct sockaddr *sa); 857 struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; 858 859 /* Sanity check */ 860 if (msg->header.arglen != 0) 861 ERROUT(EINVAL); 862 if (so == NULL) 863 ERROUT(ENXIO); 864 865 /* Get function */ 866 if (msg->header.cmd == NGM_KSOCKET_GETPEERNAME) { 867 if ((so->so_state & SS_ISCONNECTED) == 0) 868 ERROUT(ENOTCONN); 869 func = sopeeraddr; 870 } else 871 func = sosockaddr; 872 873 /* Get local or peer address */ 874 error = (*func)(so, (struct sockaddr *)&ss); 875 if (error) 876 break; 877 878 /* Send it back in a response */ 879 NG_MKRESPONSE(resp, msg, ss.ss_len, M_NOWAIT); 880 if (resp != NULL) 881 bcopy(&ss, resp->data, ss.ss_len); 882 else 883 error = ENOMEM; 884 885 break; 886 } 887 888 case NGM_KSOCKET_GETOPT: 889 { 890 struct ng_ksocket_sockopt *ksopt = 891 (struct ng_ksocket_sockopt *)msg->data; 892 struct sockopt sopt; 893 894 /* Sanity check */ 895 if (msg->header.arglen != sizeof(*ksopt)) 896 ERROUT(EINVAL); 897 if (so == NULL) 898 ERROUT(ENXIO); 899 900 /* Get response with room for option value */ 901 NG_MKRESPONSE(resp, msg, sizeof(*ksopt) 902 + NG_KSOCKET_MAX_OPTLEN, M_NOWAIT); 903 if (resp == NULL) 904 ERROUT(ENOMEM); 905 906 /* Get socket option, and put value in the response */ 907 sopt.sopt_dir = SOPT_GET; 908 sopt.sopt_level = ksopt->level; 909 sopt.sopt_name = ksopt->name; 910 sopt.sopt_td = NULL; 911 sopt.sopt_valsize = NG_KSOCKET_MAX_OPTLEN; 912 ksopt = (struct ng_ksocket_sockopt *)resp->data; 913 sopt.sopt_val = ksopt->value; 914 if ((error = sogetopt(so, &sopt)) != 0) { 915 NG_FREE_MSG(resp); 916 break; 917 } 918 919 /* Set actual value length */ 920 resp->header.arglen = sizeof(*ksopt) 921 + sopt.sopt_valsize; 922 break; 923 } 924 925 case NGM_KSOCKET_SETOPT: 926 { 927 struct ng_ksocket_sockopt *const ksopt = 928 (struct ng_ksocket_sockopt *)msg->data; 929 const int valsize = msg->header.arglen - sizeof(*ksopt); 930 struct sockopt sopt; 931 932 /* Sanity check */ 933 if (valsize < 0) 934 ERROUT(EINVAL); 935 if (so == NULL) 936 ERROUT(ENXIO); 937 938 /* Set socket option */ 939 sopt.sopt_dir = SOPT_SET; 940 sopt.sopt_level = ksopt->level; 941 sopt.sopt_name = ksopt->name; 942 sopt.sopt_val = ksopt->value; 943 sopt.sopt_valsize = valsize; 944 sopt.sopt_td = NULL; 945 error = sosetopt(so, &sopt); 946 break; 947 } 948 949 default: 950 error = EINVAL; 951 break; 952 } 953 break; 954 default: 955 error = EINVAL; 956 break; 957 } 958 done: 959 NG_RESPOND_MSG(error, node, item, resp); 960 NG_FREE_MSG(msg); 961 return (error); 962 } 963 964 /* 965 * Receive incoming data on our hook. Send it out the socket. 966 */ 967 static int 968 ng_ksocket_rcvdata(hook_p hook, item_p item) 969 { 970 struct thread *td = curthread; /* XXX broken */ 971 const node_p node = NG_HOOK_NODE(hook); 972 const priv_p priv = NG_NODE_PRIVATE(node); 973 struct socket *const so = priv->so; 974 struct sockaddr *sa = NULL; 975 int error; 976 struct mbuf *m; 977 #ifdef ALIGNED_POINTER 978 struct mbuf *n; 979 #endif /* ALIGNED_POINTER */ 980 struct sa_tag *stag; 981 982 /* Extract data */ 983 NGI_GET_M(item, m); 984 NG_FREE_ITEM(item); 985 #ifdef ALIGNED_POINTER 986 if (!ALIGNED_POINTER(mtod(m, caddr_t), uint32_t)) { 987 n = m_defrag(m, M_NOWAIT); 988 if (n == NULL) { 989 m_freem(m); 990 return (ENOBUFS); 991 } 992 m = n; 993 } 994 #endif /* ALIGNED_POINTER */ 995 /* 996 * Look if socket address is stored in packet tags. 997 * If sockaddr is ours, or provided by a third party (zero id), 998 * then we accept it. 999 */ 1000 if (((stag = (struct sa_tag *)m_tag_locate(m, NGM_KSOCKET_COOKIE, 1001 NG_KSOCKET_TAG_SOCKADDR, NULL)) != NULL) && 1002 (stag->id == NG_NODE_ID(node) || stag->id == 0)) 1003 sa = &stag->sa; 1004 1005 /* Reset specific mbuf flags to prevent addressing problems. */ 1006 m->m_flags &= ~(M_BCAST|M_MCAST); 1007 1008 /* Send packet */ 1009 error = sosend(so, sa, 0, m, 0, 0, td); 1010 1011 return (error); 1012 } 1013 1014 /* 1015 * Destroy node 1016 */ 1017 static int 1018 ng_ksocket_shutdown(node_p node) 1019 { 1020 const priv_p priv = NG_NODE_PRIVATE(node); 1021 struct socket *so = priv->so; 1022 priv_p embryo; 1023 1024 /* Close our socket (if any) */ 1025 if (priv->so != NULL) { 1026 if (SOLISTENING(so)) { 1027 SOLISTEN_LOCK(so); 1028 solisten_upcall_set(so, NULL, NULL); 1029 SOLISTEN_UNLOCK(so); 1030 } else { 1031 SOCK_RECVBUF_LOCK(so); 1032 soupcall_clear(so, SO_RCV); 1033 SOCK_RECVBUF_UNLOCK(so); 1034 SOCK_SENDBUF_LOCK(so); 1035 soupcall_clear(so, SO_SND); 1036 SOCK_SENDBUF_UNLOCK(so); 1037 } 1038 soclose(so); 1039 priv->so = NULL; 1040 } 1041 1042 /* If we are an embryo, take ourselves out of the parent's list */ 1043 if (priv->flags & KSF_EMBRYONIC) { 1044 LIST_REMOVE(priv, siblings); 1045 priv->flags &= ~KSF_EMBRYONIC; 1046 } 1047 1048 /* Remove any embryonic children we have */ 1049 while (!LIST_EMPTY(&priv->embryos)) { 1050 embryo = LIST_FIRST(&priv->embryos); 1051 ng_rmnode_self(embryo->node); 1052 } 1053 1054 /* Take down netgraph node */ 1055 bzero(priv, sizeof(*priv)); 1056 free(priv, M_NETGRAPH_KSOCKET); 1057 NG_NODE_SET_PRIVATE(node, NULL); 1058 NG_NODE_UNREF(node); /* let the node escape */ 1059 return (0); 1060 } 1061 1062 /* 1063 * Hook disconnection 1064 */ 1065 static int 1066 ng_ksocket_disconnect(hook_p hook) 1067 { 1068 KASSERT(NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0, 1069 ("%s: numhooks=%d?", __func__, 1070 NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)))); 1071 if (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))) 1072 ng_rmnode_self(NG_HOOK_NODE(hook)); 1073 return (0); 1074 } 1075 1076 /************************************************************************ 1077 HELPER STUFF 1078 ************************************************************************/ 1079 /* 1080 * You should not "just call" a netgraph node function from an external 1081 * asynchronous event. This is because in doing so you are ignoring the 1082 * locking on the netgraph nodes. Instead call your function via ng_send_fn(). 1083 * This will call the function you chose, but will first do all the 1084 * locking rigmarole. Your function MAY only be called at some distant future 1085 * time (several millisecs away) so don't give it any arguments 1086 * that may be revoked soon (e.g. on your stack). 1087 * 1088 * To decouple stack, we use queue version of ng_send_fn(). 1089 */ 1090 1091 static int 1092 ng_ksocket_incoming(struct socket *so, void *arg, int waitflag) 1093 { 1094 const node_p node = arg; 1095 const priv_p priv = NG_NODE_PRIVATE(node); 1096 int wait = ((waitflag & M_WAITOK) ? NG_WAITOK : 0) | NG_QUEUE; 1097 1098 /* 1099 * Even if node is not locked, as soon as we are called, we assume 1100 * it exist and it's private area is valid. With some care we can 1101 * access it. Mark node that incoming event for it was sent to 1102 * avoid unneded queue trashing. 1103 */ 1104 if (atomic_cmpset_int(&priv->fn_sent, 0, 1) && 1105 ng_send_fn1(node, NULL, &ng_ksocket_incoming2, so, 0, wait)) { 1106 atomic_store_rel_int(&priv->fn_sent, 0); 1107 } 1108 return (SU_OK); 1109 } 1110 1111 /* 1112 * When incoming data is appended to the socket, we get notified here. 1113 * This is also called whenever a significant event occurs for the socket. 1114 * Our original caller may have queued this even some time ago and 1115 * we cannot trust that he even still exists. The node however is being 1116 * held with a reference by the queueing code and guarantied to be valid. 1117 */ 1118 static void 1119 ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int arg2) 1120 { 1121 struct socket *so = arg1; 1122 const priv_p priv = NG_NODE_PRIVATE(node); 1123 struct ng_mesg *response; 1124 int error; 1125 1126 KASSERT(so == priv->so, ("%s: wrong socket", __func__)); 1127 1128 /* Allow next incoming event to be queued. */ 1129 atomic_store_rel_int(&priv->fn_sent, 0); 1130 1131 /* Check whether a pending connect operation has completed */ 1132 if (priv->flags & KSF_CONNECTING) { 1133 if ((error = so->so_error) != 0) { 1134 so->so_error = 0; 1135 so->so_state &= ~SS_ISCONNECTING; 1136 } 1137 if (!(so->so_state & SS_ISCONNECTING)) { 1138 NG_MKMESSAGE(response, NGM_KSOCKET_COOKIE, 1139 NGM_KSOCKET_CONNECT, sizeof(int32_t), M_NOWAIT); 1140 if (response != NULL) { 1141 response->header.flags |= NGF_RESP; 1142 response->header.token = priv->response_token; 1143 *(int32_t *)response->data = error; 1144 /* 1145 * send an async "response" message 1146 * to the node that set us up 1147 * (if it still exists) 1148 */ 1149 NG_SEND_MSG_ID(error, node, 1150 response, priv->response_addr, 0); 1151 } 1152 priv->flags &= ~KSF_CONNECTING; 1153 } 1154 } 1155 1156 /* 1157 * If we don't have a hook, we must handle data events later. When 1158 * the hook gets created and is connected, this upcall function 1159 * will be called again. 1160 */ 1161 if (priv->hook == NULL) 1162 return; 1163 1164 /* Read and forward available mbufs. */ 1165 while (1) { 1166 struct uio uio; 1167 struct sockaddr *sa; 1168 struct mbuf *m; 1169 int flags; 1170 1171 /* Try to get next packet from socket. */ 1172 uio.uio_td = NULL; 1173 uio.uio_resid = IP_MAXPACKET; 1174 flags = MSG_DONTWAIT; 1175 sa = NULL; 1176 if ((error = soreceive(so, (so->so_state & SS_ISCONNECTED) ? 1177 NULL : &sa, &uio, &m, NULL, &flags)) != 0) 1178 break; 1179 1180 /* See if we got anything. */ 1181 if (flags & MSG_TRUNC) { 1182 m_freem(m); 1183 m = NULL; 1184 } 1185 if (m == NULL) { 1186 if (sa != NULL) 1187 free(sa, M_SONAME); 1188 break; 1189 } 1190 1191 KASSERT(m->m_nextpkt == NULL, ("%s: nextpkt", __func__)); 1192 1193 /* 1194 * Stream sockets do not have packet boundaries, so 1195 * we have to allocate a header mbuf and attach the 1196 * stream of data to it. 1197 */ 1198 if (so->so_type == SOCK_STREAM) { 1199 struct mbuf *mh; 1200 1201 mh = m_gethdr(M_NOWAIT, MT_DATA); 1202 if (mh == NULL) { 1203 m_freem(m); 1204 if (sa != NULL) 1205 free(sa, M_SONAME); 1206 break; 1207 } 1208 1209 mh->m_next = m; 1210 for (; m; m = m->m_next) 1211 mh->m_pkthdr.len += m->m_len; 1212 m = mh; 1213 } 1214 1215 /* Put peer's socket address (if any) into a tag */ 1216 if (sa != NULL) { 1217 struct sa_tag *stag; 1218 1219 stag = (struct sa_tag *)m_tag_alloc(NGM_KSOCKET_COOKIE, 1220 NG_KSOCKET_TAG_SOCKADDR, sizeof(ng_ID_t) + 1221 sa->sa_len, M_NOWAIT); 1222 if (stag == NULL) { 1223 free(sa, M_SONAME); 1224 goto sendit; 1225 } 1226 bcopy(sa, &stag->sa, sa->sa_len); 1227 free(sa, M_SONAME); 1228 stag->id = NG_NODE_ID(node); 1229 m_tag_prepend(m, &stag->tag); 1230 } 1231 1232 sendit: /* Forward data with optional peer sockaddr as packet tag */ 1233 NG_SEND_DATA_ONLY(error, priv->hook, m); 1234 } 1235 1236 /* 1237 * If the peer has closed the connection, forward a 0-length mbuf 1238 * to indicate end-of-file. 1239 */ 1240 if (so->so_rcv.sb_state & SBS_CANTRCVMORE && 1241 !(priv->flags & KSF_EOFSEEN)) { 1242 struct mbuf *m; 1243 1244 m = m_gethdr(M_NOWAIT, MT_DATA); 1245 if (m != NULL) 1246 NG_SEND_DATA_ONLY(error, priv->hook, m); 1247 priv->flags |= KSF_EOFSEEN; 1248 } 1249 } 1250 1251 static int 1252 ng_ksocket_accept(priv_p priv) 1253 { 1254 struct socket *const head = priv->so; 1255 struct socket *so; 1256 struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; 1257 struct ng_mesg *resp; 1258 struct ng_ksocket_accept *resp_data; 1259 node_p node; 1260 priv_p priv2; 1261 int len; 1262 int error; 1263 1264 SOLISTEN_LOCK(head); 1265 error = solisten_dequeue(head, &so, SOCK_NONBLOCK); 1266 if (error == EWOULDBLOCK) { 1267 priv->flags |= KSF_ACCEPTING; 1268 return (error); 1269 } 1270 priv->flags &= ~KSF_ACCEPTING; 1271 if (error) 1272 return (error); 1273 1274 if ((error = soaccept(so, (struct sockaddr *)&ss)) != 0) 1275 return (error); 1276 1277 len = OFFSETOF(struct ng_ksocket_accept, addr); 1278 len += ss.ss_len; 1279 1280 NG_MKMESSAGE(resp, NGM_KSOCKET_COOKIE, NGM_KSOCKET_ACCEPT, len, 1281 M_NOWAIT); 1282 if (resp == NULL) { 1283 soclose(so); 1284 goto out; 1285 } 1286 resp->header.flags |= NGF_RESP; 1287 resp->header.token = priv->response_token; 1288 1289 /* Clone a ksocket node to wrap the new socket */ 1290 error = ng_make_node_common(&ng_ksocket_typestruct, &node); 1291 if (error) { 1292 free(resp, M_NETGRAPH); 1293 soclose(so); 1294 goto out; 1295 } 1296 1297 if (ng_ksocket_constructor(node) != 0) { 1298 NG_NODE_UNREF(node); 1299 free(resp, M_NETGRAPH); 1300 soclose(so); 1301 goto out; 1302 } 1303 1304 priv2 = NG_NODE_PRIVATE(node); 1305 priv2->so = so; 1306 priv2->flags |= KSF_CLONED | KSF_EMBRYONIC; 1307 1308 /* 1309 * Insert the cloned node into a list of embryonic children 1310 * on the parent node. When a hook is created on the cloned 1311 * node it will be removed from this list. When the parent 1312 * is destroyed it will destroy any embryonic children it has. 1313 */ 1314 LIST_INSERT_HEAD(&priv->embryos, priv2, siblings); 1315 1316 SOCK_RECVBUF_LOCK(so); 1317 soupcall_set(so, SO_RCV, ng_ksocket_incoming, node); 1318 SOCK_RECVBUF_UNLOCK(so); 1319 SOCK_SENDBUF_LOCK(so); 1320 soupcall_set(so, SO_SND, ng_ksocket_incoming, node); 1321 SOCK_SENDBUF_UNLOCK(so); 1322 1323 /* Fill in the response data and send it or return it to the caller */ 1324 resp_data = (struct ng_ksocket_accept *)resp->data; 1325 resp_data->nodeid = NG_NODE_ID(node); 1326 bcopy(&ss, &resp_data->addr, ss.ss_len); 1327 NG_SEND_MSG_ID(error, node, resp, priv->response_addr, 0); 1328 1329 out: 1330 1331 return (0); 1332 } 1333 1334 static int 1335 ng_ksocket_listen_upcall(struct socket *so, void *arg, int waitflag) 1336 { 1337 priv_p priv = arg; 1338 int wait = ((waitflag & M_WAITOK) ? NG_WAITOK : 0) | NG_QUEUE; 1339 1340 ng_send_fn1(priv->node, NULL, &ng_ksocket_listen_upcall2, priv, 0, 1341 wait); 1342 return (SU_OK); 1343 } 1344 1345 static void 1346 ng_ksocket_listen_upcall2(node_p node, hook_p hook, void *arg1, int arg2) 1347 { 1348 const priv_p priv = NG_NODE_PRIVATE(node); 1349 1350 (void )ng_ksocket_accept(priv); 1351 } 1352 1353 /* 1354 * Parse out either an integer value or an alias. 1355 */ 1356 static int 1357 ng_ksocket_parse(const struct ng_ksocket_alias *aliases, 1358 const char *s, int family) 1359 { 1360 int k, val; 1361 char *eptr; 1362 1363 /* Try aliases */ 1364 for (k = 0; aliases[k].name != NULL; k++) { 1365 if (strcmp(s, aliases[k].name) == 0 1366 && aliases[k].family == family) 1367 return aliases[k].value; 1368 } 1369 1370 /* Try parsing as a number */ 1371 val = (int)strtoul(s, &eptr, 10); 1372 if (val < 0 || *eptr != '\0') 1373 return (-1); 1374 return (val); 1375 } 1376