1*a71a9546SAutomerger Merge Worker /* Shared library add-on to iptables to add TCPMSS target support. 2*a71a9546SAutomerger Merge Worker * 3*a71a9546SAutomerger Merge Worker * Copyright (c) 2000 Marc Boucher 4*a71a9546SAutomerger Merge Worker */ 5*a71a9546SAutomerger Merge Worker #include "config.h" 6*a71a9546SAutomerger Merge Worker #include <stdio.h> 7*a71a9546SAutomerger Merge Worker #include <xtables.h> 8*a71a9546SAutomerger Merge Worker #include <netinet/ip.h> 9*a71a9546SAutomerger Merge Worker #include <linux/netfilter/xt_TCPMSS.h> 10*a71a9546SAutomerger Merge Worker 11*a71a9546SAutomerger Merge Worker enum { 12*a71a9546SAutomerger Merge Worker O_SET_MSS = 0, 13*a71a9546SAutomerger Merge Worker O_CLAMP_MSS, 14*a71a9546SAutomerger Merge Worker }; 15*a71a9546SAutomerger Merge Worker 16*a71a9546SAutomerger Merge Worker struct mssinfo { 17*a71a9546SAutomerger Merge Worker struct xt_entry_target t; 18*a71a9546SAutomerger Merge Worker struct xt_tcpmss_info mss; 19*a71a9546SAutomerger Merge Worker }; 20*a71a9546SAutomerger Merge Worker 21*a71a9546SAutomerger Merge Worker static void __TCPMSS_help(int hdrsize) 22*a71a9546SAutomerger Merge Worker { 23*a71a9546SAutomerger Merge Worker printf( 24*a71a9546SAutomerger Merge Worker "TCPMSS target mutually-exclusive options:\n" 25*a71a9546SAutomerger Merge Worker " --set-mss value explicitly set MSS option to specified value\n" 26*a71a9546SAutomerger Merge Worker " --clamp-mss-to-pmtu automatically clamp MSS value to (path_MTU - %d)\n", 27*a71a9546SAutomerger Merge Worker hdrsize); 28*a71a9546SAutomerger Merge Worker } 29*a71a9546SAutomerger Merge Worker 30*a71a9546SAutomerger Merge Worker static void TCPMSS_help(void) 31*a71a9546SAutomerger Merge Worker { 32*a71a9546SAutomerger Merge Worker __TCPMSS_help(sizeof(struct iphdr)); 33*a71a9546SAutomerger Merge Worker } 34*a71a9546SAutomerger Merge Worker 35*a71a9546SAutomerger Merge Worker static void TCPMSS_help6(void) 36*a71a9546SAutomerger Merge Worker { 37*a71a9546SAutomerger Merge Worker __TCPMSS_help(SIZEOF_STRUCT_IP6_HDR); 38*a71a9546SAutomerger Merge Worker } 39*a71a9546SAutomerger Merge Worker 40*a71a9546SAutomerger Merge Worker static const struct xt_option_entry TCPMSS4_opts[] = { 41*a71a9546SAutomerger Merge Worker {.name = "set-mss", .id = O_SET_MSS, .type = XTTYPE_UINT16, 42*a71a9546SAutomerger Merge Worker .min = 0, .max = UINT16_MAX - sizeof(struct iphdr), 43*a71a9546SAutomerger Merge Worker .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_tcpmss_info, mss)}, 44*a71a9546SAutomerger Merge Worker {.name = "clamp-mss-to-pmtu", .id = O_CLAMP_MSS, .type = XTTYPE_NONE}, 45*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND, 46*a71a9546SAutomerger Merge Worker }; 47*a71a9546SAutomerger Merge Worker 48*a71a9546SAutomerger Merge Worker static const struct xt_option_entry TCPMSS6_opts[] = { 49*a71a9546SAutomerger Merge Worker {.name = "set-mss", .id = O_SET_MSS, .type = XTTYPE_UINT16, 50*a71a9546SAutomerger Merge Worker .min = 0, .max = UINT16_MAX - SIZEOF_STRUCT_IP6_HDR, 51*a71a9546SAutomerger Merge Worker .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_tcpmss_info, mss)}, 52*a71a9546SAutomerger Merge Worker {.name = "clamp-mss-to-pmtu", .id = O_CLAMP_MSS, .type = XTTYPE_NONE}, 53*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND, 54*a71a9546SAutomerger Merge Worker }; 55*a71a9546SAutomerger Merge Worker 56*a71a9546SAutomerger Merge Worker static void TCPMSS_parse(struct xt_option_call *cb) 57*a71a9546SAutomerger Merge Worker { 58*a71a9546SAutomerger Merge Worker struct xt_tcpmss_info *mssinfo = cb->data; 59*a71a9546SAutomerger Merge Worker 60*a71a9546SAutomerger Merge Worker xtables_option_parse(cb); 61*a71a9546SAutomerger Merge Worker if (cb->entry->id == O_CLAMP_MSS) 62*a71a9546SAutomerger Merge Worker mssinfo->mss = XT_TCPMSS_CLAMP_PMTU; 63*a71a9546SAutomerger Merge Worker } 64*a71a9546SAutomerger Merge Worker 65*a71a9546SAutomerger Merge Worker static void TCPMSS_check(struct xt_fcheck_call *cb) 66*a71a9546SAutomerger Merge Worker { 67*a71a9546SAutomerger Merge Worker if (cb->xflags == 0) 68*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM, 69*a71a9546SAutomerger Merge Worker "TCPMSS target: At least one parameter is required"); 70*a71a9546SAutomerger Merge Worker } 71*a71a9546SAutomerger Merge Worker 72*a71a9546SAutomerger Merge Worker static void TCPMSS_print(const void *ip, const struct xt_entry_target *target, 73*a71a9546SAutomerger Merge Worker int numeric) 74*a71a9546SAutomerger Merge Worker { 75*a71a9546SAutomerger Merge Worker const struct xt_tcpmss_info *mssinfo = 76*a71a9546SAutomerger Merge Worker (const struct xt_tcpmss_info *)target->data; 77*a71a9546SAutomerger Merge Worker if(mssinfo->mss == XT_TCPMSS_CLAMP_PMTU) 78*a71a9546SAutomerger Merge Worker printf(" TCPMSS clamp to PMTU"); 79*a71a9546SAutomerger Merge Worker else 80*a71a9546SAutomerger Merge Worker printf(" TCPMSS set %u", mssinfo->mss); 81*a71a9546SAutomerger Merge Worker } 82*a71a9546SAutomerger Merge Worker 83*a71a9546SAutomerger Merge Worker static void TCPMSS_save(const void *ip, const struct xt_entry_target *target) 84*a71a9546SAutomerger Merge Worker { 85*a71a9546SAutomerger Merge Worker const struct xt_tcpmss_info *mssinfo = 86*a71a9546SAutomerger Merge Worker (const struct xt_tcpmss_info *)target->data; 87*a71a9546SAutomerger Merge Worker 88*a71a9546SAutomerger Merge Worker if(mssinfo->mss == XT_TCPMSS_CLAMP_PMTU) 89*a71a9546SAutomerger Merge Worker printf(" --clamp-mss-to-pmtu"); 90*a71a9546SAutomerger Merge Worker else 91*a71a9546SAutomerger Merge Worker printf(" --set-mss %u", mssinfo->mss); 92*a71a9546SAutomerger Merge Worker } 93*a71a9546SAutomerger Merge Worker 94*a71a9546SAutomerger Merge Worker static int TCPMSS_xlate(struct xt_xlate *xl, 95*a71a9546SAutomerger Merge Worker const struct xt_xlate_tg_params *params) 96*a71a9546SAutomerger Merge Worker { 97*a71a9546SAutomerger Merge Worker const struct xt_tcpmss_info *mssinfo = 98*a71a9546SAutomerger Merge Worker (const struct xt_tcpmss_info *)params->target->data; 99*a71a9546SAutomerger Merge Worker if (mssinfo->mss == XT_TCPMSS_CLAMP_PMTU) 100*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "tcp option maxseg size set rt mtu"); 101*a71a9546SAutomerger Merge Worker else 102*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "tcp option maxseg size set %d", mssinfo->mss); 103*a71a9546SAutomerger Merge Worker 104*a71a9546SAutomerger Merge Worker return 1; 105*a71a9546SAutomerger Merge Worker } 106*a71a9546SAutomerger Merge Worker 107*a71a9546SAutomerger Merge Worker static struct xtables_target tcpmss_tg_reg[] = { 108*a71a9546SAutomerger Merge Worker { 109*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV4, 110*a71a9546SAutomerger Merge Worker .name = "TCPMSS", 111*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION, 112*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_tcpmss_info)), 113*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_info)), 114*a71a9546SAutomerger Merge Worker .help = TCPMSS_help, 115*a71a9546SAutomerger Merge Worker .print = TCPMSS_print, 116*a71a9546SAutomerger Merge Worker .save = TCPMSS_save, 117*a71a9546SAutomerger Merge Worker .x6_parse = TCPMSS_parse, 118*a71a9546SAutomerger Merge Worker .x6_fcheck = TCPMSS_check, 119*a71a9546SAutomerger Merge Worker .x6_options = TCPMSS4_opts, 120*a71a9546SAutomerger Merge Worker .xlate = TCPMSS_xlate, 121*a71a9546SAutomerger Merge Worker }, 122*a71a9546SAutomerger Merge Worker { 123*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV6, 124*a71a9546SAutomerger Merge Worker .name = "TCPMSS", 125*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION, 126*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_tcpmss_info)), 127*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_info)), 128*a71a9546SAutomerger Merge Worker .help = TCPMSS_help6, 129*a71a9546SAutomerger Merge Worker .print = TCPMSS_print, 130*a71a9546SAutomerger Merge Worker .save = TCPMSS_save, 131*a71a9546SAutomerger Merge Worker .x6_parse = TCPMSS_parse, 132*a71a9546SAutomerger Merge Worker .x6_fcheck = TCPMSS_check, 133*a71a9546SAutomerger Merge Worker .x6_options = TCPMSS6_opts, 134*a71a9546SAutomerger Merge Worker .xlate = TCPMSS_xlate, 135*a71a9546SAutomerger Merge Worker }, 136*a71a9546SAutomerger Merge Worker }; 137*a71a9546SAutomerger Merge Worker 138*a71a9546SAutomerger Merge Worker void _init(void) 139*a71a9546SAutomerger Merge Worker { 140*a71a9546SAutomerger Merge Worker xtables_register_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg)); 141*a71a9546SAutomerger Merge Worker } 142