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#define uint32 unsigned long 35#define uint16 unsigned short 36#define uint unsigned int 37#define uint8 unsigned char 38#define uint64 unsigned long long 39#include <swapi.h> 40#include <nvports.h> 41 42 43#define MAX_HOSTNAME 256 44 45 46static char* usage = 47 " 48Usage: add [interface-name] [vlan_id] 49 rem [vlan-name] 50 set_flag [interface-name] [flag-num] [0 | 1] 51 set_egress_map [vlan-name] [skb_priority] [vlan_qos] 52 set_ingress_map [vlan-name] [skb_priority] [vlan_qos] 53 set_name_type [name-type] 54 55* The [interface-name] is the name of the ethernet card that hosts 56 the VLAN you are talking about. 57* The vlan_id is the identifier (0-4095) of the VLAN you are operating on. 58* skb_priority is the priority in the socket buffer (sk_buff). 59* vlan_qos is the 3 bit priority in the VLAN header 60* name-type: VLAN_PLUS_VID (vlan0005), VLAN_PLUS_VID_NO_PAD (vlan5), 61 DEV_PLUS_VID (eth0.0005), DEV_PLUS_VID_NO_PAD (eth0.5) 62* bind-type: PER_DEVICE # Allows vlan 5 on eth0 and eth1 to be unique. 63 PER_KERNEL # Forces vlan 5 to be unique across all devices. 64* FLAGS: 1 REORDER_HDR When this is set, the VLAN device will move the 65 ethernet header around to make it look exactly like a real 66 ethernet device. This may help programs such as DHCPd which 67 read the raw ethernet packet and make assumptions about the 68 location of bytes. If you don't need it, don't turn it on, because 69 there will be at least a small performance degradation. Default 70 is OFF. 71"; 72 73void show_usage() { 74 fprintf(stdout,usage); 75} 76 77int hex_to_bytes(char* bytes, int bytes_length, char* hex_str) { 78 int hlen; 79 int i; 80 81 int j = 0; 82 char hex[3]; 83 char* stop; /* not used for any real purpose */ 84 85 hlen = strlen(hex_str); 86 87 hex[2] = 0; 88 89 for (i = 0; i<hlen; i++) { 90 91 hex[0] = hex_str[i]; 92 i++; 93 if (i >= hlen) { 94 return j; /* done */ 95 } 96 97 hex[1] = hex_str[i]; 98 bytes[j++] = (char)strtoul(hex, &stop, 16); 99 } 100 return j; 101} 102 103 104int main(int argc, char** argv) { 105 int fd; 106 struct vlan_ioctl_args if_request; 107 108 char* cmd = NULL; 109 char* if_name = NULL; 110 unsigned int vid = 0; 111 unsigned int skb_priority; 112 unsigned short vlan_qos; 113 unsigned int nm_type = VLAN_NAME_TYPE_PLUS_VID; 114 115 char* conf_file_name = "/proc/net/vlan/config"; 116 unsigned int port = 0; 117 int retVal, port_enb, port_untag, ports_enable; 118 char *curptr = NULL; 119 120 memset(&if_request, 0, sizeof(struct vlan_ioctl_args)); 121 122 if ((argc < 3) || (argc > 5)) { 123 fprintf(stdout,"Expecting argc to be 3-5, inclusive. Was: %d\n",argc); 124 125 show_usage(); 126 exit(1); 127 } 128 else { 129 cmd = argv[1]; 130 131 if (strcasecmp(cmd, "set_name_type") == 0) { 132 if (strcasecmp(argv[2], "VLAN_PLUS_VID") == 0) { 133 nm_type = VLAN_NAME_TYPE_PLUS_VID; 134 } 135 else if (strcasecmp(argv[2], "VLAN_PLUS_VID_NO_PAD") == 0) { 136 nm_type = VLAN_NAME_TYPE_PLUS_VID_NO_PAD; 137 } 138 else if (strcasecmp(argv[2], "DEV_PLUS_VID") == 0) { 139 nm_type = VLAN_NAME_TYPE_RAW_PLUS_VID; 140 } 141 else if (strcasecmp(argv[2], "DEV_PLUS_VID_NO_PAD") == 0) { 142 nm_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD; 143 } 144 else { 145 // MATHIEU 146 //cerr << "Invalid name type.\n"; 147 fprintf(stderr,"Invalid name type.\n"); 148 149 show_usage(); 150 exit(1); 151 } 152 if_request.u.name_type = nm_type; 153 } 154 else { 155 if_name = argv[2]; 156 if (strlen(if_name) > 15) { 157 // MATHIEU 158 //cerr << "ERROR: if_name must be 15 characters or less." << endl; 159 fprintf(stderr,"ERROR: if_name must be 15 characters or less.\n"); 160 161 exit(1); 162 } 163 strcpy(if_request.device1, if_name); 164 } 165 166 if (argc == 4) { 167 vid = atoi(argv[3]); 168 if_request.u.VID = vid; 169 } 170 171 if (argc == 5) { 172 skb_priority = atoi(argv[3]); 173 vlan_qos = atoi(argv[4]); 174 if_request.u.skb_priority = skb_priority; 175 if_request.vlan_qos = vlan_qos; 176 } 177 } 178 179 // Open up the /proc/vlan/config 180 if ((fd = open(conf_file_name, O_RDONLY)) < 0) { 181 // MATHIEU 182 //cerr << "ERROR: Could not open /proc/vlan/config.\n"; 183 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"); 184 185 } 186 else { 187 close(fd); 188 } 189 190 /* We use sockets now, instead of the file descriptor */ 191 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 192 fprintf(stderr, "FATAL: Couldn't open a socket..go figure!\n"); 193 exit(2); 194 } 195 196 /* add */ 197 if (strcasecmp(cmd, "add") == 0) { 198 if_request.cmd = ADD_VLAN_CMD; 199 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 200 fprintf(stderr,"ERROR: trying to add VLAN #%u to IF -:%s:- error: %s\n", 201 vid, if_name, strerror(errno)); 202 } 203 else { 204 205 if ((bcm_api_init())<0) { 206 fprintf(stderr,"No Robo device found\n"); 207 } 208 else 209 { 210 if (BCM_RET_SUCCESS != (retVal = bcm_vlan_create(0,vid))) 211 { 212 fprintf(stderr,"ERROR: trying to create VLAN #%u for switch\n", vid); 213 } 214 else 215 { 216 fprintf(stdout,"Added VLAN with VID == %u to IF -:%s:-\n", 217 vid, if_name); 218 if (vid == 1) { 219 fprintf(stdout, "WARNING: VLAN 1 does not work with many switches,\nconsider another number if you have problems.\n"); 220 } 221 } 222 bcm_api_deinit(); 223 } 224 225 } 226 }//if 227 else if (strcasecmp(cmd, "rem") == 0) { 228 if_request.cmd = DEL_VLAN_CMD; 229 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 230 fprintf(stderr,"ERROR: trying to remove VLAN -:%s:- error: %s\n", 231 if_name, strerror(errno)); 232 } 233 else { 234 if ((bcm_api_init())<0) { 235 fprintf(stderr,"No Robo device found\n"); 236 } 237 else 238 { 239 /* get vid from interface name */ 240 if ((curptr = strrchr(if_name,'.'))) { 241 if (!sscanf(++curptr,"%d",&vid)) 242 vid = 0; 243 } else 244 vid = 0; 245 if (BCM_RET_SUCCESS != (retVal = bcm_vlan_create(0,vid))) 246 { 247 fprintf(stderr,"ERROR: trying to remove VLAN #%u for switch\n", vid); 248 } 249 else 250 { 251 fprintf(stdout,"Removed VLAN -:%s:-\n", if_name); 252 } 253 bcm_api_deinit(); 254 } 255 } 256 }//if 257 else if (strcasecmp(cmd, "set_egress_map") == 0) { 258 if_request.cmd = SET_VLAN_EGRESS_PRIORITY_CMD; 259 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 260 fprintf(stderr,"ERROR: trying to set egress map on device -:%s:- error: %s\n", 261 if_name, strerror(errno)); 262 } 263 else { 264 fprintf(stdout,"Set egress mapping on device -:%s:- " 265 "Should be visible in /proc/net/vlan/%s\n", 266 if_name, if_name); 267 } 268 } 269 else if (strcasecmp(cmd, "set_ingress_map") == 0) { 270 if_request.cmd = SET_VLAN_INGRESS_PRIORITY_CMD; 271 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 272 fprintf(stderr,"ERROR: trying to set ingress map on device -:%s:- error: %s\n", 273 if_name, strerror(errno)); 274 } 275 else { 276 fprintf(stdout,"Set ingress mapping on device -:%s:- " 277 "Should be visible in /proc/net/vlan/%s\n", 278 if_name, if_name); 279 } 280 } 281 else if (strcasecmp(cmd, "set_flag") == 0) { 282 if_request.cmd = SET_VLAN_FLAG_CMD; 283 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 284 fprintf(stderr,"ERROR: trying to set flag on device -:%s:- error: %s\n", 285 if_name, strerror(errno)); 286 } 287 else { 288 fprintf(stdout,"Set flag on device -:%s:- " 289 "Should be visible in /proc/net/vlan/%s\n", 290 if_name, if_name); 291 } 292 } 293 else if (strcasecmp(cmd, "set_name_type") == 0) { 294 if_request.cmd = SET_VLAN_NAME_TYPE_CMD; 295 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 296 fprintf(stderr,"ERROR: trying to set name type for VLAN subsystem, error: %s\n", 297 strerror(errno)); 298 } 299 else { 300 fprintf(stdout,"Set name-type for VLAN subsystem." 301 " Should be visible in /proc/net/vlan/config\n"); 302 } 303 } 304 else if (strcasecmp(cmd, "add_port") == 0 || strcasecmp(cmd, "add_port_nountag") == 0 305 || strcasecmp(cmd, "add_port_nountag_nodeftag") == 0) { 306 /* enable port for this vlan id */ 307 vid = atoi(argv[2]); 308 port = atoi(argv[3]); 309 port_enb = PBMP_PORT((port-1)); 310 /* if add_port_nountag don't untag */ 311 if (strcasecmp(cmd, "add_port_nountag") == 0 312 || nvExistsPortAttrib("native",port) 313 || strcasecmp(cmd, "add_port_nountag_nodeftag") == 0) 314 port_untag = 0; 315 else 316 port_untag = PBMP_PORT((port-1)); 317 if (port < BCM_MIN_PORT || port > BCM_MAX_PORT) 318 { 319 fprintf(stderr,"ERROR: invalid port number, must be between %d and %d\n", 320 BCM_MIN_PORT,BCM_MAX_PORT); 321 } 322 if ((bcm_api_init())<0) { 323 fprintf(stderr,"No Robo device found\n"); 324 } 325 else 326 { 327 if (strcasecmp(cmd, "add_port_nountag_nodeftag") == 0) 328 { 329 if (BCM_RET_SUCCESS != (retVal = bcm_vlan_port_add(0,vid,port_enb,port_untag,0))){ 330 fprintf(stderr,"Error trying to add port\n"); 331 } 332 } 333 else 334 { 335 if (BCM_RET_SUCCESS != (retVal = bcm_vlan_port_add(0,vid,port_enb,port_untag,1))){ 336 fprintf(stderr,"Error trying to add port\n"); 337 } 338 } 339 bcm_api_deinit(); 340 } 341 }//if 342 else if (strcasecmp(cmd, "ports_enable") == 0) { 343 /* activate vlans in switch */ 344 ports_enable = atoi(argv[2]); 345 if (ports_enable > 1 || ports_enable < 0) 346 { 347 fprintf(stderr,"ERROR: invalid port enable, must be 0 or 1\n"); 348 } 349 if ((bcm_api_init())<0) { 350 fprintf(stderr,"No Robo device found\n"); 351 } 352 else 353 { 354 if (BCM_RET_SUCCESS != (retVal =bcm_vlan_enable(0,ports_enable))){ 355 fprintf(stderr,"Error trying to enable ports\n"); 356 } 357 bcm_api_deinit(); 358 } 359 } 360 else { 361 fprintf(stderr, "Unknown command -:%s:-\n", cmd); 362 363 show_usage(); 364 exit(5); 365 } 366 367 return 0; 368}/* main */ 369