xref: /freebsd-14.2/lib/libnetgraph/msg.c (revision 4cf49a43)
1*4cf49a43SJulian Elischer 
2*4cf49a43SJulian Elischer /*
3*4cf49a43SJulian Elischer  * msg.c
4*4cf49a43SJulian Elischer  *
5*4cf49a43SJulian Elischer  * Copyright (c) 1996-1999 Whistle Communications, Inc.
6*4cf49a43SJulian Elischer  * All rights reserved.
7*4cf49a43SJulian Elischer  *
8*4cf49a43SJulian Elischer  * Subject to the following obligations and disclaimer of warranty, use and
9*4cf49a43SJulian Elischer  * redistribution of this software, in source or object code forms, with or
10*4cf49a43SJulian Elischer  * without modifications are expressly permitted by Whistle Communications;
11*4cf49a43SJulian Elischer  * provided, however, that:
12*4cf49a43SJulian Elischer  * 1. Any and all reproductions of the source or object code must include the
13*4cf49a43SJulian Elischer  *    copyright notice above and the following disclaimer of warranties; and
14*4cf49a43SJulian Elischer  * 2. No rights are granted, in any manner or form, to use Whistle
15*4cf49a43SJulian Elischer  *    Communications, Inc. trademarks, including the mark "WHISTLE
16*4cf49a43SJulian Elischer  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
17*4cf49a43SJulian Elischer  *    such appears in the above copyright notice or in the software.
18*4cf49a43SJulian Elischer  *
19*4cf49a43SJulian Elischer  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
20*4cf49a43SJulian Elischer  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
21*4cf49a43SJulian Elischer  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
22*4cf49a43SJulian Elischer  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
23*4cf49a43SJulian Elischer  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
24*4cf49a43SJulian Elischer  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
25*4cf49a43SJulian Elischer  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
26*4cf49a43SJulian Elischer  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
27*4cf49a43SJulian Elischer  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
28*4cf49a43SJulian Elischer  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
29*4cf49a43SJulian Elischer  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30*4cf49a43SJulian Elischer  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
31*4cf49a43SJulian Elischer  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
32*4cf49a43SJulian Elischer  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33*4cf49a43SJulian Elischer  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34*4cf49a43SJulian Elischer  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
35*4cf49a43SJulian Elischer  * OF SUCH DAMAGE.
36*4cf49a43SJulian Elischer  *
37*4cf49a43SJulian Elischer  * Author: Archie Cobbs <[email protected]>
38*4cf49a43SJulian Elischer  *
39*4cf49a43SJulian Elischer  * $FreeBSD$
40*4cf49a43SJulian Elischer  * $Whistle: msg.c,v 1.9 1999/01/20 00:57:23 archie Exp $
41*4cf49a43SJulian Elischer  */
42*4cf49a43SJulian Elischer 
43*4cf49a43SJulian Elischer #include <sys/types.h>
44*4cf49a43SJulian Elischer #include <stdarg.h>
45*4cf49a43SJulian Elischer #include <netgraph/ng_message.h>
46*4cf49a43SJulian Elischer #include <netgraph/ng_socket.h>
47*4cf49a43SJulian Elischer 
48*4cf49a43SJulian Elischer #include "netgraph.h"
49*4cf49a43SJulian Elischer #include "internal.h"
50*4cf49a43SJulian Elischer 
51*4cf49a43SJulian Elischer /* Next message token value */
52*4cf49a43SJulian Elischer static int	gMsgId;
53*4cf49a43SJulian Elischer 
54*4cf49a43SJulian Elischer /* For delivering both messages and replies */
55*4cf49a43SJulian Elischer static int	NgDeliverMsg(int cs, const char *path,
56*4cf49a43SJulian Elischer 		  const struct ng_mesg *hdr, const void *args, size_t arglen);
57*4cf49a43SJulian Elischer 
58*4cf49a43SJulian Elischer /*
59*4cf49a43SJulian Elischer  * Send a message to a node using control socket node "cs".
60*4cf49a43SJulian Elischer  * Returns -1 if error and sets errno appropriately.
61*4cf49a43SJulian Elischer  * If successful, returns the message ID (token) used.
62*4cf49a43SJulian Elischer  */
63*4cf49a43SJulian Elischer int
64*4cf49a43SJulian Elischer NgSendMsg(int cs, const char *path,
65*4cf49a43SJulian Elischer 	  int cookie, int cmd, const void *args, size_t arglen)
66*4cf49a43SJulian Elischer {
67*4cf49a43SJulian Elischer 	struct ng_mesg msg;
68*4cf49a43SJulian Elischer 
69*4cf49a43SJulian Elischer 	/* Prepare message header */
70*4cf49a43SJulian Elischer 	memset(&msg, 0, sizeof(msg));
71*4cf49a43SJulian Elischer 	msg.header.version = NG_VERSION;
72*4cf49a43SJulian Elischer 	msg.header.typecookie = cookie;
73*4cf49a43SJulian Elischer 	msg.header.token = ++gMsgId;
74*4cf49a43SJulian Elischer 	msg.header.flags = NGF_ORIG;
75*4cf49a43SJulian Elischer 	msg.header.cmd = cmd;
76*4cf49a43SJulian Elischer 	snprintf(msg.header.cmdstr, NG_CMDSTRLEN + 1, "cmd%d", cmd);
77*4cf49a43SJulian Elischer 
78*4cf49a43SJulian Elischer 	/* Deliver message */
79*4cf49a43SJulian Elischer 	if (NgDeliverMsg(cs, path, &msg, args, arglen) < 0)
80*4cf49a43SJulian Elischer 		return (-1);
81*4cf49a43SJulian Elischer 	return(gMsgId);
82*4cf49a43SJulian Elischer }
83*4cf49a43SJulian Elischer 
84*4cf49a43SJulian Elischer /*
85*4cf49a43SJulian Elischer  * Send a message that is a reply to a previously received message.
86*4cf49a43SJulian Elischer  * Returns -1 and sets errno on error, otherwise returns zero.
87*4cf49a43SJulian Elischer  */
88*4cf49a43SJulian Elischer int
89*4cf49a43SJulian Elischer NgSendReplyMsg(int cs, const char *path,
90*4cf49a43SJulian Elischer 	const struct ng_mesg *msg, const void *args, size_t arglen)
91*4cf49a43SJulian Elischer {
92*4cf49a43SJulian Elischer 	struct ng_mesg rep;
93*4cf49a43SJulian Elischer 
94*4cf49a43SJulian Elischer 	/* Prepare message header */
95*4cf49a43SJulian Elischer 	rep = *msg;
96*4cf49a43SJulian Elischer 	rep.header.flags = NGF_RESP;
97*4cf49a43SJulian Elischer 
98*4cf49a43SJulian Elischer 	/* Deliver message */
99*4cf49a43SJulian Elischer 	return (NgDeliverMsg(cs, path, &rep, args, arglen));
100*4cf49a43SJulian Elischer }
101*4cf49a43SJulian Elischer 
102*4cf49a43SJulian Elischer /*
103*4cf49a43SJulian Elischer  * Send a message to a node using control socket node "cs".
104*4cf49a43SJulian Elischer  * Returns -1 if error and sets errno appropriately, otherwise zero.
105*4cf49a43SJulian Elischer  */
106*4cf49a43SJulian Elischer static int
107*4cf49a43SJulian Elischer NgDeliverMsg(int cs, const char *path,
108*4cf49a43SJulian Elischer 	const struct ng_mesg *hdr, const void *args, size_t arglen)
109*4cf49a43SJulian Elischer {
110*4cf49a43SJulian Elischer 	u_char sgbuf[NG_PATHLEN + 3];
111*4cf49a43SJulian Elischer 	struct sockaddr_ng *const sg = (struct sockaddr_ng *) sgbuf;
112*4cf49a43SJulian Elischer 	u_char *buf = NULL;
113*4cf49a43SJulian Elischer 	struct ng_mesg *msg;
114*4cf49a43SJulian Elischer 	int errnosv = 0;
115*4cf49a43SJulian Elischer 	int rtn = 0;
116*4cf49a43SJulian Elischer 
117*4cf49a43SJulian Elischer 	/* Sanity check */
118*4cf49a43SJulian Elischer 	if (args == NULL)
119*4cf49a43SJulian Elischer 		arglen = 0;
120*4cf49a43SJulian Elischer 
121*4cf49a43SJulian Elischer 	/* Get buffer */
122*4cf49a43SJulian Elischer 	if ((buf = malloc(sizeof(*msg) + arglen)) == NULL) {
123*4cf49a43SJulian Elischer 		errnosv = errno;
124*4cf49a43SJulian Elischer 		if (_gNgDebugLevel >= 1)
125*4cf49a43SJulian Elischer 			NGLOG("malloc");
126*4cf49a43SJulian Elischer 		rtn = -1;
127*4cf49a43SJulian Elischer 		goto done;
128*4cf49a43SJulian Elischer 	}
129*4cf49a43SJulian Elischer 	msg = (struct ng_mesg *) buf;
130*4cf49a43SJulian Elischer 
131*4cf49a43SJulian Elischer 	/* Finalize message */
132*4cf49a43SJulian Elischer 	*msg = *hdr;
133*4cf49a43SJulian Elischer 	msg->header.arglen = arglen;
134*4cf49a43SJulian Elischer 	memcpy(msg->data, args, arglen);
135*4cf49a43SJulian Elischer 
136*4cf49a43SJulian Elischer 	/* Prepare socket address */
137*4cf49a43SJulian Elischer 	sg->sg_family = AF_NETGRAPH;
138*4cf49a43SJulian Elischer 	snprintf(sg->sg_data, NG_PATHLEN + 1, "%s", path);
139*4cf49a43SJulian Elischer 	sg->sg_len = strlen(sg->sg_data) + 3;
140*4cf49a43SJulian Elischer 
141*4cf49a43SJulian Elischer 	/* Debugging */
142*4cf49a43SJulian Elischer 	if (_gNgDebugLevel >= 2) {
143*4cf49a43SJulian Elischer 		NGLOGX("SENDING %s:",
144*4cf49a43SJulian Elischer 		    (msg->header.flags & NGF_RESP) ? "RESPONSE" : "MESSAGE");
145*4cf49a43SJulian Elischer 		_NgDebugSockaddr(sg);
146*4cf49a43SJulian Elischer 		_NgDebugMsg(msg);
147*4cf49a43SJulian Elischer 	}
148*4cf49a43SJulian Elischer 
149*4cf49a43SJulian Elischer 	/* Send it */
150*4cf49a43SJulian Elischer 	if (sendto(cs, msg, sizeof(*msg) + arglen,
151*4cf49a43SJulian Elischer 		   0, (struct sockaddr *) sg, sg->sg_len) < 0) {
152*4cf49a43SJulian Elischer 		errnosv = errno;
153*4cf49a43SJulian Elischer 		if (_gNgDebugLevel >= 1)
154*4cf49a43SJulian Elischer 			NGLOG("sendto(%s)", sg->sg_data);
155*4cf49a43SJulian Elischer 		rtn = -1;
156*4cf49a43SJulian Elischer 		goto done;
157*4cf49a43SJulian Elischer 	}
158*4cf49a43SJulian Elischer 
159*4cf49a43SJulian Elischer done:
160*4cf49a43SJulian Elischer 	/* Done */
161*4cf49a43SJulian Elischer 	free(buf);		/* OK if buf is NULL */
162*4cf49a43SJulian Elischer 	errno = errnosv;
163*4cf49a43SJulian Elischer 	return (rtn);
164*4cf49a43SJulian Elischer }
165*4cf49a43SJulian Elischer 
166*4cf49a43SJulian Elischer /*
167*4cf49a43SJulian Elischer  * Receive a control message.
168*4cf49a43SJulian Elischer  *
169*4cf49a43SJulian Elischer  * On error, this returns -1 and sets errno.
170*4cf49a43SJulian Elischer  * Otherwise, it returns the length of the received reply.
171*4cf49a43SJulian Elischer  */
172*4cf49a43SJulian Elischer int
173*4cf49a43SJulian Elischer NgRecvMsg(int cs, struct ng_mesg *rep, size_t replen, char *path)
174*4cf49a43SJulian Elischer {
175*4cf49a43SJulian Elischer 	u_char sgbuf[NG_PATHLEN + sizeof(struct sockaddr_ng)];
176*4cf49a43SJulian Elischer 	struct sockaddr_ng *const sg = (struct sockaddr_ng *) sgbuf;
177*4cf49a43SJulian Elischer 	int len, sglen = sizeof(sgbuf);
178*4cf49a43SJulian Elischer 	int errnosv;
179*4cf49a43SJulian Elischer 
180*4cf49a43SJulian Elischer 	/* Read reply */
181*4cf49a43SJulian Elischer 	len = recvfrom(cs, rep, replen, 0, (struct sockaddr *) sg, &sglen);
182*4cf49a43SJulian Elischer 	if (len < 0) {
183*4cf49a43SJulian Elischer 		errnosv = errno;
184*4cf49a43SJulian Elischer 		if (_gNgDebugLevel >= 1)
185*4cf49a43SJulian Elischer 			NGLOG("recvfrom");
186*4cf49a43SJulian Elischer 		goto errout;
187*4cf49a43SJulian Elischer 	}
188*4cf49a43SJulian Elischer 	if (path != NULL)
189*4cf49a43SJulian Elischer 		snprintf(path, NG_PATHLEN + 1, "%s", sg->sg_data);
190*4cf49a43SJulian Elischer 
191*4cf49a43SJulian Elischer 	/* Debugging */
192*4cf49a43SJulian Elischer 	if (_gNgDebugLevel >= 2) {
193*4cf49a43SJulian Elischer 		NGLOGX("RECEIVED %s:",
194*4cf49a43SJulian Elischer 		    (rep->header.flags & NGF_RESP) ? "RESPONSE" : "MESSAGE");
195*4cf49a43SJulian Elischer 		_NgDebugSockaddr(sg);
196*4cf49a43SJulian Elischer 		_NgDebugMsg(rep);
197*4cf49a43SJulian Elischer 	}
198*4cf49a43SJulian Elischer 
199*4cf49a43SJulian Elischer 	/* Done */
200*4cf49a43SJulian Elischer 	return (len);
201*4cf49a43SJulian Elischer 
202*4cf49a43SJulian Elischer errout:
203*4cf49a43SJulian Elischer 	errno = errnosv;
204*4cf49a43SJulian Elischer 	return (-1);
205*4cf49a43SJulian Elischer }
206*4cf49a43SJulian Elischer 
207