1*3b2bd0f6Slogwang /* 2*3b2bd0f6Slogwang * msg.c 3*3b2bd0f6Slogwang * 4*3b2bd0f6Slogwang * Copyright (c) 1996-1999 Whistle Communications, Inc. 5*3b2bd0f6Slogwang * All rights reserved. 6*3b2bd0f6Slogwang * 7*3b2bd0f6Slogwang * Subject to the following obligations and disclaimer of warranty, use and 8*3b2bd0f6Slogwang * redistribution of this software, in source or object code forms, with or 9*3b2bd0f6Slogwang * without modifications are expressly permitted by Whistle Communications; 10*3b2bd0f6Slogwang * provided, however, that: 11*3b2bd0f6Slogwang * 1. Any and all reproductions of the source or object code must include the 12*3b2bd0f6Slogwang * copyright notice above and the following disclaimer of warranties; and 13*3b2bd0f6Slogwang * 2. No rights are granted, in any manner or form, to use Whistle 14*3b2bd0f6Slogwang * Communications, Inc. trademarks, including the mark "WHISTLE 15*3b2bd0f6Slogwang * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 16*3b2bd0f6Slogwang * such appears in the above copyright notice or in the software. 17*3b2bd0f6Slogwang * 18*3b2bd0f6Slogwang * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 19*3b2bd0f6Slogwang * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 20*3b2bd0f6Slogwang * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 21*3b2bd0f6Slogwang * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 22*3b2bd0f6Slogwang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 23*3b2bd0f6Slogwang * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 24*3b2bd0f6Slogwang * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 25*3b2bd0f6Slogwang * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 26*3b2bd0f6Slogwang * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 27*3b2bd0f6Slogwang * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 28*3b2bd0f6Slogwang * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 29*3b2bd0f6Slogwang * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 30*3b2bd0f6Slogwang * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 31*3b2bd0f6Slogwang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32*3b2bd0f6Slogwang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33*3b2bd0f6Slogwang * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 34*3b2bd0f6Slogwang * OF SUCH DAMAGE. 35*3b2bd0f6Slogwang * 36*3b2bd0f6Slogwang * Author: Archie Cobbs <[email protected]> 37*3b2bd0f6Slogwang * 38*3b2bd0f6Slogwang * $Whistle: msg.c,v 1.9 1999/01/20 00:57:23 archie Exp $ 39*3b2bd0f6Slogwang */ 40*3b2bd0f6Slogwang 41*3b2bd0f6Slogwang #ifdef FSTACK 42*3b2bd0f6Slogwang #define _GNU_SOURCE 43*3b2bd0f6Slogwang #include <stdio.h> 44*3b2bd0f6Slogwang #endif 45*3b2bd0f6Slogwang 46*3b2bd0f6Slogwang #include <sys/cdefs.h> 47*3b2bd0f6Slogwang __FBSDID("$FreeBSD$"); 48*3b2bd0f6Slogwang 49*3b2bd0f6Slogwang #include <sys/types.h> 50*3b2bd0f6Slogwang #include <sys/socket.h> 51*3b2bd0f6Slogwang #include <stdarg.h> 52*3b2bd0f6Slogwang #include <netgraph/ng_message.h> 53*3b2bd0f6Slogwang #include <netgraph/ng_socket.h> 54*3b2bd0f6Slogwang 55*3b2bd0f6Slogwang #include "netgraph.h" 56*3b2bd0f6Slogwang #include "internal.h" 57*3b2bd0f6Slogwang 58*3b2bd0f6Slogwang /* Next message token value */ 59*3b2bd0f6Slogwang static int gMsgId; 60*3b2bd0f6Slogwang 61*3b2bd0f6Slogwang /* For delivering both messages and replies */ 62*3b2bd0f6Slogwang static int NgDeliverMsg(int cs, const char *path, 63*3b2bd0f6Slogwang const struct ng_mesg *hdr, const void *args, size_t arglen); 64*3b2bd0f6Slogwang 65*3b2bd0f6Slogwang /* 66*3b2bd0f6Slogwang * Send a message to a node using control socket node "cs". 67*3b2bd0f6Slogwang * Returns -1 if error and sets errno appropriately. 68*3b2bd0f6Slogwang * If successful, returns the message ID (token) used. 69*3b2bd0f6Slogwang */ 70*3b2bd0f6Slogwang int 71*3b2bd0f6Slogwang NgSendMsg(int cs, const char *path, 72*3b2bd0f6Slogwang int cookie, int cmd, const void *args, size_t arglen) 73*3b2bd0f6Slogwang { 74*3b2bd0f6Slogwang struct ng_mesg msg; 75*3b2bd0f6Slogwang 76*3b2bd0f6Slogwang /* Prepare message header */ 77*3b2bd0f6Slogwang memset(&msg, 0, sizeof(msg)); 78*3b2bd0f6Slogwang msg.header.version = NG_VERSION; 79*3b2bd0f6Slogwang msg.header.typecookie = cookie; 80*3b2bd0f6Slogwang if (++gMsgId < 0) 81*3b2bd0f6Slogwang gMsgId = 1; 82*3b2bd0f6Slogwang msg.header.token = gMsgId; 83*3b2bd0f6Slogwang msg.header.flags = NGF_ORIG; 84*3b2bd0f6Slogwang msg.header.cmd = cmd; 85*3b2bd0f6Slogwang snprintf((char *)msg.header.cmdstr, NG_CMDSTRSIZ, "cmd%d", cmd); 86*3b2bd0f6Slogwang 87*3b2bd0f6Slogwang /* Deliver message */ 88*3b2bd0f6Slogwang if (NgDeliverMsg(cs, path, &msg, args, arglen) < 0) 89*3b2bd0f6Slogwang return (-1); 90*3b2bd0f6Slogwang return (msg.header.token); 91*3b2bd0f6Slogwang } 92*3b2bd0f6Slogwang 93*3b2bd0f6Slogwang /* 94*3b2bd0f6Slogwang * Send a message given in ASCII format. We first ask the node to translate 95*3b2bd0f6Slogwang * the command into binary, and then we send the binary. 96*3b2bd0f6Slogwang */ 97*3b2bd0f6Slogwang int 98*3b2bd0f6Slogwang NgSendAsciiMsg(int cs, const char *path, const char *fmt, ...) 99*3b2bd0f6Slogwang { 100*3b2bd0f6Slogwang struct ng_mesg *reply, *binary, *ascii; 101*3b2bd0f6Slogwang char *buf, *cmd, *args; 102*3b2bd0f6Slogwang va_list fmtargs; 103*3b2bd0f6Slogwang int token; 104*3b2bd0f6Slogwang 105*3b2bd0f6Slogwang /* Parse out command and arguments */ 106*3b2bd0f6Slogwang va_start(fmtargs, fmt); 107*3b2bd0f6Slogwang vasprintf(&buf, fmt, fmtargs); 108*3b2bd0f6Slogwang va_end(fmtargs); 109*3b2bd0f6Slogwang if (buf == NULL) 110*3b2bd0f6Slogwang return (-1); 111*3b2bd0f6Slogwang 112*3b2bd0f6Slogwang /* Parse out command, arguments */ 113*3b2bd0f6Slogwang for (cmd = buf; isspace(*cmd); cmd++) 114*3b2bd0f6Slogwang ; 115*3b2bd0f6Slogwang for (args = cmd; *args != '\0' && !isspace(*args); args++) 116*3b2bd0f6Slogwang ; 117*3b2bd0f6Slogwang if (*args != '\0') { 118*3b2bd0f6Slogwang while (isspace(*args)) 119*3b2bd0f6Slogwang *args++ = '\0'; 120*3b2bd0f6Slogwang } 121*3b2bd0f6Slogwang 122*3b2bd0f6Slogwang /* Get a bigger buffer to hold inner message header plus arg string */ 123*3b2bd0f6Slogwang if ((ascii = malloc(sizeof(struct ng_mesg) 124*3b2bd0f6Slogwang + strlen(args) + 1)) == NULL) { 125*3b2bd0f6Slogwang free(buf); 126*3b2bd0f6Slogwang return (-1); 127*3b2bd0f6Slogwang } 128*3b2bd0f6Slogwang memset(ascii, 0, sizeof(*ascii)); 129*3b2bd0f6Slogwang 130*3b2bd0f6Slogwang /* Build inner header (only need cmdstr, arglen, and data fields) */ 131*3b2bd0f6Slogwang strncpy((char *)ascii->header.cmdstr, cmd, 132*3b2bd0f6Slogwang sizeof(ascii->header.cmdstr) - 1); 133*3b2bd0f6Slogwang strcpy(ascii->data, args); 134*3b2bd0f6Slogwang ascii->header.arglen = strlen(ascii->data) + 1; 135*3b2bd0f6Slogwang free(buf); 136*3b2bd0f6Slogwang 137*3b2bd0f6Slogwang /* Send node a request to convert ASCII to binary */ 138*3b2bd0f6Slogwang if (NgSendMsg(cs, path, NGM_GENERIC_COOKIE, NGM_ASCII2BINARY, 139*3b2bd0f6Slogwang (u_char *)ascii, sizeof(*ascii) + ascii->header.arglen) < 0) { 140*3b2bd0f6Slogwang free(ascii); 141*3b2bd0f6Slogwang return (-1); 142*3b2bd0f6Slogwang } 143*3b2bd0f6Slogwang free(ascii); 144*3b2bd0f6Slogwang 145*3b2bd0f6Slogwang /* Get reply */ 146*3b2bd0f6Slogwang if (NgAllocRecvMsg(cs, &reply, NULL) < 0) 147*3b2bd0f6Slogwang return (-1); 148*3b2bd0f6Slogwang 149*3b2bd0f6Slogwang /* Now send binary version */ 150*3b2bd0f6Slogwang binary = (struct ng_mesg *)reply->data; 151*3b2bd0f6Slogwang if (++gMsgId < 0) 152*3b2bd0f6Slogwang gMsgId = 1; 153*3b2bd0f6Slogwang binary->header.token = gMsgId; 154*3b2bd0f6Slogwang binary->header.version = NG_VERSION; 155*3b2bd0f6Slogwang if (NgDeliverMsg(cs, 156*3b2bd0f6Slogwang path, binary, binary->data, binary->header.arglen) < 0) { 157*3b2bd0f6Slogwang free(reply); 158*3b2bd0f6Slogwang return (-1); 159*3b2bd0f6Slogwang } 160*3b2bd0f6Slogwang token = binary->header.token; 161*3b2bd0f6Slogwang free(reply); 162*3b2bd0f6Slogwang return (token); 163*3b2bd0f6Slogwang } 164*3b2bd0f6Slogwang 165*3b2bd0f6Slogwang /* 166*3b2bd0f6Slogwang * Send a message that is a reply to a previously received message. 167*3b2bd0f6Slogwang * Returns -1 and sets errno on error, otherwise returns zero. 168*3b2bd0f6Slogwang */ 169*3b2bd0f6Slogwang int 170*3b2bd0f6Slogwang NgSendReplyMsg(int cs, const char *path, 171*3b2bd0f6Slogwang const struct ng_mesg *msg, const void *args, size_t arglen) 172*3b2bd0f6Slogwang { 173*3b2bd0f6Slogwang struct ng_mesg rep; 174*3b2bd0f6Slogwang 175*3b2bd0f6Slogwang /* Prepare message header */ 176*3b2bd0f6Slogwang rep = *msg; 177*3b2bd0f6Slogwang rep.header.flags = NGF_RESP; 178*3b2bd0f6Slogwang 179*3b2bd0f6Slogwang /* Deliver message */ 180*3b2bd0f6Slogwang return (NgDeliverMsg(cs, path, &rep, args, arglen)); 181*3b2bd0f6Slogwang } 182*3b2bd0f6Slogwang 183*3b2bd0f6Slogwang /* 184*3b2bd0f6Slogwang * Send a message to a node using control socket node "cs". 185*3b2bd0f6Slogwang * Returns -1 if error and sets errno appropriately, otherwise zero. 186*3b2bd0f6Slogwang */ 187*3b2bd0f6Slogwang static int 188*3b2bd0f6Slogwang NgDeliverMsg(int cs, const char *path, 189*3b2bd0f6Slogwang const struct ng_mesg *hdr, const void *args, size_t arglen) 190*3b2bd0f6Slogwang { 191*3b2bd0f6Slogwang u_char sgbuf[NG_PATHSIZ + NGSA_OVERHEAD]; 192*3b2bd0f6Slogwang struct sockaddr_ng *const sg = (struct sockaddr_ng *) sgbuf; 193*3b2bd0f6Slogwang u_char *buf = NULL; 194*3b2bd0f6Slogwang struct ng_mesg *msg; 195*3b2bd0f6Slogwang int errnosv = 0; 196*3b2bd0f6Slogwang int rtn = 0; 197*3b2bd0f6Slogwang 198*3b2bd0f6Slogwang /* Sanity check */ 199*3b2bd0f6Slogwang if (args == NULL) 200*3b2bd0f6Slogwang arglen = 0; 201*3b2bd0f6Slogwang 202*3b2bd0f6Slogwang /* Get buffer */ 203*3b2bd0f6Slogwang if ((buf = malloc(sizeof(*msg) + arglen)) == NULL) { 204*3b2bd0f6Slogwang errnosv = errno; 205*3b2bd0f6Slogwang if (_gNgDebugLevel >= 1) 206*3b2bd0f6Slogwang NGLOG("malloc"); 207*3b2bd0f6Slogwang rtn = -1; 208*3b2bd0f6Slogwang goto done; 209*3b2bd0f6Slogwang } 210*3b2bd0f6Slogwang msg = (struct ng_mesg *) buf; 211*3b2bd0f6Slogwang 212*3b2bd0f6Slogwang /* Finalize message */ 213*3b2bd0f6Slogwang *msg = *hdr; 214*3b2bd0f6Slogwang msg->header.arglen = arglen; 215*3b2bd0f6Slogwang memcpy(msg->data, args, arglen); 216*3b2bd0f6Slogwang 217*3b2bd0f6Slogwang /* Prepare socket address */ 218*3b2bd0f6Slogwang sg->sg_family = AF_NETGRAPH; 219*3b2bd0f6Slogwang /* XXX handle overflow */ 220*3b2bd0f6Slogwang strlcpy(sg->sg_data, path, NG_PATHSIZ); 221*3b2bd0f6Slogwang sg->sg_len = strlen(sg->sg_data) + 1 + NGSA_OVERHEAD; 222*3b2bd0f6Slogwang 223*3b2bd0f6Slogwang /* Debugging */ 224*3b2bd0f6Slogwang if (_gNgDebugLevel >= 2) { 225*3b2bd0f6Slogwang NGLOGX("SENDING %s:", 226*3b2bd0f6Slogwang (msg->header.flags & NGF_RESP) ? "RESPONSE" : "MESSAGE"); 227*3b2bd0f6Slogwang _NgDebugSockaddr(sg); 228*3b2bd0f6Slogwang _NgDebugMsg(msg, sg->sg_data); 229*3b2bd0f6Slogwang } 230*3b2bd0f6Slogwang 231*3b2bd0f6Slogwang /* Send it */ 232*3b2bd0f6Slogwang if (sendto(cs, msg, sizeof(*msg) + arglen, 233*3b2bd0f6Slogwang 0, (struct sockaddr *) sg, sg->sg_len) < 0) { 234*3b2bd0f6Slogwang errnosv = errno; 235*3b2bd0f6Slogwang if (_gNgDebugLevel >= 1) 236*3b2bd0f6Slogwang NGLOG("sendto(%s)", sg->sg_data); 237*3b2bd0f6Slogwang rtn = -1; 238*3b2bd0f6Slogwang goto done; 239*3b2bd0f6Slogwang } 240*3b2bd0f6Slogwang 241*3b2bd0f6Slogwang #ifndef FSTACK 242*3b2bd0f6Slogwang /* Wait for reply if there should be one. */ 243*3b2bd0f6Slogwang if (msg->header.cmd & NGM_HASREPLY && !(msg->header.flags & NGF_RESP)) { 244*3b2bd0f6Slogwang struct pollfd rfds; 245*3b2bd0f6Slogwang int n; 246*3b2bd0f6Slogwang 247*3b2bd0f6Slogwang rfds.fd = cs; 248*3b2bd0f6Slogwang rfds.events = POLLIN; 249*3b2bd0f6Slogwang rfds.revents = 0; 250*3b2bd0f6Slogwang n = poll(&rfds, 1, INFTIM); 251*3b2bd0f6Slogwang if (n == -1) { 252*3b2bd0f6Slogwang errnosv = errno; 253*3b2bd0f6Slogwang if (_gNgDebugLevel >= 1) 254*3b2bd0f6Slogwang NGLOG("poll"); 255*3b2bd0f6Slogwang rtn = -1; 256*3b2bd0f6Slogwang } 257*3b2bd0f6Slogwang } 258*3b2bd0f6Slogwang #endif 259*3b2bd0f6Slogwang 260*3b2bd0f6Slogwang done: 261*3b2bd0f6Slogwang /* Done */ 262*3b2bd0f6Slogwang free(buf); /* OK if buf is NULL */ 263*3b2bd0f6Slogwang errno = errnosv; 264*3b2bd0f6Slogwang return (rtn); 265*3b2bd0f6Slogwang } 266*3b2bd0f6Slogwang 267*3b2bd0f6Slogwang /* 268*3b2bd0f6Slogwang * Receive a control message. 269*3b2bd0f6Slogwang * 270*3b2bd0f6Slogwang * On error, this returns -1 and sets errno. 271*3b2bd0f6Slogwang * Otherwise, it returns the length of the received reply. 272*3b2bd0f6Slogwang */ 273*3b2bd0f6Slogwang int 274*3b2bd0f6Slogwang NgRecvMsg(int cs, struct ng_mesg *rep, size_t replen, char *path) 275*3b2bd0f6Slogwang { 276*3b2bd0f6Slogwang u_char sgbuf[NG_PATHSIZ + NGSA_OVERHEAD]; 277*3b2bd0f6Slogwang struct sockaddr_ng *const sg = (struct sockaddr_ng *) sgbuf; 278*3b2bd0f6Slogwang socklen_t sglen = sizeof(sgbuf); 279*3b2bd0f6Slogwang int len, errnosv; 280*3b2bd0f6Slogwang 281*3b2bd0f6Slogwang /* Read reply */ 282*3b2bd0f6Slogwang len = recvfrom(cs, rep, replen, 0, (struct sockaddr *) sg, &sglen); 283*3b2bd0f6Slogwang if (len < 0) { 284*3b2bd0f6Slogwang errnosv = errno; 285*3b2bd0f6Slogwang if (_gNgDebugLevel >= 1) 286*3b2bd0f6Slogwang NGLOG("recvfrom"); 287*3b2bd0f6Slogwang goto errout; 288*3b2bd0f6Slogwang } 289*3b2bd0f6Slogwang if (path != NULL) 290*3b2bd0f6Slogwang strlcpy(path, sg->sg_data, NG_PATHSIZ); 291*3b2bd0f6Slogwang 292*3b2bd0f6Slogwang /* Debugging */ 293*3b2bd0f6Slogwang if (_gNgDebugLevel >= 2) { 294*3b2bd0f6Slogwang NGLOGX("RECEIVED %s:", 295*3b2bd0f6Slogwang (rep->header.flags & NGF_RESP) ? "RESPONSE" : "MESSAGE"); 296*3b2bd0f6Slogwang _NgDebugSockaddr(sg); 297*3b2bd0f6Slogwang _NgDebugMsg(rep, sg->sg_data); 298*3b2bd0f6Slogwang } 299*3b2bd0f6Slogwang 300*3b2bd0f6Slogwang /* Done */ 301*3b2bd0f6Slogwang return (len); 302*3b2bd0f6Slogwang 303*3b2bd0f6Slogwang errout: 304*3b2bd0f6Slogwang errno = errnosv; 305*3b2bd0f6Slogwang return (-1); 306*3b2bd0f6Slogwang } 307*3b2bd0f6Slogwang 308*3b2bd0f6Slogwang /* 309*3b2bd0f6Slogwang * Identical to NgRecvMsg() except buffer is dynamically allocated. 310*3b2bd0f6Slogwang */ 311*3b2bd0f6Slogwang int 312*3b2bd0f6Slogwang NgAllocRecvMsg(int cs, struct ng_mesg **rep, char *path) 313*3b2bd0f6Slogwang { 314*3b2bd0f6Slogwang int len; 315*3b2bd0f6Slogwang #ifndef FSTACK 316*3b2bd0f6Slogwang socklen_t optlen; 317*3b2bd0f6Slogwang 318*3b2bd0f6Slogwang optlen = sizeof(len); 319*3b2bd0f6Slogwang if (getsockopt(cs, SOL_SOCKET, SO_RCVBUF, &len, &optlen) == -1 || 320*3b2bd0f6Slogwang #else 321*3b2bd0f6Slogwang len = NGCTL_DEFAULT_RCVBUF; 322*3b2bd0f6Slogwang if ( 323*3b2bd0f6Slogwang #endif 324*3b2bd0f6Slogwang (*rep = malloc(len)) == NULL) 325*3b2bd0f6Slogwang return (-1); 326*3b2bd0f6Slogwang if ((len = NgRecvMsg(cs, *rep, len, path)) < 0) 327*3b2bd0f6Slogwang free(*rep); 328*3b2bd0f6Slogwang return (len); 329*3b2bd0f6Slogwang } 330*3b2bd0f6Slogwang 331*3b2bd0f6Slogwang /* 332*3b2bd0f6Slogwang * Receive a control message and convert the arguments to ASCII 333*3b2bd0f6Slogwang */ 334*3b2bd0f6Slogwang int 335*3b2bd0f6Slogwang NgRecvAsciiMsg(int cs, struct ng_mesg *reply, size_t replen, char *path) 336*3b2bd0f6Slogwang { 337*3b2bd0f6Slogwang struct ng_mesg *msg, *ascii; 338*3b2bd0f6Slogwang int bufSize, errnosv; 339*3b2bd0f6Slogwang u_char *buf; 340*3b2bd0f6Slogwang 341*3b2bd0f6Slogwang /* Allocate buffer */ 342*3b2bd0f6Slogwang bufSize = 2 * sizeof(*reply) + replen; 343*3b2bd0f6Slogwang if ((buf = malloc(bufSize)) == NULL) 344*3b2bd0f6Slogwang return (-1); 345*3b2bd0f6Slogwang msg = (struct ng_mesg *)buf; 346*3b2bd0f6Slogwang ascii = (struct ng_mesg *)msg->data; 347*3b2bd0f6Slogwang 348*3b2bd0f6Slogwang /* Get binary message */ 349*3b2bd0f6Slogwang if (NgRecvMsg(cs, msg, bufSize, path) < 0) 350*3b2bd0f6Slogwang goto fail; 351*3b2bd0f6Slogwang memcpy(reply, msg, sizeof(*msg)); 352*3b2bd0f6Slogwang 353*3b2bd0f6Slogwang /* Ask originating node to convert the arguments to ASCII */ 354*3b2bd0f6Slogwang if (NgSendMsg(cs, path, NGM_GENERIC_COOKIE, 355*3b2bd0f6Slogwang NGM_BINARY2ASCII, msg, sizeof(*msg) + msg->header.arglen) < 0) 356*3b2bd0f6Slogwang goto fail; 357*3b2bd0f6Slogwang if (NgRecvMsg(cs, msg, bufSize, NULL) < 0) 358*3b2bd0f6Slogwang goto fail; 359*3b2bd0f6Slogwang 360*3b2bd0f6Slogwang /* Copy result to client buffer */ 361*3b2bd0f6Slogwang if (sizeof(*ascii) + ascii->header.arglen > replen) { 362*3b2bd0f6Slogwang errno = ERANGE; 363*3b2bd0f6Slogwang fail: 364*3b2bd0f6Slogwang errnosv = errno; 365*3b2bd0f6Slogwang free(buf); 366*3b2bd0f6Slogwang errno = errnosv; 367*3b2bd0f6Slogwang return (-1); 368*3b2bd0f6Slogwang } 369*3b2bd0f6Slogwang strncpy(reply->data, ascii->data, ascii->header.arglen); 370*3b2bd0f6Slogwang 371*3b2bd0f6Slogwang /* Done */ 372*3b2bd0f6Slogwang free(buf); 373*3b2bd0f6Slogwang return (0); 374*3b2bd0f6Slogwang } 375*3b2bd0f6Slogwang 376*3b2bd0f6Slogwang /* 377*3b2bd0f6Slogwang * Identical to NgRecvAsciiMsg() except buffer is dynamically allocated. 378*3b2bd0f6Slogwang */ 379*3b2bd0f6Slogwang int 380*3b2bd0f6Slogwang NgAllocRecvAsciiMsg(int cs, struct ng_mesg **reply, char *path) 381*3b2bd0f6Slogwang { 382*3b2bd0f6Slogwang int len; 383*3b2bd0f6Slogwang #ifndef FSTACK 384*3b2bd0f6Slogwang socklen_t optlen; 385*3b2bd0f6Slogwang 386*3b2bd0f6Slogwang optlen = sizeof(len); 387*3b2bd0f6Slogwang if (getsockopt(cs, SOL_SOCKET, SO_RCVBUF, &len, &optlen) == -1 || 388*3b2bd0f6Slogwang #else 389*3b2bd0f6Slogwang len = NGCTL_DEFAULT_RCVBUF; 390*3b2bd0f6Slogwang if ( 391*3b2bd0f6Slogwang #endif 392*3b2bd0f6Slogwang (*reply = malloc(len)) == NULL) 393*3b2bd0f6Slogwang return (-1); 394*3b2bd0f6Slogwang if ((len = NgRecvAsciiMsg(cs, *reply, len, path)) < 0) 395*3b2bd0f6Slogwang free(*reply); 396*3b2bd0f6Slogwang return (len); 397*3b2bd0f6Slogwang } 398