Exemple #1
0
static int parse_ip(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
{
	int res = -1;
	int argc = *argc_p;
	char **argv = *argv_p;

	if (argc < 2)
		return -1;

	if (strcmp(*argv, "src") == 0) {
		NEXT_ARG();
		res = parse_ip_addr(&argc, &argv, sel, 12);
	} else if (strcmp(*argv, "dst") == 0) {
		NEXT_ARG();
		res = parse_ip_addr(&argc, &argv, sel, 16);
	} else if (strcmp(*argv, "tos") == 0 ||
	    matches(*argv, "dsfield") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 1, 0);
	} else if (strcmp(*argv, "ihl") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 0, 0);
	} else if (strcmp(*argv, "protocol") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 9, 0);
	} else if (matches(*argv, "precedence") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 1, 0);
	} else if (strcmp(*argv, "nofrag") == 0) {
		argc--; argv++;
		res = pack_key16(sel, 0, 0x3FFF, 6, 0);
	} else if (strcmp(*argv, "firstfrag") == 0) {
		argc--; argv++;
		res = pack_key16(sel, 0x2000, 0x3FFF, 6, 0);
	} else if (strcmp(*argv, "df") == 0) {
		argc--; argv++;
		res = pack_key16(sel, 0x4000, 0x4000, 6, 0);
	} else if (strcmp(*argv, "mf") == 0) {
		argc--; argv++;
		res = pack_key16(sel, 0x2000, 0x2000, 6, 0);
	} else if (strcmp(*argv, "dport") == 0) {
		NEXT_ARG();
		res = parse_u16(&argc, &argv, sel, 22, 0);
	} else if (strcmp(*argv, "sport") == 0) {
		NEXT_ARG();
		res = parse_u16(&argc, &argv, sel, 20, 0);
	} else if (strcmp(*argv, "icmp_type") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 20, 0);
	} else if (strcmp(*argv, "icmp_code") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 21, 0);
	} else
		return -1;

	*argc_p = argc;
	*argv_p = argv;
	return res;
}
Exemple #2
0
static int discover_print(char *target_ip_str)
{
	uint32_t target_ip = 0;
	if (target_ip_str) {
		target_ip = parse_ip_addr(target_ip_str);
		if (target_ip == 0) {
			fprintf(stderr, "invalid ip address: %s\n", target_ip_str);
			return -1;
		}
	}

	struct hdhomerun_discover_device_t result_list[64];
	int count = hdhomerun_discover_find_devices_custom(target_ip, HDHOMERUN_DEVICE_TYPE_TUNER, HDHOMERUN_DEVICE_ID_WILDCARD, result_list, 64);
	if (count < 0) {
		fprintf(stderr, "error sending discover request\n");
		return -1;
	}
	if (count == 0) {
		printf("no devices found\n");
		return 0;
	}

	int index;
	for (index = 0; index < count; index++) {
		struct hdhomerun_discover_device_t *result = &result_list[index];
		printf("hdhomerun device %08lX found at %u.%u.%u.%u\n",
			(unsigned long)result->device_id,
			(unsigned int)(result->ip_addr >> 24) & 0x0FF, (unsigned int)(result->ip_addr >> 16) & 0x0FF,
			(unsigned int)(result->ip_addr >> 8) & 0x0FF, (unsigned int)(result->ip_addr >> 0) & 0x0FF
		);
	}

	return count;
}
Exemple #3
0
/** setup listening TCP */
static int
setup_fd(char* addr, int port)
{
	struct sockaddr_storage ad;
	socklen_t len;
	int fd;
	int c = 1;
	int fam = parse_ip_addr(addr, port, &ad, &len);
	fd = socket(fam, SOCK_STREAM, 0);
	if(fd == -1) {
		log_errno("socket");
		return -1;
	}
	if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
		(void*)&c, (socklen_t) sizeof(int)) < 0) {
		log_errno("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
	}
	if(bind(fd, (struct sockaddr*)&ad, len) == -1) {
		log_errno("bind");
		fd_close(fd);
		return -1;
	}
	if(listen(fd, 5) == -1) {
		log_errno("listen");
		fd_close(fd);
		return -1;
	}
	return fd;
}
Exemple #4
0
void
parse_reject_statement(FILE *cfile)
{
	struct iaddrlist *list;
	struct iaddr addr;
	char *val;
	int token;

	do {
		if (!parse_ip_addr(cfile, &addr)) {
			parse_warn("expecting IP address.");
			skip_to_semi(cfile);
			return;
		}

		list = malloc(sizeof(struct iaddrlist));
		if (!list)
			error("no memory for reject list!");

		list->addr = addr;
		list->next = config->reject_list;
		config->reject_list = list;

		token = next_token(&val, cfile);
	} while (token == ',');

	if (token != ';') {
		parse_warn("expecting semicolon.");
		skip_to_semi(cfile);
	}
}
Exemple #5
0
/*
 * client-lease-declaration :==
 *	BOOTP |
 *	INTERFACE string |
 *	FIXED_ADDR ip_address |
 *	FILENAME string |
 *	SERVER_NAME string |
 *	OPTION option-decl |
 *	RENEW time-decl |
 *	REBIND time-decl |
 *	EXPIRE time-decl
 */
void
parse_client_lease_declaration(FILE *cfile, struct client_lease *lease)
{
	char *val;
	int token;

	switch (next_token(&val, cfile)) {
	case TOK_BOOTP:
		lease->is_bootp = 1;
		break;
	case TOK_INTERFACE:
		token = next_token(&val, cfile);
		if (token != TOK_STRING) {
			parse_warn("expecting interface name (in quotes).");
			skip_to_semi(cfile);
			break;
		}
		if (strcmp(ifi->name, val) != 0) {
			parse_warn("wrong interface name. Expecting '%s'.",
			   ifi->name);
			skip_to_semi(cfile);
			break;
		}
		break;
	case TOK_FIXED_ADDR:
		if (!parse_ip_addr(cfile, &lease->address))
			return;
		break;
	case TOK_MEDIUM:
		parse_string_list(cfile, &lease->medium, 0);
		return;
	case TOK_FILENAME:
		lease->filename = parse_string(cfile);
		return;
	case TOK_SERVER_NAME:
		lease->server_name = parse_string(cfile);
		return;
	case TOK_RENEW:
		lease->renewal = parse_date(cfile);
		return;
	case TOK_REBIND:
		lease->rebind = parse_date(cfile);
		return;
	case TOK_EXPIRE:
		lease->expiry = parse_date(cfile);
		return;
	case TOK_OPTION:
		parse_option_decl(cfile, lease->options);
		return;
	default:
		parse_warn("expecting lease declaration.");
		skip_to_semi(cfile);
		break;
	}
	token = next_token(&val, cfile);
	if (token != ';') {
		parse_warn("expecting semicolon.");
		skip_to_semi(cfile);
	}
}
Exemple #6
0
/*
 * client-lease-declaration :==
 *	BOOTP |
 *	INTERFACE string |
 *	FIXED_ADDR ip_address |
 *	FILENAME string |
 *	SERVER_NAME string |
 *	OPTION option-decl |
 *	RENEW time-decl |
 *	REBIND time-decl |
 *	EXPIRE time-decl
 */
void
parse_client_lease_declaration(FILE *cfile, struct client_lease *lease,
    struct interface_info **ipp)
{
	int			 token;
	char			*val;
	struct interface_info	*ip;

	switch (next_token(&val, cfile)) {
	case BOOTP:
		lease->is_bootp = 1;
		break;
	case INTERFACE:
		token = next_token(&val, cfile);
		if (token != STRING) {
			parse_warn("expecting interface name (in quotes).");
			skip_to_semi(cfile);
			break;
		}
		ip = interface_or_dummy(val);
		*ipp = ip;
		break;
	case FIXED_ADDR:
		if (!parse_ip_addr(cfile, &lease->address))
			return;
		break;
	case MEDIUM:
		parse_string_list(cfile, &lease->medium, 0);
		return;
	case FILENAME:
		lease->filename = parse_string(cfile);
		return;
	case SERVER_NAME:
		lease->server_name = parse_string(cfile);
		return;
	case RENEW:
		lease->renewal = parse_date(cfile);
		return;
	case REBIND:
		lease->rebind = parse_date(cfile);
		return;
	case EXPIRE:
		lease->expiry = parse_date(cfile);
		return;
	case OPTION:
		parse_option_decl(cfile, lease->options);
		return;
	default:
		parse_warn("expecting lease declaration.");
		skip_to_semi(cfile);
		break;
	}
	token = next_token(&val, cfile);
	if (token != SEMI) {
		parse_warn("expecting semicolon.");
		skip_to_semi(cfile);
	}
}
PyObject *py_device_discover(PyObject *cls, PyObject *args, PyObject *kwds) {
    PyObject *result = NULL;
    PyObject *tuner = NULL;
    char *target_ip_str = NULL;
    uint32_t target_ip = 0;
    int count = 0, i;
    char *kwlist[] = {"target_ip", NULL};
    struct hdhomerun_discover_device_t result_list[64];

    if(!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &target_ip_str))
        return NULL;

    if(target_ip_str) {
        target_ip = parse_ip_addr(target_ip_str);
        if (target_ip == 0) {
            PyErr_SetString(hdhomerun_device_error, "invalid ip address");
            return NULL;
        }
    }

    count = hdhomerun_discover_find_devices_custom(target_ip, HDHOMERUN_DEVICE_TYPE_TUNER, HDHOMERUN_DEVICE_ID_WILDCARD, result_list, 64);

    if(count < 0) {
        PyErr_SetString(hdhomerun_device_error, "error sending discover request");
        return NULL;
    }

    result = PyList_New((Py_ssize_t)count);
    if(!result) {
        return NULL;
    }

    if(count > 0) {
        for(i=0; i<count; i++) {
            tuner = PyObject_CallFunction(cls, "II", result_list[i].ip_addr, result_list[i].device_id);
            if(tuner == NULL) { Py_DECREF(result); return NULL; }
            if(PyList_SetItem(result, i, tuner) != 0) { Py_DECREF(result); return NULL; }
        }
    }

    return result;
}
Exemple #8
0
static void *kni_ifconfig(void *a)
{
	struct ifconfig_arg *arg = a;
	struct knidev *dev = arg->dev;
	struct conf_opt *opt = arg->opt;
	struct ifreq ifr;
	const char *opt1;
	in_addr_t addr;
	int mask;

	strcpy(ifr.ifr_name, opt->name);

	if (ioctl(sock_fd, SIOCGIFINDEX, &ifr, sizeof(ifr))) {
		fprintf(stderr, "%s: SIOCGIFINDEX: %s\n", opt->name, strerror(errno));
		arg->err = errno;
		return NULL;
	}

	dev->ifindex = ifr.ifr_ifindex;

	ioctl(sock_fd, SIOCGIFFLAGS, &ifr, sizeof(ifr));

	ifr.ifr_flags |= IFF_UP | IFF_NOARP;

	while (ioctl(sock_fd, SIOCSIFFLAGS, &ifr, sizeof(ifr)))
		sleep(1);

	opt1 = conf_get_subopt(opt, "ip-addr");
	if (opt1) {
		if (parse_ip_addr(opt1, &addr, &mask)) {
			arg->err = EINVAL;
			return NULL;
		}

		ipaddr_add(dev->ifindex, addr, mask);
	}

	arg->err = 0;

	return NULL;
}
Exemple #9
0
static int connect_server(const char *host, int port, int want_v4, char *errmsg, int msglen)
{
    struct sockaddr_storage sa;
    int fd = -1;
    
    errmsg[0] = '\0';
    if (parse_ip_addr(host, port, want_v4, &sa)) {
	fd = socket(sa.ss_family, SOCK_STREAM, 0);
	if (fd == -1) {
	    snprintf(errmsg, msglen, "failed to create a socket: %s\n", strerror(errno));
	    return -1;
	}
	
	if (connect(fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
	    snprintf(errmsg, msglen, "could not connect: %s\n", strerror(errno));
	    close(fd);
	    return -1;
	}
    }
    
    return fd;
}
Exemple #10
0
static int parse_config_line(char *line)
{
    char *val;
    
    /* remove the spaces around the string */
    line = trim(line);
    
    /* empty line? OK, done */
    if (strlen(line) == 0)
	return TRUE;
    
    /* is it a comment? */
    if (*line == '#')
	return TRUE;
    
    val = strchr(line, '=');
    if (!val) {
	fprintf(stderr, "Error: bad configuration line: \"%s\".\n", line);
	return FALSE;
    }

    /* the string at line now only has the param name and val is the value string */
    *val++ = '\0';
    
    /* remove more spaces */
    line = trim(line);
    val = trim(val);
    
    /*
     * set the actual option
     */
    
    if (!strcmp(line, "pidfile")) {
	if (!settings.pidfile)
	    settings.pidfile = strdup(val);
    }
    
    else if (!strcmp(line, "logfile")) {
	if (!settings.logfile)
	    settings.logfile = strdup(val);
    }
    
    else if (!strcmp(line, "port")) {
	if (!settings.port)
	    settings.port = atoi(val);
	if (settings.port < 1 || settings.port > 65535) {
	    fprintf(stderr, "Error: Port %d is outside the range of valid port numbers [1-65535].\n", settings.port);
	    return FALSE;
	}
    }
    
    else if (!strcmp(line, "ipv6addr")) {
	struct sockaddr_in6 tmp;
	if (!parse_ip_addr(val, (struct sockaddr*)&tmp, FALSE)) {
	    fprintf(stderr, "Error: %s is not a valid ipv6 address.\n", val);
	    return FALSE;
	}
	
	if (!settings.bind_addr_6.sin6_family != AF_INET6)
	    settings.bind_addr_6 = tmp;
    }
    
    else if (!strcmp(line, "ipv4addr")) {
	struct sockaddr_in tmp;
	if (!parse_ip_addr(val, (struct sockaddr*)&tmp, TRUE)) {
	    fprintf(stderr, "Error: %s is not a valid ipv4 address.\n", val);
	    return FALSE;
	}
	
	if (!settings.bind_addr_4.sin_family != AF_INET)
	    settings.bind_addr_4 = tmp;
    }
    
    else if (!strcmp(line, "disable_family")) {
	if (!settings.disable_ipv4 && !strcmp(val, "v4"))
	    settings.disable_ipv4 = TRUE;
	else if (!settings.disable_ipv6 && !strcmp(val, "v6"))
	    settings.disable_ipv6 = TRUE;
	else if (strcmp(val, "v4") && strcmp(val, "v6")) {
	    fprintf(stderr, "Error: the value for disable_family is either v4 or v6, not %s.\n", val);
	}
    }
    
    else if (!strcmp(line, "unixsocket")) {
	if (strlen(val) > SUN_PATH_MAX - 1) {
	    fprintf(stderr, "Error: The unix socket filename is too long.\n");
	    return FALSE;
	}
	    
	if (settings.bind_addr_unix.sun_family == 0) {
	    settings.bind_addr_unix.sun_family = AF_UNIX;
	    strncpy(settings.bind_addr_unix.sun_path, val, SUN_PATH_MAX - 1);
	    settings.bind_addr_unix.sun_path[SUN_PATH_MAX-1] = '\0';
	}
    }
    
    else if (!strcmp(line, "nodaemon")) {
	if (*val == '1' || !strcmp(val, "true"))
	    settings.nodaemon = TRUE;
	else if (*val != '0' && strcmp(val, "false")) {
	    fprintf(stderr, "Error: nodaemon may only be set to \"0\", \"1\", "
	                    "\"true\" or \"false\".\n");
	    return FALSE;
	}
	/* this option does not need to be set to false explicitly: that is the default value */
    }
    
    else if (!strcmp(line, "workdir")) {
	if (!settings.workdir)
	    settings.workdir = strdup(val);
    }
    
    else if (!strcmp(line, "client_timeout")) {
	if (!settings.client_timeout)
	    settings.client_timeout = atoi(val);
	
	if (settings.client_timeout < 30 ||
	    settings.client_timeout > (24 * 60 * 60)) {
	    fprintf(stderr, "Error: the value for client_timeout must be in the"
	                    " range [30, 86400].\n");
	    return FALSE;
	}
    }
    
    else if (!strcmp(line, "dbhost")) {
	if (!settings.dbhost)
	    settings.dbhost = strdup(val);
    }
    
    else if (!strcmp(line, "dbport")) {
	if (!settings.dbport)
	    settings.dbport = strdup(val);
    }
    
    else if (!strcmp(line, "dbuser")) {
	if (!settings.dbuser)
	    settings.dbuser = strdup(val);
    }
    
    else if (!strcmp(line, "dbpass")) {
	if (!settings.dbpass)
	    settings.dbpass = strdup(val);
    }
    
    else if (!strcmp(line, "dbname")) {
	if (!settings.dbname)
	    settings.dbname = strdup(val);
    }
    
    else
	/* it's a warning, no need to return FALSE */
	fprintf(stderr, "Warning: unrecognized option \"%s\".\n", line);
	
    return TRUE;
}
Exemple #11
0
static int read_parameters(int argc, char *argv[], char **conffile,
			   int *request_kill, int *show_message)
{
    int opt;
    
    while ((opt = getopt(argc, argv, "4:6:a:c:D:d:H:hkl:mno:P:p:s:t:u:w:")) != -1) {
	switch (opt) {
	    case '4': /* bind address */
		if (!parse_ip_addr(optarg, (struct sockaddr*)&settings.bind_addr_4, TRUE)) {
		    fprintf(stderr, "Error: \"%s\" was not recognized as an ipv4 address.", optarg);
		    return FALSE;
		}
		break;
		
	    case '6': /* bind address */
		if (!parse_ip_addr(optarg, (struct sockaddr*)&settings.bind_addr_6, FALSE)) {
		    fprintf(stderr, "Error: \"%s\" was not recognized as an ipv6 address.", optarg);
		    return FALSE;
		}
		break;
		
	    case 'a':
		settings.dbpass = strdup(optarg);
		break;
		
	    case 'c': /* config file */
		*conffile = optarg;
		break;
		
	    case 'D':
		settings.dbname = strdup(optarg);
		break;
		
	    case 'd': /* disable ipv4 / ipv6 */
		if (!strcmp(optarg, "v4"))
		    settings.disable_ipv4 = TRUE;
		else if (!strcmp(optarg, "v6"))
		    settings.disable_ipv6 = TRUE;
		else {
		    fprintf(stderr, "Error: \"v4"" or \"v6\" expected after parameter -d.");
		    return FALSE;
		}
		break;
		
	    case 'H':
		settings.dbhost = strdup(optarg);
		break;
		
	    case 'k': /* kill server */
		*request_kill = TRUE;
		break;
		
	    case 'l': /* log file */
		settings.logfile = strdup(optarg);
		break;
		
	    case 'm':
		*show_message = TRUE;
		break;
		
	    case 'n': /* don't daemonize */
		settings.nodaemon = TRUE;
		break;
		
	    case 'o':
		settings.dbport = strdup(optarg);
		break;
		
	    case 'P': /* port number */
		settings.port = atoi(optarg);
		if (settings.port < 1 || settings.port > 65535) {
		    fprintf(stderr, "Error: Port %d is outside the range of valid port numbers [1-65535].\n", settings.port);
		    return FALSE;
		}
		break;
		
	    case 'p': /* pid file */
		settings.pidfile = strdup(optarg);
		break;
		
	    case 's':
		if (strlen(optarg) > SUN_PATH_MAX - 1) {
		    fprintf(stderr, "Error: The unix socket filename is too long.\n");
		    return FALSE;
		}
		    
		settings.bind_addr_unix.sun_family = AF_UNIX;
		strncpy(settings.bind_addr_unix.sun_path, optarg, SUN_PATH_MAX - 1);
		settings.bind_addr_unix.sun_path[SUN_PATH_MAX-1] = '\0';
		break;
		
	    case 't':
		settings.client_timeout = atoi(optarg);
		if (settings.client_timeout <= 30 ||
		    settings.client_timeout > (24 * 60 * 60)) {
		    fprintf(stderr, "Error: Silly value %s given as the client timeout.\n",
			    optarg);
		    return FALSE;
		}
		break;
		
	    case 'u':
		settings.dbuser = strdup(optarg);
		break;
		
	    case 'w': /* work dir */
		settings.workdir = strdup(optarg);
		break;
		
	    case 'h': /* help */
		return FALSE;
		
	    default: /* unrecognized */
		fprintf(stderr, "Error: unknown option '%c'.\n", optopt);
		return FALSE;
	}
    }
    
    return TRUE;
}
Exemple #12
0
int
parse_option_decl(FILE *cfile, struct option_data *options)
{
	char		*val;
	int		 token;
	u_int8_t	 buf[4];
	u_int8_t	 hunkbuf[1024];
	int		 hunkix = 0;
	char		*fmt;
	struct iaddr	 ip_addr;
	u_int8_t	*dp;
	int		 len, code;
	int		 nul_term = 0;

	token = next_token(&val, cfile);
	if (!is_identifier(token)) {
		parse_warn("expecting identifier after option keyword.");
		if (token != ';')
			skip_to_semi(cfile);
		return (-1);
	}

	/* Look up the actual option info. */
	fmt = NULL;
	for (code = 0; code < 256; code++)
		if (strcmp(dhcp_options[code].name, val) == 0)
			break;

	if (code > 255) {
		parse_warn("no option named %s", val);
		skip_to_semi(cfile);
		return (-1);
	}

	/* Parse the option data... */
	do {
		for (fmt = dhcp_options[code].format; *fmt; fmt++) {
			if (*fmt == 'A')
				break;
			switch (*fmt) {
			case 'X':
				len = parse_X(cfile, &hunkbuf[hunkix],
				    sizeof(hunkbuf) - hunkix);
				hunkix += len;
				break;
			case 't': /* Text string... */
				token = next_token(&val, cfile);
				if (token != TOK_STRING) {
					parse_warn("expecting string.");
					skip_to_semi(cfile);
					return (-1);
				}
				len = strlen(val);
				if (hunkix + len + 1 > sizeof(hunkbuf)) {
					parse_warn("option data buffer %s",
					    "overflow");
					skip_to_semi(cfile);
					return (-1);
				}
				memcpy(&hunkbuf[hunkix], val, len + 1);
				nul_term = 1;
				hunkix += len;
				break;
			case 'I': /* IP address. */
				if (!parse_ip_addr(cfile, &ip_addr))
					return (-1);
				len = ip_addr.len;
				dp = ip_addr.iabuf;
alloc:
				if (hunkix + len > sizeof(hunkbuf)) {
					parse_warn("option data buffer "
					    "overflow");
					skip_to_semi(cfile);
					return (-1);
				}
				memcpy(&hunkbuf[hunkix], dp, len);
				hunkix += len;
				break;
			case 'L':	/* Unsigned 32-bit integer... */
			case 'l':	/* Signed 32-bit integer... */
				token = next_token(&val, cfile);
				if (token != TOK_NUMBER) {
need_number:
					parse_warn("expecting number.");
					if (token != ';')
						skip_to_semi(cfile);
					return (-1);
				}
				convert_num(buf, val, 0, 32);
				len = 4;
				dp = buf;
				goto alloc;
			case 's':	/* Signed 16-bit integer. */
			case 'S':	/* Unsigned 16-bit integer. */
				token = next_token(&val, cfile);
				if (token != TOK_NUMBER)
					goto need_number;
				convert_num(buf, val, 0, 16);
				len = 2;
				dp = buf;
				goto alloc;
			case 'b':	/* Signed 8-bit integer. */
			case 'B':	/* Unsigned 8-bit integer. */
				token = next_token(&val, cfile);
				if (token != TOK_NUMBER)
					goto need_number;
				convert_num(buf, val, 0, 8);
				len = 1;
				dp = buf;
				goto alloc;
			case 'f': /* Boolean flag. */
				token = next_token(&val, cfile);
				if (!is_identifier(token)) {
					parse_warn("expecting identifier.");
bad_flag:
					if (token != ';')
						skip_to_semi(cfile);
					return (-1);
				}
				if (!strcasecmp(val, "true") ||
				    !strcasecmp(val, "on"))
					buf[0] = 1;
				else if (!strcasecmp(val, "false") ||
				    !strcasecmp(val, "off"))
					buf[0] = 0;
				else {
					parse_warn("expecting boolean.");
					goto bad_flag;
				}
				len = 1;
				dp = buf;
				goto alloc;
			default:
				warning("Bad format %c in parse_option_param.",
				    *fmt);
				skip_to_semi(cfile);
				return (-1);
			}
		}
		token = next_token(&val, cfile);
	} while (*fmt == 'A' && token == ',');

	if (token != ';') {
		parse_warn("semicolon expected.");
		skip_to_semi(cfile);
		return (-1);
	}

	options[code].data = malloc(hunkix + nul_term);
	if (!options[code].data)
		error("out of memory allocating option data.");
	memcpy(options[code].data, hunkbuf, hunkix + nul_term);
	options[code].len = hunkix;
	return (code);
}
static ftnPtr
parse_ftn(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur, struct mpls_switch *sw) {
    ftnPtr ret = NULL;
	nhlfePtr nhlfe_entry;
    xmlChar *str;
    uint32_t ip_wildcards;

    struct ofp_match match; // in network byte order

	// initialize match
	memset(&match, 0, sizeof(struct ofp_match));
	match.mpls_label1 = htonl(MPLS_INVALID_LABEL);
	match.mpls_label2 = htonl(MPLS_INVALID_LABEL);
	// wildcard everything by default
	match.wildcards = htonl((OFPFW_ALL) ^ ((OFPFW_MPLS_L1) | (OFPFW_MPLS_L2)));

    // allocate the struct
    ret = (ftnPtr) malloc(sizeof(ftn));
    if (ret == NULL) {
        fprintf(stderr,"out of memory\n");
		return(NULL);
    }
    memset(ret, 0, sizeof(ftn));

    /* We don't care what the top level element name is */
    cur = cur->xmlChildrenNode;
    while (cur != NULL) {
    	str = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
        if (!xmlStrcmp(cur->name, (const xmlChar *) "dl_type")) {
			ret->FEC.dl_type = (uint16_t)atoi((char *)str);
			match.dl_type = htons(ret->FEC.dl_type);
			match.wildcards = match.wildcards ^ htonl(OFPFW_DL_TYPE);
		}
        else if (!xmlStrcmp(cur->name, (const xmlChar *) "dl_vlan")) {
        	ret->FEC.dl_vlan = (uint16_t)atoi((char *)str);
        	match.dl_vlan = htons(ret->FEC.dl_vlan);
        	match.wildcards = match.wildcards ^ htonl(OFPFW_DL_VLAN);
        }
        else if (!xmlStrcmp(cur->name, (const xmlChar *) "in_port")) {
			ret->FEC.in_port = (uint16_t)atoi((char *)str);
			match.in_port = htons(ret->FEC.in_port);
			match.wildcards = match.wildcards ^ htonl(OFPFW_IN_PORT);
		}
        else if (!xmlStrcmp(cur->name, (const xmlChar *) "dl_src")) {
			eth_atoi((char *)str, ret->FEC.dl_src);
			// already in network byte order
			memcpy(&match.dl_src,  &ret->FEC.dl_src, ETH_ADDR_LEN);
			match.wildcards = match.wildcards ^ htonl(OFPFW_DL_SRC);
		}
        else if (!xmlStrcmp(cur->name, (const xmlChar *) "dl_dst")) {
			eth_atoi((char *)str, ret->FEC.dl_dst);
			// already in network byte order
			memcpy(&match.dl_dst,  &ret->FEC.dl_dst, ETH_ADDR_LEN);
			match.wildcards = match.wildcards ^ htonl(OFPFW_DL_DST);
		}
        else if (!xmlStrcmp(cur->name, (const xmlChar *) "nw_src")) {
			ret->FEC.nw_src = ntohl(parse_ip_addr((char *)str, &ip_wildcards));
			match.nw_src = htonl(ret->FEC.nw_src);
			match.wildcards = (match.wildcards ^ ntohl(OFPFW_NW_SRC_MASK)) | ip_wildcards;
		}
        else if (!xmlStrcmp(cur->name, (const xmlChar *) "nw_dst")) {
			ret->FEC.nw_dst = ntohl(parse_ip_addr((char *)str, &ip_wildcards));
			match.nw_dst = htonl(ret->FEC.nw_dst);
			match.wildcards = (match.wildcards ^ ntohl(OFPFW_NW_DST_MASK)) | ip_wildcards;
		}
        else if (!xmlStrcmp(cur->name, (const xmlChar *) "nw_proto")) {
			ret->FEC.nw_proto = (uint16_t)atoi((char *)str);
			match.nw_proto = ret->FEC.nw_proto;
			match.wildcards = match.wildcards ^ htonl(OFPFW_NW_PROTO);
		}
        else if (!xmlStrcmp(cur->name, (const xmlChar *) "tp_src")) {
			ret->FEC.tp_src = (uint16_t)atoi((char *)str);
			match.tp_src = htons(ret->FEC.tp_src);
			match.wildcards = match.wildcards ^ htonl(OFPFW_TP_SRC);
		}
        else if (!xmlStrcmp(cur->name, (const xmlChar *) "tp_dst")) {
       		ret->FEC.tp_dst = (uint16_t)atoi((char *)str);
       		match.tp_dst = htons(ret->FEC.tp_dst);
       		match.wildcards = match.wildcards ^ htonl(OFPFW_TP_DST);
      	}

		// XXX parse_nhlfe must be called last otherwise the match struct
		// will be incomplete
        // Note: assumes only one NHFLE per entry
        else if ((!xmlStrcmp(cur->name, (const xmlChar *) "NHLFE"))) {
        	nhlfe_entry = parse_nhlfe(doc, ns, cur, sw, &match);
			if (nhlfe_entry) {
	//			printf("parse_ftn: got an nhlfe_entry! actions_len = %u\n", nhlfe_entry->actions_len);
				nhlfe_entry->next_entry = NULL;
				ret->nhlfe = nhlfe_entry;
			}
		}
        // XXX FEC stores all but the wildcards in host byte order
        // wildcards bitmap is in network byte order
        ret->FEC.wildcards = match.wildcards;

        free(str);
		cur = cur->next;
    }

    return(ret);
}
static int parse_ip(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
{
	int res = -1;
	int argc = *argc_p;
	char **argv = *argv_p;

	if (argc < 2)
		return -1;

	if (strcmp(*argv, "src") == 0) {
		NEXT_ARG();
		res = parse_ip_addr(&argc, &argv, sel, 12);
		goto done;
	}
	if (strcmp(*argv, "dst") == 0) {
		NEXT_ARG();
		res = parse_ip_addr(&argc, &argv, sel, 16);
		goto done;
	}
	//------------->richie: add to parse ip range
	if (strcmp(*argv, "ssrc") == 0) {
		//fprintf(stderr, "enter ssrc\n");
		NEXT_ARG();
		res = nk_parse_ip_addr(&argc, &argv, sel, 12, TC_SSRC_IP);
		goto done;
	}
	if (strcmp(*argv, "esrc") == 0) {
		//fprintf(stderr, "enter esrc\n");
		NEXT_ARG();
		res = nk_parse_ip_addr(&argc, &argv, sel, 12, TC_ESRC_IP);
		goto done;
	}
	if (strcmp(*argv, "sdst") == 0) {
		//fprintf(stderr, "enter sdst\n");
		NEXT_ARG();
		res = nk_parse_ip_addr(&argc, &argv, sel, 16, TC_SDST_IP);
		goto done;
	}
	if (strcmp(*argv, "edst") == 0) {
		//fprintf(stderr, "enter edst\n");
		NEXT_ARG();
		res = nk_parse_ip_addr(&argc, &argv, sel, 16, TC_EDST_IP);
		goto done;
	}
	//<--------------------
	if (strcmp(*argv, "tos") == 0 ||
	    matches(*argv, "dsfield") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 1, 0);
		goto done;
	}
	if (strcmp(*argv, "ihl") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 0, 0);
		goto done;
	}
	if (strcmp(*argv, "protocol") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 9, 0);
		goto done;
	}
	if (matches(*argv, "precedence") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 1, 0);
		goto done;
	}
	if (strcmp(*argv, "nofrag") == 0) {
		argc--; argv++;
		res = pack_key16(sel, 0, 0x3FFF, 6, 0);
		goto done;
	}
	if (strcmp(*argv, "firstfrag") == 0) {
		argc--; argv++;
		res = pack_key16(sel, 0, 0x1FFF, 6, 0);
		goto done;
	}
	if (strcmp(*argv, "df") == 0) {
		argc--; argv++;
		res = pack_key16(sel, 0x4000, 0x4000, 6, 0);
		goto done;
	}
	if (strcmp(*argv, "mf") == 0) {
		argc--; argv++;
		res = pack_key16(sel, 0x2000, 0x2000, 6, 0);
		goto done;
	}
	if (strcmp(*argv, "dport") == 0) {
		NEXT_ARG();
		res = parse_u16(&argc, &argv, sel, 22, 0);
		goto done;
	}
	if (strcmp(*argv, "sport") == 0) {
		NEXT_ARG();
		res = parse_u16(&argc, &argv, sel, 20, 0);
		goto done;
	}
	// 2004/05/12 Ryan : added to support QoS for port range setting
	// -->
	if (strcmp(*argv, "ssport") == 0) {
		NEXT_ARG();
		//printf("enter ssport\n");
//fprintf(stderr, "enter ssport!!!!!!!!!!!\n");

		res = nk_parse_u16(&argc, &argv, sel, 20, 0 , TC_SSRC_PORT);
		goto done;
	}
	if (strcmp(*argv, "esport") == 0) {
		NEXT_ARG();
		//printf("enter esport\n");
//fprintf(stderr, "enter esport!!!!!!!!!!!\n");
		res = nk_parse_u16(&argc, &argv, sel, 20, 0 , TC_ESRC_PORT);
		goto done;
	}
	if (strcmp(*argv, "sdport") == 0) {
		NEXT_ARG();
		//printf("enter sdport\n");
//fprintf(stderr, "enter sdport!!!!!!!!!!!\n");
		res = nk_parse_u16(&argc, &argv, sel, 22, 0 , TC_SDST_PORT);
		goto done;
	}
	if (strcmp(*argv, "edport") == 0) {
		NEXT_ARG();
		//printf("enter edport\n");
//fprintf(stderr, "enter edport!!!!!!!!!!!\n");
		res = nk_parse_u16(&argc, &argv, sel, 22, 0 , TC_EDST_PORT);
		goto done;
	}
	// <--

	//2004/09/29 richie: add to support inbound QoS by interface
	if (strcmp(*argv, "wanif") == 0) {
		NEXT_ARG();
		//printf("enter wanif!!!!!!!!!!!!!!!!!!!!!!!!!!11");
		res = nk_parse_u16(&argc, &argv, sel, 100, 0 , TC_WANIF);
		goto done;
	}
	//
	//2004/09/29 richie: add to support inbound QoS by ALG type
	if (strcmp(*argv, "ap_type") == 0) {
		NEXT_ARG();
		//printf("enter ap_type!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
		res = nk_parse_u16(&argc, &argv, sel, 120, 0 , TC_AP_TYPE);
		goto done;
	}
	//

	if (strcmp(*argv, "icmp_type") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 20, 0);
		goto done;
	}
	if (strcmp(*argv, "icmp_code") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 20, 1);
		goto done;
	}
	return -1;

done:
	*argc_p = argc;
	*argv_p = argv;
	return res;
}
Exemple #15
0
struct option *
parse_option_decl(FILE *cfile, struct option_data *options)
{
	char		*val;
	int		 token;
	u_int8_t	 buf[4];
	u_int8_t	 hunkbuf[1024];
	int		 hunkix = 0;
	char		*vendor;
	char		*fmt;
	struct universe	*universe;
	struct option	*option;
	struct iaddr	 ip_addr;
	u_int8_t	*dp;
	int		 len;
	int		 nul_term = 0;

	token = next_token(&val, cfile);
	if (!is_identifier(token)) {
		parse_warn("expecting identifier after option keyword.");
		if (token != SEMI)
			skip_to_semi(cfile);
		return (NULL);
	}
	if ((vendor = strdup(val)) == NULL)
		error("no memory for vendor information.");

	token = peek_token(&val, cfile);
	if (token == DOT) {
		/* Go ahead and take the DOT token... */
		token = next_token(&val, cfile);

		/* The next token should be an identifier... */
		token = next_token(&val, cfile);
		if (!is_identifier(token)) {
			parse_warn("expecting identifier after '.'");
			if (token != SEMI)
				skip_to_semi(cfile);
			return (NULL);
		}

		/* Look up the option name hash table for the specified
		   vendor. */
		universe = ((struct universe *)hash_lookup(&universe_hash,
		    (unsigned char *)vendor, 0));
		/* If it's not there, we can't parse the rest of the
		   declaration. */
		if (!universe) {
			parse_warn("no vendor named %s.", vendor);
			skip_to_semi(cfile);
			return (NULL);
		}
	} else {
		/* Use the default hash table, which contains all the
		   standard dhcp option names. */
		val = vendor;
		universe = &dhcp_universe;
	}

	/* Look up the actual option info... */
	option = (struct option *)hash_lookup(universe->hash,
	    (unsigned char *)val, 0);

	/* If we didn't get an option structure, it's an undefined option. */
	if (!option) {
		if (val == vendor)
			parse_warn("no option named %s", val);
		else
			parse_warn("no option named %s for vendor %s",
				    val, vendor);
		skip_to_semi(cfile);
		return (NULL);
	}

	/* Free the initial identifier token. */
	free(vendor);

	/* Parse the option data... */
	do {
		for (fmt = option->format; *fmt; fmt++) {
			if (*fmt == 'A')
				break;
			switch (*fmt) {
			case 'X':
				len = parse_X(cfile, &hunkbuf[hunkix],
				    sizeof(hunkbuf) - hunkix);
				hunkix += len;
				break;
			case 't': /* Text string... */
				token = next_token(&val, cfile);
				if (token != STRING) {
					parse_warn("expecting string.");
					skip_to_semi(cfile);
					return (NULL);
				}
				len = strlen(val);
				if (hunkix + len + 1 > sizeof(hunkbuf)) {
					parse_warn("option data buffer %s",
					    "overflow");
					skip_to_semi(cfile);
					return (NULL);
				}
				memcpy(&hunkbuf[hunkix], val, len + 1);
				nul_term = 1;
				hunkix += len;
				break;
			case 'I': /* IP address. */
				if (!parse_ip_addr(cfile, &ip_addr))
					return (NULL);
				len = ip_addr.len;
				dp = ip_addr.iabuf;
alloc:
				if (hunkix + len > sizeof(hunkbuf)) {
					parse_warn("option data buffer "
					    "overflow");
					skip_to_semi(cfile);
					return (NULL);
				}
				memcpy(&hunkbuf[hunkix], dp, len);
				hunkix += len;
				break;
			case 'L':	/* Unsigned 32-bit integer... */
			case 'l':	/* Signed 32-bit integer... */
				token = next_token(&val, cfile);
				if (token != NUMBER) {
need_number:
					parse_warn("expecting number.");
					if (token != SEMI)
						skip_to_semi(cfile);
					return (NULL);
				}
				convert_num(buf, val, 0, 32);
				len = 4;
				dp = buf;
				goto alloc;
			case 's':	/* Signed 16-bit integer. */
			case 'S':	/* Unsigned 16-bit integer. */
				token = next_token(&val, cfile);
				if (token != NUMBER)
					goto need_number;
				convert_num(buf, val, 0, 16);
				len = 2;
				dp = buf;
				goto alloc;
			case 'b':	/* Signed 8-bit integer. */
			case 'B':	/* Unsigned 8-bit integer. */
				token = next_token(&val, cfile);
				if (token != NUMBER)
					goto need_number;
				convert_num(buf, val, 0, 8);
				len = 1;
				dp = buf;
				goto alloc;
			case 'f': /* Boolean flag. */
				token = next_token(&val, cfile);
				if (!is_identifier(token)) {
					parse_warn("expecting identifier.");
bad_flag:
					if (token != SEMI)
						skip_to_semi(cfile);
					return (NULL);
				}
				if (!strcasecmp(val, "true") ||
				    !strcasecmp(val, "on"))
					buf[0] = 1;
				else if (!strcasecmp(val, "false") ||
				    !strcasecmp(val, "off"))
					buf[0] = 0;
				else {
					parse_warn("expecting boolean.");
					goto bad_flag;
				}
				len = 1;
				dp = buf;
				goto alloc;
			default:
				warning("Bad format %c in parse_option_param.",
				    *fmt);
				skip_to_semi(cfile);
				return (NULL);
			}
		}
		token = next_token(&val, cfile);
	} while (*fmt == 'A' && token == COMMA);

	if (token != SEMI) {
		parse_warn("semicolon expected.");
		skip_to_semi(cfile);
		return (NULL);
	}

	options[option->code].data = malloc(hunkix + nul_term);
	if (!options[option->code].data)
		error("out of memory allocating option data.");
	memcpy(options[option->code].data, hunkbuf, hunkix + nul_term);
	options[option->code].len = hunkix;
	return (option);
}