Annotation of embedaddon/dhcdrop/src/dhcdrop.c, revision 1.1.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>