Annotation of embedaddon/dhcdrop/src/dhcdrop.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2009 by Chebotarev Roman <roma@ultranet.ru>
! 3: *
! 4: * This program is free software; you can redistribute it and/or modify
! 5: * it under the terms of the GNU General Public License as published by
! 6: * the Free Software Foundation; either version 2 of the License.
! 7: *
! 8: * This program is distributed in the hope that it will be useful,
! 9: * but WITHOUT ANY WARRANTY; without even the implied warranty of
! 10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 11: * GNU General Public License for more details.
! 12: *
! 13: * You should have received a copy of the GNU General Public License
! 14: * along with this program; if not, write to the Free Software
! 15: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
! 16: */
! 17:
! 18: #include "common_includes.h"
! 19: #include "net.h"
! 20: #include "dhcp.h"
! 21: #include "dhcdrop_types.h"
! 22: #include "net_functions.h"
! 23: #include "dhcp_functions.h"
! 24: #include "dhcdrop.h"
! 25:
! 26: const char usage_message[] = "Usage:\n"
! 27: "dhcpdrop [-h] [-D] [-t] [-y] [-r] [-b] [-a] [-A] [-f] [-R] [-q]\n"
! 28: "\t[-m <count>] [-c <count>] [-n <hostname>] [-N <clientname>]\n"
! 29: "\t[-p <port>] [-P <port>] [-w <secs>] [-T <timeout>]\n"
! 30: "\t[-M <max-hosts-scan>] [-l <MAC-address>] [-L <network>]\n"
! 31: "\t[-S <network/mask>] [-F <from-IP>] [-s <server-IP>]\n"
! 32: "\t[-C <"CHILDREN_TYPE" count (2 - 32)>] [<initial MAC address>]\n"
! 33: "\t-i <interface-name|interface-index>\n";
! 34:
! 35: const char keys[] = "\t-h - print this help message\n"
! 36: "\t-D - list of available network interfaces.\n"
! 37: "\t Format - index:name.\n"
! 38: "\t-t - test mode. Send DHCPDISCOVER and wait DHCPOFFER.\n"
! 39: "\t Exit with code 200 if DHCPOFFER is received.\n"
! 40: "\t Otherwise - exit with code 0.\n"
! 41: "\t-y - answer 'yes' to all questions.\n"
! 42: "\t-r - disable ethernet address randomize.\n"
! 43: "\t-b - use flag 'broadcast' in DHCP message\n"
! 44: "\t (default: don't use flag broadcast).\n"
! 45: "\t-a - always wait server('s) response\n"
! 46: "\t on default DHCP client port (68)\n"
! 47: "\t-A - always wait server('s) response\n"
! 48: "\t from default DHCP server port (67)\n"
! 49: "\t-f - flood mode. Generate DHCPDISCOVER flood.\n"
! 50: "\t-R - send DHCPRELEASE from source MAC address specified\n"
! 51: "\t by <initial MAC address> and IP address specified\n"
! 52: "\t by option -F to server specified by option -s.\n"
! 53: "\t-q - quiet mode.\n"
! 54: "\t-m count - maximum number of attempts\n"
! 55: "\t to receive answer from DHCP server.\n"
! 56: "\t-c count - maximum number of receiving addresses\n"
! 57: "\t from DHCP server (default: 255).\n"
! 58: "\t-n hostname - value of DHCP-option 'HostName'\n"
! 59: "\t (default: 'DHCP-dropper').\n"
! 60: "\t-N clientname - value of DHCP-option 'Vendor-Class'\n"
! 61: "\t (default: 'DHCP-dropper').\n"
! 62: "\t-p port - set client port value.\n"
! 63: "\t-P port - set server port value.\n"
! 64: "\t-w seconds - set timeout after which the process will be\n"
! 65: "\t restarted when using agressive mode (see option -L)\n"
! 66: "\t (default: 60 secs).\n"
! 67: "\t-T timeout - set timeout (of) waiting server response\n"
! 68: "\t in seconds (default: 3).\n"
! 69: "\t-M max-hosts-scan - maximum number of hosts scanned if\n"
! 70: "\t agressive mode (is used) (option -L).\n"
! 71: "\t-l MAC-address - ethernet address of DHCP server\n"
! 72: "\t which need(s) to (be) ignore(d). May be several servers.\n"
! 73: "\t Need option '-l' for each server.\n"
! 74: "\t-L network - specify legal network(s) on interfase. May be\n"
! 75: "\t several networks. If this parameter is set, dhcdrop\n"
! 76: "\t uses agressive mode: it scans address range assigned\n"
! 77: "\t by DHCP server for searching hosts with incorrect addresses,\n"
! 78: "\t sends DHCPRELEASE to server from every found host after\n"
! 79: "\t this it restarts process of receiving addreses.\n"
! 80: "\t-S network/mask - ARP-scan for network 'network' with network\n"
! 81: "\t mask 'mask' (CIDR notation). Source IP address for scanning\n"
! 82: "\t specified by option -F. If source IP is not set - using random\n"
! 83: "\t IP address from network address range.\n"
! 84: "\t-F from-IP - source IP for scanning network or sending\n"
! 85: "\t DHCPRELEASE (see option -S and -R).\n"
! 86: "\t-s server-IP - specify DHCP server IP address.\n"
! 87: "\t Used with option -R.\n"
! 88: "\t-C count - "
! 89: #ifdef _WIN32
! 90: "child thread"
! 91: #else
! 92: "children"
! 93: #endif
! 94: " number\n"
! 95: "\t (default: 0, minimal value: 2, maximum: 32).\n"
! 96: "\t Compatible only with flag '-f'.\n"
! 97: #ifdef _WIN32
! 98: "\t WARNING: not effectively under OS Windows.\n"
! 99: #endif
! 100: "\t-i interface - defines network interface, can be name or\n"
! 101: "\t index (cannot be 'any'). For listing available\n"
! 102: "\t interfaces use option -D.\n";
! 103:
! 104: const char ret_codes[] = "Program can exit with codes:\n"
! 105: "\t0 - Exit success. Illegal DHCP server not found.\n"
! 106: "\t10 - invalid user ID. You must be root for running programm.\n"
! 107: "\t20 - failed to set signal handler.\n"
! 108: "\t30 - configuration error. See usage.\n"
! 109: "\t40 - memory allocation error. Insufficient memory?\n"
! 110: "\t50 - error opening ethernet device.\n"
! 111: "\t51 - error listing devices.\n"
! 112: "\t60 - pcap filter overflow.\n"
! 113: "\t70 - pcap compile error.\n"
! 114: "\t80 - pcap set filter error.\n"
! 115: "\t90 - error sending packet.\n"
! 116: "\t100 - error getting packet.\n"
! 117: "\t110 - set non blocked mode error.\n"
! 118: "\t120 - invalid device.\n"
! 119: "\t200 - illegal DHCP server was found.\n";
! 120:
! 121: const char leases_warning[] = "\nWARNING: Failed to take away all the IP addresses assigned by DHCP server.\n"
! 122: "Perhaps DHCP server checks availability of IP addresses by sending ARP-request\n"
! 123: "before assigning them. Try to restart dhcpdrop later. If it doesn't help\n"
! 124: "try to disconnect problem hosts temporarily, then send manually DHCPRELEASE\n"
! 125: "from address of this hosts (use option -R) and restart dhcdrop.\n";
! 126:
! 127: const uint8_t broadcast_ether[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
! 128:
! 129: int main (int argc, char **argv)
! 130: {
! 131: struct config_params config; /* Parametrs from command line */
! 132:
! 133: srand(time(0));
! 134: atexit(cleanup);
! 135: set_timer_handler(timeout);
! 136: set_console_handler(int_sign);
! 137:
! 138: configure(argc, argv, &config);
! 139:
! 140: int ret = exec_action(&config);
! 141:
! 142: if(!config.quiet_mode && !config.test_mode)
! 143: printf("Finished.\n");
! 144:
! 145: return ret;
! 146: }
! 147:
! 148: int exec_action(const struct config_params * config)
! 149: {
! 150: int ret;
! 151:
! 152: #ifndef _WIN32
! 153: if(geteuid())
! 154: {
! 155: printf("Your EUID shoud be 0 (root) to run this program.\n"
! 156: "Currently your EUID is %u. Aborting.\n", geteuid());
! 157: return ERR_EUID;
! 158: }
! 159: #endif
! 160:
! 161: if(config->discover)
! 162: interfaces_discover(0);
! 163:
! 164: if(!config->test_mode && !config->quiet_mode)
! 165: printf("Using interface: '%s'\n", config->if_name);
! 166:
! 167: if(config->flood)
! 168: {
! 169: printf("Sending DHCPDISCOVER flood. Press Ctrl+C to abort...\n");
! 170: send_flood(config);
! 171: return EXIT_SUCCESS;
! 172: }
! 173:
! 174: /* Opening network device */
! 175: pcap_t * pcap_socket = get_device(config);
! 176:
! 177: if(config->scanned_network)
! 178: {
! 179: scan_subnet(pcap_socket, config->from_ip, config->source_mac, config->scanned_network, config->scan_netmask);
! 180: pcap_close(pcap_socket);
! 181: return EXIT_SUCCESS;
! 182: }
! 183:
! 184: if(config->send_dhcprelease)
! 185: {
! 186: printf("Send DHCPRELEASE from %s ", config->str_source_mac);
! 187: printf("client IP %s ", iptos(config->from_ip));
! 188: printf("to DHCP server %s\n", iptos(config->server_ip));
! 189: ret = send_dhcp_release(pcap_socket, config, config->source_mac,
! 190: config->server_ip, config->from_ip, rand());
! 191: pcap_close(pcap_socket);
! 192: return ret;
! 193: }
! 194:
! 195: struct dhcp_packet server_response;
! 196: uint16_t response_length;
! 197:
! 198: /* Searching DHCP server in the network */
! 199: struct dhcp_packet_net_header net_header;
! 200: ret = get_dhcp_server(config, pcap_socket, &net_header,
! 201: &server_response, &response_length);
! 202: if(!ret)
! 203: {
! 204: pcap_close(pcap_socket);
! 205: return EXIT_SUCCESS; /* Illegal DHCP server not found */
! 206: }
! 207:
! 208: if(ret != ILLEGAL_SERV_FOUND)
! 209: return ret; /* Error occured */
! 210:
! 211: if(config->test_mode) /* If test-mode - exit without dropping */
! 212: {
! 213: pcap_close(pcap_socket);
! 214: return ILLEGAL_SERV_FOUND;
! 215: }
! 216:
! 217: char str_srv_etheraddr[MAX_STR_MAC_LEN + 1];
! 218: bzero(str_srv_etheraddr, sizeof(str_srv_etheraddr));
! 219: etheraddr_bin_to_str(net_header.eth_head.ether_shost, str_srv_etheraddr);
! 220: /* Drop server with ethernet address in 'str_srv_etheraddr' */
! 221: int dropped = drop_dhcp_server(config, pcap_socket, str_srv_etheraddr);
! 222: if(config->quiet_mode)
! 223: printf("%d adresses received from DHCP server.\n", dropped);
! 224:
! 225: if(legal_nets_list(get_count, 0)) /* If set - use agressive mode */
! 226: {
! 227: if(!agressive_clean_leases(pcap_socket, config, &net_header,
! 228: &server_response, response_length))
! 229: {
! 230: if(hosts_list(get_count, 0, 0) > 1)
! 231: {
! 232: /* Ask user: "Restart dropping? [y/n]" */
! 233: char yN[2] = "n"; /* Default - don't restart */
! 234: (config->yes)? yN[0] = 'y' : (printf("Restart dropping? [y/n] "), scanf("%s", yN));
! 235: if((yN[0] == 'y') || (yN[0] == 'Y'))
! 236: {
! 237: printf("Restart dropping DHCP server after %d seconds timeout...\n", config->wait_before_restart);
! 238: sleep(config->wait_before_restart);
! 239: dropped = drop_dhcp_server(config, pcap_socket, str_srv_etheraddr);
! 240: if(config->quiet_mode)
! 241: printf("%d adresses received.\n", dropped);
! 242: if((dropped < (hosts_list(get_count, 0, NULL) - 1 + 1)) && /* -1 - itself DHCP server,
! 243: + 1 - start address */
! 244: !config->quiet_mode)
! 245: printf("%s\n", leases_warning);
! 246: }
! 247: }
! 248: }
! 249: }
! 250:
! 251: pcap_close(pcap_socket);
! 252:
! 253: return ILLEGAL_SERV_FOUND;
! 254: }
! 255:
! 256: void configure(const int argc, char **argv, struct config_params * params)
! 257: {
! 258: bzero(params, sizeof(struct config_params));
! 259: params->rand_mac_always = 1; /* Default - randomize source ethernet address */
! 260: params->max_attempts = MAX_ATTEMPTS; /* If == 0 - exit */
! 261: params->server_port = DEF_SERVER_PORT;
! 262: params->client_port = DEF_CLIENT_PORT;
! 263: params->max_hosts_scan = MAX_HOSTS_SCAN;
! 264: params->wait_before_restart = WAIT_BEFORE_RERUN;
! 265:
! 266: if(argc < 2)
! 267: usage(0);
! 268:
! 269: int i;
! 270: int ret;
! 271:
! 272: for(i = 1; i < argc; ++i)
! 273: {
! 274: /* t y r f b h m i c n N C l p P a A T D L M w S F R s*/
! 275: if(argv[i][0] == '-')
! 276: {
! 277: /*Parsing options without params*/
! 278: if(strlen(argv[i]) > 2)
! 279: usage(0);
! 280: switch(argv[i][1])
! 281: {
! 282: case 't':
! 283: params->test_mode = 1;
! 284: continue;
! 285: case 'y':
! 286: params->yes = 1;
! 287: continue;
! 288: case 'r':
! 289: params->rand_mac_always = 0;
! 290: continue;
! 291: case 'f':
! 292: params->flood = 1;
! 293: continue;
! 294: case 'b':
! 295: params->broadcast = 1;
! 296: continue;
! 297: case 'a':
! 298: params->always_wait_to_68 = 1;
! 299: continue;
! 300: case 'A':
! 301: params->always_wait_from_67 = 1;
! 302: continue;
! 303: case 'R':
! 304: params->send_dhcprelease = 1;
! 305: continue;
! 306: case 'q':
! 307: params->quiet_mode = 1;
! 308: continue;
! 309: case 'D':
! 310: params->discover = 1;
! 311: return;
! 312: case 'h':
! 313: usage(1);
! 314: break;
! 315: }
! 316: if(i + 1 >= argc)
! 317: usage(0);
! 318: if(argv[i + 1][0] == '-')
! 319: usage(0);
! 320:
! 321: /*Parsing options with params*/
! 322: switch(argv[i][1])
! 323: {
! 324: case 'm':
! 325: params->max_attempts = atoi(argv[i + 1]);
! 326: if(params->max_attempts < 1)
! 327: usage(0);
! 328: break;
! 329: case 'i':
! 330: params->if_name = argv[i + 1];
! 331: if(atoi(params->if_name) > 0)
! 332: {
! 333: params->if_name = interfaces_discover(atoi(params->if_name));
! 334: if(!params->if_name)
! 335: {
! 336: printf("Can't find device by index: '%s', use option '-D' for interface discover. Exit.\n",
! 337: argv[i + 1]);
! 338: exit(ERR_LISTING_DEV);
! 339: }
! 340: }
! 341: break;
! 342: case 'c':
! 343: params->max_address_count = atoi(argv[i + 1]);
! 344: if(params->max_address_count < 1)
! 345: usage(0);
! 346: break;
! 347: case 'n':
! 348: if(strlen(argv[i + 1]) > (sizeof(params->client_hostname) - 1))
! 349: {
! 350: printf("Client hostname too long.\n");
! 351: usage(0);
! 352: }
! 353: memcpy(params->client_hostname, argv[i + 1], strlen(argv[i + 1]));
! 354: break;
! 355: case 'N':
! 356: if(strlen(argv[i + 1]) > (sizeof(params->dhcp_client) - 1))
! 357: {
! 358: printf("DHCP client name too long.\n");
! 359: usage(0);
! 360: }
! 361: memcpy(params->dhcp_client, argv[i + 1], strlen(argv[i + 1]));
! 362: break;
! 363: case 'C':
! 364: params->children_count = atoi(argv[i + 1]);
! 365: if(params->children_count < 2 ||
! 366: params->children_count > MAX_CHILDREN)
! 367: usage(0);
! 368: break;
! 369: case 'p':
! 370: params->client_port = atoi(argv[i + 1]);
! 371: if(params->client_port < 1 || params->client_port > MAX_PORT_VALUE)
! 372: {
! 373: printf("Invalid DHCP client port value: '%s'\n", argv[i + 1]);
! 374: usage(0);
! 375: }
! 376: break;
! 377: case 'P':
! 378: params->server_port = atoi(argv[i + 1]);
! 379: if(params->server_port < 1 || params->server_port > MAX_PORT_VALUE)
! 380: {
! 381: printf("Invalid DHCP server port value: '%s'\n", argv[i + 1]);
! 382: usage(0);
! 383: }
! 384: break;
! 385: case 'l':
! 386: if(strlen(argv[i + 1]) > 17)
! 387: {
! 388: printf("Legal-server ethernet address too long.\n");
! 389: usage(0);
! 390: }
! 391: if(!ignor_servers_list(add, argv[i + 1]))
! 392: {
! 393: printf("Invalid legal-server ethernet address: '%s'\n", argv[i + 1]);
! 394: usage(0);
! 395: }
! 396: break;
! 397: case 'T':
! 398: params->timeout = atoi(argv[i + 1]);
! 399: if(params->timeout < 1)
! 400: {
! 401: printf("Invalid timeout value: '%s'\n", argv[i + 1]);
! 402: usage(0);
! 403: }
! 404: break;
! 405: case 'L':
! 406: {
! 407: if(strlen(argv[i + 1]) > MAX_IP4_ALEN) /* 3 = / + \d + d\. Sample: "/24" */
! 408: {
! 409: printf("Invalid legal network IP address: '%s'\n", argv[i + 1]);
! 410: usage(0);
! 411: }
! 412:
! 413: uint32_t net;
! 414: if( ( net = inet_addr(argv[i + 1])) == INADDR_NONE)
! 415: {
! 416: printf("Invalid legal network IP address: '%s'\n", argv[i + 1]);
! 417: usage(0);
! 418: }
! 419:
! 420: legal_nets_list(add, &net);
! 421:
! 422: break;
! 423: }
! 424: case 'M':
! 425: params->max_hosts_scan = atoi(argv[i + 1]);
! 426: if(params->max_hosts_scan < 4)
! 427: {
! 428: printf("Invalid maximum hosts scan value: %s. Minimum - 4.\n", argv[i + 1]);
! 429: usage(0);
! 430: }
! 431: break;
! 432: case 'w':
! 433: params->wait_before_restart = atoi(argv[i + 1]);
! 434: if(params->wait_before_restart < 1)
! 435: {
! 436: printf("Invalid 'wait before rerun' value: %s\n", argv[i + 1]);
! 437: usage(0);
! 438: }
! 439: break;
! 440: case 'S':
! 441: {
! 442: char network[MAX_IP4_ALEN + 3 + 1]; /* 3 - CIDR mask (/24 e.g.) 1 - \0 */
! 443: bzero(network, sizeof(network));
! 444:
! 445: if(strlen(argv[i + 1]) > (sizeof(network) - 1))
! 446: {
! 447: printf("Invalid network for scanning: %s - too long.\n", argv[i + 1]);
! 448: usage(0);
! 449: }
! 450:
! 451: strncpy(network, argv[i + 1], strlen(argv[i + 1]));
! 452:
! 453: char * mask = strrchr(network, '/');
! 454: if(!mask)
! 455: {
! 456: printf("Invalid network for scanning: %s - netmask not specified.\n", network);
! 457: usage(0);
! 458: }
! 459:
! 460: *mask = '\0'; /* Split network and netmask strings */
! 461: ++mask;
! 462:
! 463: if( (params->scanned_network = inet_addr(network)) == INADDR_NONE)
! 464: {
! 465: printf("Invalid network IP address for scanning: %s\n", network);
! 466: usage(0);
! 467: }
! 468:
! 469: params->scan_netmask = atoi(mask);
! 470: if( (params->scan_netmask < 0) || (params->scan_netmask > 30))
! 471: {
! 472: printf("Invalid netmask length: %s. Minimum - 0, maximum - 30.\n", mask);
! 473: usage(0);
! 474: }
! 475:
! 476: int bit_pos;
! 477: uint32_t netmask = 0;
! 478: for(bit_pos = 0; bit_pos < (32 - params->scan_netmask) ; ++bit_pos)
! 479: netmask |= 1 << bit_pos;
! 480: params->scan_netmask = htonl(~netmask);
! 481:
! 482: break;
! 483: }
! 484: case 'F':
! 485: {
! 486: if( (params->from_ip = inet_addr(argv[i + 1])) == INADDR_NONE)
! 487: {
! 488: printf("Invalid source IP address: %s\n", argv[i + 1]);
! 489: usage(0);
! 490: }
! 491: break;
! 492: }
! 493: case 's':
! 494: {
! 495: if( (params->server_ip = inet_addr(argv[i + 1])) == INADDR_NONE)
! 496: {
! 497: printf("Invalid server IP address: %s\n", argv[i + 1]);
! 498: usage(0);
! 499: }
! 500: break;
! 501: }
! 502: default:
! 503: usage(0);
! 504: break;
! 505: }
! 506: ++i;
! 507: }
! 508: else
! 509: {
! 510: if(strlen(argv[i]) > (sizeof(params->str_source_mac) - 1) )
! 511: {
! 512: printf("Length source MAC address too long. Exit.\n");
! 513: usage(0);
! 514: }
! 515: if(strlen(params->str_source_mac))
! 516: usage(0); /*Ethernet address already set*/
! 517: replace_semicolons(argv[i]);
! 518: strncat(params->str_source_mac, argv[i], MAX_STR_MAC_LEN);
! 519: }
! 520: }
! 521:
! 522: if(params->flood && params->test_mode)
! 523: {
! 524: printf("Error: option '-f' (flood) not compatible with option '-t' (test mode).\n");
! 525: usage(0);
! 526: }
! 527:
! 528: if(params->children_count && ! params->flood)
! 529: {
! 530: printf("Error: option '-C' (children count) compatible only with option '-f' (flood).\n");
! 531: usage(0);
! 532: }
! 533:
! 534: if(params->max_address_count > 255 && !params->rand_mac_always && !params->flood)
! 535: {
! 536: printf("Error: Option 'max address count' can't be greatest then 255 if you use option -r\n");
! 537: usage(0);
! 538: }
! 539:
! 540: if(!params->if_name)
! 541: usage(0);
! 542:
! 543: if(!strcmp("any", params->if_name))
! 544: {
! 545: printf("Can't drop DHCP server on 'any' device! Exit.\n");
! 546: exit(ERR_CONFIG);
! 547: }
! 548:
! 549: if( params->send_dhcprelease && (!params->server_ip ||
! 550: !params->from_ip || !strlen(params->str_source_mac)) )
! 551: {
! 552: printf("You must specify server IP address (use option -s), client IP address (use option -F)\n"
! 553: "\tand MAC address for sending DHCPRELEASE.\n");
! 554: usage(0);
! 555: }
! 556:
! 557: /* If not set initial MAC - set random value */
! 558: if(!strlen(params->str_source_mac))
! 559: rand_ether_addr(params->str_source_mac);
! 560: ret = etheraddr_str_to_bin(params->str_source_mac, params->source_mac);
! 561: if(!ret)
! 562: {
! 563: printf("Invalid parametrs in etheraddr_str_to_bin(). Aborting programm!");
! 564: abort();
! 565: }
! 566: if(ret < 0)
! 567: {
! 568: printf("Invalid source MAC address: '%s'\n", params->str_source_mac);
! 569: usage(0);
! 570: }
! 571:
! 572: if(! *params->client_hostname)
! 573: strncat(params->client_hostname, DEF_HOSTNAME, sizeof(params->client_hostname) - 1);
! 574: if(! *params->dhcp_client)
! 575: strncat(params->dhcp_client, DEF_DHCPCLIENT, sizeof(params->dhcp_client) - 1);
! 576: if( !params->max_address_count && !params->flood)
! 577: params->max_address_count = MAX_ADDR_COUNT;
! 578: if( !params->timeout)
! 579: params->timeout = DEF_TIMEOUT;
! 580: return;
! 581: }
! 582:
! 583: /*
! 584: If num == 0 - show all available interfaces and exit from programm.
! 585: Else - return name of interface by number 'num'
! 586: */
! 587: char * interfaces_discover(const int num)
! 588: {
! 589: if(!num)
! 590: printf("Available interfaces:\n");
! 591:
! 592: char errbuf[PCAP_ERRBUF_SIZE];
! 593: pcap_if_t *dev_list_start = 0, * dev_ptr = 0;
! 594: char * if_name = 0;
! 595: int32_t ret = pcap_findalldevs(&dev_list_start, errbuf);
! 596:
! 597: if(ret == -1)
! 598: {
! 599: printf("Error: %s\n", errbuf);
! 600: exit(ERR_LISTING_DEV);
! 601: }
! 602:
! 603: if(!dev_list_start)
! 604: {
! 605: printf("Error.\n");
! 606: exit(ERR_LISTING_DEV);
! 607: }
! 608:
! 609: int i = 1;
! 610: for(dev_ptr = dev_list_start; dev_ptr; dev_ptr = dev_ptr->next)
! 611: {
! 612: if(num)
! 613: {
! 614: if(!strcmp("any", dev_ptr->name))
! 615: continue;
! 616: if((i == num))
! 617: {
! 618: if_name = (char *) calloc(strlen(dev_ptr->name) + 1, sizeof(char));
! 619: if(!if_name)
! 620: {
! 621: printf("Can't allocate memory for interface '%s'. Quit.\n", dev_ptr->name);
! 622: exit(ERR_MEMORY);
! 623: }
! 624: strncpy(if_name, dev_ptr->name, strlen(dev_ptr->name));
! 625: pcap_freealldevs(dev_list_start);
! 626: return if_name;
! 627:
! 628: }
! 629: ++i;
! 630: }
! 631: else
! 632: {
! 633: if(strcmp("any", dev_ptr->name))
! 634: {
! 635: printf("%d:", i++);
! 636: ifprint(dev_ptr);
! 637: }
! 638: }
! 639: }
! 640:
! 641: pcap_freealldevs(dev_list_start);
! 642:
! 643: if(num) /* Suitable device not found */
! 644: return 0;
! 645:
! 646: exit(ERR_CONFIG);
! 647: }
! 648:
! 649: void send_flood(const struct config_params * params)
! 650: {
! 651: int i;
! 652: int ret_code;
! 653: struct flood_params par;
! 654: par.config = params;
! 655: #ifdef _WIN32
! 656: HANDLE threads[MAX_THREADS_COUNT]; /* Array of threads for DHCP senders */
! 657: DWORD th_id[MAX_THREADS_COUNT]; /* Array of threads identifiers */
! 658: par.flood_threads = threads;
! 659: par.threads_ids = th_id;
! 660: #endif
! 661:
! 662: if(params->children_count < 2)
! 663: {
! 664: if( (ret_code = start_flood((void*) &par) ) )
! 665: exit(ret_code);
! 666: return;
! 667: }
! 668: #ifdef _WIN32
! 669: printf("WARNING: multithread flood not effectively under OS Windows!\n");
! 670: #endif
! 671: printf("Create %d "CHILDREN_TYPE" for flood.\n", params->children_count);
! 672: for( i = 0; i < params->children_count; ++i)
! 673: new_child(&par, i);
! 674: printf("Waiting for all "CHILDREN_TYPE".\n");
! 675: wait_children(&par);
! 676: return;
! 677: }
! 678:
! 679: int get_dhcp_server(const struct config_params * config, /* Configuration parametrs. Can't be NULL */
! 680: pcap_t * pcap_socket, /* Pointer to pcap device. Can't be NULL */
! 681: struct dhcp_packet_net_header * net_header, /* Can't be NULL */
! 682: struct dhcp_packet * server_response, /* Function store DHCP response server here, */
! 683: /* can't be NULL */
! 684: uint16_t * response_length)
! 685: {
! 686: if(!pcap_socket || !server_response)
! 687: return ERR_ABNORMAL;
! 688:
! 689: char filter[PCAP_FILTER_LEN + 1]; /* filter for pcap_setfilter */
! 690: char str_ether_addr[MAX_STR_MAC_LEN + 1];
! 691:
! 692: bzero(filter, sizeof(filter));
! 693:
! 694: /* Create and set DHCP filter */
! 695: int ret;
! 696: if( (ret = make_serverdiscover_filter(filter, sizeof(filter) - 1, config, config->str_source_mac)) )
! 697: {
! 698: printf("Can't create DHCP filter.\n");
! 699: exit(ret);
! 700: }
! 701: /*printf("Filter: %s\n", filter);*/
! 702: if( (ret = set_pcap_filter(pcap_socket, filter)) )
! 703: {
! 704: printf("Can't set DHCP filter.\n");
! 705: exit(ret);
! 706: }
! 707:
! 708: int packet_len;
! 709:
! 710: int i;
! 711: uint32_t xid = rand();
! 712: for(i = 0; i < config->max_attempts; ++ i)
! 713: {
! 714: /* Sending DHCPDISCOVER */
! 715: if( (ret = send_dhcp_discover(pcap_socket, config, 0, xid)) )
! 716: return ret;
! 717: /* and waiting DHCPOFFER */
! 718: ret = get_dhcp_response(pcap_socket, config->timeout, DHCPOFFER, xid,
! 719: net_header, server_response, &packet_len);
! 720: if(!ret) /* DHCP server responded */
! 721: {
! 722: struct in_addr ip;
! 723: /* Trying to decode DHCP response */
! 724: if((ret = get_dhcp_option(server_response, packet_len,
! 725: DHO_DHCP_SERVER_IDENTIFIER, (void*)&ip.s_addr, sizeof(ip.s_addr))) < 1)
! 726: {
! 727: printf("Can't get DHCP server ID option!\n");
! 728: continue;
! 729: }
! 730:
! 731: if(ret < 0)
! 732: continue; /* Possible DoS */
! 733:
! 734: if(config->test_mode)
! 735: {
! 736: printf("DHCP SRV: %s ", inet_ntoa(ip));
! 737: ip.s_addr = net_header->ip_header.saddr;
! 738: printf("(IP-hdr: %s) SRV ether: ", inet_ntoa(ip));
! 739: print_ether(net_header->eth_head.ether_shost);
! 740: printf(", YIP: %s\n", inet_ntoa(server_response->yiaddr));
! 741: }
! 742: else
! 743: {
! 744: /* Convert server ethernet address to string */
! 745: bzero(str_ether_addr, sizeof(str_ether_addr));
! 746: etheraddr_bin_to_str(net_header->eth_head.ether_shost, str_ether_addr);
! 747: /* Print DHCP-info from packet */
! 748: printf("Got response from server %s ", inet_ntoa(ip));
! 749: ip.s_addr = net_header->ip_header.saddr;
! 750: printf("(IP-header %s), server ethernet address: ", inet_ntoa(ip));
! 751: print_ether(net_header->eth_head.ether_shost);
! 752: printf(", ");
! 753: uint32_t lease_time;
! 754: if(get_dhcp_option(server_response, packet_len, DHO_DHCP_LEASE_TIME,
! 755: (void*)&lease_time, sizeof(lease_time)) > 0)
! 756: printf("lease time: %.2gh (%us)\n", (float)ntohl(lease_time)/3600, ntohl(lease_time));
! 757:
! 758: decode_dhcp(server_response, packet_len);
! 759:
! 760: /* Ask user: "Drop him? [y/n]" */
! 761: char yN[2] = "n"; /* Default - don't drop */
! 762: (config->yes)? yN[0] = 'y' : (printf("Drop him? [y/n] "), scanf("%s", yN));
! 763: if((yN[0] != 'y') && (yN[0] != 'Y')) /* Don't drop this server */
! 764: {
! 765: /*Add DHCP server ethernet address in ignored list*/
! 766: ignor_servers_list(add, str_ether_addr);
! 767:
! 768: /* Reinit PCAP filter */
! 769: if( (ret = make_serverdiscover_filter(filter, sizeof(filter) - 1,
! 770: config, config->str_source_mac)) )
! 771: {
! 772: printf("Can't create DHCP filter.\n");
! 773: exit(ret);
! 774: }
! 775: /*printf("Filter: %s\n", filter);*/
! 776: if( (ret = set_pcap_filter(pcap_socket, filter)) )
! 777: {
! 778: printf("Can't set DHCP filter.\n");
! 779: exit(ret);
! 780: }
! 781:
! 782: /* Reinit DHCP server search loop */
! 783: i = -1;
! 784: if(!config->quiet_mode)
! 785: printf("Searching next server...\n");
! 786: continue;
! 787: }
! 788: *response_length = packet_len;
! 789: }
! 790: break;
! 791: }
! 792:
! 793: if(ret > 0)
! 794: exit(ret); /* Fatal error occured */
! 795:
! 796: if(!config->quiet_mode)
! 797: printf("Wait DHCPOFFER timeout. Resending DHCPDISCOVER.\n");
! 798: }
! 799:
! 800: if(ret < 0) /* DHCPDISCOVER timeout. Illegal server not found. */
! 801: return 0;
! 802:
! 803: return ILLEGAL_SERV_FOUND;
! 804: }
! 805:
! 806: int drop_dhcp_server(const struct config_params * config, pcap_t * pcap_socket,
! 807: const char * srv_etheraddr)
! 808: {
! 809: char filter[PCAP_FILTER_LEN + 1]; /* filter for pcap_setfilter */
! 810: uint8_t bin_src_etheraddr[ETH_ALEN];
! 811: char str_src_etheraddr[MAX_STR_MAC_LEN + 1];
! 812: struct dhcp_packet_net_header net_header;
! 813: struct dhcp_packet dhcp_resp;
! 814:
! 815: bzero(str_src_etheraddr, sizeof(str_src_etheraddr));
! 816:
! 817: strncat(str_src_etheraddr, config->str_source_mac, sizeof(str_src_etheraddr) - 1);
! 818: etheraddr_str_to_bin(str_src_etheraddr, bin_src_etheraddr);
! 819:
! 820: int ret;
! 821: int i;
! 822: int j;
! 823: int packet_len;
! 824: uint32_t xid;
! 825: int grab_ip_count = 0;
! 826:
! 827: /* Send DHCPDISCOVER(s) and wait response from DHCP server */
! 828: for(i = config->max_attempts; i > 0;)
! 829: {
! 830: bzero(filter, sizeof(filter));
! 831: /* Create and set filter for DHCP transaction */
! 832: if( (ret = make_serverdrop_filter(filter, sizeof(filter) - 1, config,
! 833: str_src_etheraddr, srv_etheraddr)) )
! 834: {
! 835: printf("Can't create pcap filter for dropping DHCP server! Exit.\n");
! 836: exit(ret);
! 837: }
! 838:
! 839: if( (ret = set_pcap_filter(pcap_socket, filter)) )
! 840: {
! 841: printf("Can't set DHCP filter.\n");
! 842: exit(ret);
! 843: }
! 844:
! 845: xid = rand();
! 846: /* Sending DHCPDISCOVER */
! 847: if( (ret = send_dhcp_discover(pcap_socket, config, bin_src_etheraddr, xid)) )
! 848: exit(ret);
! 849:
! 850: /* and waiting DHCPOFFER */
! 851: ret = get_dhcp_response(pcap_socket, config->timeout, DHCPOFFER, xid,
! 852: &net_header, &dhcp_resp, &packet_len);
! 853:
! 854: if(!ret) /* DHCP server responded */
! 855: {
! 856: uint32_t server_id;
! 857: if((ret = get_dhcp_option(&dhcp_resp, packet_len,
! 858: DHO_DHCP_SERVER_IDENTIFIER, (void*)&server_id, sizeof(server_id))) < 1)
! 859: {
! 860: printf("Can't get DHCP server ID option!\n");
! 861: continue;
! 862: }
! 863: if(ret < 0)
! 864: continue; /* Possible DoS */
! 865:
! 866: /* Trying to receive offered IP address */
! 867: for(j = 0; j < config->max_attempts; ++j)
! 868: {
! 869: /* Sendig DHCPREQUEST */
! 870: if( (ret = send_dhcp_request(pcap_socket, config, bin_src_etheraddr,
! 871: server_id, dhcp_resp.yiaddr.s_addr, xid)) )
! 872: exit(ret);
! 873:
! 874: /* and waiting DHCPACK */
! 875: ret = get_dhcp_response(pcap_socket, config->timeout, DHCPACK, xid,
! 876: &net_header, &dhcp_resp, &packet_len);
! 877: if(!ret) /* DHCP server responded */
! 878: {
! 879: ++grab_ip_count;
! 880: if(!config->quiet_mode)
! 881: {
! 882: printf("%d. ", grab_ip_count);
! 883: decode_dhcp(&dhcp_resp, packet_len);
! 884: }
! 885:
! 886: bzero(str_src_etheraddr, sizeof(str_src_etheraddr));
! 887:
! 888: if(config->rand_mac_always)
! 889: {
! 890: rand_ether_addr(str_src_etheraddr);
! 891: etheraddr_str_to_bin(str_src_etheraddr, bin_src_etheraddr);
! 892: }
! 893: else
! 894: {
! 895: ++bin_src_etheraddr[ETH_ALEN - 1];
! 896: etheraddr_bin_to_str(bin_src_etheraddr, str_src_etheraddr);
! 897: }
! 898:
! 899: i = config->max_attempts;
! 900: goto get_next_ip;
! 901: }
! 902:
! 903: if(ret > 0)
! 904: exit(ret); /* Fatal error occured */
! 905:
! 906: if(!config->quiet_mode)
! 907: printf("Wait DHCPACK timeout. Resending DHCPREQUEST.\n");
! 908: }
! 909: }
! 910:
! 911: if(ret > 0)
! 912: exit(ret); /* Fatal error occured */
! 913:
! 914: if(!config->quiet_mode)
! 915: printf("Wait DHCPOFFER timeout. Resending DHCPDISCOVER.\n");
! 916: --i;
! 917:
! 918: get_next_ip:;
! 919: if(grab_ip_count >= config->max_address_count)
! 920: break;
! 921: }
! 922: return grab_ip_count;
! 923: }
! 924:
! 925: int agressive_clean_leases(pcap_t * pcap_socket,
! 926: const struct config_params * config, struct dhcp_packet_net_header * srv_net_header,
! 927: const struct dhcp_packet * srv_resp, uint16_t resp_len)
! 928: {
! 929: if(!config->quiet_mode)
! 930: printf("Trying to use agressive mode.\n");
! 931:
! 932: uint32_t server_netmask;
! 933:
! 934: if(get_dhcp_option(srv_resp, resp_len, DHO_SUBNET_MASK, &server_netmask, sizeof(server_netmask)) < 1)
! 935: {
! 936: printf("Can't get netmask from DHCP packet.\n");
! 937: return -1;
! 938: }
! 939:
! 940: int lnets_count = legal_nets_list(get_count, 0);
! 941: uint32_t lnet, i;
! 942: for(i = 0; i < lnets_count; ++i)
! 943: {
! 944: lnet = legal_nets_list(by_index, &i);
! 945: if((srv_resp->yiaddr.s_addr & server_netmask) ==
! 946: (lnet & server_netmask))
! 947: {
! 948: printf("Can't use argessive mode because the network assigned "
! 949: "by DHCP server and the legal network are the same: %s/%d & ",
! 950: iptos(srv_resp->yiaddr.s_addr & server_netmask), to_cidr(server_netmask));
! 951: printf("%s/%d\n", iptos(lnet & server_netmask), to_cidr(server_netmask));
! 952: return -1;
! 953: }
! 954: }
! 955:
! 956:
! 957: /* Searching hosts in illegal network */
! 958:
! 959: uint32_t start_ip = ntohl(srv_resp->yiaddr.s_addr & server_netmask);
! 960:
! 961: if(!start_ip)
! 962: {
! 963: printf("Invalid IP address in DHCP server response: %s\n", inet_ntoa(srv_resp->yiaddr));
! 964: return -1;
! 965: }
! 966:
! 967: uint32_t end_ip = start_ip + (~ntohl(server_netmask));
! 968:
! 969: /* Check IP address range length */
! 970: if((end_ip - start_ip) > config->max_hosts_scan)
! 971: {
! 972: printf("Too long IP address scan range: %d. Maximum allowed scans: %d. "
! 973: "Use option -M for change this value.\n",
! 974: end_ip - start_ip, config->max_hosts_scan);
! 975: return -1;
! 976: }
! 977:
! 978: if(!config->quiet_mode)
! 979: {
! 980: printf("Starting ARP scanning network in range: %s - ", iptos(htonl(start_ip)));
! 981: printf("%s...\n", iptos(htonl(end_ip)));
! 982: }
! 983:
! 984: int ret = arp_scan(pcap_socket, start_ip, end_ip,
! 985: srv_resp->yiaddr.s_addr, srv_resp->chaddr);
! 986:
! 987: if(ret)
! 988: exit(ret);
! 989:
! 990: /* Now we have list of hosts with IP adresses assigned by illegal DHCP server */
! 991: int hosts_count = hosts_list(get_count, 0, NULL);
! 992: if(hosts_count < 2) /* Hosts with invalid IP addresses not found. 1 - itself DHCP server */
! 993: {
! 994: if(!config->quiet_mode)
! 995: printf("Hosts with invalid IP addresses not found.\n");
! 996: return 0;
! 997: }
! 998:
! 999: char ether_addr[MAX_STR_MAC_LEN + 1];
! 1000: bzero(ether_addr, sizeof(ether_addr));
! 1001: uint8_t bin_ethaddr[ETH_ALEN];
! 1002: uint32_t ip;
! 1003:
! 1004: printf("Illegal DHCP server perhaps assigned IP adresses to the following hosts:\n");
! 1005: for(i = 0; i < hosts_count; ++i)
! 1006: {
! 1007: ip = hosts_list(by_index, i, bin_ethaddr);
! 1008: etheraddr_bin_to_str(bin_ethaddr, ether_addr);
! 1009: printf("%d. Received ARP-reply from: %s (%s)%s", i + 1, ether_addr, iptos(ip),
! 1010: ((ip == srv_net_header->ip_header.saddr) &&
! 1011: !memcmp(srv_net_header->eth_head.ether_shost, bin_ethaddr, ETH_ALEN)
! 1012: )? " - itself DHCP server.\n" : "\n");
! 1013: }
! 1014:
! 1015: printf("Sending DHCPRELEASE for invalid clients:\n");
! 1016: for(i = 0; i < hosts_count; ++i)
! 1017: {
! 1018: ip = hosts_list(by_index, i, bin_ethaddr);
! 1019: if((ip == srv_net_header->ip_header.saddr) &&
! 1020: !memcmp(srv_net_header->eth_head.ether_shost, bin_ethaddr, ETH_ALEN))
! 1021: continue;
! 1022: etheraddr_bin_to_str(bin_ethaddr, ether_addr);
! 1023: printf("Send DHCPRELEASE for host %s (%s).\n", ether_addr, iptos(ip));
! 1024: if( (ret = send_dhcp_release(pcap_socket, config, bin_ethaddr,
! 1025: srv_net_header->ip_header.saddr, ip, rand())) )
! 1026: exit(ret);
! 1027: sleep(2);
! 1028: }
! 1029:
! 1030: return 0;
! 1031: }
! 1032:
! 1033: void scan_subnet(pcap_t * pcap_socket, uint32_t from_ip, const uint8_t * from_eth,
! 1034: const uint32_t network, const uint32_t netmask)
! 1035: {
! 1036: uint32_t start_ip = ntohl(network & netmask);
! 1037: uint32_t end_ip = start_ip + (~ntohl(netmask));
! 1038:
! 1039: printf("Starting ARP-scanning for subnet %s/%d.\n", iptos(htonl(start_ip & ntohl(netmask))),
! 1040: to_cidr(netmask));
! 1041:
! 1042: printf("IP address range %s - ", iptos(htonl(start_ip)));
! 1043: printf("%s.\n", iptos(htonl(end_ip)));
! 1044:
! 1045: if(!from_ip)
! 1046: {
! 1047: from_ip = htonl(start_ip + ((uint32_t) rand() % (end_ip - start_ip)));
! 1048: printf("WARNING: Source IP is not set (use option -F).\n"
! 1049: "Using random value for source IP address: %s\n", iptos(from_ip));
! 1050: }
! 1051:
! 1052: int ret = arp_scan(pcap_socket, start_ip, end_ip, from_ip, from_eth);
! 1053:
! 1054: /* Now we have list of hosts with IP adresses assigned by illegal DHCP server */
! 1055: int hosts_count = hosts_list(get_count, 0, NULL);
! 1056: char ether_addr[MAX_STR_MAC_LEN + 1];
! 1057: bzero(ether_addr, sizeof(ether_addr));
! 1058: uint8_t bin_ethaddr[ETH_ALEN];
! 1059: uint32_t ip;
! 1060: int i;
! 1061:
! 1062: for(i = 0; i < hosts_count; ++i)
! 1063: {
! 1064: ip = hosts_list(by_index, i, bin_ethaddr);
! 1065: etheraddr_bin_to_str(bin_ethaddr, ether_addr);
! 1066: printf("%d. Received ARP-reply from: %s (%s).\n", i + 1, ether_addr, iptos(ip));
! 1067: }
! 1068:
! 1069: if(ret)
! 1070: exit(ret);
! 1071: }
! 1072:
! 1073: int arp_scan(pcap_t * pcap_socket, const uint32_t start_range, const uint32_t end_range,
! 1074: uint32_t from_ip, const uint8_t * from_ether)
! 1075: {
! 1076: int ret;
! 1077:
! 1078: /* Set PCAP filter for receiving ARP packets for host 'from_ether'*/
! 1079: char str_from_ether[MAX_STR_MAC_LEN + 1];
! 1080: static char filter[PCAP_FILTER_LEN + 1];
! 1081:
! 1082: bzero(filter, sizeof(filter));
! 1083: bzero(str_from_ether, sizeof(str_from_ether));
! 1084:
! 1085: etheraddr_bin_to_str(from_ether, str_from_ether);
! 1086:
! 1087: if( (ret = make_arp_filter(filter, sizeof(filter) - 1, str_from_ether)) )
! 1088: {
! 1089: printf("Can't create ARP filter. Error code: %d.\n", ret);
! 1090: return ret;
! 1091: }
! 1092:
! 1093: if( (ret = set_pcap_filter(pcap_socket, filter)) )
! 1094: {
! 1095: printf("Can't set ARP filter.\n");
! 1096: return ret;
! 1097: }
! 1098:
! 1099: hosts_list(flush, 0, 0);
! 1100:
! 1101: /* Scanning network */
! 1102: int l;
! 1103: for(l = 0; l < 2; ++l)
! 1104: {
! 1105: uint32_t ip;
! 1106: for(ip = start_range; ip <= end_range; ++ip)
! 1107: {
! 1108: if( (ret = send_arpreq(pcap_socket, htonl(ip), from_ip, from_ether)) )
! 1109: {
! 1110: printf("Sending ARP packet error! Code: %d.\n", ret);
! 1111: return ret;
! 1112: }
! 1113:
! 1114: usleep(60);
! 1115:
! 1116: if( (ret = get_arpresps(pcap_socket, 0)) )
! 1117: {
! 1118: printf("Get ARP packet error! Code: %d.\n", ret);
! 1119: return ret;
! 1120: }
! 1121: }
! 1122: }
! 1123: /* Waiting for slow hosts */
! 1124: if( (ret = get_arpresps(pcap_socket, 2)) )
! 1125: {
! 1126: printf("Get ARP packet error! Code: %d.\n", ret);
! 1127: return ret;
! 1128: }
! 1129:
! 1130: return 0;
! 1131: }
! 1132:
! 1133: int get_arpresps(pcap_t * pcap_socket, int timeout)
! 1134: {
! 1135: uint8_t ether_packet[DHCP_MTU_MAX];
! 1136: struct arp_packet_net_header * arp_header;
! 1137:
! 1138: time_t timeout_time;
! 1139: int one_packet_timeout = timeout ? 1 : 0;
! 1140: if(timeout)
! 1141: timeout_time = time(0) + timeout;
! 1142:
! 1143: int ret;
! 1144: while(1)
! 1145: {
! 1146: if( (ret = get_packet(pcap_socket, ether_packet, one_packet_timeout)) < 0)
! 1147: return ERR_GETPACKET;
! 1148:
! 1149: if(ret)
! 1150: {
! 1151: arp_header = (struct arp_packet_net_header *) ether_packet;
! 1152: if(arp_header->arp_head.arp_oper == ARP_OP_RESP)
! 1153: {
! 1154: struct arp_data * arp_d = (struct arp_data *)
! 1155: (ether_packet + sizeof(struct arp_packet_net_header));
! 1156: hosts_list(add, arp_d->from_ip, arp_d->from_ether);
! 1157: }
! 1158: }
! 1159:
! 1160: if(!timeout)
! 1161: break;
! 1162:
! 1163: if(time(0) == timeout_time)
! 1164: break;
! 1165: }
! 1166:
! 1167: return 0;
! 1168: }
! 1169:
! 1170: int send_arpreq(pcap_t * pcap_socket, const uint32_t to_ip,
! 1171: const uint32_t from_ip, const uint8_t * from_ether)
! 1172: {
! 1173: static struct arp_data arp_d;
! 1174:
! 1175: memcpy(arp_d.from_ether, from_ether, ETH_ALEN);
! 1176: arp_d.from_ip = from_ip;
! 1177:
! 1178: memcpy(arp_d.to_ether, broadcast_ether, ETH_ALEN);
! 1179: arp_d.to_ip = to_ip;
! 1180:
! 1181: if(!send_packet(pcap_socket, arp_packet, (uint8_t *) &arp_d, sizeof(arp_d), 0, from_ether, 0))
! 1182: {
! 1183: pcap_close(pcap_socket);
! 1184: return ERR_SENDPACKET;
! 1185: }
! 1186: return 0;
! 1187: }
! 1188:
! 1189: #ifdef _WIN32
! 1190: BOOL WINAPI int_sign(DWORD signal)
! 1191: #else
! 1192: int int_sign(int32_t signal)
! 1193: #endif
! 1194: {
! 1195: if(signal == INTERRUPT_SIGNAL)
! 1196: {
! 1197: printf("Interrupted. Quit.\n");
! 1198: exit(EXIT_SUCCESS);
! 1199: }
! 1200: return 0;
! 1201: }
! 1202:
! 1203: #ifdef _WIN32
! 1204: unsigned __stdcall start_flood( void* arg )
! 1205: #else
! 1206: int start_flood( void* arg )
! 1207: #endif
! 1208: {
! 1209: flood_params_ptr par_ptr = (flood_params_ptr) arg;
! 1210: int j = 0, i;
! 1211: int ret;
! 1212:
! 1213: uint8_t src_ether[ETH_ALEN];
! 1214:
! 1215: int packets_count = par_ptr->config->max_address_count + ((par_ptr->config->max_address_count)? 0 : 1 );
! 1216:
! 1217: memcpy(src_ether, par_ptr->config->source_mac, sizeof(src_ether));
! 1218:
! 1219: pcap_t * pcap_socket = get_device(par_ptr->config);
! 1220:
! 1221: while( j < packets_count )
! 1222: { /* Sending DHCDISCOVER */
! 1223: if( (ret = send_dhcp_discover(pcap_socket, par_ptr->config, src_ether, 0)) )
! 1224: return ret;
! 1225:
! 1226: usleep(CAP_TIMEOUT);
! 1227:
! 1228: if(par_ptr->config->rand_mac_always) /* Randomize source ethernet address for next DHCPDISCOVER */
! 1229: {
! 1230: src_ether[0] = 0;
! 1231: for(i = 1; i < 6; ++i)
! 1232: src_ether[i] = rand();
! 1233: }
! 1234: if(par_ptr->config->max_address_count)
! 1235: ++j;
! 1236: }
! 1237: pcap_close(pcap_socket);
! 1238: return 0;
! 1239: }
! 1240:
! 1241:
! 1242: void new_child(const struct flood_params * p, const int child_num)
! 1243: {
! 1244: #ifdef _WIN32
! 1245: printf("Create thread #%d.\n", child_num + 1);
! 1246: p->flood_threads[child_num] = (HANDLE)_beginthreadex(NULL, 0, start_flood, (void*) p, 0,
! 1247: (uint32_t *) &p->threads_ids[child_num]);
! 1248:
! 1249: #else
! 1250: int pid;
! 1251: pid = fork();
! 1252: if(pid)
! 1253: printf("Create child #%d with pid %d.\n", child_num + 1, pid);
! 1254: else
! 1255: { /* Generate flood from child processes */
! 1256: exit(start_flood((void*) p));
! 1257: }
! 1258:
! 1259: #endif
! 1260: }
! 1261:
! 1262: void wait_children(const struct flood_params * p)
! 1263: {
! 1264: #ifdef _WIN32
! 1265: WaitForMultipleObjects(p->config->children_count, (HANDLE*) p->flood_threads, 1, INFINITE);
! 1266: #else
! 1267: int32_t pid;
! 1268: while( (pid = wait(0)) != -1)
! 1269: printf("Child with pid %d finished.\n", pid);
! 1270: #endif
! 1271: return;
! 1272: }
! 1273:
! 1274: int send_dhcp_discover(pcap_t * pcap_socket, const struct config_params * config,
! 1275: uint8_t * src_ether, const uint32_t xid)
! 1276: {
! 1277: /* Create DHCPDISCOVER */
! 1278: struct dhcp_packet dhcp_req;
! 1279:
! 1280: int dhcp_opt_len = make_dhcp_req(&dhcp_req, DHCPDISCOVER, src_ether ? src_ether : config->source_mac,
! 1281: 0, 0, xid, config);
! 1282: int snd_data_len = sizeof(struct dhcp_packet) - DHCP_OPTION_LEN + dhcp_opt_len;
! 1283: if(snd_data_len < BOOTP_MIN_LEN)
! 1284: snd_data_len = BOOTP_MIN_LEN;
! 1285:
! 1286: /* Send DHCPDISCOVER to DHCP server */
! 1287: if(!send_packet(pcap_socket, dhcp_packet, (uint8_t*) &dhcp_req,
! 1288: snd_data_len, config, src_ether ? src_ether : config->source_mac, 0))
! 1289: {
! 1290: printf("Can't send packet: %s\n", pcap_geterr(pcap_socket));
! 1291: pcap_close(pcap_socket);
! 1292: return ERR_SENDPACKET;
! 1293: }
! 1294:
! 1295: return 0;
! 1296: }
! 1297:
! 1298: int make_serverdiscover_filter(char * out_filter, const int max_filter_len,
! 1299: const struct config_params * config, const char * src_etheraddr)
! 1300: {
! 1301: if(!out_filter || !config)
! 1302: return ERR_ABNORMAL;
! 1303:
! 1304: /* Adding in pcap-filter all ignored servers */
! 1305: struct ignored_mac_node * ign_ptr = ignor_servers_list(get_top, 0);
! 1306:
! 1307: snprintf(out_filter, max_filter_len + 1,
! 1308: STR_SERVERDISCOVER_FILTER, src_etheraddr,
! 1309: (config->always_wait_from_67)? DEF_SERVER_PORT : config->server_port,
! 1310: (config->always_wait_to_68)? DEF_CLIENT_PORT : config->client_port
! 1311: );
! 1312:
! 1313: while(ign_ptr)
! 1314: {
! 1315: if(strlen(" and not ether src host ") +
! 1316: strlen(ign_ptr->mac_addr) +
! 1317: strlen(out_filter) > max_filter_len)
! 1318: {
! 1319: printf("Error! Filter owerflow.\n");
! 1320: return ERR_FILTER_OWERFLOW;
! 1321: }
! 1322:
! 1323: strncat(out_filter, " and not ether src host ", max_filter_len - strlen(out_filter));
! 1324: strncat(out_filter, ign_ptr->mac_addr, max_filter_len - strlen(out_filter));
! 1325: ign_ptr = ign_ptr->next;
! 1326: }
! 1327:
! 1328: return 0;
! 1329: }
! 1330:
! 1331: int make_arp_filter(char * out_filter, const int max_filter_len, const char * src_etheraddr)
! 1332: {
! 1333: if(!out_filter)
! 1334: return ERR_ABNORMAL;
! 1335:
! 1336: static const char arp_filter[] = "arp and ether dst ";
! 1337:
! 1338: if((strlen(arp_filter) + strlen(src_etheraddr)) > max_filter_len)
! 1339: return -1;
! 1340:
! 1341: strncpy(out_filter, arp_filter, max_filter_len);
! 1342: strncat(out_filter, src_etheraddr, max_filter_len - strlen(out_filter));
! 1343:
! 1344: return 0;
! 1345: }
! 1346:
! 1347: int make_serverdrop_filter(char * out_filter, const int max_filter_len,
! 1348: const struct config_params * config,
! 1349: const char * src_etheraddr, const char * server_ethaddr)
! 1350: {
! 1351: if(!out_filter || !config || !src_etheraddr || !server_ethaddr)
! 1352: return ERR_ABNORMAL;
! 1353:
! 1354: snprintf(out_filter, max_filter_len + 1, STR_SERVERDROP_FILTER, src_etheraddr,
! 1355: (config->always_wait_from_67)? DEF_SERVER_PORT : config->server_port,
! 1356: (config->always_wait_to_68)? DEF_CLIENT_PORT : config->client_port,
! 1357: server_ethaddr);
! 1358:
! 1359: return 0;
! 1360: }
! 1361:
! 1362:
! 1363: int set_pcap_filter(pcap_t * pcap_socket, char * filter_expression)
! 1364: {
! 1365: struct bpf_program fp;
! 1366: if(pcap_compile(pcap_socket, &fp, filter_expression, 1, 0) == -1)
! 1367: {
! 1368: printf("pcap_compile error: %s\nFilter expression is: '%s'\n",
! 1369: pcap_geterr(pcap_socket), filter_expression);
! 1370: pcap_close(pcap_socket);
! 1371: return ERR_PCAP_COMPILE;
! 1372: }
! 1373:
! 1374: if(pcap_setfilter(pcap_socket, &fp) == -1)
! 1375: {
! 1376: perror("pcap_setfilter");
! 1377: pcap_close(pcap_socket);
! 1378: return ERR_PCAP_SETFILTER;
! 1379: }
! 1380:
! 1381: pcap_freecode(&fp);
! 1382:
! 1383: return 0;
! 1384: }
! 1385:
! 1386: int send_dhcp_request(pcap_t * pcap_socket, const struct config_params * config,
! 1387: uint8_t * src_ether, /* Pseudo-client source ethernet address. Can't be NULL */
! 1388: const uint32_t server_ip_address, /* DHCP server IP address. Can't be NULL */
! 1389: const uint32_t req_ip_addr, /* Required client IP address. Can't be NULL */
! 1390: const int32_t xid
! 1391: )
! 1392: {
! 1393: if(!pcap_socket || !config || !src_ether || !server_ip_address || !req_ip_addr)
! 1394: return ERR_ABNORMAL;
! 1395:
! 1396: /* Create DHCPREQUEST */
! 1397: struct dhcp_packet dhcp_req;
! 1398:
! 1399: int dhcp_opt_len = make_dhcp_req(&dhcp_req, DHCPREQUEST, src_ether,
! 1400: server_ip_address, req_ip_addr, xid, config);
! 1401:
! 1402: int snd_data_len = sizeof(struct dhcp_packet) - DHCP_OPTION_LEN + dhcp_opt_len;
! 1403: if(snd_data_len < BOOTP_MIN_LEN)
! 1404: snd_data_len = BOOTP_MIN_LEN;
! 1405:
! 1406: /* Send DHCPREQUEST to DHCP server */
! 1407: if(!send_packet(pcap_socket, dhcp_packet, (uint8_t*) &dhcp_req,
! 1408: snd_data_len, config, src_ether ? src_ether : config->source_mac, 0))
! 1409: {
! 1410: printf("Can't send packet: %s\n", pcap_geterr(pcap_socket));
! 1411: pcap_close(pcap_socket);
! 1412: return ERR_SENDPACKET;
! 1413: }
! 1414:
! 1415: return 0;
! 1416: }
! 1417:
! 1418: int send_dhcp_release(pcap_t * pcap_socket, const struct config_params * config,
! 1419: const uint8_t * src_ether, /* Pseudo-client source ethernet address. Can't be NULL */
! 1420: const uint32_t server_ip_address, /* DHCP server IP address. Can't be NULL */
! 1421: const uint32_t cl_ip_addr, /* Released client IP address. Can't be NULL */
! 1422: const int32_t xid
! 1423: )
! 1424: {
! 1425: if(!pcap_socket || !config || !src_ether || !server_ip_address || !cl_ip_addr)
! 1426: return ERR_ABNORMAL;
! 1427:
! 1428: /* Create DHCPREQUEST */
! 1429: struct dhcp_packet dhcp_req;
! 1430:
! 1431: int dhcp_opt_len = make_dhcp_req(&dhcp_req, DHCPRELEASE, src_ether,
! 1432: server_ip_address, cl_ip_addr, xid, config);
! 1433:
! 1434: int snd_data_len = sizeof(struct dhcp_packet) - DHCP_OPTION_LEN + dhcp_opt_len;
! 1435: if(snd_data_len < BOOTP_MIN_LEN)
! 1436: snd_data_len = BOOTP_MIN_LEN;
! 1437:
! 1438: /* Send DHCPREQUEST to DHCP server */
! 1439: if(!send_packet(pcap_socket, dhcp_packet, (uint8_t*) &dhcp_req,
! 1440: snd_data_len, config, src_ether ? src_ether : config->source_mac, server_ip_address))
! 1441: {
! 1442: printf("Can't send packet: %s\n", pcap_geterr(pcap_socket));
! 1443: pcap_close(pcap_socket);
! 1444: return ERR_SENDPACKET;
! 1445: }
! 1446:
! 1447: return 0;
! 1448: }
! 1449:
! 1450: int get_dhcp_response(pcap_t * pcap_socket, const int timeout, const uint8_t resp_type,
! 1451: const uint32_t xid, struct dhcp_packet_net_header * net_header,
! 1452: struct dhcp_packet * response, int * dhcp_data_len)
! 1453: {
! 1454: uint8_t ether_packet[DHCP_MTU_MAX];
! 1455: struct dhcp_packet_net_header * dhcp_net_header;
! 1456: struct dhcp_packet *dhcp_resp;
! 1457: uint8_t dhcp_msg_type;
! 1458:
! 1459: const int max_errors = 10;
! 1460: int errors = 0;
! 1461:
! 1462: while(1)
! 1463: {
! 1464: if(errors == max_errors)
! 1465: break;
! 1466:
! 1467: int ret = get_packet(pcap_socket, ether_packet, timeout);
! 1468:
! 1469: if(ret < 0)
! 1470: return ERR_GETPACKET;
! 1471:
! 1472: if(!ret)
! 1473: return -1; /* Timeout - server not respond */
! 1474:
! 1475: /* Analysing packet */
! 1476: dhcp_net_header = (struct dhcp_packet_net_header *) ether_packet;
! 1477: dhcp_resp = (struct dhcp_packet *) (ether_packet + sizeof(struct dhcp_packet_net_header));
! 1478:
! 1479: *dhcp_data_len = ntohs(dhcp_net_header->udp_header.len)
! 1480: - sizeof(struct udphdr); /* UDP data length equal DHCP-packet length */
! 1481:
! 1482: if(*dhcp_data_len > DHCP_MAX_LEN)
! 1483: {
! 1484: printf("UDP data len too long (%u bytes)! Attempting DoS?\n", *dhcp_data_len);
! 1485: ++errors;
! 1486: continue;
! 1487: }
! 1488:
! 1489: if(
! 1490: (dhcp_resp->op != BOOTREPLY) ||
! 1491: (get_dhcp_option(dhcp_resp, *dhcp_data_len, DHO_DHCP_MESSAGE_TYPE,
! 1492: (void*)&dhcp_msg_type, sizeof(dhcp_msg_type)) < 1) ||
! 1493: (dhcp_msg_type != resp_type) ||
! 1494: (dhcp_resp->xid != xid)
! 1495: )
! 1496: {
! 1497: ++errors;
! 1498: continue;
! 1499: }
! 1500:
! 1501: memcpy(net_header, ether_packet, sizeof(struct dhcp_packet_net_header));
! 1502: memcpy(response, dhcp_resp, *dhcp_data_len);
! 1503: return 0;
! 1504: }
! 1505:
! 1506: return -1;
! 1507: }
! 1508:
! 1509:
! 1510: struct ignored_mac_node * ignor_servers_list(enum list_operations operation, char * ether_addr)
! 1511: {
! 1512: if(ether_addr)
! 1513: {
! 1514: replace_semicolons(ether_addr);
! 1515: int hex;
! 1516: if(sscanf(ether_addr, "%x:%x:%x:%x:%x:%x",
! 1517: &hex, &hex, &hex, &hex, &hex, &hex) < 6) /* Invalid format! */
! 1518: return 0;
! 1519: }
! 1520:
! 1521: static struct ignored_mac_node * ignored_list_top = 0;
! 1522:
! 1523: switch(operation)
! 1524: {
! 1525: case add:
! 1526: {
! 1527: if(!ether_addr || (strlen(ether_addr) < MIN_STR_MAC_LEN))
! 1528: return 0;
! 1529:
! 1530: struct ignored_mac_node * new_node =
! 1531: (struct ignored_mac_node *) malloc(sizeof(struct ignored_mac_node));
! 1532:
! 1533: if(! new_node)
! 1534: {
! 1535: printf("Can't allocate memory for legal DHCP server ethernet address! Exit.");
! 1536: exit(ERR_MEMORY);
! 1537: }
! 1538:
! 1539: bzero(new_node, sizeof(struct ignored_mac_node));
! 1540: strncpy(new_node->mac_addr, ether_addr, sizeof(new_node->mac_addr) - 1);
! 1541: new_node->next = ignored_list_top;
! 1542: ignored_list_top = new_node;
! 1543: return ignored_list_top;
! 1544: }
! 1545: break;
! 1546: case rem:
! 1547: {
! 1548: struct ignored_mac_node * node_ptr = ignored_list_top;
! 1549: while(node_ptr)
! 1550: {
! 1551: if(!strncmp(node_ptr->mac_addr, ether_addr, sizeof(node_ptr->mac_addr) - 1))
! 1552: {
! 1553: struct ignored_mac_node * removed = node_ptr;
! 1554: node_ptr = node_ptr->next;
! 1555: free(removed);
! 1556: return ignored_list_top;
! 1557: }
! 1558: else
! 1559: node_ptr = node_ptr->next;
! 1560: }
! 1561: }
! 1562: break;
! 1563: case get_top:
! 1564: return ignored_list_top;
! 1565: case search:
! 1566: {
! 1567: struct ignored_mac_node * node_ptr = ignored_list_top;
! 1568: while(node_ptr)
! 1569: if(!strncmp(node_ptr->mac_addr, ether_addr, sizeof(node_ptr->mac_addr) - 1))
! 1570: return ignored_list_top;
! 1571: else
! 1572: node_ptr = node_ptr->next;
! 1573: }
! 1574: break;
! 1575: case flush:
! 1576: {
! 1577: struct ignored_mac_node * next_node;
! 1578: while(ignored_list_top)
! 1579: {
! 1580: next_node = ignored_list_top->next;
! 1581: free(ignored_list_top);
! 1582: ignored_list_top = next_node;
! 1583: }
! 1584: return ignored_list_top;
! 1585: }
! 1586: break;
! 1587: default:
! 1588: break;
! 1589: }
! 1590: return 0;
! 1591: }
! 1592:
! 1593: uint32_t legal_nets_list(enum list_operations operation, const uint32_t * value)
! 1594: {
! 1595: static uint32_t * legal_nets = 0;
! 1596: static int count = 0;
! 1597: static int capacity = 0;
! 1598:
! 1599: switch(operation)
! 1600: {
! 1601: case get_count:
! 1602: return count;
! 1603: case add:
! 1604: if(!capacity)
! 1605: {
! 1606: capacity = 4;
! 1607: if( !(legal_nets = (uint32_t *) malloc(sizeof(uint32_t) * capacity)) )
! 1608: {
! 1609: printf("Can't allocate memory for legal networks! Exit.\n");
! 1610: exit(ERR_MEMORY);
! 1611: }
! 1612: }
! 1613:
! 1614: if(count == capacity)
! 1615: {
! 1616: capacity *= 2;
! 1617: if( !(legal_nets = (uint32_t*) realloc(legal_nets, capacity)))
! 1618: {
! 1619: printf("Can't reallocate memory for legal networks! Exit.\n");
! 1620: exit(ERR_MEMORY);
! 1621: }
! 1622: }
! 1623:
! 1624: legal_nets[count] = *value;
! 1625: ++count;
! 1626: break;
! 1627: case by_index:
! 1628: return legal_nets[*value];
! 1629: case flush:
! 1630: count = 0;
! 1631: capacity = 0;
! 1632: if(legal_nets)
! 1633: free(legal_nets);
! 1634: break;
! 1635: default:
! 1636: printf("Unknown operation on legal nets.\n");
! 1637: break;
! 1638: }
! 1639: return count;
! 1640: }
! 1641:
! 1642: int hosts_list(enum list_operations operation, uint32_t ip_addr, uint8_t * ether_addr)
! 1643: {
! 1644: struct invalid_host
! 1645: {
! 1646: uint8_t ether_addr[ETH_ALEN];
! 1647: uint32_t ip_addr;
! 1648: };
! 1649:
! 1650: static struct invalid_host * hosts_list = 0;
! 1651: static int count = 0;
! 1652: static int capacity = 0;
! 1653:
! 1654: switch(operation)
! 1655: {
! 1656: case get_count:
! 1657: return count;
! 1658: case add:
! 1659: {
! 1660: int i;
! 1661: for(i = 0; i < count; ++i)
! 1662: if(!memcmp(hosts_list[i].ether_addr, ether_addr, sizeof(hosts_list[i].ether_addr)) &&
! 1663: (hosts_list[i].ip_addr == ip_addr)) /* Dupe */
! 1664: return 0;
! 1665:
! 1666: if(!capacity)
! 1667: {
! 1668: capacity = 4;
! 1669: if(! (hosts_list = (struct invalid_host* ) malloc(sizeof(struct invalid_host) * capacity)) )
! 1670: {
! 1671: printf("Can't allocate memory for invalid hosts list! Exit.\n");
! 1672: exit(ERR_MEMORY);
! 1673: }
! 1674: }
! 1675:
! 1676: if(count == capacity)
! 1677: {
! 1678: capacity *= 2;
! 1679: if( !(hosts_list = (struct invalid_host *) realloc(hosts_list, sizeof(struct invalid_host) * capacity)))
! 1680: {
! 1681: printf("Can't reallocate memory for invalid hosts list! Exit.\n");
! 1682: exit(ERR_MEMORY);
! 1683: }
! 1684: }
! 1685:
! 1686: memcpy(hosts_list[count].ether_addr, ether_addr, sizeof(hosts_list[count].ether_addr));
! 1687: hosts_list[count].ip_addr = ip_addr;
! 1688: ++count;
! 1689: }
! 1690: break;
! 1691: case by_index:
! 1692: if( (ip_addr < 0) || (ip_addr > (count - 1)) )
! 1693: return -1;
! 1694:
! 1695: memcpy(ether_addr, hosts_list[ip_addr].ether_addr, sizeof(hosts_list[ip_addr].ether_addr));
! 1696: return hosts_list[ip_addr].ip_addr;
! 1697: case flush:
! 1698: capacity = 0;
! 1699: count = 0;
! 1700: if(hosts_list)
! 1701: free(hosts_list);
! 1702: break;
! 1703: default:
! 1704: printf("Unknown operations on invalid hostst list.\n");
! 1705: break;
! 1706: }
! 1707:
! 1708: return 0;
! 1709: }
! 1710:
! 1711: void cleanup(void)
! 1712: {
! 1713: ignor_servers_list(flush, 0);
! 1714: legal_nets_list(flush, 0);
! 1715: hosts_list(flush, 0, 0);
! 1716: }
! 1717:
! 1718:
! 1719: int decode_dhcp(const struct dhcp_packet * packet, const uint16_t packet_len)
! 1720: {
! 1721: uint8_t dhcp_msg_type;
! 1722: switch(packet->op)
! 1723: {
! 1724: case BOOTREQUEST: printf("Got BOOTREQUEST("); break;
! 1725: case BOOTREPLY: printf("Got BOOTREPLY ("); break;
! 1726: default: printf("Unknown message type: %u\n", packet->op); return 0;
! 1727: }
! 1728: if(get_dhcp_option(packet, packet_len, DHO_DHCP_MESSAGE_TYPE,
! 1729: (void*)&dhcp_msg_type, sizeof(dhcp_msg_type)) < 1)
! 1730: {
! 1731: printf("Error: Can't get DHCP message type.\n");
! 1732: return 0;
! 1733: }
! 1734:
! 1735: switch(dhcp_msg_type)
! 1736: {
! 1737: case DHCPDISCOVER: printf("DHCPDISCOVER) "); break;
! 1738: case DHCPOFFER: printf("DHCPOFFER) "); break;
! 1739: case DHCPREQUEST: printf("DHCPREQUEST) "); break;
! 1740: case DHCPDECLINE: printf("DHCPDECLINE) "); break;
! 1741: case DHCPACK: printf("DHCPACK) "); break;
! 1742: case DHCPNAK: printf("DHCPNAK) "); break;
! 1743: case DHCPRELEASE: printf("DHCPRELEASE) "); break;
! 1744: case DHCPINFORM: printf("DHCPINFORM) "); break;
! 1745: default: printf("Unknown DHCP message type: %u)\n", dhcp_msg_type);
! 1746: }
! 1747:
! 1748: if(packet->flags && htons(BOOTP_BROADCAST))
! 1749: printf("flags: BROADCAST ");
! 1750: printf("for client ether: ");
! 1751: print_ether(packet->chaddr);
! 1752:
! 1753: uint32_t netmask = 0;
! 1754: printf(" You IP: %s", inet_ntoa(packet->yiaddr));
! 1755: if(get_dhcp_option(packet, packet_len, DHO_SUBNET_MASK, (void*)&netmask, sizeof(netmask)) < 1)
! 1756: printf("\n");
! 1757: else
! 1758: printf("/%d\n", to_cidr(netmask));
! 1759:
! 1760: return dhcp_msg_type;
! 1761: }
! 1762:
! 1763: void usage(const char help)
! 1764: {
! 1765: (help)? printf("%s\n%s\n%s", usage_message, keys, ret_codes) : printf("%s", usage_message);
! 1766: printf("\n%s\n", COPYRIGHT HOMEPAGE);
! 1767: if(!help)
! 1768: printf("Use option -h for help. Exit.\n");
! 1769: exit(ERR_CONFIG);
! 1770: }
! 1771:
! 1772: /* Convert network mask to CIDR notation */
! 1773: uint32_t to_cidr(uint32_t mask)
! 1774: {
! 1775: mask = ntohl(mask);
! 1776: int i;
! 1777: for(i = 0; i < 33; ++i)
! 1778: if(mask & (1 << i))
! 1779: break;
! 1780: return (i == 33)? 0 : 32 - i;
! 1781: }
! 1782:
! 1783: /* Convert a numeric IP address to a string */
! 1784: char *iptos(const uint32_t in)
! 1785: {
! 1786: static char output[IPTOSBUFFERS][3*4 + 3 + 1];
! 1787: static short which;
! 1788: uint8_t *p;
! 1789:
! 1790: p = (uint8_t *)∈
! 1791: which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
! 1792: snprintf(output[which], sizeof(output), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
! 1793: return output[which];
! 1794: }
! 1795:
! 1796: void ifprint(const pcap_if_t *dev)
! 1797: {
! 1798: pcap_addr_t *pcap_addr;
! 1799: /* Name */
! 1800: printf("%s", dev->name);
! 1801: /* Description */
! 1802: if (dev->description)
! 1803: printf("\n descr: %s", dev->description);
! 1804: /* IP addresses */
! 1805: for(pcap_addr = dev->addresses; pcap_addr; pcap_addr = pcap_addr->next)
! 1806: {
! 1807: if(!pcap_addr->addr)
! 1808: continue;
! 1809: switch(pcap_addr->addr->sa_family)
! 1810: {
! 1811: case AF_INET:
! 1812: if (pcap_addr->addr)
! 1813: printf("\n iaddr: %s", iptos(((struct sockaddr_in *)pcap_addr->addr)->sin_addr.s_addr));
! 1814: if (pcap_addr->netmask)
! 1815: printf("/%d ", to_cidr(((struct sockaddr_in *)pcap_addr->netmask)->sin_addr.s_addr));
! 1816: if (pcap_addr->broadaddr)
! 1817: printf(" bcast: %s",iptos(((struct sockaddr_in *)pcap_addr->broadaddr)->sin_addr.s_addr));
! 1818: if (pcap_addr->dstaddr)
! 1819: printf(" dst addr: %s",iptos(((struct sockaddr_in *)pcap_addr->dstaddr)->sin_addr.s_addr));
! 1820: break;
! 1821: case AF_INET6:
! 1822: break;
! 1823:
! 1824: default:
! 1825: break;
! 1826: }
! 1827: }
! 1828: printf("\n");
! 1829: }
! 1830:
! 1831: inline int etheraddr_bin_to_str(const uint8_t * bin_addr, char * str_addr)
! 1832: {
! 1833: if(!bin_addr || !str_addr)
! 1834: return 0;
! 1835: snprintf(str_addr, MAX_STR_MAC_LEN + 1, "%02x:%02x:%02x:%02x:%02x:%02x",
! 1836: bin_addr[0], bin_addr[1], bin_addr[2], bin_addr[3], bin_addr[4], bin_addr[5]);
! 1837: return 1;
! 1838: }
! 1839:
! 1840: int etheraddr_str_to_bin(const char * str_addr, uint8_t * bin_addr)
! 1841: {
! 1842: if(!str_addr || !bin_addr)
! 1843: return 0;
! 1844:
! 1845: static char ether_addr[MAX_STR_MAC_LEN + 1]; /* Non-const buffer for strtok */
! 1846: bzero(ether_addr, sizeof(ether_addr));
! 1847: strncpy(ether_addr, str_addr, sizeof(ether_addr) - 1);
! 1848:
! 1849: int i = 0;
! 1850: int byte;
! 1851: char * bytePtr = strtok(ether_addr, ":-");
! 1852: while(bytePtr)
! 1853: {
! 1854: if(i > 5)
! 1855: return -1; /* Ethernet address consist from 6 bytes! */
! 1856:
! 1857: if(strlen(bytePtr) > 2)
! 1858: return -1; /* Too long digit */
! 1859:
! 1860: if(sscanf(bytePtr, "%02x", &byte) < 1)
! 1861: return -1; /* Invalid HEX digit */
! 1862:
! 1863: bin_addr[i++] = (uint8_t) byte;
! 1864: bytePtr = strtok(NULL, ":-");
! 1865: }
! 1866: if(i < 6)
! 1867: return -1; ; /* Ethernet address consist from 6 bytes! */
! 1868: return 1;
! 1869: }
! 1870:
! 1871: inline void replace_semicolons(char * str_ether)
! 1872: {
! 1873: char * p = str_ether;
! 1874: while(*p)
! 1875: {
! 1876: if(*p == '-')
! 1877: *p = ':';
! 1878: ++p;
! 1879: }
! 1880: }
! 1881:
! 1882: inline void print_ether(const uint8_t * ether_addr)
! 1883: {
! 1884: int i;
! 1885: for(i = 0; i < ETH_ALEN; ++i)
! 1886: printf((i == (ETH_ALEN - 1) ) ? "%02X" :"%02X:", ether_addr[i]);
! 1887: }
! 1888:
! 1889: inline void rand_ether_addr(char * str_mac_addr) /* Minimal size of str_mac_addr must be STR_MAC_LEN (18) */
! 1890: {
! 1891: /* Fill first byte */
! 1892: strncat(str_mac_addr, "00:", 3);
! 1893: char * p = str_mac_addr + strlen(str_mac_addr);
! 1894: int i;
! 1895: for(i = 0; i < 5; ++i, p +=3) /* Randomize next 5 bytes */
! 1896: snprintf(p, 4, (i < 4)? ("%02X:") : "%02X", (int)(rand() & 0xFF));
! 1897: return;
! 1898: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>