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