152419Sjulian/* 252419Sjulian * main.c 352419Sjulian * 452419Sjulian * Copyright (c) 1996-1999 Whistle Communications, Inc. 552419Sjulian * All rights reserved. 652419Sjulian * 752419Sjulian * Subject to the following obligations and disclaimer of warranty, use and 852419Sjulian * redistribution of this software, in source or object code forms, with or 952419Sjulian * without modifications are expressly permitted by Whistle Communications; 1052419Sjulian * provided, however, that: 1152419Sjulian * 1. Any and all reproductions of the source or object code must include the 1252419Sjulian * copyright notice above and the following disclaimer of warranties; and 1352419Sjulian * 2. No rights are granted, in any manner or form, to use Whistle 1452419Sjulian * Communications, Inc. trademarks, including the mark "WHISTLE 1552419Sjulian * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 1652419Sjulian * such appears in the above copyright notice or in the software. 1752419Sjulian * 1852419Sjulian * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 1952419Sjulian * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 2052419Sjulian * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 2152419Sjulian * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 2252419Sjulian * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 2352419Sjulian * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 2452419Sjulian * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 2552419Sjulian * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 2652419Sjulian * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 2752419Sjulian * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 2852419Sjulian * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 2952419Sjulian * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 3052419Sjulian * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 3152419Sjulian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3252419Sjulian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3352419Sjulian * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 3452419Sjulian * OF SUCH DAMAGE. 3552419Sjulian * 3652419Sjulian * $Whistle: main.c,v 1.9 1999/01/20 00:26:26 archie Exp $ 3752419Sjulian */ 3852419Sjulian 39119020Scharnier#include <sys/cdefs.h> 40119020Scharnier__FBSDID("$FreeBSD$"); 41119020Scharnier 4252419Sjulian#include <stdio.h> 4352419Sjulian#include <stdlib.h> 4452419Sjulian#include <string.h> 4552419Sjulian#include <ctype.h> 4652419Sjulian#include <unistd.h> 4752419Sjulian#include <sysexits.h> 4852419Sjulian#include <errno.h> 4952419Sjulian#include <err.h> 50121464Sharti#include <stringlist.h> 5152419Sjulian 5252419Sjulian#include <sys/types.h> 5352419Sjulian#include <sys/socket.h> 5452419Sjulian#include <sys/select.h> 5552419Sjulian 5652450Sdillon#include <netgraph.h> 5752419Sjulian 5852419Sjulian#define DEFAULT_HOOKNAME "debug" 5952419Sjulian#define NG_SOCK_HOOK_NAME "hook" 6052419Sjulian 6152419Sjulian#define BUF_SIZE (64 * 1024) 6252419Sjulian 6352419Sjulianstatic void WriteAscii(u_char * buf, int len); 6452419Sjulianstatic void Usage(void); 65121464Shartistatic void send_msgs(int, const char *); 6652419Sjulian 67118858Shartistatic int outfd = STDOUT_FILENO; 68118858Shartistatic int infd = STDIN_FILENO; 69118858Sharti 70121464Shartistatic StringList *msgs; 71121464Sharti 7252419Sjulian/* 7352419Sjulian * main() 7452419Sjulian */ 7552419Sjulianint 7652419Sjulianmain(int ac, char *av[]) 7752419Sjulian{ 7852419Sjulian struct ngm_connect ngc; 79118860Sharti const char *path = NULL; 80118860Sharti const char *hook = DEFAULT_HOOKNAME; 8152419Sjulian int csock, dsock; 8252419Sjulian int asciiFlag = 0; 8363436Sphk int loopFlag = 0; 8463931Sarchie int noInput = 0; 85121464Sharti int execFlag = 0; 8652419Sjulian int ch; 8752419Sjulian 88121464Sharti if ((msgs = sl_init()) == NULL) 89121464Sharti err(EX_OSERR, NULL); 90121464Sharti 9152419Sjulian /* Parse flags */ 92121464Sharti while ((ch = getopt(ac, av, "aedlm:nsS")) != -1) { 9352419Sjulian switch (ch) { 9463436Sphk case 'a': 9563436Sphk asciiFlag = 1; 9663436Sphk break; 9752419Sjulian case 'd': 9852419Sjulian NgSetDebug(NgSetDebug(-1) + 1); 9952419Sjulian break; 100121464Sharti case 'e': 101121464Sharti execFlag = 1; 102121464Sharti break; 10363436Sphk case 'l': 10463436Sphk loopFlag = 1; 10552419Sjulian break; 10663931Sarchie case 'n': 10763931Sarchie noInput = 1; 10863931Sarchie break; 109121464Sharti case 'm': 110121464Sharti if (sl_add(msgs, optarg) == -1) 111121464Sharti err(EX_OSERR, NULL); 112121464Sharti break; 113118858Sharti case 's': 114118858Sharti outfd = STDIN_FILENO; 115118858Sharti break; 116118858Sharti case 'S': 117118858Sharti infd = STDOUT_FILENO; 118118858Sharti break; 11952419Sjulian case '?': 12052419Sjulian default: 12152419Sjulian Usage(); 12252419Sjulian } 12352419Sjulian } 12452419Sjulian ac -= optind; 12552419Sjulian av += optind; 12652419Sjulian 127121464Sharti if (execFlag) { 128121464Sharti if (asciiFlag || loopFlag) { 129121464Sharti fprintf(stderr, "conflicting options\n"); 130121464Sharti Usage(); 131121464Sharti } 132121464Sharti if (ac < 3) 133121464Sharti Usage(); 134121464Sharti path = av[0]; 13552419Sjulian hook = av[1]; 136121464Sharti av += 2; 137121464Sharti ac -= 2; 138121464Sharti } else { 139121464Sharti /* Get params */ 140121464Sharti switch (ac) { 141121464Sharti case 2: 142121464Sharti hook = av[1]; 143121464Sharti /* FALLTHROUGH */ 144121464Sharti case 1: 145121464Sharti path = av[0]; 146121464Sharti break; 147121464Sharti default: 148121464Sharti Usage(); 149121464Sharti } 15052419Sjulian } 15152419Sjulian 15252419Sjulian /* Get sockets */ 15352419Sjulian if (NgMkSockNode(NULL, &csock, &dsock) < 0) 15452419Sjulian errx(EX_OSERR, "can't get sockets"); 15552419Sjulian 15652419Sjulian /* Connect socket node to specified node */ 15752419Sjulian snprintf(ngc.path, sizeof(ngc.path), "%s", path); 15852419Sjulian snprintf(ngc.ourhook, sizeof(ngc.ourhook), NG_SOCK_HOOK_NAME); 15952419Sjulian snprintf(ngc.peerhook, sizeof(ngc.peerhook), "%s", hook); 16052419Sjulian 16152419Sjulian if (NgSendMsg(csock, ".", 16252419Sjulian NGM_GENERIC_COOKIE, NGM_CONNECT, &ngc, sizeof(ngc)) < 0) 16352419Sjulian errx(EX_OSERR, "can't connect to node"); 16452419Sjulian 165121464Sharti if (execFlag) { 166121464Sharti /* move dsock to fd 0 and 1 */ 167121464Sharti (void)close(0); 168121464Sharti (void)close(1); 169121464Sharti if (!noInput) 170121464Sharti (void)dup2(dsock, 0); 171121464Sharti (void)dup2(dsock, 1); 172121464Sharti 173121464Sharti send_msgs(csock, path); 174121464Sharti 175121464Sharti /* try executing the program */ 176121464Sharti (void)execv(av[0], av); 177121464Sharti err(EX_OSERR, "%s", av[0]); 178121464Sharti 179121464Sharti } else 180121464Sharti send_msgs(csock, path); 181121464Sharti 18263931Sarchie /* Close standard input if not reading from it */ 18363931Sarchie if (noInput) 18463931Sarchie fclose(stdin); 18563931Sarchie 18652419Sjulian /* Relay data */ 18752419Sjulian while (1) { 18852419Sjulian fd_set rfds; 18952419Sjulian 19052419Sjulian /* Setup bits */ 19152419Sjulian FD_ZERO(&rfds); 19263931Sarchie if (!noInput) 193118858Sharti FD_SET(infd, &rfds); 19452419Sjulian FD_SET(dsock, &rfds); 19552419Sjulian 19652419Sjulian /* Wait for something to happen */ 19752419Sjulian if (select(FD_SETSIZE, &rfds, NULL, NULL, NULL) < 0) 19852419Sjulian err(EX_OSERR, "select"); 19952419Sjulian 20052419Sjulian /* Check data from socket */ 20152419Sjulian if (FD_ISSET(dsock, &rfds)) { 20252419Sjulian char buf[BUF_SIZE]; 20352419Sjulian int rl, wl; 20452419Sjulian 20552419Sjulian /* Read packet from socket */ 20652419Sjulian if ((rl = NgRecvData(dsock, 20752419Sjulian buf, sizeof(buf), NULL)) < 0) 20852419Sjulian err(EX_OSERR, "read(hook)"); 20952419Sjulian if (rl == 0) 21052419Sjulian errx(EX_OSERR, "read EOF from hook?!"); 21152419Sjulian 21252419Sjulian /* Write packet to stdout */ 21352419Sjulian if (asciiFlag) 21452419Sjulian WriteAscii((u_char *) buf, rl); 215118858Sharti else if ((wl = write(outfd, buf, rl)) != rl) { 21652419Sjulian if (wl < 0) { 21752419Sjulian err(EX_OSERR, "write(stdout)"); 21852419Sjulian } else { 21952419Sjulian errx(EX_OSERR, 22052419Sjulian "stdout: read %d, wrote %d", 22152419Sjulian rl, wl); 22252419Sjulian } 22352419Sjulian } 22463436Sphk /* Loopback */ 22563436Sphk if (loopFlag) { 22663436Sphk if (NgSendData(dsock, NG_SOCK_HOOK_NAME, buf, rl) < 0) 22763436Sphk err(EX_OSERR, "write(hook)"); 22863436Sphk } 22952419Sjulian } 23052419Sjulian 23152419Sjulian /* Check data from stdin */ 232118858Sharti if (FD_ISSET(infd, &rfds)) { 23352419Sjulian char buf[BUF_SIZE]; 23452419Sjulian int rl; 23552419Sjulian 23652419Sjulian /* Read packet from stdin */ 237118858Sharti if ((rl = read(infd, buf, sizeof(buf))) < 0) 23852419Sjulian err(EX_OSERR, "read(stdin)"); 23952419Sjulian if (rl == 0) 24052419Sjulian errx(EX_OSERR, "EOF(stdin)"); 24152419Sjulian 24252419Sjulian /* Write packet to socket */ 24352419Sjulian if (NgSendData(dsock, NG_SOCK_HOOK_NAME, buf, rl) < 0) 24452419Sjulian err(EX_OSERR, "write(hook)"); 24552419Sjulian } 24652419Sjulian } 24752419Sjulian} 24852419Sjulian 24952419Sjulian/* 25052419Sjulian * Dump data in hex and ASCII form 25152419Sjulian */ 25252419Sjulianstatic void 25352419SjulianWriteAscii(u_char *buf, int len) 25452419Sjulian{ 25552419Sjulian char ch, sbuf[100]; 25652419Sjulian int k, count; 25752419Sjulian 25852419Sjulian for (count = 0; count < len; count += 16) { 25952419Sjulian snprintf(sbuf, sizeof(sbuf), "%04x: ", count); 26052419Sjulian for (k = 0; k < 16; k++) 26152419Sjulian if (count + k < len) 26252419Sjulian snprintf(sbuf + strlen(sbuf), 26352419Sjulian sizeof(sbuf) - strlen(sbuf), 26452419Sjulian "%02x ", buf[count + k]); 26552419Sjulian else 26652419Sjulian snprintf(sbuf + strlen(sbuf), 26752419Sjulian sizeof(sbuf) - strlen(sbuf), " "); 26852419Sjulian snprintf(sbuf + strlen(sbuf), sizeof(sbuf) - strlen(sbuf), " "); 26952419Sjulian for (k = 0; k < 16; k++) 27052419Sjulian if (count + k < len) { 27152419Sjulian ch = isprint(buf[count + k]) ? 27252419Sjulian buf[count + k] : '.'; 27352419Sjulian snprintf(sbuf + strlen(sbuf), 27452419Sjulian sizeof(sbuf) - strlen(sbuf), "%c", ch); 27552419Sjulian } else 27652419Sjulian snprintf(sbuf + strlen(sbuf), 27753908Sarchie sizeof(sbuf) - strlen(sbuf), " "); 27852419Sjulian snprintf(sbuf + strlen(sbuf), 27952419Sjulian sizeof(sbuf) - strlen(sbuf), "\n"); 280118858Sharti (void) write(outfd, sbuf, strlen(sbuf)); 28152419Sjulian } 28252419Sjulian ch = '\n'; 283118858Sharti write(outfd, &ch, 1); 28452419Sjulian} 28552419Sjulian 28652419Sjulian/* 28752419Sjulian * Display usage and exit 28852419Sjulian */ 28952419Sjulianstatic void 29052419SjulianUsage(void) 29152419Sjulian{ 292119020Scharnier fprintf(stderr, "usage: nghook [-adlnsS] path [hookname]\n"); 293121464Sharti fprintf(stderr, " or: nghook -e [-n] [-m msg]* path hookname prog " 294121464Sharti "[args...]\n"); 295119020Scharnier exit(EX_USAGE); 29652419Sjulian} 297121464Sharti 298121464Sharti/* 299121464Sharti * Send the messages to the node 300121464Sharti */ 301121464Shartistatic void 302121464Shartisend_msgs(int cs, const char *path) 303121464Sharti{ 304121464Sharti u_int i; 305121464Sharti 306121464Sharti for (i = 0; i < msgs->sl_cur; i++) 307121464Sharti if (NgSendAsciiMsg(cs, path, "%s", msgs->sl_str[i]) == -1) 308121464Sharti err(EX_OSERR, "sending message '%s'", msgs->sl_str[i]); 309121464Sharti} 310