static void test_address_get_if_addrs(void *arg) { int rv; uint32_t addr_h = 0; tor_addr_t tor_addr; (void)arg; rv = get_interface_address(LOG_ERR, &addr_h); /* When the network is down, a system might not have any non-local * non-multicast IPv4 addresses, not even internal ones. * Unit tests shouldn't fail because of this. */ if (rv == 0) { tor_addr_from_ipv4h(&tor_addr, addr_h); tt_assert(!tor_addr_is_loopback(&tor_addr)); tt_assert(!tor_addr_is_multicast(&tor_addr)); /* The address may or may not be an internal address */ tt_assert(tor_addr_is_v4(&tor_addr)); } done: return; }
/****************************************************************************** * get_control_sock - see net.h *****************************************************************************/ int get_control_sock (void) { //The socket that will listen for control connections from the client. int csfd; //Variables used to collect the IPv4 address of the server. char *interfaceSetting = "INTERFACE_CONFIG"; //ftp.conf setting char *interfaceResult; //value of the ftp.conf setting char interfaceAddr[INET_ADDRSTRLEN]; //Variables used to collect the default port. char *portSetting = "DEFAULT_PORT_CONFIG"; //ftp.conf setting char *portResult; //Read the config file for the default port. if ((portResult = get_config_value (portSetting, FTP_CONFIG_FILE)) == NULL) { return -1; } //Read the config file to find which interface to use to make the socket. if ((interfaceResult = get_config_value (interfaceSetting, FTP_CONFIG_FILE)) == NULL) { return -1; } /* Get the IPv4 address for the interface that was set in the configuration * file.*/ if (get_interface_address (interfaceResult, &interfaceAddr) == -1) { free (interfaceResult); free (portResult); return -1; } free (interfaceResult); /* Create a control connection socket that is ready to accept a connection * from the client. */ if ((csfd = get_pasv_sock (interfaceAddr, portResult)) == -1) { return -1; } free (portResult); return csfd; }
static void test_address_get_if_addrs_internal_fail(void *arg) { smartlist_t *results1 = NULL, *results2 = NULL; int rv = 0; uint32_t ipv4h_addr = 0; tor_addr_t ipv6_addr; memset(&ipv6_addr, 0, sizeof(tor_addr_t)); (void)arg; MOCK(get_interface_addresses_raw, mock_get_interface_addresses_raw_fail); MOCK(get_interface_address6_via_udp_socket_hack, mock_get_interface_address6_via_udp_socket_hack_fail); results1 = get_interface_address6_list(LOG_ERR, AF_INET6, 1); tt_ptr_op(results1, OP_NE, NULL); tt_int_op(smartlist_len(results1),OP_EQ,0); results2 = get_interface_address_list(LOG_ERR, 1); tt_ptr_op(results2, OP_NE, NULL); tt_int_op(smartlist_len(results2),OP_EQ,0); rv = get_interface_address6(LOG_ERR, AF_INET6, &ipv6_addr); tt_int_op(rv, OP_EQ, -1); rv = get_interface_address(LOG_ERR, &ipv4h_addr); tt_int_op(rv, OP_EQ, -1); done: UNMOCK(get_interface_addresses_raw); UNMOCK(get_interface_address6_via_udp_socket_hack); interface_address6_list_free(results1); interface_address6_list_free(results2); return; }
GDHCPServer *g_dhcp_server_new(GDHCPType type, int ifindex, GDHCPServerError *error) { GDHCPServer *dhcp_server = NULL; if (ifindex < 0) { *error = G_DHCP_SERVER_ERROR_INVALID_INDEX; return NULL; } dhcp_server = g_try_new0(GDHCPServer, 1); if (!dhcp_server) { *error = G_DHCP_SERVER_ERROR_NOMEM; return NULL; } dhcp_server->interface = get_interface_name(ifindex); if (!dhcp_server->interface) { *error = G_DHCP_SERVER_ERROR_INTERFACE_UNAVAILABLE; goto error; } if (!interface_is_up(ifindex)) { *error = G_DHCP_SERVER_ERROR_INTERFACE_DOWN; goto error; } dhcp_server->server_nip = get_interface_address(ifindex); if (dhcp_server->server_nip == 0) { *error = G_DHCP_SERVER_ERROR_IP_ADDRESS_INVALID; goto error; } dhcp_server->nip_lease_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); dhcp_server->option_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); dhcp_server->started = FALSE; /* All the leases have the same fixed lease time, * do not support DHCP_LEASE_TIME option from client. */ dhcp_server->lease_seconds = DEFAULT_DHCP_LEASE_SEC; dhcp_server->type = type; dhcp_server->ref_count = 1; dhcp_server->ifindex = ifindex; dhcp_server->listener_sockfd = -1; dhcp_server->listener_watch = -1; dhcp_server->listener_channel = NULL; dhcp_server->save_lease_func = NULL; dhcp_server->save_ack_lease_func = NULL; dhcp_server->debug_func = NULL; dhcp_server->debug_data = NULL; *error = G_DHCP_SERVER_ERROR_NONE; return dhcp_server; error: g_free(dhcp_server->interface); g_free(dhcp_server); return NULL; }
int main(int argc, char *argv[]) { int get_tmp = 1, get_cmd; if(argc < 3) { print_help(argv[0]); exit(2); } int option_index = 0; static struct option long_options[] = { { "mac", required_argument, 0, 'm' }, { "interface", required_argument, 0, 'i' }, { "vlan", required_argument, 0, 'v' }, { "dhcp_xid", required_argument, 0, 'x' }, { "tos", required_argument, 0, 't' }, { "option51-lease_time", required_argument, 0, 'L' }, { "option50-ip", required_argument, 0, 'I' }, { "option60-vci", required_argument, 0, 'o' }, { "option12-hostname", required_argument, 0, 'h' }, { "timeout", required_argument, 0, 'T' }, { "bind-ip", no_argument, 0, 'b' }, { "bind-timeout", required_argument, 0, 'k' }, { "bcast_flag", no_argument, 0, 'f'}, { "verbose", no_argument, 0, 'V'}, { "fqdn-server-not-update", no_argument, 0, 'n'}, { "fqdn-server-update-a", no_argument, 0, 's'}, { "fqdn-domain-name", required_argument, 0, 'd'}, { "padding", no_argument, 0, 'p'}, { "port", required_argument, 0, 'P'}, { "giaddr", required_argument, 0, 'g'}, { "unicast", optional_argument, 0, 'u'}, { "nagios", no_argument, 0, 'a'}, { "server", required_argument, 0, 'S'}, { "release", no_argument, 0, 'r'}, { 0, 0, 0, 0 } }; /*getopt routine to get command line arguments*/ while(get_tmp < argc) { get_cmd = getopt_long(argc, argv, "m:i:v:t:bfVrpansu::T:P:g:S:I:o:k:L:h:d:",\ long_options, &option_index); if(get_cmd == -1 ) { break; } switch(get_cmd) { case 'm': { u_char aux_dhmac[ETHER_ADDR_LEN + 1]; if(strlen(optarg) > 18) { fprintf(stdout, "Invalid mac address\n"); exit(2); } strcpy(dhmac_fname, optarg); sscanf((char *)optarg, "%2X:%2X:%2X:%2X:%2X:%2X", (u_int32_t *) &aux_dhmac[0], (u_int32_t *) &aux_dhmac[1], (u_int32_t *) &aux_dhmac[2], (u_int32_t *) &aux_dhmac[3], (u_int32_t *) &aux_dhmac[4], (u_int32_t *) &aux_dhmac[5]); memcpy(dhmac, aux_dhmac, sizeof(dhmac)); dhmac_flag = 1; } break; case 'i': iface = if_nametoindex(optarg); if(iface == 0) { fprintf(stdout, "Interface doesnot exist\n"); exit(2); } strncpy(iface_name, optarg, 29); break; case 'v': if(atoi(optarg) < 1 || atoi(optarg) > 4095) { fprintf(stdout, "VLAN ID is not valid. Range 1 to 4095\n"); exit(2); } vlan = atoi(optarg); l2_hdr_size = 18; break; case 'r': dhcp_release_flag = 1; break; case 'b': ip_listen_flag = 1; break; case 'k': listen_timeout = atoi(optarg); tval_listen.tv_sec = listen_timeout; break; case 'x': { u_int32_t aux_dhcp_xid[2]; aux_dhcp_xid[0] = 0; sscanf((char *)optarg, "%X", &aux_dhcp_xid[0]); dhcp_xid = aux_dhcp_xid[0]; } break; case 't': if(atoi(optarg) >= 256 || atoi(optarg) < 0) { fprintf(stdout, "Invalid TOS value\n"); exit(2); } l3_tos = atoi(optarg); break; case 'L': option51_lease_time = atoi(optarg); break; case 'I': option50_ip = inet_addr(optarg); break; case 'o': if(strlen(optarg) > 256) { fprintf(stdout, "VCI string size should be less than 256\n"); exit(2); } vci_flag = 1; memcpy(vci_buff, optarg, sizeof(vci_buff)); break; case 'h': if(strlen(optarg) > 256) { fprintf(stdout, "Hostname string size should be less than 256\n"); exit(2); } hostname_flag = 1; memcpy(hostname_buff, optarg, sizeof(hostname_buff)); break; case 'd': if(strlen(optarg) > 256) { fprintf(stdout, "FQDN domain name string size should be less than 256\n"); exit(2); } fqdn_flag = 1; memcpy(fqdn_buff, optarg, sizeof(fqdn_buff)); break; case 'n': fqdn_n = 1; break; case 's': fqdn_s = 1; break; case 'T': if(atoi(optarg) < 5 || atoi(optarg) > 3600) { fprintf(stdout, "Invalid timout value. Range 5 to 3600\n"); exit(2); } timeout = atoi(optarg); break; case 'P': if(atoi(optarg) <=0 || atoi(optarg) > 65535) { fprintf(stdout, "Invalid portt value. Range 1 to 65535\n"); exit(2); } port = atoi(optarg); break; case 'g': giaddr = optarg; break; case 'S': server_addr = optarg; break; case 'p': padding_flag = 1; break; case 'f': bcast_flag = htons(0x8000); break; case 'V': verbose = 1; break; case 'u': if (optarg) { struct in_addr out; if (!inet_aton(optarg, &out)) { fprintf(stdout, "Invalid unicast IP address."); exit(2); } unicast_ip_address = out.s_addr; } unicast_flag = 1; break; case 'a': nagios_flag = 1; break; default: exit(2); } get_tmp++; } if(!dhmac_flag) { print_help(argv[0]); exit(2); } /* Opens the PF_PACKET socket */ if(open_socket() < 0) { if (nagios_flag) fprintf(stdout, "CRITICAL: Socket error."); else fprintf(stdout, "Socket error\n"); exit(2); } /* Sets the promiscuous mode */ set_promisc(); if (unicast_flag && !unicast_ip_address) { unicast_ip_address = get_interface_address(); } /* Sets a random DHCP xid */ set_rand_dhcp_xid(); /* * If DHCP release flag is set, send DHCP release packet * and exit. get_dhinfo parses the DHCP info from log file * and unlinks it from the system */ if(dhcp_release_flag) { if(get_dhinfo() == ERR_FILE_OPEN) { if (nagios_flag) { fprintf(stdout, "CRITICAL: Error on opening DHCP info file."); } else { fprintf(stdout, "Error on opening DHCP info file\n"); fprintf(stdout, "Release the DHCP IP after acquiring\n"); } exit(2); } build_option53(DHCP_MSGRELEASE); /* Option53 DHCP release */ if(hostname_flag) { build_option12_hostname(); } if(fqdn_flag) { build_option81_fqdn(); } build_option54(); /* Server id */ build_optioneof(); /* End of option */ build_dhpacket(DHCP_MSGRELEASE); /* Build DHCP release packet */ send_packet(DHCP_MSGRELEASE); /* Send DHCP release packet */ clear_promisc(); /* Clear the promiscuous mode */ close_socket(); return 0; } if(timeout) { time_last = time(NULL); } build_option53(DHCP_MSGDISCOVER); /* Option53 for DHCP discover */ if(hostname_flag) { build_option12_hostname(); } if(fqdn_flag) { build_option81_fqdn(); } if(option50_ip) { build_option50(); /* Option50 - req. IP */ } if(option51_lease_time) { build_option51(); /* Option51 - DHCP lease time requested */ } if(vci_flag == 1) { build_option60_vci(); /* Option60 - VCI */ } build_optioneof(); /* End of option */ build_dhpacket(DHCP_MSGDISCOVER); /* Build DHCP discover packet */ int dhcp_offer_state = 0; while(dhcp_offer_state != DHCP_OFFR_RCVD) { /* Sends DHCP discover packet */ send_packet(DHCP_MSGDISCOVER); /* * recv_packet functions returns when the specified * packet is received */ dhcp_offer_state = recv_packet(DHCP_MSGOFFER); if(timeout) { time_now = time(NULL); if((time_now - time_last) > timeout) { if (nagios_flag) fprintf(stdout, "CRITICAL: Timeout reached: DISCOVER."); close_socket(); exit(2); } } if(dhcp_offer_state == DHCP_OFFR_RCVD) { if (!nagios_flag) fprintf(stdout, "DHCP offer received\t - "); set_serv_id_opt50(); if (!nagios_flag) fprintf(stdout, "Offered IP : %s\n", get_ip_str(dhcph_g->dhcp_yip)); if(!nagios_flag && verbose) { print_dhinfo(DHCP_MSGOFFER); } } } /* Reset the dhopt buffer to build DHCP request options */ reset_dhopt_size(); build_option53(DHCP_MSGREQUEST); build_option50(); build_option54(); if(hostname_flag) { build_option12_hostname(); } if(fqdn_flag) { build_option81_fqdn(); } if(vci_flag == 1) { build_option60_vci(); } if(option51_lease_time) { build_option51(); /* Option51 - DHCP lease time requested */ } build_option55(); build_optioneof(); build_dhpacket(DHCP_MSGREQUEST); /* Builds specified packet */ int dhcp_ack_state = 1; while(dhcp_ack_state != DHCP_ACK_RCVD) { send_packet(DHCP_MSGREQUEST); dhcp_ack_state = recv_packet(DHCP_MSGACK); if(timeout) { time_now = time(NULL); if((time_now - time_last) > timeout) { if (nagios_flag) fprintf(stdout, "CRITICAL: Timeout reached: REQUEST."); else fprintf(stdout, "Timeout reached. Exiting\n"); close_socket(); exit(1); } } if(dhcp_ack_state == DHCP_ACK_RCVD) { if (nagios_flag) { fprintf(stdout, "OK: Acquired IP: %s", get_ip_str(dhcph_g->dhcp_yip)); } else { fprintf(stdout, "DHCP ack received\t - "); fprintf(stdout, "Acquired IP: %s\n", get_ip_str(dhcph_g->dhcp_yip)); } /* Logs DHCP IP details to log file. This file is used for DHCP release */ log_dhinfo(); if(!nagios_flag && verbose) { print_dhinfo(DHCP_MSGACK); } } else if (dhcp_ack_state == DHCP_NAK_RCVD) { if (!nagios_flag) { fprintf(stdout, "DHCP nack received\t - "); fprintf(stdout, "Client MAC : %02x:%02x:%02x:%02x:%02x:%02x\n", \ dhmac[0], dhmac[1], dhmac[2], dhmac[3], dhmac[4], dhmac[5]); } } } /* If IP listen flag is enabled, Listen on obtained for ARP, ICMP protocols */ if(!nagios_flag && ip_listen_flag) { fprintf(stdout, "\nListening on %s for ARP and ICMP protocols\n", iface_name); fprintf(stdout, "IP address: %s, Listen timeout: %d seconds\n", get_ip_str(htonl(ip_address)), listen_timeout); int arp_icmp_rcv_state = 0; while(arp_icmp_rcv_state != LISTEN_TIMOUET) { arp_icmp_rcv_state = recv_packet(ARP_ICMP_RCV); /* Send ARP reply if ARP request received */ if(arp_icmp_rcv_state == ARP_RCVD) { /*if(verbose) { fprintf(stdout, "ARP request received\n"); fprintf(stdout, "Sending ARP reply\n"); }*/ build_packet(ARP_SEND); send_packet(ARP_SEND); } else if(arp_icmp_rcv_state == ICMP_RCVD) { /* Send ICMP reply if ICMP echo request received */ /*if(verbose) { fprintf(stdout, "ICMP request received\n"); fprintf(stdout, "Sending ICMP reply\n"); }*/ build_packet(ICMP_SEND); send_packet(ICMP_SEND); } } fprintf(stdout, "Listen timout reached\n"); } /* Clear the promiscuous mode */ clear_promisc(); /* Close the socket */ close_socket(); return 0; }
/****************************************************************************** * cmd_pasv - see net.h *****************************************************************************/ int cmd_pasv (session_info_t *si) { //The setting to be searched for in the config file. char *interfaceSetting = "INTERFACE_CONFIG"; //The value for the setting that was searched for in the config file. char *interfaceResult; //The IPv4 address of the configuration file interface. char interfaceAddr[INET_ADDRSTRLEN]; int csfd = si->csfd; //Ensure the client has logged in. if (!si->loggedin) { send_mesg_530 (csfd, REPLY_530_REQUEST); return -1; } /* The server "MUST" close the data connection port when: * "The port specification is changed by a command from the user". * Source: RFC 959 page 19 */ if (si->dsfd > 0) { if (close (si->dsfd) == -1) fprintf (stderr, "%s: close: %s\n", __FUNCTION__, strerror (errno)); si->dsfd = 0; } //Read the config file to find which interface to use to make the socket. if ((interfaceResult = get_config_value (interfaceSetting, FTP_CONFIG_FILE)) == NULL) { return -1; } /* Get the IPv4 address for the interface specified in the configuration * file. Free the interface string, it is no longer required. */ if (get_interface_address (interfaceResult, &interfaceAddr) == -1) { free (interfaceResult); return -1; } free (interfaceResult); //Create a socket that will listen for a data connection from a client. if ((si->dsfd = get_pasv_sock (interfaceAddr, NULL)) == -1) { return -1; } //Send the data connection address information to the control socket. if (send_mesg_227 (csfd, si->dsfd) == -1) { close (si->dsfd); si->dsfd = 0; return -1; } //Accept a connection from the client on the listening socket. if ((si->dsfd = accept_connection (si->dsfd, ACCEPT_PASV, si)) == -1) { si->dsfd = 0; return -1; } return si->dsfd; }
int main(int argc, char *argv[]) { int get_tmp = 1, get_cmd; int dhinfo_ret; if(argc < 3) { print_help(argv[0]); exit(2); } init_rand(); atexit(cleanup); signal(SIGSEGV, sigcleanup); signal(SIGABRT, sigcleanup); signal(SIGTERM, sigcleanup); signal(SIGINT, sigcleanup); signal(SIGHUP, sigcleanup); int option_index = 0; static struct option long_options[] = { { "mac", required_argument, 0, 'm' }, { "random-mac", no_argument, 0, 'R' }, { "log-filename", required_argument, 0, 'F' }, { "interface", required_argument, 0, 'i' }, { "vlan", required_argument, 0, 'v' }, { "dhcp_xid", required_argument, 0, 'x' }, { "tos", required_argument, 0, 't' }, { "option51-lease_time", required_argument, 0, 'L' }, { "option50-ip", required_argument, 0, 'I' }, { "option60-vci", required_argument, 0, 'o' }, { "option12-hostname", required_argument, 0, 'h' }, { "timeout", required_argument, 0, 'T' }, { "bind-ip", no_argument, 0, 'b' }, { "bind-timeout", required_argument, 0, 'k' }, { "bcast_flag", no_argument, 0, 'f'}, { "verbose", no_argument, 0, 'V'}, { "fqdn-server-not-update", no_argument, 0, 'n'}, { "fqdn-server-update-a", no_argument, 0, 's'}, { "fqdn-domain-name", required_argument, 0, 'd'}, { "padding", no_argument, 0, 'p'}, { "port", required_argument, 0, 'P'}, { "giaddr", required_argument, 0, 'g'}, { "unicast", optional_argument, 0, 'u'}, { "nagios", no_argument, 0, 'a'}, { "server", required_argument, 0, 'S'}, { "release", no_argument, 0, 'r'}, { "quiet", no_argument, 0, 'q'}, { "request-only", no_argument, 0, 'Q'}, { 0, 0, 0, 0 } }; /*getopt routine to get command line arguments*/ while(get_tmp < argc) { get_cmd = getopt_long(argc, argv, "m:Ri:v:t:bfVrpansu::T:P:g:S:I:o:k:L:h:d:F:qQ",\ long_options, &option_index); if(get_cmd == -1 ) { break; } switch(get_cmd) { case 'q': quiet = 1; break; case 'm': { u_char aux_dhmac[ETHER_ADDR_LEN + 1]; if(strlen(optarg) != 17 || sscanf(optarg, ETH_F_FMT, ETH_F_PARG(aux_dhmac)) != 6 ) { fprintf(stderr, "Invalid mac address\n"); exit(2); } memcpy(dhmac, aux_dhmac, sizeof(dhmac)); dhmac_flag = 1; } break; case 'R': { int i; for (i = 0; i < ETHER_ADDR_LEN; i++) dhmac[i] = rand() & 0xff; /* clear multicast bit, set the L bit, clear MSB */ dhmac[0] &= ~0x81; dhmac[0] |= 0x02; dhmac_flag = 1; } break; case 'F': if (strlen(optarg) > sizeof(dhmac_fname) - 1) { fprintf(stderr, "-F filename given is too long\n"); exit(2); } strcpy(dhmac_fname, optarg); dhmac_fname_flag = 1; break; case 'i': iface_name = optarg; break; case 'v': if(atoi(optarg) < 1 || atoi(optarg) > 4095) { fprintf(stderr, "VLAN ID is not valid. Range 1 to 4095\n"); exit(2); } vlan = atoi(optarg); l2_hdr_size = 18; break; case 'r': dhcp_release_flag = 1; break; case 'Q': dhcp_request_flag = 1; break; case 'b': ip_listen_flag = 1; break; case 'k': listen_timeout = atoi(optarg); tval_listen.tv_sec = listen_timeout; break; case 'x': { u_int32_t aux_dhcp_xid[2]; aux_dhcp_xid[0] = 0; sscanf((char *)optarg, "%X", &aux_dhcp_xid[0]); dhcp_xid = aux_dhcp_xid[0]; } break; case 't': if(atoi(optarg) >= 256 || atoi(optarg) < 0) { fprintf(stderr, "Invalid TOS value\n"); exit(2); } l3_tos = atoi(optarg); break; case 'L': option51_lease_time = atoi(optarg); break; case 'I': option50_ip = inet_addr(optarg); break; case 'o': if(strlen(optarg) >= 256) { fprintf(stderr, "VCI string size should be less than 256\n"); exit(2); } vci_flag = 1; vci_buff = optarg; break; case 'h': if(strlen(optarg) >= 256) { fprintf(stderr, "Hostname string size should be less than 256\n"); exit(2); } hostname_flag = 1; hostname_buff = optarg; break; case 'd': if(strlen(optarg) >= 253) { fprintf(stderr, "FQDN domain name string size should be less than 253\n"); exit(2); } fqdn_flag = 1; fqdn_buff = optarg; break; case 'n': fqdn_n = 1; break; case 's': fqdn_s = 1; break; case 'T': if(atoi(optarg) < 5 || atoi(optarg) > 3600) { fprintf(stderr, "Invalid timout value. Range 5 to 3600\n"); exit(2); } timeout = atoi(optarg); break; case 'P': if(atoi(optarg) <=0 || atoi(optarg) > 65535) { fprintf(stderr, "Invalid port value. Range 1 to 65535\n"); exit(2); } port = atoi(optarg); break; case 'g': giaddr = optarg; break; case 'S': server_addr = optarg; break; case 'p': padding_flag = 1; break; case 'f': bcast_flag = htons(0x8000); break; case 'V': verbose = 1; break; case 'u': if (optarg) { struct in_addr out; if (!inet_aton(optarg, &out)) { fprintf(stderr, "Invalid unicast IP address."); exit(2); } unicast_ip_address = out.s_addr; } unicast_flag = 1; break; case 'a': nagios_flag = 1; break; default: exit(2); } get_tmp++; } if(!dhmac_flag) { print_help(argv[0]); exit(2); } if (!dhmac_fname_flag) sprintf(dhmac_fname, ETH_F_FMT, ETH_F_ARG(dhmac)); dhinfo_ret = get_dhinfo(); iface = if_nametoindex(iface_name); if(iface == 0) { fprintf(stderr, "Interface %s does not exist\n", iface_name); exit(2); } /* Opens the PF_PACKET socket */ if(open_socket() < 0) critical("Socket error: %m"); /* Sets the promiscuous mode */ set_promisc(); if (unicast_flag && !unicast_ip_address) { unicast_ip_address = get_interface_address(); } /* Sets a random DHCP xid */ set_rand_dhcp_xid(); time_now = time_last = time(NULL); /* * If DHCP release flag is set, send DHCP release packet * and exit. get_dhinfo parses the DHCP info from log file * and unlinks it from the system */ if(dhcp_release_flag) { if(dhinfo_ret) critical("Error on opening DHCP info file: %s", strerror(dhinfo_ret)); if (!server_id) critical("Can't release IP without an active lease"); build_option53(DHCP_MSGRELEASE); /* Option53 DHCP release */ if(hostname_flag) { build_option12_hostname(); } if(fqdn_flag) { build_option81_fqdn(); } build_option54(); /* Server id */ build_optioneof(); /* End of option */ build_dhpacket(DHCP_MSGRELEASE); /* Build DHCP release packet */ send_packet(DHCP_MSGRELEASE); /* Send DHCP release packet */ /* update status file: we no longer have our IP address */ log_dhinfo(); return 0; } if (dhcp_request_flag) { if(dhinfo_ret) critical("Error on opening DHCP info file: %s", strerror(dhinfo_ret)); if (!server_id) critical("Can't refresh IP without an active lease"); /* Clients begin to attempt to renew their leases once half the lease interval has expired. */ if (lease_expires_at - time_now > option51_lease_time / 2) return 0; goto request; } build_option53(DHCP_MSGDISCOVER); /* Option53 for DHCP discover */ if(hostname_flag) { build_option12_hostname(); } if(fqdn_flag) { build_option81_fqdn(); } if(option50_ip) { build_option50(); /* Option50 - req. IP */ } if(option51_lease_time) { build_option51(); /* Option51 - DHCP lease time requested */ } if(vci_flag == 1) { build_option60_vci(); /* Option60 - VCI */ } build_optioneof(); /* End of option */ build_dhpacket(DHCP_MSGDISCOVER); /* Build DHCP discover packet */ int dhcp_offer_state = 0; while(dhcp_offer_state != DHCP_OFFR_RCVD) { /* Sends DHCP discover packet */ send_packet(DHCP_MSGDISCOVER); /* * recv_packet functions returns when the specified * packet is received */ dhcp_offer_state = recv_packet(DHCP_MSGOFFER); if(timeout) { time_now = time(NULL); if((time_now - time_last) > timeout) critical("Timeout reached: DISCOVER"); } if(dhcp_offer_state == DHCP_OFFR_RCVD) { if (!nagios_flag && !quiet) printf("DHCP offer received\t - "); set_serv_id_opt50(); if (!nagios_flag && !quiet) printf("Offered IP : %s\n", get_ip_str(dhcph_g->dhcp_yip)); if(!nagios_flag && verbose) { print_dhinfo(DHCP_MSGOFFER); } } } request: /* Reset the dhopt buffer to build DHCP request options */ reset_dhopt_size(); build_option53(DHCP_MSGREQUEST); build_option50(); build_option54(); if(hostname_flag) { build_option12_hostname(); } if(fqdn_flag) { build_option81_fqdn(); } if(vci_flag == 1) { build_option60_vci(); } if(option51_lease_time) { build_option51(); /* Option51 - DHCP lease time requested */ } build_option55(); build_optioneof(); build_dhpacket(DHCP_MSGREQUEST); /* Builds specified packet */ int dhcp_ack_state = 1; while(dhcp_ack_state != DHCP_ACK_RCVD) { send_packet(DHCP_MSGREQUEST); dhcp_ack_state = recv_packet(DHCP_MSGACK); if(timeout) { time_now = time(NULL); if((time_now - time_last) > timeout) critical("Timeout reached: REQUEST"); } if(dhcp_ack_state == DHCP_ACK_RCVD) { if (nagios_flag) { printf("OK: Acquired IP: %s", get_ip_str(dhcph_g->dhcp_yip)); } else if (!quiet) { printf("DHCP ack received\t - "); printf("Acquired IP: %s\n", get_ip_str(dhcph_g->dhcp_yip)); } else { /* quiet */ printf("%s\n", get_ip_str(dhcph_g->dhcp_yip)); } /* Logs DHCP IP details to log file. This file is used for DHCP release */ log_dhinfo(); if(!nagios_flag && verbose) { print_dhinfo(DHCP_MSGACK); } } else if (dhcp_ack_state == DHCP_NAK_RCVD) { if (!nagios_flag && !quiet) { printf("DHCP nack received\t - "); printf("Client MAC : %02x:%02x:%02x:%02x:%02x:%02x\n", \ dhmac[0], dhmac[1], dhmac[2], dhmac[3], dhmac[4], dhmac[5]); } } } /* If IP listen flag is enabled, Listen on obtained for ARP, ICMP protocols */ if(!nagios_flag && ip_listen_flag) { if (!quiet) { printf("\nListening on %s for ARP and ICMP protocols\n", iface_name); printf("IP address: %s, Listen timeout: %d seconds\n", get_ip_str(htonl(ip_address)), listen_timeout); } int arp_icmp_rcv_state = 0; while(arp_icmp_rcv_state != LISTEN_TIMEOUT) { arp_icmp_rcv_state = recv_packet(ARP_ICMP_RCV); /* Send ARP reply if ARP request received */ if(arp_icmp_rcv_state == ARP_RCVD) { /*if(verbose) { printf("ARP request received\n"); printf("Sending ARP reply\n"); }*/ build_packet(ARP_SEND); send_packet(ARP_SEND); } else if(arp_icmp_rcv_state == ICMP_RCVD) { /* Send ICMP reply if ICMP echo request received */ /*if(verbose) { printf("ICMP request received\n"); printf("Sending ICMP reply\n"); }*/ build_packet(ICMP_SEND); send_packet(ICMP_SEND); } } printf("Listen timout reached\n"); } return 0; }