libxt_length.c revision 500f483fff529dcd88ec96b9d5054be6cd6363a0
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, NULL, '1' }, 25 { } 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 struct xt_entry_match **match) 71{ 72 struct xt_length_info *info = (struct xt_length_info *)(*match)->data; 73 74 switch (c) { 75 case '1': 76 if (*flags) 77 exit_error(PARAMETER_PROBLEM, 78 "length: `--length' may only be " 79 "specified once"); 80 check_inverse(optarg, &invert, &optind, 0); 81 parse_lengths(argv[optind-1], info); 82 if (invert) 83 info->invert = 1; 84 *flags = 1; 85 break; 86 87 default: 88 return 0; 89 } 90 return 1; 91} 92 93/* Final check; must have specified --length. */ 94static void 95final_check(unsigned int flags) 96{ 97 if (!flags) 98 exit_error(PARAMETER_PROBLEM, 99 "length: You must specify `--length'"); 100} 101 102/* Common match printing code. */ 103static void 104print_length(struct xt_length_info *info) 105{ 106 if (info->invert) 107 printf("! "); 108 109 if (info->max == info->min) 110 printf("%u ", info->min); 111 else 112 printf("%u:%u ", info->min, info->max); 113} 114 115/* Prints out the matchinfo. */ 116static void 117print(const void *ip, 118 const struct xt_entry_match *match, 119 int numeric) 120{ 121 printf("length "); 122 print_length((struct xt_length_info *)match->data); 123} 124 125/* Saves the union ipt_matchinfo in parsable form to stdout. */ 126static void 127save(const void *ip, const struct xt_entry_match *match) 128{ 129 printf("--length "); 130 print_length((struct xt_length_info *)match->data); 131} 132 133static struct xtables_match length = { 134 .family = AF_INET, 135 .name = "length", 136 .version = IPTABLES_VERSION, 137 .size = XT_ALIGN(sizeof(struct xt_length_info)), 138 .userspacesize = XT_ALIGN(sizeof(struct xt_length_info)), 139 .help = &help, 140 .parse = &parse, 141 .final_check = &final_check, 142 .print = &print, 143 .save = &save, 144 .extra_opts = opts 145}; 146 147static struct xtables_match length6 = { 148 .family = AF_INET6, 149 .name = "length", 150 .version = IPTABLES_VERSION, 151 .size = XT_ALIGN(sizeof(struct xt_length_info)), 152 .userspacesize = XT_ALIGN(sizeof(struct xt_length_info)), 153 .help = &help, 154 .parse = &parse, 155 .final_check = &final_check, 156 .print = &print, 157 .save = &save, 158 .extra_opts = opts 159}; 160 161void _init(void) 162{ 163 xtables_register_match(&length); 164 xtables_register_match(&length6); 165} 166