Deleted Added
full compact
ng_socket.c (225736) ng_socket.c (231587)
1/*
2 * ng_socket.c
3 */
4
5/*-
6 * Copyright (c) 1996-1999 Whistle Communications, Inc.
7 * All rights reserved.
8 *

--- 23 unchanged lines hidden (view full) ---

32 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
36 * OF SUCH DAMAGE.
37 *
38 * Author: Julian Elischer <julian@freebsd.org>
39 *
1/*
2 * ng_socket.c
3 */
4
5/*-
6 * Copyright (c) 1996-1999 Whistle Communications, Inc.
7 * All rights reserved.
8 *

--- 23 unchanged lines hidden (view full) ---

32 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
36 * OF SUCH DAMAGE.
37 *
38 * Author: Julian Elischer <julian@freebsd.org>
39 *
40 * $FreeBSD: stable/9/sys/netgraph/ng_socket.c 224778 2011-08-11 12:30:23Z rwatson $
40 * $FreeBSD: stable/9/sys/netgraph/ng_socket.c 231587 2012-02-13 15:21:12Z glebius $
41 * $Whistle: ng_socket.c,v 1.28 1999/11/01 09:24:52 julian Exp $
42 */
43
44/*
45 * Netgraph socket nodes
46 *
47 * There are two types of netgraph sockets, control and data.
48 * Control sockets have a netgraph node, but data sockets are
49 * parasitic on control sockets, and have no node of their own.
50 */
51
52#include <sys/param.h>
53#include <sys/domain.h>
41 * $Whistle: ng_socket.c,v 1.28 1999/11/01 09:24:52 julian Exp $
42 */
43
44/*
45 * Netgraph socket nodes
46 *
47 * There are two types of netgraph sockets, control and data.
48 * Control sockets have a netgraph node, but data sockets are
49 * parasitic on control sockets, and have no node of their own.
50 */
51
52#include <sys/param.h>
53#include <sys/domain.h>
54#include <sys/hash.h>
54#include <sys/kernel.h>
55#include <sys/linker.h>
56#include <sys/lock.h>
57#include <sys/malloc.h>
58#include <sys/mbuf.h>
59#include <sys/mutex.h>
60#include <sys/priv.h>
61#include <sys/protosw.h>
62#include <sys/queue.h>
63#include <sys/socket.h>
64#include <sys/socketvar.h>
65#include <sys/syscallsubr.h>
66#include <sys/sysctl.h>
55#include <sys/kernel.h>
56#include <sys/linker.h>
57#include <sys/lock.h>
58#include <sys/malloc.h>
59#include <sys/mbuf.h>
60#include <sys/mutex.h>
61#include <sys/priv.h>
62#include <sys/protosw.h>
63#include <sys/queue.h>
64#include <sys/socket.h>
65#include <sys/socketvar.h>
66#include <sys/syscallsubr.h>
67#include <sys/sysctl.h>
67#ifdef NOTYET
68#include <sys/vnode.h>
69#endif
70
71#include <net/vnet.h>
72
73#include <netgraph/ng_message.h>
74#include <netgraph/netgraph.h>
75#include <netgraph/ng_socketvar.h>
76#include <netgraph/ng_socket.h>
77

--- 32 unchanged lines hidden (view full) ---

110 */
111
112/* Netgraph node methods */
113static ng_constructor_t ngs_constructor;
114static ng_rcvmsg_t ngs_rcvmsg;
115static ng_shutdown_t ngs_shutdown;
116static ng_newhook_t ngs_newhook;
117static ng_connect_t ngs_connect;
68
69#include <net/vnet.h>
70
71#include <netgraph/ng_message.h>
72#include <netgraph/netgraph.h>
73#include <netgraph/ng_socketvar.h>
74#include <netgraph/ng_socket.h>
75

--- 32 unchanged lines hidden (view full) ---

108 */
109
110/* Netgraph node methods */
111static ng_constructor_t ngs_constructor;
112static ng_rcvmsg_t ngs_rcvmsg;
113static ng_shutdown_t ngs_shutdown;
114static ng_newhook_t ngs_newhook;
115static ng_connect_t ngs_connect;
116static ng_findhook_t ngs_findhook;
118static ng_rcvdata_t ngs_rcvdata;
119static ng_disconnect_t ngs_disconnect;
120
121/* Internal methods */
122static int ng_attach_data(struct socket *so);
123static int ng_attach_cntl(struct socket *so);
124static int ng_attach_common(struct socket *so, int type);
125static void ng_detach_common(struct ngpcb *pcbp, int type);
126static void ng_socket_free_priv(struct ngsock *priv);
117static ng_rcvdata_t ngs_rcvdata;
118static ng_disconnect_t ngs_disconnect;
119
120/* Internal methods */
121static int ng_attach_data(struct socket *so);
122static int ng_attach_cntl(struct socket *so);
123static int ng_attach_common(struct socket *so, int type);
124static void ng_detach_common(struct ngpcb *pcbp, int type);
125static void ng_socket_free_priv(struct ngsock *priv);
127#ifdef NOTYET
128static int ng_internalize(struct mbuf *m, struct thread *p);
129#endif
130static int ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp);
131static int ng_bind(struct sockaddr *nam, struct ngpcb *pcbp);
132
133static int ngs_mod_event(module_t mod, int event, void *data);
134static void ng_socket_item_applied(void *context, int error);
135
136/* Netgraph type descriptor */
137static struct ng_type typestruct = {
138 .version = NG_ABI_VERSION,
139 .name = NG_SOCKET_NODE_TYPE,
140 .mod_event = ngs_mod_event,
141 .constructor = ngs_constructor,
142 .rcvmsg = ngs_rcvmsg,
143 .shutdown = ngs_shutdown,
144 .newhook = ngs_newhook,
145 .connect = ngs_connect,
126static int ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp);
127static int ng_bind(struct sockaddr *nam, struct ngpcb *pcbp);
128
129static int ngs_mod_event(module_t mod, int event, void *data);
130static void ng_socket_item_applied(void *context, int error);
131
132/* Netgraph type descriptor */
133static struct ng_type typestruct = {
134 .version = NG_ABI_VERSION,
135 .name = NG_SOCKET_NODE_TYPE,
136 .mod_event = ngs_mod_event,
137 .constructor = ngs_constructor,
138 .rcvmsg = ngs_rcvmsg,
139 .shutdown = ngs_shutdown,
140 .newhook = ngs_newhook,
141 .connect = ngs_connect,
142 .findhook = ngs_findhook,
146 .rcvdata = ngs_rcvdata,
147 .disconnect = ngs_disconnect,
148};
149NETGRAPH_INIT_ORDERED(socket, &typestruct, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
150
151/* Buffer space */
152static u_long ngpdg_sendspace = 20 * 1024; /* really max datagram size */
153SYSCTL_ULONG(_net_graph, OID_AUTO, maxdgram, CTLFLAG_RW,

--- 50 unchanged lines hidden (view full) ---

204 struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
205 struct ng_mesg *msg;
206 struct mbuf *m0;
207 item_p item;
208 char *path = NULL;
209 int len, error = 0;
210 struct ng_apply_info apply;
211
143 .rcvdata = ngs_rcvdata,
144 .disconnect = ngs_disconnect,
145};
146NETGRAPH_INIT_ORDERED(socket, &typestruct, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
147
148/* Buffer space */
149static u_long ngpdg_sendspace = 20 * 1024; /* really max datagram size */
150SYSCTL_ULONG(_net_graph, OID_AUTO, maxdgram, CTLFLAG_RW,

--- 50 unchanged lines hidden (view full) ---

201 struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
202 struct ng_mesg *msg;
203 struct mbuf *m0;
204 item_p item;
205 char *path = NULL;
206 int len, error = 0;
207 struct ng_apply_info apply;
208
212#ifdef NOTYET
213 if (control && (error = ng_internalize(control, td))) {
214 if (pcbp->sockdata == NULL) {
215 error = ENOTCONN;
216 goto release;
217 }
218 }
219#else /* NOTYET */
220 if (control) {
221 error = EINVAL;
222 goto release;
223 }
209 if (control) {
210 error = EINVAL;
211 goto release;
212 }
224#endif /* NOTYET */
225
226 /* Require destination as there may be >= 1 hooks on this node. */
227 if (addr == NULL) {
228 error = EDESTADDRREQ;
229 goto release;
230 }
231
232 /*

--- 301 unchanged lines hidden (view full) ---

534 pcbp = sotongpcb(so);
535
536 /* Make the generic node components */
537 if ((error = ng_make_node_common(&typestruct, &node)) != 0) {
538 ng_detach_common(pcbp, NG_CONTROL);
539 return (error);
540 }
541
213
214 /* Require destination as there may be >= 1 hooks on this node. */
215 if (addr == NULL) {
216 error = EDESTADDRREQ;
217 goto release;
218 }
219
220 /*

--- 301 unchanged lines hidden (view full) ---

522 pcbp = sotongpcb(so);
523
524 /* Make the generic node components */
525 if ((error = ng_make_node_common(&typestruct, &node)) != 0) {
526 ng_detach_common(pcbp, NG_CONTROL);
527 return (error);
528 }
529
542 /* Allocate node private info */
530 /*
531 * Allocate node private info and hash. We start
532 * with 16 hash entries, however we may grow later
533 * in ngs_newhook(). We can't predict how much hooks
534 * does this node plan to have.
535 */
543 priv = malloc(sizeof(*priv), M_NETGRAPH_SOCK, M_WAITOK | M_ZERO);
536 priv = malloc(sizeof(*priv), M_NETGRAPH_SOCK, M_WAITOK | M_ZERO);
537 priv->hash = hashinit(16, M_NETGRAPH_SOCK, &priv->hmask);
544
545 /* Initialize mutex. */
546 mtx_init(&priv->mtx, "ng_socket", NULL, MTX_DEF);
547
548 /* Link the pcb the private data. */
549 priv->ctlsock = pcbp;
550 pcbp->sockdata = priv;
551 priv->refs++;

--- 89 unchanged lines hidden (view full) ---

641ng_socket_free_priv(struct ngsock *priv)
642{
643 mtx_assert(&priv->mtx, MA_OWNED);
644
645 priv->refs--;
646
647 if (priv->refs == 0) {
648 mtx_destroy(&priv->mtx);
538
539 /* Initialize mutex. */
540 mtx_init(&priv->mtx, "ng_socket", NULL, MTX_DEF);
541
542 /* Link the pcb the private data. */
543 priv->ctlsock = pcbp;
544 pcbp->sockdata = priv;
545 priv->refs++;

--- 89 unchanged lines hidden (view full) ---

635ng_socket_free_priv(struct ngsock *priv)
636{
637 mtx_assert(&priv->mtx, MA_OWNED);
638
639 priv->refs--;
640
641 if (priv->refs == 0) {
642 mtx_destroy(&priv->mtx);
643 hashdestroy(priv->hash, M_NETGRAPH_SOCK, priv->hmask);
649 free(priv, M_NETGRAPH_SOCK);
650 return;
651 }
652
653 if ((priv->refs == 1) && (priv->node != NULL)) {
654 node_p node = priv->node;
655
656 priv->node = NULL;
657 mtx_unlock(&priv->mtx);
658 NG_NODE_UNREF(node);
659 ng_rmnode_self(node);
660 } else
661 mtx_unlock(&priv->mtx);
662}
663
644 free(priv, M_NETGRAPH_SOCK);
645 return;
646 }
647
648 if ((priv->refs == 1) && (priv->node != NULL)) {
649 node_p node = priv->node;
650
651 priv->node = NULL;
652 mtx_unlock(&priv->mtx);
653 NG_NODE_UNREF(node);
654 ng_rmnode_self(node);
655 } else
656 mtx_unlock(&priv->mtx);
657}
658
664#ifdef NOTYET
665/*
659/*
666 * File descriptors can be passed into an AF_NETGRAPH socket.
667 * Note, that file descriptors cannot be passed OUT.
668 * Only character device descriptors are accepted.
669 * Character devices are useful to connect a graph to a device,
670 * which after all is the purpose of this whole system.
671 */
672static int
673ng_internalize(struct mbuf *control, struct thread *td)
674{
675 const struct cmsghdr *cm = mtod(control, const struct cmsghdr *);
676 struct file *fp;
677 struct vnode *vn;
678 int oldfds;
679 int fd;
680
681 if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET ||
682 cm->cmsg_len != control->m_len) {
683 TRAP_ERROR;
684 return (EINVAL);
685 }
686
687 /* Check there is only one FD. XXX what would more than one signify? */
688 oldfds = ((caddr_t)cm + cm->cmsg_len - (caddr_t)data) / sizeof (int);
689 if (oldfds != 1) {
690 TRAP_ERROR;
691 return (EINVAL);
692 }
693
694 /* Check that the FD given is legit. and change it to a pointer to a
695 * struct file. */
696 fd = CMSG_DATA(cm);
697 if ((error = fget(td, fd, 0, &fp)) != 0)
698 return (error);
699
700 /* Depending on what kind of resource it is, act differently. For
701 * devices, we treat it as a file. For an AF_NETGRAPH socket,
702 * shortcut straight to the node. */
703 switch (fp->f_type) {
704 case DTYPE_VNODE:
705 vn = fp->f_data;
706 if (vn && (vn->v_type == VCHR)) {
707 /* for a VCHR, actually reference the FILE */
708 fhold(fp);
709 /* XXX then what :) */
710 /* how to pass on to other modules? */
711 } else {
712 fdrop(fp, td);
713 TRAP_ERROR;
714 return (EINVAL);
715 }
716 break;
717 default:
718 fdrop(fp, td);
719 TRAP_ERROR;
720 return (EINVAL);
721 }
722 fdrop(fp, td);
723 return (0);
724}
725#endif /* NOTYET */
726
727/*
728 * Connect the data socket to a named control socket node.
729 */
730static int
731ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp)
732{
733 struct sockaddr_ng *sap;
734 node_p farnode;
735 struct ngsock *priv;

--- 76 unchanged lines hidden (view full) ---

812 * You can only create new nodes from the socket end of things.
813 */
814static int
815ngs_constructor(node_p nodep)
816{
817 return (EINVAL);
818}
819
660 * Connect the data socket to a named control socket node.
661 */
662static int
663ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp)
664{
665 struct sockaddr_ng *sap;
666 node_p farnode;
667 struct ngsock *priv;

--- 76 unchanged lines hidden (view full) ---

744 * You can only create new nodes from the socket end of things.
745 */
746static int
747ngs_constructor(node_p nodep)
748{
749 return (EINVAL);
750}
751
752static void
753ngs_rehash(node_p node)
754{
755 struct ngsock *priv = NG_NODE_PRIVATE(node);
756 struct ngshash *new;
757 struct hookpriv *hp;
758 hook_p hook;
759 uint32_t h;
760 u_long hmask;
761
762 new = hashinit_flags((priv->hmask + 1) * 2, M_NETGRAPH_SOCK, &hmask,
763 HASH_NOWAIT);
764 if (new == NULL)
765 return;
766
767 LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
768 hp = NG_HOOK_PRIVATE(hook);
769#ifdef INVARIANTS
770 LIST_REMOVE(hp, next);
771#endif
772 h = hash32_str(NG_HOOK_NAME(hook), HASHINIT) & hmask;
773 LIST_INSERT_HEAD(&new[h], hp, next);
774 }
775
776 hashdestroy(priv->hash, M_NETGRAPH_SOCK, priv->hmask);
777 priv->hash = new;
778 priv->hmask = hmask;
779}
780
820/*
821 * We allow any hook to be connected to the node.
822 * There is no per-hook private information though.
823 */
824static int
825ngs_newhook(node_p node, hook_p hook, const char *name)
826{
781/*
782 * We allow any hook to be connected to the node.
783 * There is no per-hook private information though.
784 */
785static int
786ngs_newhook(node_p node, hook_p hook, const char *name)
787{
827 NG_HOOK_SET_PRIVATE(hook, NG_NODE_PRIVATE(node));
788 struct ngsock *const priv = NG_NODE_PRIVATE(node);
789 struct hookpriv *hp;
790 uint32_t h;
791
792 hp = malloc(sizeof(*hp), M_NETGRAPH_SOCK, M_NOWAIT);
793 if (hp == NULL)
794 return (ENOMEM);
795 if (node->nd_numhooks * 2 > priv->hmask)
796 ngs_rehash(node);
797 hp->hook = hook;
798 h = hash32_str(name, HASHINIT) & priv->hmask;
799 LIST_INSERT_HEAD(&priv->hash[h], hp, next);
800 NG_HOOK_SET_PRIVATE(hook, hp);
801
828 return (0);
829}
830
831/*
832 * If only one hook, allow read(2) and write(2) to work.
833 */
834static int
835ngs_connect(hook_p hook)

--- 5 unchanged lines hidden (view full) ---

841 if (NG_NODE_NUMHOOKS(node) == 1)
842 priv->datasock->ng_socket->so_state |= SS_ISCONNECTED;
843 else
844 priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED;
845 }
846 return (0);
847}
848
802 return (0);
803}
804
805/*
806 * If only one hook, allow read(2) and write(2) to work.
807 */
808static int
809ngs_connect(hook_p hook)

--- 5 unchanged lines hidden (view full) ---

815 if (NG_NODE_NUMHOOKS(node) == 1)
816 priv->datasock->ng_socket->so_state |= SS_ISCONNECTED;
817 else
818 priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED;
819 }
820 return (0);
821}
822
823/* Look up hook by name */
824static hook_p
825ngs_findhook(node_p node, const char *name)
826{
827 struct ngsock *priv = NG_NODE_PRIVATE(node);
828 struct hookpriv *hp;
829 uint32_t h;
830
831 /*
832 * Microoptimisation for an ng_socket with
833 * a single hook, which is a common case.
834 */
835 if (node->nd_numhooks == 1) {
836 hook_p hook;
837
838 hook = LIST_FIRST(&node->nd_hooks);
839
840 if (strcmp(NG_HOOK_NAME(hook), name) == 0)
841 return (hook);
842 else
843 return (NULL);
844 }
845
846 h = hash32_str(name, HASHINIT) & priv->hmask;
847
848 LIST_FOREACH(hp, &priv->hash[h], next)
849 if (strcmp(NG_HOOK_NAME(hp->hook), name) == 0)
850 return (hp->hook);
851
852 return (NULL);
853}
854
849/*
850 * Incoming messages get passed up to the control socket.
851 * Unless they are for us specifically (socket_type)
852 */
853static int
854ngs_rcvmsg(node_p node, item_p item, hook_p lasthook)
855{
856 struct ngsock *const priv = NG_NODE_PRIVATE(node);

--- 151 unchanged lines hidden (view full) ---

1008 * For this type, removal of the last link destroys the node
1009 * if the NOLINGER flag is set.
1010 */
1011static int
1012ngs_disconnect(hook_p hook)
1013{
1014 node_p node = NG_HOOK_NODE(hook);
1015 struct ngsock *const priv = NG_NODE_PRIVATE(node);
855/*
856 * Incoming messages get passed up to the control socket.
857 * Unless they are for us specifically (socket_type)
858 */
859static int
860ngs_rcvmsg(node_p node, item_p item, hook_p lasthook)
861{
862 struct ngsock *const priv = NG_NODE_PRIVATE(node);

--- 151 unchanged lines hidden (view full) ---

1014 * For this type, removal of the last link destroys the node
1015 * if the NOLINGER flag is set.
1016 */
1017static int
1018ngs_disconnect(hook_p hook)
1019{
1020 node_p node = NG_HOOK_NODE(hook);
1021 struct ngsock *const priv = NG_NODE_PRIVATE(node);
1022 struct hookpriv *hp = NG_HOOK_PRIVATE(hook);
1016
1023
1024 LIST_REMOVE(hp, next);
1025 free(hp, M_NETGRAPH_SOCK);
1026
1017 if ((priv->datasock) && (priv->datasock->ng_socket)) {
1018 if (NG_NODE_NUMHOOKS(node) == 1)
1019 priv->datasock->ng_socket->so_state |= SS_ISCONNECTED;
1020 else
1021 priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED;
1022 }
1023
1024 if ((priv->flags & NGS_FLAG_NOLINGER) &&

--- 155 unchanged lines hidden ---
1027 if ((priv->datasock) && (priv->datasock->ng_socket)) {
1028 if (NG_NODE_NUMHOOKS(node) == 1)
1029 priv->datasock->ng_socket->so_state |= SS_ISCONNECTED;
1030 else
1031 priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED;
1032 }
1033
1034 if ((priv->flags & NGS_FLAG_NOLINGER) &&

--- 155 unchanged lines hidden ---