1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
/* ebt_mark
*
* Authors:
* Bart De Schuymer <bdschuym@pandora.be>
*
* July, 2002, September 2006
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include "../include/ebtables_u.h"
#include <linux/netfilter_bridge/ebt_mark_t.h>
static int mark_supplied;
#define MARK_TARGET '1'
#define MARK_SETMARK '2'
#define MARK_ORMARK '3'
#define MARK_ANDMARK '4'
#define MARK_XORMARK '5'
static const struct option opts[] =
{
{ "mark-target" , required_argument, 0, MARK_TARGET },
/* an oldtime messup, we should have always used the scheme
* <extension-name>-<option> */
{ "set-mark" , required_argument, 0, MARK_SETMARK },
{ "mark-set" , required_argument, 0, MARK_SETMARK },
{ "mark-or" , required_argument, 0, MARK_ORMARK },
{ "mark-and" , required_argument, 0, MARK_ANDMARK },
{ "mark-xor" , required_argument, 0, MARK_XORMARK },
{ 0 }
};
static void print_help()
{
printf(
"mark target options:\n"
" --mark-set value : Set nfmark value\n"
" --mark-or value : Or nfmark with value (nfmark |= value)\n"
" --mark-and value : And nfmark with value (nfmark &= value)\n"
" --mark-xor value : Xor nfmark with value (nfmark ^= value)\n"
" --mark-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
}
static void init(struct ebt_entry_target *target)
{
struct ebt_mark_t_info *markinfo =
(struct ebt_mark_t_info *)target->data;
markinfo->target = EBT_ACCEPT;
markinfo->mark = 0;
mark_supplied = 0;
}
#define OPT_MARK_TARGET 0x01
#define OPT_MARK_SETMARK 0x02
#define OPT_MARK_ORMARK 0x04
#define OPT_MARK_ANDMARK 0x08
#define OPT_MARK_XORMARK 0x10
static int parse(int c, char **argv, int argc,
const struct ebt_u_entry *entry, unsigned int *flags,
struct ebt_entry_target **target)
{
struct ebt_mark_t_info *markinfo =
(struct ebt_mark_t_info *)(*target)->data;
char *end;
switch (c) {
case MARK_TARGET:
{ int tmp;
ebt_check_option2(flags, OPT_MARK_TARGET);
if (FILL_TARGET(optarg, tmp))
ebt_print_error2("Illegal --mark-target target");
/* the 4 lsb are left to designate the target */
markinfo->target = (markinfo->target & ~EBT_VERDICT_BITS) | (tmp & EBT_VERDICT_BITS);
}
return 1;
case MARK_SETMARK:
ebt_check_option2(flags, OPT_MARK_SETMARK);
if (*flags & (OPT_MARK_ORMARK|OPT_MARK_ANDMARK|OPT_MARK_XORMARK))
ebt_print_error2("--mark-set cannot be used together with specific --mark option");
break;
case MARK_ORMARK:
ebt_check_option2(flags, OPT_MARK_ORMARK);
if (*flags & (OPT_MARK_SETMARK|OPT_MARK_ANDMARK|OPT_MARK_XORMARK))
ebt_print_error2("--mark-or cannot be used together with specific --mark option");
markinfo->target = (markinfo->target & EBT_VERDICT_BITS) | MARK_OR_VALUE;
break;
case MARK_ANDMARK:
ebt_check_option2(flags, OPT_MARK_ANDMARK);
if (*flags & (OPT_MARK_SETMARK|OPT_MARK_ORMARK|OPT_MARK_XORMARK))
ebt_print_error2("--mark-and cannot be used together with specific --mark option");
markinfo->target = (markinfo->target & EBT_VERDICT_BITS) | MARK_AND_VALUE;
break;
case MARK_XORMARK:
ebt_check_option2(flags, OPT_MARK_XORMARK);
if (*flags & (OPT_MARK_SETMARK|OPT_MARK_ANDMARK|OPT_MARK_ORMARK))
ebt_print_error2("--mark-xor cannot be used together with specific --mark option");
markinfo->target = (markinfo->target & EBT_VERDICT_BITS) | MARK_XOR_VALUE;
break;
default:
return 0;
}
/* mutual code */
markinfo->mark = strtoul(optarg, &end, 0);
if (*end != '\0' || end == optarg)
ebt_print_error2("Bad MARK value '%s'", optarg);
mark_supplied = 1;
return 1;
}
static void final_check(const struct ebt_u_entry *entry,
const struct ebt_entry_target *target, const char *name,
unsigned int hookmask, unsigned int time)
{
struct ebt_mark_t_info *markinfo =
(struct ebt_mark_t_info *)target->data;
if (time == 0 && mark_supplied == 0) {
ebt_print_error("No mark value supplied");
} else if (BASE_CHAIN && (markinfo->target|~EBT_VERDICT_BITS) == EBT_RETURN)
ebt_print_error("--mark-target RETURN not allowed on base chain");
}
static void print(const struct ebt_u_entry *entry,
const struct ebt_entry_target *target)
{
struct ebt_mark_t_info *markinfo =
(struct ebt_mark_t_info *)target->data;
int tmp;
tmp = markinfo->target & ~EBT_VERDICT_BITS;
if (tmp == MARK_SET_VALUE)
printf("--mark-set");
else if (tmp == MARK_OR_VALUE)
printf("--mark-or");
else if (tmp == MARK_XOR_VALUE)
printf("--mark-xor");
else if (tmp == MARK_AND_VALUE)
printf("--mark-and");
else
ebt_print_error("oops, unknown mark action, try a later version of ebtables");
printf(" 0x%lx", markinfo->mark);
tmp = markinfo->target | ~EBT_VERDICT_BITS;
printf(" --mark-target %s", TARGET_NAME(tmp));
}
static int compare(const struct ebt_entry_target *t1,
const struct ebt_entry_target *t2)
{
struct ebt_mark_t_info *markinfo1 =
(struct ebt_mark_t_info *)t1->data;
struct ebt_mark_t_info *markinfo2 =
(struct ebt_mark_t_info *)t2->data;
return markinfo1->target == markinfo2->target &&
markinfo1->mark == markinfo2->mark;
}
static struct ebt_u_target mark_target =
{
.name = "mark",
.size = sizeof(struct ebt_mark_t_info),
.help = print_help,
.init = init,
.parse = parse,
.final_check = final_check,
.print = print,
.compare = compare,
.extra_ops = opts,
};
static void _INIT(void)
{
ebt_register_target(&mark_target);
}
|