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