File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcdrop / src / dhcdrop.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:25:35 2012 UTC (13 years, 4 months ago) by misho
Branches: dhcdrop, MAIN
CVS tags: v0_5, HEAD
dhcdrop

    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 *)&in;
 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>