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