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