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 " 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 unsigned 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 unsigned 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 147struct iptables_target dscp 148= { NULL, 149 "DSCP", 150 IPTABLES_VERSION, 151 IPT_ALIGN(sizeof(struct ipt_DSCP_info)), 152 IPT_ALIGN(sizeof(struct ipt_DSCP_info)), 153 &help, 154 &init, 155 &parse, 156 &final_check, 157 &print, 158 &save, 159 opts 160}; 161 162void _init(void) 163{ 164 register_target(&dscp); 165} 166