Пример #1
0
int main(int argc, char *argv[])
{
	int get_tmp = 1, get_cmd;

	if(argc < 3) {
	print_help(argv[0]);
	exit(1);
	}

	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' },
	{ "option12-name", required_argument, 0, 'n' },
	{ "option51-lease_time", required_argument, 0, 'L' },
	{ "option50-ip", required_argument, 0, 'I' },
	{ "option60-vci", required_argument, 0, 'o' },
	{ "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'},
	{ "write-log", no_argument, 0, 'W'},
	{ "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:bfVWrT:I:o:k:L:n:",\
		long_options, &option_index);
	if(get_cmd == -1 ) {
		break;
	}
	switch(get_cmd) {
		case 'm':
		if(strlen(optarg) > 18) {
			fprintf(stdout, "Invalid mac address\n");
			exit(1);
		}
		strcpy(dhmac_fname, optarg);
		sscanf((char *)optarg, "%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX", &dhmac[0], \
		&dhmac[1], &dhmac[2], &dhmac[3], &dhmac[4], &dhmac[5]);
		dhmac_flag = 1;
		break;

		case 'i':
		iface = if_nametoindex(optarg);
		if(iface == 0) {
			fprintf(stdout, "Interface doesnot exist\n");
			exit(1);
		}
		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(1);
		}
		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':
		sscanf((char *)optarg, "%X", &dhcp_xid);
		break;

		case 't':
		if(atoi(optarg) >= 256 || atoi(optarg) < 0) {
			fprintf(stdout, "Invalid TOS value\n");
			exit(1);
		}
		l3_tos = atoi(optarg);
		break;

		case 'L':
		option51_lease_time = atoi(optarg);
		break;

		case 'I':
		option50_ip = inet_addr(optarg);
		break;

		case 'n':
		strncpy(option12_name, optarg, sizeof(option12_name));
		break;

		case 'o':
		if(strlen(optarg) > 256) {
			fprintf(stdout, "VCI string size should be less than 256\n");
			exit(1);
		}
		vci_flag = 1;
		memcpy(vci_buff, optarg, sizeof(vci_buff));
		break;

		case 'T':
		if(atoi(optarg) < 5 || atoi(optarg) > 3600) {
			fprintf(stdout, "Invalid timout value. Range 5 to 3600\n");
			exit(1);
		}
		timeout = atoi(optarg);
		break;

		case 'f':
			bcast_flag = htons(0x8000);
		break;

		case 'V':
		verbose = 1;
		break;

		case 'W':
		writelog = 1;
		break;

		default:
		exit(1);
	}
	get_tmp++;
	}

	if(!dhmac_flag) {
	print_help(argv[0]);
	exit(1);
	}
	/* Opens the PF_PACKET socket */
	if(open_socket() < 0) {
	fprintf(stdout, "Socket error\n");
	exit(1);
	}

	/* Sets the promiscuous mode */
	set_promisc();

	/* 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) {
		fprintf(stdout, "Error on opening DHCP info file\n");
		fprintf(stdout, "Release the DHCP IP after acquiring\n");
		exit(1);
	}
	build_option53(DHCP_MSGRELEASE); /* Option53 DHCP release */
	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(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;
	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) {
		close_socket();
		exit(1);
		}
	}
	if(dhcp_offer_state == DHCP_OFFR_RCVD) {
		fprintf(stdout, "DHCP offer received\t - ");
		set_serv_id_opt50();
		fprintf(stdout, "Offered IP : %s\n", inet_ntoa(*(struct in_addr *)&dhcph_g->dhcp_yip));
		if(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(vci_flag == 1) {
	build_option60_vci();
	}
	if(strlen(option12_name) > 0) {
		build_option12();	/* Option 12 - Client ID (hostname) */
	}
	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;
	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) {
		fprintf(stdout, "Timeout reached. Exiting\n");
		close_socket();
		exit(1);
		}
	}

	if(dhcp_ack_state == DHCP_ACK_RCVD) {
		fprintf(stdout, "DHCP ack received\t - ");
		fprintf(stdout, "Acquired IP: %s\n", inet_ntoa(*(struct in_addr *)&dhcph_g->dhcp_yip));

		/* Logs DHCP IP details to log file. This file is used for DHCP release */
		if(writelog) {
			log_dhinfo();
		}
		if(verbose) {
			print_dhinfo(DHCP_MSGACK);
		}
	} else if (dhcp_ack_state == DHCP_NAK_RCVD) {
		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(ip_listen_flag) {
	struct in_addr taddr;

	taddr.s_addr=htonl(ip_address);
	fprintf(stdout, "\nListening on %s for ARP and ICMP protocols\n", iface_name);
	fprintf(stdout, "IP address: %s, Listen timeout: %d seconds\n", inet_ntoa(taddr), 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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}