libxt_length.c revision bbe83862a5e1baf15f7c923352d4afdf59bc70e2
1/* Shared library add-on to iptables to add packet length matching support. */ 2#include <stdio.h> 3#include <netdb.h> 4#include <string.h> 5#include <stdlib.h> 6#include <getopt.h> 7 8#include <xtables.h> 9#include <linux/netfilter/xt_length.h> 10 11static void length_help(void) 12{ 13 printf( 14"length match options:\n" 15"[!] --length length[:length] Match packet length against value or range\n" 16" of values (inclusive)\n"); 17} 18 19static const struct option length_opts[] = { 20 { "length", 1, NULL, '1' }, 21 { .name = NULL } 22}; 23 24static u_int16_t 25parse_length(const char *s) 26{ 27 unsigned int len; 28 29 if (!xtables_strtoui(s, NULL, &len, 0, UINT32_MAX)) 30 xtables_error(PARAMETER_PROBLEM, "length invalid: \"%s\"\n", s); 31 else 32 return len; 33} 34 35/* If a single value is provided, min and max are both set to the value */ 36static void 37parse_lengths(const char *s, struct xt_length_info *info) 38{ 39 char *buffer; 40 char *cp; 41 42 buffer = strdup(s); 43 if ((cp = strchr(buffer, ':')) == NULL) 44 info->min = info->max = parse_length(buffer); 45 else { 46 *cp = '\0'; 47 cp++; 48 49 info->min = buffer[0] ? parse_length(buffer) : 0; 50 info->max = cp[0] ? parse_length(cp) : 0xFFFF; 51 } 52 free(buffer); 53 54 if (info->min > info->max) 55 xtables_error(PARAMETER_PROBLEM, 56 "length min. range value `%u' greater than max. " 57 "range value `%u'", info->min, info->max); 58 59} 60 61static int 62length_parse(int c, char **argv, int invert, unsigned int *flags, 63 const void *entry, struct xt_entry_match **match) 64{ 65 struct xt_length_info *info = (struct xt_length_info *)(*match)->data; 66 67 switch (c) { 68 case '1': 69 if (*flags) 70 xtables_error(PARAMETER_PROBLEM, 71 "length: `--length' may only be " 72 "specified once"); 73 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 74 parse_lengths(optarg, info); 75 if (invert) 76 info->invert = 1; 77 *flags = 1; 78 break; 79 80 default: 81 return 0; 82 } 83 return 1; 84} 85 86static void length_check(unsigned int flags) 87{ 88 if (!flags) 89 xtables_error(PARAMETER_PROBLEM, 90 "length: You must specify `--length'"); 91} 92 93static void 94length_print(const void *ip, const struct xt_entry_match *match, int numeric) 95{ 96 const struct xt_length_info *info = (void *)match->data; 97 98 printf("length %s", info->invert ? "!" : ""); 99 if (info->min == info->max) 100 printf("%u ", info->min); 101 else 102 printf("%u:%u ", info->min, info->max); 103} 104 105static void length_save(const void *ip, const struct xt_entry_match *match) 106{ 107 const struct xt_length_info *info = (void *)match->data; 108 109 printf("%s--length ", info->invert ? "! " : ""); 110 if (info->min == info->max) 111 printf("%u ", info->min); 112 else 113 printf("%u:%u ", info->min, info->max); 114} 115 116static struct xtables_match length_match = { 117 .family = NFPROTO_UNSPEC, 118 .name = "length", 119 .version = XTABLES_VERSION, 120 .size = XT_ALIGN(sizeof(struct xt_length_info)), 121 .userspacesize = XT_ALIGN(sizeof(struct xt_length_info)), 122 .help = length_help, 123 .parse = length_parse, 124 .final_check = length_check, 125 .print = length_print, 126 .save = length_save, 127 .extra_opts = length_opts, 128}; 129 130void _init(void) 131{ 132 xtables_register_match(&length_match); 133} 134