1// 2//Copyright (C) 2001 Ben Greear 3// 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. 8// 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. 13// 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. 17// 18// To contact the Author, Ben Greear: greearb@candelatech.com 19// 20 21 22#include <errno.h> 23#include <stdio.h> 24#include <stdlib.h> 25#include <unistd.h> 26#include <fcntl.h> 27#include <strings.h> 28#include <sys/ioctl.h> 29#include <linux/if_vlan.h> 30#include <linux/sockios.h> 31#include <string.h> 32#include <sys/socket.h> 33#include <sys/types.h> 34 35 36#define MAX_HOSTNAME 256 37 38 39static char* usage = \ 40"Usage: add [interface-name] [vlan_id]\n" 41" rem [vlan-name]\n" 42" set_flag [interface-name] [flag-num] [0 | 1]\n" 43" set_egress_map [vlan-name] [skb_priority] [vlan_qos]\n" 44" set_ingress_map [vlan-name] [skb_priority] [vlan_qos]\n" 45" set_name_type [name-type]\n" 46"\n" 47"* The [interface-name] is the name of the ethernet card that hosts\n" 48" the VLAN you are talking about.\n" 49"* The vlan_id is the identifier (0-4095) of the VLAN you are operating on.\n" 50"* skb_priority is the priority in the socket buffer (sk_buff).\n" 51"* vlan_qos is the 3 bit priority in the VLAN header\n" 52"* name-type: VLAN_PLUS_VID (vlan0005), VLAN_PLUS_VID_NO_PAD (vlan5),\n" 53" DEV_PLUS_VID (eth0.0005), DEV_PLUS_VID_NO_PAD (eth0.5)\n" 54"* bind-type: PER_DEVICE # Allows vlan 5 on eth0 and eth1 to be unique.\n" 55" PER_KERNEL # Forces vlan 5 to be unique across all devices.\n" 56"* FLAGS: 1 REORDER_HDR When this is set, the VLAN device will move the\n" 57" ethernet header around to make it look exactly like a real\n" 58" ethernet device. This may help programs such as DHCPd which\n" 59" read the raw ethernet packet and make assumptions about the\n" 60" location of bytes. If you don't need it, don't turn it on, because\n" 61" there will be at least a small performance degradation. Default\n" 62" is OFF.\n"; 63 64void show_usage() { 65 fprintf(stdout,usage); 66} 67 68int hex_to_bytes(char* bytes, int bytes_length, char* hex_str) { 69 int hlen; 70 int i; 71 72 int j = 0; 73 char hex[3]; 74 char* stop; /* not used for any real purpose */ 75 76 hlen = strlen(hex_str); 77 78 hex[2] = 0; 79 80 for (i = 0; i<hlen; i++) { 81 82 hex[0] = hex_str[i]; 83 i++; 84 if (i >= hlen) { 85 return j; /* done */ 86 } 87 88 hex[1] = hex_str[i]; 89 bytes[j++] = (char)strtoul(hex, &stop, 16); 90 } 91 return j; 92} 93 94 95int main(int argc, char** argv) { 96 int fd; 97 struct vlan_ioctl_args if_request; 98 99 char* cmd = NULL; 100 char* if_name = NULL; 101 unsigned int vid = 0; 102 unsigned int skb_priority; 103 unsigned short vlan_qos; 104 unsigned int nm_type = VLAN_NAME_TYPE_PLUS_VID; 105 106 char* conf_file_name = "/proc/net/vlan/config"; 107 108 memset(&if_request, 0, sizeof(struct vlan_ioctl_args)); 109 110 if ((argc < 3) || (argc > 5)) { 111 fprintf(stdout,"Expecting argc to be 3-5, inclusive. Was: %d\n",argc); 112 113 show_usage(); 114 exit(1); 115 } 116 else { 117 cmd = argv[1]; 118 119 if (strcasecmp(cmd, "set_name_type") == 0) { 120 if (strcasecmp(argv[2], "VLAN_PLUS_VID") == 0) { 121 nm_type = VLAN_NAME_TYPE_PLUS_VID; 122 } 123 else if (strcasecmp(argv[2], "VLAN_PLUS_VID_NO_PAD") == 0) { 124 nm_type = VLAN_NAME_TYPE_PLUS_VID_NO_PAD; 125 } 126 else if (strcasecmp(argv[2], "DEV_PLUS_VID") == 0) { 127 nm_type = VLAN_NAME_TYPE_RAW_PLUS_VID; 128 } 129 else if (strcasecmp(argv[2], "DEV_PLUS_VID_NO_PAD") == 0) { 130 nm_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD; 131 } 132 else { 133 // MATHIEU 134 //cerr << "Invalid name type.\n"; 135 fprintf(stderr,"Invalid name type.\n"); 136 137 show_usage(); 138 exit(1); 139 } 140 if_request.u.name_type = nm_type; 141 } 142 else { 143 if_name = argv[2]; 144 if (strlen(if_name) > 15) { 145 // MATHIEU 146 //cerr << "ERROR: if_name must be 15 characters or less." << endl; 147 fprintf(stderr,"ERROR: if_name must be 15 characters or less.\n"); 148 149 exit(1); 150 } 151 strcpy(if_request.device1, if_name); 152 } 153 154 if (argc == 4) { 155 vid = atoi(argv[3]); 156 if_request.u.VID = vid; 157 } 158 159 if (argc == 5) { 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; 164 } 165 } 166 167 // Open up the /proc/vlan/config 168 if ((fd = open(conf_file_name, O_RDONLY)) < 0) { 169 // MATHIEU 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"); 172 173 } 174 else { 175 close(fd); 176 } 177 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"); 181 exit(2); 182 } 183 184 /* add */ 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)); 190 } 191 }//if 192 else if (strcasecmp(cmd, "rem") == 0) { 193 if_request.cmd = DEL_VLAN_CMD; 194 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 195 fprintf(stderr,"ERROR: trying to remove VLAN -:%s:- error: %s\n", 196 if_name, strerror(errno)); 197 } 198 }//if 199 else if (strcasecmp(cmd, "set_egress_map") == 0) { 200 if_request.cmd = SET_VLAN_EGRESS_PRIORITY_CMD; 201 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 202 fprintf(stderr,"ERROR: trying to set egress map on device -:%s:- error: %s\n", 203 if_name, strerror(errno)); 204 } 205 } 206 else if (strcasecmp(cmd, "set_ingress_map") == 0) { 207 if_request.cmd = SET_VLAN_INGRESS_PRIORITY_CMD; 208 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 209 fprintf(stderr,"ERROR: trying to set ingress map on device -:%s:- error: %s\n", 210 if_name, strerror(errno)); 211 } 212 } 213 else if (strcasecmp(cmd, "set_flag") == 0) { 214 if_request.cmd = SET_VLAN_FLAG_CMD; 215 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 216 fprintf(stderr,"ERROR: trying to set flag on device -:%s:- error: %s\n", 217 if_name, strerror(errno)); 218 } 219 } 220 else if (strcasecmp(cmd, "set_name_type") == 0) { 221 if_request.cmd = SET_VLAN_NAME_TYPE_CMD; 222 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 223 fprintf(stderr,"ERROR: trying to set name type for VLAN subsystem, error: %s\n", 224 strerror(errno)); 225 } 226 } 227 else { 228 fprintf(stderr, "Unknown command -:%s:-\n", cmd); 229 230 show_usage(); 231 exit(5); 232 } 233 234 return 0; 235}/* main */ 236