Home | History | Annotate | Download | only in extensions
      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