xref: /freebsd/sys/netgraph/ng_socket.c (revision 3047fefe49f57a673de8df152c199de12ec2c6d3)
1 
2 /*
3  * ng_socket.c
4  *
5  * Copyright (c) 1996-1999 Whistle Communications, Inc.
6  * All rights reserved.
7  *
8  * Subject to the following obligations and disclaimer of warranty, use and
9  * redistribution of this software, in source or object code forms, with or
10  * without modifications are expressly permitted by Whistle Communications;
11  * provided, however, that:
12  * 1. Any and all reproductions of the source or object code must include the
13  *    copyright notice above and the following disclaimer of warranties; and
14  * 2. No rights are granted, in any manner or form, to use Whistle
15  *    Communications, Inc. trademarks, including the mark "WHISTLE
16  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
17  *    such appears in the above copyright notice or in the software.
18  *
19  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
20  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
21  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
22  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
24  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
25  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
26  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
27  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
28  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
29  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
31  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
35  * OF SUCH DAMAGE.
36  *
37  * Author: Julian Elischer <julian@freebsd.org>
38  *
39  * $FreeBSD$
40  * $Whistle: ng_socket.c,v 1.28 1999/11/01 09:24:52 julian Exp $
41  */
42 
43 /*
44  * Netgraph socket nodes
45  *
46  * There are two types of netgraph sockets, control and data.
47  * Control sockets have a netgraph node, but data sockets are
48  * parasitic on control sockets, and have no node of their own.
49  */
50 
51 #include <sys/param.h>
52 #include <sys/domain.h>
53 #include <sys/errno.h>
54 #include <sys/kernel.h>
55 #include <sys/lock.h>
56 #include <sys/malloc.h>
57 #include <sys/mbuf.h>
58 #include <sys/protosw.h>
59 #include <sys/queue.h>
60 #include <sys/signalvar.h>
61 #include <sys/socket.h>
62 #include <sys/socketvar.h>
63 #include <sys/sx.h>
64 #include <sys/sysctl.h>
65 #include <sys/systm.h>
66 #ifdef NOTYET
67 #include <sys/vnode.h>
68 #endif
69 #include <netgraph/ng_message.h>
70 #include <netgraph/netgraph.h>
71 #include <netgraph/ng_socketvar.h>
72 #include <netgraph/ng_socket.h>
73 
74 #ifdef NG_SEPARATE_MALLOC
75 MALLOC_DEFINE(M_NETGRAPH_PATH, "netgraph_path", "netgraph path info ");
76 MALLOC_DEFINE(M_NETGRAPH_SOCK, "netgraph_sock", "netgraph socket info ");
77 #else
78 #define M_NETGRAPH_PATH M_NETGRAPH
79 #define M_NETGRAPH_SOCK M_NETGRAPH
80 #endif
81 
82 /*
83  * It's Ascii-art time!
84  *   +-------------+   +-------------+
85  *   |socket  (ctl)|   |socket (data)|
86  *   +-------------+   +-------------+
87  *          ^                 ^
88  *          |                 |
89  *          v                 v
90  *    +-----------+     +-----------+
91  *    |pcb   (ctl)|     |pcb  (data)|
92  *    +-----------+     +-----------+
93  *          ^                 ^
94  *          |                 |
95  *          v                 v
96  *      +--------------------------+
97  *      |   Socket type private    |
98  *      |       data               |
99  *      +--------------------------+
100  *                   ^
101  *                   |
102  *                   v
103  *           +----------------+
104  *           | struct ng_node |
105  *           +----------------+
106  */
107 
108 /* Netgraph node methods */
109 static ng_constructor_t	ngs_constructor;
110 static ng_rcvmsg_t	ngs_rcvmsg;
111 static ng_shutdown_t	ngs_shutdown;
112 static ng_newhook_t	ngs_newhook;
113 static ng_connect_t	ngs_connect;
114 static ng_rcvdata_t	ngs_rcvdata;
115 static ng_disconnect_t	ngs_disconnect;
116 
117 /* Internal methods */
118 static int	ng_attach_data(struct socket *so);
119 static int	ng_attach_cntl(struct socket *so);
120 static int	ng_attach_common(struct socket *so, int type);
121 static void	ng_detach_common(struct ngpcb *pcbp, int type);
122 /*static int	ng_internalize(struct mbuf *m, struct thread *p); */
123 
124 static int	ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp);
125 static int	ng_bind(struct sockaddr *nam, struct ngpcb *pcbp);
126 
127 static int	ngs_mod_event(module_t mod, int event, void *data);
128 static int	ship_msg(struct ngpcb *pcbp, struct ng_mesg *msg,
129 			struct sockaddr_ng *addr);
130 
131 /* Netgraph type descriptor */
132 static struct ng_type typestruct = {
133 	NG_ABI_VERSION,
134 	NG_SOCKET_NODE_TYPE,
135 	ngs_mod_event,
136 	ngs_constructor,
137 	ngs_rcvmsg,
138 	ngs_shutdown,
139 	ngs_newhook,
140 	NULL,
141 	ngs_connect,
142 	ngs_rcvdata,
143 	ngs_disconnect,
144 	NULL
145 };
146 NETGRAPH_INIT(socket, &typestruct);
147 
148 /* Buffer space */
149 static u_long ngpdg_sendspace = 20 * 1024;	/* really max datagram size */
150 static u_long ngpdg_recvspace = 20 * 1024;
151 
152 /* List of all sockets */
153 static LIST_HEAD(, ngpcb) ngsocklist;
154 
155 #define sotongpcb(so) ((struct ngpcb *)(so)->so_pcb)
156 
157 /* If getting unexplained errors returned, set this to "Debugger("X"); */
158 #ifndef TRAP_ERROR
159 #define TRAP_ERROR
160 #endif
161 
162 /***************************************************************
163 	Control sockets
164 ***************************************************************/
165 
166 static int
167 ngc_attach(struct socket *so, int proto, struct thread *td)
168 {
169 	struct ngpcb *const pcbp = sotongpcb(so);
170 
171 	if (suser(td))
172 		return (EPERM);
173 	if (pcbp != NULL)
174 		return (EISCONN);
175 	return (ng_attach_cntl(so));
176 }
177 
178 static int
179 ngc_detach(struct socket *so)
180 {
181 	struct ngpcb *const pcbp = sotongpcb(so);
182 
183 	if (pcbp == NULL)
184 		return (EINVAL);
185 	ng_detach_common(pcbp, NG_CONTROL);
186 	return (0);
187 }
188 
189 static int
190 ngc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
191 	 struct mbuf *control, struct thread *td)
192 {
193 	struct ngpcb *const pcbp = sotongpcb(so);
194 	struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
195 	struct ng_mesg *msg;
196 	struct mbuf *m0;
197 	char *path = NULL;
198 	int len, error = 0;
199 
200 	if (pcbp == NULL) {
201 		error = EINVAL;
202 		goto release;
203 	}
204 #ifdef	NOTYET
205 	if (control && (error = ng_internalize(control, td))) {
206 		if (pcbp->sockdata == NULL) {
207 			error = ENOTCONN;
208 			goto release;
209 		}
210 	}
211 #else	/* NOTYET */
212 	if (control) {
213 		error = EINVAL;
214 		goto release;
215 	}
216 #endif	/* NOTYET */
217 
218 	/* Require destination as there may be >= 1 hooks on this node */
219 	if (addr == NULL) {
220 		error = EDESTADDRREQ;
221 		goto release;
222 	}
223 
224 	/* Allocate an expendable buffer for the path, chop off
225 	 * the sockaddr header, and make sure it's NUL terminated */
226 	len = sap->sg_len - 2;
227 	MALLOC(path, char *, len + 1, M_NETGRAPH_PATH, M_WAITOK);
228 	if (path == NULL) {
229 		error = ENOMEM;
230 		goto release;
231 	}
232 	bcopy(sap->sg_data, path, len);
233 	path[len] = '\0';
234 
235 	/* Move the actual message out of mbufs into a linear buffer.
236 	 * Start by adding up the size of the data. (could use mh_len?) */
237 	for (len = 0, m0 = m; m0 != NULL; m0 = m0->m_next)
238 		len += m0->m_len;
239 
240 	/* Move the data into a linear buffer as well. Messages are not
241 	 * delivered in mbufs. */
242 	MALLOC(msg, struct ng_mesg *, len + 1, M_NETGRAPH_MSG, M_WAITOK);
243 	if (msg == NULL) {
244 		error = ENOMEM;
245 		goto release;
246 	}
247 	m_copydata(m, 0, len, (char *)msg);
248 
249 #ifdef TRACE_MESSAGES
250 	do {
251 		item_p item;
252 		if ((item = ng_package_msg(msg)) == NULL) {
253 			(msg) = NULL;
254 			(error) = ENOMEM;
255 printf("err=%d\n",error);
256 			break;
257 		}
258 		if (((error) = ng_address_path((pcbp->sockdata->node), (item),
259 					(path), (NULL))) == 0) {
260 printf("[%x]:<---------[socket]: c=<%d>cmd=%x(%s) f=%x #%d (%s)\n",
261 item->el_dest->nd_ID,
262 msg->header.typecookie,
263 msg->header.cmd,
264 msg->header.cmdstr,
265 msg->header.flags,
266 msg->header.token,
267 item->el_dest->nd_type->name);
268 			SAVE_LINE(item);
269 			(error) = ng_snd_item((item), 0);
270 		}
271 else {
272 printf("errx=%d\n",error);
273 }
274 		(msg) = NULL;
275 	} while (0);
276 
277 #else
278 	/* The callee will free the msg when done. The path is our business. */
279 	NG_SEND_MSG_PATH(error, pcbp->sockdata->node, msg, path, 0);
280 #endif
281 release:
282 	if (path != NULL)
283 		FREE(path, M_NETGRAPH_PATH);
284 	if (control != NULL)
285 		m_freem(control);
286 	if (m != NULL)
287 		m_freem(m);
288 	return (error);
289 }
290 
291 static int
292 ngc_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
293 {
294 	struct ngpcb *const pcbp = sotongpcb(so);
295 
296 	if (pcbp == 0)
297 		return (EINVAL);
298 	return (ng_bind(nam, pcbp));
299 }
300 
301 static int
302 ngc_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
303 {
304 printf(" program tried to connect control socket to remote node\n ");
305 	/*
306 	 * At this time refuse to do this.. it used to
307 	 * do something but it was undocumented and not used.
308 	 */
309 	return (EINVAL);
310 }
311 
312 /***************************************************************
313 	Data sockets
314 ***************************************************************/
315 
316 static int
317 ngd_attach(struct socket *so, int proto, struct thread *td)
318 {
319 	struct ngpcb *const pcbp = sotongpcb(so);
320 
321 	if (pcbp != NULL)
322 		return (EISCONN);
323 	return (ng_attach_data(so));
324 }
325 
326 static int
327 ngd_detach(struct socket *so)
328 {
329 	struct ngpcb *const pcbp = sotongpcb(so);
330 
331 	if (pcbp == NULL)
332 		return (EINVAL);
333 	ng_detach_common(pcbp, NG_DATA);
334 	return (0);
335 }
336 
337 static int
338 ngd_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
339 	 struct mbuf *control, struct thread *td)
340 {
341 	struct ngpcb *const pcbp = sotongpcb(so);
342 	struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
343 	int     len, error;
344 	hook_p  hook = NULL;
345 	char	hookname[NG_HOOKLEN + 1];
346 
347 	if ((pcbp == NULL) || (control != NULL)) {
348 		error = EINVAL;
349 		goto release;
350 	}
351 	if (pcbp->sockdata == NULL) {
352 		error = ENOTCONN;
353 		goto release;
354 	}
355 	/*
356 	 * If the user used any of these ways to not specify an address
357 	 * then handle specially.
358 	 */
359 	if ((sap == NULL)
360 	    || ((len = sap->sg_len - 2) <= 0)
361 	    || (*sap->sg_data == '\0')) {
362 		if (NG_NODE_NUMHOOKS(pcbp->sockdata->node) != 1) {
363 			error = EDESTADDRREQ;
364 			goto release;
365 		}
366 		/*
367 		 * if exactly one hook exists, just use it.
368 		 * Special case to allow write(2) to work on an ng_socket.
369 		 */
370 		hook = LIST_FIRST(&pcbp->sockdata->node->nd_hooks);
371 	} else {
372 		if (len > NG_HOOKLEN) {
373 			error = EINVAL;
374 			goto release;
375 		}
376 
377 		/*
378 		 * chop off the sockaddr header, and make sure it's NUL
379 		 * terminated
380 		 */
381 		bcopy(sap->sg_data, hookname, len);
382 		hookname[len] = '\0';
383 
384 		/* Find the correct hook from 'hookname' */
385 		LIST_FOREACH(hook, &pcbp->sockdata->node->nd_hooks, hk_hooks) {
386 			if (strcmp(hookname, NG_HOOK_NAME(hook)) == 0) {
387 				break;
388 			}
389 		}
390 		if (hook == NULL) {
391 			error = EHOSTUNREACH;
392 		}
393 	}
394 
395 	/* Send data (OK if hook is NULL) */
396 	NG_SEND_DATA_ONLY(error, hook, m);	/* makes m NULL */
397 
398 release:
399 	if (control != NULL)
400 		m_freem(control);
401 	if (m != NULL)
402 		m_freem(m);
403 	return (error);
404 }
405 
406 static int
407 ngd_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
408 {
409 	struct ngpcb *const pcbp = sotongpcb(so);
410 
411 	if (pcbp == 0)
412 		return (EINVAL);
413 	return (ng_connect_data(nam, pcbp));
414 }
415 
416 /*
417  * Used for both data and control sockets
418  */
419 static int
420 ng_setsockaddr(struct socket *so, struct sockaddr **addr)
421 {
422 	struct ngpcb *pcbp;
423 	struct sockaddr_ng *sg;
424 	int sg_len, namelen, s;
425 
426 	/* Why isn't sg_data a `char[1]' ? :-( */
427 	sg_len = sizeof(struct sockaddr_ng) - sizeof(sg->sg_data) + 1;
428 
429 	s = splnet();
430 	pcbp = sotongpcb(so);
431 	if ((pcbp == NULL) || (pcbp->sockdata == NULL)) {
432 		splx(s);
433 		return (EINVAL);
434 	}
435 
436 	namelen = 0;		/* silence compiler ! */
437 	if ( NG_NODE_HAS_NAME(pcbp->sockdata->node))
438 		sg_len += namelen = strlen(NG_NODE_NAME(pcbp->sockdata->node));
439 
440 	MALLOC(sg, struct sockaddr_ng *, sg_len, M_SONAME, M_WAITOK | M_ZERO);
441 
442 	if (NG_NODE_HAS_NAME(pcbp->sockdata->node))
443 		bcopy(NG_NODE_NAME(pcbp->sockdata->node), sg->sg_data, namelen);
444 	splx(s);
445 
446 	sg->sg_len = sg_len;
447 	sg->sg_family = AF_NETGRAPH;
448 	*addr = (struct sockaddr *)sg;
449 
450 	return (0);
451 }
452 
453 /*
454  * Attach a socket to it's protocol specific partner.
455  * For a control socket, actually create a netgraph node and attach
456  * to it as well.
457  */
458 
459 static int
460 ng_attach_cntl(struct socket *so)
461 {
462 	struct ngsock *privdata;
463 	struct ngpcb *pcbp;
464 	int error;
465 
466 	/* Setup protocol control block */
467 	if ((error = ng_attach_common(so, NG_CONTROL)) != 0)
468 		return (error);
469 	pcbp = sotongpcb(so);
470 
471 	/* Allocate node private info */
472 	MALLOC(privdata, struct ngsock *,
473 	    sizeof(*privdata), M_NETGRAPH_SOCK, M_WAITOK | M_ZERO);
474 	if (privdata == NULL) {
475 		ng_detach_common(pcbp, NG_CONTROL);
476 		return (ENOMEM);
477 	}
478 
479 	/* Make the generic node components */
480 	if ((error = ng_make_node_common(&typestruct, &privdata->node)) != 0) {
481 		FREE(privdata, M_NETGRAPH_SOCK);
482 		ng_detach_common(pcbp, NG_CONTROL);
483 		return (error);
484 	}
485 	NG_NODE_SET_PRIVATE(privdata->node, privdata);
486 
487 	/* Link the pcb and the node private data */
488 	privdata->ctlsock = pcbp;
489 	pcbp->sockdata = privdata;
490 	privdata->refs++;
491 	return (0);
492 }
493 
494 static int
495 ng_attach_data(struct socket *so)
496 {
497 	return(ng_attach_common(so, NG_DATA));
498 }
499 
500 /*
501  * Set up a socket protocol control block.
502  * This code is shared between control and data sockets.
503  */
504 static int
505 ng_attach_common(struct socket *so, int type)
506 {
507 	struct ngpcb *pcbp;
508 	int error;
509 
510 	/* Standard socket setup stuff */
511 	error = soreserve(so, ngpdg_sendspace, ngpdg_recvspace);
512 	if (error)
513 		return (error);
514 
515 	/* Allocate the pcb */
516 	MALLOC(pcbp, struct ngpcb *, sizeof(*pcbp), M_PCB, M_WAITOK | M_ZERO);
517 	if (pcbp == NULL)
518 		return (ENOMEM);
519 	pcbp->type = type;
520 
521 	/* Link the pcb and the socket */
522 	so->so_pcb = (caddr_t) pcbp;
523 	pcbp->ng_socket = so;
524 
525 	/* Add the socket to linked list */
526 	LIST_INSERT_HEAD(&ngsocklist, pcbp, socks);
527 	return (0);
528 }
529 
530 /*
531  * Disassociate the socket from it's protocol specific
532  * partner. If it's attached to a node's private data structure,
533  * then unlink from that too. If we were the last socket attached to it,
534  * then shut down the entire node. Shared code for control and data sockets.
535  */
536 static void
537 ng_detach_common(struct ngpcb *pcbp, int which)
538 {
539 	struct ngsock *priv;
540 
541 	if (pcbp->sockdata) {
542 		priv = pcbp->sockdata;
543 		pcbp->sockdata = NULL;
544 		switch (which) {
545 		case NG_CONTROL:
546 			priv->ctlsock = NULL;
547 			break;
548 		case NG_DATA:
549 			priv->datasock = NULL;
550 			break;
551 		default:
552 			panic(__func__);
553 		}
554 		if ((--priv->refs == 0) && (priv->node != NULL))
555 			ng_rmnode_self(priv->node);
556 	}
557 	pcbp->ng_socket->so_pcb = NULL;
558 	pcbp->ng_socket = NULL;
559 	LIST_REMOVE(pcbp, socks);
560 	FREE(pcbp, M_PCB);
561 }
562 
563 #ifdef NOTYET
564 /*
565  * File descriptors can be passed into a AF_NETGRAPH socket.
566  * Note, that file descriptors cannot be passed OUT.
567  * Only character device descriptors are accepted.
568  * Character devices are useful to connect a graph to a device,
569  * which after all is the purpose of this whole system.
570  */
571 static int
572 ng_internalize(struct mbuf *control, struct thread *td)
573 {
574 	const struct cmsghdr *cm = mtod(control, const struct cmsghdr *);
575 	struct file *fp;
576 	struct vnode *vn;
577 	int oldfds;
578 	int fd;
579 
580 	if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET ||
581 	    cm->cmsg_len != control->m_len) {
582 		TRAP_ERROR;
583 		return (EINVAL);
584 	}
585 
586 	/* Check there is only one FD. XXX what would more than one signify? */
587 	oldfds = ((caddr_t)cm + cm->cmsg_len - (caddr_t)data) / sizeof (int);
588 	if (oldfds != 1) {
589 		TRAP_ERROR;
590 		return (EINVAL);
591 	}
592 
593 	/* Check that the FD given is legit. and change it to a pointer to a
594 	 * struct file. */
595 	fd = CMSG_DATA(cm);
596 	if ((error = fget(td, fd, &fp)) != 0)
597 		return (error);
598 
599 	/* Depending on what kind of resource it is, act differently. For
600 	 * devices, we treat it as a file. For a AF_NETGRAPH socket,
601 	 * shortcut straight to the node. */
602 	switch (fp->f_type) {
603 	case DTYPE_VNODE:
604 		vn = (struct vnode *) fp->f_data;
605 		if (vn && (vn->v_type == VCHR)) {
606 			/* for a VCHR, actually reference the FILE */
607 			fp->f_count++;
608 			/* XXX then what :) */
609 			/* how to pass on to other modules? */
610 		} else {
611 			fdrop(fp, td);
612 			TRAP_ERROR;
613 			return (EINVAL);
614 		}
615 		break;
616 	default:
617 		fdrop(fp, td);
618 		TRAP_ERROR;
619 		return (EINVAL);
620 	}
621 	fdrop(fp, td);
622 	return (0);
623 }
624 #endif	/* NOTYET */
625 
626 /*
627  * Connect the data socket to a named control socket node.
628  */
629 static int
630 ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp)
631 {
632 	struct sockaddr_ng *sap;
633 	node_p farnode;
634 	struct ngsock *priv;
635 	int error;
636 	item_p item;
637 
638 	/* If we are already connected, don't do it again */
639 	if (pcbp->sockdata != NULL)
640 		return (EISCONN);
641 
642 	/* Find the target (victim) and check it doesn't already have a data
643 	 * socket. Also check it is a 'socket' type node.
644 	 * Use ng_package_data() and address_path() to do this.
645 	 */
646 
647 	sap = (struct sockaddr_ng *) nam;
648 	/* The item will hold the node reference */
649 	item = ng_package_data(NULL, NULL);
650 	if (item == NULL) {
651 		return (ENOMEM);
652 	}
653 	if ((error = ng_address_path(NULL, item,  sap->sg_data, 0)))
654 		return (error); /* item is freed on failure */
655 
656 	/*
657 	 * Extract node from item and free item. Remember we now have
658 	 * a reference on the node. The item holds it for us.
659 	 * when we free the item we release the reference.
660 	 */
661 	farnode = item->el_dest; /* shortcut */
662 	if (strcmp(farnode->nd_type->name, NG_SOCKET_NODE_TYPE) != 0) {
663 		NG_FREE_ITEM(item); /* drop the reference to the node */
664 		return (EINVAL);
665 	}
666 	priv = NG_NODE_PRIVATE(farnode);
667 	if (priv->datasock != NULL) {
668 		NG_FREE_ITEM(item);	/* drop the reference to the node */
669 		return (EADDRINUSE);
670 	}
671 
672 	/*
673 	 * Link the PCB and the private data struct. and note the extra
674 	 * reference. Drop the extra reference on the node.
675 	 */
676 	priv->datasock = pcbp;
677 	pcbp->sockdata = priv;
678 	priv->refs++; /* XXX possible race if it's being freed */
679 	NG_FREE_ITEM(item);	/* drop the reference to the node */
680 	return (0);
681 }
682 
683 /*
684  * Binding a socket means giving the corresponding node a name
685  */
686 static int
687 ng_bind(struct sockaddr *nam, struct ngpcb *pcbp)
688 {
689 	struct ngsock *const priv = pcbp->sockdata;
690 	struct sockaddr_ng *const sap = (struct sockaddr_ng *) nam;
691 
692 	if (priv == NULL) {
693 		TRAP_ERROR;
694 		return (EINVAL);
695 	}
696 	if ((sap->sg_len < 4)
697 	||  (sap->sg_len > (NG_NODELEN + 3))
698 	||  (sap->sg_data[0] == '\0')
699 	||  (sap->sg_data[sap->sg_len - 3] != '\0')) {
700 		TRAP_ERROR;
701 		return (EINVAL);
702 	}
703 	return (ng_name_node(priv->node, sap->sg_data));
704 }
705 
706 /*
707  * Take a message and pass it up to the control socket associated
708  * with the node.
709  */
710 static int
711 ship_msg(struct ngpcb *pcbp, struct ng_mesg *msg, struct sockaddr_ng *addr)
712 {
713 	struct socket *const so = pcbp->ng_socket;
714 	struct mbuf *mdata;
715 	int msglen;
716 
717 	/* Copy the message itself into an mbuf chain */
718 	msglen = sizeof(struct ng_mesg) + msg->header.arglen;
719 	mdata = m_devget((caddr_t) msg, msglen, 0, NULL, NULL);
720 
721 	/* Here we free the message, as we are the end of the line.
722 	 * We need to do that regardless of whether we got mbufs. */
723 	NG_FREE_MSG(msg);
724 
725 	if (mdata == NULL) {
726 		TRAP_ERROR;
727 		return (ENOBUFS);
728 	}
729 
730 	/* Send it up to the socket */
731 	if (sbappendaddr(&so->so_rcv,
732 	    (struct sockaddr *) addr, mdata, NULL) == 0) {
733 		TRAP_ERROR;
734 		m_freem(mdata);
735 		return (ENOBUFS);
736 	}
737 	sorwakeup(so);
738 	return (0);
739 }
740 
741 /*
742  * You can only create new nodes from the socket end of things.
743  */
744 static int
745 ngs_constructor(node_p nodep)
746 {
747 	return (EINVAL);
748 }
749 
750 /*
751  * We allow any hook to be connected to the node.
752  * There is no per-hook private information though.
753  */
754 static int
755 ngs_newhook(node_p node, hook_p hook, const char *name)
756 {
757 	NG_HOOK_SET_PRIVATE(hook, NG_NODE_PRIVATE(node));
758 	return (0);
759 }
760 
761 /*
762  * if only one hook, allow read(2) and write(2) to work.
763  */
764 static int
765 ngs_connect(hook_p hook)
766 {
767 	node_p node = NG_HOOK_NODE(hook);
768 	struct ngsock *priv = NG_NODE_PRIVATE(node);
769 
770 	if ((priv->datasock)
771 	&&  (priv->datasock->ng_socket)) {
772 		if (NG_NODE_NUMHOOKS(node) == 1) {
773 			priv->datasock->ng_socket->so_state |= SS_ISCONNECTED;
774 		} else {
775 			priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED;
776 		}
777 	}
778 	return (0);
779 }
780 
781 /*
782  * Incoming messages get passed up to the control socket.
783  * Unless they are for us specifically (socket_type)
784  */
785 static int
786 ngs_rcvmsg(node_p node, item_p item, hook_p lasthook)
787 {
788 	struct ngsock *const priv = NG_NODE_PRIVATE(node);
789 	struct ngpcb *const pcbp = priv->ctlsock;
790 	struct sockaddr_ng *addr;
791 	int addrlen;
792 	int error = 0;
793 	struct	ng_mesg *msg;
794 	ng_ID_t	retaddr = NGI_RETADDR(item);
795 	char	retabuf[32];
796 
797 	NGI_GET_MSG(item, msg);
798 	NG_FREE_ITEM(item); /* we have all we need */
799 
800 	/* Only allow mesgs to be passed if we have the control socket.
801 	 * Data sockets can only support the generic messages. */
802 	if (pcbp == NULL) {
803 		TRAP_ERROR;
804 		return (EINVAL);
805 	}
806 #ifdef TRACE_MESSAGES
807 printf("[%x]:---------->[socket]: c=<%d>cmd=%x(%s) f=%x #%d\n",
808 retaddr,
809 msg->header.typecookie,
810 msg->header.cmd,
811 msg->header.cmdstr,
812 msg->header.flags,
813 msg->header.token);
814 
815 #endif
816 
817 	if (msg->header.typecookie == NGM_SOCKET_COOKIE) {
818 		switch (msg->header.cmd) {
819 		case NGM_SOCK_CMD_NOLINGER:
820 			priv->flags |= NGS_FLAG_NOLINGER;
821 			break;
822 		case NGM_SOCK_CMD_LINGER:
823 			priv->flags &= ~NGS_FLAG_NOLINGER;
824 			break;
825 		default:
826 			error = EINVAL;		/* unknown command */
827 		}
828 		/* Free the message and return */
829 		NG_FREE_MSG(msg);
830 		return(error);
831 
832 	}
833 	/* Get the return address into a sockaddr */
834 	sprintf(retabuf,"[%x]:", retaddr);
835 	addrlen = strlen(retabuf);
836 	MALLOC(addr, struct sockaddr_ng *, addrlen + 4, M_NETGRAPH_PATH, M_NOWAIT);
837 	if (addr == NULL) {
838 		TRAP_ERROR;
839 		return (ENOMEM);
840 	}
841 	addr->sg_len = addrlen + 3;
842 	addr->sg_family = AF_NETGRAPH;
843 	bcopy(retabuf, addr->sg_data, addrlen);
844 	addr->sg_data[addrlen] = '\0';
845 
846 	/* Send it up */
847 	error = ship_msg(pcbp, msg, addr);
848 	FREE(addr, M_NETGRAPH_PATH);
849 	return (error);
850 }
851 
852 /*
853  * Receive data on a hook
854  */
855 static int
856 ngs_rcvdata(hook_p hook, item_p item)
857 {
858 	struct ngsock *const priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
859 	struct ngpcb *const pcbp = priv->datasock;
860 	struct socket *so;
861 	struct sockaddr_ng *addr;
862 	char *addrbuf[NG_HOOKLEN + 1 + 4];
863 	int addrlen;
864 	struct mbuf *m;
865 
866 	NGI_GET_M(item, m);
867 	NG_FREE_ITEM(item);
868 	/* If there is no data socket, black-hole it */
869 	if (pcbp == NULL) {
870 		NG_FREE_M(m);
871 		return (0);
872 	}
873 	so = pcbp->ng_socket;
874 
875 	/* Get the return address into a sockaddr. */
876 	addrlen = strlen(NG_HOOK_NAME(hook));	/* <= NG_HOOKLEN */
877 	addr = (struct sockaddr_ng *) addrbuf;
878 	addr->sg_len = addrlen + 3;
879 	addr->sg_family = AF_NETGRAPH;
880 	bcopy(NG_HOOK_NAME(hook), addr->sg_data, addrlen);
881 	addr->sg_data[addrlen] = '\0';
882 
883 	/* Try to tell the socket which hook it came in on */
884 	if (sbappendaddr(&so->so_rcv, (struct sockaddr *) addr, m, NULL) == 0) {
885 		m_freem(m);
886 		TRAP_ERROR;
887 		return (ENOBUFS);
888 	}
889 	sorwakeup(so);
890 	return (0);
891 }
892 
893 /*
894  * Hook disconnection
895  *
896  * For this type, removal of the last link destroys the node
897  * if the NOLINGER flag is set.
898  */
899 static int
900 ngs_disconnect(hook_p hook)
901 {
902 	node_p node = NG_HOOK_NODE(hook);
903 	struct ngsock *const priv = NG_NODE_PRIVATE(node);
904 
905 	if ((priv->datasock)
906 	&&  (priv->datasock->ng_socket)) {
907 		if (NG_NODE_NUMHOOKS(node) == 1) {
908 			priv->datasock->ng_socket->so_state |= SS_ISCONNECTED;
909 		} else {
910 			priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED;
911 		}
912 	}
913 
914 	if ((priv->flags & NGS_FLAG_NOLINGER )
915 	&& (NG_NODE_NUMHOOKS(node) == 0)
916 	&& (NG_NODE_IS_VALID(node))) {
917 		ng_rmnode_self(node);
918 	}
919 	return (0);
920 }
921 
922 /*
923  * Do local shutdown processing.
924  * In this case, that involves making sure the socket
925  * knows we should be shutting down.
926  */
927 static int
928 ngs_shutdown(node_p node)
929 {
930 	struct ngsock *const priv = NG_NODE_PRIVATE(node);
931 	struct ngpcb *const dpcbp = priv->datasock;
932 	struct ngpcb *const pcbp = priv->ctlsock;
933 
934 	if (dpcbp != NULL) {
935 		soisdisconnected(dpcbp->ng_socket);
936 		dpcbp->sockdata = NULL;
937 		priv->datasock = NULL;
938 		priv->refs--;
939 	}
940 	if (pcbp != NULL) {
941 		soisdisconnected(pcbp->ng_socket);
942 		pcbp->sockdata = NULL;
943 		priv->ctlsock = NULL;
944 		priv->refs--;
945 	}
946 	NG_NODE_SET_PRIVATE(node, NULL);
947 	NG_NODE_UNREF(node);
948 	FREE(priv, M_NETGRAPH_SOCK);
949 	return (0);
950 }
951 
952 static	int
953 dummy_disconnect(struct socket *so)
954 {
955 	return (0);
956 }
957 /*
958  * Control and data socket type descriptors
959  */
960 
961 static struct pr_usrreqs ngc_usrreqs = {
962 	NULL,			/* abort */
963 	pru_accept_notsupp,
964 	ngc_attach,
965 	ngc_bind,
966 	ngc_connect,
967 	pru_connect2_notsupp,
968 	pru_control_notsupp,
969 	ngc_detach,
970 	dummy_disconnect,	/* disconnect */
971 	pru_listen_notsupp,
972 	NULL,			/* setpeeraddr */
973 	pru_rcvd_notsupp,
974 	pru_rcvoob_notsupp,
975 	ngc_send,
976 	pru_sense_null,
977 	NULL,			/* shutdown */
978 	ng_setsockaddr,
979 	sosend,
980 	soreceive,
981 	sopoll
982 };
983 
984 static struct pr_usrreqs ngd_usrreqs = {
985 	NULL,			/* abort */
986 	pru_accept_notsupp,
987 	ngd_attach,
988 	NULL,			/* bind */
989 	ngd_connect,
990 	pru_connect2_notsupp,
991 	pru_control_notsupp,
992 	ngd_detach,
993 	dummy_disconnect,	/* disconnect */
994 	pru_listen_notsupp,
995 	NULL,			/* setpeeraddr */
996 	pru_rcvd_notsupp,
997 	pru_rcvoob_notsupp,
998 	ngd_send,
999 	pru_sense_null,
1000 	NULL,			/* shutdown */
1001 	ng_setsockaddr,
1002 	sosend,
1003 	soreceive,
1004 	sopoll
1005 };
1006 
1007 /*
1008  * Definitions of protocols supported in the NETGRAPH domain.
1009  */
1010 
1011 extern struct domain ngdomain;		/* stop compiler warnings */
1012 
1013 static struct protosw ngsw[] = {
1014 	{
1015 		SOCK_DGRAM,		/* protocol type */
1016 		&ngdomain,		/* backpointer to domain */
1017 		NG_CONTROL,
1018 		PR_ATOMIC | PR_ADDR /* | PR_RIGHTS */,	/* flags */
1019 		0, 0, 0, 0,		/* input, output, ctlinput, ctloutput */
1020 		NULL,			/* ousrreq */
1021 		0, 0, 0, 0,		/* init, fasttimeo, slowtimo, drain */
1022 		&ngc_usrreqs,		/* usrreq table (above) */
1023 		/*{NULL}*/		/* pffh (protocol filter head?) */
1024 	},
1025 	{
1026 		SOCK_DGRAM,		/* protocol type */
1027 		&ngdomain,		/* backpointer to domain */
1028 		NG_DATA,
1029 		PR_ATOMIC | PR_ADDR,	/* flags */
1030 		0, 0, 0, 0,		/* input, output, ctlinput, ctloutput */
1031 		NULL,			/* ousrreq() */
1032 		0, 0, 0, 0,		/* init, fasttimeo, slowtimo, drain */
1033 		&ngd_usrreqs,		/* usrreq table (above) */
1034 		/*{NULL}*/		/* pffh (protocol filter head?) */
1035 	}
1036 };
1037 
1038 struct domain ngdomain = {
1039 	AF_NETGRAPH,
1040 	"netgraph",
1041 	NULL,					/* init() */
1042 	NULL,					/* externalise() */
1043 	NULL,					/* dispose() */
1044 	ngsw,					/* protosw entry */
1045 	&ngsw[sizeof(ngsw) / sizeof(ngsw[0])], 	/* Number of protosw entries */
1046 	NULL,					/* next domain in list */
1047 	NULL,					/* rtattach() */
1048 	0,					/* arg to rtattach in bits */
1049 	0					/* maxrtkey */
1050 };
1051 
1052 /*
1053  * Handle loading and unloading for this node type
1054  * This is to handle auxiliary linkages (e.g protocol domain addition).
1055  */
1056 static int
1057 ngs_mod_event(module_t mod, int event, void *data)
1058 {
1059 	int error = 0;
1060 
1061 	switch (event) {
1062 	case MOD_LOAD:
1063 		/* Register protocol domain */
1064 		net_add_domain(&ngdomain);
1065 		break;
1066 	case MOD_UNLOAD:
1067 		/* Insure there are no open netgraph sockets */
1068 		if (!LIST_EMPTY(&ngsocklist)) {
1069 			error = EBUSY;
1070 			break;
1071 		}
1072 
1073 #ifdef NOTYET
1074 		if ((LIST_EMPTY(&ngsocklist)) && (typestruct.refs == 0)) {
1075 		/* Unregister protocol domain XXX can't do this yet.. */
1076 			if ((error = net_rm_domain(&ngdomain)) != 0)
1077 				break;
1078 		} else
1079 #endif
1080 			error = EBUSY;
1081 		break;
1082 	default:
1083 		error = EOPNOTSUPP;
1084 		break;
1085 	}
1086 	return (error);
1087 }
1088 
1089 SYSCTL_INT(_net_graph, OID_AUTO, family, CTLFLAG_RD, 0, AF_NETGRAPH, "");
1090 SYSCTL_NODE(_net_graph, OID_AUTO, data, CTLFLAG_RW, 0, "DATA");
1091 SYSCTL_INT(_net_graph_data, OID_AUTO, proto, CTLFLAG_RD, 0, NG_DATA, "");
1092 SYSCTL_NODE(_net_graph, OID_AUTO, control, CTLFLAG_RW, 0, "CONTROL");
1093 SYSCTL_INT(_net_graph_control, OID_AUTO, proto, CTLFLAG_RD, 0, NG_CONTROL, "");
1094 
1095