1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #pragma ident "%Z%%M% %I% %E% SMI" /* SunOS */ 29 30 #include <ctype.h> 31 #include <sys/sysmacros.h> 32 #include <sys/types.h> 33 #include <sys/errno.h> 34 #include <setjmp.h> 35 #include <sys/socket.h> 36 #include <net/if.h> 37 #include <netinet/in_systm.h> 38 #include <netinet/in.h> 39 #include <netinet/ip.h> 40 #include <netinet/if_ether.h> 41 #include "snoop.h" 42 43 #define NULL 0 44 45 extern void interpret_mip_cntrlmsg(int, uchar_t *, int); 46 47 struct porttable { 48 int pt_num; 49 char *pt_short; 50 char *pt_long; 51 }; 52 53 struct porttable pt_udp[] = { 54 7, "ECHO", "Echo", 55 9, "DISCARD", "Discard", 56 13, "DAYTIME", "Daytime", 57 19, "CHARGEN", "Character generator", 58 37, "TIME", "Time", 59 42, "NAME", "Host name server", 60 53, "DNS", "Domain Name Server", 61 67, "BOOTPS", "Bootstrap Protocol Server", 62 68, "BOOTPC", "Boostrap Protocol Client", 63 69, "TFTP", "Trivial File Transfer Protocol", 64 79, "FINGER", "Finger", 65 /* 111, "PORTMAP", "Portmapper", Just Sun RPC */ 66 123, "NTP", "Network Time Protocol", 67 137, "NBNS", "Netbios name service", 68 138, "NBDG", "Netbios datagram service", 69 389, "LDAP", "Lightweight Directory Access Protocol", 70 427, "SLP", "Service Location Protocol", 71 /* Mobile IP defines a set of new control messages sent over UDP port 434 */ 72 434, "Mobile IP", "Mobile IP Control Messages", 73 512, "BIFF", "BIFF", 74 513, "WHO", "WHO", 75 514, "SYSLOG", "SYSLOG", 76 517, "TALK", "TALK", 77 520, "RIP", "Routing Information Protocol", 78 550, "NEW-RWHO", "NEW-RWHO", 79 560, "RMONITOR", "RMONITOR", 80 561, "MONITOR", "MONITOR", 81 521, "RIPng", "Routing Information Protocol for IPv6", 82 1080, "SOCKS", "SOCKS Gateway", 83 0, NULL, "", 84 }; 85 86 struct porttable pt_tcp[] = { 87 1, "TCPMUX", "TCPMUX", 88 7, "ECHO", "Echo", 89 9, "DISCARD", "Discard", 90 11, "SYSTAT", "Active users", 91 13, "DAYTIME", "Daytime", 92 15, "NETSTAT", "Who is up", 93 19, "CHARGEN", "Character generator", 94 20, "FTP-DATA", "File Transfer Protocol (data)", 95 21, "FTP", "File Transfer Protocol", 96 23, "TELNET", "Terminal connection", 97 25, "SMTP", "Simple Mail Transport Protocol", 98 37, "TIME", "Time", 99 39, "RLP", "Resource Location Protocol", 100 42, "NAMESERVER", "Host Name Server", 101 43, "NICNAME", "Who is", 102 53, "DNS", "Domain Name Server", 103 67, "BOOTPS", "Bootstrap Protocol Server", 104 68, "BOOTPC", "Bootstrap Protocol Client", 105 69, "TFTP", "Trivial File Transfer Protocol", 106 70, "GOPHER", "Internet Gopher Protocol", 107 77, "RJE", "RJE service (private)", 108 79, "FINGER", "Finger", 109 80, "HTTP", "HyperText Transfer Protocol", 110 87, "LINK", "Link", 111 95, "SUPDUP", "SUPDUP Protocol", 112 101, "HOSTNAME", "NIC Host Name Server", 113 102, "ISO-TSAP", "ISO-TSAP", 114 103, "X400", "X400 Mail service", 115 104, "X400-SND", "X400 Mail service", 116 105, "CSNET-NS", "CSNET-NS", 117 109, "POP-2", "POP-2", 118 /* 111, "PORTMAP", "Portmapper", Just Sun RPC */ 119 113, "AUTH", "Authentication Service", 120 117, "UUCP-PATH", "UUCP Path Service", 121 119, "NNTP", "Network News Transfer Protocol", 122 123, "NTP", "Network Time Protocol", 123 139, "NBT", "Netbios over TCP", 124 143, "IMAP", "Internet Message Access Protocol", 125 144, "NeWS", "Network extensible Window System", 126 389, "LDAP", "Lightweight Directory Access Protocol", 127 427, "SLP", "Service Location Protocol", 128 443, "HTTPS", "HTTP over SSL", 129 445, "SMB", "Direct Hosted Server Message Block", 130 512, "EXEC", "EXEC", 131 513, "RLOGIN", "RLOGIN", 132 514, "RSHELL", "RSHELL", 133 515, "PRINTER", "PRINTER", 134 530, "COURIER", "COURIER", 135 540, "UUCP", "UUCP", 136 600, "PCSERVER", "PCSERVER", 137 1524, "INGRESLOCK", "INGRESLOCK", 138 1080, "SOCKS", "SOCKS Gateway", 139 2904, "M2UA", "SS7 MTP2 User Adaption Layer", 140 2905, "M3UA", "SS7 MTP3 User Adaption Layer", 141 6000, "XWIN", "X Window System", 142 8080, "HTTP (proxy)", "HyperText Transfer Protocol (proxy)", 143 9900, "IUA", "ISDN Q.921 User Adaption Layer", 144 0, NULL, "", 145 }; 146 147 char * 148 getportname(int proto, in_port_t port) 149 { 150 struct porttable *p, *pt; 151 152 switch (proto) { 153 case IPPROTO_SCTP: /* fallthru */ 154 case IPPROTO_TCP: pt = pt_tcp; break; 155 case IPPROTO_UDP: pt = pt_udp; break; 156 default: return (NULL); 157 } 158 159 for (p = pt; p->pt_num; p++) { 160 if (port == p->pt_num) 161 return (p->pt_short); 162 } 163 return (NULL); 164 } 165 166 int 167 reservedport(int proto, int port) 168 { 169 struct porttable *p, *pt; 170 171 switch (proto) { 172 case IPPROTO_TCP: pt = pt_tcp; break; 173 case IPPROTO_UDP: pt = pt_udp; break; 174 default: return (NULL); 175 } 176 for (p = pt; p->pt_num; p++) { 177 if (port == p->pt_num) 178 return (1); 179 } 180 return (0); 181 } 182 183 /* 184 * Need to be able to register an 185 * interpreter for transient ports. 186 * See TFTP interpreter. 187 */ 188 #define MAXTRANS 64 189 struct ttable { 190 int t_port; 191 int (*t_proc)(); 192 } transients [MAXTRANS]; 193 194 int 195 add_transient(int port, int (*proc)()) 196 { 197 static struct ttable *next = transients; 198 199 next->t_port = port; 200 next->t_proc = proc; 201 202 if (++next >= &transients[MAXTRANS]) 203 next = transients; 204 205 return (1); 206 } 207 208 static struct ttable * 209 is_transient(int port) 210 { 211 struct ttable *p; 212 213 for (p = transients; p->t_port && p < &transients[MAXTRANS]; p++) { 214 if (port == p->t_port) 215 return (p); 216 } 217 218 return (NULL); 219 } 220 221 void 222 del_transient(int port) 223 { 224 struct ttable *p; 225 226 for (p = transients; p->t_port && p < &transients[MAXTRANS]; p++) { 227 if (port == p->t_port) 228 p->t_port = -1; 229 } 230 } 231 232 static void 233 interpret_syslog(int flags, char dir, int port, const char *syslogstr, 234 int dlen) 235 { 236 static const char *pris[] = { 237 "emerg", "alert", "crit", "error", "warn", "notice", "info", "debug" 238 }; 239 static const char *facs[] = { 240 "kern", "user", "mail", "daemon", "auth", "syslog", "lpr", "news", 241 "uucp", NULL, NULL, NULL, NULL, "audit", NULL, "cron", "local0", 242 "local1", "local2", "local3", "local4", "local5", "local6", "local7" 243 }; 244 245 int composit; 246 int pri = -1; 247 int facil = -1; 248 boolean_t bogus = B_TRUE; 249 int priostrlen = 0; 250 int datalen = dlen; 251 char unknown[4]; /* for unrecognized ones */ 252 const char *facilstr = "BAD"; 253 const char *pristr = "FMT"; 254 const char *data = syslogstr; 255 256 /* 257 * Is there enough data to interpret (left bracket + at least 3 chars 258 * which could be digits, right bracket, or space)? 259 */ 260 if (datalen >= 4 && data != NULL) { 261 if (*data == '<') { 262 const int FACS_LEN = sizeof (facs) / sizeof (facs[0]); 263 char buffer[4]; 264 char *end; 265 266 data++; 267 datalen--; 268 269 strlcpy(buffer, data, sizeof (buffer)); 270 composit = strtoul(buffer, &end, 0); 271 data += end - buffer; 272 if (*data == '>') { 273 data++; 274 datalen -= end - buffer + 1; 275 276 pri = composit & 0x7; 277 facil = (composit & 0xF8) >> 3; 278 279 if ((facil >= FACS_LEN) || 280 (facs[facil] == NULL)) { 281 snprintf(unknown, sizeof (unknown), 282 "%d", facil); 283 facilstr = unknown; 284 } else { 285 facilstr = facs[facil]; 286 } 287 pristr = pris[pri]; 288 priostrlen = dlen - datalen; 289 bogus = B_FALSE; 290 } else { 291 data = syslogstr; 292 datalen = dlen; 293 } 294 } 295 } 296 297 if (flags & F_SUM) { 298 (void) snprintf(get_sum_line(), MAXLINE, 299 "SYSLOG %c port=%d %s.%s: %s", 300 dir, port, facilstr, pristr, 301 show_string(syslogstr, dlen, 20)); 302 303 } 304 305 if (flags & F_DTAIL) { 306 static char syslog[] = "SYSLOG: "; 307 show_header(syslog, syslog, dlen); 308 show_space(); 309 (void) sprintf(get_detail_line(0, 80), 310 "%s%sPriority: %.*s%s(%s.%s)", prot_nest_prefix, syslog, 311 priostrlen, syslogstr, bogus ? "" : " ", 312 facilstr, pristr); 313 (void) sprintf(get_line(0, 0), 314 "\"%s\"", 315 show_string(syslogstr, dlen, 60)); 316 show_trailer(); 317 } 318 } 319 320 int src_port, dst_port, curr_proto; 321 322 int 323 interpret_reserved(int flags, int proto, in_port_t src, in_port_t dst, 324 char *data, int dlen) 325 { 326 char *pn; 327 int dir, port, which; 328 char pbuff[16], hbuff[32]; 329 struct ttable *ttabp; 330 331 src_port = src; 332 dst_port = dst; 333 curr_proto = proto; 334 335 pn = getportname(proto, src); 336 if (pn != NULL) { 337 dir = 'R'; 338 port = dst; 339 which = src; 340 } else { 341 pn = getportname(proto, dst); 342 if (pn == NULL) { 343 ttabp = is_transient(src); 344 if (ttabp) { 345 (ttabp->t_proc)(flags, data, dlen); 346 return (1); 347 } 348 ttabp = is_transient(dst); 349 if (ttabp) { 350 (ttabp->t_proc)(flags, data, dlen); 351 return (1); 352 } 353 return (0); 354 } 355 356 dir = 'C'; 357 port = src; 358 which = dst; 359 } 360 361 if ((dst == 53 || src == 53) && proto != IPPROTO_TCP) { 362 interpret_dns(flags, proto, (uchar_t *)data, dlen); 363 return (1); 364 } 365 366 if (dst == 514 && proto != IPPROTO_TCP) { 367 /* 368 * TCP port 514 is rshell. UDP port 514 is syslog. 369 */ 370 interpret_syslog(flags, dir, port, (const char *)data, dlen); 371 return (1); 372 } 373 374 if (dlen > 0) { 375 switch (which) { 376 case 67: 377 case 68: 378 interpret_dhcp(flags, data, dlen); 379 return (1); 380 case 69: 381 interpret_tftp(flags, data, dlen); 382 return (1); 383 case 80: 384 case 8080: 385 interpret_http(flags, data, dlen); 386 return (1); 387 case 123: 388 interpret_ntp(flags, data, dlen); 389 return (1); 390 case 137: 391 interpret_netbios_ns(flags, data, dlen); 392 return (1); 393 case 138: 394 interpret_netbios_datagram(flags, data, dlen); 395 return (1); 396 case 139: 397 case 445: 398 /* 399 * SMB on port 445 is a subset of NetBIOS SMB 400 * on port 139. The same interpreter can be used 401 * for both. 402 */ 403 interpret_netbios_ses(flags, data, dlen); 404 return (1); 405 case 389: 406 interpret_ldap(flags, data, dlen, src, dst); 407 return (1); 408 case 427: 409 interpret_slp(flags, data, dlen); 410 return (1); 411 case 434: 412 interpret_mip_cntrlmsg(flags, (uchar_t *)data, dlen); 413 return (1); 414 case 520: 415 interpret_rip(flags, data, dlen); 416 return (1); 417 case 521: 418 interpret_rip6(flags, data, dlen); 419 return (1); 420 case 1080: 421 if (dir == 'C') 422 interpret_socks_call(flags, data, dlen); 423 else 424 interpret_socks_reply(flags, data, dlen); 425 return (1); 426 } 427 } 428 429 if (flags & F_SUM) { 430 (void) sprintf(get_sum_line(), 431 "%s %c port=%d %s", 432 pn, dir, port, 433 show_string(data, dlen, 20)); 434 } 435 436 if (flags & F_DTAIL) { 437 (void) sprintf(pbuff, "%s: ", pn); 438 (void) sprintf(hbuff, "%s: ", pn); 439 show_header(pbuff, hbuff, dlen); 440 show_space(); 441 (void) sprintf(get_line(0, 0), 442 "\"%s\"", 443 show_string(data, dlen, 60)); 444 show_trailer(); 445 } 446 return (1); 447 } 448 449 char * 450 show_string(const char *str, int dlen, int maxlen) 451 /* 452 * Prints len bytes from str enclosed in quotes. 453 * If len is negative, length is taken from strlen(str). 454 * No more than maxlen bytes will be printed. Longer 455 * strings are flagged with ".." after the closing quote. 456 * Non-printing characters are converted to C-style escape 457 * codes or octal digits. 458 */ 459 { 460 #define TBSIZE 256 461 static char tbuff[TBSIZE]; 462 const char *p; 463 char *pp; 464 int printable = 0; 465 int c, len; 466 467 len = dlen > maxlen ? maxlen : dlen; 468 dlen = len; 469 470 for (p = str, pp = tbuff; len; p++, len--) { 471 switch (c = *p & 0xFF) { 472 case '\n': (void) strcpy(pp, "\\n"); pp += 2; break; 473 case '\b': (void) strcpy(pp, "\\b"); pp += 2; break; 474 case '\t': (void) strcpy(pp, "\\t"); pp += 2; break; 475 case '\r': (void) strcpy(pp, "\\r"); pp += 2; break; 476 case '\f': (void) strcpy(pp, "\\f"); pp += 2; break; 477 default: 478 if (isascii(c) && isprint(c)) { 479 *pp++ = c; 480 printable++; 481 } else { 482 (void) sprintf(pp, 483 isdigit(*(p + 1)) ? 484 "\\%03o" : "\\%o", c); 485 pp += strlen(pp); 486 } 487 break; 488 } 489 *pp = '\0'; 490 /* 491 * Check for overflow of temporary buffer. Allow for 492 * the next character to be a \nnn followed by a trailing 493 * null. If not, then just bail with what we have. 494 */ 495 if (pp + 5 >= &tbuff[TBSIZE]) { 496 break; 497 } 498 } 499 return (printable > dlen / 2 ? tbuff : ""); 500 } 501