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#include "libbb.h"
31#include <net/if.h>
32
33
34
35
36enum vlan_ioctl_cmds {
37 ADD_VLAN_CMD,
38 DEL_VLAN_CMD,
39 SET_VLAN_INGRESS_PRIORITY_CMD,
40 SET_VLAN_EGRESS_PRIORITY_CMD,
41 GET_VLAN_INGRESS_PRIORITY_CMD,
42 GET_VLAN_EGRESS_PRIORITY_CMD,
43 SET_VLAN_NAME_TYPE_CMD,
44 SET_VLAN_FLAG_CMD
45};
46enum vlan_name_types {
47 VLAN_NAME_TYPE_PLUS_VID,
48 VLAN_NAME_TYPE_RAW_PLUS_VID,
49 VLAN_NAME_TYPE_PLUS_VID_NO_PAD,
50 VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
51 VLAN_NAME_TYPE_HIGHEST
52};
53
54struct vlan_ioctl_args {
55 int cmd;
56 char device1[24];
57
58 union {
59 char device2[24];
60 int VID;
61 unsigned int skb_priority;
62 unsigned int name_type;
63 unsigned int bind_type;
64 unsigned int flag;
65 } u;
66
67 short vlan_qos;
68};
69
70#define VLAN_GROUP_ARRAY_LEN 4096
71#define SIOCSIFVLAN 0x8983
72
73
74
75
76static const char *xfind_str(const char *table, const char *str)
77{
78 while (strcasecmp(str, table + 1) != 0) {
79 if (!table[0])
80 bb_show_usage();
81 table += table[0];
82 }
83 return table - 1;
84}
85
86static const char cmds[] ALIGN1 = {
87 4, ADD_VLAN_CMD, 7,
88 'a','d','d',0,
89 3, DEL_VLAN_CMD, 7,
90 'r','e','m',0,
91 3, SET_VLAN_NAME_TYPE_CMD, 17,
92 's','e','t','_','n','a','m','e','_','t','y','p','e',0,
93 5, SET_VLAN_FLAG_CMD, 12,
94 's','e','t','_','f','l','a','g',0,
95 5, SET_VLAN_EGRESS_PRIORITY_CMD, 18,
96 's','e','t','_','e','g','r','e','s','s','_','m','a','p',0,
97 5, SET_VLAN_INGRESS_PRIORITY_CMD, 0,
98 's','e','t','_','i','n','g','r','e','s','s','_','m','a','p',0,
99};
100
101static const char name_types[] ALIGN1 = {
102 VLAN_NAME_TYPE_PLUS_VID, 16,
103 'V','L','A','N','_','P','L','U','S','_','V','I','D',0,
104 VLAN_NAME_TYPE_PLUS_VID_NO_PAD, 22,
105 'V','L','A','N','_','P','L','U','S','_','V','I','D','_','N','O','_','P','A','D',0,
106 VLAN_NAME_TYPE_RAW_PLUS_VID, 15,
107 'D','E','V','_','P','L','U','S','_','V','I','D',0,
108 VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, 0,
109 'D','E','V','_','P','L','U','S','_','V','I','D','_','N','O','_','P','A','D',0,
110};
111
112int vconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
113int vconfig_main(int argc, char **argv)
114{
115 struct vlan_ioctl_args ifr;
116 const char *p;
117 int fd;
118
119 memset(&ifr, 0, sizeof(ifr));
120
121 ++argv;
122 if (!argv[0])
123 bb_show_usage();
124 p = xfind_str(cmds + 2, argv[0]);
125 ifr.cmd = *p;
126 if (argc != p[-1])
127 bb_show_usage();
128
129 if (ifr.cmd == SET_VLAN_NAME_TYPE_CMD) {
130
131 ifr.u.name_type = *xfind_str(name_types + 1, argv[1]);
132 } else {
133 strncpy_IFNAMSIZ(ifr.device1, argv[1]);
134 p = argv[2];
135
136
137
138
139
140
141
142 if (ifr.cmd == SET_VLAN_FLAG_CMD) {
143
144 ifr.u.flag = xatou_range(p, 0, 1);
145
146 ifr.vlan_qos = xatou_range(argv[3], 0, 7);
147 } else if (ifr.cmd == ADD_VLAN_CMD) {
148
149 ifr.u.VID = xatou_range(p, 0, VLAN_GROUP_ARRAY_LEN - 1);
150 } else if (ifr.cmd != DEL_VLAN_CMD) {
151
152 ifr.u.skb_priority = xatou(p);
153 ifr.vlan_qos = xatou_range(argv[3], 0, 7);
154 }
155 }
156
157 fd = xsocket(AF_INET, SOCK_STREAM, 0);
158 ioctl_or_perror_and_die(fd, SIOCSIFVLAN, &ifr,
159 "ioctl error for %s", argv[0]);
160
161 return 0;
162}
163