libxt_length.c revision 661f112072bc13a1625c4eb5983695e122ea97da
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 11/* Function which prints out usage message. */ 12static void 13help(void) 14{ 15 printf( 16"length v%s options:\n" 17"[!] --length length[:length] Match packet length against value or range\n" 18" of values (inclusive)\n", 19IPTABLES_VERSION); 20 21} 22 23static const struct option opts[] = { 24 { "length", 1, 0, '1' }, 25 {0} 26}; 27 28static u_int16_t 29parse_length(const char *s) 30{ 31 unsigned int len; 32 33 if (string_to_number(s, 0, 0xFFFF, &len) == -1) 34 exit_error(PARAMETER_PROBLEM, "length invalid: `%s'\n", s); 35 else 36 return (u_int16_t )len; 37} 38 39/* If a single value is provided, min and max are both set to the value */ 40static void 41parse_lengths(const char *s, struct xt_length_info *info) 42{ 43 char *buffer; 44 char *cp; 45 46 buffer = strdup(s); 47 if ((cp = strchr(buffer, ':')) == NULL) 48 info->min = info->max = parse_length(buffer); 49 else { 50 *cp = '\0'; 51 cp++; 52 53 info->min = buffer[0] ? parse_length(buffer) : 0; 54 info->max = cp[0] ? parse_length(cp) : 0xFFFF; 55 } 56 free(buffer); 57 58 if (info->min > info->max) 59 exit_error(PARAMETER_PROBLEM, 60 "length min. range value `%u' greater than max. " 61 "range value `%u'", info->min, info->max); 62 63} 64 65/* Function which parses command options; returns true if it 66 ate an option */ 67static int 68parse(int c, char **argv, int invert, unsigned int *flags, 69 const void *entry, 70 unsigned int *nfcache, 71 struct xt_entry_match **match) 72{ 73 struct xt_length_info *info = (struct xt_length_info *)(*match)->data; 74 75 switch (c) { 76 case '1': 77 if (*flags) 78 exit_error(PARAMETER_PROBLEM, 79 "length: `--length' may only be " 80 "specified once"); 81 check_inverse(optarg, &invert, &optind, 0); 82 parse_lengths(argv[optind-1], info); 83 if (invert) 84 info->invert = 1; 85 *flags = 1; 86 break; 87 88 default: 89 return 0; 90 } 91 return 1; 92} 93 94/* Final check; must have specified --length. */ 95static void 96final_check(unsigned int flags) 97{ 98 if (!flags) 99 exit_error(PARAMETER_PROBLEM, 100 "length: You must specify `--length'"); 101} 102 103/* Common match printing code. */ 104static void 105print_length(struct xt_length_info *info) 106{ 107 if (info->invert) 108 printf("! "); 109 110 if (info->max == info->min) 111 printf("%u ", info->min); 112 else 113 printf("%u:%u ", info->min, info->max); 114} 115 116/* Prints out the matchinfo. */ 117static void 118print(const void *ip, 119 const struct xt_entry_match *match, 120 int numeric) 121{ 122 printf("length "); 123 print_length((struct xt_length_info *)match->data); 124} 125 126/* Saves the union ipt_matchinfo in parsable form to stdout. */ 127static void 128save(const void *ip, const struct xt_entry_match *match) 129{ 130 printf("--length "); 131 print_length((struct xt_length_info *)match->data); 132} 133 134static struct xtables_match length = { 135 .family = AF_INET, 136 .name = "length", 137 .version = IPTABLES_VERSION, 138 .size = XT_ALIGN(sizeof(struct xt_length_info)), 139 .userspacesize = XT_ALIGN(sizeof(struct xt_length_info)), 140 .help = &help, 141 .parse = &parse, 142 .final_check = &final_check, 143 .print = &print, 144 .save = &save, 145 .extra_opts = opts 146}; 147 148static struct xtables_match length6 = { 149 .family = AF_INET6, 150 .name = "length", 151 .version = IPTABLES_VERSION, 152 .size = XT_ALIGN(sizeof(struct xt_length_info)), 153 .userspacesize = XT_ALIGN(sizeof(struct xt_length_info)), 154 .help = &help, 155 .parse = &parse, 156 .final_check = &final_check, 157 .print = &print, 158 .save = &save, 159 .extra_opts = opts 160}; 161 162void _init(void) 163{ 164 xtables_register_match(&length); 165 xtables_register_match(&length6); 166} 167