Home | History | Annotate | Download | only in extensions
      1 /* Shared library add-on to iptables to add TCPMSS target support.
      2  *
      3  * Copyright (c) 2000 Marc Boucher
      4 */
      5 #include <stdio.h>
      6 #include <string.h>
      7 #include <stdlib.h>
      8 #include <getopt.h>
      9 
     10 #include <ip6tables.h>
     11 #include <linux/netfilter_ipv6/ip6_tables.h>
     12 #include <linux/netfilter_ipv6/ip6t_TCPMSS.h>
     13 
     14 struct mssinfo {
     15 	struct ip6t_entry_target t;
     16 	struct ip6t_tcpmss_info mss;
     17 };
     18 
     19 /* Function which prints out usage message. */
     20 static void
     21 help(void)
     22 {
     23 	printf(
     24 "TCPMSS target v%s mutually-exclusive options:\n"
     25 "  --set-mss value               explicitly set MSS option to specified value\n"
     26 "  --clamp-mss-to-pmtu           automatically clamp MSS value to (path_MTU - 60)\n",
     27 IPTABLES_VERSION);
     28 }
     29 
     30 static struct option opts[] = {
     31 	{ "set-mss", 1, 0, '1' },
     32 	{ "clamp-mss-to-pmtu", 0, 0, '2' },
     33 	{ 0 }
     34 };
     35 
     36 /* Initialize the target. */
     37 static void
     38 init(struct ip6t_entry_target *t, unsigned int *nfcache)
     39 {
     40 }
     41 
     42 /* Function which parses command options; returns true if it
     43    ate an option */
     44 static int
     45 parse(int c, char **argv, int invert, unsigned int *flags,
     46       const struct ip6t_entry *entry,
     47       struct ip6t_entry_target **target)
     48 {
     49 	struct ip6t_tcpmss_info *mssinfo
     50 		= (struct ip6t_tcpmss_info *)(*target)->data;
     51 
     52 	switch (c) {
     53 		unsigned int mssval;
     54 
     55 	case '1':
     56 		if (*flags)
     57 			exit_error(PARAMETER_PROBLEM,
     58 			           "TCPMSS target: Only one option may be specified");
     59 		if (string_to_number(optarg, 0, 65535 - 60, &mssval) == -1)
     60 			exit_error(PARAMETER_PROBLEM, "Bad TCPMSS value `%s'", optarg);
     61 
     62 		mssinfo->mss = mssval;
     63 		*flags = 1;
     64 		break;
     65 
     66 	case '2':
     67 		if (*flags)
     68 			exit_error(PARAMETER_PROBLEM,
     69 			           "TCPMSS target: Only one option may be specified");
     70 		mssinfo->mss = IP6T_TCPMSS_CLAMP_PMTU;
     71 		*flags = 1;
     72 		break;
     73 
     74 	default:
     75 		return 0;
     76 	}
     77 
     78 	return 1;
     79 }
     80 
     81 static void
     82 final_check(unsigned int flags)
     83 {
     84 	if (!flags)
     85 		exit_error(PARAMETER_PROBLEM,
     86 		           "TCPMSS target: At least one parameter is required");
     87 }
     88 
     89 /* Prints out the targinfo. */
     90 static void
     91 print(const struct ip6t_ip6 *ip6,
     92       const struct ip6t_entry_target *target,
     93       int numeric)
     94 {
     95 	const struct ip6t_tcpmss_info *mssinfo =
     96 		(const struct ip6t_tcpmss_info *)target->data;
     97 	if(mssinfo->mss == IP6T_TCPMSS_CLAMP_PMTU)
     98 		printf("TCPMSS clamp to PMTU ");
     99 	else
    100 		printf("TCPMSS set %u ", mssinfo->mss);
    101 }
    102 
    103 /* Saves the union ip6t_targinfo in parsable form to stdout. */
    104 static void
    105 save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
    106 {
    107 	const struct ip6t_tcpmss_info *mssinfo =
    108 		(const struct ip6t_tcpmss_info *)target->data;
    109 
    110 	if(mssinfo->mss == IP6T_TCPMSS_CLAMP_PMTU)
    111 		printf("--clamp-mss-to-pmtu ");
    112 	else
    113 		printf("--set-mss %u ", mssinfo->mss);
    114 }
    115 
    116 static struct ip6tables_target mss = {
    117 	.next		= NULL,
    118 	.name		= "TCPMSS",
    119 	.version	= IPTABLES_VERSION,
    120 	.size		= IP6T_ALIGN(sizeof(struct ip6t_tcpmss_info)),
    121 	.userspacesize	= IP6T_ALIGN(sizeof(struct ip6t_tcpmss_info)),
    122 	.help		= &help,
    123 	.init		= &init,
    124 	.parse		= &parse,
    125 	.final_check	= &final_check,
    126 	.print		= &print,
    127 	.save		= &save,
    128 	.extra_opts	= opts
    129 };
    130 
    131 void _init(void)
    132 {
    133 	register_target6(&mss);
    134 }
    135