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