libxt_length.c revision ddac6c5bc636003d664d25c08ea3fe176565096c
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 (string_to_number(s, 0, 0xFFFF, &len) == -1) 30 exit_error(PARAMETER_PROBLEM, "length invalid: `%s'\n", s); 31 else 32 return (u_int16_t )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 exit_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 exit_error(PARAMETER_PROBLEM, 71 "length: `--length' may only be " 72 "specified once"); 73 check_inverse(optarg, &invert, &optind, 0); 74 parse_lengths(argv[optind-1], 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 exit_error(PARAMETER_PROBLEM, 90 "length: You must specify `--length'"); 91} 92 93static void 94print_length(struct xt_length_info *info) 95{ 96 if (info->invert) 97 printf("! "); 98 99 if (info->max == info->min) 100 printf("%u ", info->min); 101 else 102 printf("%u:%u ", info->min, info->max); 103} 104 105static void 106length_print(const void *ip, const struct xt_entry_match *match, int numeric) 107{ 108 printf("length "); 109 print_length((struct xt_length_info *)match->data); 110} 111 112static void length_save(const void *ip, const struct xt_entry_match *match) 113{ 114 printf("--length "); 115 print_length((struct xt_length_info *)match->data); 116} 117 118static struct xtables_match length_match = { 119 .family = AF_UNSPEC, 120 .name = "length", 121 .version = XTABLES_VERSION, 122 .size = XT_ALIGN(sizeof(struct xt_length_info)), 123 .userspacesize = XT_ALIGN(sizeof(struct xt_length_info)), 124 .help = length_help, 125 .parse = length_parse, 126 .final_check = length_check, 127 .print = length_print, 128 .save = length_save, 129 .extra_opts = length_opts, 130}; 131 132void _init(void) 133{ 134 xtables_register_match(&length_match); 135} 136