Example #1
0
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;
}
Example #2
0
/******************************************************************************
 * 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;
}
Example #3
0
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;
}
Example #4
0
File: server.c Project: rzr/connman
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;
}
Example #5
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;
}
Example #6
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;
}
Example #7
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;
}