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