Home | History | Annotate | Download | only in extensions
      1 /* Shared library add-on to iptables to add devgroup matching support.
      2  *
      3  * Copyright (c) 2011 Patrick McHardy <kaber (at) trash.net>
      4  */
      5 #include <stdio.h>
      6 #include <string.h>
      7 #include <stdlib.h>
      8 #include <errno.h>
      9 #include <xtables.h>
     10 #include <linux/netfilter/xt_devgroup.h>
     11 
     12 static void devgroup_help(void)
     13 {
     14 	printf(
     15 "devgroup match options:\n"
     16 "[!] --src-group value[/mask]	Match device group of incoming device\n"
     17 "[!] --dst-group value[/mask]	Match device group of outgoing device\n"
     18 		);
     19 }
     20 
     21 enum {
     22 	O_SRC_GROUP = 0,
     23 	O_DST_GROUP,
     24 };
     25 
     26 static const struct xt_option_entry devgroup_opts[] = {
     27 	{.name = "src-group", .id = O_SRC_GROUP, .type = XTTYPE_STRING,
     28 	 .flags = XTOPT_INVERT},
     29 	{.name = "dst-group", .id = O_DST_GROUP, .type = XTTYPE_STRING,
     30 	 .flags = XTOPT_INVERT},
     31 	XTOPT_TABLEEND,
     32 };
     33 
     34 /* array of devgroups from /etc/iproute2/group_map */
     35 static struct xtables_lmap *devgroups;
     36 
     37 static void devgroup_init(struct xt_entry_match *match)
     38 {
     39 	const char file[] = "/etc/iproute2/group_map";
     40 	devgroups = xtables_lmap_init(file);
     41 	if (devgroups == NULL && errno != ENOENT)
     42 		fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno));
     43 }
     44 
     45 static void devgroup_parse(struct xt_option_call *cb)
     46 {
     47 	struct xt_devgroup_info *info = cb->data;
     48 	unsigned int id;
     49 	char *end;
     50 
     51 	xtables_option_parse(cb);
     52 	switch (cb->entry->id) {
     53 	case O_SRC_GROUP:
     54 		info->src_group = strtoul(cb->arg, &end, 0);
     55 		if (end != cb->arg && (*end == '/' || *end == '\0')) {
     56 			if (*end == '/')
     57 				info->src_mask = strtoul(end+1, &end, 0);
     58 			else
     59 				info->src_mask = 0xffffffff;
     60 			if (*end != '\0' || end == cb->arg)
     61 				xtables_error(PARAMETER_PROBLEM,
     62 					      "Bad src-group value `%s'",
     63 					      cb->arg);
     64 		} else {
     65 			id = xtables_lmap_name2id(devgroups, cb->arg);
     66 			if (id == -1)
     67 				xtables_error(PARAMETER_PROBLEM,
     68 					      "Device group `%s' not found",
     69 					      cb->arg);
     70 			info->src_group = id;
     71 			info->src_mask  = 0xffffffff;
     72 		}
     73 		info->flags |= XT_DEVGROUP_MATCH_SRC;
     74 		if (cb->invert)
     75 			info->flags |= XT_DEVGROUP_INVERT_SRC;
     76 		break;
     77 	case O_DST_GROUP:
     78 		info->dst_group = strtoul(cb->arg, &end, 0);
     79 		if (end != cb->arg && (*end == '/' || *end == '\0')) {
     80 			if (*end == '/')
     81 				info->dst_mask = strtoul(end+1, &end, 0);
     82 			else
     83 				info->dst_mask = 0xffffffff;
     84 			if (*end != '\0' || end == cb->arg)
     85 				xtables_error(PARAMETER_PROBLEM,
     86 					      "Bad dst-group value `%s'",
     87 					      cb->arg);
     88 		} else {
     89 			id = xtables_lmap_name2id(devgroups, cb->arg);
     90 			if (id == -1)
     91 				xtables_error(PARAMETER_PROBLEM,
     92 					      "Device group `%s' not found",
     93 					      cb->arg);
     94 			info->dst_group = id;
     95 			info->dst_mask  = 0xffffffff;
     96 		}
     97 		info->flags |= XT_DEVGROUP_MATCH_DST;
     98 		if (cb->invert)
     99 			info->flags |= XT_DEVGROUP_INVERT_DST;
    100 		break;
    101 	}
    102 }
    103 
    104 static void
    105 print_devgroup(unsigned int id, unsigned int mask, int numeric)
    106 {
    107 	const char *name = NULL;
    108 
    109 	if (mask != 0xffffffff)
    110 		printf("0x%x/0x%x", id, mask);
    111 	else {
    112 		if (numeric == 0)
    113 			name = xtables_lmap_id2name(devgroups, id);
    114 		if (name)
    115 			printf("%s", name);
    116 		else
    117 			printf("0x%x", id);
    118 	}
    119 }
    120 
    121 static void devgroup_show(const char *pfx, const struct xt_devgroup_info *info,
    122 			  int numeric)
    123 {
    124 	if (info->flags & XT_DEVGROUP_MATCH_SRC) {
    125 		if (info->flags & XT_DEVGROUP_INVERT_SRC)
    126 			printf(" !");
    127 		printf(" %ssrc-group ", pfx);
    128 		print_devgroup(info->src_group, info->src_mask, numeric);
    129 	}
    130 
    131 	if (info->flags & XT_DEVGROUP_MATCH_DST) {
    132 		if (info->flags & XT_DEVGROUP_INVERT_DST)
    133 			printf(" !");
    134 		printf(" %sdst-group ", pfx);
    135 		print_devgroup(info->src_group, info->src_mask, numeric);
    136 	}
    137 }
    138 
    139 static void devgroup_print(const void *ip, const struct xt_entry_match *match,
    140                         int numeric)
    141 {
    142 	const struct xt_devgroup_info *info = (const void *)match->data;
    143 
    144 	devgroup_show("", info, numeric);
    145 }
    146 
    147 static void devgroup_save(const void *ip, const struct xt_entry_match *match)
    148 {
    149 	const struct xt_devgroup_info *info = (const void *)match->data;
    150 
    151 	devgroup_show("--", info, 0);
    152 }
    153 
    154 static void devgroup_check(struct xt_fcheck_call *cb)
    155 {
    156 	if (cb->xflags == 0)
    157 		xtables_error(PARAMETER_PROBLEM,
    158 			      "devgroup match: You must specify either "
    159 			      "'--src-group' or '--dst-group'");
    160 }
    161 
    162 static struct xtables_match devgroup_mt_reg = {
    163 	.name		= "devgroup",
    164 	.version	= XTABLES_VERSION,
    165 	.family		= NFPROTO_UNSPEC,
    166 	.size		= XT_ALIGN(sizeof(struct xt_devgroup_info)),
    167 	.userspacesize	= XT_ALIGN(sizeof(struct xt_devgroup_info)),
    168 	.init		= devgroup_init,
    169 	.help		= devgroup_help,
    170 	.print		= devgroup_print,
    171 	.save		= devgroup_save,
    172 	.x6_parse	= devgroup_parse,
    173 	.x6_fcheck	= devgroup_check,
    174 	.x6_options	= devgroup_opts,
    175 };
    176 
    177 void _init(void)
    178 {
    179 	xtables_register_match(&devgroup_mt_reg);
    180 }
    181