xref: /dflybsd-src/sys/netgraph7/socket/ng_socket.c (revision 05d02a3813e2bef176c69d68035311fd2efbd031)
10147868eSNuno Antunes /*
20147868eSNuno Antunes  * ng_socket.c
30147868eSNuno Antunes  */
40147868eSNuno Antunes 
50147868eSNuno Antunes /*-
60147868eSNuno Antunes  * Copyright (c) 1996-1999 Whistle Communications, Inc.
70147868eSNuno Antunes  * All rights reserved.
80147868eSNuno Antunes  *
90147868eSNuno Antunes  * Subject to the following obligations and disclaimer of warranty, use and
100147868eSNuno Antunes  * redistribution of this software, in source or object code forms, with or
110147868eSNuno Antunes  * without modifications are expressly permitted by Whistle Communications;
120147868eSNuno Antunes  * provided, however, that:
130147868eSNuno Antunes  * 1. Any and all reproductions of the source or object code must include the
140147868eSNuno Antunes  *    copyright notice above and the following disclaimer of warranties; and
150147868eSNuno Antunes  * 2. No rights are granted, in any manner or form, to use Whistle
160147868eSNuno Antunes  *    Communications, Inc. trademarks, including the mark "WHISTLE
170147868eSNuno Antunes  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
180147868eSNuno Antunes  *    such appears in the above copyright notice or in the software.
190147868eSNuno Antunes  *
200147868eSNuno Antunes  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
210147868eSNuno Antunes  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
220147868eSNuno Antunes  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
230147868eSNuno Antunes  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
240147868eSNuno Antunes  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
250147868eSNuno Antunes  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
260147868eSNuno Antunes  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
270147868eSNuno Antunes  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
280147868eSNuno Antunes  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
290147868eSNuno Antunes  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
300147868eSNuno Antunes  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
310147868eSNuno Antunes  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
320147868eSNuno Antunes  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
330147868eSNuno Antunes  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
340147868eSNuno Antunes  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
350147868eSNuno Antunes  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
360147868eSNuno Antunes  * OF SUCH DAMAGE.
370147868eSNuno Antunes  *
380147868eSNuno Antunes  * Author: Julian Elischer <julian@freebsd.org>
390147868eSNuno Antunes  *
400147868eSNuno Antunes  * $FreeBSD: src/sys/netgraph/ng_socket.c,v 1.85 2008/03/11 21:58:48 mav Exp $
410147868eSNuno Antunes  * $Whistle: ng_socket.c,v 1.28 1999/11/01 09:24:52 julian Exp $
420147868eSNuno Antunes  */
430147868eSNuno Antunes 
440147868eSNuno Antunes /*
450147868eSNuno Antunes  * Netgraph socket nodes
460147868eSNuno Antunes  *
470147868eSNuno Antunes  * There are two types of netgraph sockets, control and data.
480147868eSNuno Antunes  * Control sockets have a netgraph node, but data sockets are
490147868eSNuno Antunes  * parasitic on control sockets, and have no node of their own.
500147868eSNuno Antunes  */
510147868eSNuno Antunes 
520147868eSNuno Antunes #include <sys/domain.h>
530147868eSNuno Antunes #include <sys/kernel.h>
540147868eSNuno Antunes #include <sys/linker.h>
550147868eSNuno Antunes #include <sys/lock.h>
560147868eSNuno Antunes #include <sys/malloc.h>
570147868eSNuno Antunes #include <sys/mbuf.h>
58e858b308SNuno Antunes #include <sys/msgport2.h>
590147868eSNuno Antunes /*
600147868eSNuno Antunes #include <sys/mutex.h>
610147868eSNuno Antunes */
62e858b308SNuno Antunes #include <sys/param.h>
632b3f93eaSMatthew Dillon #include <sys/caps.h>
640147868eSNuno Antunes #include <sys/proc.h>
650147868eSNuno Antunes #include <sys/protosw.h>
660147868eSNuno Antunes #include <sys/queue.h>
670147868eSNuno Antunes #include <sys/socket.h>
680147868eSNuno Antunes #include <sys/socketvar.h>
69a48a177fSNuno Antunes #include <sys/socketvar2.h>
700147868eSNuno Antunes /*
710147868eSNuno Antunes #include <sys/syscallsubr.h>
720147868eSNuno Antunes */
730147868eSNuno Antunes #include <sys/sysctl.h>
740147868eSNuno Antunes #include <sys/vnode.h>
75ac58e50cSNuno Antunes 
760147868eSNuno Antunes #include <netgraph7/ng_message.h>
770147868eSNuno Antunes #include <netgraph7/netgraph.h>
780147868eSNuno Antunes #include "ng_socketvar.h"
790147868eSNuno Antunes #include "ng_socket.h"
800147868eSNuno Antunes 
810147868eSNuno Antunes #ifdef NG_SEPARATE_MALLOC
820147868eSNuno Antunes MALLOC_DEFINE(M_NETGRAPH_PATH, "netgraph_path", "netgraph path info ");
830147868eSNuno Antunes MALLOC_DEFINE(M_NETGRAPH_SOCK, "netgraph_sock", "netgraph socket info ");
840147868eSNuno Antunes #else
850147868eSNuno Antunes #define M_NETGRAPH_PATH M_NETGRAPH
860147868eSNuno Antunes #define M_NETGRAPH_SOCK M_NETGRAPH
870147868eSNuno Antunes #endif
880147868eSNuno Antunes 
890147868eSNuno Antunes /*
900147868eSNuno Antunes  * It's Ascii-art time!
910147868eSNuno Antunes  *   +-------------+   +-------------+
920147868eSNuno Antunes  *   |socket  (ctl)|   |socket (data)|
930147868eSNuno Antunes  *   +-------------+   +-------------+
940147868eSNuno Antunes  *          ^                 ^
950147868eSNuno Antunes  *          |                 |
960147868eSNuno Antunes  *          v                 v
970147868eSNuno Antunes  *    +-----------+     +-----------+
980147868eSNuno Antunes  *    |pcb   (ctl)|     |pcb  (data)|
990147868eSNuno Antunes  *    +-----------+     +-----------+
1000147868eSNuno Antunes  *          ^                 ^
1010147868eSNuno Antunes  *          |                 |
1020147868eSNuno Antunes  *          v                 v
1030147868eSNuno Antunes  *      +--------------------------+
1040147868eSNuno Antunes  *      |   Socket type private    |
1050147868eSNuno Antunes  *      |       data               |
1060147868eSNuno Antunes  *      +--------------------------+
1070147868eSNuno Antunes  *                   ^
1080147868eSNuno Antunes  *                   |
1090147868eSNuno Antunes  *                   v
1100147868eSNuno Antunes  *           +----------------+
1110147868eSNuno Antunes  *           | struct ng_node |
1120147868eSNuno Antunes  *           +----------------+
1130147868eSNuno Antunes  */
1140147868eSNuno Antunes 
1150147868eSNuno Antunes /* Netgraph node methods */
1160147868eSNuno Antunes static ng_constructor_t	ngs_constructor;
1170147868eSNuno Antunes static ng_rcvmsg_t	ngs_rcvmsg;
1180147868eSNuno Antunes static ng_shutdown_t	ngs_shutdown;
1190147868eSNuno Antunes static ng_newhook_t	ngs_newhook;
1200147868eSNuno Antunes static ng_connect_t	ngs_connect;
1210147868eSNuno Antunes static ng_rcvdata_t	ngs_rcvdata;
1220147868eSNuno Antunes static ng_disconnect_t	ngs_disconnect;
1230147868eSNuno Antunes 
1240147868eSNuno Antunes /* Internal methods */
1250147868eSNuno Antunes static int	ng_attach_data(struct socket *so);
1260147868eSNuno Antunes static int	ng_attach_cntl(struct socket *so);
1270147868eSNuno Antunes static int	ng_attach_common(struct socket *so, int type);
1280147868eSNuno Antunes static void	ng_detach_common(struct ngpcb *pcbp, int type);
1290147868eSNuno Antunes static void	ng_socket_free_priv(struct ngsock *priv);
1300147868eSNuno Antunes #ifdef NOTYET
1310147868eSNuno Antunes static int	ng_internalize(struct mbuf *m, struct thread *p);
1320147868eSNuno Antunes #endif
1330147868eSNuno Antunes static int	ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp);
1340147868eSNuno Antunes static int	ng_bind(struct sockaddr *nam, struct ngpcb *pcbp);
1350147868eSNuno Antunes 
1360147868eSNuno Antunes static int	ngs_mod_event(module_t mod, int event, void *data);
1370147868eSNuno Antunes static void	ng_socket_item_applied(void *context, int error);
138ac58e50cSNuno Antunes static int	linker_api_available(void);
1390147868eSNuno Antunes 
1400147868eSNuno Antunes /* Netgraph type descriptor */
1410147868eSNuno Antunes static struct ng_type typestruct = {
1420147868eSNuno Antunes 	.version =	NG_ABI_VERSION,
1430147868eSNuno Antunes 	.name =		NG_SOCKET_NODE_TYPE,
1440147868eSNuno Antunes 	.mod_event =	ngs_mod_event,
1450147868eSNuno Antunes 	.constructor =	ngs_constructor,
1460147868eSNuno Antunes 	.rcvmsg =	ngs_rcvmsg,
1470147868eSNuno Antunes 	.shutdown =	ngs_shutdown,
1480147868eSNuno Antunes 	.newhook =	ngs_newhook,
1490147868eSNuno Antunes 	.connect =	ngs_connect,
1500147868eSNuno Antunes 	.rcvdata =	ngs_rcvdata,
1510147868eSNuno Antunes 	.disconnect =	ngs_disconnect,
1520147868eSNuno Antunes };
1530147868eSNuno Antunes NETGRAPH_INIT_ORDERED(socket, &typestruct, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
1540147868eSNuno Antunes 
1550147868eSNuno Antunes /* Buffer space */
1560147868eSNuno Antunes static u_long ngpdg_sendspace = 20 * 1024;	/* really max datagram size */
1570147868eSNuno Antunes SYSCTL_INT(_net_graph, OID_AUTO, maxdgram, CTLFLAG_RW,
1580147868eSNuno Antunes     &ngpdg_sendspace , 0, "Maximum outgoing Netgraph datagram size");
1590147868eSNuno Antunes static u_long ngpdg_recvspace = 20 * 1024;
1600147868eSNuno Antunes SYSCTL_INT(_net_graph, OID_AUTO, recvspace, CTLFLAG_RW,
1610147868eSNuno Antunes     &ngpdg_recvspace , 0, "Maximum space for incoming Netgraph datagrams");
1620147868eSNuno Antunes 
1630147868eSNuno Antunes #define sotongpcb(so) ((struct ngpcb *)(so)->so_pcb)
1640147868eSNuno Antunes 
1650147868eSNuno Antunes /* If getting unexplained errors returned, set this to "kdb_enter("X"); */
1660147868eSNuno Antunes #ifndef TRAP_ERROR
1670147868eSNuno Antunes #define TRAP_ERROR
1680147868eSNuno Antunes #endif
1690147868eSNuno Antunes 
1700147868eSNuno Antunes /***************************************************************
1710147868eSNuno Antunes 	Control sockets
1720147868eSNuno Antunes ***************************************************************/
1730147868eSNuno Antunes 
174e858b308SNuno Antunes static void
ngc_attach(netmsg_t msg)175e858b308SNuno Antunes ngc_attach(netmsg_t msg)
1760147868eSNuno Antunes {
177e858b308SNuno Antunes 	struct socket *so = msg->attach.base.nm_so;
178e858b308SNuno Antunes 	struct pru_attach_info *ai = msg->attach.nm_ai;
1790147868eSNuno Antunes 	struct ngpcb *const pcbp = sotongpcb(so);
180e858b308SNuno Antunes 	int error;
1810147868eSNuno Antunes 
1822b3f93eaSMatthew Dillon 	if (caps_priv_check(ai->p_ucred,
1832b3f93eaSMatthew Dillon 			    SYSCAP_RESTRICTEDROOT | __SYSCAP_NULLCRED))
1842b3f93eaSMatthew Dillon 	{
185e858b308SNuno Antunes 		error = EPERM;
1862b3f93eaSMatthew Dillon 	} else if (pcbp != NULL) {
187e858b308SNuno Antunes 		error = EISCONN;
1882b3f93eaSMatthew Dillon 	} else {
189e858b308SNuno Antunes 		error = ng_attach_cntl(so);
1902b3f93eaSMatthew Dillon 	}
191e858b308SNuno Antunes 	lwkt_replymsg(&msg->attach.base.lmsg, error);
1920147868eSNuno Antunes }
1930147868eSNuno Antunes 
194e858b308SNuno Antunes static void
ngc_detach(netmsg_t msg)195e858b308SNuno Antunes ngc_detach(netmsg_t msg)
1960147868eSNuno Antunes {
197e858b308SNuno Antunes 	struct socket *so = msg->detach.base.nm_so;
1980147868eSNuno Antunes 	struct ngpcb *const pcbp = sotongpcb(so);
1990147868eSNuno Antunes 
2000147868eSNuno Antunes 	KASSERT(pcbp != NULL, ("ngc_detach: pcbp == NULL"));
2010147868eSNuno Antunes 	ng_detach_common(pcbp, NG_CONTROL);
202e858b308SNuno Antunes 	lwkt_replymsg(&msg->detach.base.lmsg, 0);
2030147868eSNuno Antunes }
2040147868eSNuno Antunes 
205e858b308SNuno Antunes static void
ngc_send(netmsg_t netmsg)206e858b308SNuno Antunes ngc_send(netmsg_t netmsg)
2070147868eSNuno Antunes {
208e858b308SNuno Antunes 	struct socket *so = netmsg->send.base.nm_so;
209e858b308SNuno Antunes 	struct mbuf *m = netmsg->send.nm_m;
210e858b308SNuno Antunes 	struct sockaddr *addr = netmsg->send.nm_addr;
211e858b308SNuno Antunes 	struct mbuf *control = netmsg->send.nm_control;
2120147868eSNuno Antunes 	struct ngpcb *const pcbp = sotongpcb(so);
2130147868eSNuno Antunes 	struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
2140147868eSNuno Antunes 	struct ng_mesg *msg;
2150147868eSNuno Antunes 	struct mbuf *m0;
2160147868eSNuno Antunes 	item_p item;
2170147868eSNuno Antunes 	char *path = NULL;
2180147868eSNuno Antunes 	int len, error = 0;
219ad9efc7bSNuno Antunes 	struct ng_apply_info *apply;
2200147868eSNuno Antunes 
2210147868eSNuno Antunes #ifdef	NOTYET
2220147868eSNuno Antunes 	if (control && (error = ng_internalize(control, td))) {
2230147868eSNuno Antunes 		if (pcbp->sockdata == NULL) {
2240147868eSNuno Antunes 			error = ENOTCONN;
2250147868eSNuno Antunes 			goto release;
2260147868eSNuno Antunes 		}
2270147868eSNuno Antunes 	}
2280147868eSNuno Antunes #else	/* NOTYET */
2290147868eSNuno Antunes 	if (control) {
2300147868eSNuno Antunes 		error = EINVAL;
2310147868eSNuno Antunes 		goto release;
2320147868eSNuno Antunes 	}
2330147868eSNuno Antunes #endif	/* NOTYET */
2340147868eSNuno Antunes 
2350147868eSNuno Antunes 	/* Require destination as there may be >= 1 hooks on this node. */
2360147868eSNuno Antunes 	if (addr == NULL) {
2370147868eSNuno Antunes 		error = EDESTADDRREQ;
2380147868eSNuno Antunes 		goto release;
2390147868eSNuno Antunes 	}
2400147868eSNuno Antunes 
2410147868eSNuno Antunes 	/*
2420147868eSNuno Antunes 	 * Allocate an expendable buffer for the path, chop off
2430147868eSNuno Antunes 	 * the sockaddr header, and make sure it's NUL terminated.
2440147868eSNuno Antunes 	 */
2450147868eSNuno Antunes 	len = sap->sg_len - 2;
2460147868eSNuno Antunes 	path = kmalloc(len + 1, M_NETGRAPH_PATH, M_WAITOK);
2470147868eSNuno Antunes 	bcopy(sap->sg_data, path, len);
2480147868eSNuno Antunes 	path[len] = '\0';
2490147868eSNuno Antunes 
2500147868eSNuno Antunes 	/*
2510147868eSNuno Antunes 	 * Move the actual message out of mbufs into a linear buffer.
2520147868eSNuno Antunes 	 * Start by adding up the size of the data. (could use mh_len?)
2530147868eSNuno Antunes 	 */
2540147868eSNuno Antunes 	for (len = 0, m0 = m; m0 != NULL; m0 = m0->m_next)
2550147868eSNuno Antunes 		len += m0->m_len;
2560147868eSNuno Antunes 
2570147868eSNuno Antunes 	/*
2580147868eSNuno Antunes 	 * Move the data into a linear buffer as well.
2590147868eSNuno Antunes 	 * Messages are not delivered in mbufs.
2600147868eSNuno Antunes 	 */
2610147868eSNuno Antunes 	msg = kmalloc(len + 1, M_NETGRAPH_MSG, M_WAITOK);
262*05d02a38SAaron LI 	m_copydata(m, 0, len, msg);
2630147868eSNuno Antunes 
2640147868eSNuno Antunes 	if (msg->header.version != NG_VERSION) {
2650147868eSNuno Antunes 		kfree(msg, M_NETGRAPH_MSG);
2660147868eSNuno Antunes 		error = EINVAL;
2670147868eSNuno Antunes 		goto release;
2680147868eSNuno Antunes 	}
2690147868eSNuno Antunes 
2700147868eSNuno Antunes 	/*
2710147868eSNuno Antunes 	 * Hack alert!
2720147868eSNuno Antunes 	 * We look into the message and if it mkpeers a node of unknown type, we
2730147868eSNuno Antunes 	 * try to load it. We need to do this now, in syscall thread, because if
2740147868eSNuno Antunes 	 * message gets queued and applied later we will get panic.
2750147868eSNuno Antunes 	 */
2760147868eSNuno Antunes 	if (msg->header.typecookie == NGM_GENERIC_COOKIE &&
2770147868eSNuno Antunes 	    msg->header.cmd == NGM_MKPEER) {
2780147868eSNuno Antunes 		struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) msg->data;
2790147868eSNuno Antunes 		struct ng_type *type;
2800147868eSNuno Antunes 
2810147868eSNuno Antunes 		if ((type = ng_findtype(mkp->type)) == NULL) {
2820147868eSNuno Antunes 			char filename[NG_TYPESIZ + 3];
2830147868eSNuno Antunes 			linker_file_t fileid;
2840147868eSNuno Antunes 
285e858b308SNuno Antunes 			if (!linker_api_available()) {
286e858b308SNuno Antunes 				error = ENXIO;
287e858b308SNuno Antunes 				goto done;
288e858b308SNuno Antunes 			}
2890147868eSNuno Antunes 
2900147868eSNuno Antunes 			/* Not found, try to load it as a loadable module. */
291a62226e4SSascha Wildner 			ksnprintf(filename, sizeof(filename), "ng_%s.ko",
2920147868eSNuno Antunes 			    mkp->type);
2930147868eSNuno Antunes 			error = linker_load_file(filename, &fileid);
2940147868eSNuno Antunes 			if (error != 0) {
2950147868eSNuno Antunes 				kfree(msg, M_NETGRAPH_MSG);
2960147868eSNuno Antunes 				goto release;
2970147868eSNuno Antunes 			}
2980147868eSNuno Antunes 
2990147868eSNuno Antunes 			/* See if type has been loaded successfully. */
3000147868eSNuno Antunes 			if ((type = ng_findtype(mkp->type)) == NULL) {
3010147868eSNuno Antunes 				kfree(msg, M_NETGRAPH_MSG);
3020147868eSNuno Antunes 				(void)linker_file_unload(fileid);
3030147868eSNuno Antunes 				error =  ENXIO;
3040147868eSNuno Antunes 				goto release;
3050147868eSNuno Antunes 			}
3060147868eSNuno Antunes 		}
3070147868eSNuno Antunes 	}
3080147868eSNuno Antunes 
3090147868eSNuno Antunes 	item = ng_package_msg(msg, NG_WAITOK);
3100147868eSNuno Antunes 	if ((error = ng_address_path((pcbp->sockdata->node), item, path, 0))
3110147868eSNuno Antunes 	    != 0) {
3120147868eSNuno Antunes #ifdef TRACE_MESSAGES
313a62226e4SSascha Wildner 		kprintf("ng_address_path: errx=%d\n", error);
3140147868eSNuno Antunes #endif
3150147868eSNuno Antunes 		goto release;
3160147868eSNuno Antunes 	}
3170147868eSNuno Antunes 
3180147868eSNuno Antunes #ifdef TRACE_MESSAGES
319a62226e4SSascha Wildner 	kprintf("[%x]:<---------[socket]: c=<%d>cmd=%x(%s) f=%x #%d (%s)\n",
3200147868eSNuno Antunes 		item->el_dest->nd_ID,
3210147868eSNuno Antunes 		msg->header.typecookie,
3220147868eSNuno Antunes 		msg->header.cmd,
3230147868eSNuno Antunes 		msg->header.cmdstr,
3240147868eSNuno Antunes 		msg->header.flags,
3250147868eSNuno Antunes 		msg->header.token,
3260147868eSNuno Antunes 		item->el_dest->nd_type->name);
3270147868eSNuno Antunes #endif
3280147868eSNuno Antunes 	SAVE_LINE(item);
329ad9efc7bSNuno Antunes 
3300147868eSNuno Antunes 	/*
331ad9efc7bSNuno Antunes 	 * We do not want the user thread to return from syscall until the
332ad9efc7bSNuno Antunes 	 * item is processed by destination node.  We register callback
333ad9efc7bSNuno Antunes 	 * on the item, which will reply to the user thread when item
3340147868eSNuno Antunes 	 * was applied.
3350147868eSNuno Antunes 	 */
336ad9efc7bSNuno Antunes 	apply = ng_alloc_apply();
337ad9efc7bSNuno Antunes 	bzero(apply, sizeof(*apply));
338ad9efc7bSNuno Antunes 	apply->apply = ng_socket_item_applied;
339ad9efc7bSNuno Antunes 	apply->context = &netmsg->send.base.lmsg;
340ad9efc7bSNuno Antunes 	item->apply = apply;
3410147868eSNuno Antunes 
342ad9efc7bSNuno Antunes 	error = ng_snd_item(item, NG_PROGRESS);
3430147868eSNuno Antunes 
3440147868eSNuno Antunes release:
3450147868eSNuno Antunes 	if (path != NULL)
3460147868eSNuno Antunes 		kfree(path, M_NETGRAPH_PATH);
3470147868eSNuno Antunes 	if (control != NULL)
3480147868eSNuno Antunes 		m_freem(control);
3490147868eSNuno Antunes 	if (m != NULL)
3500147868eSNuno Antunes 		m_freem(m);
351e858b308SNuno Antunes done:
352ad9efc7bSNuno Antunes 	if (error != EINPROGRESS)
353e858b308SNuno Antunes 		lwkt_replymsg(&netmsg->send.base.lmsg, error);
3540147868eSNuno Antunes }
3550147868eSNuno Antunes 
356e858b308SNuno Antunes static void
ngc_bind(netmsg_t msg)357e858b308SNuno Antunes ngc_bind(netmsg_t msg)
3580147868eSNuno Antunes {
359e858b308SNuno Antunes 	struct socket *so = msg->connect.base.nm_so;
360e858b308SNuno Antunes 	struct sockaddr *nam = msg->connect.nm_nam;
3610147868eSNuno Antunes 	struct ngpcb *const pcbp = sotongpcb(so);
362e858b308SNuno Antunes 	int error;
3630147868eSNuno Antunes 
3640147868eSNuno Antunes 	if (pcbp == NULL)
365e858b308SNuno Antunes 		error = EINVAL;
366e858b308SNuno Antunes 	else
367e858b308SNuno Antunes 		error = ng_bind(nam, pcbp);
368e858b308SNuno Antunes 	lwkt_replymsg(&msg->connect.base.lmsg, error);
3690147868eSNuno Antunes }
3700147868eSNuno Antunes 
371e858b308SNuno Antunes static void
ngc_connect(netmsg_t msg)372e858b308SNuno Antunes ngc_connect(netmsg_t msg)
3730147868eSNuno Antunes {
3740147868eSNuno Antunes 	/*
3750147868eSNuno Antunes 	 * At this time refuse to do this.. it used to
3760147868eSNuno Antunes 	 * do something but it was undocumented and not used.
3770147868eSNuno Antunes 	 */
378a62226e4SSascha Wildner 	kprintf("program tried to connect control socket to remote node\n");
379e858b308SNuno Antunes 	lwkt_replymsg(&msg->connect.base.lmsg, EINVAL);
3800147868eSNuno Antunes }
3810147868eSNuno Antunes 
3820147868eSNuno Antunes /***************************************************************
3830147868eSNuno Antunes 	Data sockets
3840147868eSNuno Antunes ***************************************************************/
3850147868eSNuno Antunes 
386e858b308SNuno Antunes static void
ngd_attach(netmsg_t msg)387e858b308SNuno Antunes ngd_attach(netmsg_t msg)
3880147868eSNuno Antunes {
389e858b308SNuno Antunes 	struct socket *so = msg->attach.base.nm_so;
3900147868eSNuno Antunes 	struct ngpcb *const pcbp = sotongpcb(so);
391e858b308SNuno Antunes 	int error;
3920147868eSNuno Antunes 
3930147868eSNuno Antunes 	if (pcbp != NULL)
394e858b308SNuno Antunes 		error =  EISCONN;
395e858b308SNuno Antunes 	else
396e858b308SNuno Antunes 		error = ng_attach_data(so);
397e858b308SNuno Antunes 	lwkt_replymsg(&msg->connect.base.lmsg, error);
3980147868eSNuno Antunes }
3990147868eSNuno Antunes 
400e858b308SNuno Antunes static void
ngd_detach(netmsg_t msg)401e858b308SNuno Antunes ngd_detach(netmsg_t msg)
4020147868eSNuno Antunes {
403e858b308SNuno Antunes 	struct socket *so = msg->detach.base.nm_so;
4040147868eSNuno Antunes 	struct ngpcb *const pcbp = sotongpcb(so);
4050147868eSNuno Antunes 
4060147868eSNuno Antunes 	KASSERT(pcbp != NULL, ("ngd_detach: pcbp == NULL"));
4070147868eSNuno Antunes 	ng_detach_common(pcbp, NG_DATA);
408e858b308SNuno Antunes 	lwkt_replymsg(&msg->detach.base.lmsg, 0);
4090147868eSNuno Antunes }
4100147868eSNuno Antunes 
411e858b308SNuno Antunes static void
ngd_send(netmsg_t msg)412e858b308SNuno Antunes ngd_send(netmsg_t msg)
4130147868eSNuno Antunes {
414e858b308SNuno Antunes 	struct socket *so = msg->send.base.nm_so;
415e858b308SNuno Antunes 	struct mbuf *m = msg->send.nm_m;
416e858b308SNuno Antunes 	struct sockaddr *addr = msg->send.nm_addr;
417e858b308SNuno Antunes 	struct mbuf *control = msg->send.nm_control;
4180147868eSNuno Antunes 	struct ngpcb *const pcbp = sotongpcb(so);
4190147868eSNuno Antunes 	struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
4200147868eSNuno Antunes 	int	len, error;
4210147868eSNuno Antunes 	hook_p  hook = NULL;
4220147868eSNuno Antunes 	char	hookname[NG_HOOKSIZ];
4230147868eSNuno Antunes 
4240147868eSNuno Antunes 	if ((pcbp == NULL) || (control != NULL)) {
4250147868eSNuno Antunes 		error = EINVAL;
4260147868eSNuno Antunes 		goto release;
4270147868eSNuno Antunes 	}
4280147868eSNuno Antunes 	if (pcbp->sockdata == NULL) {
4290147868eSNuno Antunes 		error = ENOTCONN;
4300147868eSNuno Antunes 		goto release;
4310147868eSNuno Antunes 	}
4320147868eSNuno Antunes 
4330147868eSNuno Antunes 	if (sap == NULL)
4340147868eSNuno Antunes 		len = 0;		/* Make compiler happy. */
4350147868eSNuno Antunes 	else
4360147868eSNuno Antunes 		len = sap->sg_len - 2;
4370147868eSNuno Antunes 
4380147868eSNuno Antunes 	/*
4390147868eSNuno Antunes 	 * If the user used any of these ways to not specify an address
4400147868eSNuno Antunes 	 * then handle specially.
4410147868eSNuno Antunes 	 */
4420147868eSNuno Antunes 	if ((sap == NULL) || (len <= 0) || (*sap->sg_data == '\0')) {
4430147868eSNuno Antunes 		if (NG_NODE_NUMHOOKS(pcbp->sockdata->node) != 1) {
4440147868eSNuno Antunes 			error = EDESTADDRREQ;
4450147868eSNuno Antunes 			goto release;
4460147868eSNuno Antunes 		}
4470147868eSNuno Antunes 		/*
4480147868eSNuno Antunes 		 * If exactly one hook exists, just use it.
4490147868eSNuno Antunes 		 * Special case to allow write(2) to work on an ng_socket.
4500147868eSNuno Antunes 		 */
4510147868eSNuno Antunes 		hook = LIST_FIRST(&pcbp->sockdata->node->nd_hooks);
4520147868eSNuno Antunes 	} else {
4530147868eSNuno Antunes 		if (len >= NG_HOOKSIZ) {
4540147868eSNuno Antunes 			error = EINVAL;
4550147868eSNuno Antunes 			goto release;
4560147868eSNuno Antunes 		}
4570147868eSNuno Antunes 
4580147868eSNuno Antunes 		/*
4590147868eSNuno Antunes 		 * chop off the sockaddr header, and make sure it's NUL
4600147868eSNuno Antunes 		 * terminated
4610147868eSNuno Antunes 		 */
4620147868eSNuno Antunes 		bcopy(sap->sg_data, hookname, len);
4630147868eSNuno Antunes 		hookname[len] = '\0';
4640147868eSNuno Antunes 
4650147868eSNuno Antunes 		/* Find the correct hook from 'hookname' */
4660147868eSNuno Antunes 		hook = ng_findhook(pcbp->sockdata->node, hookname);
4670147868eSNuno Antunes 		if (hook == NULL) {
4680147868eSNuno Antunes 			error = EHOSTUNREACH;
4690147868eSNuno Antunes 			goto release;
4700147868eSNuno Antunes 		}
4710147868eSNuno Antunes 	}
4720147868eSNuno Antunes 
4730147868eSNuno Antunes 	/* Send data. */
4740147868eSNuno Antunes 	NG_SEND_DATA_FLAGS(error, hook, m, NG_WAITOK);
4750147868eSNuno Antunes 
4760147868eSNuno Antunes release:
4770147868eSNuno Antunes 	if (control != NULL)
4780147868eSNuno Antunes 		m_freem(control);
4790147868eSNuno Antunes 	if (m != NULL)
4800147868eSNuno Antunes 		m_freem(m);
481e858b308SNuno Antunes 	lwkt_replymsg(&msg->send.base.lmsg, error);
4820147868eSNuno Antunes }
4830147868eSNuno Antunes 
484e858b308SNuno Antunes static void
ngd_connect(netmsg_t msg)485e858b308SNuno Antunes ngd_connect(netmsg_t msg)
4860147868eSNuno Antunes {
487e858b308SNuno Antunes 	struct socket *so = msg->connect.base.nm_so;
488e858b308SNuno Antunes 	struct sockaddr *nam = msg->connect.nm_nam;
4890147868eSNuno Antunes 	struct ngpcb *const pcbp = sotongpcb(so);
490e858b308SNuno Antunes 	int error;
4910147868eSNuno Antunes 
4920147868eSNuno Antunes 	if (pcbp == NULL)
493e858b308SNuno Antunes 		error = EINVAL;
494e858b308SNuno Antunes 	else
495e858b308SNuno Antunes 		error = ng_connect_data(nam, pcbp);
496e858b308SNuno Antunes 	lwkt_replymsg(&msg->connect.base.lmsg, error);
4970147868eSNuno Antunes }
4980147868eSNuno Antunes 
4990147868eSNuno Antunes /*
5000147868eSNuno Antunes  * Used for both data and control sockets
5010147868eSNuno Antunes  */
502e858b308SNuno Antunes static void
ng_getsockaddr(netmsg_t msg)503e858b308SNuno Antunes ng_getsockaddr(netmsg_t msg)
5040147868eSNuno Antunes {
505e858b308SNuno Antunes 	struct socket *so = msg->sockaddr.base.nm_so;
506e858b308SNuno Antunes 	struct sockaddr **addr = msg->sockaddr.nm_nam;
5070147868eSNuno Antunes 	struct ngpcb *pcbp;
5080147868eSNuno Antunes 	struct sockaddr_ng *sg;
5090147868eSNuno Antunes 	int sg_len;
5100147868eSNuno Antunes 	int error = 0;
5110147868eSNuno Antunes 
5120147868eSNuno Antunes 	/* Why isn't sg_data a `char[1]' ? :-( */
5130147868eSNuno Antunes 	sg_len = sizeof(struct sockaddr_ng) - sizeof(sg->sg_data) + 1;
5140147868eSNuno Antunes 
5150147868eSNuno Antunes 	pcbp = sotongpcb(so);
516e858b308SNuno Antunes 	if ((pcbp == NULL) || (pcbp->sockdata == NULL)) {
5170147868eSNuno Antunes 		/* XXXGL: can this still happen? */
518e858b308SNuno Antunes 		error = EINVAL;
519e858b308SNuno Antunes 		goto replymsg;
520e858b308SNuno Antunes 	}
5210147868eSNuno Antunes 
5220147868eSNuno Antunes 	mtx_lock(&pcbp->sockdata->mtx);
5230147868eSNuno Antunes 	if (pcbp->sockdata->node != NULL) {
5240147868eSNuno Antunes 		node_p node = pcbp->sockdata->node;
5250147868eSNuno Antunes 		int namelen = 0;	/* silence compiler! */
5260147868eSNuno Antunes 
5270147868eSNuno Antunes 		if (NG_NODE_HAS_NAME(node))
5280147868eSNuno Antunes 			sg_len += namelen = strlen(NG_NODE_NAME(node));
5290147868eSNuno Antunes 
5300147868eSNuno Antunes 		sg = kmalloc(sg_len, M_SONAME, M_WAITOK | M_ZERO);
5310147868eSNuno Antunes 
5320147868eSNuno Antunes 		if (NG_NODE_HAS_NAME(node))
5330147868eSNuno Antunes 			bcopy(NG_NODE_NAME(node), sg->sg_data, namelen);
5340147868eSNuno Antunes 
5350147868eSNuno Antunes 		sg->sg_len = sg_len;
5360147868eSNuno Antunes 		sg->sg_family = AF_NETGRAPH;
5370147868eSNuno Antunes 		*addr = (struct sockaddr *)sg;
5380147868eSNuno Antunes 		mtx_unlock(&pcbp->sockdata->mtx);
5390147868eSNuno Antunes 	} else {
5400147868eSNuno Antunes 		mtx_unlock(&pcbp->sockdata->mtx);
5410147868eSNuno Antunes 		error = EINVAL;
5420147868eSNuno Antunes 	}
5430147868eSNuno Antunes 
544e858b308SNuno Antunes replymsg:
545e858b308SNuno Antunes 	lwkt_replymsg(&msg->sockaddr.base.lmsg, error);
5460147868eSNuno Antunes }
5470147868eSNuno Antunes 
5480147868eSNuno Antunes /*
5490147868eSNuno Antunes  * Attach a socket to it's protocol specific partner.
5500147868eSNuno Antunes  * For a control socket, actually create a netgraph node and attach
5510147868eSNuno Antunes  * to it as well.
5520147868eSNuno Antunes  */
5530147868eSNuno Antunes 
5540147868eSNuno Antunes static int
ng_attach_cntl(struct socket * so)5550147868eSNuno Antunes ng_attach_cntl(struct socket *so)
5560147868eSNuno Antunes {
5570147868eSNuno Antunes 	struct ngsock *priv;
5580147868eSNuno Antunes 	struct ngpcb *pcbp;
5590147868eSNuno Antunes 	int error;
5600147868eSNuno Antunes 
5610147868eSNuno Antunes 	/* Allocate node private info */
5620147868eSNuno Antunes 	priv = kmalloc(sizeof(*priv), M_NETGRAPH_SOCK, M_WAITOK | M_ZERO);
5630147868eSNuno Antunes 
5640147868eSNuno Antunes 	/* Setup protocol control block */
5650147868eSNuno Antunes 	if ((error = ng_attach_common(so, NG_CONTROL)) != 0) {
5660147868eSNuno Antunes 		kfree(priv, M_NETGRAPH_SOCK);
5670147868eSNuno Antunes 		return (error);
5680147868eSNuno Antunes 	}
5690147868eSNuno Antunes 	pcbp = sotongpcb(so);
5700147868eSNuno Antunes 
5710147868eSNuno Antunes 	/* Link the pcb the private data. */
5720147868eSNuno Antunes 	priv->ctlsock = pcbp;
5730147868eSNuno Antunes 	pcbp->sockdata = priv;
5740147868eSNuno Antunes 	priv->refs++;
5750147868eSNuno Antunes 
5760147868eSNuno Antunes 	/* Initialize mutex. */
577c0095626SSascha Wildner 	mtx_init(&priv->mtx, "ng_socket");
5780147868eSNuno Antunes 
5790147868eSNuno Antunes 	/* Make the generic node components */
5800147868eSNuno Antunes 	if ((error = ng_make_node_common(&typestruct, &priv->node)) != 0) {
5810147868eSNuno Antunes 		kfree(priv, M_NETGRAPH_SOCK);
5820147868eSNuno Antunes 		ng_detach_common(pcbp, NG_CONTROL);
5830147868eSNuno Antunes 		return (error);
5840147868eSNuno Antunes 	}
5850147868eSNuno Antunes 
5860147868eSNuno Antunes 	/* Link the node and the private data. */
5870147868eSNuno Antunes 	NG_NODE_SET_PRIVATE(priv->node, priv);
5880147868eSNuno Antunes 	NG_NODE_REF(priv->node);
5890147868eSNuno Antunes 	priv->refs++;
5900147868eSNuno Antunes 
5910147868eSNuno Antunes 	return (0);
5920147868eSNuno Antunes }
5930147868eSNuno Antunes 
5940147868eSNuno Antunes static int
ng_attach_data(struct socket * so)5950147868eSNuno Antunes ng_attach_data(struct socket *so)
5960147868eSNuno Antunes {
5970147868eSNuno Antunes 	return (ng_attach_common(so, NG_DATA));
5980147868eSNuno Antunes }
5990147868eSNuno Antunes 
6000147868eSNuno Antunes /*
6010147868eSNuno Antunes  * Set up a socket protocol control block.
6020147868eSNuno Antunes  * This code is shared between control and data sockets.
6030147868eSNuno Antunes  */
6040147868eSNuno Antunes static int
ng_attach_common(struct socket * so,int type)6050147868eSNuno Antunes ng_attach_common(struct socket *so, int type)
6060147868eSNuno Antunes {
6070147868eSNuno Antunes 	struct ngpcb *pcbp;
6080147868eSNuno Antunes 	int error;
6090147868eSNuno Antunes 
6100147868eSNuno Antunes 	/* Standard socket setup stuff. */
6110147868eSNuno Antunes 	error = soreserve(so, ngpdg_sendspace, ngpdg_recvspace, NULL);
6120147868eSNuno Antunes 	if (error)
6130147868eSNuno Antunes 		return (error);
6140147868eSNuno Antunes 
6150147868eSNuno Antunes 	/* Allocate the pcb. */
6160147868eSNuno Antunes 	pcbp = kmalloc(sizeof(struct ngpcb), M_PCB, M_WAITOK | M_ZERO);
6170147868eSNuno Antunes 	pcbp->type = type;
6180147868eSNuno Antunes 
6190147868eSNuno Antunes 	/* Link the pcb and the socket. */
6200147868eSNuno Antunes 	so->so_pcb = (caddr_t)pcbp;
6210147868eSNuno Antunes 	pcbp->ng_socket = so;
6220147868eSNuno Antunes 
6230147868eSNuno Antunes 	return (0);
6240147868eSNuno Antunes }
6250147868eSNuno Antunes 
6260147868eSNuno Antunes /*
6270147868eSNuno Antunes  * Disassociate the socket from it's protocol specific
6280147868eSNuno Antunes  * partner. If it's attached to a node's private data structure,
6290147868eSNuno Antunes  * then unlink from that too. If we were the last socket attached to it,
6300147868eSNuno Antunes  * then shut down the entire node. Shared code for control and data sockets.
6310147868eSNuno Antunes  */
6320147868eSNuno Antunes static void
ng_detach_common(struct ngpcb * pcbp,int which)6330147868eSNuno Antunes ng_detach_common(struct ngpcb *pcbp, int which)
6340147868eSNuno Antunes {
6350147868eSNuno Antunes 	struct ngsock *priv = pcbp->sockdata;
6360147868eSNuno Antunes 
6370147868eSNuno Antunes 	if (priv != NULL) {
6380147868eSNuno Antunes 		mtx_lock(&priv->mtx);
6390147868eSNuno Antunes 
6400147868eSNuno Antunes 		switch (which) {
6410147868eSNuno Antunes 		case NG_CONTROL:
6420147868eSNuno Antunes 			priv->ctlsock = NULL;
6430147868eSNuno Antunes 			break;
6440147868eSNuno Antunes 		case NG_DATA:
6450147868eSNuno Antunes 			priv->datasock = NULL;
6460147868eSNuno Antunes 			break;
6470147868eSNuno Antunes 		default:
6480147868eSNuno Antunes 			panic(__func__);
6490147868eSNuno Antunes 		}
6500147868eSNuno Antunes 		pcbp->sockdata = NULL;
6510147868eSNuno Antunes 
6520147868eSNuno Antunes 		ng_socket_free_priv(priv);
6530147868eSNuno Antunes 	}
6540147868eSNuno Antunes 
6550147868eSNuno Antunes 	pcbp->ng_socket->so_pcb = NULL;
6560147868eSNuno Antunes 	kfree(pcbp, M_PCB);
6570147868eSNuno Antunes }
6580147868eSNuno Antunes 
6590147868eSNuno Antunes /*
6600147868eSNuno Antunes  * Remove a reference from node private data.
6610147868eSNuno Antunes  */
6620147868eSNuno Antunes static void
ng_socket_free_priv(struct ngsock * priv)6630147868eSNuno Antunes ng_socket_free_priv(struct ngsock *priv)
6640147868eSNuno Antunes {
665a6c72860SNuno Antunes 	KKASSERT(mtx_owned(&priv->mtx));
6660147868eSNuno Antunes 
6670147868eSNuno Antunes 	priv->refs--;
6680147868eSNuno Antunes 
6690147868eSNuno Antunes 	if (priv->refs == 0) {
670a6c72860SNuno Antunes 		mtx_uninit(&priv->mtx);
6710147868eSNuno Antunes 		kfree(priv, M_NETGRAPH_SOCK);
6720147868eSNuno Antunes 		return;
6730147868eSNuno Antunes 	}
6740147868eSNuno Antunes 
6750147868eSNuno Antunes 	if ((priv->refs == 1) && (priv->node != NULL)) {
6760147868eSNuno Antunes 		node_p node = priv->node;
6770147868eSNuno Antunes 
6780147868eSNuno Antunes 		priv->node = NULL;
6790147868eSNuno Antunes 		mtx_unlock(&priv->mtx);
6800147868eSNuno Antunes 		NG_NODE_UNREF(node);
6810147868eSNuno Antunes 		ng_rmnode_self(node);
6820147868eSNuno Antunes 	} else
6830147868eSNuno Antunes 		mtx_unlock(&priv->mtx);
6840147868eSNuno Antunes }
6850147868eSNuno Antunes 
6860147868eSNuno Antunes #ifdef NOTYET
6870147868eSNuno Antunes /*
6880147868eSNuno Antunes  * File descriptors can be passed into an AF_NETGRAPH socket.
6890147868eSNuno Antunes  * Note, that file descriptors cannot be passed OUT.
6900147868eSNuno Antunes  * Only character device descriptors are accepted.
6910147868eSNuno Antunes  * Character devices are useful to connect a graph to a device,
6920147868eSNuno Antunes  * which after all is the purpose of this whole system.
6930147868eSNuno Antunes  */
6940147868eSNuno Antunes static int
ng_internalize(struct mbuf * control,struct thread * td)6950147868eSNuno Antunes ng_internalize(struct mbuf *control, struct thread *td)
6960147868eSNuno Antunes {
6970147868eSNuno Antunes 	const struct cmsghdr *cm = mtod(control, const struct cmsghdr *);
6980147868eSNuno Antunes 	struct file *fp;
6990147868eSNuno Antunes 	struct vnode *vn;
7000147868eSNuno Antunes 	int oldfds;
7010147868eSNuno Antunes 	int fd;
7020147868eSNuno Antunes 
7030147868eSNuno Antunes 	if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET ||
7040147868eSNuno Antunes 	    cm->cmsg_len != control->m_len) {
7050147868eSNuno Antunes 		TRAP_ERROR;
7060147868eSNuno Antunes 		return (EINVAL);
7070147868eSNuno Antunes 	}
7080147868eSNuno Antunes 
7090147868eSNuno Antunes 	/* Check there is only one FD. XXX what would more than one signify? */
7100147868eSNuno Antunes 	oldfds = ((caddr_t)cm + cm->cmsg_len - (caddr_t)data) / sizeof (int);
7110147868eSNuno Antunes 	if (oldfds != 1) {
7120147868eSNuno Antunes 		TRAP_ERROR;
7130147868eSNuno Antunes 		return (EINVAL);
7140147868eSNuno Antunes 	}
7150147868eSNuno Antunes 
7160147868eSNuno Antunes 	/* Check that the FD given is legit. and change it to a pointer to a
7170147868eSNuno Antunes 	 * struct file. */
7180147868eSNuno Antunes 	fd = CMSG_DATA(cm);
7190147868eSNuno Antunes 	if ((error = fget(td, fd, &fp)) != 0)
7200147868eSNuno Antunes 		return (error);
7210147868eSNuno Antunes 
7220147868eSNuno Antunes 	/* Depending on what kind of resource it is, act differently. For
7230147868eSNuno Antunes 	 * devices, we treat it as a file. For an AF_NETGRAPH socket,
7240147868eSNuno Antunes 	 * shortcut straight to the node. */
7250147868eSNuno Antunes 	switch (fp->f_type) {
7260147868eSNuno Antunes 	case DTYPE_VNODE:
7270147868eSNuno Antunes 		vn = fp->f_data;
7280147868eSNuno Antunes 		if (vn && (vn->v_type == VCHR)) {
7290147868eSNuno Antunes 			/* for a VCHR, actually reference the FILE */
7300147868eSNuno Antunes 			fhold(fp);
7310147868eSNuno Antunes 			/* XXX then what :) */
7320147868eSNuno Antunes 			/* how to pass on to other modules? */
7330147868eSNuno Antunes 		} else {
7340147868eSNuno Antunes 			fdrop(fp, td);
7350147868eSNuno Antunes 			TRAP_ERROR;
7360147868eSNuno Antunes 			return (EINVAL);
7370147868eSNuno Antunes 		}
7380147868eSNuno Antunes 		break;
7390147868eSNuno Antunes 	default:
7400147868eSNuno Antunes 		fdrop(fp, td);
7410147868eSNuno Antunes 		TRAP_ERROR;
7420147868eSNuno Antunes 		return (EINVAL);
7430147868eSNuno Antunes 	}
7440147868eSNuno Antunes 	fdrop(fp, td);
7450147868eSNuno Antunes 	return (0);
7460147868eSNuno Antunes }
7470147868eSNuno Antunes #endif	/* NOTYET */
7480147868eSNuno Antunes 
7490147868eSNuno Antunes /*
7500147868eSNuno Antunes  * Connect the data socket to a named control socket node.
7510147868eSNuno Antunes  */
7520147868eSNuno Antunes static int
ng_connect_data(struct sockaddr * nam,struct ngpcb * pcbp)7530147868eSNuno Antunes ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp)
7540147868eSNuno Antunes {
7550147868eSNuno Antunes 	struct sockaddr_ng *sap;
7560147868eSNuno Antunes 	node_p farnode;
7570147868eSNuno Antunes 	struct ngsock *priv;
7580147868eSNuno Antunes 	int error;
7590147868eSNuno Antunes 	item_p item;
7600147868eSNuno Antunes 
7610147868eSNuno Antunes 	/* If we are already connected, don't do it again. */
7620147868eSNuno Antunes 	if (pcbp->sockdata != NULL)
7630147868eSNuno Antunes 		return (EISCONN);
7640147868eSNuno Antunes 
7650147868eSNuno Antunes 	/*
7660147868eSNuno Antunes 	 * Find the target (victim) and check it doesn't already have
7670147868eSNuno Antunes 	 * a data socket. Also check it is a 'socket' type node.
7680147868eSNuno Antunes 	 * Use ng_package_data() and ng_address_path() to do this.
7690147868eSNuno Antunes 	 */
7700147868eSNuno Antunes 
7710147868eSNuno Antunes 	sap = (struct sockaddr_ng *) nam;
7720147868eSNuno Antunes 	/* The item will hold the node reference. */
7730147868eSNuno Antunes 	item = ng_package_data(NULL, NG_WAITOK);
7740147868eSNuno Antunes 
7753acc7e05SNuno Antunes 	if ((error = ng_address_path(NULL, item,  sap->sg_data, 0))) {
7763acc7e05SNuno Antunes 		ng_free_item(item);
7773acc7e05SNuno Antunes 		return (error);
7783acc7e05SNuno Antunes 	}
7790147868eSNuno Antunes 
7800147868eSNuno Antunes 	/*
7810147868eSNuno Antunes 	 * Extract node from item and free item. Remember we now have
7820147868eSNuno Antunes 	 * a reference on the node. The item holds it for us.
7830147868eSNuno Antunes 	 * when we free the item we release the reference.
7840147868eSNuno Antunes 	 */
7850147868eSNuno Antunes 	farnode = item->el_dest; /* shortcut */
7860147868eSNuno Antunes 	if (strcmp(farnode->nd_type->name, NG_SOCKET_NODE_TYPE) != 0) {
7873acc7e05SNuno Antunes 		ng_free_item(item); /* drop the reference to the node */
7880147868eSNuno Antunes 		return (EINVAL);
7890147868eSNuno Antunes 	}
7900147868eSNuno Antunes 	priv = NG_NODE_PRIVATE(farnode);
7910147868eSNuno Antunes 	if (priv->datasock != NULL) {
7923acc7e05SNuno Antunes 		ng_free_item(item);	/* drop the reference to the node */
7930147868eSNuno Antunes 		return (EADDRINUSE);
7940147868eSNuno Antunes 	}
7950147868eSNuno Antunes 
7960147868eSNuno Antunes 	/*
7970147868eSNuno Antunes 	 * Link the PCB and the private data struct. and note the extra
7980147868eSNuno Antunes 	 * reference. Drop the extra reference on the node.
7990147868eSNuno Antunes 	 */
8000147868eSNuno Antunes 	mtx_lock(&priv->mtx);
8010147868eSNuno Antunes 	priv->datasock = pcbp;
8020147868eSNuno Antunes 	pcbp->sockdata = priv;
8030147868eSNuno Antunes 	priv->refs++;
8040147868eSNuno Antunes 	mtx_unlock(&priv->mtx);
8053acc7e05SNuno Antunes 	ng_free_item(item);	/* drop the reference to the node */
8060147868eSNuno Antunes 	return (0);
8070147868eSNuno Antunes }
8080147868eSNuno Antunes 
8090147868eSNuno Antunes /*
8100147868eSNuno Antunes  * Binding a socket means giving the corresponding node a name
8110147868eSNuno Antunes  */
8120147868eSNuno Antunes static int
ng_bind(struct sockaddr * nam,struct ngpcb * pcbp)8130147868eSNuno Antunes ng_bind(struct sockaddr *nam, struct ngpcb *pcbp)
8140147868eSNuno Antunes {
8150147868eSNuno Antunes 	struct ngsock *const priv = pcbp->sockdata;
8160147868eSNuno Antunes 	struct sockaddr_ng *const sap = (struct sockaddr_ng *) nam;
8170147868eSNuno Antunes 
8180147868eSNuno Antunes 	if (priv == NULL) {
8190147868eSNuno Antunes 		TRAP_ERROR;
8200147868eSNuno Antunes 		return (EINVAL);
8210147868eSNuno Antunes 	}
8220147868eSNuno Antunes 	if ((sap->sg_len < 4) || (sap->sg_len > (NG_NODESIZ + 2)) ||
8230147868eSNuno Antunes 	    (sap->sg_data[0] == '\0') ||
8240147868eSNuno Antunes 	    (sap->sg_data[sap->sg_len - 3] != '\0')) {
8250147868eSNuno Antunes 		TRAP_ERROR;
8260147868eSNuno Antunes 		return (EINVAL);
8270147868eSNuno Antunes 	}
8280147868eSNuno Antunes 	return (ng_name_node(priv->node, sap->sg_data));
8290147868eSNuno Antunes }
8300147868eSNuno Antunes 
8310147868eSNuno Antunes /***************************************************************
8320147868eSNuno Antunes 	Netgraph node
8330147868eSNuno Antunes ***************************************************************/
8340147868eSNuno Antunes 
8350147868eSNuno Antunes /*
8360147868eSNuno Antunes  * You can only create new nodes from the socket end of things.
8370147868eSNuno Antunes  */
8380147868eSNuno Antunes static int
ngs_constructor(node_p nodep)8390147868eSNuno Antunes ngs_constructor(node_p nodep)
8400147868eSNuno Antunes {
8410147868eSNuno Antunes 	return (EINVAL);
8420147868eSNuno Antunes }
8430147868eSNuno Antunes 
8440147868eSNuno Antunes /*
8450147868eSNuno Antunes  * We allow any hook to be connected to the node.
8460147868eSNuno Antunes  * There is no per-hook private information though.
8470147868eSNuno Antunes  */
8480147868eSNuno Antunes static int
ngs_newhook(node_p node,hook_p hook,const char * name)8490147868eSNuno Antunes ngs_newhook(node_p node, hook_p hook, const char *name)
8500147868eSNuno Antunes {
8510147868eSNuno Antunes 	NG_HOOK_SET_PRIVATE(hook, NG_NODE_PRIVATE(node));
8520147868eSNuno Antunes 	return (0);
8530147868eSNuno Antunes }
8540147868eSNuno Antunes 
8550147868eSNuno Antunes /*
8560147868eSNuno Antunes  * If only one hook, allow read(2) and write(2) to work.
8570147868eSNuno Antunes  */
8580147868eSNuno Antunes static int
ngs_connect(hook_p hook)8590147868eSNuno Antunes ngs_connect(hook_p hook)
8600147868eSNuno Antunes {
8610147868eSNuno Antunes 	node_p node = NG_HOOK_NODE(hook);
8620147868eSNuno Antunes 	struct ngsock *priv = NG_NODE_PRIVATE(node);
8630147868eSNuno Antunes 
8640147868eSNuno Antunes 	if ((priv->datasock) && (priv->datasock->ng_socket)) {
8650147868eSNuno Antunes 		if (NG_NODE_NUMHOOKS(node) == 1)
8660147868eSNuno Antunes 			sosetstate(priv->datasock->ng_socket, SS_ISCONNECTED);
8670147868eSNuno Antunes 		else
8680147868eSNuno Antunes 			soclrstate(priv->datasock->ng_socket, SS_ISCONNECTED);
8690147868eSNuno Antunes 	}
8700147868eSNuno Antunes 	return (0);
8710147868eSNuno Antunes }
8720147868eSNuno Antunes 
8730147868eSNuno Antunes /*
8740147868eSNuno Antunes  * Incoming messages get passed up to the control socket.
8750147868eSNuno Antunes  * Unless they are for us specifically (socket_type)
8760147868eSNuno Antunes  */
8770147868eSNuno Antunes static int
ngs_rcvmsg(node_p node,item_p item,hook_p lasthook)8780147868eSNuno Antunes ngs_rcvmsg(node_p node, item_p item, hook_p lasthook)
8790147868eSNuno Antunes {
8800147868eSNuno Antunes 	struct ngsock *const priv = NG_NODE_PRIVATE(node);
8810147868eSNuno Antunes 	struct ngpcb *const pcbp = priv->ctlsock;
8820147868eSNuno Antunes 	struct socket *so;
8830147868eSNuno Antunes 	struct sockaddr_ng addr;
8840147868eSNuno Antunes 	struct ng_mesg *msg;
8850147868eSNuno Antunes 	struct mbuf *m;
8860147868eSNuno Antunes 	ng_ID_t	retaddr = NGI_RETADDR(item);
8870147868eSNuno Antunes 	int addrlen;
8880147868eSNuno Antunes 	int error = 0;
8890147868eSNuno Antunes 
8900147868eSNuno Antunes 	NGI_GET_MSG(item, msg);
8910147868eSNuno Antunes 	NG_FREE_ITEM(item);
8920147868eSNuno Antunes 
8930147868eSNuno Antunes 	/*
8940147868eSNuno Antunes 	 * Only allow mesgs to be passed if we have the control socket.
8950147868eSNuno Antunes 	 * Data sockets can only support the generic messages.
8960147868eSNuno Antunes 	 */
8970147868eSNuno Antunes 	if (pcbp == NULL) {
8980147868eSNuno Antunes 		TRAP_ERROR;
8990147868eSNuno Antunes 		NG_FREE_MSG(msg);
9000147868eSNuno Antunes 		return (EINVAL);
9010147868eSNuno Antunes 	}
9020147868eSNuno Antunes 	so = pcbp->ng_socket;
9030147868eSNuno Antunes 
9040147868eSNuno Antunes #ifdef TRACE_MESSAGES
905a62226e4SSascha Wildner 	kprintf("[%x]:---------->[socket]: c=<%d>cmd=%x(%s) f=%x #%d\n",
9060147868eSNuno Antunes 		retaddr,
9070147868eSNuno Antunes 		msg->header.typecookie,
9080147868eSNuno Antunes 		msg->header.cmd,
9090147868eSNuno Antunes 		msg->header.cmdstr,
9100147868eSNuno Antunes 		msg->header.flags,
9110147868eSNuno Antunes 		msg->header.token);
9120147868eSNuno Antunes #endif
9130147868eSNuno Antunes 
9140147868eSNuno Antunes 	if (msg->header.typecookie == NGM_SOCKET_COOKIE) {
9150147868eSNuno Antunes 		switch (msg->header.cmd) {
9160147868eSNuno Antunes 		case NGM_SOCK_CMD_NOLINGER:
9170147868eSNuno Antunes 			priv->flags |= NGS_FLAG_NOLINGER;
9180147868eSNuno Antunes 			break;
9190147868eSNuno Antunes 		case NGM_SOCK_CMD_LINGER:
9200147868eSNuno Antunes 			priv->flags &= ~NGS_FLAG_NOLINGER;
9210147868eSNuno Antunes 			break;
9220147868eSNuno Antunes 		default:
9230147868eSNuno Antunes 			error = EINVAL;		/* unknown command */
9240147868eSNuno Antunes 		}
9250147868eSNuno Antunes 		/* Free the message and return. */
9260147868eSNuno Antunes 		NG_FREE_MSG(msg);
9270147868eSNuno Antunes 		return (error);
9280147868eSNuno Antunes 	}
9290147868eSNuno Antunes 
9300147868eSNuno Antunes 	/* Get the return address into a sockaddr. */
9310147868eSNuno Antunes 	bzero(&addr, sizeof(addr));
9320147868eSNuno Antunes 	addr.sg_len = sizeof(addr);
9330147868eSNuno Antunes 	addr.sg_family = AF_NETGRAPH;
934a62226e4SSascha Wildner 	addrlen = ksnprintf((char *)&addr.sg_data, sizeof(addr.sg_data),
9350147868eSNuno Antunes 	    "[%x]:", retaddr);
9360147868eSNuno Antunes 	if (addrlen < 0 || addrlen > sizeof(addr.sg_data)) {
937a62226e4SSascha Wildner 		kprintf("%s: ksnprintf([%x]) failed - %d\n", __func__, retaddr,
9380147868eSNuno Antunes 		    addrlen);
9390147868eSNuno Antunes 		NG_FREE_MSG(msg);
9400147868eSNuno Antunes 		return (EINVAL);
9410147868eSNuno Antunes 	}
9420147868eSNuno Antunes 
9430147868eSNuno Antunes 	/* Copy the message itself into an mbuf chain. */
944*05d02a38SAaron LI 	m = m_devget(msg, sizeof(struct ng_mesg) + msg->header.arglen, 0, NULL);
9450147868eSNuno Antunes 
9460147868eSNuno Antunes 	/*
9470147868eSNuno Antunes 	 * Here we free the message. We need to do that
9480147868eSNuno Antunes 	 * regardless of whether we got mbufs.
9490147868eSNuno Antunes 	 */
9500147868eSNuno Antunes 	NG_FREE_MSG(msg);
9510147868eSNuno Antunes 
9520147868eSNuno Antunes 	if (m == NULL) {
9530147868eSNuno Antunes 		TRAP_ERROR;
9540147868eSNuno Antunes 		return (ENOBUFS);
9550147868eSNuno Antunes 	}
9560147868eSNuno Antunes 
9570147868eSNuno Antunes 	/* Send it up to the socket. */
958593159d8SSepherosa Ziehau 	lwkt_gettoken(&so->so_rcv.ssb_token);
9590147868eSNuno Antunes 	if (sbappendaddr((struct sockbuf *)&so->so_rcv, (struct sockaddr *)&addr, m, NULL) == 0) {
960593159d8SSepherosa Ziehau 		lwkt_reltoken(&so->so_rcv.ssb_token);
9610147868eSNuno Antunes 		TRAP_ERROR;
9620147868eSNuno Antunes 		m_freem(m);
9630147868eSNuno Antunes 		return (ENOBUFS);
9640147868eSNuno Antunes 	}
965593159d8SSepherosa Ziehau 	lwkt_reltoken(&so->so_rcv.ssb_token);
9660147868eSNuno Antunes 	sorwakeup(so);
9670147868eSNuno Antunes 
9680147868eSNuno Antunes 	return (error);
9690147868eSNuno Antunes }
9700147868eSNuno Antunes 
9710147868eSNuno Antunes /*
9720147868eSNuno Antunes  * Receive data on a hook
9730147868eSNuno Antunes  */
9740147868eSNuno Antunes static int
ngs_rcvdata(hook_p hook,item_p item)9750147868eSNuno Antunes ngs_rcvdata(hook_p hook, item_p item)
9760147868eSNuno Antunes {
9770147868eSNuno Antunes 	struct ngsock *const priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
9780147868eSNuno Antunes 	struct ngpcb *const pcbp = priv->datasock;
9790147868eSNuno Antunes 	struct socket *so;
9800147868eSNuno Antunes 	struct sockaddr_ng *addr;
9810147868eSNuno Antunes 	char *addrbuf[NG_HOOKSIZ + 4];
9820147868eSNuno Antunes 	int addrlen;
9830147868eSNuno Antunes 	struct mbuf *m;
9840147868eSNuno Antunes 
9850147868eSNuno Antunes 	NGI_GET_M(item, m);
9860147868eSNuno Antunes 	NG_FREE_ITEM(item);
9870147868eSNuno Antunes 
9880147868eSNuno Antunes 	/* If there is no data socket, black-hole it. */
9890147868eSNuno Antunes 	if (pcbp == NULL) {
9900147868eSNuno Antunes 		NG_FREE_M(m);
9910147868eSNuno Antunes 		return (0);
9920147868eSNuno Antunes 	}
9930147868eSNuno Antunes 	so = pcbp->ng_socket;
9940147868eSNuno Antunes 
9950147868eSNuno Antunes 	/* Get the return address into a sockaddr. */
9960147868eSNuno Antunes 	addrlen = strlen(NG_HOOK_NAME(hook));	/* <= NG_HOOKSIZ - 1 */
9970147868eSNuno Antunes 	addr = (struct sockaddr_ng *) addrbuf;
9980147868eSNuno Antunes 	addr->sg_len = addrlen + 3;
9990147868eSNuno Antunes 	addr->sg_family = AF_NETGRAPH;
10000147868eSNuno Antunes 	bcopy(NG_HOOK_NAME(hook), addr->sg_data, addrlen);
10010147868eSNuno Antunes 	addr->sg_data[addrlen] = '\0';
10020147868eSNuno Antunes 
10030147868eSNuno Antunes 	/* Try to tell the socket which hook it came in on. */
1004593159d8SSepherosa Ziehau 	lwkt_gettoken(&so->so_rcv.ssb_token);
10050147868eSNuno Antunes 	if (sbappendaddr((struct sockbuf *)&so->so_rcv, (struct sockaddr *)addr, m, NULL) == 0) {
1006593159d8SSepherosa Ziehau 		lwkt_reltoken(&so->so_rcv.ssb_token);
10070147868eSNuno Antunes 		m_freem(m);
10080147868eSNuno Antunes 		TRAP_ERROR;
10090147868eSNuno Antunes 		return (ENOBUFS);
10100147868eSNuno Antunes 	}
1011593159d8SSepherosa Ziehau 	lwkt_reltoken(&so->so_rcv.ssb_token);
10120147868eSNuno Antunes 	sorwakeup(so);
10130147868eSNuno Antunes 	return (0);
10140147868eSNuno Antunes }
10150147868eSNuno Antunes 
10160147868eSNuno Antunes /*
10170147868eSNuno Antunes  * Hook disconnection
10180147868eSNuno Antunes  *
10190147868eSNuno Antunes  * For this type, removal of the last link destroys the node
10200147868eSNuno Antunes  * if the NOLINGER flag is set.
10210147868eSNuno Antunes  */
10220147868eSNuno Antunes static int
ngs_disconnect(hook_p hook)10230147868eSNuno Antunes ngs_disconnect(hook_p hook)
10240147868eSNuno Antunes {
10250147868eSNuno Antunes 	node_p node = NG_HOOK_NODE(hook);
10260147868eSNuno Antunes 	struct ngsock *const priv = NG_NODE_PRIVATE(node);
10270147868eSNuno Antunes 
10280147868eSNuno Antunes 	if ((priv->datasock) && (priv->datasock->ng_socket)) {
10290147868eSNuno Antunes 		if (NG_NODE_NUMHOOKS(node) == 1)
10300147868eSNuno Antunes 			sosetstate(priv->datasock->ng_socket, SS_ISCONNECTED);
10310147868eSNuno Antunes 		else
10320147868eSNuno Antunes 			soclrstate(priv->datasock->ng_socket, SS_ISCONNECTED);
10330147868eSNuno Antunes 	}
10340147868eSNuno Antunes 
10350147868eSNuno Antunes 	if ((priv->flags & NGS_FLAG_NOLINGER) &&
10360147868eSNuno Antunes 	    (NG_NODE_NUMHOOKS(node) == 0) && (NG_NODE_IS_VALID(node)))
10370147868eSNuno Antunes 		ng_rmnode_self(node);
10380147868eSNuno Antunes 
10390147868eSNuno Antunes 	return (0);
10400147868eSNuno Antunes }
10410147868eSNuno Antunes 
10420147868eSNuno Antunes /*
10430147868eSNuno Antunes  * Do local shutdown processing.
10440147868eSNuno Antunes  * In this case, that involves making sure the socket
10450147868eSNuno Antunes  * knows we should be shutting down.
10460147868eSNuno Antunes  */
10470147868eSNuno Antunes static int
ngs_shutdown(node_p node)10480147868eSNuno Antunes ngs_shutdown(node_p node)
10490147868eSNuno Antunes {
10500147868eSNuno Antunes 	struct ngsock *const priv = NG_NODE_PRIVATE(node);
10510147868eSNuno Antunes 	struct ngpcb *const dpcbp = priv->datasock;
10520147868eSNuno Antunes 	struct ngpcb *const pcbp = priv->ctlsock;
10530147868eSNuno Antunes 
10540147868eSNuno Antunes 	if (dpcbp != NULL)
10550147868eSNuno Antunes 		soisdisconnected(dpcbp->ng_socket);
10560147868eSNuno Antunes 
10570147868eSNuno Antunes 	if (pcbp != NULL)
10580147868eSNuno Antunes 		soisdisconnected(pcbp->ng_socket);
10590147868eSNuno Antunes 
10600147868eSNuno Antunes 	mtx_lock(&priv->mtx);
10610147868eSNuno Antunes 	priv->node = NULL;
10620147868eSNuno Antunes 	NG_NODE_SET_PRIVATE(node, NULL);
10630147868eSNuno Antunes 	ng_socket_free_priv(priv);
10640147868eSNuno Antunes 
10650147868eSNuno Antunes 	NG_NODE_UNREF(node);
10660147868eSNuno Antunes 	return (0);
10670147868eSNuno Antunes }
10680147868eSNuno Antunes 
10690147868eSNuno Antunes static void
ng_socket_item_applied(void * context,int error)10700147868eSNuno Antunes ng_socket_item_applied(void *context, int error)
10710147868eSNuno Antunes {
1072ad9efc7bSNuno Antunes 	lwkt_msg *msg = context;
10730147868eSNuno Antunes 
1074ad9efc7bSNuno Antunes 	lwkt_replymsg(msg, error);
10750147868eSNuno Antunes }
10760147868eSNuno Antunes 
10770147868eSNuno Antunes /*
10780147868eSNuno Antunes  * Control and data socket type descriptors
10790147868eSNuno Antunes  *
10800147868eSNuno Antunes  * XXXRW: Perhaps _close should do something?
10810147868eSNuno Antunes  */
10820147868eSNuno Antunes 
10830147868eSNuno Antunes static struct pr_usrreqs ngc_usrreqs = {
10840147868eSNuno Antunes 	.pru_abort =		NULL,
10850147868eSNuno Antunes 	.pru_attach =		ngc_attach,
10860147868eSNuno Antunes 	.pru_bind =		ngc_bind,
10870147868eSNuno Antunes 	.pru_connect =		ngc_connect,
10880147868eSNuno Antunes 	.pru_detach =		ngc_detach,
1089e858b308SNuno Antunes 	.pru_disconnect =	NULL,
10900147868eSNuno Antunes 	.pru_peeraddr =		NULL,
10910147868eSNuno Antunes 	.pru_send =		ngc_send,
10920147868eSNuno Antunes 	.pru_shutdown =		NULL,
10930147868eSNuno Antunes 	.pru_sockaddr =		ng_getsockaddr,
10940147868eSNuno Antunes 	.pru_sosend =		sosend,
10950147868eSNuno Antunes 	.pru_soreceive =	soreceive,
10960147868eSNuno Antunes 	/* .pru_close =		NULL, */
10970147868eSNuno Antunes };
10980147868eSNuno Antunes 
10990147868eSNuno Antunes static struct pr_usrreqs ngd_usrreqs = {
11000147868eSNuno Antunes 	.pru_abort =		NULL,
11010147868eSNuno Antunes 	.pru_attach =		ngd_attach,
11020147868eSNuno Antunes 	.pru_bind =		NULL,
11030147868eSNuno Antunes 	.pru_connect =		ngd_connect,
11040147868eSNuno Antunes 	.pru_detach =		ngd_detach,
1105e858b308SNuno Antunes 	.pru_disconnect =	NULL,
11060147868eSNuno Antunes 	.pru_peeraddr =		NULL,
11070147868eSNuno Antunes 	.pru_send =		ngd_send,
11080147868eSNuno Antunes 	.pru_shutdown =		NULL,
11090147868eSNuno Antunes 	.pru_sockaddr =		ng_getsockaddr,
11100147868eSNuno Antunes 	.pru_sosend =		sosend,
11110147868eSNuno Antunes 	.pru_soreceive =	soreceive,
11120147868eSNuno Antunes 	/* .pru_close =		NULL, */
11130147868eSNuno Antunes };
11140147868eSNuno Antunes 
11150147868eSNuno Antunes /*
11160147868eSNuno Antunes  * Definitions of protocols supported in the NETGRAPH domain.
11170147868eSNuno Antunes  */
11180147868eSNuno Antunes 
11190147868eSNuno Antunes extern struct domain ngdomain;		/* stop compiler warnings */
11200147868eSNuno Antunes 
11210147868eSNuno Antunes static struct protosw ngsw[] = {
11220147868eSNuno Antunes {
11230147868eSNuno Antunes 	.pr_type =		SOCK_DGRAM,
11240147868eSNuno Antunes 	.pr_domain =		&ngdomain,
11250147868eSNuno Antunes 	.pr_protocol =		NG_CONTROL,
11260147868eSNuno Antunes 	.pr_flags =		PR_ATOMIC | PR_ADDR /* | PR_RIGHTS */,
11270147868eSNuno Antunes 	.pr_usrreqs =		&ngc_usrreqs
11280147868eSNuno Antunes },
11290147868eSNuno Antunes {
11300147868eSNuno Antunes 	.pr_type =		SOCK_DGRAM,
11310147868eSNuno Antunes 	.pr_domain =		&ngdomain,
11320147868eSNuno Antunes 	.pr_protocol =		NG_DATA,
11330147868eSNuno Antunes 	.pr_flags =		PR_ATOMIC | PR_ADDR,
11340147868eSNuno Antunes 	.pr_usrreqs =		&ngd_usrreqs
11350147868eSNuno Antunes }
11360147868eSNuno Antunes };
11370147868eSNuno Antunes 
11380147868eSNuno Antunes struct domain ngdomain = {
11390147868eSNuno Antunes 	.dom_family =		AF_NETGRAPH,
11400147868eSNuno Antunes 	.dom_name =		"netgraph",
11410147868eSNuno Antunes 	.dom_protosw =		ngsw,
11420147868eSNuno Antunes 	.dom_protoswNPROTOSW =	&ngsw[NELEM(ngsw)]
11430147868eSNuno Antunes };
11440147868eSNuno Antunes 
11450147868eSNuno Antunes /*
11460147868eSNuno Antunes  * Handle loading and unloading for this node type.
11470147868eSNuno Antunes  * This is to handle auxiliary linkages (e.g protocol domain addition).
11480147868eSNuno Antunes  */
11490147868eSNuno Antunes static int
ngs_mod_event(module_t mod,int event,void * data)11500147868eSNuno Antunes ngs_mod_event(module_t mod, int event, void *data)
11510147868eSNuno Antunes {
11520147868eSNuno Antunes 	int error = 0;
11530147868eSNuno Antunes 
11540147868eSNuno Antunes 	switch (event) {
11550147868eSNuno Antunes 	case MOD_LOAD:
11560147868eSNuno Antunes 		/* Register protocol domain. */
11570147868eSNuno Antunes 		net_add_domain(&ngdomain);
11580147868eSNuno Antunes 		break;
11590147868eSNuno Antunes 	case MOD_UNLOAD:
11600147868eSNuno Antunes #ifdef NOTYET
11610147868eSNuno Antunes 		/* Unregister protocol domain XXX can't do this yet.. */
11620147868eSNuno Antunes 		if ((error = net_rm_domain(&ngdomain)) != 0)
11630147868eSNuno Antunes 			break;
11640147868eSNuno Antunes 		else
11650147868eSNuno Antunes #endif
11660147868eSNuno Antunes 			error = EBUSY;
11670147868eSNuno Antunes 		break;
11680147868eSNuno Antunes 	default:
11690147868eSNuno Antunes 		error = EOPNOTSUPP;
11700147868eSNuno Antunes 		break;
11710147868eSNuno Antunes 	}
11720147868eSNuno Antunes 	return (error);
11730147868eSNuno Antunes }
11740147868eSNuno Antunes 
1175ac58e50cSNuno Antunes static int
linker_api_available(void)1176ac58e50cSNuno Antunes linker_api_available(void)
1177ac58e50cSNuno Antunes {
1178ac58e50cSNuno Antunes 	/* linker_* API won't work without a process context */
1179ac58e50cSNuno Antunes 	if (curproc == NULL)
1180ac58e50cSNuno Antunes 		return 0;
1181ac58e50cSNuno Antunes 	/*
1182ac58e50cSNuno Antunes 	 * nlookup_init() relies on namei_oc to be initialized,
1183ac58e50cSNuno Antunes 	 * but it's not when the netgraph module is loaded during boot.
1184ac58e50cSNuno Antunes 	 */
1185ac58e50cSNuno Antunes 	if (namei_oc == NULL)
1186ac58e50cSNuno Antunes 		return 0;
1187ac58e50cSNuno Antunes 	return 1;
1188ac58e50cSNuno Antunes }
1189ac58e50cSNuno Antunes 
11900147868eSNuno Antunes SYSCTL_INT(_net_graph, OID_AUTO, family, CTLFLAG_RD, 0, AF_NETGRAPH, "");
11910147868eSNuno Antunes SYSCTL_NODE(_net_graph, OID_AUTO, data, CTLFLAG_RW, 0, "DATA");
11920147868eSNuno Antunes SYSCTL_INT(_net_graph_data, OID_AUTO, proto, CTLFLAG_RD, 0, NG_DATA, "");
11930147868eSNuno Antunes SYSCTL_NODE(_net_graph, OID_AUTO, control, CTLFLAG_RW, 0, "CONTROL");
11940147868eSNuno Antunes SYSCTL_INT(_net_graph_control, OID_AUTO, proto, CTLFLAG_RD, 0, NG_CONTROL, "");
11950147868eSNuno Antunes 
1196