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