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
ng_parse_generic_sockdata_getLength(const struct ng_parse_type * type,const u_char * start,const u_char * buf)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
ng_ksocket_sockaddr_parse(const struct ng_parse_type * type,const char * s,int * off,const u_char * const start,u_char * const buf,int * buflen)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
ng_ksocket_sockaddr_unparse(const struct ng_parse_type * type,const u_char * data,int * off,char * cbuf,int cbuflen)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
ng_parse_sockoptval_getLength(const struct ng_parse_type * type,const u_char * start,const u_char * buf)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
ng_ksocket_constructor(node_p node)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
ng_ksocket_newhook(node_p node,hook_p hook,const char * name0)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
ng_ksocket_connect(hook_p hook)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
ng_ksocket_rcvmsg(node_p node,item_p item,hook_p lasthook)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
ng_ksocket_rcvdata(hook_p hook,item_p item)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
ng_ksocket_shutdown(node_p node)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
ng_ksocket_disconnect(hook_p hook)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
ng_ksocket_incoming(struct socket * so,void * arg,int waitflag)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
ng_ksocket_incoming2(node_p node,hook_p hook,void * arg1,int arg2)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
ng_ksocket_accept(priv_p priv)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
ng_ksocket_listen_upcall(struct socket * so,void * arg,int waitflag)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
ng_ksocket_listen_upcall2(node_p node,hook_p hook,void * arg1,int arg2)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
ng_ksocket_parse(const struct ng_ksocket_alias * aliases,const char * s,int family)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