1/* Shared library add-on to iptables for ECN, $Version$ 2 * 3 * (C) 2002 by Harald Welte <laforge@gnumonks.org> 4 * 5 * This program is distributed under the terms of GNU GPL v2, 1991 6 * 7 * libipt_ECN.c borrowed heavily from libipt_DSCP.c 8 */ 9#include <stdio.h> 10#include <xtables.h> 11#include <linux/netfilter_ipv4/ipt_ECN.h> 12 13enum { 14 O_ECN_TCP_REMOVE = 0, 15 O_ECN_TCP_CWR, 16 O_ECN_TCP_ECE, 17 O_ECN_IP_ECT, 18 F_ECN_TCP_REMOVE = 1 << O_ECN_TCP_REMOVE, 19 F_ECN_TCP_CWR = 1 << O_ECN_TCP_CWR, 20 F_ECN_TCP_ECE = 1 << O_ECN_TCP_ECE, 21}; 22 23static void ECN_help(void) 24{ 25 printf( 26"ECN target options\n" 27" --ecn-tcp-remove Remove all ECN bits from TCP header\n"); 28} 29 30#if 0 31"ECN target v%s EXPERIMENTAL options (use with extreme care!)\n" 32" --ecn-ip-ect Set the IPv4 ECT codepoint (0 to 3)\n" 33" --ecn-tcp-cwr Set the IPv4 CWR bit (0 or 1)\n" 34" --ecn-tcp-ece Set the IPv4 ECE bit (0 or 1)\n", 35#endif 36 37static const struct xt_option_entry ECN_opts[] = { 38 {.name = "ecn-tcp-remove", .id = O_ECN_TCP_REMOVE, .type = XTTYPE_NONE, 39 .excl = F_ECN_TCP_CWR | F_ECN_TCP_ECE}, 40 {.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_UINT8, 41 .min = 0, .max = 1, .excl = F_ECN_TCP_REMOVE}, 42 {.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_UINT8, 43 .min = 0, .max = 1, .excl = F_ECN_TCP_REMOVE}, 44 {.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8, 45 .min = 0, .max = 3}, 46 XTOPT_TABLEEND, 47}; 48 49static void ECN_parse(struct xt_option_call *cb) 50{ 51 struct ipt_ECN_info *einfo = cb->data; 52 53 xtables_option_parse(cb); 54 switch (cb->entry->id) { 55 case O_ECN_TCP_REMOVE: 56 einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR; 57 einfo->proto.tcp.ece = 0; 58 einfo->proto.tcp.cwr = 0; 59 break; 60 case O_ECN_TCP_CWR: 61 einfo->operation |= IPT_ECN_OP_SET_CWR; 62 einfo->proto.tcp.cwr = cb->val.u8; 63 break; 64 case O_ECN_TCP_ECE: 65 einfo->operation |= IPT_ECN_OP_SET_ECE; 66 einfo->proto.tcp.ece = cb->val.u8; 67 break; 68 case O_ECN_IP_ECT: 69 einfo->operation |= IPT_ECN_OP_SET_IP; 70 einfo->ip_ect = cb->val.u8; 71 break; 72 } 73} 74 75static void ECN_check(struct xt_fcheck_call *cb) 76{ 77 if (cb->xflags == 0) 78 xtables_error(PARAMETER_PROBLEM, 79 "ECN target: An operation is required"); 80} 81 82static void ECN_print(const void *ip, const struct xt_entry_target *target, 83 int numeric) 84{ 85 const struct ipt_ECN_info *einfo = 86 (const struct ipt_ECN_info *)target->data; 87 88 printf(" ECN"); 89 90 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 91 && einfo->proto.tcp.ece == 0 92 && einfo->proto.tcp.cwr == 0) 93 printf(" TCP remove"); 94 else { 95 if (einfo->operation & IPT_ECN_OP_SET_ECE) 96 printf(" ECE=%u", einfo->proto.tcp.ece); 97 98 if (einfo->operation & IPT_ECN_OP_SET_CWR) 99 printf(" CWR=%u", einfo->proto.tcp.cwr); 100 101 if (einfo->operation & IPT_ECN_OP_SET_IP) 102 printf(" ECT codepoint=%u", einfo->ip_ect); 103 } 104} 105 106static void ECN_save(const void *ip, const struct xt_entry_target *target) 107{ 108 const struct ipt_ECN_info *einfo = 109 (const struct ipt_ECN_info *)target->data; 110 111 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 112 && einfo->proto.tcp.ece == 0 113 && einfo->proto.tcp.cwr == 0) 114 printf(" --ecn-tcp-remove"); 115 else { 116 117 if (einfo->operation & IPT_ECN_OP_SET_ECE) 118 printf(" --ecn-tcp-ece %d", einfo->proto.tcp.ece); 119 120 if (einfo->operation & IPT_ECN_OP_SET_CWR) 121 printf(" --ecn-tcp-cwr %d", einfo->proto.tcp.cwr); 122 123 if (einfo->operation & IPT_ECN_OP_SET_IP) 124 printf(" --ecn-ip-ect %d", einfo->ip_ect); 125 } 126} 127 128static struct xtables_target ecn_tg_reg = { 129 .name = "ECN", 130 .version = XTABLES_VERSION, 131 .family = NFPROTO_IPV4, 132 .size = XT_ALIGN(sizeof(struct ipt_ECN_info)), 133 .userspacesize = XT_ALIGN(sizeof(struct ipt_ECN_info)), 134 .help = ECN_help, 135 .print = ECN_print, 136 .save = ECN_save, 137 .x6_parse = ECN_parse, 138 .x6_fcheck = ECN_check, 139 .x6_options = ECN_opts, 140}; 141 142void _init(void) 143{ 144 xtables_register_target(&ecn_tg_reg); 145} 146