1/* 2#------------------------------------------------------------------------------- 3# 4# $Id: netstat-nat.c,v 1.33 2010/01/09 19:34:24 danny Exp $ 5# 6# $Log: netstat-nat.c,v $ 7# Revision 1.33 2010/01/09 19:34:24 danny 8# fix for properly display DNAT over SNAT connection 9# 10# Revision 1.32 2007/11/24 13:18:48 danny 11# - Added '-R' option to show routed connections instead of showing them with '-L' 12# - Some allocation & free bugs were squashed 13# 14# Revision 1.31 2007/05/26 11:48:08 danny 15# Added 'nf_conntrack' support 16# Added NAT host connection information (Used IP and port for NAT) 17# 18# Revision 1.30 2006/08/17 17:43:25 danny 19# - fix for read-in (ip_conntrack), previous versions could sometimes hang or 20# segfault on some systems. 21# - fix for displaying dnat over snat connections. 22# - changed my email to danny@tweegy.nl and changed homepage url 23# 24# Revision 1.29 2005/07/20 19:50:43 mardan 25# gcc 2.96 compatability fix 26# enlarged readin of ip_conntrack line 27# 28# Revision 1.28 2005/01/29 15:24:37 mardan 29# Some cleanups, bumped to version 1.4.5 30# 31# Revision 1.27 2005/01/23 16:33:09 mardan 32# Added protocol resolving 33# 34# Revision 1.26 2005/01/21 22:54:14 mardan 35# Added some forgotten states 36# 37# Revision 1.25 2005/01/01 17:02:24 mardan 38# Extraction of IPs and ports more dynamicly so it can be used with layer7 and 39# maybe others when layout of ip_conntrack changes 40# Added autoconf 41# 42# Revision 1.24 2003/09/01 20:36:52 mardan 43# Fixed small bug which didn't allow to display hostnames in expanded mode, 44# not enough bytes where allocated. 45# 46# Revision 1.23 2003/08/31 10:59:15 mardan 47# Merged patch from Guomundur D. Haraldsson <gdh@binhex.EU.org> which does a 48# more properly memory alloction and saver copies of variables. 49# Changed versions to v1.4.3. Ready to release if found stable. 50# Changed my e-mail to danny@tweegy.demon.nl 51# 52# Revision 1.22 2003/02/08 17:41:44 mardan 53# made some last minor changes. 54# ready to release v1.4.2 55# 56# Revision 1.21 2003/01/24 21:24:34 mardan 57# Added unknown protocol, display as 'raw' 58# Fixed hussle up in states when sorting connections 59# 60# Revision 1.20 2003/01/02 15:40:48 mardan 61# Merged patch from Marceln, which removes unused variables, more understandable 62# memory allocation error message, check to exit when there are no NAT connections 63# and making netstat-nat compatible with uLibC. 64# Updated files to v1.4.2 65# 66# Revision 1.19 2002/09/22 20:10:19 mardan 67# Added '-v: print version' 68# Added 'uninstall' to Makefile 69# Updated all other files. 70# 71# Revision 1.18 2002/09/22 17:16:08 mardan 72# Rewritten connection_table to allocate memory dynamicly. 73# 74# Revision 1.17 2002/09/12 19:32:12 mardan 75# Added display local connections to NAT box self 76# Updated README 77# Small changes in Makefile 78# 79# Revision 1.16 2002/09/08 20:23:48 mardan 80# Added sort by connection option. (source/destination IP/port) 81# Updated README and man-page. 82# 83# Revision 1.15 2002/08/07 19:25:59 mardan 84# Fixed bug, displayed wrong icmp connection in state REPLIED (dest was gateway). 85# 86# Revision 1.14 2002/08/07 19:02:54 mardan 87# Fixed 'icmp' bug. Segmentation fault occured when displaying NATed icmp connections. 88# 89# Revision 1.13 2002/08/06 19:32:54 mardan 90# Added small feature: no header output. 91# Lots of code cleanup. 92# 93# Revision 1.12 2002/08/03 00:22:22 mardan 94# Added portname resolving based on the listed names in 'services'. 95# Re-arranged the layout. 96# Added a Makefile and a header file. 97# Updated the README. 98# 99# Revision 1.11 2002/07/12 20:05:54 mardan 100# Added argument for extended view of hostnames. 101# Moved display-code into one function. 102# Removed most unnessacery code. 103# Updated README 104# 105# Revision 1.10 2002/07/10 19:58:33 mardan 106# Added filtering by destination-host, re-arranged some code to work properly. 107# Tested DNAT icmp and udp.(pls report if any bugs occur) 108# Fixed a few declaration bugs. 109# 110# Revision 1.9 2002/07/09 20:00:36 mardan 111# Added fully DNAT support (udp & icmp not fully tested yet, but should work), 112# including argument support for (S)(D)NAT selection. 113# Re-arranged layout code, can possible merged into one function. 114# Some few minor changes. 115# Started to work on destination-host selection. 116# 117# Revision 1.8 2002/07/07 20:27:47 mardan 118# Added display by source host/IP. 119# Made a few fixes/changes. 120# Updated the REAMDE. 121# 122# Revision 1.7 2002/06/30 19:55:41 mardan 123# Added README and COPYING (license) FILES. 124# 125# Revision 1.6 2002/06/23 16:27:26 mardan 126# Finished udp. 127# Maybe some layout changes in future? therwise tool is finished. 128# 129# Revision 1.5 2002/06/23 14:07:46 mardan 130# Added protocol arg option. 131# Todo: udp protocol 132# 133# Revision 1.4 2002/06/23 12:57:35 mardan 134# Added ident strings for test :-) 135# 136# Revision 1.3 2002/06/23 12:47:08 mardan 137# Fixed resolved hostname hussle-up/layout 138# Moved all source code into netstat-nat.c 139# 140# Revision 1.2 2002/06/23 11:56:09 mardan 141# Added NAT icmp display. 142# Still need to do udp (more states possible) 143# Really need to fix resolved hostnames display, still hussled up. 144# 145# Revision 1.1.1.1 2002/05/04 01:08:06 mardan 146# Initial import of netstat-nat, the C version. 147# Array pointers really needs to be fixed, still lots of other bugs.. 148# So far only TCP displayed. 149# No commandline args for e.g. no_nameresolving, protocol. 150# 151# 152# 153# Copyright (c) 2006 by D.Wijsman (danny@tweegy.nl). 154# All rights reserved. 155# 156# This program is free software; you can redistribute it and/or modify it 157# under the terms of the GNU General Public License as published by the Free 158# Software Foundation; either version 2 of the License, or (at your option) 159# any later version. 160# 161# This program is distributed in the hope that it will be useful, but WITHOUT 162# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 163# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 164# more details. 165# 166# You should have received a copy of the GNU General Public License 167# along with this program; see the file COPYING. If not, write to 168# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 169# 170# 171#------------------------------------------------------------------------------- 172*/ 173 174 175typedef struct _ip_addresses 176{ 177 char ip[16]; 178 char dev[16]; 179 struct _ip_addresses *prev; 180 struct _ip_addresses *next; 181} sIpAddresses; 182#include "netstat-nat.h" 183 184static char const rcsid[] = "$Id: netstat-nat.c,v 1.33 2010/01/09 19:34:24 danny Exp $"; 185char SRC_IP[50]; 186char DST_IP[50]; 187int SNAT = 1; 188int DNAT = 1; 189int LOCAL = 0; 190int ROUTED = 0; 191static char PROTOCOL[4]; 192int connection_index = 0; 193char ***connection_table; 194struct _ip_addresses *IpAddresses = NULL; 195 196 197int main(int argc, char *argv[]) 198 { 199 const char *args = "hnp:s:d:SDxor:L?vNR"; 200 static int SORT_ROW = 1; 201 static int EXT_VIEW = 0; 202 static int RESOLVE = 1; 203 static int no_hdr = 0; 204 static int NAT_HOP = 0; 205 FILE *f; 206 char line[350]; 207 char src[50]; 208 char dst[50]; 209 char host[50]; 210 char buf[100]; 211 char buf2[100]; 212 char from[50] = "NATed Address"; 213 char nathost[50] = "NAT-host Address"; 214 char dest[50] = "Destination Address"; 215 char *ret; 216 217 char ***pa; 218 char *store; 219 int index, a, b, c, j, r; 220 221 /* variables to display routed and/or local connections */ 222 struct ifconf ifc; 223 struct ifreq *req; 224 struct sockaddr_in *ipaddr; 225 char *ifbuf, *facename, *ptr; 226 int facefound, lastlen, len, sock; 227 //IpAddresses = NULL; 228 229 // check parameters 230 while ((c = getopt(argc, argv, args)) != -1) { 231 switch (c) { 232 case 'h': 233 display_help(); 234 return 1; 235 case '?': 236 display_help(); 237 return 1; 238 case 'v': 239 printf("Version %s\n", VERSION); 240 return(0); 241 case 'n': 242 RESOLVE = 0; 243 break; 244 case 'p': 245 strcopy(PROTOCOL, sizeof(PROTOCOL), optarg); 246 break; 247 case 's': 248 strcopy(SRC_IP, sizeof(SRC_IP), optarg); 249 lookup_ip(SRC_IP, sizeof(SRC_IP)); 250 break; 251 case 'd': 252 strcopy(DST_IP, sizeof(DST_IP), optarg); 253 lookup_ip(DST_IP, sizeof(DST_IP)); 254 break; 255 case 'S': 256 DNAT = 0; 257 break; 258 case 'D': 259 SNAT = 0; 260 break; 261 case 'L': 262 SNAT = 0; 263 DNAT = 0; 264 LOCAL = 1; 265 ROUTED = 0; 266 break; 267 case 'R': 268 SNAT = 0; 269 DNAT = 0; 270 LOCAL = 0; 271 ROUTED = 1; 272 break; 273 case 'x': 274 EXT_VIEW = 1; 275 break; 276 case 'o': 277 no_hdr = 1; 278 break; 279 case 'N': 280 NAT_HOP = 1; 281 break; 282 case 'r': 283 if (optarg == NULL || optarg == '\0') { 284 display_help(); 285 return 1; 286 } 287 if (strcmp(optarg, "scr") == 0) SORT_ROW = 1; //default 288 if (strcmp(optarg, "dst") == 0) SORT_ROW = 2; 289 if (strcmp(optarg, "src-port") == 0) SORT_ROW = 3; 290 if (strcmp(optarg, "dst-port") == 0) SORT_ROW = 4; 291 if (strcmp(optarg, "state") == 0) SORT_ROW = 5; 292 break; 293 } 294 } 295 // some param checks 296 if (LOCAL == 1 || ROUTED == 1) { 297 SNAT = 0; 298 DNAT = 0; 299 NAT_HOP = 0; 300 } 301 // get local IP addresses 302 if (ROUTED || LOCAL) { 303 // find all interfaces 304 305 sock = socket(PF_INET, SOCK_DGRAM, 0); 306 lastlen = 0; 307 len = 100 * sizeof(struct ifreq); 308 for(;;) { 309 if((ifbuf = malloc(len)) == NULL) { 310 perror("malloc"); 311 exit(EXIT_FAILURE); 312 } 313 ifc.ifc_buf = ifbuf; 314 ifc.ifc_len = len; 315 316 if(ioctl(sock, SIOCGIFCONF, &ifc) < 0) { 317 if(errno != EINVAL || lastlen != 0) { 318 perror("ioctl:SIOCGIFCONF"); 319 exit(EXIT_FAILURE); 320 } 321 } else { 322 if(ifc.ifc_len == lastlen) 323 // success // 324 break; 325 lastlen = ifc.ifc_len; 326 } 327 // increment buffer // 328 len += 10 * sizeof(struct ifreq); 329 free(ifbuf); 330 } 331 // store all local addresses in memory // 332 for(ptr = ifbuf; ptr < ifbuf + ifc.ifc_len; ) { 333 req = (struct ifreq *)ptr; 334 ipaddr = (struct sockaddr_in *) &req->ifr_addr; 335// printf("The IP address associated with %s is %s\n", req->ifr_name, inet_ntoa(ipaddr->sin_addr)); 336 ip_addresses_add(&IpAddresses, req->ifr_name, inet_ntoa(ipaddr->sin_addr)); 337 ptr += sizeof(struct ifreq); 338 } 339 if (ifbuf) { 340 free(ifbuf); 341 } 342 } 343 344 connection_table = (char ***) xcalloc((1) * sizeof(char **)); 345 // some checking for IPTables and read file 346 if ((f = fopen(NF_CONNTRACK_LOCATION, "r")) == NULL) { 347 if ((f = fopen(IP_CONNTRACK_LOCATION, "r")) == NULL) { 348 printf("Could not read info about connections from the kernel, make sure netfilter is enabled in kernel or by modules.\n"); 349 return 1; 350 } 351 } 352 353 // process conntrack table 354 if (!no_hdr) { 355 if (LOCAL || ROUTED) { 356 strcopy(from, sizeof(from), "Source Address"); 357 strcopy(dest, sizeof(dest), "Destination Address"); 358 } 359 if (!EXT_VIEW) { 360 printf("%-6s%-36s", "Proto", from); 361 if (NAT_HOP && !LOCAL) { 362 printf("%-36s", nathost); 363 } 364 printf("%-36s%-6s" ,dest, "State"); 365 printf("\n"); 366 } else { 367 printf("%-6s%-41s", "Proto", from); 368 if (NAT_HOP && !LOCAL) { 369 printf("%-41s", nathost); 370 } 371 printf("%-41s%-6s" ,dest, "State"); 372 printf("\n"); 373 } 374 } 375 376 // bugfix for proper read-in on some systems, provided by Supaflyster 377 while (!feof(f)) 378 { 379 ret = fgets(line, sizeof(line), f); 380 if (strlen(line) > 0) { 381 process_entry(line); 382 } 383 memset(line, 0, sizeof(line)); 384 } 385 fclose(f); 386 387 // create index of arrays pointed to main connection array 388 if (connection_index == 0) { 389 // There are no connections at this moment! free mem and exit 390 free(connection_table); 391 ip_addresses_free(&IpAddresses); 392 return (0); 393 } 394 395 pa = (char ***) xcalloc((connection_index) * sizeof(char **)); 396 397 for (index = 0; index < connection_index; index++) { 398 pa[index] = (char **) xcalloc((ROWS) * sizeof(char *)); 399 400 for (j = 0; j < ROWS; j++) { 401 pa[index][j] = &connection_table[index][j][0]; 402 } 403 } 404 // sort by protocol and defined row 405 for (a = 0; a < connection_index - 1; a++) { 406 for (b = a + 1; b < connection_index; b++) { 407 r = strcmp(pa[a][0], pa[b][0]); 408 if (r > 0) { 409 for (j = 0; j < ROWS; j++) { 410 store = pa[a][j]; 411 pa[a][j] = pa[b][j]; 412 pa[b][j] = store; 413 } 414 } 415 if (r == 0) { 416 if (strcmp(pa[a][SORT_ROW], pa[b][SORT_ROW]) > 0) { 417 for (j = 0; j < ROWS; j++) { 418 store = pa[a][j]; 419 pa[a][j] = pa[b][j]; 420 pa[b][j] = store; 421 } 422 } 423 } 424 } 425 } 426 427 // print connections 428 for (index = 0; index < connection_index; index++) { 429 if (RESOLVE) { 430 lookup_hostname(&pa[index][1]); 431 lookup_hostname(&pa[index][2]); 432 lookup_hostname(&pa[index][6]); 433 if (strlen(pa[index][3]) > 0 || strlen(pa[index][4]) > 0 || strlen(pa[index][7]) > 0) { 434 lookup_portname(&pa[index][3], pa[index][0]); 435 lookup_portname(&pa[index][4], pa[index][0]); 436 lookup_portname(&pa[index][7], pa[index][0]); 437 } 438 } 439 if (!EXT_VIEW) { 440 strcopy(buf, sizeof(buf), ""); 441 strncat(buf, pa[index][1], 34 - strlen(pa[index][3])); 442 if (!strcmp(pa[index][0], "tcp") || !strcmp(pa[index][0], "udp")) { 443 snprintf(buf2, sizeof(buf2), "%s:%s", buf, pa[index][3]); 444 } 445 else { 446 snprintf(buf2, sizeof(buf2), "%s", buf); 447 } 448 snprintf(src, sizeof(src), "%-36s", buf2); 449 strcopy(buf, sizeof(buf), ""); 450 strncat(buf, pa[index][2], 34 - strlen(pa[index][4])); 451 if (!strcmp(pa[index][0], "tcp") || !strcmp(pa[index][0], "udp")) { 452 snprintf(buf2, sizeof(buf2), "%s:%s", buf, pa[index][4]); 453 } 454 else { 455 snprintf(buf2, sizeof(buf2), "%s", buf); 456 } 457 snprintf(dst, sizeof(dst), "%-36s", buf2); 458 if (NAT_HOP) { 459 strcopy(buf, sizeof(buf), ""); 460 strncat(buf, pa[index][6], 34 - strlen(pa[index][7])); 461 if (!strcmp(pa[index][0], "tcp") || !strcmp(pa[index][0], "udp")) { 462 snprintf(buf2, sizeof(buf2), "%s:%s", buf, pa[index][7]); 463 } 464 else { 465 snprintf(buf2, sizeof(buf2), "%s", buf); 466 } 467 snprintf(host, sizeof(dst), "%-36s", buf2); 468 } 469 } else { 470 strcopy(buf, sizeof(buf), ""); 471 strncat(buf, pa[index][1], 39 - strlen(pa[index][3])); 472 if (!strcmp(pa[index][0], "tcp") || !strcmp(pa[index][0], "udp")) { 473 snprintf(buf2, sizeof(buf2), "%s:%s", buf, pa[index][3]); 474 } 475 else { 476 snprintf(buf2, sizeof(buf2), "%s", buf); 477 } 478 snprintf(src , sizeof(src), "%-41s", buf2); 479 strcopy(buf, sizeof(buf), ""); 480 strncat(buf, pa[index][2], 39 - strlen(pa[index][4])); 481 if (!strcmp(pa[index][0], "tcp") || !strcmp(pa[index][0], "udp")) { 482 snprintf(buf2, sizeof(buf2), "%s:%s", buf, pa[index][4]); 483 } 484 else { 485 snprintf(buf2, sizeof(buf2), "%s", buf); 486 } 487 snprintf(dst, sizeof(dst), "%-41s", buf2); 488 if (NAT_HOP) { 489 strcopy(buf, sizeof(buf), ""); 490 strncat(buf, pa[index][6], 39 - strlen(pa[index][7])); 491 if (!strcmp(pa[index][0], "tcp") || !strcmp(pa[index][0], "udp")) { 492 snprintf(buf2, sizeof(buf2), "%s:%s", buf, pa[index][7]); 493 } 494 else { 495 snprintf(buf2, sizeof(buf2), "%s", buf); 496 } 497 snprintf(host, sizeof(dst), "%-41s", buf2); 498 } 499 } 500 printf("%-6s%s", pa[index][0], src); 501 if (NAT_HOP) { 502 printf("%s", host); 503 } 504 printf("%s%-11s", dst, pa[index][5]); 505 printf("\n"); 506 507 } 508 509 ip_addresses_free(&IpAddresses); 510 511 for (a = 0; a < connection_index; a++) { 512 for (j = 0; j < ROWS; j++) { 513 if (connection_table[a][j] != NULL) free(connection_table[a][j]); 514 } 515 free(connection_table[a]); 516 free(pa[a]); 517 } 518 free(connection_table); 519 free(pa); 520 return(0); 521} 522 523// get protocol 524int get_protocol(char *line, char *protocol) 525{ 526 int i,j, protocol_nr; 527 char protocol_name[11] = ""; 528 char protocol_raw[6] = ""; 529 530 if (string_search(line, "tcp")) { 531 memcpy(protocol, "tcp", 3); 532 } 533 else if (string_search(line, "udp")) { 534 memcpy(protocol, "udp", 3); 535 } 536 else if (string_search(line, "icmp")) { 537 memcpy(protocol, "icmp", 4); 538 } 539 else { 540 // here we search for protocol number and give it a name (get_protocol_name) 541 for (i = 0; i < strlen(line); i++ ) { 542 if(!strncmp(&line[i], "unknown ", 9)) { 543 i += 9; 544 for (j = i; j < strlen(line); j++) { 545 if (line[j] == ' ') { 546 break; 547 } 548 strncat(protocol_raw, &line[j], 1); 549 } 550 protocol_nr = atoi(protocol_raw); 551 get_protocol_name(protocol_name, protocol_nr); 552 memcpy(protocol, protocol_name, 5); 553 break; 554 } 555 } 556 //memcpy(protocol, "raw", 3); 557 } 558// printf("PROTO: %s\n", protocol); 559 return(0); 560} 561 562// get connection status 563int get_connection_state(char *line, char *state) 564{ 565 if (string_search(line, "ESTABLISHED")) { 566 memcpy(state, "ESTABLISHED", 11); 567 } 568 else if (string_search(line, "TIME_WAIT")) { 569 memcpy(state, "TIME_WAIT", 9); 570 } 571 else if (string_search(line, "FIN_WAIT")) { 572 memcpy(state, "FIN_WAIT", 8); 573 } 574 else if (string_search(line, "SYN_RECV")) { 575 memcpy(state, "SYN_RECV", 8); 576 } 577 else if (string_search(line, "SYN_SENT")) { 578 memcpy(state, "SYN_SENT", 8); 579 } 580 else if (string_search(line, "UNREPLIED")) { 581 memcpy(state, "UNREPLIED", 9); 582 } 583 else if (string_search(line, "CLOSE")) { 584 memcpy(state, "CLOSE", 5); 585 } 586 else if (string_search(line, "ASSURED")) { 587 memcpy(state, "ASSURED", 7); 588 } 589 else { 590 if (string_search(line, "udp")) { 591 memcpy(state, "UNREPLIED", 9); 592 } 593 else { 594 memcpy(state, " ", 1); 595 } 596 } 597// printf("STATE: %s\n", state); 598 return(0); 599} 600 601void process_entry(char *line) 602{ 603 int count = 0; 604 char srcip_f[16] = ""; 605 char dstip_f[16] = ""; 606 char srcip_s[16] = ""; 607 char dstip_s[16] = ""; 608 char srcport[6] = ""; 609 char dstport[6] = ""; 610 char srcport_s[6] = ""; 611 char dstport_s[6] = ""; 612 char protocol[5] = ""; 613 char state[12] = ""; 614 615 search_first_hit("src=", line, srcip_f); 616 search_first_hit("dst=", line, dstip_f); 617 search_sec_hit("src=", line, srcip_s); 618 search_sec_hit("dst=", line, dstip_s); 619 search_first_hit("sport=", line, srcport); 620 search_first_hit("dport=", line, dstport); 621 search_sec_hit("sport=", line, srcport_s); 622 search_sec_hit("dport=", line, dstport_s); 623 624 get_protocol(line, protocol); 625 if (strcmp(PROTOCOL, "")) { 626 if (strncmp(PROTOCOL, protocol, 3)) { 627// printf("RETURN\n"); 628 return; 629 } 630 } 631 get_connection_state(line, state); 632 if (SNAT) { 633 if ((!strcmp(srcip_f, dstip_s) == 0) && (strcmp(dstip_f, srcip_s) == 0)) { 634 check_src_dst(protocol, srcip_f, dstip_f, srcport, dstport, dstip_s, dstport_s, state); 635 } 636 } 637 if (DNAT) { 638 if ((strcmp(srcip_f, dstip_s) == 0) && (!strcmp(dstip_f, srcip_s) == 0)) { 639 check_src_dst(protocol, srcip_f, srcip_s, srcport, srcport_s, dstip_f, dstport_s, state); 640 } 641 } 642 // bugfix for displaying dnat over snat connections, submitted by Supaflyster (intercepted traffic to DNAT) (2 interfaces) 643 if (DNAT || SNAT) { 644 if ((!strcmp(srcip_f, srcip_s) == 0) && (!strcmp(srcip_f, dstip_s) == 0) && (!strcmp(dstip_f, srcip_s) == 0) && (!strcmp(dstip_f, dstip_s) == 0) ) { 645 check_src_dst(protocol, srcip_f, srcip_s, srcport, srcport_s, dstip_s, dstport_s, state); 646 } 647 } 648 // (DNAT) (1 interface) 649 if (DNAT) { 650 if ((!strcmp(srcip_f, srcip_s) == 0) && (!strcmp(srcip_f, dstip_s) == 0) && (!strcmp(dstip_f, srcip_s) == 0) && (strcmp(dstip_f, dstip_s) == 0) ) { 651 check_src_dst(protocol, srcip_f, srcip_s, srcport, srcport_s, dstip_s, dstport_s, state); 652 } 653 } 654 if (LOCAL) { 655 if ((strcmp(srcip_f, dstip_s) == 0) && (strcmp(dstip_f, srcip_s) == 0) 656 && ((ip_addresses_search(IpAddresses, srcip_f) == 1) || (ip_addresses_search(IpAddresses, srcip_s) == 1) 657 || (ip_addresses_search(IpAddresses, dstip_f) == 1) || (ip_addresses_search(IpAddresses, dstip_s) == 1))) { 658 check_src_dst(protocol, srcip_f, srcip_s, srcport, dstport, "", "", state); 659 } 660 } 661 if (ROUTED) { 662 if ((strcmp(srcip_f, dstip_s) == 0) && (strcmp(dstip_f, srcip_s) == 0) 663 && (ip_addresses_search(IpAddresses, srcip_f) == 0) && (ip_addresses_search(IpAddresses, srcip_s) == 0) 664 && (ip_addresses_search(IpAddresses, dstip_f) == 0) && (ip_addresses_search(IpAddresses, dstip_s) == 0)) { 665 check_src_dst(protocol, srcip_f, srcip_s, srcport, dstport, "", "", state); 666 } 667 } 668// printf("%s %s %s %s %s %s\n", protocol, srcip_f, dstip_f, srcip_s, dstip_s, state); 669} 670 671 672// -- Internal used functions 673// Check filtering by source and destination IP 674void check_src_dst(char *protocol, char *src_ip, char *dst_ip, char *src_port, char *dst_port, char *nathostip, char *nathostport, char *status) 675 { 676 if ((check_if_source(src_ip)) && (strcmp(DST_IP, "") == 0)) { 677 store_data(protocol, src_ip, dst_ip, src_port, dst_port, nathostip, nathostport, status); 678 } 679 else if ((check_if_destination(dst_ip)) && (strcmp(SRC_IP, "") == 0)) { 680 store_data(protocol, src_ip, dst_ip, src_port, dst_port, nathostip, nathostport, status); 681 } 682 else if ((check_if_destination(dst_ip)) && (check_if_source(src_ip))) { 683 store_data(protocol, src_ip, dst_ip, src_port, dst_port, nathostip, nathostport, status); 684 } 685 } 686 687void store_data(char *protocol, char *src_ip, char *dst_ip, char *src_port, char *dst_port, char *nathostip, char *nathostport, char *status) 688 { 689 690 connection_table = (char ***) xrealloc(connection_table, (connection_index +1) * sizeof(char **)); 691 connection_table[connection_index] = (char **) xcalloc(200 * sizeof(char *)); 692 connection_table[connection_index][0] = (char *) xcalloc(10); 693 connection_table[connection_index][1] = (char *) xcalloc(60); 694 connection_table[connection_index][2] = (char *) xcalloc(60); 695 connection_table[connection_index][3] = (char *) xcalloc(20); 696 connection_table[connection_index][4] = (char *) xcalloc(20); 697 connection_table[connection_index][5] = (char *) xcalloc(15); 698 connection_table[connection_index][6] = (char *) xcalloc(60); 699 connection_table[connection_index][7] = (char *) xcalloc(20); 700 701 strcopy(connection_table[connection_index][3], 20, src_port); 702 strcopy(connection_table[connection_index][4], 20, dst_port); 703 strcopy(connection_table[connection_index][1], 60, src_ip); 704 strcopy(connection_table[connection_index][2], 60, dst_ip); 705 strcopy(connection_table[connection_index][0], 10, protocol); 706 strcopy(connection_table[connection_index][5], 15, status); 707 strcopy(connection_table[connection_index][6], 60, nathostip); 708 strcopy(connection_table[connection_index][7], 20, nathostport); 709 connection_index++; 710 } 711 712void lookup_portname(char **port, char *proto) 713 { 714 char buf_port[10]; 715 int portnr; 716 struct servent *service; 717 size_t port_size; 718 719 strcopy(buf_port, sizeof(buf_port), *port); 720 portnr = htons(atoi(buf_port)); 721 722 if ((service = getservbyport(portnr, proto))) { 723 //port_size = strlen(service->s_name) + 8; 724 //*port = xrealloc(*port, port_size); hmm double alloction 725 strcopy(*port, 20, service->s_name); 726 } 727 } 728 729void extract_ip(char *gen_buffer) 730 { 731 char *split; 732 split = strtok(gen_buffer, "="); 733 split = strtok(NULL, "="); 734 strcpy(gen_buffer, split); 735 } 736 737int lookup_hostname(char **r_host) 738 { 739 int addr; 740 struct hostent *hp; 741 char **p; 742 size_t r_host_size; 743 744 addr = inet_addr(*r_host); 745 if ((hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET)) == NULL) 746 return 0; 747 748 for (p = hp->h_addr_list; *p != 0; p++){ 749 struct in_addr in; 750 (void)memcpy(&in.s_addr, *p, sizeof(in.s_addr)); 751 //r_host_size = strlen(*r_host) + 25; 752 //*r_host = xrealloc(*r_host, r_host_size); hmm double allocation 753 strcopy(*r_host, 60, hp->h_name); 754 } 755 return 0; 756 } 757 758 759int lookup_ip(char *hostname, size_t hostname_size) 760 { 761 char *ip; 762 struct hostent *hp; 763 struct in_addr ip_addr; 764 765 if ((hp = gethostbyname(hostname)) == NULL) { 766 printf("Unknown host: %s\n", hostname); 767 exit(-1); 768 } 769 770 ip_addr = *(struct in_addr *)(hp->h_addr); 771 ip = inet_ntoa(*(struct in_addr *)(hp->h_addr)); 772 strcopy(hostname, hostname_size, ip); 773 return 1; 774 } 775/* 776int match(char *string, char *pattern) 777 { 778 int i; 779 regex_t re; 780 char buf[200]; 781 782 i = regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB); 783 784 if (i != 0) { 785 (void)regerror(i, &re, buf, sizeof(buf)); 786 return 0; 787 } 788 789 i = regexec(&re, string, (size_t) 0, NULL, 0); 790 regfree(&re); 791 792 if (i != 0) { 793 (void)regerror(i, &re, buf, sizeof(buf)); 794 return 0; 795 } 796 797 return 1; 798 } 799*/ 800int check_if_source(char *host) 801 { 802 if ((strcmp(host, SRC_IP) == 0) || (strcmp(SRC_IP, "") == 0)) { 803 return 1; 804 } 805 return 0; 806 } 807 808int check_if_destination(char *host) 809 { 810 if ((strcmp(host, DST_IP) == 0) || (strcmp(DST_IP, "") == 0)) { 811 return 1; 812 } 813 return 0; 814 } 815 816 817static void *xcalloc(size_t bufsize) 818 { 819 void *buf; 820 821 if ((buf = calloc(1, bufsize)) != NULL) { 822 return buf; 823 } else { 824 printf("Could not allocate memory (%i bytes); %s.\n -- Exiting.\n", bufsize, strerror(errno)); 825 exit(1); 826 } 827 } 828 829 830static void *xrealloc(void *oldbuf, size_t newbufsize) 831 { 832 void *newbuf; 833 834 if ((newbuf = realloc(oldbuf, newbufsize)) != NULL) { 835 return newbuf; 836 } else { 837 printf("Could not allocate memory (%i bytes); %s.\n -- Exiting.\n", newbufsize, strerror(errno)); 838 exit(1); 839 } 840 } 841 842char *xstrdup (const char *dup) 843{ 844 char *ret; 845 if ((ret = strdup(dup)) == NULL) { 846 printf("Could not set value into struct (%s); %s.\n -- Exiting.\n", dup, strerror(errno)); 847 exit(EXIT_FAILURE); 848 } 849 return ret; 850} 851 852void ip_addresses_add(struct _ip_addresses **list, const char *dev, const char *ip) 853{ 854 struct _ip_addresses *new = malloc(sizeof * new); 855 if (new != NULL) { 856 strncpy(new->ip, ip, 15); 857 strncpy(new->dev, dev, 15); 858 new->next = NULL; 859 if (*list == NULL) { 860 *list = new; 861 } 862 else { 863 struct _ip_addresses *tail = *list; 864 while (tail->next != NULL) 865 { 866 tail = tail->next; 867 } 868 tail->next = new; 869 } 870 } 871} 872 873int ip_addresses_search(struct _ip_addresses *list, const char *ip) 874{ 875 struct _ip_addresses *akt = list; 876 if (list == NULL) return 0; 877 while (akt != NULL) 878 { 879 if (strcmp (akt->ip, ip) == 0) { 880 return 1; 881 } 882 akt = akt->next; 883 } 884 return 0; 885} 886 887void ip_addresses_free(struct _ip_addresses **node) 888{ 889 struct _ip_addresses *this = *node; 890 struct _ip_addresses *temp; 891 while (this != NULL) 892 { 893 temp = this->next; 894 free(this); 895 this = temp; 896 } 897 *node = NULL; 898} 899 900int string_search(char *string, char *search) 901{ 902 int searchLen; 903 int i; 904 searchLen = strlen(search); 905 if (searchLen > strlen(string)) { 906 return(0); // this can't match 907 } 908 for (i = 0; i < strlen(string) - searchLen + 1; i++) { 909 if (!strncasecmp((char *)&string[i], search, searchLen)) { 910 return(1); // we got hit 911 } 912 } 913 return(0); 914} 915 916 917int search_first_hit(char *search, char *line, char *ret) 918{ 919 unsigned int searchLen; 920 unsigned int i; 921 unsigned int j; 922 unsigned int lineLen; 923 924 lineLen = strlen(line); 925 searchLen = strlen(search); 926 927 if (searchLen > lineLen) { 928 return(1); // this can't match, invalid data? 929 } 930 for (i = 0; i < lineLen - searchLen + 1; i++) { 931 if (!strncasecmp((char *)&line[i], search, searchLen)) { 932 break; // we got hit 933 } 934 } 935 for (j = i + searchLen; j < i + 15 + searchLen; j++) { 936 if (j > lineLen) { 937 return(1); // incomplete data 938 } 939 if (line[j] == ' ') { 940 break; // we reach _space_ delimiter 941 } 942 } 943 memcpy(ret, &line[i + searchLen], j - i - searchLen); 944 return(0); 945} 946 947 948int search_sec_hit(char *search, char *line, char *ret) 949{ 950 unsigned int searchLen; 951 unsigned int i; 952 unsigned int j; 953 unsigned int got_first = 0; 954 unsigned int lineLen; 955 956 lineLen = strlen(line); 957 searchLen = strlen(search); 958 959 if (searchLen > lineLen) { 960 return(1); // this can't match, invalid data? 961 } 962 for (i = 0; i < lineLen - searchLen + 1; i++) { 963 if (!strncasecmp((char *)&line[i], search, searchLen)) { 964 if (got_first) { 965 break; // we got hit (second) 966 } 967 got_first = 1; 968 } 969 } 970 for (j = i + searchLen; j < i + 15 + searchLen; j++) { 971 if (j > lineLen) { 972 return(1); // incomplete data 973 } 974 if (line[j] == ' ') { 975 break; // we reach _space_ delimiter 976 } 977 } 978 memcpy(ret, &line[i + searchLen], j - i - searchLen); 979 return(0); 980} 981 982 983void get_protocol_name(char *protocol_name, int protocol_nr) 984{ 985 struct protoent *proto_struct; 986 char strconvers[10] = ""; 987 proto_struct = getprotobynumber(protocol_nr); 988 if (proto_struct != NULL) { 989 memcpy(protocol_name, proto_struct->p_name, 5); 990 } 991 else { 992 snprintf(strconvers, 6, "%d", protocol_nr); 993 memcpy(protocol_name, strconvers, 5); 994 } 995} 996 997 998void display_help() 999{ 1000 printf("args: -h: displays this help\n"); 1001 printf(" -n: don't resolve host/portnames\n"); 1002 printf(" -p <protocol> : display connections by protocol\n"); 1003 printf(" -s <source-host> : display connections by source\n"); 1004 printf(" -d <destination-host>: display connections by destination\n"); 1005 printf(" -S: display SNAT connections\n"); 1006 printf(" -D: display DNAT connections (default: SNAT & DNAT)\n"); 1007 printf(" -L: display only connections to NAT box itself (doesn't show SNAT & DNAT)\n"); 1008 printf(" -R: display only connections routed through the NAT box (doesn't show SNAT & DNAT)\n"); 1009 printf(" -x: extended hostnames view\n"); 1010 printf(" -r src | dst | src-port | dst-port | state : sort connections\n"); 1011 printf(" -o: strip output header\n"); 1012 printf(" -N: display NAT box connection information (only valid with SNAT & DNAT)\n"); 1013 printf(" -v: print version\n"); 1014 printf("\n"); 1015 printf(" netstat-nat [-S|-D|-L|-R] [-no]\n"); 1016 printf(" netstat-nat [-nxo]\n"); 1017} 1018 1019// -- End of internal used functions 1020 1021// -- The End -- 1022