1cb3c7a5dSArchie Cobbs 2cb3c7a5dSArchie Cobbs /* 3cb3c7a5dSArchie Cobbs * ng_ksocket.c 4cb3c7a5dSArchie Cobbs * 5cb3c7a5dSArchie Cobbs * Copyright (c) 1996-1999 Whistle Communications, Inc. 6cb3c7a5dSArchie Cobbs * All rights reserved. 7cb3c7a5dSArchie Cobbs * 8cb3c7a5dSArchie Cobbs * Subject to the following obligations and disclaimer of warranty, use and 9cb3c7a5dSArchie Cobbs * redistribution of this software, in source or object code forms, with or 10cb3c7a5dSArchie Cobbs * without modifications are expressly permitted by Whistle Communications; 11cb3c7a5dSArchie Cobbs * provided, however, that: 12cb3c7a5dSArchie Cobbs * 1. Any and all reproductions of the source or object code must include the 13cb3c7a5dSArchie Cobbs * copyright notice above and the following disclaimer of warranties; and 14cb3c7a5dSArchie Cobbs * 2. No rights are granted, in any manner or form, to use Whistle 15cb3c7a5dSArchie Cobbs * Communications, Inc. trademarks, including the mark "WHISTLE 16cb3c7a5dSArchie Cobbs * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 17cb3c7a5dSArchie Cobbs * such appears in the above copyright notice or in the software. 18cb3c7a5dSArchie Cobbs * 19cb3c7a5dSArchie Cobbs * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 20cb3c7a5dSArchie Cobbs * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 21cb3c7a5dSArchie Cobbs * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 22cb3c7a5dSArchie Cobbs * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 23cb3c7a5dSArchie Cobbs * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 24cb3c7a5dSArchie Cobbs * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 25cb3c7a5dSArchie Cobbs * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 26cb3c7a5dSArchie Cobbs * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 27cb3c7a5dSArchie Cobbs * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 28cb3c7a5dSArchie Cobbs * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 29cb3c7a5dSArchie Cobbs * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 30cb3c7a5dSArchie Cobbs * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 31cb3c7a5dSArchie Cobbs * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 32cb3c7a5dSArchie Cobbs * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33cb3c7a5dSArchie Cobbs * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34cb3c7a5dSArchie Cobbs * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 35cb3c7a5dSArchie Cobbs * OF SUCH DAMAGE. 36cb3c7a5dSArchie Cobbs * 37cb3c7a5dSArchie Cobbs * Author: Archie Cobbs <archie@whistle.com> 38cb3c7a5dSArchie Cobbs * 39cb3c7a5dSArchie Cobbs * $FreeBSD$ 40cb3c7a5dSArchie Cobbs * $Whistle: ng_ksocket.c,v 1.1 1999/11/16 20:04:40 archie Exp $ 41cb3c7a5dSArchie Cobbs */ 42cb3c7a5dSArchie Cobbs 43cb3c7a5dSArchie Cobbs /* 44cb3c7a5dSArchie Cobbs * Kernel socket node type. This node type is basically a kernel-mode 45cb3c7a5dSArchie Cobbs * version of a socket... kindof like the reverse of the socket node type. 46cb3c7a5dSArchie Cobbs */ 47cb3c7a5dSArchie Cobbs 48cb3c7a5dSArchie Cobbs #include <sys/param.h> 49cb3c7a5dSArchie Cobbs #include <sys/systm.h> 50cb3c7a5dSArchie Cobbs #include <sys/kernel.h> 51cb3c7a5dSArchie Cobbs #include <sys/conf.h> 52cb3c7a5dSArchie Cobbs #include <sys/mbuf.h> 53cb3c7a5dSArchie Cobbs #include <sys/proc.h> 54cb3c7a5dSArchie Cobbs #include <sys/malloc.h> 55cb3c7a5dSArchie Cobbs #include <sys/protosw.h> 56cb3c7a5dSArchie Cobbs #include <sys/errno.h> 57cb3c7a5dSArchie Cobbs #include <sys/socket.h> 58cb3c7a5dSArchie Cobbs #include <sys/socketvar.h> 59cb3c7a5dSArchie Cobbs #include <sys/syslog.h> 60cb3c7a5dSArchie Cobbs #include <sys/uio.h> 61cb3c7a5dSArchie Cobbs 62cb3c7a5dSArchie Cobbs #include <netgraph/ng_message.h> 63cb3c7a5dSArchie Cobbs #include <netgraph/netgraph.h> 64cb3c7a5dSArchie Cobbs #include <netgraph/ng_ksocket.h> 65cb3c7a5dSArchie Cobbs 66cb3c7a5dSArchie Cobbs #include <netinet/in.h> 67cb3c7a5dSArchie Cobbs #include <netatalk/at.h> 68cb3c7a5dSArchie Cobbs 69cb3c7a5dSArchie Cobbs /* Node private data */ 7019bff684SArchie Cobbs struct ng_ksocket_private { 71cb3c7a5dSArchie Cobbs hook_p hook; 72cb3c7a5dSArchie Cobbs struct socket *so; 73cb3c7a5dSArchie Cobbs }; 7419bff684SArchie Cobbs typedef struct ng_ksocket_private *priv_p; 75cb3c7a5dSArchie Cobbs 76cb3c7a5dSArchie Cobbs /* Netgraph node methods */ 77cb3c7a5dSArchie Cobbs static ng_constructor_t ng_ksocket_constructor; 78cb3c7a5dSArchie Cobbs static ng_rcvmsg_t ng_ksocket_rcvmsg; 79cb3c7a5dSArchie Cobbs static ng_shutdown_t ng_ksocket_rmnode; 80cb3c7a5dSArchie Cobbs static ng_newhook_t ng_ksocket_newhook; 81cb3c7a5dSArchie Cobbs static ng_rcvdata_t ng_ksocket_rcvdata; 82cb3c7a5dSArchie Cobbs static ng_disconnect_t ng_ksocket_disconnect; 83cb3c7a5dSArchie Cobbs 84cb3c7a5dSArchie Cobbs /* Alias structure */ 85cb3c7a5dSArchie Cobbs struct ng_ksocket_alias { 86cb3c7a5dSArchie Cobbs const char *name; 87cb3c7a5dSArchie Cobbs const int value; 88cb3c7a5dSArchie Cobbs const int family; 89cb3c7a5dSArchie Cobbs }; 90cb3c7a5dSArchie Cobbs 91cb3c7a5dSArchie Cobbs /* Helper functions */ 92cb3c7a5dSArchie Cobbs static void ng_ksocket_incoming(struct socket *so, void *arg, int waitflag); 93cb3c7a5dSArchie Cobbs static int ng_ksocket_parse(const struct ng_ksocket_alias *aliases, 94cb3c7a5dSArchie Cobbs const char *s, int family); 95cb3c7a5dSArchie Cobbs 96cb3c7a5dSArchie Cobbs /* Node type descriptor */ 97cb3c7a5dSArchie Cobbs static struct ng_type ng_ksocket_typestruct = { 98cb3c7a5dSArchie Cobbs NG_VERSION, 99cb3c7a5dSArchie Cobbs NG_KSOCKET_NODE_TYPE, 100cb3c7a5dSArchie Cobbs NULL, 101cb3c7a5dSArchie Cobbs ng_ksocket_constructor, 102cb3c7a5dSArchie Cobbs ng_ksocket_rcvmsg, 103cb3c7a5dSArchie Cobbs ng_ksocket_rmnode, 104cb3c7a5dSArchie Cobbs ng_ksocket_newhook, 105cb3c7a5dSArchie Cobbs NULL, 106cb3c7a5dSArchie Cobbs NULL, 107cb3c7a5dSArchie Cobbs ng_ksocket_rcvdata, 108cb3c7a5dSArchie Cobbs ng_ksocket_rcvdata, 109cb3c7a5dSArchie Cobbs ng_ksocket_disconnect 110cb3c7a5dSArchie Cobbs }; 111cb3c7a5dSArchie Cobbs NETGRAPH_INIT(ksocket, &ng_ksocket_typestruct); 112cb3c7a5dSArchie Cobbs 113cb3c7a5dSArchie Cobbs /* Protocol family aliases */ 114cb3c7a5dSArchie Cobbs static const struct ng_ksocket_alias ng_ksocket_families[] = { 115cb3c7a5dSArchie Cobbs { "local", PF_LOCAL }, 116cb3c7a5dSArchie Cobbs { "inet", PF_INET }, 117cb3c7a5dSArchie Cobbs { "inet6", PF_INET6 }, 118cb3c7a5dSArchie Cobbs { "atalk", PF_APPLETALK }, 119cb3c7a5dSArchie Cobbs { "ipx", PF_IPX }, 120cb3c7a5dSArchie Cobbs { "atm", PF_ATM }, 121cb3c7a5dSArchie Cobbs { NULL, -1 }, 122cb3c7a5dSArchie Cobbs }; 123cb3c7a5dSArchie Cobbs 124cb3c7a5dSArchie Cobbs /* Socket type aliases */ 125cb3c7a5dSArchie Cobbs static const struct ng_ksocket_alias ng_ksocket_types[] = { 126cb3c7a5dSArchie Cobbs { "stream", SOCK_STREAM }, 127cb3c7a5dSArchie Cobbs { "dgram", SOCK_DGRAM }, 128cb3c7a5dSArchie Cobbs { "raw", SOCK_RAW }, 129cb3c7a5dSArchie Cobbs { "rdm", SOCK_RDM }, 130cb3c7a5dSArchie Cobbs { "seqpacket", SOCK_SEQPACKET }, 131cb3c7a5dSArchie Cobbs { NULL, -1 }, 132cb3c7a5dSArchie Cobbs }; 133cb3c7a5dSArchie Cobbs 134cb3c7a5dSArchie Cobbs /* Protocol aliases */ 135cb3c7a5dSArchie Cobbs static const struct ng_ksocket_alias ng_ksocket_protos[] = { 136cb3c7a5dSArchie Cobbs { "ip", IPPROTO_IP, PF_INET }, 137cb3c7a5dSArchie Cobbs { "raw", IPPROTO_IP, PF_INET }, 138cb3c7a5dSArchie Cobbs { "icmp", IPPROTO_ICMP, PF_INET }, 139cb3c7a5dSArchie Cobbs { "igmp", IPPROTO_IGMP, PF_INET }, 140cb3c7a5dSArchie Cobbs { "tcp", IPPROTO_TCP, PF_INET }, 141cb3c7a5dSArchie Cobbs { "udp", IPPROTO_UDP, PF_INET }, 142cb3c7a5dSArchie Cobbs { "gre", IPPROTO_GRE, PF_INET }, 143cb3c7a5dSArchie Cobbs { "esp", IPPROTO_ESP, PF_INET }, 144cb3c7a5dSArchie Cobbs { "ah", IPPROTO_AH, PF_INET }, 145cb3c7a5dSArchie Cobbs { "swipe", IPPROTO_SWIPE, PF_INET }, 146cb3c7a5dSArchie Cobbs { "encap", IPPROTO_ENCAP, PF_INET }, 147cb3c7a5dSArchie Cobbs { "divert", IPPROTO_DIVERT, PF_INET }, 148cb3c7a5dSArchie Cobbs { "ddp", ATPROTO_DDP, PF_APPLETALK }, 149cb3c7a5dSArchie Cobbs { "aarp", ATPROTO_AARP, PF_APPLETALK }, 150cb3c7a5dSArchie Cobbs { NULL, -1 }, 151cb3c7a5dSArchie Cobbs }; 152cb3c7a5dSArchie Cobbs 153cb3c7a5dSArchie Cobbs #define ERROUT(x) do { error = (x); goto done; } while (0) 154cb3c7a5dSArchie Cobbs 155cb3c7a5dSArchie Cobbs /************************************************************************ 156cb3c7a5dSArchie Cobbs NETGRAPH NODE STUFF 157cb3c7a5dSArchie Cobbs ************************************************************************/ 158cb3c7a5dSArchie Cobbs 159cb3c7a5dSArchie Cobbs /* 160cb3c7a5dSArchie Cobbs * Node type constructor 161cb3c7a5dSArchie Cobbs */ 162cb3c7a5dSArchie Cobbs static int 163cb3c7a5dSArchie Cobbs ng_ksocket_constructor(node_p *nodep) 164cb3c7a5dSArchie Cobbs { 165cb3c7a5dSArchie Cobbs priv_p priv; 166cb3c7a5dSArchie Cobbs int error; 167cb3c7a5dSArchie Cobbs 168cb3c7a5dSArchie Cobbs /* Allocate private structure */ 169cb3c7a5dSArchie Cobbs MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_WAITOK); 170cb3c7a5dSArchie Cobbs if (priv == NULL) 171cb3c7a5dSArchie Cobbs return (ENOMEM); 172cb3c7a5dSArchie Cobbs bzero(priv, sizeof(*priv)); 173cb3c7a5dSArchie Cobbs 174cb3c7a5dSArchie Cobbs /* Call generic node constructor */ 175cb3c7a5dSArchie Cobbs if ((error = ng_make_node_common(&ng_ksocket_typestruct, nodep))) { 176cb3c7a5dSArchie Cobbs FREE(priv, M_NETGRAPH); 177cb3c7a5dSArchie Cobbs return (error); 178cb3c7a5dSArchie Cobbs } 179cb3c7a5dSArchie Cobbs (*nodep)->private = priv; 180cb3c7a5dSArchie Cobbs 181cb3c7a5dSArchie Cobbs /* Done */ 182cb3c7a5dSArchie Cobbs return (0); 183cb3c7a5dSArchie Cobbs } 184cb3c7a5dSArchie Cobbs 185cb3c7a5dSArchie Cobbs /* 186cb3c7a5dSArchie Cobbs * Give our OK for a hook to be added. The hook name is of the 187cb3c7a5dSArchie Cobbs * form "<family>:<type>:<proto>" where the three components may 188cb3c7a5dSArchie Cobbs * be decimal numbers or else aliases from the above lists. 189cb3c7a5dSArchie Cobbs * 190cb3c7a5dSArchie Cobbs * Connecting a hook amounts to opening the socket. Disconnecting 191cb3c7a5dSArchie Cobbs * the hook closes the socket and destroys the node as well. 192cb3c7a5dSArchie Cobbs */ 193cb3c7a5dSArchie Cobbs static int 194cb3c7a5dSArchie Cobbs ng_ksocket_newhook(node_p node, hook_p hook, const char *name0) 195cb3c7a5dSArchie Cobbs { 196cb3c7a5dSArchie Cobbs const priv_p priv = node->private; 197cb3c7a5dSArchie Cobbs char *s1, *s2, name[NG_HOOKLEN+1]; 198cb3c7a5dSArchie Cobbs int family, type, protocol, error; 199cb3c7a5dSArchie Cobbs struct proc *p = &proc0; /* XXX help what to do here */ 200cb3c7a5dSArchie Cobbs 201cb3c7a5dSArchie Cobbs /* Check if we're already connected */ 202cb3c7a5dSArchie Cobbs if (priv->hook != NULL) 203cb3c7a5dSArchie Cobbs return (EISCONN); 204cb3c7a5dSArchie Cobbs 205cb3c7a5dSArchie Cobbs /* Extract family, type, and protocol from hook name */ 206cb3c7a5dSArchie Cobbs snprintf(name, sizeof(name), "%s", name0); 207cb3c7a5dSArchie Cobbs s1 = name; 208cb3c7a5dSArchie Cobbs if ((s2 = index(s1, '/')) == NULL) 209cb3c7a5dSArchie Cobbs return (EINVAL); 210cb3c7a5dSArchie Cobbs *s2++ = '\0'; 211cb3c7a5dSArchie Cobbs if ((family = ng_ksocket_parse(ng_ksocket_families, s1, 0)) == -1) 212cb3c7a5dSArchie Cobbs return (EINVAL); 213cb3c7a5dSArchie Cobbs s1 = s2; 214cb3c7a5dSArchie Cobbs if ((s2 = index(s1, '/')) == NULL) 215cb3c7a5dSArchie Cobbs return (EINVAL); 216cb3c7a5dSArchie Cobbs *s2++ = '\0'; 217cb3c7a5dSArchie Cobbs if ((type = ng_ksocket_parse(ng_ksocket_types, s1, 0)) == -1) 218cb3c7a5dSArchie Cobbs return (EINVAL); 219cb3c7a5dSArchie Cobbs s1 = s2; 220cb3c7a5dSArchie Cobbs if ((protocol = ng_ksocket_parse(ng_ksocket_protos, s1, family)) == -1) 221cb3c7a5dSArchie Cobbs return (EINVAL); 222cb3c7a5dSArchie Cobbs 223cb3c7a5dSArchie Cobbs /* Create the socket */ 224cb3c7a5dSArchie Cobbs if ((error = socreate(family, &priv->so, type, protocol, p)) != 0) 225cb3c7a5dSArchie Cobbs return (error); 226cb3c7a5dSArchie Cobbs 227cb3c7a5dSArchie Cobbs /* XXX call soreserve() ? */ 228cb3c7a5dSArchie Cobbs 229cb3c7a5dSArchie Cobbs /* Add our hook for incoming data */ 230cb3c7a5dSArchie Cobbs priv->so->so_upcallarg = (caddr_t)node; 231cb3c7a5dSArchie Cobbs priv->so->so_upcall = ng_ksocket_incoming; 232cb3c7a5dSArchie Cobbs priv->so->so_rcv.sb_flags |= SB_UPCALL; 233cb3c7a5dSArchie Cobbs 234cb3c7a5dSArchie Cobbs /* OK */ 235cb3c7a5dSArchie Cobbs priv->hook = hook; 236cb3c7a5dSArchie Cobbs return (0); 237cb3c7a5dSArchie Cobbs } 238cb3c7a5dSArchie Cobbs 239cb3c7a5dSArchie Cobbs /* 240cb3c7a5dSArchie Cobbs * Receive a control message 241cb3c7a5dSArchie Cobbs */ 242cb3c7a5dSArchie Cobbs static int 243cb3c7a5dSArchie Cobbs ng_ksocket_rcvmsg(node_p node, struct ng_mesg *msg, 244cb3c7a5dSArchie Cobbs const char *raddr, struct ng_mesg **rptr) 245cb3c7a5dSArchie Cobbs { 246cb3c7a5dSArchie Cobbs const priv_p priv = node->private; 247cb3c7a5dSArchie Cobbs struct ng_mesg *resp = NULL; 248cb3c7a5dSArchie Cobbs struct proc *p = &proc0; 249cb3c7a5dSArchie Cobbs int error = 0; 250cb3c7a5dSArchie Cobbs 251cb3c7a5dSArchie Cobbs switch (msg->header.typecookie) { 252cb3c7a5dSArchie Cobbs case NGM_KSOCKET_COOKIE: 253cb3c7a5dSArchie Cobbs switch (msg->header.cmd) { 254cb3c7a5dSArchie Cobbs case NGM_KSOCKET_BIND: 255cb3c7a5dSArchie Cobbs { 256cb3c7a5dSArchie Cobbs struct sockaddr *sa = (struct sockaddr *)msg->data; 257cb3c7a5dSArchie Cobbs struct socket *const so = priv->so; 258cb3c7a5dSArchie Cobbs 259cb3c7a5dSArchie Cobbs /* Must have a connected hook first */ 260cb3c7a5dSArchie Cobbs if (priv->hook == NULL) 261cb3c7a5dSArchie Cobbs ERROUT(ENETDOWN); 262cb3c7a5dSArchie Cobbs 263cb3c7a5dSArchie Cobbs /* Set and sanity check sockaddr length */ 264cb3c7a5dSArchie Cobbs if (msg->header.arglen > SOCK_MAXADDRLEN) 265cb3c7a5dSArchie Cobbs ERROUT(ENAMETOOLONG); 266cb3c7a5dSArchie Cobbs sa->sa_len = msg->header.arglen; 267cb3c7a5dSArchie Cobbs error = sobind(so, sa, p); 268cb3c7a5dSArchie Cobbs break; 269cb3c7a5dSArchie Cobbs } 270cb3c7a5dSArchie Cobbs case NGM_KSOCKET_LISTEN: 271cb3c7a5dSArchie Cobbs { 272cb3c7a5dSArchie Cobbs struct socket *const so = priv->so; 273cb3c7a5dSArchie Cobbs int backlog; 274cb3c7a5dSArchie Cobbs 275cb3c7a5dSArchie Cobbs /* Must have a connected hook first */ 276cb3c7a5dSArchie Cobbs if (priv->hook == NULL) 277cb3c7a5dSArchie Cobbs ERROUT(ENETDOWN); 278cb3c7a5dSArchie Cobbs 279cb3c7a5dSArchie Cobbs /* Get backlog argument */ 280cb3c7a5dSArchie Cobbs if (msg->header.arglen != sizeof(int)) 281cb3c7a5dSArchie Cobbs ERROUT(EINVAL); 282cb3c7a5dSArchie Cobbs backlog = *((int *)msg->data); 283cb3c7a5dSArchie Cobbs 284cb3c7a5dSArchie Cobbs /* Do listen */ 285cb3c7a5dSArchie Cobbs if ((error = solisten(so, backlog, p)) != 0) 286cb3c7a5dSArchie Cobbs break; 287cb3c7a5dSArchie Cobbs 288cb3c7a5dSArchie Cobbs /* Notify sender when we get a connection attempt */ 289cb3c7a5dSArchie Cobbs /* XXX implement me */ 290cb3c7a5dSArchie Cobbs break; 291cb3c7a5dSArchie Cobbs } 292cb3c7a5dSArchie Cobbs 293cb3c7a5dSArchie Cobbs case NGM_KSOCKET_ACCEPT: 294cb3c7a5dSArchie Cobbs { 295cb3c7a5dSArchie Cobbs ERROUT(ENODEV); /* XXX implement me */ 296cb3c7a5dSArchie Cobbs break; 297cb3c7a5dSArchie Cobbs } 298cb3c7a5dSArchie Cobbs 299cb3c7a5dSArchie Cobbs case NGM_KSOCKET_CONNECT: 300cb3c7a5dSArchie Cobbs { 301cb3c7a5dSArchie Cobbs struct socket *const so = priv->so; 302cb3c7a5dSArchie Cobbs struct sockaddr *sa = (struct sockaddr *)msg->data; 303cb3c7a5dSArchie Cobbs 304cb3c7a5dSArchie Cobbs /* Must have a connected hook first */ 305cb3c7a5dSArchie Cobbs if (priv->hook == NULL) 306cb3c7a5dSArchie Cobbs ERROUT(ENETDOWN); 307cb3c7a5dSArchie Cobbs 308cb3c7a5dSArchie Cobbs /* Set and sanity check sockaddr length */ 309cb3c7a5dSArchie Cobbs if (msg->header.arglen > SOCK_MAXADDRLEN) 310cb3c7a5dSArchie Cobbs ERROUT(ENAMETOOLONG); 311cb3c7a5dSArchie Cobbs sa->sa_len = msg->header.arglen; 312cb3c7a5dSArchie Cobbs 313cb3c7a5dSArchie Cobbs /* Do connect */ 314cb3c7a5dSArchie Cobbs if ((so->so_state & SS_ISCONNECTING) != 0) 315cb3c7a5dSArchie Cobbs ERROUT(EALREADY); 316cb3c7a5dSArchie Cobbs if ((error = soconnect(so, sa, p)) != 0) { 317cb3c7a5dSArchie Cobbs so->so_state &= ~SS_ISCONNECTING; 318cb3c7a5dSArchie Cobbs ERROUT(error); 319cb3c7a5dSArchie Cobbs } 320cb3c7a5dSArchie Cobbs if ((so->so_state & SS_ISCONNECTING) != 0) 321cb3c7a5dSArchie Cobbs /* Notify sender when we connect */ 322cb3c7a5dSArchie Cobbs /* XXX implement me */ 323cb3c7a5dSArchie Cobbs ERROUT(EINPROGRESS); 324cb3c7a5dSArchie Cobbs break; 325cb3c7a5dSArchie Cobbs } 326cb3c7a5dSArchie Cobbs 327cb3c7a5dSArchie Cobbs case NGM_KSOCKET_GETNAME: 328cb3c7a5dSArchie Cobbs { 329cb3c7a5dSArchie Cobbs ERROUT(ENODEV); /* XXX implement me */ 330cb3c7a5dSArchie Cobbs break; 331cb3c7a5dSArchie Cobbs } 332cb3c7a5dSArchie Cobbs 333cb3c7a5dSArchie Cobbs case NGM_KSOCKET_GETPEERNAME: 334cb3c7a5dSArchie Cobbs { 335cb3c7a5dSArchie Cobbs ERROUT(ENODEV); /* XXX implement me */ 336cb3c7a5dSArchie Cobbs break; 337cb3c7a5dSArchie Cobbs } 338cb3c7a5dSArchie Cobbs 339cb3c7a5dSArchie Cobbs case NGM_KSOCKET_GETOPT: 340cb3c7a5dSArchie Cobbs { 341cb3c7a5dSArchie Cobbs ERROUT(ENODEV); /* XXX implement me */ 342cb3c7a5dSArchie Cobbs break; 343cb3c7a5dSArchie Cobbs } 344cb3c7a5dSArchie Cobbs 345cb3c7a5dSArchie Cobbs case NGM_KSOCKET_SETOPT: 346cb3c7a5dSArchie Cobbs { 347cb3c7a5dSArchie Cobbs ERROUT(ENODEV); /* XXX implement me */ 348cb3c7a5dSArchie Cobbs break; 349cb3c7a5dSArchie Cobbs } 350cb3c7a5dSArchie Cobbs 351cb3c7a5dSArchie Cobbs default: 352cb3c7a5dSArchie Cobbs error = EINVAL; 353cb3c7a5dSArchie Cobbs break; 354cb3c7a5dSArchie Cobbs } 355cb3c7a5dSArchie Cobbs break; 356cb3c7a5dSArchie Cobbs default: 357cb3c7a5dSArchie Cobbs error = EINVAL; 358cb3c7a5dSArchie Cobbs break; 359cb3c7a5dSArchie Cobbs } 360cb3c7a5dSArchie Cobbs if (rptr) 361cb3c7a5dSArchie Cobbs *rptr = resp; 362cb3c7a5dSArchie Cobbs else if (resp) 363cb3c7a5dSArchie Cobbs FREE(resp, M_NETGRAPH); 364cb3c7a5dSArchie Cobbs 365cb3c7a5dSArchie Cobbs done: 366cb3c7a5dSArchie Cobbs FREE(msg, M_NETGRAPH); 367cb3c7a5dSArchie Cobbs return (error); 368cb3c7a5dSArchie Cobbs } 369cb3c7a5dSArchie Cobbs 370cb3c7a5dSArchie Cobbs /* 371cb3c7a5dSArchie Cobbs * Receive incoming data on our hook. Send it out the socket. 372cb3c7a5dSArchie Cobbs */ 373cb3c7a5dSArchie Cobbs static int 374cb3c7a5dSArchie Cobbs ng_ksocket_rcvdata(hook_p hook, struct mbuf *m, meta_p meta) 375cb3c7a5dSArchie Cobbs { 376cb3c7a5dSArchie Cobbs const node_p node = hook->node; 377cb3c7a5dSArchie Cobbs const priv_p priv = node->private; 378cb3c7a5dSArchie Cobbs struct socket *const so = priv->so; 379cb3c7a5dSArchie Cobbs struct proc *p = &proc0; 380cb3c7a5dSArchie Cobbs int error; 381cb3c7a5dSArchie Cobbs 382cb3c7a5dSArchie Cobbs NG_FREE_META(meta); 383cb3c7a5dSArchie Cobbs error = (*so->so_proto->pr_usrreqs->pru_sosend)(so, 0, 0, m, 0, 0, p); 384cb3c7a5dSArchie Cobbs return (error); 385cb3c7a5dSArchie Cobbs } 386cb3c7a5dSArchie Cobbs 387cb3c7a5dSArchie Cobbs /* 388cb3c7a5dSArchie Cobbs * Destroy node 389cb3c7a5dSArchie Cobbs */ 390cb3c7a5dSArchie Cobbs static int 391cb3c7a5dSArchie Cobbs ng_ksocket_rmnode(node_p node) 392cb3c7a5dSArchie Cobbs { 393cb3c7a5dSArchie Cobbs const priv_p priv = node->private; 394cb3c7a5dSArchie Cobbs 39519bff684SArchie Cobbs /* Close our socket (if any) */ 39619bff684SArchie Cobbs if (priv->so != NULL) { 39719bff684SArchie Cobbs soclose(priv->so); 39819bff684SArchie Cobbs priv->so = NULL; 39919bff684SArchie Cobbs } 40019bff684SArchie Cobbs 401cb3c7a5dSArchie Cobbs /* Take down netgraph node */ 402cb3c7a5dSArchie Cobbs node->flags |= NG_INVALID; 403cb3c7a5dSArchie Cobbs ng_cutlinks(node); 404cb3c7a5dSArchie Cobbs ng_unname(node); 405cb3c7a5dSArchie Cobbs bzero(priv, sizeof(*priv)); 406cb3c7a5dSArchie Cobbs FREE(priv, M_NETGRAPH); 407cb3c7a5dSArchie Cobbs node->private = NULL; 408cb3c7a5dSArchie Cobbs ng_unref(node); /* let the node escape */ 409cb3c7a5dSArchie Cobbs return (0); 410cb3c7a5dSArchie Cobbs } 411cb3c7a5dSArchie Cobbs 412cb3c7a5dSArchie Cobbs /* 413cb3c7a5dSArchie Cobbs * Hook disconnection 414cb3c7a5dSArchie Cobbs */ 415cb3c7a5dSArchie Cobbs static int 416cb3c7a5dSArchie Cobbs ng_ksocket_disconnect(hook_p hook) 417cb3c7a5dSArchie Cobbs { 41819bff684SArchie Cobbs KASSERT(hook->node->numhooks == 0, 41919bff684SArchie Cobbs ("%s: numhooks=%d?", __FUNCTION__, hook->node->numhooks)); 420cb3c7a5dSArchie Cobbs ng_rmnode(hook->node); 421cb3c7a5dSArchie Cobbs return (0); 422cb3c7a5dSArchie Cobbs } 423cb3c7a5dSArchie Cobbs 424cb3c7a5dSArchie Cobbs /************************************************************************ 425cb3c7a5dSArchie Cobbs HELPER STUFF 426cb3c7a5dSArchie Cobbs ************************************************************************/ 427cb3c7a5dSArchie Cobbs 428cb3c7a5dSArchie Cobbs /* 429cb3c7a5dSArchie Cobbs * When incoming data is appended to the socket, we get notified here. 430cb3c7a5dSArchie Cobbs */ 431cb3c7a5dSArchie Cobbs static void 432cb3c7a5dSArchie Cobbs ng_ksocket_incoming(struct socket *so, void *arg, int waitflag) 433cb3c7a5dSArchie Cobbs { 434cb3c7a5dSArchie Cobbs const node_p node = arg; 435cb3c7a5dSArchie Cobbs const priv_p priv = node->private; 436cb3c7a5dSArchie Cobbs meta_p meta = NULL; 437cb3c7a5dSArchie Cobbs struct sockaddr *nam; 438cb3c7a5dSArchie Cobbs struct mbuf *m; 439cb3c7a5dSArchie Cobbs struct uio auio; 44019bff684SArchie Cobbs int s, flags, error; 44119bff684SArchie Cobbs 44219bff684SArchie Cobbs s = splnet(); 443cb3c7a5dSArchie Cobbs 444cb3c7a5dSArchie Cobbs /* Sanity check */ 44519bff684SArchie Cobbs if ((node->flags & NG_INVALID) != 0) { 44619bff684SArchie Cobbs splx(s); 447cb3c7a5dSArchie Cobbs return; 44819bff684SArchie Cobbs } 449cb3c7a5dSArchie Cobbs KASSERT(so == priv->so, ("%s: wrong socket", __FUNCTION__)); 450cb3c7a5dSArchie Cobbs KASSERT(priv->hook != NULL, ("%s: no hook", __FUNCTION__)); 451cb3c7a5dSArchie Cobbs 452cb3c7a5dSArchie Cobbs /* Read and forward available mbuf's */ 453cb3c7a5dSArchie Cobbs auio.uio_procp = NULL; 454cb3c7a5dSArchie Cobbs auio.uio_resid = 1000000000; 455cb3c7a5dSArchie Cobbs flags = MSG_DONTWAIT; 456cb3c7a5dSArchie Cobbs do { 457cb3c7a5dSArchie Cobbs if ((error = (*so->so_proto->pr_usrreqs->pru_soreceive) 458cb3c7a5dSArchie Cobbs (so, &nam, &auio, &m, (struct mbuf **)0, &flags)) == 0) 459cb3c7a5dSArchie Cobbs NG_SEND_DATA(error, priv->hook, m, meta); 460cb3c7a5dSArchie Cobbs } while (error == 0 && m != NULL); 46119bff684SArchie Cobbs splx(s); 462cb3c7a5dSArchie Cobbs } 463cb3c7a5dSArchie Cobbs 464cb3c7a5dSArchie Cobbs /* 465cb3c7a5dSArchie Cobbs * Parse out either an integer value or an alias. 466cb3c7a5dSArchie Cobbs */ 467cb3c7a5dSArchie Cobbs static int 468cb3c7a5dSArchie Cobbs ng_ksocket_parse(const struct ng_ksocket_alias *aliases, 469cb3c7a5dSArchie Cobbs const char *s, int family) 470cb3c7a5dSArchie Cobbs { 471cb3c7a5dSArchie Cobbs int k, val; 472cb3c7a5dSArchie Cobbs const char *eptr; 473cb3c7a5dSArchie Cobbs 474cb3c7a5dSArchie Cobbs /* Try aliases */ 475cb3c7a5dSArchie Cobbs for (k = 0; aliases[k].name != NULL; k++) { 476cb3c7a5dSArchie Cobbs if (strcmp(s, aliases[k].name) == 0 477cb3c7a5dSArchie Cobbs && aliases[k].family == family) 478cb3c7a5dSArchie Cobbs return aliases[k].value; 479cb3c7a5dSArchie Cobbs } 480cb3c7a5dSArchie Cobbs 481cb3c7a5dSArchie Cobbs /* Try parsing as a number */ 482cb3c7a5dSArchie Cobbs val = (int)strtoul(s, &eptr, 10); 483cb3c7a5dSArchie Cobbs if (val <= 0 || *eptr != '\0') 484cb3c7a5dSArchie Cobbs return (-1); 485cb3c7a5dSArchie Cobbs return (val); 486cb3c7a5dSArchie Cobbs } 487cb3c7a5dSArchie Cobbs 488