libxt_tcpmss.c revision ea146a982e26c42f9954f140276f8deeb2edbe98
1/* Shared library add-on to iptables to add tcp MSS 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_tcpmss.h> 10 11/* Function which prints out usage message. */ 12static void 13help(void) 14{ 15 printf( 16"tcpmss match v%s options:\n" 17"[!] --mss value[:value] Match TCP MSS range.\n" 18" (only valid for TCP SYN or SYN/ACK packets)\n", 19IPTABLES_VERSION); 20} 21 22static const struct option opts[] = { 23 { "mss", 1, 0, '1' }, 24 {0} 25}; 26 27static u_int16_t 28parse_tcp_mssvalue(const char *mssvalue) 29{ 30 unsigned int mssvaluenum; 31 32 if (string_to_number(mssvalue, 0, 65535, &mssvaluenum) != -1) 33 return (u_int16_t)mssvaluenum; 34 35 exit_error(PARAMETER_PROBLEM, 36 "Invalid mss `%s' specified", mssvalue); 37} 38 39static void 40parse_tcp_mssvalues(const char *mssvaluestring, 41 u_int16_t *mss_min, u_int16_t *mss_max) 42{ 43 char *buffer; 44 char *cp; 45 46 buffer = strdup(mssvaluestring); 47 if ((cp = strchr(buffer, ':')) == NULL) 48 *mss_min = *mss_max = parse_tcp_mssvalue(buffer); 49 else { 50 *cp = '\0'; 51 cp++; 52 53 *mss_min = buffer[0] ? parse_tcp_mssvalue(buffer) : 0; 54 *mss_max = cp[0] ? parse_tcp_mssvalue(cp) : 0xFFFF; 55 } 56 free(buffer); 57} 58 59/* Function which parses command options; returns true if it 60 ate an option */ 61static int 62parse(int c, char **argv, int invert, unsigned int *flags, 63 const void *entry, 64 struct xt_entry_match **match) 65{ 66 struct xt_tcpmss_match_info *mssinfo = 67 (struct xt_tcpmss_match_info *)(*match)->data; 68 69 switch (c) { 70 case '1': 71 if (*flags) 72 exit_error(PARAMETER_PROBLEM, 73 "Only one `--mss' allowed"); 74 check_inverse(optarg, &invert, &optind, 0); 75 parse_tcp_mssvalues(argv[optind-1], 76 &mssinfo->mss_min, &mssinfo->mss_max); 77 if (invert) 78 mssinfo->invert = 1; 79 *flags = 1; 80 break; 81 default: 82 return 0; 83 } 84 return 1; 85} 86 87static void 88print_tcpmss(u_int16_t mss_min, u_int16_t mss_max, int invert, int numeric) 89{ 90 if (invert) 91 printf("! "); 92 93 if (mss_min == mss_max) 94 printf("%u ", mss_min); 95 else 96 printf("%u:%u ", mss_min, mss_max); 97} 98 99/* Final check; must have specified --mss. */ 100static void 101final_check(unsigned int flags) 102{ 103 if (!flags) 104 exit_error(PARAMETER_PROBLEM, 105 "tcpmss match: You must specify `--mss'"); 106} 107 108/* Prints out the matchinfo. */ 109static void 110print(const void *ip, 111 const struct xt_entry_match *match, 112 int numeric) 113{ 114 const struct xt_tcpmss_match_info *mssinfo = 115 (const struct xt_tcpmss_match_info *)match->data; 116 117 printf("tcpmss match "); 118 print_tcpmss(mssinfo->mss_min, mssinfo->mss_max, 119 mssinfo->invert, numeric); 120} 121 122/* Saves the union ipt_matchinfo in parsable form to stdout. */ 123static void 124save(const void *ip, const struct xt_entry_match *match) 125{ 126 const struct xt_tcpmss_match_info *mssinfo = 127 (const struct xt_tcpmss_match_info *)match->data; 128 129 printf("--mss "); 130 print_tcpmss(mssinfo->mss_min, mssinfo->mss_max, 131 mssinfo->invert, 0); 132} 133 134static struct xtables_match tcpmss = { 135 .family = AF_INET, 136 .name = "tcpmss", 137 .version = IPTABLES_VERSION, 138 .size = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)), 139 .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_match_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 tcpmss6 = { 149 .family = AF_INET6, 150 .name = "tcpmss", 151 .version = IPTABLES_VERSION, 152 .size = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)), 153 .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_match_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(&tcpmss); 165 xtables_register_match(&tcpmss6); 166} 167