1 /*
2 * ng_socket.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: Julian Elischer <julian@freebsd.org>
39 *
40 * $FreeBSD: src/sys/netgraph/ng_socket.c,v 1.85 2008/03/11 21:58:48 mav Exp $
41 * $Whistle: ng_socket.c,v 1.28 1999/11/01 09:24:52 julian Exp $
42 */
43
44 /*
45 * Netgraph socket nodes
46 *
47 * There are two types of netgraph sockets, control and data.
48 * Control sockets have a netgraph node, but data sockets are
49 * parasitic on control sockets, and have no node of their own.
50 */
51
52 #include <sys/domain.h>
53 #include <sys/kernel.h>
54 #include <sys/linker.h>
55 #include <sys/lock.h>
56 #include <sys/malloc.h>
57 #include <sys/mbuf.h>
58 #include <sys/msgport2.h>
59 /*
60 #include <sys/mutex.h>
61 */
62 #include <sys/param.h>
63 #include <sys/caps.h>
64 #include <sys/proc.h>
65 #include <sys/protosw.h>
66 #include <sys/queue.h>
67 #include <sys/socket.h>
68 #include <sys/socketvar.h>
69 #include <sys/socketvar2.h>
70 /*
71 #include <sys/syscallsubr.h>
72 */
73 #include <sys/sysctl.h>
74 #include <sys/vnode.h>
75
76 #include <netgraph7/ng_message.h>
77 #include <netgraph7/netgraph.h>
78 #include "ng_socketvar.h"
79 #include "ng_socket.h"
80
81 #ifdef NG_SEPARATE_MALLOC
82 MALLOC_DEFINE(M_NETGRAPH_PATH, "netgraph_path", "netgraph path info ");
83 MALLOC_DEFINE(M_NETGRAPH_SOCK, "netgraph_sock", "netgraph socket info ");
84 #else
85 #define M_NETGRAPH_PATH M_NETGRAPH
86 #define M_NETGRAPH_SOCK M_NETGRAPH
87 #endif
88
89 /*
90 * It's Ascii-art time!
91 * +-------------+ +-------------+
92 * |socket (ctl)| |socket (data)|
93 * +-------------+ +-------------+
94 * ^ ^
95 * | |
96 * v v
97 * +-----------+ +-----------+
98 * |pcb (ctl)| |pcb (data)|
99 * +-----------+ +-----------+
100 * ^ ^
101 * | |
102 * v v
103 * +--------------------------+
104 * | Socket type private |
105 * | data |
106 * +--------------------------+
107 * ^
108 * |
109 * v
110 * +----------------+
111 * | struct ng_node |
112 * +----------------+
113 */
114
115 /* Netgraph node methods */
116 static ng_constructor_t ngs_constructor;
117 static ng_rcvmsg_t ngs_rcvmsg;
118 static ng_shutdown_t ngs_shutdown;
119 static ng_newhook_t ngs_newhook;
120 static ng_connect_t ngs_connect;
121 static ng_rcvdata_t ngs_rcvdata;
122 static ng_disconnect_t ngs_disconnect;
123
124 /* Internal methods */
125 static int ng_attach_data(struct socket *so);
126 static int ng_attach_cntl(struct socket *so);
127 static int ng_attach_common(struct socket *so, int type);
128 static void ng_detach_common(struct ngpcb *pcbp, int type);
129 static void ng_socket_free_priv(struct ngsock *priv);
130 #ifdef NOTYET
131 static int ng_internalize(struct mbuf *m, struct thread *p);
132 #endif
133 static int ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp);
134 static int ng_bind(struct sockaddr *nam, struct ngpcb *pcbp);
135
136 static int ngs_mod_event(module_t mod, int event, void *data);
137 static void ng_socket_item_applied(void *context, int error);
138 static int linker_api_available(void);
139
140 /* Netgraph type descriptor */
141 static struct ng_type typestruct = {
142 .version = NG_ABI_VERSION,
143 .name = NG_SOCKET_NODE_TYPE,
144 .mod_event = ngs_mod_event,
145 .constructor = ngs_constructor,
146 .rcvmsg = ngs_rcvmsg,
147 .shutdown = ngs_shutdown,
148 .newhook = ngs_newhook,
149 .connect = ngs_connect,
150 .rcvdata = ngs_rcvdata,
151 .disconnect = ngs_disconnect,
152 };
153 NETGRAPH_INIT_ORDERED(socket, &typestruct, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
154
155 /* Buffer space */
156 static u_long ngpdg_sendspace = 20 * 1024; /* really max datagram size */
157 SYSCTL_INT(_net_graph, OID_AUTO, maxdgram, CTLFLAG_RW,
158 &ngpdg_sendspace , 0, "Maximum outgoing Netgraph datagram size");
159 static u_long ngpdg_recvspace = 20 * 1024;
160 SYSCTL_INT(_net_graph, OID_AUTO, recvspace, CTLFLAG_RW,
161 &ngpdg_recvspace , 0, "Maximum space for incoming Netgraph datagrams");
162
163 #define sotongpcb(so) ((struct ngpcb *)(so)->so_pcb)
164
165 /* If getting unexplained errors returned, set this to "kdb_enter("X"); */
166 #ifndef TRAP_ERROR
167 #define TRAP_ERROR
168 #endif
169
170 /***************************************************************
171 Control sockets
172 ***************************************************************/
173
174 static void
ngc_attach(netmsg_t msg)175 ngc_attach(netmsg_t msg)
176 {
177 struct socket *so = msg->attach.base.nm_so;
178 struct pru_attach_info *ai = msg->attach.nm_ai;
179 struct ngpcb *const pcbp = sotongpcb(so);
180 int error;
181
182 if (caps_priv_check(ai->p_ucred,
183 SYSCAP_RESTRICTEDROOT | __SYSCAP_NULLCRED))
184 {
185 error = EPERM;
186 } else if (pcbp != NULL) {
187 error = EISCONN;
188 } else {
189 error = ng_attach_cntl(so);
190 }
191 lwkt_replymsg(&msg->attach.base.lmsg, error);
192 }
193
194 static void
ngc_detach(netmsg_t msg)195 ngc_detach(netmsg_t msg)
196 {
197 struct socket *so = msg->detach.base.nm_so;
198 struct ngpcb *const pcbp = sotongpcb(so);
199
200 KASSERT(pcbp != NULL, ("ngc_detach: pcbp == NULL"));
201 ng_detach_common(pcbp, NG_CONTROL);
202 lwkt_replymsg(&msg->detach.base.lmsg, 0);
203 }
204
205 static void
ngc_send(netmsg_t netmsg)206 ngc_send(netmsg_t netmsg)
207 {
208 struct socket *so = netmsg->send.base.nm_so;
209 struct mbuf *m = netmsg->send.nm_m;
210 struct sockaddr *addr = netmsg->send.nm_addr;
211 struct mbuf *control = netmsg->send.nm_control;
212 struct ngpcb *const pcbp = sotongpcb(so);
213 struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
214 struct ng_mesg *msg;
215 struct mbuf *m0;
216 item_p item;
217 char *path = NULL;
218 int len, error = 0;
219 struct ng_apply_info *apply;
220
221 #ifdef NOTYET
222 if (control && (error = ng_internalize(control, td))) {
223 if (pcbp->sockdata == NULL) {
224 error = ENOTCONN;
225 goto release;
226 }
227 }
228 #else /* NOTYET */
229 if (control) {
230 error = EINVAL;
231 goto release;
232 }
233 #endif /* NOTYET */
234
235 /* Require destination as there may be >= 1 hooks on this node. */
236 if (addr == NULL) {
237 error = EDESTADDRREQ;
238 goto release;
239 }
240
241 /*
242 * Allocate an expendable buffer for the path, chop off
243 * the sockaddr header, and make sure it's NUL terminated.
244 */
245 len = sap->sg_len - 2;
246 path = kmalloc(len + 1, M_NETGRAPH_PATH, M_WAITOK);
247 bcopy(sap->sg_data, path, len);
248 path[len] = '\0';
249
250 /*
251 * Move the actual message out of mbufs into a linear buffer.
252 * Start by adding up the size of the data. (could use mh_len?)
253 */
254 for (len = 0, m0 = m; m0 != NULL; m0 = m0->m_next)
255 len += m0->m_len;
256
257 /*
258 * Move the data into a linear buffer as well.
259 * Messages are not delivered in mbufs.
260 */
261 msg = kmalloc(len + 1, M_NETGRAPH_MSG, M_WAITOK);
262 m_copydata(m, 0, len, msg);
263
264 if (msg->header.version != NG_VERSION) {
265 kfree(msg, M_NETGRAPH_MSG);
266 error = EINVAL;
267 goto release;
268 }
269
270 /*
271 * Hack alert!
272 * We look into the message and if it mkpeers a node of unknown type, we
273 * try to load it. We need to do this now, in syscall thread, because if
274 * message gets queued and applied later we will get panic.
275 */
276 if (msg->header.typecookie == NGM_GENERIC_COOKIE &&
277 msg->header.cmd == NGM_MKPEER) {
278 struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) msg->data;
279 struct ng_type *type;
280
281 if ((type = ng_findtype(mkp->type)) == NULL) {
282 char filename[NG_TYPESIZ + 3];
283 linker_file_t fileid;
284
285 if (!linker_api_available()) {
286 error = ENXIO;
287 goto done;
288 }
289
290 /* Not found, try to load it as a loadable module. */
291 ksnprintf(filename, sizeof(filename), "ng_%s.ko",
292 mkp->type);
293 error = linker_load_file(filename, &fileid);
294 if (error != 0) {
295 kfree(msg, M_NETGRAPH_MSG);
296 goto release;
297 }
298
299 /* See if type has been loaded successfully. */
300 if ((type = ng_findtype(mkp->type)) == NULL) {
301 kfree(msg, M_NETGRAPH_MSG);
302 (void)linker_file_unload(fileid);
303 error = ENXIO;
304 goto release;
305 }
306 }
307 }
308
309 item = ng_package_msg(msg, NG_WAITOK);
310 if ((error = ng_address_path((pcbp->sockdata->node), item, path, 0))
311 != 0) {
312 #ifdef TRACE_MESSAGES
313 kprintf("ng_address_path: errx=%d\n", error);
314 #endif
315 goto release;
316 }
317
318 #ifdef TRACE_MESSAGES
319 kprintf("[%x]:<---------[socket]: c=<%d>cmd=%x(%s) f=%x #%d (%s)\n",
320 item->el_dest->nd_ID,
321 msg->header.typecookie,
322 msg->header.cmd,
323 msg->header.cmdstr,
324 msg->header.flags,
325 msg->header.token,
326 item->el_dest->nd_type->name);
327 #endif
328 SAVE_LINE(item);
329
330 /*
331 * We do not want the user thread to return from syscall until the
332 * item is processed by destination node. We register callback
333 * on the item, which will reply to the user thread when item
334 * was applied.
335 */
336 apply = ng_alloc_apply();
337 bzero(apply, sizeof(*apply));
338 apply->apply = ng_socket_item_applied;
339 apply->context = &netmsg->send.base.lmsg;
340 item->apply = apply;
341
342 error = ng_snd_item(item, NG_PROGRESS);
343
344 release:
345 if (path != NULL)
346 kfree(path, M_NETGRAPH_PATH);
347 if (control != NULL)
348 m_freem(control);
349 if (m != NULL)
350 m_freem(m);
351 done:
352 if (error != EINPROGRESS)
353 lwkt_replymsg(&netmsg->send.base.lmsg, error);
354 }
355
356 static void
ngc_bind(netmsg_t msg)357 ngc_bind(netmsg_t msg)
358 {
359 struct socket *so = msg->connect.base.nm_so;
360 struct sockaddr *nam = msg->connect.nm_nam;
361 struct ngpcb *const pcbp = sotongpcb(so);
362 int error;
363
364 if (pcbp == NULL)
365 error = EINVAL;
366 else
367 error = ng_bind(nam, pcbp);
368 lwkt_replymsg(&msg->connect.base.lmsg, error);
369 }
370
371 static void
ngc_connect(netmsg_t msg)372 ngc_connect(netmsg_t msg)
373 {
374 /*
375 * At this time refuse to do this.. it used to
376 * do something but it was undocumented and not used.
377 */
378 kprintf("program tried to connect control socket to remote node\n");
379 lwkt_replymsg(&msg->connect.base.lmsg, EINVAL);
380 }
381
382 /***************************************************************
383 Data sockets
384 ***************************************************************/
385
386 static void
ngd_attach(netmsg_t msg)387 ngd_attach(netmsg_t msg)
388 {
389 struct socket *so = msg->attach.base.nm_so;
390 struct ngpcb *const pcbp = sotongpcb(so);
391 int error;
392
393 if (pcbp != NULL)
394 error = EISCONN;
395 else
396 error = ng_attach_data(so);
397 lwkt_replymsg(&msg->connect.base.lmsg, error);
398 }
399
400 static void
ngd_detach(netmsg_t msg)401 ngd_detach(netmsg_t msg)
402 {
403 struct socket *so = msg->detach.base.nm_so;
404 struct ngpcb *const pcbp = sotongpcb(so);
405
406 KASSERT(pcbp != NULL, ("ngd_detach: pcbp == NULL"));
407 ng_detach_common(pcbp, NG_DATA);
408 lwkt_replymsg(&msg->detach.base.lmsg, 0);
409 }
410
411 static void
ngd_send(netmsg_t msg)412 ngd_send(netmsg_t msg)
413 {
414 struct socket *so = msg->send.base.nm_so;
415 struct mbuf *m = msg->send.nm_m;
416 struct sockaddr *addr = msg->send.nm_addr;
417 struct mbuf *control = msg->send.nm_control;
418 struct ngpcb *const pcbp = sotongpcb(so);
419 struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
420 int len, error;
421 hook_p hook = NULL;
422 char hookname[NG_HOOKSIZ];
423
424 if ((pcbp == NULL) || (control != NULL)) {
425 error = EINVAL;
426 goto release;
427 }
428 if (pcbp->sockdata == NULL) {
429 error = ENOTCONN;
430 goto release;
431 }
432
433 if (sap == NULL)
434 len = 0; /* Make compiler happy. */
435 else
436 len = sap->sg_len - 2;
437
438 /*
439 * If the user used any of these ways to not specify an address
440 * then handle specially.
441 */
442 if ((sap == NULL) || (len <= 0) || (*sap->sg_data == '\0')) {
443 if (NG_NODE_NUMHOOKS(pcbp->sockdata->node) != 1) {
444 error = EDESTADDRREQ;
445 goto release;
446 }
447 /*
448 * If exactly one hook exists, just use it.
449 * Special case to allow write(2) to work on an ng_socket.
450 */
451 hook = LIST_FIRST(&pcbp->sockdata->node->nd_hooks);
452 } else {
453 if (len >= NG_HOOKSIZ) {
454 error = EINVAL;
455 goto release;
456 }
457
458 /*
459 * chop off the sockaddr header, and make sure it's NUL
460 * terminated
461 */
462 bcopy(sap->sg_data, hookname, len);
463 hookname[len] = '\0';
464
465 /* Find the correct hook from 'hookname' */
466 hook = ng_findhook(pcbp->sockdata->node, hookname);
467 if (hook == NULL) {
468 error = EHOSTUNREACH;
469 goto release;
470 }
471 }
472
473 /* Send data. */
474 NG_SEND_DATA_FLAGS(error, hook, m, NG_WAITOK);
475
476 release:
477 if (control != NULL)
478 m_freem(control);
479 if (m != NULL)
480 m_freem(m);
481 lwkt_replymsg(&msg->send.base.lmsg, error);
482 }
483
484 static void
ngd_connect(netmsg_t msg)485 ngd_connect(netmsg_t msg)
486 {
487 struct socket *so = msg->connect.base.nm_so;
488 struct sockaddr *nam = msg->connect.nm_nam;
489 struct ngpcb *const pcbp = sotongpcb(so);
490 int error;
491
492 if (pcbp == NULL)
493 error = EINVAL;
494 else
495 error = ng_connect_data(nam, pcbp);
496 lwkt_replymsg(&msg->connect.base.lmsg, error);
497 }
498
499 /*
500 * Used for both data and control sockets
501 */
502 static void
ng_getsockaddr(netmsg_t msg)503 ng_getsockaddr(netmsg_t msg)
504 {
505 struct socket *so = msg->sockaddr.base.nm_so;
506 struct sockaddr **addr = msg->sockaddr.nm_nam;
507 struct ngpcb *pcbp;
508 struct sockaddr_ng *sg;
509 int sg_len;
510 int error = 0;
511
512 /* Why isn't sg_data a `char[1]' ? :-( */
513 sg_len = sizeof(struct sockaddr_ng) - sizeof(sg->sg_data) + 1;
514
515 pcbp = sotongpcb(so);
516 if ((pcbp == NULL) || (pcbp->sockdata == NULL)) {
517 /* XXXGL: can this still happen? */
518 error = EINVAL;
519 goto replymsg;
520 }
521
522 mtx_lock(&pcbp->sockdata->mtx);
523 if (pcbp->sockdata->node != NULL) {
524 node_p node = pcbp->sockdata->node;
525 int namelen = 0; /* silence compiler! */
526
527 if (NG_NODE_HAS_NAME(node))
528 sg_len += namelen = strlen(NG_NODE_NAME(node));
529
530 sg = kmalloc(sg_len, M_SONAME, M_WAITOK | M_ZERO);
531
532 if (NG_NODE_HAS_NAME(node))
533 bcopy(NG_NODE_NAME(node), sg->sg_data, namelen);
534
535 sg->sg_len = sg_len;
536 sg->sg_family = AF_NETGRAPH;
537 *addr = (struct sockaddr *)sg;
538 mtx_unlock(&pcbp->sockdata->mtx);
539 } else {
540 mtx_unlock(&pcbp->sockdata->mtx);
541 error = EINVAL;
542 }
543
544 replymsg:
545 lwkt_replymsg(&msg->sockaddr.base.lmsg, error);
546 }
547
548 /*
549 * Attach a socket to it's protocol specific partner.
550 * For a control socket, actually create a netgraph node and attach
551 * to it as well.
552 */
553
554 static int
ng_attach_cntl(struct socket * so)555 ng_attach_cntl(struct socket *so)
556 {
557 struct ngsock *priv;
558 struct ngpcb *pcbp;
559 int error;
560
561 /* Allocate node private info */
562 priv = kmalloc(sizeof(*priv), M_NETGRAPH_SOCK, M_WAITOK | M_ZERO);
563
564 /* Setup protocol control block */
565 if ((error = ng_attach_common(so, NG_CONTROL)) != 0) {
566 kfree(priv, M_NETGRAPH_SOCK);
567 return (error);
568 }
569 pcbp = sotongpcb(so);
570
571 /* Link the pcb the private data. */
572 priv->ctlsock = pcbp;
573 pcbp->sockdata = priv;
574 priv->refs++;
575
576 /* Initialize mutex. */
577 mtx_init(&priv->mtx, "ng_socket");
578
579 /* Make the generic node components */
580 if ((error = ng_make_node_common(&typestruct, &priv->node)) != 0) {
581 kfree(priv, M_NETGRAPH_SOCK);
582 ng_detach_common(pcbp, NG_CONTROL);
583 return (error);
584 }
585
586 /* Link the node and the private data. */
587 NG_NODE_SET_PRIVATE(priv->node, priv);
588 NG_NODE_REF(priv->node);
589 priv->refs++;
590
591 return (0);
592 }
593
594 static int
ng_attach_data(struct socket * so)595 ng_attach_data(struct socket *so)
596 {
597 return (ng_attach_common(so, NG_DATA));
598 }
599
600 /*
601 * Set up a socket protocol control block.
602 * This code is shared between control and data sockets.
603 */
604 static int
ng_attach_common(struct socket * so,int type)605 ng_attach_common(struct socket *so, int type)
606 {
607 struct ngpcb *pcbp;
608 int error;
609
610 /* Standard socket setup stuff. */
611 error = soreserve(so, ngpdg_sendspace, ngpdg_recvspace, NULL);
612 if (error)
613 return (error);
614
615 /* Allocate the pcb. */
616 pcbp = kmalloc(sizeof(struct ngpcb), M_PCB, M_WAITOK | M_ZERO);
617 pcbp->type = type;
618
619 /* Link the pcb and the socket. */
620 so->so_pcb = (caddr_t)pcbp;
621 pcbp->ng_socket = so;
622
623 return (0);
624 }
625
626 /*
627 * Disassociate the socket from it's protocol specific
628 * partner. If it's attached to a node's private data structure,
629 * then unlink from that too. If we were the last socket attached to it,
630 * then shut down the entire node. Shared code for control and data sockets.
631 */
632 static void
ng_detach_common(struct ngpcb * pcbp,int which)633 ng_detach_common(struct ngpcb *pcbp, int which)
634 {
635 struct ngsock *priv = pcbp->sockdata;
636
637 if (priv != NULL) {
638 mtx_lock(&priv->mtx);
639
640 switch (which) {
641 case NG_CONTROL:
642 priv->ctlsock = NULL;
643 break;
644 case NG_DATA:
645 priv->datasock = NULL;
646 break;
647 default:
648 panic(__func__);
649 }
650 pcbp->sockdata = NULL;
651
652 ng_socket_free_priv(priv);
653 }
654
655 pcbp->ng_socket->so_pcb = NULL;
656 kfree(pcbp, M_PCB);
657 }
658
659 /*
660 * Remove a reference from node private data.
661 */
662 static void
ng_socket_free_priv(struct ngsock * priv)663 ng_socket_free_priv(struct ngsock *priv)
664 {
665 KKASSERT(mtx_owned(&priv->mtx));
666
667 priv->refs--;
668
669 if (priv->refs == 0) {
670 mtx_uninit(&priv->mtx);
671 kfree(priv, M_NETGRAPH_SOCK);
672 return;
673 }
674
675 if ((priv->refs == 1) && (priv->node != NULL)) {
676 node_p node = priv->node;
677
678 priv->node = NULL;
679 mtx_unlock(&priv->mtx);
680 NG_NODE_UNREF(node);
681 ng_rmnode_self(node);
682 } else
683 mtx_unlock(&priv->mtx);
684 }
685
686 #ifdef NOTYET
687 /*
688 * File descriptors can be passed into an AF_NETGRAPH socket.
689 * Note, that file descriptors cannot be passed OUT.
690 * Only character device descriptors are accepted.
691 * Character devices are useful to connect a graph to a device,
692 * which after all is the purpose of this whole system.
693 */
694 static int
ng_internalize(struct mbuf * control,struct thread * td)695 ng_internalize(struct mbuf *control, struct thread *td)
696 {
697 const struct cmsghdr *cm = mtod(control, const struct cmsghdr *);
698 struct file *fp;
699 struct vnode *vn;
700 int oldfds;
701 int fd;
702
703 if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET ||
704 cm->cmsg_len != control->m_len) {
705 TRAP_ERROR;
706 return (EINVAL);
707 }
708
709 /* Check there is only one FD. XXX what would more than one signify? */
710 oldfds = ((caddr_t)cm + cm->cmsg_len - (caddr_t)data) / sizeof (int);
711 if (oldfds != 1) {
712 TRAP_ERROR;
713 return (EINVAL);
714 }
715
716 /* Check that the FD given is legit. and change it to a pointer to a
717 * struct file. */
718 fd = CMSG_DATA(cm);
719 if ((error = fget(td, fd, &fp)) != 0)
720 return (error);
721
722 /* Depending on what kind of resource it is, act differently. For
723 * devices, we treat it as a file. For an AF_NETGRAPH socket,
724 * shortcut straight to the node. */
725 switch (fp->f_type) {
726 case DTYPE_VNODE:
727 vn = fp->f_data;
728 if (vn && (vn->v_type == VCHR)) {
729 /* for a VCHR, actually reference the FILE */
730 fhold(fp);
731 /* XXX then what :) */
732 /* how to pass on to other modules? */
733 } else {
734 fdrop(fp, td);
735 TRAP_ERROR;
736 return (EINVAL);
737 }
738 break;
739 default:
740 fdrop(fp, td);
741 TRAP_ERROR;
742 return (EINVAL);
743 }
744 fdrop(fp, td);
745 return (0);
746 }
747 #endif /* NOTYET */
748
749 /*
750 * Connect the data socket to a named control socket node.
751 */
752 static int
ng_connect_data(struct sockaddr * nam,struct ngpcb * pcbp)753 ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp)
754 {
755 struct sockaddr_ng *sap;
756 node_p farnode;
757 struct ngsock *priv;
758 int error;
759 item_p item;
760
761 /* If we are already connected, don't do it again. */
762 if (pcbp->sockdata != NULL)
763 return (EISCONN);
764
765 /*
766 * Find the target (victim) and check it doesn't already have
767 * a data socket. Also check it is a 'socket' type node.
768 * Use ng_package_data() and ng_address_path() to do this.
769 */
770
771 sap = (struct sockaddr_ng *) nam;
772 /* The item will hold the node reference. */
773 item = ng_package_data(NULL, NG_WAITOK);
774
775 if ((error = ng_address_path(NULL, item, sap->sg_data, 0))) {
776 ng_free_item(item);
777 return (error);
778 }
779
780 /*
781 * Extract node from item and free item. Remember we now have
782 * a reference on the node. The item holds it for us.
783 * when we free the item we release the reference.
784 */
785 farnode = item->el_dest; /* shortcut */
786 if (strcmp(farnode->nd_type->name, NG_SOCKET_NODE_TYPE) != 0) {
787 ng_free_item(item); /* drop the reference to the node */
788 return (EINVAL);
789 }
790 priv = NG_NODE_PRIVATE(farnode);
791 if (priv->datasock != NULL) {
792 ng_free_item(item); /* drop the reference to the node */
793 return (EADDRINUSE);
794 }
795
796 /*
797 * Link the PCB and the private data struct. and note the extra
798 * reference. Drop the extra reference on the node.
799 */
800 mtx_lock(&priv->mtx);
801 priv->datasock = pcbp;
802 pcbp->sockdata = priv;
803 priv->refs++;
804 mtx_unlock(&priv->mtx);
805 ng_free_item(item); /* drop the reference to the node */
806 return (0);
807 }
808
809 /*
810 * Binding a socket means giving the corresponding node a name
811 */
812 static int
ng_bind(struct sockaddr * nam,struct ngpcb * pcbp)813 ng_bind(struct sockaddr *nam, struct ngpcb *pcbp)
814 {
815 struct ngsock *const priv = pcbp->sockdata;
816 struct sockaddr_ng *const sap = (struct sockaddr_ng *) nam;
817
818 if (priv == NULL) {
819 TRAP_ERROR;
820 return (EINVAL);
821 }
822 if ((sap->sg_len < 4) || (sap->sg_len > (NG_NODESIZ + 2)) ||
823 (sap->sg_data[0] == '\0') ||
824 (sap->sg_data[sap->sg_len - 3] != '\0')) {
825 TRAP_ERROR;
826 return (EINVAL);
827 }
828 return (ng_name_node(priv->node, sap->sg_data));
829 }
830
831 /***************************************************************
832 Netgraph node
833 ***************************************************************/
834
835 /*
836 * You can only create new nodes from the socket end of things.
837 */
838 static int
ngs_constructor(node_p nodep)839 ngs_constructor(node_p nodep)
840 {
841 return (EINVAL);
842 }
843
844 /*
845 * We allow any hook to be connected to the node.
846 * There is no per-hook private information though.
847 */
848 static int
ngs_newhook(node_p node,hook_p hook,const char * name)849 ngs_newhook(node_p node, hook_p hook, const char *name)
850 {
851 NG_HOOK_SET_PRIVATE(hook, NG_NODE_PRIVATE(node));
852 return (0);
853 }
854
855 /*
856 * If only one hook, allow read(2) and write(2) to work.
857 */
858 static int
ngs_connect(hook_p hook)859 ngs_connect(hook_p hook)
860 {
861 node_p node = NG_HOOK_NODE(hook);
862 struct ngsock *priv = NG_NODE_PRIVATE(node);
863
864 if ((priv->datasock) && (priv->datasock->ng_socket)) {
865 if (NG_NODE_NUMHOOKS(node) == 1)
866 sosetstate(priv->datasock->ng_socket, SS_ISCONNECTED);
867 else
868 soclrstate(priv->datasock->ng_socket, SS_ISCONNECTED);
869 }
870 return (0);
871 }
872
873 /*
874 * Incoming messages get passed up to the control socket.
875 * Unless they are for us specifically (socket_type)
876 */
877 static int
ngs_rcvmsg(node_p node,item_p item,hook_p lasthook)878 ngs_rcvmsg(node_p node, item_p item, hook_p lasthook)
879 {
880 struct ngsock *const priv = NG_NODE_PRIVATE(node);
881 struct ngpcb *const pcbp = priv->ctlsock;
882 struct socket *so;
883 struct sockaddr_ng addr;
884 struct ng_mesg *msg;
885 struct mbuf *m;
886 ng_ID_t retaddr = NGI_RETADDR(item);
887 int addrlen;
888 int error = 0;
889
890 NGI_GET_MSG(item, msg);
891 NG_FREE_ITEM(item);
892
893 /*
894 * Only allow mesgs to be passed if we have the control socket.
895 * Data sockets can only support the generic messages.
896 */
897 if (pcbp == NULL) {
898 TRAP_ERROR;
899 NG_FREE_MSG(msg);
900 return (EINVAL);
901 }
902 so = pcbp->ng_socket;
903
904 #ifdef TRACE_MESSAGES
905 kprintf("[%x]:---------->[socket]: c=<%d>cmd=%x(%s) f=%x #%d\n",
906 retaddr,
907 msg->header.typecookie,
908 msg->header.cmd,
909 msg->header.cmdstr,
910 msg->header.flags,
911 msg->header.token);
912 #endif
913
914 if (msg->header.typecookie == NGM_SOCKET_COOKIE) {
915 switch (msg->header.cmd) {
916 case NGM_SOCK_CMD_NOLINGER:
917 priv->flags |= NGS_FLAG_NOLINGER;
918 break;
919 case NGM_SOCK_CMD_LINGER:
920 priv->flags &= ~NGS_FLAG_NOLINGER;
921 break;
922 default:
923 error = EINVAL; /* unknown command */
924 }
925 /* Free the message and return. */
926 NG_FREE_MSG(msg);
927 return (error);
928 }
929
930 /* Get the return address into a sockaddr. */
931 bzero(&addr, sizeof(addr));
932 addr.sg_len = sizeof(addr);
933 addr.sg_family = AF_NETGRAPH;
934 addrlen = ksnprintf((char *)&addr.sg_data, sizeof(addr.sg_data),
935 "[%x]:", retaddr);
936 if (addrlen < 0 || addrlen > sizeof(addr.sg_data)) {
937 kprintf("%s: ksnprintf([%x]) failed - %d\n", __func__, retaddr,
938 addrlen);
939 NG_FREE_MSG(msg);
940 return (EINVAL);
941 }
942
943 /* Copy the message itself into an mbuf chain. */
944 m = m_devget(msg, sizeof(struct ng_mesg) + msg->header.arglen, 0, NULL);
945
946 /*
947 * Here we free the message. We need to do that
948 * regardless of whether we got mbufs.
949 */
950 NG_FREE_MSG(msg);
951
952 if (m == NULL) {
953 TRAP_ERROR;
954 return (ENOBUFS);
955 }
956
957 /* Send it up to the socket. */
958 lwkt_gettoken(&so->so_rcv.ssb_token);
959 if (sbappendaddr((struct sockbuf *)&so->so_rcv, (struct sockaddr *)&addr, m, NULL) == 0) {
960 lwkt_reltoken(&so->so_rcv.ssb_token);
961 TRAP_ERROR;
962 m_freem(m);
963 return (ENOBUFS);
964 }
965 lwkt_reltoken(&so->so_rcv.ssb_token);
966 sorwakeup(so);
967
968 return (error);
969 }
970
971 /*
972 * Receive data on a hook
973 */
974 static int
ngs_rcvdata(hook_p hook,item_p item)975 ngs_rcvdata(hook_p hook, item_p item)
976 {
977 struct ngsock *const priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
978 struct ngpcb *const pcbp = priv->datasock;
979 struct socket *so;
980 struct sockaddr_ng *addr;
981 char *addrbuf[NG_HOOKSIZ + 4];
982 int addrlen;
983 struct mbuf *m;
984
985 NGI_GET_M(item, m);
986 NG_FREE_ITEM(item);
987
988 /* If there is no data socket, black-hole it. */
989 if (pcbp == NULL) {
990 NG_FREE_M(m);
991 return (0);
992 }
993 so = pcbp->ng_socket;
994
995 /* Get the return address into a sockaddr. */
996 addrlen = strlen(NG_HOOK_NAME(hook)); /* <= NG_HOOKSIZ - 1 */
997 addr = (struct sockaddr_ng *) addrbuf;
998 addr->sg_len = addrlen + 3;
999 addr->sg_family = AF_NETGRAPH;
1000 bcopy(NG_HOOK_NAME(hook), addr->sg_data, addrlen);
1001 addr->sg_data[addrlen] = '\0';
1002
1003 /* Try to tell the socket which hook it came in on. */
1004 lwkt_gettoken(&so->so_rcv.ssb_token);
1005 if (sbappendaddr((struct sockbuf *)&so->so_rcv, (struct sockaddr *)addr, m, NULL) == 0) {
1006 lwkt_reltoken(&so->so_rcv.ssb_token);
1007 m_freem(m);
1008 TRAP_ERROR;
1009 return (ENOBUFS);
1010 }
1011 lwkt_reltoken(&so->so_rcv.ssb_token);
1012 sorwakeup(so);
1013 return (0);
1014 }
1015
1016 /*
1017 * Hook disconnection
1018 *
1019 * For this type, removal of the last link destroys the node
1020 * if the NOLINGER flag is set.
1021 */
1022 static int
ngs_disconnect(hook_p hook)1023 ngs_disconnect(hook_p hook)
1024 {
1025 node_p node = NG_HOOK_NODE(hook);
1026 struct ngsock *const priv = NG_NODE_PRIVATE(node);
1027
1028 if ((priv->datasock) && (priv->datasock->ng_socket)) {
1029 if (NG_NODE_NUMHOOKS(node) == 1)
1030 sosetstate(priv->datasock->ng_socket, SS_ISCONNECTED);
1031 else
1032 soclrstate(priv->datasock->ng_socket, SS_ISCONNECTED);
1033 }
1034
1035 if ((priv->flags & NGS_FLAG_NOLINGER) &&
1036 (NG_NODE_NUMHOOKS(node) == 0) && (NG_NODE_IS_VALID(node)))
1037 ng_rmnode_self(node);
1038
1039 return (0);
1040 }
1041
1042 /*
1043 * Do local shutdown processing.
1044 * In this case, that involves making sure the socket
1045 * knows we should be shutting down.
1046 */
1047 static int
ngs_shutdown(node_p node)1048 ngs_shutdown(node_p node)
1049 {
1050 struct ngsock *const priv = NG_NODE_PRIVATE(node);
1051 struct ngpcb *const dpcbp = priv->datasock;
1052 struct ngpcb *const pcbp = priv->ctlsock;
1053
1054 if (dpcbp != NULL)
1055 soisdisconnected(dpcbp->ng_socket);
1056
1057 if (pcbp != NULL)
1058 soisdisconnected(pcbp->ng_socket);
1059
1060 mtx_lock(&priv->mtx);
1061 priv->node = NULL;
1062 NG_NODE_SET_PRIVATE(node, NULL);
1063 ng_socket_free_priv(priv);
1064
1065 NG_NODE_UNREF(node);
1066 return (0);
1067 }
1068
1069 static void
ng_socket_item_applied(void * context,int error)1070 ng_socket_item_applied(void *context, int error)
1071 {
1072 lwkt_msg *msg = context;
1073
1074 lwkt_replymsg(msg, error);
1075 }
1076
1077 /*
1078 * Control and data socket type descriptors
1079 *
1080 * XXXRW: Perhaps _close should do something?
1081 */
1082
1083 static struct pr_usrreqs ngc_usrreqs = {
1084 .pru_abort = NULL,
1085 .pru_attach = ngc_attach,
1086 .pru_bind = ngc_bind,
1087 .pru_connect = ngc_connect,
1088 .pru_detach = ngc_detach,
1089 .pru_disconnect = NULL,
1090 .pru_peeraddr = NULL,
1091 .pru_send = ngc_send,
1092 .pru_shutdown = NULL,
1093 .pru_sockaddr = ng_getsockaddr,
1094 .pru_sosend = sosend,
1095 .pru_soreceive = soreceive,
1096 /* .pru_close = NULL, */
1097 };
1098
1099 static struct pr_usrreqs ngd_usrreqs = {
1100 .pru_abort = NULL,
1101 .pru_attach = ngd_attach,
1102 .pru_bind = NULL,
1103 .pru_connect = ngd_connect,
1104 .pru_detach = ngd_detach,
1105 .pru_disconnect = NULL,
1106 .pru_peeraddr = NULL,
1107 .pru_send = ngd_send,
1108 .pru_shutdown = NULL,
1109 .pru_sockaddr = ng_getsockaddr,
1110 .pru_sosend = sosend,
1111 .pru_soreceive = soreceive,
1112 /* .pru_close = NULL, */
1113 };
1114
1115 /*
1116 * Definitions of protocols supported in the NETGRAPH domain.
1117 */
1118
1119 extern struct domain ngdomain; /* stop compiler warnings */
1120
1121 static struct protosw ngsw[] = {
1122 {
1123 .pr_type = SOCK_DGRAM,
1124 .pr_domain = &ngdomain,
1125 .pr_protocol = NG_CONTROL,
1126 .pr_flags = PR_ATOMIC | PR_ADDR /* | PR_RIGHTS */,
1127 .pr_usrreqs = &ngc_usrreqs
1128 },
1129 {
1130 .pr_type = SOCK_DGRAM,
1131 .pr_domain = &ngdomain,
1132 .pr_protocol = NG_DATA,
1133 .pr_flags = PR_ATOMIC | PR_ADDR,
1134 .pr_usrreqs = &ngd_usrreqs
1135 }
1136 };
1137
1138 struct domain ngdomain = {
1139 .dom_family = AF_NETGRAPH,
1140 .dom_name = "netgraph",
1141 .dom_protosw = ngsw,
1142 .dom_protoswNPROTOSW = &ngsw[NELEM(ngsw)]
1143 };
1144
1145 /*
1146 * Handle loading and unloading for this node type.
1147 * This is to handle auxiliary linkages (e.g protocol domain addition).
1148 */
1149 static int
ngs_mod_event(module_t mod,int event,void * data)1150 ngs_mod_event(module_t mod, int event, void *data)
1151 {
1152 int error = 0;
1153
1154 switch (event) {
1155 case MOD_LOAD:
1156 /* Register protocol domain. */
1157 net_add_domain(&ngdomain);
1158 break;
1159 case MOD_UNLOAD:
1160 #ifdef NOTYET
1161 /* Unregister protocol domain XXX can't do this yet.. */
1162 if ((error = net_rm_domain(&ngdomain)) != 0)
1163 break;
1164 else
1165 #endif
1166 error = EBUSY;
1167 break;
1168 default:
1169 error = EOPNOTSUPP;
1170 break;
1171 }
1172 return (error);
1173 }
1174
1175 static int
linker_api_available(void)1176 linker_api_available(void)
1177 {
1178 /* linker_* API won't work without a process context */
1179 if (curproc == NULL)
1180 return 0;
1181 /*
1182 * nlookup_init() relies on namei_oc to be initialized,
1183 * but it's not when the netgraph module is loaded during boot.
1184 */
1185 if (namei_oc == NULL)
1186 return 0;
1187 return 1;
1188 }
1189
1190 SYSCTL_INT(_net_graph, OID_AUTO, family, CTLFLAG_RD, 0, AF_NETGRAPH, "");
1191 SYSCTL_NODE(_net_graph, OID_AUTO, data, CTLFLAG_RW, 0, "DATA");
1192 SYSCTL_INT(_net_graph_data, OID_AUTO, proto, CTLFLAG_RD, 0, NG_DATA, "");
1193 SYSCTL_NODE(_net_graph, OID_AUTO, control, CTLFLAG_RW, 0, "CONTROL");
1194 SYSCTL_INT(_net_graph_control, OID_AUTO, proto, CTLFLAG_RD, 0, NG_CONTROL, "");
1195
1196