1/* Shared library add-on to iptables for DSCP 2 * 3 * (C) 2000- 2002 by Matthew G. Marsh <mgm@paktronix.com>, 4 * Harald Welte <laforge@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 25static void init(struct ipt_entry_target *t, unsigned int *nfcache) 26{ 27} 28 29static 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 45static struct option opts[] = { 46 { "set-dscp", 1, 0, 'F' }, 47 { "set-dscp-class", 1, 0, 'G' }, 48 { 0 } 49}; 50 51static void 52parse_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 69static void 70parse_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 79static int 80parse(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 110static void 111final_check(unsigned int flags) 112{ 113 if (!flags) 114 exit_error(PARAMETER_PROBLEM, 115 "DSCP target: Parameter --set-dscp is required"); 116} 117 118static void 119print_dscp(u_int8_t dscp, int numeric) 120{ 121 printf("0x%02x ", dscp); 122} 123 124/* Prints out the targinfo. */ 125static void 126print(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. */ 137static void 138save(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 146static 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 161void _init(void) 162{ 163 register_target(&dscp); 164} 165