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: src/usr.sbin/nghook/main.c,v 1.4 1999/11/30 02:09:36 archie Exp $ 38 * $DragonFly: src/usr.sbin/nghook/main.c,v 1.4 2005/03/16 05:27:27 joerg Exp $ 39 * $Whistle: main.c,v 1.9 1999/01/20 00:26:26 archie Exp $ 40 */ 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 /* 66 * main() 67 */ 68 int 69 main(int ac, char *av[]) 70 { 71 struct ngm_connect ngc; 72 const char *path = NULL, *hook = DEFAULT_HOOKNAME; 73 int csock, dsock; 74 int asciiFlag = 0; 75 int ch; 76 77 /* Parse flags */ 78 while ((ch = getopt(ac, av, "da")) != EOF) { 79 switch (ch) { 80 case 'd': 81 NgSetDebug(NgSetDebug(-1) + 1); 82 break; 83 case 'a': 84 asciiFlag = 1; 85 break; 86 case '?': 87 default: 88 Usage(); 89 } 90 } 91 ac -= optind; 92 av += optind; 93 94 /* Get params */ 95 switch (ac) { 96 case 2: 97 hook = av[1]; 98 /* FALLTHROUGH */ 99 case 1: 100 path = av[0]; 101 break; 102 default: 103 Usage(); 104 } 105 106 /* Get sockets */ 107 if (NgMkSockNode(NULL, &csock, &dsock) < 0) 108 errx(EX_OSERR, "can't get sockets"); 109 110 /* Connect socket node to specified node */ 111 snprintf(ngc.path, sizeof(ngc.path), "%s", path); 112 snprintf(ngc.ourhook, sizeof(ngc.ourhook), NG_SOCK_HOOK_NAME); 113 snprintf(ngc.peerhook, sizeof(ngc.peerhook), "%s", hook); 114 115 if (NgSendMsg(csock, ".", 116 NGM_GENERIC_COOKIE, NGM_CONNECT, &ngc, sizeof(ngc)) < 0) 117 errx(EX_OSERR, "can't connect to node"); 118 119 /* Relay data */ 120 while (1) { 121 fd_set rfds; 122 123 /* Setup bits */ 124 FD_ZERO(&rfds); 125 FD_SET(0, &rfds); 126 FD_SET(dsock, &rfds); 127 128 /* Wait for something to happen */ 129 if (select(FD_SETSIZE, &rfds, NULL, NULL, NULL) < 0) 130 err(EX_OSERR, "select"); 131 132 /* Check data from socket */ 133 if (FD_ISSET(dsock, &rfds)) { 134 char buf[BUF_SIZE]; 135 int rl, wl; 136 137 /* Read packet from socket */ 138 if ((rl = NgRecvData(dsock, 139 buf, sizeof(buf), NULL)) < 0) 140 err(EX_OSERR, "read(hook)"); 141 if (rl == 0) 142 errx(EX_OSERR, "read EOF from hook?!"); 143 144 /* Write packet to stdout */ 145 if (asciiFlag) 146 WriteAscii((u_char *) buf, rl); 147 else if ((wl = write(1, buf, rl)) != rl) { 148 if (wl < 0) { 149 err(EX_OSERR, "write(stdout)"); 150 } else { 151 errx(EX_OSERR, 152 "stdout: read %d, wrote %d", 153 rl, wl); 154 } 155 } 156 } 157 158 /* Check data from stdin */ 159 if (FD_ISSET(0, &rfds)) { 160 char buf[BUF_SIZE]; 161 int rl; 162 163 /* Read packet from stdin */ 164 if ((rl = read(0, buf, sizeof(buf))) < 0) 165 err(EX_OSERR, "read(stdin)"); 166 if (rl == 0) 167 errx(EX_OSERR, "EOF(stdin)"); 168 169 /* Write packet to socket */ 170 if (NgSendData(dsock, NG_SOCK_HOOK_NAME, buf, rl) < 0) 171 err(EX_OSERR, "write(hook)"); 172 } 173 } 174 } 175 176 /* 177 * Dump data in hex and ASCII form 178 */ 179 static void 180 WriteAscii(u_char *buf, int len) 181 { 182 char ch, sbuf[100]; 183 int k, count; 184 185 for (count = 0; count < len; count += 16) { 186 snprintf(sbuf, sizeof(sbuf), "%04x: ", count); 187 for (k = 0; k < 16; k++) 188 if (count + k < len) 189 snprintf(sbuf + strlen(sbuf), 190 sizeof(sbuf) - strlen(sbuf), 191 "%02x ", buf[count + k]); 192 else 193 snprintf(sbuf + strlen(sbuf), 194 sizeof(sbuf) - strlen(sbuf), " "); 195 snprintf(sbuf + strlen(sbuf), sizeof(sbuf) - strlen(sbuf), " "); 196 for (k = 0; k < 16; k++) 197 if (count + k < len) { 198 ch = isprint(buf[count + k]) ? 199 buf[count + k] : '.'; 200 snprintf(sbuf + strlen(sbuf), 201 sizeof(sbuf) - strlen(sbuf), "%c", ch); 202 } else 203 snprintf(sbuf + strlen(sbuf), 204 sizeof(sbuf) - strlen(sbuf), " "); 205 snprintf(sbuf + strlen(sbuf), 206 sizeof(sbuf) - strlen(sbuf), "\n"); 207 write(1, sbuf, strlen(sbuf)); 208 } 209 ch = '\n'; 210 write(1, &ch, 1); 211 } 212 213 /* 214 * Display usage and exit 215 */ 216 static void 217 Usage(void) 218 { 219 errx(EX_USAGE, "usage: nghook [-da] path [hookname]"); 220 } 221 222