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