diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c --- a/sys/netgraph/ng_base.c +++ b/sys/netgraph/ng_base.c @@ -234,7 +234,7 @@ static int ng_con_part2(node_p node, item_p item, hook_p hook); static int ng_con_part3(node_p node, item_p item, hook_p hook); static int ng_mkpeer(node_p node, const char *name, const char *name2, - char *type); + char *type, ng_ID_t *); static void ng_name_rehash(void); static void ng_ID_rehash(void); @@ -497,6 +497,13 @@ &ng_generic_mkpeer_type, NULL }, + { + NGM_GENERIC_COOKIE, + NGM_MKPEERID, + "mkpeerid", + &ng_generic_mkpeer_type, + &ng_parse_hint32_type + }, { NGM_GENERIC_COOKIE, NGM_CONNECT, @@ -1542,7 +1549,8 @@ * an unconnected node? */ static int -ng_mkpeer(node_p node, const char *name, const char *name2, char *type) +ng_mkpeer(node_p node, const char *name, const char *name2, char *type, + ng_ID_t *nid) { node_p node2; hook_p hook1, hook2; @@ -1596,6 +1604,8 @@ } NG_HOOK_UNREF(hook1); NG_HOOK_UNREF(hook2); + if (error == 0 && nid != NULL) + *nid = NG_NODE_ID(node2); return (error); } @@ -2525,6 +2535,13 @@ case NGM_SHUTDOWN: ng_rmnode(here, NULL, NULL, 0); break; + case NGM_MKPEERID: + /* set up resp then fallthough if ok */ + NG_MKRESPONSE(resp, msg, sizeof(ng_ID_t), M_NOWAIT); + if (resp == NULL) { + error = ENOMEM; + break; + } case NGM_MKPEER: { struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) msg->data; @@ -2537,7 +2554,8 @@ mkp->type[sizeof(mkp->type) - 1] = '\0'; mkp->ourhook[sizeof(mkp->ourhook) - 1] = '\0'; mkp->peerhook[sizeof(mkp->peerhook) - 1] = '\0'; - error = ng_mkpeer(here, mkp->ourhook, mkp->peerhook, mkp->type); + error = ng_mkpeer(here, mkp->ourhook, mkp->peerhook, mkp->type, + resp == NULL ? NULL : (ng_ID_t *)resp->data); break; } case NGM_CONNECT: diff --git a/sys/netgraph/ng_message.h b/sys/netgraph/ng_message.h --- a/sys/netgraph/ng_message.h +++ b/sys/netgraph/ng_message.h @@ -139,6 +139,8 @@ NGM_ASCII2BINARY= (13|NGM_READONLY|NGM_HASREPLY), /* (optional) Get/set text config. */ NGM_TEXT_CONFIG = 14, + /* Create and attach a peer node also return the ID of created node */ + NGM_MKPEERID = (15|NGM_HASREPLY), }; /* diff --git a/sys/netgraph/ng_socket.c b/sys/netgraph/ng_socket.c --- a/sys/netgraph/ng_socket.c +++ b/sys/netgraph/ng_socket.c @@ -279,7 +279,7 @@ * message gets queued and applied later we will get panic. */ if (msg->header.typecookie == NGM_GENERIC_COOKIE && - msg->header.cmd == NGM_MKPEER) { + (msg->header.cmd == NGM_MKPEER || msg->header.cmd == NGM_MKPEERID)) { struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) msg->data; if (ng_findtype(mkp->type) == NULL) { diff --git a/usr.sbin/ngctl/mkpeer.c b/usr.sbin/ngctl/mkpeer.c --- a/usr.sbin/ngctl/mkpeer.c +++ b/usr.sbin/ngctl/mkpeer.c @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include "ngctl.h" @@ -45,12 +47,14 @@ const struct ngcmd mkpeer_cmd = { MkPeerCmd, - "mkpeer [path] ", + "mkpeer [-i] [path] ", "Create and connect a new node to the node at \"path\"", "The mkpeer command atomically creates a new node of type \"type\"" " and connects it to the node at \"path\". The hooks used for the" " connection are \"hook\" on the original node and \"peerhook\"" " on the new node." + " If the -i flag is given, return the node ID as a string that can" + " be used to reference the node." " If \"path\" is omitted then \".\" is assumed.", { NULL } }; @@ -60,18 +64,36 @@ { struct ngm_mkpeer mkp; const char *path = "."; + struct ng_mesg *resp = NULL; + int ch, cmd = NGM_MKPEER; + + /* Get options */ + optind = 1; + while ((ch = getopt(ac, av, "i")) != -1) { + switch (ch) { + case 'i': + cmd = NGM_MKPEERID; + break; + case '?': + default: + return (CMDRTN_USAGE); + break; + } + } + ac -= optind; + av += optind; /* Get arguments */ switch (ac) { - case 5: - path = av[1]; + case 4: + path = av[0]; ac--; av++; /* FALLTHROUGH */ - case 4: - snprintf(mkp.type, sizeof(mkp.type), "%s", av[1]); - snprintf(mkp.ourhook, sizeof(mkp.ourhook), "%s", av[2]); - snprintf(mkp.peerhook, sizeof(mkp.peerhook), "%s", av[3]); + case 3: + snprintf(mkp.type, sizeof(mkp.type), "%s", av[0]); + snprintf(mkp.ourhook, sizeof(mkp.ourhook), "%s", av[1]); + snprintf(mkp.peerhook, sizeof(mkp.peerhook), "%s", av[2]); break; default: return (CMDRTN_USAGE); @@ -79,10 +101,20 @@ /* Send message */ if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, - NGM_MKPEER, &mkp, sizeof(mkp)) < 0) { + cmd, &mkp, sizeof(mkp)) < 0) { warn("send msg"); return (CMDRTN_ERROR); } + if (cmd == NGM_MKPEERID) { + if (NgAllocRecvMsg(csock, &resp, NULL) < 0) { + warn("recv msg"); + return (CMDRTN_ERROR); + } + /* want this to be easy to capture in shell script */ + printf("[%08x]\n", *((ng_ID_t *)resp->data)); + free(resp); + } + return (CMDRTN_OK); }