1 /* Shared library add-on to iptables for DSCP 2 * 3 * (C) 2000- 2002 by Matthew G. Marsh <mgm (at) paktronix.com>, 4 * Harald Welte <laforge (at) gnumonks.org> 5 * 6 * This program is distributed under the terms of GNU GPL v2, 1991 7 * 8 * libipt_DSCP.c borrowed heavily from libipt_TOS.c 9 * 10 * --set-class added by Iain Barnes 11 */ 12 #include <stdio.h> 13 #include <string.h> 14 #include <stdlib.h> 15 #include <getopt.h> 16 17 #include <iptables.h> 18 #include <linux/netfilter_ipv4/ip_tables.h> 19 #include <linux/netfilter_ipv4/ipt_DSCP.h> 20 21 /* This is evil, but it's my code - HW*/ 22 #include "libipt_dscp_helper.c" 23 24 25 static void init(struct ipt_entry_target *t, unsigned int *nfcache) 26 { 27 } 28 29 static void help(void) 30 { 31 printf( 32 "DSCP target options\n" 33 " --set-dscp value Set DSCP field in packet header to value\n" 34 " This value can be in decimal (ex: 32)\n" 35 " or in hex (ex: 0x20)\n" 36 " --set-dscp-class class Set the DSCP field in packet header to the\n" 37 " value represented by the DiffServ class value.\n" 38 " This class may be EF,BE or any of the CSxx\n" 39 " or AFxx classes.\n" 40 "\n" 41 " These two options are mutually exclusive !\n" 42 ); 43 } 44 45 static struct option opts[] = { 46 { "set-dscp", 1, 0, 'F' }, 47 { "set-dscp-class", 1, 0, 'G' }, 48 { 0 } 49 }; 50 51 static void 52 parse_dscp(const char *s, struct ipt_DSCP_info *dinfo) 53 { 54 unsigned int dscp; 55 56 if (string_to_number(s, 0, 255, &dscp) == -1) 57 exit_error(PARAMETER_PROBLEM, 58 "Invalid dscp `%s'\n", s); 59 60 if (dscp > IPT_DSCP_MAX) 61 exit_error(PARAMETER_PROBLEM, 62 "DSCP `%d` out of range\n", dscp); 63 64 dinfo->dscp = (u_int8_t )dscp; 65 return; 66 } 67 68 69 static void 70 parse_class(const char *s, struct ipt_DSCP_info *dinfo) 71 { 72 unsigned int dscp = class_to_dscp(s); 73 74 /* Assign the value */ 75 dinfo->dscp = (u_int8_t)dscp; 76 } 77 78 79 static int 80 parse(int c, char **argv, int invert, unsigned int *flags, 81 const struct ipt_entry *entry, 82 struct ipt_entry_target **target) 83 { 84 struct ipt_DSCP_info *dinfo 85 = (struct ipt_DSCP_info *)(*target)->data; 86 87 switch (c) { 88 case 'F': 89 if (*flags) 90 exit_error(PARAMETER_PROBLEM, 91 "DSCP target: Only use --set-dscp ONCE!"); 92 parse_dscp(optarg, dinfo); 93 *flags = 1; 94 break; 95 case 'G': 96 if (*flags) 97 exit_error(PARAMETER_PROBLEM, 98 "DSCP target: Only use --set-dscp-class ONCE!"); 99 parse_class(optarg, dinfo); 100 *flags = 1; 101 break; 102 103 default: 104 return 0; 105 } 106 107 return 1; 108 } 109 110 static void 111 final_check(unsigned int flags) 112 { 113 if (!flags) 114 exit_error(PARAMETER_PROBLEM, 115 "DSCP target: Parameter --set-dscp is required"); 116 } 117 118 static void 119 print_dscp(u_int8_t dscp, int numeric) 120 { 121 printf("0x%02x ", dscp); 122 } 123 124 /* Prints out the targinfo. */ 125 static void 126 print(const struct ipt_ip *ip, 127 const struct ipt_entry_target *target, 128 int numeric) 129 { 130 const struct ipt_DSCP_info *dinfo = 131 (const struct ipt_DSCP_info *)target->data; 132 printf("DSCP set "); 133 print_dscp(dinfo->dscp, numeric); 134 } 135 136 /* Saves the union ipt_targinfo in parsable form to stdout. */ 137 static void 138 save(const struct ipt_ip *ip, const struct ipt_entry_target *target) 139 { 140 const struct ipt_DSCP_info *dinfo = 141 (const struct ipt_DSCP_info *)target->data; 142 143 printf("--set-dscp 0x%02x ", dinfo->dscp); 144 } 145 146 static struct iptables_target dscp = { 147 .next = NULL, 148 .name = "DSCP", 149 .version = IPTABLES_VERSION, 150 .size = IPT_ALIGN(sizeof(struct ipt_DSCP_info)), 151 .userspacesize = IPT_ALIGN(sizeof(struct ipt_DSCP_info)), 152 .help = &help, 153 .init = &init, 154 .parse = &parse, 155 .final_check = &final_check, 156 .print = &print, 157 .save = &save, 158 .extra_opts = opts 159 }; 160 161 void ipt_DSCP_init(void) 162 { 163 register_target(&dscp); 164 } 165