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