libxt_length.c revision cea9f71f5618250a38acb21c31fbbf93a752f7d4
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 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 = AF_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