189674Sarchie
289674Sarchie/*
389674Sarchie * write.c
489674Sarchie *
589674Sarchie * Copyright (c) 2002 Archie L. Cobbs
689674Sarchie * All rights reserved.
789674Sarchie *
889674Sarchie * Subject to the following obligations and disclaimer of warranty, use and
989674Sarchie * redistribution of this software, in source or object code forms, with or
1089674Sarchie * without modifications are expressly permitted by Archie L. Cobbs;
1189674Sarchie * provided, however, that:
1289674Sarchie * 1. Any and all reproductions of the source or object code must include the
1389674Sarchie *    copyright notice above and the following disclaimer of warranties
1489674Sarchie *
1589674Sarchie * THIS SOFTWARE IS BEING PROVIDED BY ARCHIE L. COBBS AS IS", AND TO
1689674Sarchie * THE MAXIMUM EXTENT PERMITTED BY LAW, ARCHIE L. COBBS MAKES NO
1789674Sarchie * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
1889674Sarchie * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
1989674Sarchie * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
2089674Sarchie * ARCHIE L. COBBS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
2189674Sarchie * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
2289674Sarchie * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
2389674Sarchie * IN NO EVENT SHALL ARCHIE L. COBBS BE LIABLE FOR ANY DAMAGES
2489674Sarchie * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
2589674Sarchie * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
2689674Sarchie * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
2789674Sarchie * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
2889674Sarchie * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2989674Sarchie * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3089674Sarchie * THIS SOFTWARE, EVEN IF ARCHIE L. COBBS IS ADVISED OF THE POSSIBILITY
3189674Sarchie * OF SUCH DAMAGE.
3289674Sarchie *
3389674Sarchie * $FreeBSD$
3489674Sarchie */
3589674Sarchie
36158882Sglebius#include <sys/types.h>
37158882Sglebius#include <sys/socket.h>
38158882Sglebius
39158882Sglebius#include <err.h>
40158882Sglebius#include <stdio.h>
41158882Sglebius#include <string.h>
42158882Sglebius#include <unistd.h>
43158882Sglebius
44158882Sglebius#include <netgraph/ng_socket.h>
45158882Sglebius
4689674Sarchie#include "ngctl.h"
4789674Sarchie
4889674Sarchie#define BUF_SIZE	8192
4989674Sarchie
5089674Sarchiestatic int WriteCmd(int ac, char **av);
5189674Sarchie
5289674Sarchieconst struct ngcmd write_cmd = {
5389674Sarchie	WriteCmd,
5489674Sarchie	"write hook < -f file | byte ... >",
5589674Sarchie	"Send a data packet down the hook named by \"hook\".",
5689674Sarchie	"The data may be contained in a file, or may be described directly"
5789674Sarchie	" on the command line by supplying a sequence of bytes.",
5889674Sarchie	{ "w" }
5989674Sarchie};
6089674Sarchie
6189674Sarchiestatic int
6289674SarchieWriteCmd(int ac, char **av)
6389674Sarchie{
6489674Sarchie	u_int32_t sagbuf[64];
6589674Sarchie	struct sockaddr_ng *sag = (struct sockaddr_ng *)sagbuf;
6689674Sarchie	u_char buf[BUF_SIZE];
6789674Sarchie	const char *hook;
6889674Sarchie	FILE *fp;
6989674Sarchie	u_int len;
7089674Sarchie	int byte;
7189674Sarchie	int i;
7289674Sarchie
7389674Sarchie	/* Get arguments */
7489674Sarchie	if (ac < 3)
75160002Sglebius		return (CMDRTN_USAGE);
7689674Sarchie	hook = av[1];
7789674Sarchie
7889674Sarchie	/* Get data */
7989674Sarchie	if (strcmp(av[2], "-f") == 0) {
8089674Sarchie		if (ac != 4)
81160002Sglebius			return (CMDRTN_USAGE);
8289674Sarchie		if ((fp = fopen(av[3], "r")) == NULL) {
8389674Sarchie			warn("can't read file \"%s\"", av[3]);
84160002Sglebius			return (CMDRTN_ERROR);
8589674Sarchie		}
8689674Sarchie		if ((len = fread(buf, 1, sizeof(buf), fp)) == 0) {
8789674Sarchie			if (ferror(fp))
8889674Sarchie				warn("can't read file \"%s\"", av[3]);
8989674Sarchie			else
9089674Sarchie				warnx("file \"%s\" is empty", av[3]);
9189674Sarchie			fclose(fp);
92160002Sglebius			return (CMDRTN_ERROR);
9389674Sarchie		}
9489674Sarchie		fclose(fp);
9589674Sarchie	} else {
9689674Sarchie		for (i = 2, len = 0; i < ac && len < sizeof(buf); i++, len++) {
9789674Sarchie			if (sscanf(av[i], "%i", &byte) != 1
9889674Sarchie			    || (byte < -128 || byte > 255)) {
9989674Sarchie				warnx("invalid byte \"%s\"", av[i]);
100160002Sglebius				return (CMDRTN_ERROR);
10189674Sarchie			}
10289674Sarchie			buf[len] = (u_char)byte;
10389674Sarchie		}
10489674Sarchie		if (len == 0)
105160002Sglebius			return (CMDRTN_USAGE);
10689674Sarchie	}
10789674Sarchie
10889674Sarchie	/* Send data */
10989674Sarchie	sag->sg_len = 3 + strlen(hook);
11089674Sarchie	sag->sg_family = AF_NETGRAPH;
11189674Sarchie	strlcpy(sag->sg_data, hook, sizeof(sagbuf) - 2);
11289674Sarchie	if (sendto(dsock, buf, len,
11389674Sarchie	    0, (struct sockaddr *)sag, sag->sg_len) == -1) {
11489674Sarchie		warn("writing to hook \"%s\"", hook);
115160002Sglebius		return (CMDRTN_ERROR);
11689674Sarchie	}
11789674Sarchie
11889674Sarchie	/* Done */
119160002Sglebius	return (CMDRTN_OK);
12089674Sarchie}
12189674Sarchie
122