]> git.proxmox.com Git - mirror_iproute2.git/blob - ip/iplink_macvlan.c
tc/m_gact: Drop dead code
[mirror_iproute2.git] / ip / iplink_macvlan.c
1 /*
2 * iplink_macvlan.c macvlan/macvtap device support
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Patrick McHardy <kaber@trash.net>
10 * Arnd Bergmann <arnd@arndb.de>
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/socket.h>
17 #include <linux/if_link.h>
18 #include <linux/if_ether.h>
19
20 #include "rt_names.h"
21 #include "utils.h"
22 #include "ip_common.h"
23
24 #define pfx_err(lu, ...) { \
25 fprintf(stderr, "%s: ", lu->id); \
26 fprintf(stderr, __VA_ARGS__); \
27 fprintf(stderr, "\n"); \
28 }
29
30 static void print_explain(struct link_util *lu, FILE *f)
31 {
32 fprintf(f,
33 "Usage: ... %s mode MODE [flag MODE_FLAG] MODE_OPTS\n"
34 "\n"
35 "MODE: private | vepa | bridge | passthru | source\n"
36 "MODE_FLAG: null | nopromisc\n"
37 "MODE_OPTS: for mode \"source\":\n"
38 "\tmacaddr { { add | del } <macaddr> | set [ <macaddr> [ <macaddr> ... ] ] | flush }\n",
39 lu->id
40 );
41 }
42
43 static void explain(struct link_util *lu)
44 {
45 print_explain(lu, stderr);
46 }
47
48
49 static int mode_arg(const char *arg)
50 {
51 fprintf(stderr,
52 "Error: argument of \"mode\" must be \"private\", \"vepa\", \"bridge\", \"passthru\" or \"source\", not \"%s\"\n",
53 arg);
54 return -1;
55 }
56
57 static int flag_arg(const char *arg)
58 {
59 fprintf(stderr,
60 "Error: argument of \"flag\" must be \"nopromisc\" or \"null\", not \"%s\"\n",
61 arg);
62 return -1;
63 }
64
65 static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
66 struct nlmsghdr *n)
67 {
68 __u32 mode = 0;
69 __u16 flags = 0;
70 __u32 mac_mode = 0;
71 int has_flags = 0;
72 char mac[ETH_ALEN];
73 struct rtattr *nmac;
74
75 while (argc > 0) {
76 if (matches(*argv, "mode") == 0) {
77 NEXT_ARG();
78
79 if (strcmp(*argv, "private") == 0)
80 mode = MACVLAN_MODE_PRIVATE;
81 else if (strcmp(*argv, "vepa") == 0)
82 mode = MACVLAN_MODE_VEPA;
83 else if (strcmp(*argv, "bridge") == 0)
84 mode = MACVLAN_MODE_BRIDGE;
85 else if (strcmp(*argv, "passthru") == 0)
86 mode = MACVLAN_MODE_PASSTHRU;
87 else if (strcmp(*argv, "source") == 0)
88 mode = MACVLAN_MODE_SOURCE;
89 else
90 return mode_arg(*argv);
91 } else if (matches(*argv, "flag") == 0) {
92 NEXT_ARG();
93
94 if (strcmp(*argv, "nopromisc") == 0)
95 flags |= MACVLAN_FLAG_NOPROMISC;
96 else if (strcmp(*argv, "null") == 0)
97 flags |= 0;
98 else
99 return flag_arg(*argv);
100
101 has_flags = 1;
102
103 } else if (matches(*argv, "macaddr") == 0) {
104 NEXT_ARG();
105
106 if (strcmp(*argv, "add") == 0) {
107 mac_mode = MACVLAN_MACADDR_ADD;
108 } else if (strcmp(*argv, "del") == 0) {
109 mac_mode = MACVLAN_MACADDR_DEL;
110 } else if (strcmp(*argv, "set") == 0) {
111 mac_mode = MACVLAN_MACADDR_SET;
112 } else if (strcmp(*argv, "flush") == 0) {
113 mac_mode = MACVLAN_MACADDR_FLUSH;
114 } else {
115 explain(lu);
116 return -1;
117 }
118
119 addattr32(n, 1024, IFLA_MACVLAN_MACADDR_MODE, mac_mode);
120
121 if (mac_mode == MACVLAN_MACADDR_ADD ||
122 mac_mode == MACVLAN_MACADDR_DEL) {
123 NEXT_ARG();
124
125 if (ll_addr_a2n(mac, sizeof(mac),
126 *argv) != ETH_ALEN)
127 return -1;
128
129 addattr_l(n, 1024, IFLA_MACVLAN_MACADDR, &mac,
130 ETH_ALEN);
131 }
132
133 if (mac_mode == MACVLAN_MACADDR_SET) {
134 nmac = addattr_nest(n, 1024,
135 IFLA_MACVLAN_MACADDR_DATA);
136 while (NEXT_ARG_OK()) {
137 NEXT_ARG_FWD();
138
139 if (ll_addr_a2n(mac, sizeof(mac),
140 *argv) != ETH_ALEN) {
141 PREV_ARG();
142 break;
143 }
144
145 addattr_l(n, 1024, IFLA_MACVLAN_MACADDR,
146 &mac, ETH_ALEN);
147 }
148 addattr_nest_end(n, nmac);
149 }
150 } else if (matches(*argv, "nopromisc") == 0) {
151 flags |= MACVLAN_FLAG_NOPROMISC;
152 has_flags = 1;
153 } else if (matches(*argv, "help") == 0) {
154 explain(lu);
155 return -1;
156 } else {
157 pfx_err(lu, "unknown option \"%s\"?", *argv);
158 explain(lu);
159 return -1;
160 }
161 argc--, argv++;
162 }
163
164 if (mode)
165 addattr32(n, 1024, IFLA_MACVLAN_MODE, mode);
166
167 if (has_flags) {
168 if (flags & MACVLAN_FLAG_NOPROMISC &&
169 mode != MACVLAN_MODE_PASSTHRU) {
170 pfx_err(lu, "nopromisc flag only valid in passthru mode");
171 explain(lu);
172 return -1;
173 }
174 addattr16(n, 1024, IFLA_MACVLAN_FLAGS, flags);
175 }
176 return 0;
177 }
178
179 static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
180 {
181 __u32 mode;
182 __u16 flags;
183 __u32 count;
184 unsigned char *addr;
185 int len;
186 struct rtattr *rta;
187
188 if (!tb)
189 return;
190
191 if (!tb[IFLA_MACVLAN_MODE] ||
192 RTA_PAYLOAD(tb[IFLA_MACVLAN_MODE]) < sizeof(__u32))
193 return;
194
195 mode = rta_getattr_u32(tb[IFLA_MACVLAN_MODE]);
196 fprintf(f, "mode %s ",
197 mode == MACVLAN_MODE_PRIVATE ? "private"
198 : mode == MACVLAN_MODE_VEPA ? "vepa"
199 : mode == MACVLAN_MODE_BRIDGE ? "bridge"
200 : mode == MACVLAN_MODE_PASSTHRU ? "passthru"
201 : mode == MACVLAN_MODE_SOURCE ? "source"
202 : "unknown");
203
204 if (!tb[IFLA_MACVLAN_FLAGS] ||
205 RTA_PAYLOAD(tb[IFLA_MACVLAN_FLAGS]) < sizeof(__u16))
206 flags = 0;
207 else
208 flags = rta_getattr_u16(tb[IFLA_MACVLAN_FLAGS]);
209
210 if (flags & MACVLAN_FLAG_NOPROMISC)
211 fprintf(f, "nopromisc ");
212
213 /* in source mode, there are more options to print */
214
215 if (mode != MACVLAN_MODE_SOURCE)
216 return;
217
218 if (!tb[IFLA_MACVLAN_MACADDR_COUNT] ||
219 RTA_PAYLOAD(tb[IFLA_MACVLAN_MACADDR_COUNT]) < sizeof(__u32))
220 return;
221
222 count = rta_getattr_u32(tb[IFLA_MACVLAN_MACADDR_COUNT]);
223 fprintf(f, "remotes (%d) ", count);
224
225 if (!tb[IFLA_MACVLAN_MACADDR_DATA])
226 return;
227
228 rta = RTA_DATA(tb[IFLA_MACVLAN_MACADDR_DATA]);
229 len = RTA_PAYLOAD(tb[IFLA_MACVLAN_MACADDR_DATA]);
230
231 for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
232 if (rta->rta_type != IFLA_MACVLAN_MACADDR ||
233 RTA_PAYLOAD(rta) < 6)
234 continue;
235 addr = RTA_DATA(rta);
236 fprintf(f, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x ", addr[0],
237 addr[1], addr[2], addr[3], addr[4], addr[5]);
238 }
239 }
240
241 static void macvlan_print_help(struct link_util *lu, int argc, char **argv,
242 FILE *f)
243 {
244 print_explain(lu, f);
245 }
246
247 struct link_util macvlan_link_util = {
248 .id = "macvlan",
249 .maxattr = IFLA_MACVLAN_MAX,
250 .parse_opt = macvlan_parse_opt,
251 .print_opt = macvlan_print_opt,
252 .print_help = macvlan_print_help,
253 };
254
255 struct link_util macvtap_link_util = {
256 .id = "macvtap",
257 .maxattr = IFLA_MACVLAN_MAX,
258 .parse_opt = macvlan_parse_opt,
259 .print_opt = macvlan_print_opt,
260 .print_help = macvlan_print_help,
261 };