main.c revision 118860
1 2/* 3 * main.c 4 * 5 * Copyright (c) 1996-1999 Whistle Communications, Inc. 6 * All rights reserved. 7 * 8 * Subject to the following obligations and disclaimer of warranty, use and 9 * redistribution of this software, in source or object code forms, with or 10 * without modifications are expressly permitted by Whistle Communications; 11 * provided, however, that: 12 * 1. Any and all reproductions of the source or object code must include the 13 * copyright notice above and the following disclaimer of warranties; and 14 * 2. No rights are granted, in any manner or form, to use Whistle 15 * Communications, Inc. trademarks, including the mark "WHISTLE 16 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 17 * such appears in the above copyright notice or in the software. 18 * 19 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 20 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 21 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 22 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 24 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 25 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 26 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 27 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 28 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 29 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 30 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 31 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 35 * OF SUCH DAMAGE. 36 * 37 * $FreeBSD: head/usr.sbin/nghook/main.c 118860 2003-08-13 07:51:06Z harti $ 38 * $Whistle: main.c,v 1.9 1999/01/20 00:26:26 archie Exp $ 39 */ 40 41#include <stdio.h> 42#include <stdlib.h> 43#include <string.h> 44#include <ctype.h> 45#include <unistd.h> 46#include <sysexits.h> 47#include <errno.h> 48#include <err.h> 49 50#include <sys/types.h> 51#include <sys/socket.h> 52#include <sys/select.h> 53 54#include <netgraph.h> 55 56#define DEFAULT_HOOKNAME "debug" 57#define NG_SOCK_HOOK_NAME "hook" 58 59#define BUF_SIZE (64 * 1024) 60 61static void WriteAscii(u_char * buf, int len); 62static void Usage(void); 63 64static int outfd = STDOUT_FILENO; 65static int infd = STDIN_FILENO; 66 67/* 68 * main() 69 */ 70int 71main(int ac, char *av[]) 72{ 73 struct ngm_connect ngc; 74 const char *path = NULL; 75 const char *hook = DEFAULT_HOOKNAME; 76 int csock, dsock; 77 int asciiFlag = 0; 78 int loopFlag = 0; 79 int noInput = 0; 80 int ch; 81 82 /* Parse flags */ 83 while ((ch = getopt(ac, av, "adlnsS")) != EOF) { 84 switch (ch) { 85 case 'a': 86 asciiFlag = 1; 87 break; 88 case 'd': 89 NgSetDebug(NgSetDebug(-1) + 1); 90 break; 91 case 'l': 92 loopFlag = 1; 93 break; 94 case 'n': 95 noInput = 1; 96 break; 97 case 's': 98 outfd = STDIN_FILENO; 99 break; 100 case 'S': 101 infd = STDOUT_FILENO; 102 break; 103 case '?': 104 default: 105 Usage(); 106 } 107 } 108 ac -= optind; 109 av += optind; 110 111 /* Get params */ 112 switch (ac) { 113 case 2: 114 hook = av[1]; 115 /* FALLTHROUGH */ 116 case 1: 117 path = av[0]; 118 break; 119 default: 120 Usage(); 121 } 122 123 /* Get sockets */ 124 if (NgMkSockNode(NULL, &csock, &dsock) < 0) 125 errx(EX_OSERR, "can't get sockets"); 126 127 /* Connect socket node to specified node */ 128 snprintf(ngc.path, sizeof(ngc.path), "%s", path); 129 snprintf(ngc.ourhook, sizeof(ngc.ourhook), NG_SOCK_HOOK_NAME); 130 snprintf(ngc.peerhook, sizeof(ngc.peerhook), "%s", hook); 131 132 if (NgSendMsg(csock, ".", 133 NGM_GENERIC_COOKIE, NGM_CONNECT, &ngc, sizeof(ngc)) < 0) 134 errx(EX_OSERR, "can't connect to node"); 135 136 /* Close standard input if not reading from it */ 137 if (noInput) 138 fclose(stdin); 139 140 /* Relay data */ 141 while (1) { 142 fd_set rfds; 143 144 /* Setup bits */ 145 FD_ZERO(&rfds); 146 if (!noInput) 147 FD_SET(infd, &rfds); 148 FD_SET(dsock, &rfds); 149 150 /* Wait for something to happen */ 151 if (select(FD_SETSIZE, &rfds, NULL, NULL, NULL) < 0) 152 err(EX_OSERR, "select"); 153 154 /* Check data from socket */ 155 if (FD_ISSET(dsock, &rfds)) { 156 char buf[BUF_SIZE]; 157 int rl, wl; 158 159 /* Read packet from socket */ 160 if ((rl = NgRecvData(dsock, 161 buf, sizeof(buf), NULL)) < 0) 162 err(EX_OSERR, "read(hook)"); 163 if (rl == 0) 164 errx(EX_OSERR, "read EOF from hook?!"); 165 166 /* Write packet to stdout */ 167 if (asciiFlag) 168 WriteAscii((u_char *) buf, rl); 169 else if ((wl = write(outfd, buf, rl)) != rl) { 170 if (wl < 0) { 171 err(EX_OSERR, "write(stdout)"); 172 } else { 173 errx(EX_OSERR, 174 "stdout: read %d, wrote %d", 175 rl, wl); 176 } 177 } 178 /* Loopback */ 179 if (loopFlag) { 180 if (NgSendData(dsock, NG_SOCK_HOOK_NAME, buf, rl) < 0) 181 err(EX_OSERR, "write(hook)"); 182 } 183 } 184 185 /* Check data from stdin */ 186 if (FD_ISSET(infd, &rfds)) { 187 char buf[BUF_SIZE]; 188 int rl; 189 190 /* Read packet from stdin */ 191 if ((rl = read(infd, buf, sizeof(buf))) < 0) 192 err(EX_OSERR, "read(stdin)"); 193 if (rl == 0) 194 errx(EX_OSERR, "EOF(stdin)"); 195 196 /* Write packet to socket */ 197 if (NgSendData(dsock, NG_SOCK_HOOK_NAME, buf, rl) < 0) 198 err(EX_OSERR, "write(hook)"); 199 } 200 } 201} 202 203/* 204 * Dump data in hex and ASCII form 205 */ 206static void 207WriteAscii(u_char *buf, int len) 208{ 209 char ch, sbuf[100]; 210 int k, count; 211 212 for (count = 0; count < len; count += 16) { 213 snprintf(sbuf, sizeof(sbuf), "%04x: ", count); 214 for (k = 0; k < 16; k++) 215 if (count + k < len) 216 snprintf(sbuf + strlen(sbuf), 217 sizeof(sbuf) - strlen(sbuf), 218 "%02x ", buf[count + k]); 219 else 220 snprintf(sbuf + strlen(sbuf), 221 sizeof(sbuf) - strlen(sbuf), " "); 222 snprintf(sbuf + strlen(sbuf), sizeof(sbuf) - strlen(sbuf), " "); 223 for (k = 0; k < 16; k++) 224 if (count + k < len) { 225 ch = isprint(buf[count + k]) ? 226 buf[count + k] : '.'; 227 snprintf(sbuf + strlen(sbuf), 228 sizeof(sbuf) - strlen(sbuf), "%c", ch); 229 } else 230 snprintf(sbuf + strlen(sbuf), 231 sizeof(sbuf) - strlen(sbuf), " "); 232 snprintf(sbuf + strlen(sbuf), 233 sizeof(sbuf) - strlen(sbuf), "\n"); 234 (void) write(outfd, sbuf, strlen(sbuf)); 235 } 236 ch = '\n'; 237 write(outfd, &ch, 1); 238} 239 240/* 241 * Display usage and exit 242 */ 243static void 244Usage(void) 245{ 246 errx(EX_USAGE, "usage: nghook [-adlnsS] path [hookname]"); 247} 248 249