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 --- |