Esempio n. 1
0
/* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man
 * page) into 'fm' for sending the specified flow_mod 'command' to a switch.
 * If 'actions' is specified, an action must be in 'string' and may be expanded
 * or reallocated.
 *
 * To parse syntax for an OFPT_FLOW_MOD (or NXT_FLOW_MOD), use an OFPFC_*
 * constant for 'command'.  To parse syntax for an OFPST_FLOW or
 * OFPST_AGGREGATE (or NXST_FLOW or NXST_AGGREGATE), use -1 for 'command'. */
void
parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
              bool verbose)
{
    enum {
        F_OUT_PORT = 1 << 0,
        F_ACTIONS = 1 << 1,
        F_TIMEOUT = 1 << 3,
        F_PRIORITY = 1 << 4,
        F_FLAGS = 1 << 5,
    } fields;
    char *string = xstrdup(str_);
    char *save_ptr = NULL;
    char *act_str = NULL;
    char *name;

    switch (command) {
    case -1:
        fields = F_OUT_PORT;
        break;

    case OFPFC_ADD:
        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
        break;

    case OFPFC_DELETE:
        fields = F_OUT_PORT;
        break;

    case OFPFC_DELETE_STRICT:
        fields = F_OUT_PORT | F_PRIORITY;
        break;

    case OFPFC_MODIFY:
        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
        break;

    case OFPFC_MODIFY_STRICT:
        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
        break;

    default:
        NOT_REACHED();
    }

    match_init_catchall(&fm->match);
    fm->priority = OFP_DEFAULT_PRIORITY;
    fm->cookie = htonll(0);
    fm->cookie_mask = htonll(0);
    if (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT) {
        /* For modify, by default, don't update the cookie. */
        fm->new_cookie = htonll(UINT64_MAX);
    } else{
        fm->new_cookie = htonll(0);
    }
    fm->table_id = 0xff;
    fm->command = command;
    fm->idle_timeout = OFP_FLOW_PERMANENT;
    fm->hard_timeout = OFP_FLOW_PERMANENT;
    fm->buffer_id = UINT32_MAX;
    fm->out_port = OFPP_NONE;
    fm->flags = 0;
    if (fields & F_ACTIONS) {
        act_str = strstr(string, "action");
        if (!act_str) {
            ofp_fatal(str_, verbose, "must specify an action");
        }
        *act_str = '\0';

        act_str = strchr(act_str + 1, '=');
        if (!act_str) {
            ofp_fatal(str_, verbose, "must specify an action");
        }

        act_str++;
    }
    for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
         name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
        const struct protocol *p;

        if (parse_protocol(name, &p)) {
            match_set_dl_type(&fm->match, htons(p->dl_type));
            if (p->nw_proto) {
                match_set_nw_proto(&fm->match, p->nw_proto);
            }
        } else if (fields & F_FLAGS && !strcmp(name, "send_flow_rem")) {
            fm->flags |= OFPFF_SEND_FLOW_REM;
        } else if (fields & F_FLAGS && !strcmp(name, "check_overlap")) {
            fm->flags |= OFPFF_CHECK_OVERLAP;
        } else {
            char *value;

            value = strtok_r(NULL, ", \t\r\n", &save_ptr);
            if (!value) {
                ofp_fatal(str_, verbose, "field %s missing value", name);
            }

            if (!strcmp(name, "table")) {
                fm->table_id = str_to_table_id(value);
            } else if (!strcmp(name, "out_port")) {
                if (!ofputil_port_from_string(name, &fm->out_port)) {
                    ofp_fatal(str_, verbose, "%s is not a valid OpenFlow port",
                              name);
                }
            } else if (fields & F_PRIORITY && !strcmp(name, "priority")) {
                fm->priority = str_to_u16(value, name);
            } else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) {
                fm->idle_timeout = str_to_u16(value, name);
            } else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) {
                fm->hard_timeout = str_to_u16(value, name);
            } else if (!strcmp(name, "cookie")) {
                char *mask = strchr(value, '/');

                if (mask) {
                    /* A mask means we're searching for a cookie. */
                    if (command == OFPFC_ADD) {
                        ofp_fatal(str_, verbose, "flow additions cannot use "
                                  "a cookie mask");
                    }
                    *mask = '\0';
                    fm->cookie = htonll(str_to_u64(value));
                    fm->cookie_mask = htonll(str_to_u64(mask+1));
                } else {
                    /* No mask means that the cookie is being set. */
                    if (command != OFPFC_ADD && command != OFPFC_MODIFY
                            && command != OFPFC_MODIFY_STRICT) {
                        ofp_fatal(str_, verbose, "cannot set cookie");
                    }
                    fm->new_cookie = htonll(str_to_u64(value));
                }
            } else if (mf_from_name(name)) {
                parse_field(mf_from_name(name), value, &fm->match);
            } else if (!strcmp(name, "duration")
                       || !strcmp(name, "n_packets")
                       || !strcmp(name, "n_bytes")) {
                /* Ignore these, so that users can feed the output of
                 * "ovs-ofctl dump-flows" back into commands that parse
                 * flows. */
            } else {
                ofp_fatal(str_, verbose, "unknown keyword %s", name);
            }
        }
    }
    if (!fm->cookie_mask && fm->new_cookie == htonll(UINT64_MAX)
            && (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT)) {
        /* On modifies without a mask, we are supposed to add a flow if
         * one does not exist.  If a cookie wasn't been specified, use a
         * default of zero. */
        fm->new_cookie = htonll(0);
    }
    if (fields & F_ACTIONS) {
        struct ofpbuf ofpacts;

        ofpbuf_init(&ofpacts, 32);
        str_to_inst_ofpacts(&fm->match.flow, act_str, &ofpacts);
        fm->ofpacts_len = ofpacts.size;
        fm->ofpacts = ofpbuf_steal_data(&ofpacts);
    } else {
        fm->ofpacts_len = 0;
        fm->ofpacts = NULL;
    }

    free(string);
}
Esempio n. 2
0
static const struct token *
match_token(char *word, const struct token table[])
{
	u_int			 i, match = 0;
	unsigned long int	 ulval;
	const struct token	*t = NULL;
	char			*ep;

	for (i = 0; table[i].type != ENDTOKEN; i++) {
		switch (table[i].type) {
		case NOTOKEN:
			if (word == NULL || strlen(word) == 0) {
				match++;
				t = &table[i];
			}
			break;
		case KEYWORD:

			if (word != NULL && strncmp(word, table[i].keyword,
			    strlen(word)) == 0) {
				match++;
				t = &table[i];
				if (t->value)
					res.action = t->value;
			}
			break;
		case PPP_ID:
			if (word == NULL)
				break;
			errno = 0;
			ulval = strtoul(word, &ep, 10);
			if (isdigit((unsigned char)*word) && *ep == '\0' &&
			    !(errno == ERANGE && ulval == ULONG_MAX)) {
				res.ppp_id = ulval;
				res.has_ppp_id = 1;
				match++;
				t = &table[i];
			}
			break;
		case ADDRESS:
		    {
			struct sockaddr_in sin4 = {
				.sin_family = AF_INET,
				.sin_len = sizeof(struct sockaddr_in)
			};
			struct sockaddr_in6 sin6 = {
				.sin6_family = AF_INET6,
				.sin6_len = sizeof(struct sockaddr_in6)
			};
			if (word == NULL)
				break;
			if (inet_pton(AF_INET, word, &sin4.sin_addr) == 1)
				memcpy(&res.address, &sin4, sin4.sin_len);
			else
			if (inet_pton(AF_INET6, word, &sin6.sin6_addr) == 1)
				memcpy(&res.address, &sin6, sin6.sin6_len);
			else
				break;
			match++;
			t = &table[i];
		    }
			break;
		case INTERFACE:
			if (word == NULL)
				break;
			res.interface = word;
			match++;
			t = &table[i];
			break;
		case PROTOCOL:
			if (word == NULL)
				break;
			if ((res.protocol = parse_protocol(word)) == 
			    PROTO_UNSPEC)
				break;
			match++;
			t = &table[i];
			break;
		case REALM:
			if (word == NULL)
				break;
			res.realm = word;
			match++;
			t = &table[i];
			break;
		case USERNAME:
			if (word == NULL)
				break;
			res.username = word;
			match++;
			t = &table[i];
			break;
		case ENDTOKEN:
			break;
		}
	}

	if (match != 1) {
		if (word == NULL)
			fprintf(stderr, "missing argument:\n");
		else if (match > 1)
			fprintf(stderr, "ambiguous argument: %s\n", word);
		else if (match < 1)
			fprintf(stderr, "unknown argument: %s\n", word);
		return (NULL);
	}

	return (t);
}

static void
show_valid_args(const struct token table[])
{
	int	i;

	for (i = 0; table[i].type != ENDTOKEN; i++) {
		switch (table[i].type) {
		case NOTOKEN:
			fprintf(stderr, "  <cr>\n");
			break;
		case KEYWORD:
			fprintf(stderr, "  %s\n", table[i].keyword);
			break;
		case PPP_ID:
			fprintf(stderr, "  <ppp-id>\n");
			break;
		case ADDRESS:
			fprintf(stderr, "  <address>\n");
			break;
		case INTERFACE:
			fprintf(stderr, "  <interface>\n");
			break;
		case PROTOCOL:
			fprintf(stderr, "  [ pppoe | l2tp | pptp | sstp ]\n");
			break;
		case REALM:
			fprintf(stderr, "  <realm>\n");
			break;
		case USERNAME:
			fprintf(stderr, "  <username>\n");
			break;
		case ENDTOKEN:
			break;
		}
	}
}

enum protocol
parse_protocol(const char *str)
{
	return
	    (strcasecmp(str, "PPTP" ) == 0)? PPTP  :
	    (strcasecmp(str, "L2TP" ) == 0)? L2TP  :
	    (strcasecmp(str, "PPPoE") == 0)? PPPOE :
	    (strcasecmp(str, "SSTP" ) == 0)? SSTP  : PROTO_UNSPEC;
}
Esempio n. 3
0
File: url.c Progetto: BeQ/webserver
static ret_t
cherokee_url_parse_guts (cherokee_url_t    *url,
			 cherokee_buffer_t *url_buf,
			 cherokee_buffer_t *user_ret,
			 cherokee_buffer_t *password_ret)
{
	ret_t    ret;
	cuint_t  len = 0 ;
	char    *port;
	char    *slash;
	char    *server;
	char    *arroba;
	char    *tmp;

	/* Drop protocol, if exists..
	 */
	ret = parse_protocol (url, url_buf->buf, &len);
	if (unlikely(ret < ret_ok)) return ret_error;

	tmp = url_buf->buf + len;

	/* User (and password)
	 */
	arroba = strchr (tmp, '@');
	if (arroba != NULL) {
		char *sep;

		sep = strchr (tmp, ':');
		if (sep == NULL) {
			cherokee_buffer_clean (user_ret);
			cherokee_buffer_add (user_ret, tmp, arroba - tmp);
		} else {
			cherokee_buffer_clean (user_ret);
			cherokee_buffer_add (user_ret, tmp, sep - tmp);
			sep++;
			cherokee_buffer_clean (password_ret);
			cherokee_buffer_add (password_ret, sep, arroba - sep);
		}

		tmp = arroba + 1;
	}

	/* Split the host/request
	 */
	server = tmp;
	len    = strlen (server);
	slash  = strpbrk (server, "/\\");

	if (slash == NULL) {
		cherokee_buffer_add (&url->request, "/", 1);
		cherokee_buffer_add (&url->host, server, len);
	} else {
		cherokee_buffer_add (&url->request, slash, len-(slash-server));
		cherokee_buffer_add (&url->host, server, slash-server);
	}

	/* Drop up the port, if exists..
	 */
	port = strchr (url->host.buf, ':');
	if (port != NULL) {

		/* Read port number
		 */
		if (slash != NULL) *slash = '\0';
		URL_PORT(url) = atoi (port+1);
		if (slash != NULL) *slash =  '/';

		/* .. and remove it
		 */
		ret = cherokee_buffer_drop_ending (&url->host, strlen(port));
		if (unlikely(ret < ret_ok)) return ret;
	}

#if 0
	cherokee_url_print (url);
#endif

	return ret_ok;
}
Esempio n. 4
0
/* Parses a specification of a flow from 's' into 'flow'.  's' must take the
 * form FIELD=VALUE[,FIELD=VALUE]... where each FIELD is the name of a
 * mf_field.  Fields must be specified in a natural order for satisfying
 * prerequisites.
 *
 * Returns NULL on success, otherwise a malloc()'d string that explains the
 * problem. */
char *
parse_ofp_exact_flow(struct flow *flow, const char *s)
{
    char *pos, *key, *value_s;
    char *error = NULL;
    char *copy;

    memset(flow, 0, sizeof *flow);

    pos = copy = xstrdup(s);
    while (ofputil_parse_key_value(&pos, &key, &value_s)) {
        const struct protocol *p;
        if (parse_protocol(key, &p)) {
            if (flow->dl_type) {
                error = xasprintf("%s: Ethernet type set multiple times", s);
                goto exit;
            }
            flow->dl_type = htons(p->dl_type);

            if (p->nw_proto) {
                if (flow->nw_proto) {
                    error = xasprintf("%s: network protocol set "
                                      "multiple times", s);
                    goto exit;
                }
                flow->nw_proto = p->nw_proto;
            }
        } else {
            const struct mf_field *mf;
            union mf_value value;
            char *field_error;

            mf = mf_from_name(key);
            if (!mf) {
                error = xasprintf("%s: unknown field %s", s, key);
                goto exit;
            }

            if (!mf_are_prereqs_ok(mf, flow)) {
                error = xasprintf("%s: prerequisites not met for setting %s",
                                  s, key);
                goto exit;
            }

            if (!mf_is_zero(mf, flow)) {
                error = xasprintf("%s: field %s set multiple times", s, key);
                goto exit;
            }

            field_error = mf_parse_value(mf, value_s, &value);
            if (field_error) {
                error = xasprintf("%s: bad value for %s (%s)",
                                  s, key, field_error);
                free(field_error);
                goto exit;
            }

            mf_set_flow_value(mf, &value, flow);
        }
    }

exit:
    free(copy);

    if (error) {
        memset(flow, 0, sizeof *flow);
    }
    return error;
}
Esempio n. 5
0
istream68_t * url68_stream_create(const char * url, int mode)
{
  char protocol[16];
  char tmp[512];
  const int max = sizeof(tmp)-1;
  istream68_t * isf = 0;
  int has_protocol;             /* in fact protocol:// length */

  has_protocol = parse_protocol(protocol, sizeof(protocol), url);
  if (has_protocol) {
    if (!strcmp68(protocol, "PASS")) {
      /* This is special pass thru protocol. It allows to send any
         other protocol:// or whatever to the default file handler.
         On some OS with some libC it may be useful.
      */
      url += has_protocol;      /* Skip protocol:// part */
      has_protocol = 0;         /* Allow fallback open   */
    } else if (!strcmp68(protocol, "RSC68")) {
      isf = rsc68_create_url(url, mode, 0);
    } else if (!strcmp68(protocol, "SC68")) {
      /* sc68://author/hw/title/track:loop */
      url += has_protocol;      /* Skip protocol:// part */
      strncpy(tmp, "rsc68://music/",max);
      strncpy(tmp+14, url, max-14);
      tmp[max] = 0;
      msg68(-1,"url is now [%s]\n",tmp);
      isf = rsc68_create_url(tmp, mode, 0);
    } else if (!strcmp68(protocol, "FILE") ||
               !strcmp68(protocol, "LOCAL")) {
      url += has_protocol;      /* Skip protocol:// part */
      has_protocol = 0;         /* Allow fallback open */
    } else if (!strcmp68(protocol, "NULL")) {
      isf = istream68_null_create(url);
    } else if (!strcmp68(protocol, "AUDIO")) {
      url += 5+3;
      isf  = istream68_ao_create(url,mode);
    } else if (!strcmp68(protocol, "STDIN")) {
      if (mode != 1) return 0;  /* stdin is READ_ONLY */
      isf = istream68_fd_create("stdin://",0,1);
      url = "/dev/stdin";       /* fallback */
      has_protocol = 0;         /* Allow fallback open */
    } else if (!strcmp68(protocol, "STDOUT")) {
      if (mode != 2) return 0;  /* stdout is WRITE_ONLY */
      isf = istream68_fd_create("stdout://",1,2);
      url = "/dev/stdout";      /* fallback */
      has_protocol = 0;         /* Allow fallback open */
    } else if (!strcmp68(protocol, "STDERR")) {
      if (mode != 2) return 0;  /* stderr is WRITE_ONLY */
      isf = istream68_fd_create("stderr://",2,2);
      url = "/dev/stderr";      /* fallback */
      has_protocol = 0;         /* Allow fallback open */
    } else {
      /* Try cURL for all unknown protocol */
      isf = istream68_curl_create(url,mode);
    }
  }

  /* Fallback open only if no protocol (or explicitly allowed) */
  if (!has_protocol) {
    if (!isf) {                 /* Default open as FILE */
      isf = istream68_file_create(url,mode);
    }
    if (!isf) {                 /* Fallback to file descriptor */
      isf = istream68_fd_create(url,-1,mode);
    }
  }

  msg68_trace("url68: create url='%s' %c%c => [%s,'%s']\n",
              strnevernull68(url),
              (mode&1) ? 'R' : '.',
              (mode&2) ? 'W' : '.',
              strok68(!isf),
              istream68_filename(isf));

  return isf;
}
Esempio n. 6
0
int url68_get_protocol(char * protocol, int max, const char *url)
{
  return -!parse_protocol(protocol, max, url);
}
Esempio n. 7
0
/* Convert 'string' (as described in the Flow Syntax section of the ovs-ofctl
 * man page) into 'pf'.  If 'actions' is specified, an action must be in
 * 'string' and may be expanded or reallocated. */
void
parse_ofp_str(struct flow_mod *fm, uint8_t *table_idx,
              struct ofpbuf *actions, char *string)
{
    char *save_ptr = NULL;
    char *name;

    if (table_idx) {
        *table_idx = 0xff;
    }
    cls_rule_init_catchall(&fm->cr, OFP_DEFAULT_PRIORITY);
    fm->cookie = htonll(0);
    fm->command = UINT16_MAX;
    fm->idle_timeout = OFP_FLOW_PERMANENT;
    fm->hard_timeout = OFP_FLOW_PERMANENT;
    fm->buffer_id = UINT32_MAX;
    fm->out_port = OFPP_NONE;
    fm->flags = 0;
    if (actions) {
        char *act_str = strstr(string, "action");
        if (!act_str) {
            ovs_fatal(0, "must specify an action");
        }
        *act_str = '\0';

        act_str = strchr(act_str + 1, '=');
        if (!act_str) {
            ovs_fatal(0, "must specify an action");
        }

        act_str++;

        str_to_action(act_str, actions);
        fm->actions = actions->data;
        fm->n_actions = actions->size / sizeof(union ofp_action);
    } else {
        fm->actions = NULL;
        fm->n_actions = 0;
    }
    for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
         name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
        const struct protocol *p;

        if (parse_protocol(name, &p)) {
            cls_rule_set_dl_type(&fm->cr, htons(p->dl_type));
            if (p->nw_proto) {
                cls_rule_set_nw_proto(&fm->cr, p->nw_proto);
            }
        } else {
            const struct field *f;
            char *value;

            value = strtok_r(NULL, ", \t\r\n", &save_ptr);
            if (!value) {
                ovs_fatal(0, "field %s missing value", name);
            }

            if (table_idx && !strcmp(name, "table")) {
                *table_idx = atoi(value);
            } else if (!strcmp(name, "out_port")) {
                fm->out_port = atoi(value);
            } else if (!strcmp(name, "priority")) {
                fm->cr.priority = atoi(value);
            } else if (!strcmp(name, "idle_timeout")) {
                fm->idle_timeout = atoi(value);
            } else if (!strcmp(name, "hard_timeout")) {
                fm->hard_timeout = atoi(value);
            } else if (!strcmp(name, "cookie")) {
                fm->cookie = htonll(str_to_u64(value));
            } else if (parse_field_name(name, &f)) {
                if (!strcmp(value, "*") || !strcmp(value, "ANY")) {
                    if (f->wildcard) {
                        fm->cr.wc.wildcards |= f->wildcard;
                        cls_rule_zero_wildcarded_fields(&fm->cr);
                    } else if (f->index == F_NW_SRC) {
                        cls_rule_set_nw_src_masked(&fm->cr, 0, 0);
                    } else if (f->index == F_NW_DST) {
                        cls_rule_set_nw_dst_masked(&fm->cr, 0, 0);
                    } else if (f->index == F_IPV6_SRC) {
                        cls_rule_set_ipv6_src_masked(&fm->cr,
                                &in6addr_any, &in6addr_any);
                    } else if (f->index == F_IPV6_DST) {
                        cls_rule_set_ipv6_dst_masked(&fm->cr,
                                &in6addr_any, &in6addr_any);
                    } else if (f->index == F_DL_VLAN) {
                        cls_rule_set_any_vid(&fm->cr);
                    } else if (f->index == F_DL_VLAN_PCP) {
                        cls_rule_set_any_pcp(&fm->cr);
                    } else {
                        NOT_REACHED();
                    }
                } else {
                    parse_field_value(&fm->cr, f->index, value);
                }
            } else if (!strncmp(name, "reg", 3)
                       && isdigit((unsigned char) name[3])) {
                unsigned int reg_idx = atoi(name + 3);
                if (reg_idx >= FLOW_N_REGS) {
                    ovs_fatal(0, "only %d registers supported", FLOW_N_REGS);
                }
                parse_reg_value(&fm->cr, reg_idx, value);
            } else {
                ovs_fatal(0, "unknown keyword %s", name);
            }
        }
    }
}
Esempio n. 8
0
static int policy_parse(int c, char **argv, int invert, unsigned int *flags,
                        const void *entry, struct xt_entry_match **match)
{
	struct ip6t_policy_info *info = (void *)(*match)->data;
	struct ip6t_policy_elem *e = &info->pol[info->len];
	struct in6_addr *addr = NULL, mask;
	unsigned int naddr = 0;
	int mode;

	check_inverse(optarg, &invert, &optind, 0);

	switch (c) {
	case '1':
		if (info->flags & (IP6T_POLICY_MATCH_IN|IP6T_POLICY_MATCH_OUT))
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --dir option");
		if (invert)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: can't invert --dir option");

		info->flags |= parse_direction(argv[optind-1]);
		break;
	case '2':
		if (invert)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: can't invert --policy option");

		info->flags |= parse_policy(argv[optind-1]);
		break;
	case '3':
		if (info->flags & IP6T_POLICY_MATCH_STRICT)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --strict option");

		if (invert)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: can't invert --strict option");

		info->flags |= IP6T_POLICY_MATCH_STRICT;
		break;
	case '4':
		if (e->match.reqid)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --reqid option");

		e->match.reqid = 1;
		e->invert.reqid = invert;
		e->reqid = strtol(argv[optind-1], NULL, 10);
		break;
	case '5':
		if (e->match.spi)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --spi option");

		e->match.spi = 1;
		e->invert.spi = invert;
		e->spi = strtol(argv[optind-1], NULL, 0x10);
		break;
	case '6':
		if (e->match.saddr)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --tunnel-src option");

		parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
		if (naddr > 1)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: name resolves to multiple IPs");

		e->match.saddr = 1;
		e->invert.saddr = invert;
		in6addrcpy(&e->saddr.a6, addr);
		in6addrcpy(&e->smask.a6, &mask);
                break;
	case '7':
		if (e->match.daddr)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --tunnel-dst option");

		parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
		if (naddr > 1)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: name resolves to multiple IPs");

		e->match.daddr = 1;
		e->invert.daddr = invert;
		in6addrcpy(&e->daddr.a6, addr);
		in6addrcpy(&e->dmask.a6, &mask);
		break;
	case '8':
		if (e->match.proto)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --proto option");

		e->proto = parse_protocol(argv[optind-1]);
		if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP &&
		    e->proto != IPPROTO_COMP)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: protocol must ah/esp/ipcomp");
		e->match.proto = 1;
		e->invert.proto = invert;
		break;
	case '9':
		if (e->match.mode)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --mode option");

		mode = parse_mode(argv[optind-1]);
		e->match.mode = 1;
		e->invert.mode = invert;
		e->mode = mode;
		break;
	case 'a':
		if (invert)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: can't invert --next option");

		if (++info->len == IP6T_POLICY_MAX_ELEM)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: maximum policy depth reached");
		break;
	default:
		return 0;
	}

	policy_info = info;
	return 1;
}
Esempio n. 9
0
/* Function which parses command options; returns true if it
   ate an option */
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ipt_entry *entry,
      unsigned int *nfcache,
      struct ipt_entry_match **match)
{
	struct ipt_conntrack_info *sinfo = (struct ipt_conntrack_info *)(*match)->data;
	char *protocol = NULL;
	unsigned int naddrs = 0;
	struct in_addr *addrs = NULL;


	switch (c) {
	case '1':
		check_inverse(optarg, &invert, &optind, 0);

		parse_states(argv[optind-1], sinfo);
		if (invert) {
			sinfo->invflags |= IPT_CONNTRACK_STATE;
		}
		sinfo->flags |= IPT_CONNTRACK_STATE;
		break;

	case '2':
		check_inverse(optarg, &invert, &optind, 0);

		if(invert)
			sinfo->invflags |= IPT_CONNTRACK_PROTO;

		/* Canonicalize into lower case */
		for (protocol = argv[optind-1]; *protocol; protocol++)
			*protocol = tolower(*protocol);

		protocol = argv[optind-1];
		sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = parse_protocol(protocol);

		if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0
		    && (sinfo->invflags & IPT_INV_PROTO))
			exit_error(PARAMETER_PROBLEM,
				   "rule would never match protocol");

		sinfo->flags |= IPT_CONNTRACK_PROTO;
		break;

	case '3':
		check_inverse(optarg, &invert, &optind, 9);

		if (invert)
			sinfo->invflags |= IPT_CONNTRACK_ORIGSRC;

		parse_hostnetworkmask(argv[optind-1], &addrs,
					&sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
					&naddrs);
		if(naddrs > 1)
			exit_error(PARAMETER_PROBLEM,
				"multiple IP addresses not allowed");

		if(naddrs == 1) {
			sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = addrs[0].s_addr;
		}

		sinfo->flags |= IPT_CONNTRACK_ORIGSRC;
		break;

	case '4':
		check_inverse(optarg, &invert, &optind, 0);

		if (invert)
			sinfo->invflags |= IPT_CONNTRACK_ORIGDST;

		parse_hostnetworkmask(argv[optind-1], &addrs,
					&sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
					&naddrs);
		if(naddrs > 1)
			exit_error(PARAMETER_PROBLEM,
				"multiple IP addresses not allowed");

		if(naddrs == 1) {
			sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = addrs[0].s_addr;
		}

		sinfo->flags |= IPT_CONNTRACK_ORIGDST;
		break;

	case '5':
		check_inverse(optarg, &invert, &optind, 0);

		if (invert)
			sinfo->invflags |= IPT_CONNTRACK_REPLSRC;

		parse_hostnetworkmask(argv[optind-1], &addrs,
					&sinfo->sipmsk[IP_CT_DIR_REPLY],
					&naddrs);
		if(naddrs > 1)
			exit_error(PARAMETER_PROBLEM,
				"multiple IP addresses not allowed");

		if(naddrs == 1) {
			sinfo->tuple[IP_CT_DIR_REPLY].src.ip = addrs[0].s_addr;
		}

		sinfo->flags |= IPT_CONNTRACK_REPLSRC;
		break;

	case '6':
		check_inverse(optarg, &invert, &optind, 0);

		if (invert)
			sinfo->invflags |= IPT_CONNTRACK_REPLDST;

		parse_hostnetworkmask(argv[optind-1], &addrs,
					&sinfo->dipmsk[IP_CT_DIR_REPLY],
					&naddrs);
		if(naddrs > 1)
			exit_error(PARAMETER_PROBLEM,
				"multiple IP addresses not allowed");

		if(naddrs == 1) {
			sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = addrs[0].s_addr;
		}

		sinfo->flags |= IPT_CONNTRACK_REPLDST;
		break;

	case '7':
		check_inverse(optarg, &invert, &optind, 0);

		parse_statuses(argv[optind-1], sinfo);
		if (invert) {
			sinfo->invflags |= IPT_CONNTRACK_STATUS;
		}
		sinfo->flags |= IPT_CONNTRACK_STATUS;
		break;

	case '8':
		check_inverse(optarg, &invert, &optind, 0);

		parse_expires(argv[optind-1], sinfo);
		if (invert) {
			sinfo->invflags |= IPT_CONNTRACK_EXPIRES;
		}
		sinfo->flags |= IPT_CONNTRACK_EXPIRES;
		break;

	default:
		return 0;
	}

	*flags = sinfo->flags;
	return 1;
}