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