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