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