ng_ksocket.c (166585) | ng_ksocket.c (176917) |
---|---|
1/* 2 * ng_ksocket.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: Archie Cobbs <archie@freebsd.org> 39 * | 1/* 2 * ng_ksocket.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: Archie Cobbs <archie@freebsd.org> 39 * |
40 * $FreeBSD: head/sys/netgraph/ng_ksocket.c 166585 2007-02-09 12:35:29Z bms $ | 40 * $FreeBSD: head/sys/netgraph/ng_ksocket.c 176917 2008-03-07 21:12:56Z mav $ |
41 * $Whistle: ng_ksocket.c,v 1.1 1999/11/16 20:04:40 archie Exp $ 42 */ 43 44/* 45 * Kernel socket node type. This node type is basically a kernel-mode 46 * version of a socket... kindof like the reverse of the socket node type. 47 */ 48 --- 28 unchanged lines hidden (view full) --- 77#define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0)) 78#define SADATA_OFFSET (OFFSETOF(struct sockaddr, sa_data)) 79 80/* Node private data */ 81struct ng_ksocket_private { 82 node_p node; 83 hook_p hook; 84 struct socket *so; | 41 * $Whistle: ng_ksocket.c,v 1.1 1999/11/16 20:04:40 archie Exp $ 42 */ 43 44/* 45 * Kernel socket node type. This node type is basically a kernel-mode 46 * version of a socket... kindof like the reverse of the socket node type. 47 */ 48 --- 28 unchanged lines hidden (view full) --- 77#define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0)) 78#define SADATA_OFFSET (OFFSETOF(struct sockaddr, sa_data)) 79 80/* Node private data */ 81struct ng_ksocket_private { 82 node_p node; 83 hook_p hook; 84 struct socket *so; |
85 int fn_sent; /* FN call on incoming event was sent */ |
|
85 LIST_HEAD(, ng_ksocket_private) embryos; 86 LIST_ENTRY(ng_ksocket_private) siblings; 87 u_int32_t flags; 88 u_int32_t response_token; 89 ng_ID_t response_addr; 90}; 91typedef struct ng_ksocket_private *priv_p; 92 --- 63 unchanged lines hidden (view full) --- 156 157/* Helper functions */ 158static int ng_ksocket_check_accept(priv_p); 159static void ng_ksocket_finish_accept(priv_p); 160static void ng_ksocket_incoming(struct socket *so, void *arg, int waitflag); 161static int ng_ksocket_parse(const struct ng_ksocket_alias *aliases, 162 const char *s, int family); 163static void ng_ksocket_incoming2(node_p node, hook_p hook, | 86 LIST_HEAD(, ng_ksocket_private) embryos; 87 LIST_ENTRY(ng_ksocket_private) siblings; 88 u_int32_t flags; 89 u_int32_t response_token; 90 ng_ID_t response_addr; 91}; 92typedef struct ng_ksocket_private *priv_p; 93 --- 63 unchanged lines hidden (view full) --- 157 158/* Helper functions */ 159static int ng_ksocket_check_accept(priv_p); 160static void ng_ksocket_finish_accept(priv_p); 161static void ng_ksocket_incoming(struct socket *so, void *arg, int waitflag); 162static int ng_ksocket_parse(const struct ng_ksocket_alias *aliases, 163 const char *s, int family); 164static void ng_ksocket_incoming2(node_p node, hook_p hook, |
164 void *arg1, int waitflag); | 165 void *arg1, int arg2); |
165 166/************************************************************************ 167 STRUCT SOCKADDR PARSE TYPE 168 ************************************************************************/ 169 170/* Get the length of the data portion of a generic struct sockaddr */ 171static int 172ng_parse_generic_sockdata_getLength(const struct ng_parse_type *type, --- 761 unchanged lines hidden (view full) --- 934static int 935ng_ksocket_shutdown(node_p node) 936{ 937 const priv_p priv = NG_NODE_PRIVATE(node); 938 priv_p embryo; 939 940 /* Close our socket (if any) */ 941 if (priv->so != NULL) { | 166 167/************************************************************************ 168 STRUCT SOCKADDR PARSE TYPE 169 ************************************************************************/ 170 171/* Get the length of the data portion of a generic struct sockaddr */ 172static int 173ng_parse_generic_sockdata_getLength(const struct ng_parse_type *type, --- 761 unchanged lines hidden (view full) --- 935static int 936ng_ksocket_shutdown(node_p node) 937{ 938 const priv_p priv = NG_NODE_PRIVATE(node); 939 priv_p embryo; 940 941 /* Close our socket (if any) */ 942 if (priv->so != NULL) { |
942 priv->so->so_upcall = NULL; | |
943 SOCKBUF_LOCK(&priv->so->so_rcv); 944 priv->so->so_rcv.sb_flags &= ~SB_UPCALL; 945 SOCKBUF_UNLOCK(&priv->so->so_rcv); 946 SOCKBUF_LOCK(&priv->so->so_snd); 947 priv->so->so_snd.sb_flags &= ~SB_UPCALL; 948 SOCKBUF_UNLOCK(&priv->so->so_snd); | 943 SOCKBUF_LOCK(&priv->so->so_rcv); 944 priv->so->so_rcv.sb_flags &= ~SB_UPCALL; 945 SOCKBUF_UNLOCK(&priv->so->so_rcv); 946 SOCKBUF_LOCK(&priv->so->so_snd); 947 priv->so->so_snd.sb_flags &= ~SB_UPCALL; 948 SOCKBUF_UNLOCK(&priv->so->so_snd); |
949 priv->so->so_upcall = NULL; |
|
949 soclose(priv->so); 950 priv->so = NULL; 951 } 952 953 /* If we are an embryo, take ourselves out of the parent's list */ 954 if (priv->flags & KSF_EMBRYONIC) { 955 LIST_REMOVE(priv, siblings); 956 priv->flags &= ~KSF_EMBRYONIC; --- 26 unchanged lines hidden (view full) --- 983 ng_rmnode_self(NG_HOOK_NODE(hook)); 984 return (0); 985} 986 987/************************************************************************ 988 HELPER STUFF 989 ************************************************************************/ 990/* | 950 soclose(priv->so); 951 priv->so = NULL; 952 } 953 954 /* If we are an embryo, take ourselves out of the parent's list */ 955 if (priv->flags & KSF_EMBRYONIC) { 956 LIST_REMOVE(priv, siblings); 957 priv->flags &= ~KSF_EMBRYONIC; --- 26 unchanged lines hidden (view full) --- 984 ng_rmnode_self(NG_HOOK_NODE(hook)); 985 return (0); 986} 987 988/************************************************************************ 989 HELPER STUFF 990 ************************************************************************/ 991/* |
991 * You should no-longer "just call" a netgraph node function 992 * from an external asynchronous event. 993 * This is because in doing so you are ignoring the locking on the netgraph 994 * nodes. Instead call your function via 995 * "int ng_send_fn(node_p node, hook_p hook, ng_item_fn *fn, 996 * void *arg1, int arg2);" 997 * this will call the function you chose, but will first do all the | 992 * You should not "just call" a netgraph node function from an external 993 * asynchronous event. This is because in doing so you are ignoring the 994 * locking on the netgraph nodes. Instead call your function via ng_send_fn(). 995 * This will call the function you chose, but will first do all the |
998 * locking rigmarole. Your function MAY only be called at some distant future 999 * time (several millisecs away) so don't give it any arguments 1000 * that may be revoked soon (e.g. on your stack). | 996 * locking rigmarole. Your function MAY only be called at some distant future 997 * time (several millisecs away) so don't give it any arguments 998 * that may be revoked soon (e.g. on your stack). |
1001 * In this case even the 'so' argument is doubtful. 1002 * While the function request is being processed the node 1003 * has an extra reference and as such will not disappear until 1004 * the request has at least been done, but the 'so' may not be so lucky. 1005 * handle this by checking the validity of the node in the target function 1006 * before dereferencing the socket pointer. | |
1007 * 1008 * To decouple stack, we use queue version of ng_send_fn(). 1009 */ 1010 1011static void 1012ng_ksocket_incoming(struct socket *so, void *arg, int waitflag) 1013{ 1014 const node_p node = arg; | 999 * 1000 * To decouple stack, we use queue version of ng_send_fn(). 1001 */ 1002 1003static void 1004ng_ksocket_incoming(struct socket *so, void *arg, int waitflag) 1005{ 1006 const node_p node = arg; |
1015 int wait; | 1007 const priv_p priv = NG_NODE_PRIVATE(node); 1008 int wait = ((waitflag & M_WAITOK) ? NG_WAITOK : 0) | NG_QUEUE; |
1016 | 1009 |
1017 wait = (waitflag & M_WAITOK) ? NG_WAITOK : 0; 1018 ng_send_fn1(node, NULL, &ng_ksocket_incoming2, so, waitflag, 1019 wait | NG_QUEUE); | 1010 /* 1011 * Even if node is not locked, as soon as we are called, we assume 1012 * it exist and it's private area is valid. With some care we can 1013 * access it. Mark node that incoming event for it was sent to 1014 * avoid unneded queue trashing. 1015 */ 1016 if (atomic_cmpset_int(&priv->fn_sent, 0, 1) && 1017 ng_send_fn1(node, NULL, &ng_ksocket_incoming2, so, 0, wait)) { 1018 atomic_store_rel_int(&priv->fn_sent, 0); 1019 } |
1020} 1021 1022 1023/* 1024 * When incoming data is appended to the socket, we get notified here. 1025 * This is also called whenever a significant event occurs for the socket. | 1020} 1021 1022 1023/* 1024 * When incoming data is appended to the socket, we get notified here. 1025 * This is also called whenever a significant event occurs for the socket. |
1026 * We know that HOOK is NULL. Because of how we were called we know we have a 1027 * lock on this node an are participating inthe netgraph locking. | |
1028 * Our original caller may have queued this even some time ago and 1029 * we cannot trust that he even still exists. The node however is being | 1026 * Our original caller may have queued this even some time ago and 1027 * we cannot trust that he even still exists. The node however is being |
1030 * held with a reference by the queueing code, at least until we finish, 1031 * even if it has been zapped, so first check it's validiy 1032 * before we trust the socket (which was derived from it). | 1028 * held with a reference by the queueing code and guarantied to be valid. |
1033 */ 1034static void | 1029 */ 1030static void |
1035ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int waitflag) | 1031ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int arg2) |
1036{ 1037 struct socket *so = arg1; 1038 const priv_p priv = NG_NODE_PRIVATE(node); 1039 struct mbuf *m; 1040 struct ng_mesg *response; 1041 struct uio auio; 1042 int s, flags, error; 1043 1044 s = splnet(); 1045 | 1032{ 1033 struct socket *so = arg1; 1034 const priv_p priv = NG_NODE_PRIVATE(node); 1035 struct mbuf *m; 1036 struct ng_mesg *response; 1037 struct uio auio; 1038 int s, flags, error; 1039 1040 s = splnet(); 1041 |
1046 /* Sanity check */ 1047 if (NG_NODE_NOT_VALID(node)) { 1048 splx(s); 1049 return; 1050 } | |
1051 /* so = priv->so; *//* XXX could have derived this like so */ 1052 KASSERT(so == priv->so, ("%s: wrong socket", __func__)); | 1042 /* so = priv->so; *//* XXX could have derived this like so */ 1043 KASSERT(so == priv->so, ("%s: wrong socket", __func__)); |
1044 1045 /* Allow next incoming event to be queued. */ 1046 atomic_store_rel_int(&priv->fn_sent, 0); |
|
1053 1054 /* Check whether a pending connect operation has completed */ 1055 if (priv->flags & KSF_CONNECTING) { 1056 if ((error = so->so_error) != 0) { 1057 so->so_error = 0; 1058 so->so_state &= ~SS_ISCONNECTING; 1059 } 1060 if (!(so->so_state & SS_ISCONNECTING)) { 1061 NG_MKMESSAGE(response, NGM_KSOCKET_COOKIE, | 1047 1048 /* Check whether a pending connect operation has completed */ 1049 if (priv->flags & KSF_CONNECTING) { 1050 if ((error = so->so_error) != 0) { 1051 so->so_error = 0; 1052 so->so_state &= ~SS_ISCONNECTING; 1053 } 1054 if (!(so->so_state & SS_ISCONNECTING)) { 1055 NG_MKMESSAGE(response, NGM_KSOCKET_COOKIE, |
1062 NGM_KSOCKET_CONNECT, sizeof(int32_t), waitflag); | 1056 NGM_KSOCKET_CONNECT, sizeof(int32_t), M_NOWAIT); |
1063 if (response != NULL) { 1064 response->header.flags |= NGF_RESP; 1065 response->header.token = priv->response_token; 1066 *(int32_t *)response->data = error; 1067 /* 1068 * send an async "response" message 1069 * to the node that set us up 1070 * (if it still exists) --- 78 unchanged lines hidden (view full) --- 1149 NG_SEND_DATA_ONLY(error, priv->hook, m); 1150 } 1151 1152 /* 1153 * If the peer has closed the connection, forward a 0-length mbuf 1154 * to indicate end-of-file. 1155 */ 1156 if (so->so_rcv.sb_state & SBS_CANTRCVMORE && !(priv->flags & KSF_EOFSEEN)) { | 1057 if (response != NULL) { 1058 response->header.flags |= NGF_RESP; 1059 response->header.token = priv->response_token; 1060 *(int32_t *)response->data = error; 1061 /* 1062 * send an async "response" message 1063 * to the node that set us up 1064 * (if it still exists) --- 78 unchanged lines hidden (view full) --- 1143 NG_SEND_DATA_ONLY(error, priv->hook, m); 1144 } 1145 1146 /* 1147 * If the peer has closed the connection, forward a 0-length mbuf 1148 * to indicate end-of-file. 1149 */ 1150 if (so->so_rcv.sb_state & SBS_CANTRCVMORE && !(priv->flags & KSF_EOFSEEN)) { |
1157 MGETHDR(m, waitflag, MT_DATA); | 1151 MGETHDR(m, M_NOWAIT, MT_DATA); |
1158 if (m != NULL) { 1159 m->m_len = m->m_pkthdr.len = 0; 1160 NG_SEND_DATA_ONLY(error, priv->hook, m); 1161 } 1162 priv->flags |= KSF_EOFSEEN; 1163 } 1164 splx(s); 1165} --- 146 unchanged lines hidden --- | 1152 if (m != NULL) { 1153 m->m_len = m->m_pkthdr.len = 0; 1154 NG_SEND_DATA_ONLY(error, priv->hook, m); 1155 } 1156 priv->flags |= KSF_EOFSEEN; 1157 } 1158 splx(s); 1159} --- 146 unchanged lines hidden --- |