Home | History | Annotate | Line # | Download | only in npfctl
npf_data.c revision 1.7.4.2
      1  1.7.4.2   yamt /*	$NetBSD: npf_data.c,v 1.7.4.2 2012/04/17 00:09:50 yamt Exp $	*/
      2      1.1  rmind 
      3      1.1  rmind /*-
      4  1.7.4.2   yamt  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
      5      1.1  rmind  * All rights reserved.
      6      1.1  rmind  *
      7      1.1  rmind  * Redistribution and use in source and binary forms, with or without
      8      1.1  rmind  * modification, are permitted provided that the following conditions
      9      1.1  rmind  * are met:
     10      1.1  rmind  * 1. Redistributions of source code must retain the above copyright
     11      1.1  rmind  *    notice, this list of conditions and the following disclaimer.
     12      1.1  rmind  * 2. Redistributions in binary form must reproduce the above copyright
     13      1.1  rmind  *    notice, this list of conditions and the following disclaimer in the
     14      1.1  rmind  *    documentation and/or other materials provided with the distribution.
     15      1.1  rmind  *
     16      1.1  rmind  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17      1.1  rmind  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18      1.1  rmind  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19      1.1  rmind  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20      1.1  rmind  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21      1.1  rmind  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22      1.1  rmind  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23      1.1  rmind  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24      1.1  rmind  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25      1.1  rmind  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26      1.1  rmind  * POSSIBILITY OF SUCH DAMAGE.
     27      1.1  rmind  */
     28      1.1  rmind 
     29      1.1  rmind /*
     30  1.7.4.2   yamt  * npfctl(8) data manipulation and helper routines.
     31      1.1  rmind  */
     32      1.1  rmind 
     33      1.4  rmind #include <sys/cdefs.h>
     34  1.7.4.2   yamt __RCSID("$NetBSD: npf_data.c,v 1.7.4.2 2012/04/17 00:09:50 yamt Exp $");
     35      1.4  rmind 
     36      1.1  rmind #include <sys/types.h>
     37  1.7.4.2   yamt #include <sys/null.h>
     38      1.1  rmind 
     39  1.7.4.2   yamt #include <netinet/in.h>
     40  1.7.4.2   yamt #include <netinet/in_systm.h>
     41  1.7.4.2   yamt #include <netinet/ip.h>
     42  1.7.4.2   yamt #define ICMP_STRINGS
     43  1.7.4.2   yamt #include <netinet/ip_icmp.h>
     44  1.7.4.2   yamt #include <netinet/tcp.h>
     45  1.7.4.2   yamt #include <net/if.h>
     46      1.1  rmind 
     47      1.1  rmind #include <stdlib.h>
     48      1.1  rmind #include <string.h>
     49      1.1  rmind #include <err.h>
     50  1.7.4.2   yamt #include <errno.h>
     51      1.1  rmind #include <ifaddrs.h>
     52      1.1  rmind #include <netdb.h>
     53      1.1  rmind 
     54      1.1  rmind #include "npfctl.h"
     55      1.1  rmind 
     56      1.1  rmind static struct ifaddrs *		ifs_list = NULL;
     57      1.1  rmind 
     58  1.7.4.2   yamt unsigned long
     59  1.7.4.2   yamt npfctl_find_ifindex(const char *ifname)
     60      1.1  rmind {
     61  1.7.4.2   yamt 	return if_nametoindex(ifname);
     62      1.1  rmind }
     63      1.1  rmind 
     64  1.7.4.2   yamt static bool
     65  1.7.4.2   yamt npfctl_copy_address(sa_family_t fam, npf_addr_t *addr, const void *ptr)
     66      1.1  rmind {
     67  1.7.4.2   yamt 	switch (fam) {
     68  1.7.4.2   yamt 	case AF_INET: {
     69  1.7.4.2   yamt 		const struct sockaddr_in *sin = ptr;
     70  1.7.4.2   yamt 		memcpy(addr, &sin->sin_addr, sizeof(sin->sin_addr));
     71  1.7.4.2   yamt 		return true;
     72  1.7.4.2   yamt 	}
     73  1.7.4.2   yamt 	case AF_INET6: {
     74  1.7.4.2   yamt 		const struct sockaddr_in6 *sin6 = ptr;
     75  1.7.4.2   yamt 		memcpy(addr, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
     76  1.7.4.2   yamt 		return true;
     77  1.7.4.2   yamt 	}
     78  1.7.4.2   yamt 	default:
     79  1.7.4.2   yamt 		yyerror("unknown address family %u", fam);
     80  1.7.4.2   yamt 		return false;
     81  1.7.4.2   yamt 	}
     82      1.5  rmind }
     83      1.5  rmind 
     84  1.7.4.2   yamt static bool
     85  1.7.4.2   yamt npfctl_parse_fam_addr(const char *name, sa_family_t *fam, npf_addr_t *addr)
     86      1.1  rmind {
     87  1.7.4.2   yamt 	static const struct addrinfo hint = {
     88  1.7.4.2   yamt 		.ai_family = AF_UNSPEC,
     89  1.7.4.2   yamt 		.ai_flags = AI_NUMERICHOST
     90  1.7.4.2   yamt 	};
     91  1.7.4.2   yamt 	struct addrinfo *ai;
     92  1.7.4.2   yamt 	int ret;
     93      1.1  rmind 
     94  1.7.4.2   yamt 	ret = getaddrinfo(name, NULL, &hint, &ai);
     95  1.7.4.2   yamt 	if (ret) {
     96  1.7.4.2   yamt 		yyerror("cannot parse '%s' (%s)", name, gai_strerror(ret));
     97  1.7.4.2   yamt 		return false;
     98      1.1  rmind 	}
     99  1.7.4.2   yamt 	if (fam) {
    100  1.7.4.2   yamt 		*fam = ai->ai_family;
    101      1.1  rmind 	}
    102  1.7.4.2   yamt 	if (!npfctl_copy_address(*fam, addr, ai->ai_addr)) {
    103  1.7.4.2   yamt 		return false;
    104  1.7.4.2   yamt 	}
    105  1.7.4.2   yamt 	freeaddrinfo(ai);
    106  1.7.4.2   yamt 	return true;
    107      1.1  rmind }
    108      1.1  rmind 
    109  1.7.4.2   yamt static bool
    110  1.7.4.2   yamt npfctl_parse_mask(const char *s, sa_family_t fam, npf_netmask_t *mask)
    111      1.3  rmind {
    112  1.7.4.2   yamt 	char *ep = NULL;
    113  1.7.4.2   yamt 	npf_addr_t addr;
    114  1.7.4.2   yamt 	uint8_t *ap;
    115  1.7.4.2   yamt 
    116  1.7.4.2   yamt 	if (s) {
    117  1.7.4.2   yamt 		errno = 0;
    118  1.7.4.2   yamt 		*mask = (npf_netmask_t)strtol(s, &ep, 0);
    119  1.7.4.2   yamt 		if (*ep == '\0' && s != ep && errno != ERANGE)
    120  1.7.4.2   yamt 			return true;
    121  1.7.4.2   yamt 		if (!npfctl_parse_fam_addr(s, &fam, &addr))
    122      1.3  rmind 			return false;
    123  1.7.4.2   yamt 	}
    124  1.7.4.2   yamt 
    125  1.7.4.2   yamt 	switch (fam) {
    126  1.7.4.2   yamt 	case AF_INET:
    127  1.7.4.2   yamt 		*mask = 32;
    128  1.7.4.2   yamt 		break;
    129  1.7.4.2   yamt 	case AF_INET6:
    130  1.7.4.2   yamt 		*mask = 128;
    131  1.7.4.2   yamt 		break;
    132  1.7.4.2   yamt 	default:
    133  1.7.4.2   yamt 		yyerror("unknown address family %u", fam);
    134  1.7.4.2   yamt 		return false;
    135  1.7.4.2   yamt 	}
    136  1.7.4.2   yamt 
    137  1.7.4.2   yamt 	if (ep == NULL) {
    138  1.7.4.2   yamt 		return true;
    139  1.7.4.2   yamt 	}
    140  1.7.4.2   yamt 	ap = addr.s6_addr + (*mask / 8) - 1;
    141  1.7.4.2   yamt 	while (ap >= addr.s6_addr) {
    142  1.7.4.2   yamt 		for (int j = 8; j > 0; j--) {
    143  1.7.4.2   yamt 			if (*ap & 1)
    144  1.7.4.2   yamt 				return true;
    145  1.7.4.2   yamt 			*ap >>= 1;
    146  1.7.4.2   yamt 			(*mask)--;
    147  1.7.4.2   yamt 			if (*mask == 0)
    148  1.7.4.2   yamt 				return true;
    149      1.3  rmind 		}
    150  1.7.4.2   yamt 		ap--;
    151      1.3  rmind 	}
    152      1.3  rmind 	return true;
    153      1.1  rmind }
    154      1.1  rmind 
    155  1.7.4.2   yamt /*
    156  1.7.4.2   yamt  * npfctl_parse_fam_addr_mask: return address family, address and mask.
    157  1.7.4.2   yamt  *
    158  1.7.4.2   yamt  * => Mask is optional and can be NULL.
    159  1.7.4.2   yamt  * => Returns true on success or false if unable to parse.
    160  1.7.4.2   yamt  */
    161  1.7.4.2   yamt npfvar_t *
    162  1.7.4.2   yamt npfctl_parse_fam_addr_mask(const char *addr, const char *mask,
    163  1.7.4.2   yamt     unsigned long *nummask)
    164      1.1  rmind {
    165  1.7.4.2   yamt 	npfvar_t *vp = npfvar_create(".addr");
    166  1.7.4.2   yamt 	fam_addr_mask_t fam;
    167      1.1  rmind 
    168  1.7.4.2   yamt 	memset(&fam, 0, sizeof(fam));
    169  1.7.4.2   yamt 
    170  1.7.4.2   yamt 	if (!npfctl_parse_fam_addr(addr, &fam.fam_family, &fam.fam_addr))
    171  1.7.4.2   yamt 		goto out;
    172  1.7.4.2   yamt 
    173  1.7.4.2   yamt 	/*
    174  1.7.4.2   yamt 	 * Note: both mask and nummask may be NULL.  In such case,
    175  1.7.4.2   yamt 	 * npfctl_parse_mask() will handle and will set full mask.
    176  1.7.4.2   yamt 	 */
    177  1.7.4.2   yamt 	if (nummask) {
    178  1.7.4.2   yamt 		fam.fam_mask = *nummask;
    179  1.7.4.2   yamt 	} else if (!npfctl_parse_mask(mask, fam.fam_family, &fam.fam_mask)) {
    180  1.7.4.2   yamt 		goto out;
    181  1.7.4.1   yamt 	}
    182  1.7.4.2   yamt 
    183  1.7.4.2   yamt 	if (!npfvar_add_element(vp, NPFVAR_FAM, &fam, sizeof(fam)))
    184  1.7.4.2   yamt 		goto out;
    185  1.7.4.2   yamt 
    186  1.7.4.2   yamt 	return vp;
    187  1.7.4.2   yamt out:
    188  1.7.4.2   yamt 	npfvar_destroy(vp);
    189  1.7.4.2   yamt 	return NULL;
    190  1.7.4.1   yamt }
    191  1.7.4.1   yamt 
    192  1.7.4.2   yamt npfvar_t *
    193  1.7.4.2   yamt npfctl_parse_table_id(const char *id)
    194  1.7.4.1   yamt {
    195  1.7.4.2   yamt 	npfvar_t *vp;
    196  1.7.4.2   yamt 
    197  1.7.4.2   yamt 	if (!npfctl_table_exists_p(id)) {
    198  1.7.4.2   yamt 		yyerror("table '%s' is not defined", id);
    199  1.7.4.2   yamt 		return NULL;
    200      1.1  rmind 	}
    201  1.7.4.2   yamt 	vp = npfvar_create(".table");
    202  1.7.4.2   yamt 
    203  1.7.4.2   yamt 	if (!npfvar_add_element(vp, NPFVAR_TABLE, id, strlen(id) + 1))
    204  1.7.4.2   yamt 		goto out;
    205  1.7.4.1   yamt 
    206  1.7.4.2   yamt 	return vp;
    207  1.7.4.2   yamt out:
    208  1.7.4.2   yamt 	npfvar_destroy(vp);
    209  1.7.4.2   yamt 	return NULL;
    210      1.1  rmind }
    211      1.1  rmind 
    212  1.7.4.2   yamt /*
    213  1.7.4.2   yamt  * npfctl_parse_port_range: create a port-range variable.  Note that the
    214  1.7.4.2   yamt  * passed port numbers are in network byte order.
    215  1.7.4.2   yamt  */
    216  1.7.4.2   yamt npfvar_t *
    217  1.7.4.2   yamt npfctl_parse_port_range(in_port_t s, in_port_t e)
    218      1.3  rmind {
    219  1.7.4.2   yamt 	npfvar_t *vp = npfvar_create(".port_range");
    220  1.7.4.2   yamt 	port_range_t pr;
    221      1.3  rmind 
    222  1.7.4.2   yamt 	pr.pr_start = s;
    223  1.7.4.2   yamt 	pr.pr_end = e;
    224  1.7.4.2   yamt 
    225  1.7.4.2   yamt 	if (!npfvar_add_element(vp, NPFVAR_PORT_RANGE, &pr, sizeof(pr)))
    226  1.7.4.2   yamt 		goto out;
    227  1.7.4.2   yamt 
    228  1.7.4.2   yamt 	return vp;
    229  1.7.4.2   yamt out:
    230  1.7.4.2   yamt 	npfvar_destroy(vp);
    231  1.7.4.2   yamt 	return NULL;
    232  1.7.4.2   yamt }
    233  1.7.4.2   yamt 
    234  1.7.4.2   yamt npfvar_t *
    235  1.7.4.2   yamt npfctl_parse_port_range_variable(const char *v)
    236  1.7.4.2   yamt {
    237  1.7.4.2   yamt 	npfvar_t *vp = npfvar_lookup(v);
    238  1.7.4.2   yamt 	in_port_t p;
    239  1.7.4.2   yamt 	port_range_t *pr;
    240  1.7.4.2   yamt 	size_t count = npfvar_get_count(vp);
    241  1.7.4.2   yamt 	npfvar_t *pvp = npfvar_create(".port_range");
    242  1.7.4.2   yamt 
    243  1.7.4.2   yamt 	for (size_t i = 0; i < count; i++) {
    244  1.7.4.2   yamt 		int type = npfvar_get_type(vp, i);
    245  1.7.4.2   yamt 		void *data = npfvar_get_data(vp, type, i);
    246  1.7.4.2   yamt 		switch (type) {
    247  1.7.4.2   yamt 		case NPFVAR_IDENTIFIER:
    248  1.7.4.2   yamt 		case NPFVAR_STRING:
    249  1.7.4.2   yamt 			p = npfctl_portno(data);
    250  1.7.4.2   yamt 			npfvar_add_elements(pvp, npfctl_parse_port_range(p, p));
    251  1.7.4.2   yamt 			break;
    252  1.7.4.2   yamt 		case NPFVAR_PORT_RANGE:
    253  1.7.4.2   yamt 			pr = data;
    254  1.7.4.2   yamt 			npfvar_add_element(pvp, NPFVAR_PORT_RANGE, pr,
    255  1.7.4.2   yamt 			    sizeof(*pr));
    256  1.7.4.2   yamt 			break;
    257  1.7.4.2   yamt 		case NPFVAR_NUM:
    258  1.7.4.2   yamt 			p = *(unsigned long *)data;
    259  1.7.4.2   yamt 			npfvar_add_elements(pvp, npfctl_parse_port_range(p, p));
    260      1.3  rmind 			break;
    261      1.3  rmind 		default:
    262  1.7.4.2   yamt 			yyerror("wrong variable '%s' type '%s' for port range",
    263  1.7.4.2   yamt 			    v, npfvar_type(type));
    264  1.7.4.2   yamt 			goto out;
    265      1.3  rmind 		}
    266      1.3  rmind 	}
    267  1.7.4.2   yamt 	return pvp;
    268  1.7.4.2   yamt out:
    269  1.7.4.2   yamt 	npfvar_destroy(pvp);
    270  1.7.4.2   yamt 	return NULL;
    271      1.3  rmind }
    272      1.3  rmind 
    273  1.7.4.2   yamt npfvar_t *
    274  1.7.4.2   yamt npfctl_parse_iface(const char *ifname)
    275      1.1  rmind {
    276  1.7.4.2   yamt 	npfvar_t *vp = npfvar_create(".iface");
    277  1.7.4.2   yamt 	struct ifaddrs *ifa;
    278  1.7.4.2   yamt 	fam_addr_mask_t fam;
    279  1.7.4.2   yamt 	bool gotif = false;
    280      1.1  rmind 
    281  1.7.4.2   yamt 	if (ifs_list == NULL && getifaddrs(&ifs_list) == -1) {
    282  1.7.4.2   yamt 		err(EXIT_FAILURE, "getifaddrs");
    283      1.1  rmind 	}
    284  1.7.4.2   yamt 	memset(&fam, 0, sizeof(fam));
    285      1.1  rmind 
    286  1.7.4.2   yamt 	npfvar_t *ip = npfvar_create(".ifname");
    287  1.7.4.2   yamt 	if (!npfvar_add_element(ip, NPFVAR_STRING, ifname, strlen(ifname) + 1))
    288  1.7.4.2   yamt 		goto out;
    289      1.1  rmind 
    290  1.7.4.2   yamt 	for (ifa = ifs_list; ifa != NULL; ifa = ifa->ifa_next) {
    291  1.7.4.2   yamt 		struct sockaddr *sa;
    292  1.7.4.2   yamt 		sa_family_t family;
    293      1.1  rmind 
    294  1.7.4.2   yamt 		if (strcmp(ifa->ifa_name, ifname) != 0)
    295  1.7.4.2   yamt 			continue;
    296      1.1  rmind 
    297  1.7.4.2   yamt 		gotif = true;
    298  1.7.4.2   yamt 		if ((ifa->ifa_flags & IFF_UP) == 0)
    299  1.7.4.2   yamt 			warnx("interface '%s' is down", ifname);
    300  1.7.4.2   yamt 
    301  1.7.4.2   yamt 		sa = ifa->ifa_addr;
    302  1.7.4.2   yamt 		family = sa->sa_family;
    303  1.7.4.2   yamt 		if (family != AF_INET && family != AF_INET6)
    304  1.7.4.2   yamt 			continue;
    305      1.1  rmind 
    306  1.7.4.2   yamt 		fam.fam_family = family;
    307  1.7.4.2   yamt 		fam.fam_interface = ip;
    308      1.1  rmind 
    309  1.7.4.2   yamt 		if (!npfctl_copy_address(family, &fam.fam_addr, sa))
    310  1.7.4.2   yamt 			goto out;
    311      1.1  rmind 
    312  1.7.4.2   yamt 		if (!npfctl_parse_mask(NULL, fam.fam_family, &fam.fam_mask))
    313  1.7.4.2   yamt 			goto out;
    314      1.1  rmind 
    315  1.7.4.2   yamt 		if (!npfvar_add_element(vp, NPFVAR_FAM, &fam, sizeof(fam)))
    316  1.7.4.2   yamt 			goto out;
    317  1.7.4.2   yamt 	}
    318  1.7.4.2   yamt 	if (!gotif) {
    319  1.7.4.2   yamt 		yyerror("interface '%s' not found", ifname);
    320  1.7.4.2   yamt 		goto out;
    321  1.7.4.2   yamt 	}
    322  1.7.4.2   yamt 	if (npfvar_get_count(vp) == 0) {
    323  1.7.4.2   yamt 		yyerror("no addresses matched for interface '%s'", ifname);
    324  1.7.4.2   yamt 		goto out;
    325      1.1  rmind 	}
    326  1.7.4.2   yamt 	return vp;
    327  1.7.4.2   yamt out:
    328  1.7.4.2   yamt 	npfvar_destroy(vp);
    329  1.7.4.2   yamt 	npfvar_destroy(ip);
    330  1.7.4.2   yamt 	return NULL;
    331      1.1  rmind }
    332      1.1  rmind 
    333  1.7.4.2   yamt fam_addr_mask_t *
    334  1.7.4.2   yamt npfctl_parse_cidr(char *cidr)
    335      1.1  rmind {
    336  1.7.4.2   yamt 	npfvar_t *vp;
    337  1.7.4.2   yamt 	char *p;
    338      1.1  rmind 
    339  1.7.4.2   yamt 	p = strchr(cidr, '/');
    340  1.7.4.2   yamt 	if (p) {
    341  1.7.4.2   yamt 		*p++ = '\0';
    342      1.1  rmind 	}
    343  1.7.4.2   yamt 	vp = npfctl_parse_fam_addr_mask(cidr, p, NULL);
    344  1.7.4.2   yamt 	if (vp == NULL) {
    345  1.7.4.2   yamt 		return NULL;
    346      1.1  rmind 	}
    347  1.7.4.2   yamt 	return npfvar_get_data(vp, NPFVAR_FAM, 0);
    348      1.1  rmind }
    349      1.1  rmind 
    350  1.7.4.2   yamt /*
    351  1.7.4.2   yamt  * npfctl_portno: convert port identifier (string) to a number.
    352  1.7.4.2   yamt  *
    353  1.7.4.2   yamt  * => Returns port number in network byte order.
    354  1.7.4.2   yamt  */
    355  1.7.4.2   yamt in_port_t
    356  1.7.4.2   yamt npfctl_portno(const char *port)
    357      1.1  rmind {
    358  1.7.4.2   yamt 	struct addrinfo *ai, *rai;
    359  1.7.4.2   yamt 	in_port_t p = 0;
    360  1.7.4.2   yamt 	int e;
    361  1.7.4.2   yamt 
    362  1.7.4.2   yamt 	e = getaddrinfo(NULL, port, NULL, &rai);
    363  1.7.4.2   yamt 	if (e != 0) {
    364  1.7.4.2   yamt 		yyerror("invalid port name: '%s' (%s)", port, gai_strerror(e));
    365  1.7.4.2   yamt 		return 0;
    366  1.7.4.2   yamt 	}
    367  1.7.4.2   yamt 
    368  1.7.4.2   yamt 	for (ai = rai; ai; ai = ai->ai_next) {
    369  1.7.4.2   yamt 		switch (ai->ai_family) {
    370  1.7.4.2   yamt 		case AF_INET: {
    371  1.7.4.2   yamt 			struct sockaddr_in *sin = (void *)ai->ai_addr;
    372  1.7.4.2   yamt 			p = sin->sin_port;
    373  1.7.4.2   yamt 			goto out;
    374  1.7.4.2   yamt 		}
    375  1.7.4.2   yamt 		case AF_INET6: {
    376  1.7.4.2   yamt 			struct sockaddr_in6 *sin6 = (void *)ai->ai_addr;
    377  1.7.4.2   yamt 			p = sin6->sin6_port;
    378  1.7.4.2   yamt 			goto out;
    379  1.7.4.1   yamt 		}
    380  1.7.4.2   yamt 		default:
    381  1.7.4.2   yamt 			break;
    382  1.7.4.1   yamt 		}
    383      1.3  rmind 	}
    384  1.7.4.2   yamt out:
    385  1.7.4.2   yamt 	freeaddrinfo(rai);
    386  1.7.4.2   yamt 	return p;
    387  1.7.4.2   yamt }
    388      1.3  rmind 
    389  1.7.4.2   yamt npfvar_t *
    390  1.7.4.2   yamt npfctl_parse_tcpflag(const char *s)
    391  1.7.4.2   yamt {
    392  1.7.4.2   yamt 	uint8_t tfl = 0;
    393      1.1  rmind 
    394  1.7.4.2   yamt 	while (*s) {
    395  1.7.4.2   yamt 		switch (*s) {
    396  1.7.4.2   yamt 		case 'F': tfl |= TH_FIN; break;
    397  1.7.4.2   yamt 		case 'S': tfl |= TH_SYN; break;
    398  1.7.4.2   yamt 		case 'R': tfl |= TH_RST; break;
    399  1.7.4.2   yamt 		case 'P': tfl |= TH_PUSH; break;
    400  1.7.4.2   yamt 		case 'A': tfl |= TH_ACK; break;
    401  1.7.4.2   yamt 		case 'U': tfl |= TH_URG; break;
    402  1.7.4.2   yamt 		case 'E': tfl |= TH_ECE; break;
    403  1.7.4.2   yamt 		case 'W': tfl |= TH_CWR; break;
    404  1.7.4.2   yamt 		default:
    405  1.7.4.2   yamt 			yyerror("invalid flag '%c'", *s);
    406  1.7.4.2   yamt 			return NULL;
    407      1.3  rmind 		}
    408  1.7.4.2   yamt 		s++;
    409      1.1  rmind 	}
    410      1.1  rmind 
    411  1.7.4.2   yamt 	npfvar_t *vp = npfvar_create(".tcp_flag");
    412  1.7.4.2   yamt 	if (!npfvar_add_element(vp, NPFVAR_TCPFLAG, &tfl, sizeof(tfl))) {
    413  1.7.4.2   yamt 		npfvar_destroy(vp);
    414  1.7.4.2   yamt 		return NULL;
    415  1.7.4.2   yamt 	}
    416  1.7.4.2   yamt 
    417  1.7.4.2   yamt 	return vp;
    418  1.7.4.2   yamt }
    419  1.7.4.2   yamt 
    420  1.7.4.2   yamt uint8_t
    421  1.7.4.2   yamt npfctl_icmptype(const char *type)
    422  1.7.4.2   yamt {
    423  1.7.4.2   yamt 	for (uint8_t ul = 0; icmp_type[ul]; ul++)
    424  1.7.4.2   yamt 		if (strcmp(icmp_type[ul], type) == 0)
    425  1.7.4.2   yamt 			return ul;
    426  1.7.4.2   yamt 	return ~0;
    427  1.7.4.2   yamt }
    428  1.7.4.2   yamt 
    429  1.7.4.2   yamt uint8_t
    430  1.7.4.2   yamt npfctl_icmpcode(uint8_t type, const char *code)
    431  1.7.4.2   yamt {
    432  1.7.4.2   yamt 	const char **arr;
    433  1.7.4.2   yamt 
    434  1.7.4.2   yamt 	switch (type) {
    435  1.7.4.2   yamt 	case ICMP_ECHOREPLY:
    436  1.7.4.2   yamt 	case ICMP_SOURCEQUENCH:
    437  1.7.4.2   yamt 	case ICMP_ALTHOSTADDR:
    438  1.7.4.2   yamt 	case ICMP_ECHO:
    439  1.7.4.2   yamt 	case ICMP_ROUTERSOLICIT:
    440  1.7.4.2   yamt 	case ICMP_TSTAMP:
    441  1.7.4.2   yamt 	case ICMP_TSTAMPREPLY:
    442  1.7.4.2   yamt 	case ICMP_IREQ:
    443  1.7.4.2   yamt 	case ICMP_IREQREPLY:
    444  1.7.4.2   yamt 	case ICMP_MASKREQ:
    445  1.7.4.2   yamt 	case ICMP_MASKREPLY:
    446  1.7.4.2   yamt 		arr = icmp_code_none;
    447  1.7.4.2   yamt 		break;
    448  1.7.4.2   yamt 	case ICMP_ROUTERADVERT:
    449  1.7.4.2   yamt 		arr = icmp_code_routeradvert;
    450  1.7.4.2   yamt 		break;
    451  1.7.4.2   yamt 	case ICMP_UNREACH:
    452  1.7.4.2   yamt 		arr = icmp_code_unreach;
    453  1.7.4.2   yamt 		break;
    454  1.7.4.2   yamt 	case ICMP_REDIRECT:
    455  1.7.4.2   yamt 		arr = icmp_code_redirect;
    456  1.7.4.2   yamt 		break;
    457  1.7.4.2   yamt 	case ICMP_TIMXCEED:
    458  1.7.4.2   yamt 		arr = icmp_code_timxceed;
    459  1.7.4.2   yamt 		break;
    460  1.7.4.2   yamt 	case ICMP_PARAMPROB:
    461  1.7.4.2   yamt 		arr = icmp_code_paramprob;
    462  1.7.4.2   yamt 		break;
    463  1.7.4.2   yamt 	case ICMP_PHOTURIS:
    464  1.7.4.2   yamt 		arr = icmp_code_photuris;
    465  1.7.4.2   yamt 		break;
    466  1.7.4.2   yamt 	default:
    467  1.7.4.2   yamt 		return ~0;
    468  1.7.4.2   yamt 	}
    469  1.7.4.2   yamt 
    470  1.7.4.2   yamt 	for (uint8_t ul = 0; arr[ul]; ul++) {
    471  1.7.4.2   yamt 		if (strcmp(arr[ul], code) == 0)
    472  1.7.4.2   yamt 			return ul;
    473  1.7.4.2   yamt 	}
    474  1.7.4.2   yamt 	return ~0;
    475  1.7.4.2   yamt }
    476  1.7.4.2   yamt 
    477  1.7.4.2   yamt npfvar_t *
    478  1.7.4.2   yamt npfctl_parse_icmp(uint8_t type, uint8_t code)
    479  1.7.4.2   yamt {
    480  1.7.4.2   yamt 	npfvar_t *vp = npfvar_create(".icmp");
    481  1.7.4.2   yamt 
    482  1.7.4.2   yamt 	if (!npfvar_add_element(vp, NPFVAR_ICMP, &type, sizeof(type)))
    483  1.7.4.2   yamt 		goto out;
    484  1.7.4.2   yamt 
    485  1.7.4.2   yamt 	if (!npfvar_add_element(vp, NPFVAR_ICMP, &code, sizeof(code)))
    486  1.7.4.2   yamt 		goto out;
    487  1.7.4.2   yamt 
    488  1.7.4.2   yamt 	return vp;
    489  1.7.4.2   yamt out:
    490  1.7.4.2   yamt 	npfvar_destroy(vp);
    491  1.7.4.2   yamt 	return NULL;
    492      1.1  rmind }
    493