2 //Copyright (C) 2001 Ben Greear
4 //This program is free software; you can redistribute it and/or
5 //modify it under the terms of the GNU Library General Public License
6 //as published by the Free Software Foundation; either version 2
7 //of the License, or (at your option) any later version.
9 //This program is distributed in the hope that it will be useful,
10 //but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 //GNU General Public License for more details.
14 //You should have received a copy of the GNU Library General Public License
15 //along with this program; if not, write to the Free Software
16 //Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 // To contact the Author, Ben Greear: greearb@candelatech.com
28 #include <sys/ioctl.h>
29 #include <linux/if_vlan.h>
30 #include <linux/sockios.h>
32 #include <sys/socket.h>
33 #include <sys/types.h>
36 #define MAX_HOSTNAME 256
41 "Usage: add [interface-name] [vlan_id]\n"
43 " set_flag [interface-name] [flag-num] [0 | 1]\n"
44 " set_egress_map [vlan-name] [skb_priority] [vlan_qos]\n"
45 " set_ingress_map [vlan-name] [skb_priority] [vlan_qos]\n"
46 " set_name_type [name-type]\n"
48 "* The [interface-name] is the name of the ethernet card that hosts\n"
49 " the VLAN you are talking about.\n"
50 "* The vlan_id is the identifier (0-4095) of the VLAN you are operating on.\n"
51 "* skb_priority is the priority in the socket buffer (sk_buff).\n"
52 "* vlan_qos is the 3 bit priority in the VLAN header\n"
53 "* name-type: VLAN_PLUS_VID (vlan0005), VLAN_PLUS_VID_NO_PAD (vlan5),\n"
54 " DEV_PLUS_VID (eth0.0005), DEV_PLUS_VID_NO_PAD (eth0.5)\n"
55 "* bind-type: PER_DEVICE # Allows vlan 5 on eth0 and eth1 to be unique.\n"
56 " PER_KERNEL # Forces vlan 5 to be unique across all devices.\n"
57 "* FLAGS: 1 REORDER_HDR When this is set, the VLAN device will move the\n"
58 " ethernet header around to make it look exactly like a real\n"
59 " ethernet device. This may help programs such as DHCPd which\n"
60 " read the raw ethernet packet and make assumptions about the\n"
61 " location of bytes. If you don't need it, don't turn it on, because\n"
62 " there will be at least a small performance degradation. Default\n"
66 fprintf(stdout
,usage
);
69 int hex_to_bytes(char* bytes
, int bytes_length
, char* hex_str
) {
75 char* stop
; /* not used for any real purpose */
77 hlen
= strlen(hex_str
);
81 for (i
= 0; i
<hlen
; i
++) {
90 bytes
[j
++] = (char)strtoul(hex
, &stop
, 16);
96 int main(int argc
, char** argv
) {
98 struct vlan_ioctl_args if_request
;
101 char* if_name
= NULL
;
102 unsigned int vid
= 0;
103 unsigned int skb_priority
;
104 unsigned short vlan_qos
;
105 unsigned int nm_type
= VLAN_NAME_TYPE_PLUS_VID
;
107 char* conf_file_name
= "/proc/net/vlan/config";
109 memset(&if_request
, 0, sizeof(struct vlan_ioctl_args
));
111 if ((argc
< 3) || (argc
> 5)) {
112 fprintf(stdout
,"Expecting argc to be 3-5, inclusive. Was: %d\n",argc
);
120 if (strcasecmp(cmd
, "set_name_type") == 0) {
121 if (strcasecmp(argv
[2], "VLAN_PLUS_VID") == 0) {
122 nm_type
= VLAN_NAME_TYPE_PLUS_VID
;
124 else if (strcasecmp(argv
[2], "VLAN_PLUS_VID_NO_PAD") == 0) {
125 nm_type
= VLAN_NAME_TYPE_PLUS_VID_NO_PAD
;
127 else if (strcasecmp(argv
[2], "DEV_PLUS_VID") == 0) {
128 nm_type
= VLAN_NAME_TYPE_RAW_PLUS_VID
;
130 else if (strcasecmp(argv
[2], "DEV_PLUS_VID_NO_PAD") == 0) {
131 nm_type
= VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD
;
135 //cerr << "Invalid name type.\n";
136 fprintf(stderr
,"Invalid name type.\n");
141 if_request
.u
.name_type
= nm_type
;
145 if (strlen(if_name
) > 15) {
147 //cerr << "ERROR: if_name must be 15 characters or less." << endl;
148 fprintf(stderr
,"ERROR: if_name must be 15 characters or less.\n");
151 strcpy(if_request
.device1
, if_name
);
156 if_request
.u
.VID
= vid
;
160 skb_priority
= atoi(argv
[3]);
161 vlan_qos
= atoi(argv
[4]);
162 if_request
.u
.skb_priority
= skb_priority
;
163 if_request
.vlan_qos
= vlan_qos
;
167 // Open up the /proc/vlan/config
168 if ((fd
= open(conf_file_name
, O_RDONLY
)) < 0) {
170 //cerr << "ERROR: Could not open /proc/vlan/config.\n";
171 fprintf(stderr
,"WARNING: Could not open /proc/net/vlan/config. Maybe you need to load the 8021q module, or maybe you are not using PROCFS??\n");
178 /* We use sockets now, instead of the file descriptor */
179 if ((fd
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
180 fprintf(stderr
, "FATAL: Couldn't open a socket..go figure!\n");
185 if (strcasecmp(cmd
, "add") == 0) {
186 if_request
.cmd
= ADD_VLAN_CMD
;
187 if (ioctl(fd
, SIOCSIFVLAN
, &if_request
) < 0) {
188 fprintf(stderr
,"ERROR: trying to add VLAN #%u to IF -:%s:- error: %s\n",
189 vid
, if_name
, strerror(errno
));
193 fprintf(stdout
,"Added VLAN with VID == %u to IF -:%s:-\n",
196 fprintf(stdout
, "WARNING: VLAN 1 does not work with many switches,\nconsider another number if you have problems.\n");
200 else if (strcasecmp(cmd
, "rem") == 0) {
201 if_request
.cmd
= DEL_VLAN_CMD
;
202 if (ioctl(fd
, SIOCSIFVLAN
, &if_request
) < 0) {
203 fprintf(stderr
,"ERROR: trying to remove VLAN -:%s:- error: %s\n",
204 if_name
, strerror(errno
));
208 fprintf(stdout
,"Removed VLAN -:%s:-\n", if_name
);
211 else if (strcasecmp(cmd
, "set_egress_map") == 0) {
212 if_request
.cmd
= SET_VLAN_EGRESS_PRIORITY_CMD
;
213 if (ioctl(fd
, SIOCSIFVLAN
, &if_request
) < 0) {
214 fprintf(stderr
,"ERROR: trying to set egress map on device -:%s:- error: %s\n",
215 if_name
, strerror(errno
));
219 fprintf(stdout
,"Set egress mapping on device -:%s:- "
220 "Should be visible in /proc/net/vlan/%s\n",
224 else if (strcasecmp(cmd
, "set_ingress_map") == 0) {
225 if_request
.cmd
= SET_VLAN_INGRESS_PRIORITY_CMD
;
226 if (ioctl(fd
, SIOCSIFVLAN
, &if_request
) < 0) {
227 fprintf(stderr
,"ERROR: trying to set ingress map on device -:%s:- error: %s\n",
228 if_name
, strerror(errno
));
232 fprintf(stdout
,"Set ingress mapping on device -:%s:- "
233 "Should be visible in /proc/net/vlan/%s\n",
237 else if (strcasecmp(cmd
, "set_flag") == 0) {
238 if_request
.cmd
= SET_VLAN_FLAG_CMD
;
239 if (ioctl(fd
, SIOCSIFVLAN
, &if_request
) < 0) {
240 fprintf(stderr
,"ERROR: trying to set flag on device -:%s:- error: %s\n",
241 if_name
, strerror(errno
));
245 fprintf(stdout
,"Set flag on device -:%s:- "
246 "Should be visible in /proc/net/vlan/%s\n",
250 else if (strcasecmp(cmd
, "set_name_type") == 0) {
251 if_request
.cmd
= SET_VLAN_NAME_TYPE_CMD
;
252 if (ioctl(fd
, SIOCSIFVLAN
, &if_request
) < 0) {
253 fprintf(stderr
,"ERROR: trying to set name type for VLAN subsystem, error: %s\n",
258 fprintf(stdout
,"Set name-type for VLAN subsystem."
259 " Should be visible in /proc/net/vlan/config\n");
263 fprintf(stderr
, "Unknown command -:%s:-\n", cmd
);