Deleted Added
full compact
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 ---