libxt_tcpmss.c revision 7ac405297ec38449b30e3b05fd6bf2082fd3d803
1/* Shared library add-on to iptables to add tcp MSS matching support. */ 2#include <stdbool.h> 3#include <stdio.h> 4#include <netdb.h> 5#include <string.h> 6#include <stdlib.h> 7#include <getopt.h> 8 9#include <xtables.h> 10#include <linux/netfilter/xt_tcpmss.h> 11 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 {.name = "mss", .has_arg = true, .val = '1'}, 22 XT_GETOPT_TABLEEND, 23}; 24 25static uint16_t 26parse_tcp_mssvalue(const char *mssvalue) 27{ 28 unsigned int mssvaluenum; 29 30 if (xtables_strtoui(mssvalue, NULL, &mssvaluenum, 0, UINT16_MAX)) 31 return mssvaluenum; 32 33 xtables_error(PARAMETER_PROBLEM, 34 "Invalid mss `%s' specified", mssvalue); 35} 36 37static void 38parse_tcp_mssvalues(const char *mssvaluestring, 39 uint16_t *mss_min, uint16_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 57static int 58tcpmss_parse(int c, char **argv, int invert, unsigned int *flags, 59 const void *entry, struct xt_entry_match **match) 60{ 61 struct xt_tcpmss_match_info *mssinfo = 62 (struct xt_tcpmss_match_info *)(*match)->data; 63 64 switch (c) { 65 case '1': 66 if (*flags) 67 xtables_error(PARAMETER_PROBLEM, 68 "Only one `--mss' allowed"); 69 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 70 parse_tcp_mssvalues(optarg, 71 &mssinfo->mss_min, &mssinfo->mss_max); 72 if (invert) 73 mssinfo->invert = 1; 74 *flags = 1; 75 break; 76 default: 77 return 0; 78 } 79 return 1; 80} 81 82static void tcpmss_check(unsigned int flags) 83{ 84 if (!flags) 85 xtables_error(PARAMETER_PROBLEM, 86 "tcpmss match: You must specify `--mss'"); 87} 88 89static void 90tcpmss_print(const void *ip, const struct xt_entry_match *match, int numeric) 91{ 92 const struct xt_tcpmss_match_info *info = (void *)match->data; 93 94 printf("tcpmss match %s", info->invert ? "!" : ""); 95 if (info->mss_min == info->mss_max) 96 printf("%u ", info->mss_min); 97 else 98 printf("%u:%u ", info->mss_min, info->mss_max); 99} 100 101static void tcpmss_save(const void *ip, const struct xt_entry_match *match) 102{ 103 const struct xt_tcpmss_match_info *info = (void *)match->data; 104 105 printf("%s--mss ", info->invert ? "! " : ""); 106 if (info->mss_min == info->mss_max) 107 printf("%u ", info->mss_min); 108 else 109 printf("%u:%u ", info->mss_min, info->mss_max); 110} 111 112static struct xtables_match tcpmss_match = { 113 .family = NFPROTO_UNSPEC, 114 .name = "tcpmss", 115 .version = XTABLES_VERSION, 116 .size = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)), 117 .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)), 118 .help = tcpmss_help, 119 .parse = tcpmss_parse, 120 .final_check = tcpmss_check, 121 .print = tcpmss_print, 122 .save = tcpmss_save, 123 .extra_opts = tcpmss_opts, 124}; 125 126void _init(void) 127{ 128 xtables_register_match(&tcpmss_match); 129} 130