libxt_addrtype.c revision 807e1f0e6ede73792337b595a99af21b01f8826e
1/* Shared library add-on to iptables to add addrtype matching support 2 * 3 * This program is released under the terms of GNU GPL */ 4#include <stdio.h> 5#include <string.h> 6#include <xtables.h> 7#include <linux/netfilter/xt_addrtype.h> 8 9enum { 10 O_SRC_TYPE = 0, 11 O_DST_TYPE, 12 O_LIMIT_IFACE_IN, 13 O_LIMIT_IFACE_OUT, 14 F_SRC_TYPE = 1 << O_SRC_TYPE, 15 F_DST_TYPE = 1 << O_DST_TYPE, 16 F_LIMIT_IFACE_IN = 1 << O_LIMIT_IFACE_IN, 17 F_LIMIT_IFACE_OUT = 1 << O_LIMIT_IFACE_OUT, 18}; 19 20/* from linux/rtnetlink.h, must match order of enumeration */ 21static const char *const rtn_names[] = { 22 "UNSPEC", 23 "UNICAST", 24 "LOCAL", 25 "BROADCAST", 26 "ANYCAST", 27 "MULTICAST", 28 "BLACKHOLE", 29 "UNREACHABLE", 30 "PROHIBIT", 31 "THROW", 32 "NAT", 33 "XRESOLVE", 34 NULL 35}; 36 37static void addrtype_help_types(void) 38{ 39 int i; 40 41 for (i = 0; rtn_names[i]; i++) 42 printf(" %s\n", rtn_names[i]); 43} 44 45static void addrtype_help_v0(void) 46{ 47 printf( 48"Address type match options:\n" 49" [!] --src-type type[,...] Match source address type\n" 50" [!] --dst-type type[,...] Match destination address type\n" 51"\n" 52"Valid types: \n"); 53 addrtype_help_types(); 54} 55 56static void addrtype_help_v1(void) 57{ 58 printf( 59"Address type match options:\n" 60" [!] --src-type type[,...] Match source address type\n" 61" [!] --dst-type type[,...] Match destination address type\n" 62" --limit-iface-in Match only on the packet's incoming device\n" 63" --limit-iface-out Match only on the packet's outgoing device\n" 64"\n" 65"Valid types: \n"); 66 addrtype_help_types(); 67} 68 69static int 70parse_type(const char *name, size_t len, uint16_t *mask) 71{ 72 int i; 73 74 for (i = 0; rtn_names[i]; i++) 75 if (strncasecmp(name, rtn_names[i], len) == 0) { 76 /* build up bitmask for kernel module */ 77 *mask |= (1 << i); 78 return 1; 79 } 80 81 return 0; 82} 83 84static void parse_types(const char *arg, uint16_t *mask) 85{ 86 const char *comma; 87 88 while ((comma = strchr(arg, ',')) != NULL) { 89 if (comma == arg || !parse_type(arg, comma-arg, mask)) 90 xtables_error(PARAMETER_PROBLEM, 91 "addrtype: bad type `%s'", arg); 92 arg = comma + 1; 93 } 94 95 if (strlen(arg) == 0 || !parse_type(arg, strlen(arg), mask)) 96 xtables_error(PARAMETER_PROBLEM, "addrtype: bad type \"%s\"", arg); 97} 98 99static void addrtype_parse_v0(struct xt_option_call *cb) 100{ 101 struct xt_addrtype_info *info = cb->data; 102 103 xtables_option_parse(cb); 104 switch (cb->entry->id) { 105 case O_SRC_TYPE: 106 parse_types(cb->arg, &info->source); 107 if (cb->invert) 108 info->invert_source = 1; 109 break; 110 case O_DST_TYPE: 111 parse_types(cb->arg, &info->dest); 112 if (cb->invert) 113 info->invert_dest = 1; 114 break; 115 } 116} 117 118static void addrtype_parse_v1(struct xt_option_call *cb) 119{ 120 struct xt_addrtype_info_v1 *info = cb->data; 121 122 xtables_option_parse(cb); 123 switch (cb->entry->id) { 124 case O_SRC_TYPE: 125 parse_types(cb->arg, &info->source); 126 if (cb->invert) 127 info->flags |= XT_ADDRTYPE_INVERT_SOURCE; 128 break; 129 case O_DST_TYPE: 130 parse_types(cb->arg, &info->dest); 131 if (cb->invert) 132 info->flags |= XT_ADDRTYPE_INVERT_DEST; 133 break; 134 case O_LIMIT_IFACE_IN: 135 info->flags |= XT_ADDRTYPE_LIMIT_IFACE_IN; 136 break; 137 case O_LIMIT_IFACE_OUT: 138 info->flags |= XT_ADDRTYPE_LIMIT_IFACE_OUT; 139 break; 140 } 141} 142 143static void addrtype_check(struct xt_fcheck_call *cb) 144{ 145 if (!(cb->xflags & (F_SRC_TYPE | F_DST_TYPE))) 146 xtables_error(PARAMETER_PROBLEM, 147 "addrtype: you must specify --src-type or --dst-type"); 148} 149 150static void print_types(uint16_t mask) 151{ 152 const char *sep = ""; 153 int i; 154 155 for (i = 0; rtn_names[i]; i++) 156 if (mask & (1 << i)) { 157 printf("%s%s", sep, rtn_names[i]); 158 sep = ","; 159 } 160} 161 162static void addrtype_print_v0(const void *ip, const struct xt_entry_match *match, 163 int numeric) 164{ 165 const struct xt_addrtype_info *info = (const void *)match->data; 166 167 printf(" ADDRTYPE match"); 168 if (info->source) { 169 printf(" src-type "); 170 if (info->invert_source) 171 printf("!"); 172 print_types(info->source); 173 } 174 if (info->dest) { 175 printf(" dst-type"); 176 if (info->invert_dest) 177 printf("!"); 178 print_types(info->dest); 179 } 180} 181 182static void addrtype_print_v1(const void *ip, const struct xt_entry_match *match, 183 int numeric) 184{ 185 const struct xt_addrtype_info_v1 *info = (const void *)match->data; 186 187 printf(" ADDRTYPE match"); 188 if (info->source) { 189 printf(" src-type "); 190 if (info->flags & XT_ADDRTYPE_INVERT_SOURCE) 191 printf("!"); 192 print_types(info->source); 193 } 194 if (info->dest) { 195 printf(" dst-type "); 196 if (info->flags & XT_ADDRTYPE_INVERT_DEST) 197 printf("!"); 198 print_types(info->dest); 199 } 200 if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN) 201 printf(" limit-in"); 202 if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) 203 printf(" limit-out"); 204} 205 206static void addrtype_save_v0(const void *ip, const struct xt_entry_match *match) 207{ 208 const struct xt_addrtype_info *info = (const void *)match->data; 209 210 if (info->source) { 211 if (info->invert_source) 212 printf(" !"); 213 printf(" --src-type "); 214 print_types(info->source); 215 } 216 if (info->dest) { 217 if (info->invert_dest) 218 printf(" !"); 219 printf(" --dst-type "); 220 print_types(info->dest); 221 } 222} 223 224static void addrtype_save_v1(const void *ip, const struct xt_entry_match *match) 225{ 226 const struct xt_addrtype_info_v1 *info = (const void *)match->data; 227 228 if (info->source) { 229 if (info->flags & XT_ADDRTYPE_INVERT_SOURCE) 230 printf(" !"); 231 printf(" --src-type "); 232 print_types(info->source); 233 } 234 if (info->dest) { 235 if (info->flags & XT_ADDRTYPE_INVERT_DEST) 236 printf(" !"); 237 printf(" --dst-type "); 238 print_types(info->dest); 239 } 240 if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN) 241 printf(" --limit-iface-in"); 242 if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) 243 printf(" --limit-iface-out"); 244} 245 246static const struct xt_option_entry addrtype_opts_v0[] = { 247 {.name = "src-type", .id = O_SRC_TYPE, .type = XTTYPE_STRING, 248 .flags = XTOPT_INVERT}, 249 {.name = "dst-type", .id = O_DST_TYPE, .type = XTTYPE_STRING, 250 .flags = XTOPT_INVERT}, 251 XTOPT_TABLEEND, 252}; 253 254static const struct xt_option_entry addrtype_opts_v1[] = { 255 {.name = "src-type", .id = O_SRC_TYPE, .type = XTTYPE_STRING, 256 .flags = XTOPT_INVERT}, 257 {.name = "dst-type", .id = O_DST_TYPE, .type = XTTYPE_STRING, 258 .flags = XTOPT_INVERT}, 259 {.name = "limit-iface-in", .id = O_LIMIT_IFACE_IN, 260 .type = XTTYPE_NONE, .excl = F_LIMIT_IFACE_OUT}, 261 {.name = "limit-iface-out", .id = O_LIMIT_IFACE_OUT, 262 .type = XTTYPE_NONE, .excl = F_LIMIT_IFACE_IN}, 263 XTOPT_TABLEEND, 264}; 265 266static struct xtables_match addrtype_mt_reg[] = { 267 { 268 .name = "addrtype", 269 .version = XTABLES_VERSION, 270 .family = NFPROTO_IPV4, 271 .size = XT_ALIGN(sizeof(struct xt_addrtype_info)), 272 .userspacesize = XT_ALIGN(sizeof(struct xt_addrtype_info)), 273 .help = addrtype_help_v0, 274 .print = addrtype_print_v0, 275 .save = addrtype_save_v0, 276 .x6_parse = addrtype_parse_v0, 277 .x6_fcheck = addrtype_check, 278 .x6_options = addrtype_opts_v0, 279 }, 280 { 281 .name = "addrtype", 282 .revision = 1, 283 .version = XTABLES_VERSION, 284 .family = NFPROTO_UNSPEC, 285 .size = XT_ALIGN(sizeof(struct xt_addrtype_info_v1)), 286 .userspacesize = XT_ALIGN(sizeof(struct xt_addrtype_info_v1)), 287 .help = addrtype_help_v1, 288 .print = addrtype_print_v1, 289 .save = addrtype_save_v1, 290 .x6_parse = addrtype_parse_v1, 291 .x6_fcheck = addrtype_check, 292 .x6_options = addrtype_opts_v1, 293 }, 294}; 295 296 297void _init(void) 298{ 299 xtables_register_matches(addrtype_mt_reg, ARRAY_SIZE(addrtype_mt_reg)); 300} 301