Пример #1
0
int
rfc822_parser_feed(struct rfc822_parser *rp, const char *line)
{
	if (rp->count >= RFC822_MAX_BUFFERS)
		return -1;
	return parse_addresses(rp, line, strlen(line));
}
Пример #2
0
int
main(int argc, char **argv)
{
    int ret;
    pcap_wrapper *pw;
    char ch, filter[128], is_usage = 0, show_version = 0;

    while((ch = getopt(argc, argv, "s:p:i:S:Cd:l:hv")) != -1) {
        switch(ch) {
            case 's': opts.server = strdup(optarg); break;
            case 'p': opts.port= atoi(optarg); break;
            case 'i': opts.device = strdup(optarg); break;
            case 'S': opts.script = strdup(optarg); break;
            case 'C': opts.is_calc_mode = 1; break;
            case 'd': opts.duration = atoi(optarg); break;
            case 'l':
                opts.specified_addresses = 1;
                if (parse_addresses(optarg)) {
                    logger(ERROR, "parsing local addresses\n");
                    return EXIT_FAILURE;
                }
                break;
            case 'f': opts.log_file = strdup(optarg); break;
            case 'h': is_usage = 1; break;
            case 'v': show_version= 1; break;
        }
    }

    if( is_usage ) {
        usage(argv[0]);
        exit(0);
    }
    if(show_version) {
        printf("%s version is %s\n", argv[0], VERSION);
        exit(0);
    }
    if(!opts.specified_addresses && get_addresses() != 0) {
        exit(0);
    }
    if (!opts.port) logger(ERROR, "port is required.\n");
    if (!opts.device) logger(ERROR, "device is required.\n");
    if (opts.log_file) set_log_file(opts.log_file); 
    if (!(pw = pw_create(opts.device))) logger(ERROR, "start captrue packet failed.\n");
    if(opts.server) {
        snprintf(filter, sizeof(filter), "host %s and tcp port %d", opts.server, opts.port);
    } else {
        snprintf(filter, sizeof(filter), "tcp port %d", opts.port);
    }

    check_lua_script();
    // start capature loop.
    ret = core_loop(pw, filter, process_packet);
    if(ret == -1) logger(ERROR, "start core loop failed.\n");

    pw_release(pw);
    script_release(L);
    return 0;
}
Пример #3
0
static void rt_parse(struct xt_option_call *cb)
{
	struct ip6t_rt *rtinfo = cb->data;

	xtables_option_parse(cb);
	switch (cb->entry->id) {
	case O_RT_TYPE:
		if (cb->invert)
			rtinfo->invflags |= IP6T_RT_INV_TYP;
		rtinfo->flags |= IP6T_RT_TYP;
		break;
	case O_RT_SEGSLEFT:
		if (cb->nvals == 1)
			rtinfo->segsleft[1] = rtinfo->segsleft[0];
		if (cb->invert)
			rtinfo->invflags |= IP6T_RT_INV_SGS;
		rtinfo->flags |= IP6T_RT_SGS;
		break;
	case O_RT_LEN:
		if (cb->invert)
			rtinfo->invflags |= IP6T_RT_INV_LEN;
		rtinfo->flags |= IP6T_RT_LEN;
		break;
	case O_RT0RES:
		if (!(cb->xflags & F_RT_TYPE) || rtinfo->rt_type != 0 ||
		    rtinfo->invflags & IP6T_RT_INV_TYP)
			xtables_error(PARAMETER_PROBLEM,
				   "`--rt-type 0' required before `--rt-0-res'");
		rtinfo->flags |= IP6T_RT_RES;
		break;
	case O_RT0ADDRS:
		if (!(cb->xflags & F_RT_TYPE) || rtinfo->rt_type != 0 ||
		    rtinfo->invflags & IP6T_RT_INV_TYP)
			xtables_error(PARAMETER_PROBLEM,
				   "`--rt-type 0' required before `--rt-0-addrs'");
		rtinfo->addrnr = parse_addresses(cb->arg, rtinfo->addrs);
		rtinfo->flags |= IP6T_RT_FST;
		break;
	case O_RT0NSTRICT:
		if (!(cb->xflags & F_RT0ADDRS))
			xtables_error(PARAMETER_PROBLEM,
				   "`--rt-0-addr ...' required before `--rt-0-not-strict'");
		rtinfo->flags |= IP6T_RT_FST_NSTRICT;
		break;
	}
}
Пример #4
0
static int parse_interface(SocksLink *sl, const char *optarg)
{
  struct ifaddrs ifa, *ifap = &ifa, *iface;
  int ret = 0, family;
  char host[NI_MAXHOST];

  if (getifaddrs(&ifap) != 0) {
    pr_err(sl, "getifaddrs() failed: %s", strerror(errno));
    return -1;
  }

  for (iface = ifap; iface != NULL; iface = iface->ifa_next) {
    if (strcmp(iface->ifa_name, optarg) == 0
	&& iface->ifa_addr != NULL) {
      family = iface->ifa_addr->sa_family;

#if defined(HAVE_IPV6)
      if (family != AF_INET && family != AF_INET6)
	continue ;

      ret = getnameinfo(iface->ifa_addr,
			(family == AF_INET) ? sizeof(struct sockaddr_in) :
			sizeof(struct sockaddr_in6),
			host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
#else
      if (family != AF_INET)
	continue ;

      ret = getnameinfo(iface->ifa_addr, sizeof(struct sockaddr_in) :
			host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
#endif

      if (ret) {
	pr_err(sl, "getnameinfo() failed: %s\n", gai_strerror(ret));
	break ;
      }
      if (parse_addresses(sl, host)) {
	ret = -1;
	break ;
      }
    }
  }
Пример #5
0
static int rt_parse(int c, char **argv, int invert, unsigned int *flags,
                    const void *entry, struct xt_entry_match **match)
{
    struct ip6t_rt *rtinfo = (struct ip6t_rt *)(*match)->data;

    switch (c) {
    case '1':
        if (*flags & IP6T_RT_TYP)
            xtables_error(PARAMETER_PROBLEM,
                          "Only one `--rt-type' allowed");
        xtables_check_inverse(optarg, &invert, &optind, 0, argv);
        rtinfo->rt_type = parse_rt_num(optarg, "type");
        if (invert)
            rtinfo->invflags |= IP6T_RT_INV_TYP;
        rtinfo->flags |= IP6T_RT_TYP;
        *flags |= IP6T_RT_TYP;
        break;
    case '2':
        if (*flags & IP6T_RT_SGS)
            xtables_error(PARAMETER_PROBLEM,
                          "Only one `--rt-segsleft' allowed");
        xtables_check_inverse(optarg, &invert, &optind, 0, argv);
        parse_rt_segsleft(optarg, rtinfo->segsleft);
        if (invert)
            rtinfo->invflags |= IP6T_RT_INV_SGS;
        rtinfo->flags |= IP6T_RT_SGS;
        *flags |= IP6T_RT_SGS;
        break;
    case '3':
        if (*flags & IP6T_RT_LEN)
            xtables_error(PARAMETER_PROBLEM,
                          "Only one `--rt-len' allowed");
        xtables_check_inverse(optarg, &invert, &optind, 0, argv);
        rtinfo->hdrlen = parse_rt_num(optarg, "length");
        if (invert)
            rtinfo->invflags |= IP6T_RT_INV_LEN;
        rtinfo->flags |= IP6T_RT_LEN;
        *flags |= IP6T_RT_LEN;
        break;
    case '4':
        if (*flags & IP6T_RT_RES)
            xtables_error(PARAMETER_PROBLEM,
                          "Only one `--rt-0-res' allowed");
        if ( !(*flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP) )
            xtables_error(PARAMETER_PROBLEM,
                          "`--rt-type 0' required before `--rt-0-res'");
        rtinfo->flags |= IP6T_RT_RES;
        *flags |= IP6T_RT_RES;
        break;
    case '5':
        if (*flags & IP6T_RT_FST)
            xtables_error(PARAMETER_PROBLEM,
                          "Only one `--rt-0-addrs' allowed");
        if ( !(*flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP) )
            xtables_error(PARAMETER_PROBLEM,
                          "`--rt-type 0' required before `--rt-0-addrs'");
        xtables_check_inverse(optarg, &invert, &optind, 0, argv);
        if (invert)
            xtables_error(PARAMETER_PROBLEM,
                          " '!' not allowed with `--rt-0-addrs'");
        rtinfo->addrnr = parse_addresses(optarg, rtinfo->addrs);
        rtinfo->flags |= IP6T_RT_FST;
        *flags |= IP6T_RT_FST;
        break;
    case '6':
        if (*flags & IP6T_RT_FST_NSTRICT)
            xtables_error(PARAMETER_PROBLEM,
                          "Only one `--rt-0-not-strict' allowed");
        if ( !(*flags & IP6T_RT_FST) )
            xtables_error(PARAMETER_PROBLEM,
                          "`--rt-0-addr ...' required before `--rt-0-not-strict'");
        rtinfo->flags |= IP6T_RT_FST_NSTRICT;
        *flags |= IP6T_RT_FST_NSTRICT;
        break;
    default:
        return 0;
    }

    return 1;
}
Пример #6
0
static int
parse_addresses(struct rfc822_parser *rp, const char *buffer, size_t len)
{
	const char		*s;
	char			*wptr;
	struct rfc822_address	*ra;

	s = buffer;

	/* skip over whitespaces */
	for (s = buffer; *s && isspace(*s); ++s, len--)
		;

	/* we should now pointing to the beginning of a recipient */
	if (*s == '\0')
		return 0;

	ra = calloc(1, sizeof *ra);
	if (ra == NULL)
		return -1;

	wptr = ra->name;
	for (; len; s++, len--) {
		if (*s == '(' && !rp->escape && !rp->quote)
			rp->comment++;
		if (*s == '"' && !rp->escape && !rp->comment)
			rp->quote = !rp->quote;
		if (!rp->comment && !rp->quote && !rp->escape) {
			if (*s == '<' && rp->bracket) {
				free(ra);
				return 0;
			}
			if (*s == '>' && !rp->bracket) {
				free(ra);
				return 0;
			}

			if (*s == '<') {
				wptr = ra->address;
				rp->bracket++;
				continue;
			}
			if (*s == '>') {
				rp->bracket--;
				continue;
			}
			if (*s == ',' || *s == ';')
				break;
		}
		if (*s == ')' && !rp->escape && !rp->quote && rp->comment)
			rp->comment--;
		if (*s == '\\' && !rp->escape && !rp->comment && !rp->quote)
			rp->escape = 1;
		else
			rp->escape = 0;
		*wptr++ = *s;
	}

	/* some flags still set, malformed header */
	if (rp->escape || rp->comment || rp->quote || rp->bracket) {
		free(ra);
		return 0;
	}

	/* no value, malformed header */
	if (ra->name[0] == '\0' && ra->address[0] == '\0') {
		free(ra);
		return 0;
	}

	/* no <>, use name as address */
	if (ra->address[0] == '\0') {
		memcpy(ra->address, ra->name, sizeof ra->address);
		memset(ra->name, 0, sizeof ra->name);
	}

	/* strip first trailing whitespace from name */
	wptr = &ra->name[0] + strlen(ra->name);
	while (wptr != &ra->name[0]) {
		if (*wptr && ! isspace(*wptr))
			break;
		*wptr-- = '\0';
	}

	TAILQ_INSERT_TAIL(&rp->addresses, ra, next);
	rp->count++;

	/* do we have more to process ? */
	for (; *s; ++s, --len)
		if (*s == ',' || *s == ';')
			break;

	/* nope, we're done */
	if (*s == '\0')
		return 1;

	/* there's more to come */
	if (*s == ',' || *s == ';') {
		s++;
		len--;
	}
	if (len)
		return parse_addresses(rp, s, len);
	return 1;
}
Пример #7
0
int
main(int argc, char *argv[]) {
    struct sigaction sa;
    char c;
    int option_index = 0;
    
    // Program name
    program_name = strrchr(argv[0], '/');
    if (program_name)
        program_name ++;
    else
        program_name = argv[0];
        
    // Parse command line options
    do {
        c = getopt_long(argc, argv, short_options, long_options, &option_index);

        switch (c) {

        case -1:
            break;
            
        case 'r':
            capture_file = fopen(optarg, "r");
            if (!capture_file) {
                LOGGER(ERROR, "Cannot open file '%s': %s\n", optarg,
                        strerror(errno));
                return EXIT_FAILURE;
                
            }
            break;
            
        case 'l':
            specified_addresses = 1;
            if (parse_addresses(optarg)) {
                LOGGER(ERROR, "Error parsing local addresses\n");
                return EXIT_FAILURE;
                
            }
            
            break;
            
        case 'p':
            port = strdup(optarg);
            break;
            
        case 'f':
            if (!check_format(optarg)) {
                LOGGER(ERROR, "Bad format provided: `%s'\n", optarg);
                return EXIT_FAILURE;
            }
            
            global_options.format = optarg;
            
            break;
            
        case 't':
            global_options.interval = strtoul(optarg, NULL, 10);
            if (interval <= 0 || interval >= MAX_OUTPUT_INTERVAL) {
                LOGGER(ERROR, "Bad interval provided\n");
                return EXIT_FAILURE;
            }
            
            break;
            
        case 'n':
            global_options.iterations = strtol(optarg, NULL, 10);
            if (interval < 0) {
                LOGGER(ERROR, "Bad iterations provided\n");
                return EXIT_FAILURE;
            }
            
            break;
            
        case 'T':
            global_options.threshold = strtol(optarg, NULL, 10) * 1000;
            if (global_options.threshold < 0) {
                LOGGER(ERROR, "Bad threshold provided\n");
                return EXIT_FAILURE;
            }
            
            break;

        case 'd':
            global_options.server = strdup(optarg);
            
            break;
        case 'i':
	        global_options.interface = strdup(optarg);

            break;


        case 'c':
            global_options.is_client = 1;
            break;

        case 's':
            global_options.header = optarg;
            global_options.show_header = 1;
            break;
            
        case 'S':
            global_options.show_header = 0;
            break;
            
        case 'h':
            dump_help(stdout);
            return EXIT_SUCCESS;

        case 'V':
            dump_version(stdout);
            return EXIT_SUCCESS;

        default:
            dump_usage(stderr);
            return EXIT_FAILURE;

        }

    }
    while (c != -1);
    
	if(! global_options.interface) {
        global_options.interface = "any";
	}

    if(global_options.is_client) {
        if(!global_options.server) {
            LOGGER(ERROR, "%s -d destination server is required.\n", argv[0]);
            return 0;
        }
    }
	if(global_options.server) {
		global_options.is_client = 1;
	} 
    if(!port) {
    	LOGGER(ERROR, "%s -p port is required.\n", argv[0]);
        return 0;
   	}

    // Set up signals
    sa.sa_handler = terminate;
    sigemptyset(&sa.sa_mask);
    sigaddset(&sa.sa_mask, SIGTERM);
    sigaddset(&sa.sa_mask, SIGINT);
    sa.sa_flags = 0;
    sa.sa_restorer = NULL;
    
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);
    
    // Get local addresses
    if (!specified_addresses && get_addresses() != 0)
        return EXIT_FAILURE;
    
    // Operations timestamp
    time(&timestamp);
    
    // Stats
    init_stats();
    
    if (capture_file) {
        output_offline_start(&global_options);

        offline_capture(capture_file);
        
        fclose(capture_file);
        
    }
    else {
        // Fire up capturing thread
        pthread_create(&capture_thread_id, NULL, capture, NULL);
        
		if(!global_options.threshold) {
        // Options thread
        	pthread_create(&output_thread_id, NULL, output_thread, &global_options);
        	pthread_kill(output_thread_id, SIGINT);
		}
        
        pthread_join(capture_thread_id, NULL);
        
    }
        
    free_stats();
    free_addresses();
	
	free(global_options.server);
    
    return EXIT_SUCCESS;

}
Пример #8
0
int main(int argc, char *argv[])
{
    struct mbus	*m;
    char		 c_addr[60], *token_u[2], *token_e[2];
    int		 seed = (gethostid() << 8) | (getpid() & 0xff), final_iters;
    struct timeval	 timeout;
    int		 i, num_sessions = 0;
    char **xargv = xmalloc(argc);
    int  xargc=0;

#ifdef WIN32
    win32_create_null_window(); /* Needed to listen to messages */
#else
    signal(SIGCONT, sigchld_handler);
    signal(SIGCHLD, sigchld_handler);
    signal(SIGINT, sigint_handler);
    signal(SIGTERM, sigint_handler);
    signal(SIGHUP, sigint_handler);
#endif

    debug_msg("rat-%s started argc=%d\n", RAT_VERSION, argc);

    /* We have two modes: one for operation as a transcoder, one */
    /* when working as a normal end-system audio tool. We choose */
    /* based on the first command line argument supplied.        */
    if ((argc > 2) && (strcmp(argv[1], "-T") == 0)) {
        num_sessions = 2;
    } else {
        num_sessions = 1;
    }

    if (parse_options_early(argc, (const char**)argv) == FALSE) {
        return FALSE;
    }

    srand48(seed);
    snprintf(c_addr, 60, "(media:audio module:control app:rat id:%lu)", (unsigned long) getpid());
    debug_msg("c_addr = %s\n", c_addr);
    m = mbus_init(mbus_control_rx, mbus_err_handler, c_addr);
    if (m == NULL) {
        fatal_error("RAT v" RAT_VERSION, "Could not initialize Mbus: Is multicast enabled?");
        return FALSE;
    }

    /* pull out -X arguments */
    for(i=0; i<argc; i++) {
        if( strcmp(argv[i],"-X") == 0 ) {
            xargv[xargc] = argv[i];
            xargc++;
            i++;
            xargv[xargc] = argv[i];
            xargc++;
        }
    }


    if (ui_enabled) {
        token_u[0] = generate_token();
        fork_process(UI_NAME, c_addr, &pid_ui, 1, token_u, xargc, xargv);
        debug_msg("Controller waiting for %s from UI...\n", token_u[0]);
        if ((u_addr = mbus_rendezvous_waiting(m, "()", token_u[0], m, 20000000)) == NULL) {
            fatal_error("RAT v" RAT_VERSION, "MBUS Failed to rendezvous with UI - Likely firewall/VPN issue");
            return FALSE;
        }
        debug_msg("Controller has rendezvous'd with UI (%s)\n",u_addr);
    }

    token_e[0] = generate_token();
    token_e[1] = generate_token();
    fork_process(ENGINE_NAME, c_addr, &pid_engine, num_sessions, token_e, xargc, xargv);
    should_exit = FALSE;
    for (i = 0; i < num_sessions; i++) {
        debug_msg("Controller waiting for %s from media engine...\n", token_e[i]);
        if ((e_addr[i] = mbus_rendezvous_waiting(m, "()", token_e[i], m, 20000000)) == NULL ) {
            fatal_error("RAT v" RAT_VERSION, "Failed to rendezvous with media engine - Likely firewall/VPN issue");
            return FALSE;
        }
        debug_msg("Controller rendezvous'd with media engine (%s)\n",e_addr[i]);
    }

    if (parse_addresses(m, e_addr, argc, argv) == TRUE) {
        char	*peer;

        if (ui_enabled) {
            if ((peer = mbus_rendezvous_go(m, token_u[0], (void *) m, 20000000)) == NULL) {
                fatal_error("RAT v" RAT_VERSION, "Failed to rendezvous with UI - Likely firewall/VPN issue");
                return FALSE;
            }
            debug_msg("User interface is %s\n", peer);
        }
        for (i = 0; i < num_sessions; i++) {
            if ((peer = mbus_rendezvous_go(m, token_e[i], (void *) m, 20000000)) == NULL) {
                fatal_error("RAT v" RAT_VERSION, "Failed to rendezvous with UI - Likely firewall/VPN issue");
                return FALSE;
            }
            debug_msg("Media engine %d is %s\n", i, peer);
        }
        debug_msg("Parsing options\n");
        for (i = 0; i < num_sessions; i++) {
            parse_options_late(m, e_addr[i], argc, argv);
        }
        debug_msg("Entering main loop\n");
        final_iters = 25;
        while (final_iters > 0) {
            mbus_send(m);
            mbus_heartbeat(m, 1);
            mbus_retransmit(m);
            timeout.tv_sec  = 0;
            timeout.tv_usec = 20000;
#ifdef WIN32
            win32_check_children_running();
            win32_process_messages();
#endif
            mbus_recv(m, NULL, &timeout);
            if (should_exit) {
                final_iters--;
            }
        }
        if (ui_enabled) {
            terminate(m, u_addr, &pid_ui);
        }
        for (i = 0; i < num_sessions; i++) {
            terminate(m, e_addr[i], &pid_engine);
        }
    }

    if (ui_enabled) {
        kill_process(pid_ui);
    }
    kill_process(pid_engine);

#ifdef WIN32
    WSACleanup();
#endif
    if (ui_enabled) xfree(token_u[0]);
    xfree(token_e[0]);
    xfree(token_e[1]);
    xfree(xargv);
    debug_msg("Controller exit\n");
    return 0;
}
Пример #9
0
bool read_info (const interface_t *iface, dhcp_t *dhcp)
{
	FILE *fp;
	char buffer[1024];
	char *var;
	char *value;
	char *p;
	struct stat sb;

	if (stat (iface->infofile, &sb) != 0) {
		logger (LOG_ERR, "lease information file `%s' does not exist",
				iface->infofile);
		return (false);
	}

	if (! (fp = fopen (iface->infofile, "r"))) {
		logger (LOG_ERR, "fopen `%s': %s", iface->infofile, strerror (errno));
		return (false);
	}

	dhcp->frominfo = true;

	memset (buffer, 0, sizeof (buffer));
	while ((fgets (buffer, sizeof (buffer), fp))) {
		var = buffer;

		/* Strip leading spaces/tabs */
		while ((*var == ' ') || (*var == '\t'))
			var++;

		/* Trim trailing \n */
		p = var + strlen (var) - 1;
		if (*p == '\n')
			*p = 0;


		/* Skip comments */
		if (*var == '#')
			continue;
		
		/* If we don't have an equals sign then skip it */
		if (! (p = strchr (var, '=')))
			continue;

		/* Terminate the = so we have two strings */
		*p = 0;

		value = p + 1;
		/* Strip leading and trailing quotes if present */
		if (*value == '\'' || *value == '"')
			value++;
		p = value + strlen (value) - 1;
		if (*p == '\'' || *p == '"')
			*p = 0;

		/* Don't process null vars or values */
		if (! *var || ! *value)
			continue;

		if (strcmp (var, "IPADDR") == 0)
			parse_address (&dhcp->address, value, "IPADDR");
		else if (strcmp (var, "NETMASK") == 0)
			parse_address (&dhcp->netmask, value, "NETMASK");
		else if (strcmp (var, "BROADCAST") == 0)
			parse_address (&dhcp->broadcast, value, "BROADCAST");
		else if (strcmp (var, "MTU") == 0)
			parse_ushort (&dhcp->mtu, value, "MTU");
		else if (strcmp (var, "ROUTES") == 0) {
			p = value;
			while ((value = strsep (&p, " "))) {
				char *pp = value;
				char *dest = strsep (&pp, ",");
				char *net = strsep (&pp, ",");
				char *gate = strsep (&pp, ",");
				route_t *route;

				if (! dest || ! net || ! gate) {
					logger (LOG_ERR, "read_info ROUTES `%s,%s,%s': invalid route",
							dest, net, gate);
					continue;
				}

				/* See if we can create a route */
				route = xmalloc (sizeof (route_t));
				memset (route, 0, sizeof (route_t));
				if (inet_aton (dest, &route->destination) == 0) {
					logger (LOG_ERR, "read_info ROUTES `%s': not a valid destination address",
							dest);
					free (route);
					continue;
				}
				if (inet_aton (dest, &route->netmask) == 0) {
					logger (LOG_ERR, "read_info ROUTES `%s': not a valid netmask address",
							net);
					free (route);
					continue;
				}
				if (inet_aton (dest, &route->gateway) == 0) {
					logger (LOG_ERR, "read_info ROUTES `%s': not a valid gateway address",
							gate);
					free (route);
					continue;
				}

				/* OK, now add our route */
				if (dhcp->routes) {
					route_t *r = dhcp->routes;
					while (r->next)
						r = r->next;
					r->next = route;
				} else
					dhcp->routes = route;
			}
		} else if (strcmp (var, "GATEWAYS") == 0) {
			p = value;
			while ((value = strsep (&p, " "))) {
				route_t *route = xmalloc (sizeof (route_t));
				memset (route, 0, sizeof (route_t));
				if (parse_address (&route->gateway, value, "GATEWAYS")) {
					if (dhcp->routes) {
						route_t *r = dhcp->routes;
						while (r->next)
							r = r->next;
						r->next = route;
					} else
						dhcp->routes = route;
				} else
					free (route);
			}
		} else if (strcmp (var, "HOSTNAME") == 0)
			dhcp->hostname = xstrdup (value);
		else if (strcmp (var, "DNSDOMAIN") == 0)
			dhcp->dnsdomain = xstrdup (value);
		else if (strcmp (var, "DNSSEARCH") == 0)
			dhcp->dnssearch = xstrdup (value);
		else if (strcmp (var, "DNSSERVERS") == 0)
			parse_addresses (&dhcp->dnsservers, value, "DNSSERVERS");
		else if (strcmp (var, "NTPSERVERS") == 0)
			parse_addresses (&dhcp->ntpservers, value, "NTPSERVERS");
		else if (strcmp (var, "NISDOMAIN") == 0)
			dhcp->nisdomain = xstrdup (value);
		else if (strcmp (var, "NISSERVERS") == 0)
			parse_addresses (&dhcp->nisservers, value, "NISSERVERS");
		else if (strcmp (var, "ROOTPATH") == 0)
			dhcp->rootpath = xstrdup (value);
		else if (strcmp (var, "DHCPSID") == 0)
			parse_address (&dhcp->serveraddress, value, "DHCPSID");
		else if (strcmp (var, "DHCPSNAME") == 0)
			strlcpy (dhcp->servername, value, sizeof (dhcp->servername));
		else if (strcmp (var, "LEASEDFROM") == 0)
			parse_uint (&dhcp->leasedfrom, value, "LEASEDFROM");
		else if (strcmp (var, "LEASETIME") == 0)
			parse_uint (&dhcp->leasetime, value, "LEASETIME");
		else if (strcmp (var, "RENEWALTIME") == 0)
			parse_uint (&dhcp->renewaltime, value, "RENEWALTIME");
		else if (strcmp (var, "REBINDTIME") == 0)
			parse_uint (&dhcp->rebindtime, value, "REBINDTIME");
	}

	fclose (fp);
	return (true);
}