int CreateNgKsocket() { char path[NG_PATHSIZ]; struct ngm_mkpeer arg; sprintf(arg.type, "ksocket"); sprintf(arg.peerhook, "inet/stream/tcp"); sprintf(arg.ourhook, "delusion"); memset(path, 0, sizeof(path)); sprintf(path, ".:"); if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, NGM_MKPEER, &arg, sizeof(arg)) < 0 ) { printf("%s(): Error sending message: %s", __func__, strerror(errno)); return -1; } sprintf(path, ".:%s", arg.ourhook); memset( ksock_name, 0, sizeof(ksock_name) ); sprintf(ksock_name, "http-ksocket-%d", getpid()); if ( NgNameNode(csock, path, ksock_name, getpid()) < 0 ) { printf("%s: error naming node : %s", __func__, strerror(errno)); return -1; } /* make kscoket bind and listen state */ struct sockaddr_in source; source.sin_family = AF_INET; inet_aton(SRC_IP, &source.sin_addr); source.sin_port = htons(atoi(SRC_PORT)); source.sin_len = sizeof(struct sockaddr_in); sprintf(path, "%s:", ksock_name); NgSetDebug(3); if ( NgSendMsg(csock, path, NGM_KSOCKET_COOKIE, NGM_KSOCKET_BIND, &source, sizeof(source)) < 0 ) { printf("%s(): Error sending ksocket bind: %s\n", __func__, strerror(errno)); return -1; } /* Listening ksocket */ int lst = 1024; if ( NgSendMsg(csock, path, NGM_KSOCKET_COOKIE, NGM_KSOCKET_LISTEN, &lst, sizeof(lst)) < 0 ) { printf("%s(): Error sending ksocket bind: %s\n", __func__, strerror(errno)); return -1; } int token; token = NgSendMsg(csock, path, NGM_KSOCKET_COOKIE, NGM_KSOCKET_ACCEPT, NULL, 0); if ( token < 0 && errno != EINPROGRESS && errno != EALREADY ) { printf("%s(): Accept Failed %s\n", __func__, strerror(errno)); return -1; } SetKsocketKeepAlive(ksock_name); return token; }
struct device * ng_Create(struct physical *p) { struct sockaddr_ng ngsock; u_char rbuf[2048]; struct sockaddr *sock = (struct sockaddr *)&ngsock; const struct hooklist *hlist; const struct nodeinfo *ninfo; const struct linkinfo *nlink; struct ngdevice *dev; struct ng_mesg *resp; struct ngm_mkpeer mkp; struct ngm_connect ngc; const char *devp, *endp; char lasthook[NG_HOOKSIZ]; char hook[NG_HOOKSIZ]; char nodetype[NG_TYPESIZ + NG_NODESIZ]; char modname[NG_TYPESIZ + 3]; char path[NG_PATHSIZ]; char *nodename; int len, sz, done; unsigned f; dev = NULL; if (p->fd < 0 && !strncasecmp(p->name.full, NETGRAPH_PREFIX, sizeof NETGRAPH_PREFIX - 1)) { p->fd--; /* We own the device - change fd */ if ((dev = malloc(sizeof *dev)) == NULL) return NULL; loadmodules(LOAD_VERBOSLY, "netgraph", "ng_socket", NULL); /* Create a socket node */ if (ID0NgMkSockNode(NULL, &dev->cs, &p->fd) == -1) { log_Printf(LogWARN, "Cannot create netgraph socket node: %s\n", strerror(errno)); free(dev); p->fd = -2; return NULL; } devp = p->name.full + sizeof NETGRAPH_PREFIX - 1; *lasthook = *path = '\0'; log_Printf(LogDEBUG, "%s: Opening netgraph device \"%s\"\n", p->link.name, devp); done = 0; while (*devp != '\0' && !done) { if (*devp != '[') { if (*lasthook == '\0') { log_Printf(LogWARN, "%s: Netgraph devices must start with" " [nodetype:nodename]\n", p->link.name); return ng_Abandon(dev, p); } /* Get the hook name of the new node */ if (!GETSEGMENT(hook, devp, ".[", &endp)) return ng_Abandon(dev, p); log_Printf(LogDEBUG, "%s: Got hook \"%s\"\n", p->link.name, hook); devp = endp; if (*devp == '\0') { log_Printf(LogWARN, "%s: Netgraph device must not end with a second" " hook\n", p->link.name); return ng_Abandon(dev, p); } if (devp[-1] != '[') { log_Printf(LogWARN, "%s: Expected a [nodetype:nodename] at device" " pos %d\n", p->link.name, devp - p->link.name - 1); return ng_Abandon(dev, p); } } else { /* Use lasthook as the hook name */ strcpy(hook, lasthook); devp++; } /* We've got ``lasthook'' and ``hook'', get the node type */ if (!GETSEGMENT(nodetype, devp, "]", &endp)) return ng_Abandon(dev, p); log_Printf(LogDEBUG, "%s: Got node \"%s\"\n", p->link.name, nodetype); if ((nodename = strchr(nodetype, ':')) != NULL) { *nodename++ = '\0'; if (*nodename == '\0' && *nodetype == '\0') { log_Printf(LogWARN, "%s: Empty [nodetype:nodename] at device" " pos %d\n", p->link.name, devp - p->link.name - 1); return ng_Abandon(dev, p); } } /* Ignore optional colons after nodes */ devp = *endp == ':' ? endp + 1 : endp; if (*devp == '.') devp++; if (*lasthook == '\0') { /* This is the first node in the chain */ if (nodename == NULL || *nodename == '\0') { log_Printf(LogWARN, "%s: %s: No initial device nodename\n", p->link.name, devp); return ng_Abandon(dev, p); } if (*nodetype != '\0') { /* Attempt to load the module */ snprintf(modname, sizeof modname, "ng_%s", nodetype); log_Printf(LogDEBUG, "%s: Attempting to load %s.ko\n", p->link.name, modname); loadmodules(LOAD_QUIETLY, modname, NULL); } snprintf(path, sizeof path, "%s:", nodename); /* XXX: If we have a node type, ensure it's correct */ } else { /* * Ask for a list of hooks attached to the previous node. If we * find the one we're interested in, and if it's connected to a * node of the right type using the correct hook, use that. * If we find the hook connected to something else, fail. * If we find no match, mkpeer the new node. */ if (*nodetype == '\0') { log_Printf(LogWARN, "%s: Nodetype missing at device offset %d\n", p->link.name, devp - p->name.full + sizeof NETGRAPH_PREFIX - 1); return ng_Abandon(dev, p); } /* Get a list of node hooks */ if (NgSendMsg(dev->cs, path, NGM_GENERIC_COOKIE, NGM_LISTHOOKS, NULL, 0) < 0) { log_Printf(LogWARN, "%s: %s Cannot send a LISTHOOOKS message: %s\n", p->link.name, path, strerror(errno)); return ng_Abandon(dev, p); } /* Get our list back */ resp = (struct ng_mesg *)rbuf; if (NgRecvMsg(dev->cs, resp, sizeof rbuf, NULL) <= 0) { log_Printf(LogWARN, "%s: Cannot get netgraph response: %s\n", p->link.name, strerror(errno)); return ng_Abandon(dev, p); } hlist = (const struct hooklist *)resp->data; ninfo = &hlist->nodeinfo; log_Printf(LogDEBUG, "List of netgraph node ``%s'' (id %x) hooks:\n", path, ninfo->id); /* look for a hook already attached. */ for (f = 0; f < ninfo->hooks; f++) { nlink = &hlist->link[f]; log_Printf(LogDEBUG, " Found %s -> %s (type %s)\n", nlink->ourhook, nlink->peerhook, nlink->nodeinfo.type); if (!strcmp(nlink->ourhook, lasthook)) { if (strcmp(nlink->peerhook, hook) || strcmp(nlink->nodeinfo.type, nodetype)) { log_Printf(LogWARN, "%s: hook %s:%s is already in use\n", p->link.name, nlink->ourhook, path); return ng_Abandon(dev, p); } /* The node is already hooked up nicely.... reuse it */ break; } } if (f == ninfo->hooks) { /* Attempt to load the module */ snprintf(modname, sizeof modname, "ng_%s", nodetype); log_Printf(LogDEBUG, "%s: Attempting to load %s.ko\n", p->link.name, modname); loadmodules(LOAD_QUIETLY, modname, NULL); /* Create (mkpeer) the new node */ snprintf(mkp.type, sizeof mkp.type, "%s", nodetype); snprintf(mkp.ourhook, sizeof mkp.ourhook, "%s", lasthook); snprintf(mkp.peerhook, sizeof mkp.peerhook, "%s", hook); log_Printf(LogDEBUG, "%s: Doing MKPEER %s%s -> %s (type %s)\n", p->link.name, path, mkp.ourhook, mkp.peerhook, nodetype); if (NgSendMsg(dev->cs, path, NGM_GENERIC_COOKIE, NGM_MKPEER, &mkp, sizeof mkp) < 0) { log_Printf(LogWARN, "%s Cannot create %s netgraph node: %s\n", path, nodetype, strerror(errno)); return ng_Abandon(dev, p); } } len = strlen(path); snprintf(path + len, sizeof path - len, "%s%s", path[len - 1] == ':' ? "" : ".", lasthook); } /* Get a list of node hooks */ if (NgSendMsg(dev->cs, path, NGM_GENERIC_COOKIE, NGM_LISTHOOKS, NULL, 0) < 0) { log_Printf(LogWARN, "%s: %s Cannot send a LISTHOOOKS message: %s\n", p->link.name, path, strerror(errno)); return ng_Abandon(dev, p); } /* Get our list back */ resp = (struct ng_mesg *)rbuf; if (NgRecvMsg(dev->cs, resp, sizeof rbuf, NULL) <= 0) { log_Printf(LogWARN, "%s: Cannot get netgraph response: %s\n", p->link.name, strerror(errno)); return ng_Abandon(dev, p); } hlist = (const struct hooklist *)resp->data; ninfo = &hlist->nodeinfo; if (*lasthook != '\0' && nodename != NULL && *nodename != '\0' && strcmp(ninfo->name, nodename) && NgNameNode(dev->cs, path, "%s", nodename) < 0) { log_Printf(LogWARN, "%s: %s: Cannot name netgraph node: %s\n", p->link.name, path, strerror(errno)); return ng_Abandon(dev, p); } if (!GETSEGMENT(lasthook, devp, " \t.[", &endp)) return ng_Abandon(dev, p); log_Printf(LogDEBUG, "%s: Got hook \"%s\"\n", p->link.name, lasthook); len = strlen(lasthook); done = strchr(" \t", devp[len]) ? 1 : 0; devp = endp; if (*devp != '\0') { if (devp[-1] == '[') devp--; } /* else should moan about devp[-1] being '[' ? */ } snprintf(dev->hook, sizeof dev->hook, "%s", lasthook); /* Connect the node to our socket node */ snprintf(ngc.path, sizeof ngc.path, "%s", path); snprintf(ngc.ourhook, sizeof ngc.ourhook, "%s", dev->hook); memcpy(ngc.peerhook, ngc.ourhook, sizeof ngc.peerhook); log_Printf(LogDEBUG, "Connecting netgraph socket .:%s -> %s.%s\n", ngc.ourhook, ngc.path, ngc.peerhook); if (NgSendMsg(dev->cs, ".:", NGM_GENERIC_COOKIE, NGM_CONNECT, &ngc, sizeof ngc) < 0) { log_Printf(LogWARN, "Cannot connect %s and socket netgraph " "nodes: %s\n", path, strerror(errno)); return ng_Abandon(dev, p); } /* Hook things up so that we monitor dev->cs */ p->desc.UpdateSet = ng_UpdateSet; p->desc.IsSet = ng_IsSet; p->desc.Read = ng_DescriptorRead; memcpy(&dev->dev, &basengdevice, sizeof dev->dev); } else { /* See if we're a netgraph socket */ sz = sizeof ngsock; if (getsockname(p->fd, sock, &sz) != -1 && sock->sa_family == AF_NETGRAPH) { /* * It's a netgraph node... We can't determine hook names etc, so we * stay pretty impartial.... */ log_Printf(LogPHASE, "%s: Link is a netgraph node\n", p->link.name); if ((dev = malloc(sizeof *dev)) == NULL) { log_Printf(LogWARN, "%s: Cannot allocate an ether device: %s\n", p->link.name, strerror(errno)); return NULL; } memcpy(&dev->dev, &basengdevice, sizeof dev->dev); dev->cs = -1; *dev->hook = '\0'; } } if (dev) { physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNCNOACF); return &dev->dev; } return NULL; }