Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 1 | /* ebt_vlan |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 2 | * |
| 3 | * Authors: |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 4 | * Bart De Schuymer <bdschuym@pandora.be> |
fnm3 | f794d5a | 2002-06-14 17:28:13 +0000 | [diff] [blame] | 5 | * Nick Fedchik <nick@fedchik.org.ua> |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 6 | * |
fnm3 | f794d5a | 2002-06-14 17:28:13 +0000 | [diff] [blame] | 7 | * June, 2002 |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 8 | */ |
Bart De Schuymer | e4b1fdf | 2002-06-16 09:20:22 +0000 | [diff] [blame] | 9 | |
fnm3 | f794d5a | 2002-06-14 17:28:13 +0000 | [diff] [blame] | 10 | #include <stdio.h> |
| 11 | #include <stdlib.h> |
Bart De Schuymer | e4b1fdf | 2002-06-16 09:20:22 +0000 | [diff] [blame] | 12 | #include <string.h> |
Bart De Schuymer | e4b1fdf | 2002-06-16 09:20:22 +0000 | [diff] [blame] | 13 | #include <getopt.h> |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 14 | #include <ctype.h> |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 15 | #include "../include/ebtables_u.h" |
Bart De Schuymer | c1939b1 | 2002-11-20 19:41:54 +0000 | [diff] [blame] | 16 | #include "../include/ethernetdb.h" |
Bart De Schuymer | e4b1fdf | 2002-06-16 09:20:22 +0000 | [diff] [blame] | 17 | #include <linux/netfilter_bridge/ebt_vlan.h> |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 18 | #include <linux/if_ether.h> |
| 19 | |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 20 | #define NAME_VLAN_ID "id" |
| 21 | #define NAME_VLAN_PRIO "prio" |
| 22 | #define NAME_VLAN_ENCAP "encap" |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 23 | |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 24 | #define VLAN_ID '1' |
| 25 | #define VLAN_PRIO '2' |
| 26 | #define VLAN_ENCAP '3' |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 27 | |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 28 | static struct option opts[] = { |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 29 | {"vlan-id" , required_argument, NULL, VLAN_ID}, |
| 30 | {"vlan-prio" , required_argument, NULL, VLAN_PRIO}, |
| 31 | {"vlan-encap", required_argument, NULL, VLAN_ENCAP}, |
| 32 | { 0 } |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 33 | }; |
| 34 | |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 35 | /* |
| 36 | * option inverse flags definition |
| 37 | */ |
| 38 | #define OPT_VLAN_ID 0x01 |
| 39 | #define OPT_VLAN_PRIO 0x02 |
| 40 | #define OPT_VLAN_ENCAP 0x04 |
| 41 | #define OPT_VLAN_FLAGS (OPT_VLAN_ID | OPT_VLAN_PRIO | OPT_VLAN_ENCAP) |
| 42 | |
| 43 | struct ethertypeent *ethent; |
fnm3 | 91fc2be | 2002-06-25 16:37:52 +0000 | [diff] [blame] | 44 | |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 45 | static void print_help() |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 46 | { |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 47 | printf( |
| 48 | "vlan options:\n" |
| 49 | "--vlan-id [!] id : vlan-tagged frame identifier, 0,1-4096 (integer)\n" |
| 50 | "--vlan-prio [!] prio : Priority-tagged frame's user priority, 0-7 (integer)\n" |
| 51 | "--vlan-encap [!] encap : Encapsulated frame protocol (hexadecimal or name)\n"); |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 52 | } |
| 53 | |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 54 | static void init(struct ebt_entry_match *match) |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 55 | { |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 56 | struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) match->data; |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 57 | vlaninfo->invflags = 0; |
| 58 | vlaninfo->bitmask = 0; |
| 59 | } |
| 60 | |
Bart De Schuymer | 2f0d748 | 2003-06-04 06:23:49 +0000 | [diff] [blame] | 61 | |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 62 | static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, |
| 63 | unsigned int *flags, struct ebt_entry_match **match) |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 64 | { |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 65 | struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) (*match)->data; |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 66 | char *end; |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 67 | struct ebt_vlan_info local; |
| 68 | |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 69 | switch (c) { |
| 70 | case VLAN_ID: |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 71 | ebt_check_option2(flags, OPT_VLAN_ID); |
| 72 | if (ebt_check_inverse2(optarg)) |
| 73 | vlaninfo->invflags |= EBT_VLAN_ID; |
| 74 | local.id = strtoul(optarg, &end, 10); |
| 75 | if (local.id > 4094 || *end != '\0') |
| 76 | ebt_print_error2("Invalid --vlan-id range ('%s')", optarg); |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 77 | vlaninfo->id = local.id; |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 78 | vlaninfo->bitmask |= EBT_VLAN_ID; |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 79 | break; |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 80 | case VLAN_PRIO: |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 81 | ebt_check_option2(flags, OPT_VLAN_PRIO); |
| 82 | if (ebt_check_inverse2(optarg)) |
| 83 | vlaninfo->invflags |= EBT_VLAN_PRIO; |
| 84 | local.prio = strtoul(optarg, &end, 10); |
| 85 | if (local.prio >= 8 || *end != '\0') |
| 86 | ebt_print_error2("Invalid --vlan-prio range ('%s')", optarg); |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 87 | vlaninfo->prio = local.prio; |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 88 | vlaninfo->bitmask |= EBT_VLAN_PRIO; |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 89 | break; |
fnm3 | f794d5a | 2002-06-14 17:28:13 +0000 | [diff] [blame] | 90 | case VLAN_ENCAP: |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 91 | ebt_check_option2(flags, OPT_VLAN_ENCAP); |
| 92 | if (ebt_check_inverse2(optarg)) |
| 93 | vlaninfo->invflags |= EBT_VLAN_ENCAP; |
| 94 | local.encap = strtoul(optarg, &end, 16); |
Bart De Schuymer | c1939b1 | 2002-11-20 19:41:54 +0000 | [diff] [blame] | 95 | if (*end != '\0') { |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 96 | ethent = getethertypebyname(optarg); |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 97 | if (ethent == NULL) |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 98 | ebt_print_error("Unknown --vlan-encap value ('%s')", optarg); |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 99 | local.encap = ethent->e_ethertype; |
Bart De Schuymer | c1939b1 | 2002-11-20 19:41:54 +0000 | [diff] [blame] | 100 | } |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 101 | if (local.encap < ETH_ZLEN) |
| 102 | ebt_print_error2("Invalid --vlan-encap range ('%s')", optarg); |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 103 | vlaninfo->encap = htons(local.encap); |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 104 | vlaninfo->bitmask |= EBT_VLAN_ENCAP; |
fnm3 | f794d5a | 2002-06-14 17:28:13 +0000 | [diff] [blame] | 105 | break; |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 106 | default: |
| 107 | return 0; |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 108 | |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 109 | } |
| 110 | return 1; |
| 111 | } |
| 112 | |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 113 | static void final_check(const struct ebt_u_entry *entry, |
| 114 | const struct ebt_entry_match *match, |
| 115 | const char *name, unsigned int hookmask, unsigned int time) |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 116 | { |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 117 | if (entry->ethproto != ETH_P_8021Q || entry->invflags & EBT_IPROTO) |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 118 | ebt_print_error("For vlan filtering the protocol must be specified as 802_1Q"); |
fnm3 | cd33827 | 2002-11-09 13:27:31 +0000 | [diff] [blame] | 119 | |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 120 | /* Check if specified vlan-id=0 (priority-tagged frame condition) |
| 121 | * when vlan-prio was specified. */ |
| 122 | /* I see no reason why a user should be prohibited to match on a perhaps impossible situation <BDS> |
| 123 | if (vlaninfo->bitmask & EBT_VLAN_PRIO && |
| 124 | vlaninfo->id && vlaninfo->bitmask & EBT_VLAN_ID) |
| 125 | ebt_print_error("When setting --vlan-prio the specified --vlan-id must be 0");*/ |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 126 | } |
| 127 | |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 128 | static void print(const struct ebt_u_entry *entry, |
| 129 | const struct ebt_entry_match *match) |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 130 | { |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 131 | struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) match->data; |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 132 | |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 133 | if (vlaninfo->bitmask & EBT_VLAN_ID) { |
| 134 | printf("--vlan-id %s%d ", (vlaninfo->invflags & EBT_VLAN_ID) ? "! " : "", vlaninfo->id); |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 135 | } |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 136 | if (vlaninfo->bitmask & EBT_VLAN_PRIO) { |
| 137 | printf("--vlan-prio %s%d ", (vlaninfo->invflags & EBT_VLAN_PRIO) ? "! " : "", vlaninfo->prio); |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 138 | } |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 139 | if (vlaninfo->bitmask & EBT_VLAN_ENCAP) { |
| 140 | printf("--vlan-encap %s", (vlaninfo->invflags & EBT_VLAN_ENCAP) ? "! " : ""); |
fnm3 | 8e011e6 | 2002-11-21 10:32:04 +0000 | [diff] [blame] | 141 | ethent = getethertypebynumber(ntohs(vlaninfo->encap)); |
| 142 | if (ethent != NULL) { |
| 143 | printf("%s ", ethent->e_name); |
| 144 | } else { |
| 145 | printf("%4.4X ", ntohs(vlaninfo->encap)); |
| 146 | } |
fnm3 | f794d5a | 2002-06-14 17:28:13 +0000 | [diff] [blame] | 147 | } |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 148 | } |
| 149 | |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 150 | static int compare(const struct ebt_entry_match *vlan1, |
| 151 | const struct ebt_entry_match *vlan2) |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 152 | { |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 153 | struct ebt_vlan_info *vlaninfo1 = (struct ebt_vlan_info *) vlan1->data; |
| 154 | struct ebt_vlan_info *vlaninfo2 = (struct ebt_vlan_info *) vlan2->data; |
| 155 | |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 156 | if (vlaninfo1->bitmask != vlaninfo2->bitmask) |
| 157 | return 0; |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 158 | if (vlaninfo1->invflags != vlaninfo2->invflags) |
| 159 | return 0; |
Bart De Schuymer | ff58720 | 2005-02-08 20:02:28 +0000 | [diff] [blame] | 160 | if (vlaninfo1->bitmask & EBT_VLAN_ID && |
| 161 | vlaninfo1->id != vlaninfo2->id) |
| 162 | return 0; |
| 163 | if (vlaninfo1->bitmask & EBT_VLAN_PRIO && |
| 164 | vlaninfo1->prio != vlaninfo2->prio) |
| 165 | return 0; |
| 166 | if (vlaninfo1->bitmask & EBT_VLAN_ENCAP && |
| 167 | vlaninfo1->encap != vlaninfo2->encap) |
| 168 | return 0; |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 169 | return 1; |
| 170 | } |
| 171 | |
| 172 | static struct ebt_u_match vlan_match = { |
Bart De Schuymer | fbdebad | 2008-02-03 19:58:44 +0000 | [diff] [blame] | 173 | .name = "vlan", |
Bart De Schuymer | 7cf1cca | 2003-08-30 16:20:19 +0000 | [diff] [blame] | 174 | .size = sizeof(struct ebt_vlan_info), |
| 175 | .help = print_help, |
| 176 | .init = init, |
| 177 | .parse = parse, |
| 178 | .final_check = final_check, |
| 179 | .print = print, |
| 180 | .compare = compare, |
| 181 | .extra_ops = opts, |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 182 | }; |
| 183 | |
Bart De Schuymer | 64182a3 | 2004-01-21 20:39:54 +0000 | [diff] [blame] | 184 | void _init(void) |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 185 | { |
Bart De Schuymer | 8339ff1 | 2004-01-14 20:05:27 +0000 | [diff] [blame] | 186 | ebt_register_match(&vlan_match); |
Bart De Schuymer | 1abc55d | 2002-06-01 19:23:47 +0000 | [diff] [blame] | 187 | } |