Home | History | Annotate | Download | only in extensions
      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <errno.h>
      5 #if defined(__GLIBC__) && __GLIBC__ == 2
      6 #include <net/ethernet.h>
      7 #else
      8 #include <linux/if_ether.h>
      9 #endif
     10 #include <xtables.h>
     11 #include <linux/netfilter_ipv4/ipt_realm.h>
     12 
     13 enum {
     14 	O_REALM = 0,
     15 };
     16 
     17 static void realm_help(void)
     18 {
     19 	printf(
     20 "realm match options:\n"
     21 "[!] --realm value[/mask]\n"
     22 "				Match realm\n");
     23 }
     24 
     25 static const struct xt_option_entry realm_opts[] = {
     26 	{.name = "realm", .id = O_REALM, .type = XTTYPE_STRING,
     27 	 .flags = XTOPT_MAND | XTOPT_INVERT},
     28 	XTOPT_TABLEEND,
     29 };
     30 
     31 /* array of realms from /etc/iproute2/rt_realms */
     32 static struct xtables_lmap *realms;
     33 
     34 static void realm_init(struct xt_entry_match *m)
     35 {
     36 	const char file[] = "/etc/iproute2/rt_realms";
     37 
     38 	realms = xtables_lmap_init(file);
     39 	if (realms == NULL && errno != ENOENT)
     40 		fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno));
     41 }
     42 
     43 static void realm_parse(struct xt_option_call *cb)
     44 {
     45 	struct xt_realm_info *realminfo = cb->data;
     46 	int id;
     47 	char *end;
     48 
     49 	xtables_option_parse(cb);
     50 	realminfo->id = strtoul(cb->arg, &end, 0);
     51 	if (end != cb->arg && (*end == '/' || *end == '\0')) {
     52 		if (*end == '/')
     53 			realminfo->mask = strtoul(end+1, &end, 0);
     54 		else
     55 			realminfo->mask = 0xffffffff;
     56 		if (*end != '\0' || end == cb->arg)
     57 			xtables_error(PARAMETER_PROBLEM,
     58 				   "Bad realm value \"%s\"", cb->arg);
     59 	} else {
     60 		id = xtables_lmap_name2id(realms, cb->arg);
     61 		if (id == -1)
     62 			xtables_error(PARAMETER_PROBLEM,
     63 				   "Realm \"%s\" not found", cb->arg);
     64 		realminfo->id = id;
     65 		realminfo->mask = 0xffffffff;
     66 	}
     67 	if (cb->invert)
     68 		realminfo->invert = 1;
     69 }
     70 
     71 static void
     72 print_realm(unsigned long id, unsigned long mask, int numeric)
     73 {
     74 	const char *name = NULL;
     75 
     76 	if (mask != 0xffffffff)
     77 		printf(" 0x%lx/0x%lx", id, mask);
     78 	else {
     79 		if (numeric == 0)
     80 			name = xtables_lmap_id2name(realms, id);
     81 		if (name)
     82 			printf(" %s", name);
     83 		else
     84 			printf(" 0x%lx", id);
     85 	}
     86 }
     87 
     88 static void realm_print(const void *ip, const struct xt_entry_match *match,
     89 			int numeric)
     90 {
     91 	const struct xt_realm_info *ri = (const void *)match->data;
     92 
     93 	if (ri->invert)
     94 		printf(" !");
     95 
     96 	printf(" realm");
     97 	print_realm(ri->id, ri->mask, numeric);
     98 }
     99 
    100 static void realm_save(const void *ip, const struct xt_entry_match *match)
    101 {
    102 	const struct xt_realm_info *ri = (const void *)match->data;
    103 
    104 	if (ri->invert)
    105 		printf(" !");
    106 
    107 	printf(" --realm");
    108 	print_realm(ri->id, ri->mask, 0);
    109 }
    110 
    111 static void
    112 print_realm_xlate(unsigned long id, unsigned long mask,
    113 		  int numeric, struct xt_xlate *xl, uint32_t op)
    114 {
    115 	const char *name = NULL;
    116 
    117 	if (mask != 0xffffffff)
    118 		xt_xlate_add(xl, " and 0x%lx %s 0x%lx", mask,
    119 			   op == XT_OP_EQ ? "==" : "!=", id);
    120 	else {
    121 		if (numeric == 0)
    122 			name = xtables_lmap_id2name(realms, id);
    123 		if (name)
    124 			xt_xlate_add(xl, " %s%s",
    125 				   op == XT_OP_EQ ? "" : "!= ", name);
    126 		else
    127 			xt_xlate_add(xl, " %s0x%lx",
    128 				   op == XT_OP_EQ ? "" : "!= ", id);
    129 	}
    130 }
    131 
    132 static int realm_xlate(struct xt_xlate *xl,
    133 		       const struct xt_xlate_mt_params *params)
    134 {
    135 	const struct xt_realm_info *ri = (const void *)params->match->data;
    136 	enum xt_op op = XT_OP_EQ;
    137 
    138 	if (ri->invert)
    139 		op = XT_OP_NEQ;
    140 
    141 	xt_xlate_add(xl, "rtclassid");
    142 	print_realm_xlate(ri->id, ri->mask, 0, xl, op);
    143 
    144 	return 1;
    145 }
    146 
    147 static struct xtables_match realm_mt_reg = {
    148 	.name		= "realm",
    149 	.version	= XTABLES_VERSION,
    150 	.family		= NFPROTO_IPV4,
    151 	.size		= XT_ALIGN(sizeof(struct xt_realm_info)),
    152 	.userspacesize	= XT_ALIGN(sizeof(struct xt_realm_info)),
    153 	.help		= realm_help,
    154 	.init		= realm_init,
    155 	.print		= realm_print,
    156 	.save		= realm_save,
    157 	.x6_parse	= realm_parse,
    158 	.x6_options	= realm_opts,
    159 	.xlate		= realm_xlate,
    160 };
    161 
    162 void _init(void)
    163 {
    164 	xtables_register_match(&realm_mt_reg);
    165 }
    166