Exemple #1
0
TEG_STATUS option_parse( int fd, char *str)
{
	int i;
	PARSER p;
	DELIM igualador={ '=', ' ', ':' };
	DELIM separador=DELIM_NULL;

	p.igualador = &igualador;
	p.separador = &separador;
	p.data = str;

	do {
		if( (i=parser_call( &p )) ) {
			if( option_lookup( fd,&p ) == TEG_STATUS_CONNCLOSED ) {
				return TEG_STATUS_CONNCLOSED;
			}
		}
	} while( i && p.hay_otro);

	return TEG_STATUS_SUCCESS;
}
Exemple #2
0
int main(int argc, char **argv) {
  int ch, dhcp_payload_len;
  unsigned char *dhcp_payload;
  libnet_ptag_t ptag_dhcpv4, ptag_udp, ptag_ipv4, ptag_ethernet;

  char *arg_secs, *arg_cip, *arg_chaddr, *arg_sip, *arg_ifname;
  char *arg_operation, *arg_timeout, *arg_xid, *arg_flags, *arg_yip;
  char *arg_gip, *arg_sname, *arg_fname, *arg_ether_dst, *stmp;
  char *arg_ipv4_src, *arg_ipv4_dst, *arg_ipv4_tos, *arg_ipv4_ttl;
  char *arg_reply_count;

  if (argc < 2) usage("too few arguments");

  srandom(time(NULL));

  arg_secs = arg_cip = arg_chaddr = arg_sip = arg_ifname = NULL;
  arg_operation = arg_timeout = arg_xid = arg_flags = arg_yip = NULL;
  arg_gip = arg_sname = arg_fname = arg_ether_dst = arg_reply_count = NULL;
  arg_ipv4_src = arg_ipv4_dst = arg_ipv4_tos = arg_ipv4_ttl = NULL;
  verbosity = 1;

  while ((ch = getopt(argc, argv, "s:c:h:i:o:t:x:f:y:g:S:A:B:O:X:v:F:T:L:Q:E:w:n:m")) != -1) {
    switch (ch) {
      case 's': arg_secs = optarg; break;
      case 'c': arg_cip = optarg; break;
      case 'h': arg_chaddr = optarg; break;
      case 'S': arg_sip = optarg; break;
      case 'i': arg_ifname = optarg; break;
      case 'o': arg_operation = optarg; break;
      case 't': arg_timeout = optarg; break;
      case 'x': arg_xid = optarg; break;
      case 'f': arg_flags = optarg; break;
      case 'y': arg_yip = optarg; break;
      case 'B': arg_fname = optarg; break;
      case 'A': arg_sname = optarg; break;
      case 'g': arg_gip = optarg; break;
      case 'F': arg_ipv4_src = optarg; break;
      case 'T': arg_ipv4_dst = optarg; break;
      case 'L': arg_ipv4_ttl = optarg; break;
      case 'Q': arg_ipv4_tos = optarg; break;
      case 'n': arg_reply_count = optarg; break;
      case 'E': arg_ether_dst = optarg; break;
      case 'v': verbosity = atoi(optarg); break;
      case 'm': no_double_options = 0; break;
      case 'O': add_option(optarg); break;
      case 'X': add_hexoption(optarg); break;
      case 'w': option_lookup(optarg); break;
      case '?':
      default:
        usage("unknown argument");
    }
  }
  argc -= optind;
  argv += optind;

  /* Set some basic defaults */
  set_defaults();

  /* Make sure network interface was specified with -i option */
  if (arg_ifname == NULL) {
    usage("Error: network interface (-i option) not specified.");
  }
  strncpy(ifname, arg_ifname, 99);

  /* Try to have pcap and libnet use the interface */
  pcp = pcap_open_live(ifname, SNAPLEN, 1, 1, pcap_errbuf);
  if (pcp == NULL) {
    printf("pcap_open_live(%s) failed! Did you give the right interface name " 
           "and are you root?\n", ifname);
    printf("pcap said: %s\n", pcap_errbuf);
    exit(1);
  }
  lnp = libnet_init(LIBNET_LINK, ifname, libnet_errbuf);
  if (lnp == NULL) {
    printf("libnet_init(%s) failed!\n", ifname);
    printf("libnet said: %s\n", libnet_errbuf);
    exit(1);
  }

  /* Set chaddr MAC address */
  if (arg_chaddr != NULL) {
    int len = ETHER_ADDR_LEN;
    /*chaddr = libnet_hex_aton((int8_t *)arg_chaddr, &len);*/
    chaddr = libnet_hex_aton(arg_chaddr, &len);
    if (chaddr == NULL) {
      if (verbosity > 0)
        printf("Invalid chaddr MAC address specified (%s)\n", arg_chaddr);
      exit(1);
    }
  }
  else {
    /* Try to retrieve MAC address using libnet */
    chaddr = (u_int8_t *)libnet_get_hwaddr(lnp);
    if (chaddr == NULL) {
      if (verbosity > 1) {
        printf("Failed to retrieve MAC address for interface %s, using 0:0:0:0:0:0\n"
          "Libnet said: %s\n", ifname, libnet_errbuf);
      }
      memset(chaddr, 0, ETHER_ADDR_LEN);
    }
  }

  /* Set cip address */  
  if (arg_cip != NULL) {
    cip = inet_addr(arg_cip);
    if (cip == INADDR_NONE) {
      if (verbosity > 0) 
        printf("Invalid cip address specified (%s)\n", arg_cip);
      exit(1);
    }
    cip = ntohl(cip);
  }
  else {
    /* Try to retrieve IP address using libnet */
    cip = libnet_get_ipaddr4(lnp);
    if ((int)cip == -1) {
      if (verbosity > 1) {
        printf("Failed to retrieve IPv4 address for interface %s, using cip 0.0.0.0\n"
          "Libnet said: %s\n", ifname, libnet_errbuf);
      }
      cip = inet_addr("0.0.0.0");
    }
    else
      cip = htonl(cip);
  }


  /**************************/
  /* Set various parameters */
  /**************************/

  if (arg_operation != NULL) {
    if (option_added(LIBNET_DHCP_MESSAGETYPE) && no_double_options) {
      if (verbosity > 0) {
        printf("Error: DHCP messagetype specified twice (don't use -o option if\n"
               "       you also intend to use -O to set option 53 (messagetype))\n");
      }
      exit(1);
    }
    if (strcasecmp(arg_operation, "discover") == 0) {
      operation = LIBNET_DHCP_MSGDISCOVER;
      if (arg_timeout == NULL)
        timeout = 5;
    }
    else if (strcasecmp(arg_operation, "request") == 0) {
      operation = LIBNET_DHCP_MSGREQUEST;
      if (arg_timeout == NULL)
        timeout = 5;
    }
    else if (strcasecmp(arg_operation, "inform") == 0) {
      operation = LIBNET_DHCP_MSGINFORM;
      if (timeout == 0)
        timeout = 5;
    }
    else if (strcasecmp(arg_operation, "release") == 0)
      operation = LIBNET_DHCP_MSGRELEASE;
    else if (strcasecmp(arg_operation, "decline") == 0)
      operation = LIBNET_DHCP_MSGDECLINE;
    else {
      if (verbosity > 0)
        usage("Invalid DHCP operation type");
      else
        exit(1);
    }
    /* Add MESSAGETYPE DHCP option */
    num_options++;
    options = (struct dhcp_option *)
      realloc(options, num_options * sizeof(struct dhcp_option));
    options[num_options-1].opnum = LIBNET_DHCP_MESSAGETYPE;
    options[num_options-1].oplen = 1;
    options[num_options-1].opdata[0] = operation;
  }
  else {
    /* no "-o operation" argument given */
    if (option_added(LIBNET_DHCP_MESSAGETYPE) == 0) {
      /* Add MESSAGETYPE DHCP option */
      num_options++;
      options = (struct dhcp_option *)
        realloc(options, num_options * sizeof(struct dhcp_option));
      options[num_options-1].opnum = LIBNET_DHCP_MESSAGETYPE;
      options[num_options-1].oplen = 1;
      options[num_options-1].opdata[0] = operation;
    }
  }

  if (arg_secs != NULL) {
    unsigned long ultmp;
    ultmp = strtoul(arg_secs, &stmp, 0);
    if (*stmp != '\0' || ultmp > 65535) {
      if (verbosity > 0)
        printf("Error: secs must be 0-65535 (was: %s)\n",
          arg_secs);
      exit(1);
    }
    secs = (u_int16_t)ultmp;
  }

  if (arg_timeout != NULL) {
    timeout = strtoul(arg_timeout, &stmp, 0);
    if (*stmp != '\0') {
      if (verbosity > 0)
        printf("Error: timeout value must be 0 or a positive integer (was: %s)\n",
          arg_timeout);
      exit(1);
    }
  }

  if (arg_reply_count != NULL) {
    reply_count = strtoul(arg_reply_count, &stmp, 0);
    if (*stmp != '\0') {
      if (verbosity > 0)
        printf("Error: reply_count value must be 0 or a positive integer (was: %s)\n",
          arg_reply_count);
      exit(1);
    }
  }

  if (arg_xid != NULL) {
    xid = strtoul(arg_xid, &stmp, 0);
    if (*stmp != '\0') {
      if (verbosity > 0) 
        printf("Error: xid value must be 0 or a positive integer (was: %s)\n",
          arg_xid);
      exit(1);
    } 
  }

  if (arg_flags != NULL) {
    unsigned long ultmp;
    ultmp = strtoul(arg_flags, &stmp, 0);
    if (*stmp != '\0' || ultmp > 65535) {
      if (verbosity > 0) 
        printf("Error: flags value must be 0-65535 (was: %s)\n",
          arg_flags);
      exit(1);
    }
    flags = (u_int16_t)ultmp;
  }

  if (arg_sip != NULL) {
    sip = inet_addr(arg_sip);
    if (sip == INADDR_NONE) {
      if (verbosity > 0)
        printf("Error: specified sip value is not a valid IPv4 address (was: %s)\n",
          arg_sip);
      exit(1);
    }
  }

  if (arg_yip != NULL) {
    yip = inet_addr(arg_yip);
    if (yip == INADDR_NONE) {
      if (verbosity > 0)
        printf("Error: specified yip value is not a valid IPv4 address (was: %s)\n",
          arg_yip);
      exit(1);
    }
  }

  if (arg_gip != NULL) {
    gip = inet_addr(arg_gip);
    if (gip == INADDR_NONE) {
      if (verbosity > 0)
        printf("Error: specified gip value is not a valid IPv4 address (was: %s)\n",
          arg_gip);
      exit(1);
    }
  }

  if (arg_fname != NULL) {
    fname = (char *)malloc(strlen(fname)+1);
    strcpy(fname, arg_fname);
  }
  if (arg_sname != NULL) {
    sname = (char *)malloc(strlen(sname)+1);
    strcpy(sname, arg_sname);
  }

  if (arg_ipv4_src != NULL) {
    ipv4_src = inet_addr(arg_ipv4_src);
    if (ipv4_src == INADDR_NONE) {
      if (verbosity > 0)
        printf("Error: specified ipv4_src value is not a valid IPv4 address (was: %s)\n",
          arg_ipv4_src);
      exit(1);
    }
  }

  if (arg_ipv4_dst != NULL) {
    ipv4_dst = inet_addr(arg_ipv4_dst);
    if (ipv4_dst == INADDR_NONE) {
      if (verbosity > 0)
        printf("Error: specified ipv4_dst value is not a valid IPv4 address (was: %s)\n",
          arg_ipv4_dst);
      exit(1);
    }
  }

  if (arg_ipv4_ttl != NULL) {
    unsigned long ultmp;
    ultmp = strtoul(arg_ipv4_ttl, &stmp, 0);
    if (*stmp != '\0' || ultmp > 255) {
      if (verbosity > 0) 
        printf("Error: ipv4_ttl value must be 0-255 (was: %s)\n",
          arg_xid);
      exit(1);
    }
    ipv4_ttl = (u_int8_t)ultmp;
  }

  if (arg_ipv4_tos != NULL) {
    unsigned long ultmp;
    ultmp = strtoul(arg_ipv4_tos, &stmp, 0);
    if (*stmp != '\0' || ultmp > 255) {
      if (verbosity > 0) 
        printf("Error: ipv4_tos value must be 0-255 (was: %s)\n",
          arg_ipv4_tos);
      exit(1);
    }
    ipv4_tos = (u_int8_t)ultmp;
  }

  if (arg_ether_dst != NULL) {
    int l = ETHER_ADDR_LEN;
    /*ether_dst = libnet_hex_aton((int8_t *)arg_ether_dst, &l);*/
    ether_dst = libnet_hex_aton(arg_ether_dst, &l);
    if (ether_dst == NULL) {
      if (verbosity > 0)
        printf("Error: invalid ethernet destination MAC specified (was: %s)\n",
          arg_ether_dst);
      exit(1);
    }
  }


  /******************************
   * Done setting parameters.   *
   * Start building DHCP packet *
   ******************************/

  libnet_clear_packet(lnp);

  /* Build DHCP payload (DHCP options section) */
  dhcp_payload = build_payload(&dhcp_payload_len);

  /* Create DHCP message */
  ptag_dhcpv4 = 
    libnet_build_dhcpv4(LIBNET_DHCP_REQUEST,
                         BOOTP_HTYPE_ETHER,
                         ETHER_ADDR_LEN,
                         BOOTP_HOPCOUNT,
                         xid,
                         secs,
                         flags,
                         cip,
                         yip,
                         sip,
                         gip,
                         chaddr,
                         sname,
                         fname,
                         dhcp_payload,
                         dhcp_payload_len,
                         lnp,
                         0);
  if (ptag_dhcpv4 == -1) {
    printf("Failed to build bootp packet: %s\n", libnet_errbuf);
    exit(1);
  }

/*
libnet_ptag_t
libnet_build_udp(u_int16_t sp, u_int16_t dp, u_int16_t len, u_int16_t sum,
u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag);
*/

  /* Create UDP datagram */
  ptag_udp =
    libnet_build_udp(UDP_SRCPORT,
                     UDP_DSTPORT,
                     dhcp_payload_len + LIBNET_DHCPV4_H + LIBNET_UDP_H,
                     0,
                     NULL,
                     0,
                     lnp,
                     0);
  if (ptag_udp == -1) {
    printf("Failed to build udp packet: %s\n", libnet_errbuf);
    exit(1);
  }

/*
libnet_ptag_t
libnet_build_ipv4(u_int16_t len, u_int8_t tos, u_int16_t id, u_int16_t frag,
u_int8_t ttl, u_int8_t prot, u_int16_t sum, u_int32_t src, u_int32_t dst,
u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag);
*/

  /* Create IPv4 datagram */
  ptag_ipv4 =
    libnet_build_ipv4(dhcp_payload_len + LIBNET_DHCPV4_H + LIBNET_UDP_H + LIBNET_IPV4_H,
                      ipv4_tos,
                      ipv4_id++,
                      0,
                      ipv4_ttl,
                      IPPROTO_UDP,
                      0,
                      ipv4_src,
                      ipv4_dst,
                      NULL,
                      0,
                      lnp,
                      0);
  if (ptag_ipv4 == -1) {
    printf("Failed to build ipv4 packet: %s\n", libnet_errbuf);
    exit(1);
  }

  /* Create ethernet packet */
  ptag_ethernet = 
    libnet_autobuild_ethernet(ether_dst,
                              ETHERTYPE_IP,
                              lnp);
  if (ptag_ethernet == -1) {
    printf("Failed to build ethernet packet: %s\n", libnet_errbuf);
    exit(1);
  }

  /* Write packet to network */
  if (libnet_write(lnp) == -1) {
    printf("Failed to write ethernet packet to network: %s\n", libnet_errbuf);
    exit(1);
  }

  /* If we have to wait and listen for server replies, we use
     a timer and a signal handler to quit. We do this as libpcap
     doesn't support non-blocking packet capture on some (many?)
     platforms. We could have launched another thread also, but
     using timers and signals is simpler.
   */
  if (timeout > 0) {
    struct itimerval itv;
    itv.it_interval.tv_sec = itv.it_value.tv_sec = timeout;
    itv.it_interval.tv_usec = itv.it_value.tv_usec = 0;
    setitimer(ITIMER_REAL, &itv, NULL);
    signal(SIGALRM, sighandler);
    pcap_loop(pcp, -1, pcap_callback, NULL);    
  }

  libnet_destroy(lnp);
  pcap_close(pcp);
  exit(0);
}
/**
 * Parse the arguments, looking for specific single-letter options.  Whenever
 * an option is found, the value in the option_t vector is set.
 *
 * Options start with a "-" and option parsing stops when "--" is encountered.
 * Several argumentless options can be concatenated together after the initial
 * "-".  The value of the option can immediately follow the option letter,
 * or be given by the next argument.
 *
 * Unrecognized options or missing arguments stop processing.
 *
 * @param argv		the initial argument vector
 * @param ovec		the single-letter option description vector
 * @param osize		the amount of entries in ovec
 *
 * @return The number of options processed and validated, -1 on error.
 */
int
options_parse(const char *argv[], const option_t *ovec, int osize)
{
	uchar options[127];	/* ASCII only */
	const option_t *current;
	int i;

	g_assert(argv);
	g_assert(osize >= 0);
	g_assert(0 == osize || NULL != ovec);

	/*
	 * Compile valid options.
	 */

	ZERO(&options);
	error_string[0] = '\0';

	for (i = 0; i < osize; i++) {
		const option_t *o = &ovec[i];
		uchar idx;

		g_assert(o->letter);
		idx = o->letter[0];
		if (UNSIGNED(idx) >= N_ITEMS(options)) {
			g_assert_not_reached();
			return -1; /* ASCII only */
		}
		g_assert(!options[idx]);			/* No duplicates */

		options[idx] = OPTION_F_VALID;
		if (o->letter[1] == ':')
			options[idx] |= OPTION_F_VALUE;

		if (o->value)
			*o->value = NULL;
	}

	/*
	 * Analyze the arguments, starting at argv[1].
	 * (argv[0] is the command name).
	 */

	current = NULL;
	for (i = 0; NULL != argv[i]; i++) {
		const char *arg = argv[i];
		uchar c;

		if (0 == i)
			continue;

		if (0 == strcmp(arg, "--")) {		/* End of options */
			if (current) {					/* This option lacks its argument */
				str_bprintf(error_string, sizeof error_string,
					"missing value for -%c", current->letter[0]);
				return -1;
			}
			return i + 1;
		}

		if (current) {
			/*
			 * We're expecting the next argument to be the value of the switch
			 * we parsed earlier.
			 */

			if (current->value)
				*current->value = arg;

			current = NULL;
			continue;
		}

		if (*arg++ != '-') {				/* Non-option found */
			return i; /* First non-option argument */
		}

		/*
		 * Argument is an option, that can contain multiple argumentless
		 * switches, or a switch and its value.
		 */

		g_assert(current == NULL);

		while ((c = *arg++)) {
			const option_t *opt;
			int flags;

			if (UNSIGNED(c) >= N_ITEMS(options)) {
				str_bprintf(error_string, sizeof error_string,
					"invalid non-ASCII switch");
				return -1;
			}

			flags = options[c];
			if (!(flags & OPTION_F_VALID)) {
				str_bprintf(error_string, sizeof error_string,
					"invalid -%c switch", c);
				return -1;
			}

			opt = option_lookup(c, ovec, osize);
			g_assert(opt);					/* Must have been found */

			if (flags & OPTION_F_VALUE) {	/* A value is expected */
				if (*arg) {					/* And it follows */
					if (opt->value) {
						*opt->value = arg;
					}
					break;					/* Argument held option value */
				} else
					current = opt;			/* Expecting value as next arg */
			} else {
				if (opt->value)
					*opt->value = "";	/* Signals option was present */
			}
		}
	}

	return i;
}