]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/iplink.c
Merge branch 'master' into iproute2-next
[mirror_iproute2.git] / ip / iplink.c
CommitLineData
aba5acdf
SH
1/*
2 * iplink.c "ip link".
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: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <unistd.h>
aba5acdf 16#include <fcntl.h>
1d934839 17#include <dlfcn.h>
aba5acdf
SH
18#include <errno.h>
19#include <sys/socket.h>
20#include <linux/if.h>
21#include <linux/if_packet.h>
22#include <linux/if_ether.h>
23#include <linux/sockios.h>
24#include <netinet/in.h>
25#include <arpa/inet.h>
26#include <string.h>
27#include <sys/ioctl.h>
fbea6115 28#include <stdbool.h>
837552b4 29#include <linux/mpls.h>
aba5acdf
SH
30
31#include "rt_names.h"
32#include "utils.h"
33#include "ip_common.h"
c3087c10 34#include "namespace.h"
aba5acdf 35
1d934839 36#define IPLINK_IOCTL_COMPAT 1
5e3bb534 37#ifndef LIBDIR
5c434a9e 38#define LIBDIR "/usr/lib"
b514b358 39#endif
aba5acdf 40
08f9d166
SH
41#ifndef GSO_MAX_SIZE
42#define GSO_MAX_SIZE 65536
43#endif
44#ifndef GSO_MAX_SEGS
45#define GSO_MAX_SEGS 65535
46#endif
47
48
aba5acdf 49static void usage(void) __attribute__((noreturn));
750a405a 50static int iplink_have_newlink(void);
aba5acdf
SH
51
52void iplink_usage(void)
53{
750a405a 54 if (iplink_have_newlink()) {
6773bcc2
SH
55 fprintf(stderr,
56 "Usage: ip link add [link DEV] [ name ] NAME\n"
57 " [ txqueuelen PACKETS ]\n"
58 " [ address LLADDR ]\n"
59 " [ broadcast LLADDR ]\n"
60 " [ mtu MTU ] [index IDX ]\n"
61 " [ numtxqueues QUEUE_COUNT ]\n"
62 " [ numrxqueues QUEUE_COUNT ]\n"
63 " type TYPE [ ARGS ]\n"
c7272ca7 64 "\n"
6773bcc2
SH
65 " ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]\n"
66 "\n"
67 " ip link set { DEVICE | dev DEVICE | group DEVGROUP }\n"
68 " [ { up | down } ]\n"
69 " [ type TYPE ARGS ]\n");
750a405a 70 } else
bb6ab47b
SH
71 fprintf(stderr,
72 "Usage: ip link set DEVICE [ { up | down } ]\n");
750a405a 73
6773bcc2
SH
74 fprintf(stderr,
75 " [ arp { on | off } ]\n"
76 " [ dynamic { on | off } ]\n"
77 " [ multicast { on | off } ]\n"
78 " [ allmulticast { on | off } ]\n"
79 " [ promisc { on | off } ]\n"
80 " [ trailers { on | off } ]\n"
432b92a7 81 " [ carrier { on | off } ]\n"
6773bcc2
SH
82 " [ txqueuelen PACKETS ]\n"
83 " [ name NEWNAME ]\n"
84 " [ address LLADDR ]\n"
85 " [ broadcast LLADDR ]\n"
86 " [ mtu MTU ]\n"
87 " [ netns { PID | NAME } ]\n"
974ef93b 88 " [ link-netns NAME | link-netnsid ID ]\n"
6773bcc2
SH
89 " [ alias NAME ]\n"
90 " [ vf NUM [ mac LLADDR ]\n"
91 " [ vlan VLANID [ qos VLAN-QOS ] [ proto VLAN-PROTO ] ]\n"
6773bcc2
SH
92 " [ rate TXRATE ]\n"
93 " [ max_tx_rate TXRATE ]\n"
94 " [ min_tx_rate TXRATE ]\n"
6773bcc2
SH
95 " [ spoofchk { on | off} ]\n"
96 " [ query_rss { on | off} ]\n"
97 " [ state { auto | enable | disable} ] ]\n"
98 " [ trust { on | off} ] ]\n"
5a3ec4ba
EC
99 " [ node_guid { eui64 } ]\n"
100 " [ port_guid { eui64 } ]\n"
c7272ca7
DB
101 " [ xdp { off |\n"
102 " object FILE [ section NAME ] [ verbose ] |\n"
103 " pinned FILE } ]\n"
6773bcc2
SH
104 " [ master DEVICE ][ vrf NAME ]\n"
105 " [ nomaster ]\n"
106 " [ addrgenmode { eui64 | none | stable_secret | random } ]\n"
c2db423f
SH
107 " [ protodown { on | off } ]\n"
108 " [ gso_max_size BYTES ] | [ gso_max_segs PACKETS ]\n"
c7272ca7 109 "\n"
6773bcc2 110 " ip link show [ DEVICE | group GROUP ] [up] [master DEV] [vrf NAME] [type TYPE]\n");
750a405a 111
94f1a22a 112 fprintf(stderr, "\n ip link xstats type TYPE [ ARGS ]\n");
837552b4 113 fprintf(stderr, "\n ip link afstats [ dev DEVICE ]\n");
94f1a22a 114
750a405a 115 if (iplink_have_newlink()) {
6773bcc2 116 fprintf(stderr,
c7272ca7
DB
117 "\n"
118 " ip link help [ TYPE ]\n"
119 "\n"
7827b376 120 "TYPE := { vlan | veth | vcan | vxcan | dummy | ifb | macvlan | macvtap |\n"
6bd1ea28 121 " bridge | bond | team | ipoib | ip6tnl | ipip | sit | vxlan |\n"
8595cc40 122 " gre | gretap | erspan | ip6gre | ip6gretap | ip6erspan |\n"
88272775
HL
123 " vti | nlmon | team_slave | bond_slave | bridge_slave |\n"
124 " ipvlan | ipvtap | geneve | vrf | macsec | netdevsim | rmnet }\n");
750a405a 125 }
aba5acdf
SH
126 exit(-1);
127}
128
129static void usage(void)
130{
131 iplink_usage();
132}
133
14645ec2 134static int on_off(const char *msg, const char *realval)
aba5acdf 135{
6c5ffb9a
SH
136 fprintf(stderr,
137 "Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n",
138 msg, realval);
aba5acdf
SH
139 return -1;
140}
141
1d934839
PM
142static void *BODY; /* cached dlopen(NULL) handle */
143static struct link_util *linkutil_list;
144
22a84711 145struct link_util *get_link_kind(const char *id)
1d934839
PM
146{
147 void *dlh;
148 char buf[256];
149 struct link_util *l;
150
151 for (l = linkutil_list; l; l = l->next)
22a84711 152 if (strcmp(l->id, id) == 0)
1d934839
PM
153 return l;
154
5e3bb534 155 snprintf(buf, sizeof(buf), LIBDIR "/ip/link_%s.so", id);
1d934839
PM
156 dlh = dlopen(buf, RTLD_LAZY);
157 if (dlh == NULL) {
158 /* look in current binary, only open once */
159 dlh = BODY;
160 if (dlh == NULL) {
161 dlh = BODY = dlopen(NULL, RTLD_LAZY);
162 if (dlh == NULL)
163 return NULL;
164 }
165 }
166
22a84711 167 snprintf(buf, sizeof(buf), "%s_link_util", id);
1d934839
PM
168 l = dlsym(dlh, buf);
169 if (l == NULL)
170 return NULL;
171
172 l->next = linkutil_list;
173 linkutil_list = l;
174 return l;
175}
176
d1f28cf1 177static int get_link_mode(const char *mode)
82499282 178{
4ccfb44d 179 if (strcasecmp(mode, "default") == 0)
82499282 180 return IF_LINK_MODE_DEFAULT;
4ccfb44d 181 if (strcasecmp(mode, "dormant") == 0)
82499282
SH
182 return IF_LINK_MODE_DORMANT;
183 return -1;
184}
185
ff7c2084
JP
186static int get_addr_gen_mode(const char *mode)
187{
188 if (strcasecmp(mode, "eui64") == 0)
189 return IN6_ADDR_GEN_MODE_EUI64;
190 if (strcasecmp(mode, "none") == 0)
191 return IN6_ADDR_GEN_MODE_NONE;
8e098dd8
BM
192 if (strcasecmp(mode, "stable_secret") == 0)
193 return IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
8e12bc0a
BM
194 if (strcasecmp(mode, "random") == 0)
195 return IN6_ADDR_GEN_MODE_RANDOM;
ff7c2084
JP
196 return -1;
197}
198
1d934839
PM
199#if IPLINK_IOCTL_COMPAT
200static int have_rtnl_newlink = -1;
201
202static int accept_msg(const struct sockaddr_nl *who,
0628cddd 203 struct rtnl_ctrl_data *ctrl,
1d934839
PM
204 struct nlmsghdr *n, void *arg)
205{
206 struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n);
207
66e529f5
PM
208 if (n->nlmsg_type == NLMSG_ERROR &&
209 (err->error == -EOPNOTSUPP || err->error == -EINVAL))
1d934839
PM
210 have_rtnl_newlink = 0;
211 else
212 have_rtnl_newlink = 1;
213 return -1;
214}
215
216static int iplink_have_newlink(void)
217{
218 struct {
219 struct nlmsghdr n;
220 struct ifinfomsg i;
221 char buf[1024];
d17b136f
PS
222 } req = {
223 .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
224 .n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
225 .n.nlmsg_type = RTM_NEWLINK,
226 .i.ifi_family = AF_UNSPEC,
227 };
1d934839
PM
228
229 if (have_rtnl_newlink < 0) {
d2468da0
SH
230 if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) {
231 perror("request send failed");
232 exit(1);
233 }
1d934839
PM
234 rtnl_listen(&rth, accept_msg, NULL);
235 }
236 return have_rtnl_newlink;
237}
238#else /* IPLINK_IOCTL_COMPAT */
239static int iplink_have_newlink(void)
240{
241 return 1;
242}
243#endif /* ! IPLINK_IOCTL_COMPAT */
244
65083b5f 245static int nl_get_ll_addr_len(const char *ifname)
8fe58d58
PS
246{
247 int len;
65083b5f 248 int dev_index = ll_name_to_index(ifname);
8fe58d58
PS
249 struct iplink_req req = {
250 .n = {
251 .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
252 .nlmsg_type = RTM_GETLINK,
253 .nlmsg_flags = NLM_F_REQUEST
254 },
255 .i = {
256 .ifi_family = preferred_family,
257 .ifi_index = dev_index,
258 }
259 };
86bf43c7 260 struct nlmsghdr *answer;
8fe58d58
PS
261 struct rtattr *tb[IFLA_MAX+1];
262
65083b5f
SH
263 if (dev_index == 0)
264 return -1;
265
86bf43c7 266 if (rtnl_talk(&rth, &req.n, &answer) < 0)
8fe58d58
PS
267 return -1;
268
86bf43c7
HL
269 len = answer->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
270 if (len < 0) {
271 free(answer);
8fe58d58 272 return -1;
86bf43c7 273 }
8fe58d58 274
86bf43c7
HL
275 parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)),
276 len, NLA_F_NESTED);
277 if (!tb[IFLA_ADDRESS]) {
278 free(answer);
8fe58d58 279 return -1;
86bf43c7 280 }
8fe58d58 281
06867c37 282 len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
86bf43c7 283 free(answer);
06867c37 284 return len;
8fe58d58
PS
285}
286
56e9f0ab
MS
287static void iplink_parse_vf_vlan_info(int vf, int *argcp, char ***argvp,
288 struct ifla_vf_vlan_info *ivvip)
289{
290 int argc = *argcp;
291 char **argv = *argvp;
ae8e1cb8 292 unsigned int vci;
56e9f0ab
MS
293
294 NEXT_ARG();
ae8e1cb8 295 if (get_unsigned(&vci, *argv, 0) || vci > 4095)
56e9f0ab
MS
296 invarg("Invalid \"vlan\" value\n", *argv);
297
ae8e1cb8 298 ivvip->vlan = vci;
56e9f0ab
MS
299 ivvip->vf = vf;
300 ivvip->qos = 0;
301 ivvip->vlan_proto = htons(ETH_P_8021Q);
302 if (NEXT_ARG_OK()) {
303 NEXT_ARG();
304 if (matches(*argv, "qos") == 0) {
305 NEXT_ARG();
306 if (get_unsigned(&ivvip->qos, *argv, 0))
307 invarg("Invalid \"qos\" value\n", *argv);
308 } else {
309 /* rewind arg */
310 PREV_ARG();
311 }
312 }
313 if (NEXT_ARG_OK()) {
314 NEXT_ARG();
315 if (matches(*argv, "proto") == 0) {
316 NEXT_ARG();
317 if (ll_proto_a2n(&ivvip->vlan_proto, *argv))
318 invarg("protocol is invalid\n", *argv);
319 if (ivvip->vlan_proto != htons(ETH_P_8021AD) &&
320 ivvip->vlan_proto != htons(ETH_P_8021Q)) {
321 SPRINT_BUF(b1);
322 SPRINT_BUF(b2);
323 char msg[64 + sizeof(b1) + sizeof(b2)];
324
bb6ab47b
SH
325 sprintf(msg,
326 "Invalid \"vlan protocol\" value - supported %s, %s\n",
56e9f0ab
MS
327 ll_proto_n2a(htons(ETH_P_8021Q),
328 b1, sizeof(b1)),
329 ll_proto_n2a(htons(ETH_P_8021AD),
330 b2, sizeof(b2)));
331 invarg(msg, *argv);
332 }
333 } else {
334 /* rewind arg */
335 PREV_ARG();
336 }
337 }
338
339 *argcp = argc;
340 *argvp = argv;
341}
342
d1f28cf1 343static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
65083b5f 344 struct iplink_req *req, const char *dev)
3fd86630 345{
f89a2a05
SC
346 char new_rate_api = 0, count = 0, override_legacy_rate = 0;
347 struct ifla_vf_rate tivt;
3fd86630
CW
348 int len, argc = *argcp;
349 char **argv = *argvp;
350 struct rtattr *vfinfo;
1598b9ef 351
f89a2a05
SC
352 tivt.min_tx_rate = -1;
353 tivt.max_tx_rate = -1;
354
1598b9ef 355 vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO);
3fd86630 356
f89a2a05
SC
357 while (NEXT_ARG_OK()) {
358 NEXT_ARG();
359 count++;
360 if (!matches(*argv, "max_tx_rate")) {
361 /* new API in use */
362 new_rate_api = 1;
363 /* override legacy rate */
364 override_legacy_rate = 1;
365 } else if (!matches(*argv, "min_tx_rate")) {
366 /* new API in use */
367 new_rate_api = 1;
368 }
369 }
370
371 while (count--) {
372 /* rewind arg */
373 PREV_ARG();
374 }
375
3fd86630
CW
376 while (NEXT_ARG_OK()) {
377 NEXT_ARG();
1598b9ef 378 if (matches(*argv, "mac") == 0) {
a89193a7 379 struct ifla_vf_mac ivm = { 0 };
65083b5f 380 int halen = nl_get_ll_addr_len(dev);
6c5ffb9a 381
3fd86630 382 NEXT_ARG();
1598b9ef
SH
383 ivm.vf = vf;
384 len = ll_addr_a2n((char *)ivm.mac, 32, *argv);
385 if (len < 0)
386 return -1;
8fe58d58
PS
387 if (halen > 0 && len != halen) {
388 fprintf(stderr,
389 "Invalid address length %d - must be %d bytes\n",
390 len, halen);
391 return -1;
392 }
ef0a738c
SH
393 addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC,
394 &ivm, sizeof(ivm));
3fd86630 395 } else if (matches(*argv, "vlan") == 0) {
56e9f0ab 396 struct ifla_vf_vlan_info ivvi;
6c5ffb9a 397
56e9f0ab
MS
398 iplink_parse_vf_vlan_info(vf, &argc, &argv, &ivvi);
399 /* support the old interface in case of older kernel*/
400 if (ivvi.vlan_proto == htons(ETH_P_8021Q)) {
401 struct ifla_vf_vlan ivv;
402
403 ivv.vf = ivvi.vf;
404 ivv.vlan = ivvi.vlan;
405 ivv.qos = ivvi.qos;
406 addattr_l(&req->n, sizeof(*req),
407 IFLA_VF_VLAN, &ivv, sizeof(ivv));
408 } else {
409 struct rtattr *vfvlanlist;
410
411 vfvlanlist = addattr_nest(&req->n, sizeof(*req),
412 IFLA_VF_VLAN_LIST);
413 addattr_l(&req->n, sizeof(*req),
414 IFLA_VF_VLAN_INFO, &ivvi,
415 sizeof(ivvi));
416
417 while (NEXT_ARG_OK()) {
3fd86630 418 NEXT_ARG();
56e9f0ab
MS
419 if (matches(*argv, "vlan") != 0) {
420 PREV_ARG();
421 break;
422 }
423 iplink_parse_vf_vlan_info(vf, &argc,
424 &argv, &ivvi);
425 addattr_l(&req->n, sizeof(*req),
426 IFLA_VF_VLAN_INFO, &ivvi,
427 sizeof(ivvi));
3fd86630 428 }
56e9f0ab 429 addattr_nest_end(&req->n, vfvlanlist);
3fd86630 430 }
3fd86630 431 } else if (matches(*argv, "rate") == 0) {
1598b9ef 432 struct ifla_vf_tx_rate ivt;
6c5ffb9a 433
3fd86630 434 NEXT_ARG();
6c5ffb9a 435 if (get_unsigned(&ivt.rate, *argv, 0))
1598b9ef 436 invarg("Invalid \"rate\" value\n", *argv);
6c5ffb9a 437
1598b9ef 438 ivt.vf = vf;
f89a2a05
SC
439 if (!new_rate_api)
440 addattr_l(&req->n, sizeof(*req),
441 IFLA_VF_TX_RATE, &ivt, sizeof(ivt));
442 else if (!override_legacy_rate)
443 tivt.max_tx_rate = ivt.rate;
444
445 } else if (matches(*argv, "max_tx_rate") == 0) {
446 NEXT_ARG();
447 if (get_unsigned(&tivt.max_tx_rate, *argv, 0))
448 invarg("Invalid \"max tx rate\" value\n",
449 *argv);
450 tivt.vf = vf;
451
452 } else if (matches(*argv, "min_tx_rate") == 0) {
453 NEXT_ARG();
454 if (get_unsigned(&tivt.min_tx_rate, *argv, 0))
455 invarg("Invalid \"min tx rate\" value\n",
456 *argv);
457 tivt.vf = vf;
af89576d 458
7b8179c7
GR
459 } else if (matches(*argv, "spoofchk") == 0) {
460 struct ifla_vf_spoofchk ivs;
6c5ffb9a 461
7b8179c7
GR
462 NEXT_ARG();
463 if (matches(*argv, "on") == 0)
464 ivs.setting = 1;
465 else if (matches(*argv, "off") == 0)
466 ivs.setting = 0;
467 else
ff1e35ed 468 return on_off("spoofchk", *argv);
7b8179c7 469 ivs.vf = vf;
ef0a738c
SH
470 addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK,
471 &ivs, sizeof(ivs));
7b8179c7 472
6c55c8c4
VZ
473 } else if (matches(*argv, "query_rss") == 0) {
474 struct ifla_vf_rss_query_en ivs;
6c5ffb9a 475
6c55c8c4
VZ
476 NEXT_ARG();
477 if (matches(*argv, "on") == 0)
478 ivs.setting = 1;
479 else if (matches(*argv, "off") == 0)
480 ivs.setting = 0;
481 else
ff1e35ed 482 return on_off("query_rss", *argv);
6c55c8c4 483 ivs.vf = vf;
ef0a738c
SH
484 addattr_l(&req->n, sizeof(*req), IFLA_VF_RSS_QUERY_EN,
485 &ivs, sizeof(ivs));
6c55c8c4 486
b6d77d9e
HS
487 } else if (matches(*argv, "trust") == 0) {
488 struct ifla_vf_trust ivt;
56f5daac 489
b6d77d9e
HS
490 NEXT_ARG();
491 if (matches(*argv, "on") == 0)
492 ivt.setting = 1;
493 else if (matches(*argv, "off") == 0)
494 ivt.setting = 0;
495 else
496 invarg("Invalid \"trust\" value\n", *argv);
497 ivt.vf = vf;
ef0a738c
SH
498 addattr_l(&req->n, sizeof(*req), IFLA_VF_TRUST,
499 &ivt, sizeof(ivt));
b6d77d9e 500
07fa9c15
RE
501 } else if (matches(*argv, "state") == 0) {
502 struct ifla_vf_link_state ivl;
6c5ffb9a 503
07fa9c15
RE
504 NEXT_ARG();
505 if (matches(*argv, "auto") == 0)
506 ivl.link_state = IFLA_VF_LINK_STATE_AUTO;
507 else if (matches(*argv, "enable") == 0)
508 ivl.link_state = IFLA_VF_LINK_STATE_ENABLE;
509 else if (matches(*argv, "disable") == 0)
510 ivl.link_state = IFLA_VF_LINK_STATE_DISABLE;
511 else
512 invarg("Invalid \"state\" value\n", *argv);
513 ivl.vf = vf;
ef0a738c
SH
514 addattr_l(&req->n, sizeof(*req), IFLA_VF_LINK_STATE,
515 &ivl, sizeof(ivl));
d91fb3f4
EC
516 } else if (matches(*argv, "node_guid") == 0) {
517 struct ifla_vf_guid ivg;
518
519 NEXT_ARG();
520 ivg.vf = vf;
521 if (get_guid(&ivg.guid, *argv)) {
522 invarg("Invalid GUID format\n", *argv);
523 return -1;
524 }
ef0a738c
SH
525 addattr_l(&req->n, sizeof(*req), IFLA_VF_IB_NODE_GUID,
526 &ivg, sizeof(ivg));
d91fb3f4
EC
527 } else if (matches(*argv, "port_guid") == 0) {
528 struct ifla_vf_guid ivg;
529
530 NEXT_ARG();
531 ivg.vf = vf;
532 if (get_guid(&ivg.guid, *argv)) {
533 invarg("Invalid GUID format\n", *argv);
534 return -1;
535 }
ef0a738c
SH
536 addattr_l(&req->n, sizeof(*req), IFLA_VF_IB_PORT_GUID,
537 &ivg, sizeof(ivg));
3fd86630
CW
538 } else {
539 /* rewind arg */
540 PREV_ARG();
541 break;
542 }
543 }
544
f89a2a05
SC
545 if (new_rate_api) {
546 int tmin, tmax;
9a02651a 547
f89a2a05 548 if (tivt.min_tx_rate == -1 || tivt.max_tx_rate == -1) {
65083b5f 549 ipaddr_get_vf_rate(tivt.vf, &tmin, &tmax, dev);
f89a2a05
SC
550 if (tivt.min_tx_rate == -1)
551 tivt.min_tx_rate = tmin;
552 if (tivt.max_tx_rate == -1)
553 tivt.max_tx_rate = tmax;
554 }
04be08e0
GP
555
556 if (tivt.max_tx_rate && tivt.min_tx_rate > tivt.max_tx_rate) {
557 fprintf(stderr,
558 "Invalid min_tx_rate %d - must be <= max_tx_rate %d\n",
559 tivt.min_tx_rate, tivt.max_tx_rate);
560 return -1;
561 }
562
f89a2a05
SC
563 addattr_l(&req->n, sizeof(*req), IFLA_VF_RATE, &tivt,
564 sizeof(tivt));
565 }
566
3fd86630
CW
567 if (argc == *argcp)
568 incomplete_command();
569
1598b9ef 570 addattr_nest_end(&req->n, vfinfo);
3fd86630
CW
571
572 *argcp = argc;
573 *argvp = argv;
1598b9ef 574 return 0;
3fd86630
CW
575}
576
c58213f6 577int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type)
1d934839 578{
c58213f6
SP
579 char *name = NULL;
580 char *dev = NULL;
581 char *link = NULL;
909dfe2c
PE
582 int ret, len;
583 char abuf[32];
1d934839
PM
584 int qlen = -1;
585 int mtu = -1;
e2613dc8 586 int netns = -1;
ae7229d5 587 int vf = -1;
d992f3e6
JP
588 int numtxqueues = -1;
589 int numrxqueues = -1;
ccdcbf35 590 int link_netnsid = -1;
c58213f6
SP
591 int index = 0;
592 int group = -1;
8fe58d58 593 int addr_len = 0;
1d934839 594
909dfe2c 595 ret = argc;
1d934839
PM
596
597 while (argc > 0) {
598 if (strcmp(*argv, "up") == 0) {
909dfe2c
PE
599 req->i.ifi_change |= IFF_UP;
600 req->i.ifi_flags |= IFF_UP;
1d934839 601 } else if (strcmp(*argv, "down") == 0) {
909dfe2c
PE
602 req->i.ifi_change |= IFF_UP;
603 req->i.ifi_flags &= ~IFF_UP;
1d934839
PM
604 } else if (strcmp(*argv, "name") == 0) {
605 NEXT_ARG();
c58213f6 606 if (name)
a24315ba 607 duparg("name", *argv);
625df645
PS
608 if (check_ifname(*argv))
609 invarg("\"name\" not a valid ifname", *argv);
c58213f6 610 name = *argv;
65083b5f 611 if (!dev)
c58213f6 612 dev = name;
5e25cf77
PE
613 } else if (strcmp(*argv, "index") == 0) {
614 NEXT_ARG();
c58213f6 615 if (index)
b7ea12ae 616 duparg("index", *argv);
c58213f6
SP
617 index = atoi(*argv);
618 if (index <= 0)
3c682146 619 invarg("Invalid \"index\" value", *argv);
1d934839
PM
620 } else if (matches(*argv, "link") == 0) {
621 NEXT_ARG();
c58213f6 622 link = *argv;
1d934839
PM
623 } else if (matches(*argv, "address") == 0) {
624 NEXT_ARG();
8fe58d58 625 addr_len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
0aae2346 626 if (addr_len < 0)
cb2eb999 627 return -1;
bb6ab47b
SH
628 addattr_l(&req->n, sizeof(*req),
629 IFLA_ADDRESS, abuf, addr_len);
1d934839 630 } else if (matches(*argv, "broadcast") == 0 ||
6c5ffb9a 631 strcmp(*argv, "brd") == 0) {
1d934839
PM
632 NEXT_ARG();
633 len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
cb2eb999
AH
634 if (len < 0)
635 return -1;
bb6ab47b
SH
636 addattr_l(&req->n, sizeof(*req),
637 IFLA_BROADCAST, abuf, len);
1d934839 638 } else if (matches(*argv, "txqueuelen") == 0 ||
6c5ffb9a
SH
639 strcmp(*argv, "qlen") == 0 ||
640 matches(*argv, "txqlen") == 0) {
1d934839
PM
641 NEXT_ARG();
642 if (qlen != -1)
643 duparg("txqueuelen", *argv);
644 if (get_integer(&qlen, *argv, 0))
645 invarg("Invalid \"txqueuelen\" value\n", *argv);
bb6ab47b
SH
646 addattr_l(&req->n, sizeof(*req),
647 IFLA_TXQLEN, &qlen, 4);
1d934839
PM
648 } else if (strcmp(*argv, "mtu") == 0) {
649 NEXT_ARG();
650 if (mtu != -1)
651 duparg("mtu", *argv);
652 if (get_integer(&mtu, *argv, 0))
653 invarg("Invalid \"mtu\" value\n", *argv);
909dfe2c 654 addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4);
a872b870 655 } else if (strcmp(*argv, "xdpgeneric") == 0 ||
14683814 656 strcmp(*argv, "xdpdrv") == 0 ||
1b5e8094 657 strcmp(*argv, "xdpoffload") == 0 ||
a872b870
DB
658 strcmp(*argv, "xdp") == 0) {
659 bool generic = strcmp(*argv, "xdpgeneric") == 0;
14683814 660 bool drv = strcmp(*argv, "xdpdrv") == 0;
1b5e8094 661 bool offload = strcmp(*argv, "xdpoffload") == 0;
a872b870 662
c7272ca7 663 NEXT_ARG();
65083b5f 664 if (xdp_parse(&argc, &argv, req, dev,
4f2eb14f 665 generic, drv, offload))
c7272ca7 666 exit(-1);
a24315ba 667
c58213f6
SP
668 if (offload && name == dev)
669 dev = NULL;
4b726cb1
SH
670 } else if (strcmp(*argv, "netns") == 0) {
671 NEXT_ARG();
672 if (netns != -1)
673 duparg("netns", *argv);
6c5ffb9a
SH
674 netns = netns_get_fd(*argv);
675 if (netns >= 0)
ef0a738c
SH
676 addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD,
677 &netns, 4);
0dc34c77 678 else if (get_integer(&netns, *argv, 0) == 0)
bb6ab47b
SH
679 addattr_l(&req->n, sizeof(*req),
680 IFLA_NET_NS_PID, &netns, 4);
0dc34c77 681 else
4b726cb1 682 invarg("Invalid \"netns\" value\n", *argv);
1d934839
PM
683 } else if (strcmp(*argv, "multicast") == 0) {
684 NEXT_ARG();
909dfe2c 685 req->i.ifi_change |= IFF_MULTICAST;
6c5ffb9a
SH
686
687 if (strcmp(*argv, "on") == 0)
909dfe2c 688 req->i.ifi_flags |= IFF_MULTICAST;
6c5ffb9a 689 else if (strcmp(*argv, "off") == 0)
909dfe2c 690 req->i.ifi_flags &= ~IFF_MULTICAST;
6c5ffb9a 691 else
14645ec2 692 return on_off("multicast", *argv);
1d934839
PM
693 } else if (strcmp(*argv, "allmulticast") == 0) {
694 NEXT_ARG();
909dfe2c 695 req->i.ifi_change |= IFF_ALLMULTI;
6c5ffb9a
SH
696
697 if (strcmp(*argv, "on") == 0)
909dfe2c 698 req->i.ifi_flags |= IFF_ALLMULTI;
6c5ffb9a 699 else if (strcmp(*argv, "off") == 0)
909dfe2c 700 req->i.ifi_flags &= ~IFF_ALLMULTI;
6c5ffb9a 701 else
14645ec2 702 return on_off("allmulticast", *argv);
1d934839
PM
703 } else if (strcmp(*argv, "promisc") == 0) {
704 NEXT_ARG();
909dfe2c 705 req->i.ifi_change |= IFF_PROMISC;
6c5ffb9a
SH
706
707 if (strcmp(*argv, "on") == 0)
909dfe2c 708 req->i.ifi_flags |= IFF_PROMISC;
6c5ffb9a 709 else if (strcmp(*argv, "off") == 0)
909dfe2c 710 req->i.ifi_flags &= ~IFF_PROMISC;
6c5ffb9a 711 else
14645ec2 712 return on_off("promisc", *argv);
1d934839
PM
713 } else if (strcmp(*argv, "trailers") == 0) {
714 NEXT_ARG();
909dfe2c 715 req->i.ifi_change |= IFF_NOTRAILERS;
6c5ffb9a
SH
716
717 if (strcmp(*argv, "off") == 0)
909dfe2c 718 req->i.ifi_flags |= IFF_NOTRAILERS;
6c5ffb9a 719 else if (strcmp(*argv, "on") == 0)
909dfe2c 720 req->i.ifi_flags &= ~IFF_NOTRAILERS;
6c5ffb9a 721 else
14645ec2 722 return on_off("trailers", *argv);
1d934839
PM
723 } else if (strcmp(*argv, "arp") == 0) {
724 NEXT_ARG();
909dfe2c 725 req->i.ifi_change |= IFF_NOARP;
6c5ffb9a
SH
726
727 if (strcmp(*argv, "on") == 0)
909dfe2c 728 req->i.ifi_flags &= ~IFF_NOARP;
6c5ffb9a 729 else if (strcmp(*argv, "off") == 0)
909dfe2c 730 req->i.ifi_flags |= IFF_NOARP;
6c5ffb9a 731 else
e543a6a8 732 return on_off("arp", *argv);
432b92a7
ZS
733 } else if (strcmp(*argv, "carrier") == 0) {
734 int carrier;
bb6ab47b 735
432b92a7
ZS
736 NEXT_ARG();
737 if (strcmp(*argv, "on") == 0)
738 carrier = 1;
739 else if (strcmp(*argv, "off") == 0)
740 carrier = 0;
741 else
742 return on_off("carrier", *argv);
743
744 addattr8(&req->n, sizeof(*req), IFLA_CARRIER, carrier);
ae7229d5 745 } else if (strcmp(*argv, "vf") == 0) {
1598b9ef 746 struct rtattr *vflist;
6c5ffb9a 747
ae7229d5 748 NEXT_ARG();
6c5ffb9a 749 if (get_integer(&vf, *argv, 0))
ae7229d5 750 invarg("Invalid \"vf\" value\n", *argv);
6c5ffb9a 751
1598b9ef
SH
752 vflist = addattr_nest(&req->n, sizeof(*req),
753 IFLA_VFINFO_LIST);
65083b5f 754 if (!dev)
9a02651a
SH
755 missarg("dev");
756
65083b5f 757 len = iplink_parse_vf(vf, &argc, &argv, req, dev);
1598b9ef
SH
758 if (len < 0)
759 return -1;
760 addattr_nest_end(&req->n, vflist);
a24315ba 761
c58213f6
SP
762 if (name == dev)
763 dev = NULL;
a1e191b9
JP
764 } else if (matches(*argv, "master") == 0) {
765 int ifindex;
6c5ffb9a 766
a1e191b9
JP
767 NEXT_ARG();
768 ifindex = ll_name_to_index(*argv);
769 if (!ifindex)
770 invarg("Device does not exist\n", *argv);
771 addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
772 &ifindex, 4);
104444c2
DA
773 } else if (strcmp(*argv, "vrf") == 0) {
774 int ifindex;
775
776 NEXT_ARG();
777 ifindex = ll_name_to_index(*argv);
778 if (!ifindex)
779 invarg("Not a valid VRF name\n", *argv);
780 if (!name_is_vrf(*argv))
781 invarg("Not a valid VRF name\n", *argv);
782 addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
783 &ifindex, sizeof(ifindex));
a1e191b9
JP
784 } else if (matches(*argv, "nomaster") == 0) {
785 int ifindex = 0;
6c5ffb9a 786
a1e191b9
JP
787 addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
788 &ifindex, 4);
1d934839
PM
789 } else if (matches(*argv, "dynamic") == 0) {
790 NEXT_ARG();
909dfe2c 791 req->i.ifi_change |= IFF_DYNAMIC;
6c5ffb9a
SH
792
793 if (strcmp(*argv, "on") == 0)
909dfe2c 794 req->i.ifi_flags |= IFF_DYNAMIC;
6c5ffb9a 795 else if (strcmp(*argv, "off") == 0)
909dfe2c 796 req->i.ifi_flags &= ~IFF_DYNAMIC;
6c5ffb9a 797 else
14645ec2 798 return on_off("dynamic", *argv);
1d934839
PM
799 } else if (matches(*argv, "type") == 0) {
800 NEXT_ARG();
909dfe2c 801 *type = *argv;
1d934839
PM
802 argc--; argv++;
803 break;
ace9c961 804 } else if (matches(*argv, "alias") == 0) {
c4fb35bd 805 NEXT_ARG();
f88becf3
SP
806 len = strlen(*argv);
807 if (len >= IFALIASZ)
808 invarg("alias too long\n", *argv);
ace9c961 809 addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS,
f88becf3 810 *argv, len);
db02608b
VD
811 } else if (strcmp(*argv, "group") == 0) {
812 NEXT_ARG();
c58213f6 813 if (group != -1)
db02608b 814 duparg("group", *argv);
c58213f6 815 if (rtnl_group_a2n(&group, *argv))
db02608b 816 invarg("Invalid \"group\" value\n", *argv);
c58213f6 817 addattr32(&req->n, sizeof(*req), IFLA_GROUP, group);
82499282
SH
818 } else if (strcmp(*argv, "mode") == 0) {
819 int mode;
6c5ffb9a 820
82499282 821 NEXT_ARG();
4ccfb44d 822 mode = get_link_mode(*argv);
82499282
SH
823 if (mode < 0)
824 invarg("Invalid link mode\n", *argv);
825 addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode);
4f2fdd44
SH
826 } else if (strcmp(*argv, "state") == 0) {
827 int state;
6c5ffb9a 828
4f2fdd44
SH
829 NEXT_ARG();
830 state = get_operstate(*argv);
831 if (state < 0)
832 invarg("Invalid operstate\n", *argv);
833
834 addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state);
d992f3e6
JP
835 } else if (matches(*argv, "numtxqueues") == 0) {
836 NEXT_ARG();
837 if (numtxqueues != -1)
838 duparg("numtxqueues", *argv);
839 if (get_integer(&numtxqueues, *argv, 0))
bb6ab47b
SH
840 invarg("Invalid \"numtxqueues\" value\n",
841 *argv);
d992f3e6
JP
842 addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES,
843 &numtxqueues, 4);
844 } else if (matches(*argv, "numrxqueues") == 0) {
845 NEXT_ARG();
846 if (numrxqueues != -1)
847 duparg("numrxqueues", *argv);
848 if (get_integer(&numrxqueues, *argv, 0))
bb6ab47b
SH
849 invarg("Invalid \"numrxqueues\" value\n",
850 *argv);
d992f3e6
JP
851 addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES,
852 &numrxqueues, 4);
ff7c2084
JP
853 } else if (matches(*argv, "addrgenmode") == 0) {
854 struct rtattr *afs, *afs6;
855 int mode;
6c5ffb9a 856
ff7c2084
JP
857 NEXT_ARG();
858 mode = get_addr_gen_mode(*argv);
859 if (mode < 0)
bb6ab47b
SH
860 invarg("Invalid address generation mode\n",
861 *argv);
ff7c2084
JP
862 afs = addattr_nest(&req->n, sizeof(*req), IFLA_AF_SPEC);
863 afs6 = addattr_nest(&req->n, sizeof(*req), AF_INET6);
ef0a738c
SH
864 addattr8(&req->n, sizeof(*req),
865 IFLA_INET6_ADDR_GEN_MODE, mode);
ff7c2084
JP
866 addattr_nest_end(&req->n, afs6);
867 addattr_nest_end(&req->n, afs);
974ef93b
ND
868 } else if (matches(*argv, "link-netns") == 0) {
869 NEXT_ARG();
870 if (link_netnsid != -1)
871 duparg("link-netns/link-netnsid", *argv);
872 link_netnsid = get_netnsid_from_name(*argv);
873 /* No nsid? Try to assign one. */
874 if (link_netnsid < 0)
875 set_netnsid_from_name(*argv, -1);
876 link_netnsid = get_netnsid_from_name(*argv);
877 if (link_netnsid < 0)
878 invarg("Invalid \"link-netns\" value\n",
879 *argv);
880 addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID,
881 link_netnsid);
ccdcbf35
ND
882 } else if (matches(*argv, "link-netnsid") == 0) {
883 NEXT_ARG();
884 if (link_netnsid != -1)
974ef93b 885 duparg("link-netns/link-netnsid", *argv);
ccdcbf35 886 if (get_integer(&link_netnsid, *argv, 0))
bb6ab47b
SH
887 invarg("Invalid \"link-netnsid\" value\n",
888 *argv);
ccdcbf35
ND
889 addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID,
890 link_netnsid);
18864827
AK
891 } else if (strcmp(*argv, "protodown") == 0) {
892 unsigned int proto_down;
893
894 NEXT_ARG();
895 if (strcmp(*argv, "on") == 0)
896 proto_down = 1;
897 else if (strcmp(*argv, "off") == 0)
898 proto_down = 0;
899 else
900 return on_off("protodown", *argv);
901 addattr8(&req->n, sizeof(*req), IFLA_PROTO_DOWN,
902 proto_down);
c2db423f
SH
903 } else if (strcmp(*argv, "gso_max_size") == 0) {
904 unsigned int max_size;
905
906 NEXT_ARG();
051274b4 907 if (get_unsigned(&max_size, *argv, 0) ||
08f9d166 908 max_size > GSO_MAX_SIZE)
c2db423f
SH
909 invarg("Invalid \"gso_max_size\" value\n",
910 *argv);
08f9d166
SH
911 addattr32(&req->n, sizeof(*req),
912 IFLA_GSO_MAX_SIZE, max_size);
c2db423f
SH
913 } else if (strcmp(*argv, "gso_max_segs") == 0) {
914 unsigned int max_segs;
915
916 NEXT_ARG();
08f9d166
SH
917 if (get_unsigned(&max_segs, *argv, 0) ||
918 max_segs > GSO_MAX_SEGS)
c2db423f
SH
919 invarg("Invalid \"gso_max_segs\" value\n",
920 *argv);
08f9d166
SH
921 addattr32(&req->n, sizeof(*req),
922 IFLA_GSO_MAX_SEGS, max_segs);
1d934839 923 } else {
05325552
PM
924 if (matches(*argv, "help") == 0)
925 usage();
940a96e6
PS
926
927 if (strcmp(*argv, "dev") == 0)
928 NEXT_ARG();
c58213f6 929 if (dev != name)
1d934839 930 duparg2("dev", *argv);
625df645
PS
931 if (check_ifname(*argv))
932 invarg("\"dev\" not a valid ifname", *argv);
c58213f6 933 dev = *argv;
1d934839
PM
934 }
935 argc--; argv++;
936 }
937
c58213f6
SP
938 ret -= argc;
939
a24315ba 940 /* Allow "ip link add dev" and "ip link add name" */
c58213f6
SP
941 if (!name)
942 name = dev;
943 else if (!dev)
944 dev = name;
945 else if (!strcmp(name, dev))
946 name = dev;
a24315ba 947
65083b5f
SH
948 if (dev && addr_len) {
949 int halen = nl_get_ll_addr_len(dev);
ef0a738c 950
8fe58d58
PS
951 if (halen >= 0 && halen != addr_len) {
952 fprintf(stderr,
ef0a738c
SH
953 "Invalid address length %d - must be %d bytes\n",
954 addr_len, halen);
8fe58d58
PS
955 return -1;
956 }
957 }
958
c58213f6 959 if (!(req->n.nlmsg_flags & NLM_F_CREATE) && index) {
b06a2960
SP
960 fprintf(stderr,
961 "index can be used only when creating devices.\n");
962 exit(-1);
963 }
964
db02608b 965 if (group != -1) {
c58213f6 966 if (!dev) {
db02608b 967 if (argc) {
6773bcc2
SH
968 fprintf(stderr,
969 "Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
970 *argv);
c58213f6 971 exit(-1);
db02608b 972 }
c58213f6 973 if (req->n.nlmsg_flags & NLM_F_CREATE) {
bb6ab47b
SH
974 fprintf(stderr,
975 "group cannot be used when creating devices.\n");
c58213f6 976 exit(-1);
db02608b
VD
977 }
978
c58213f6
SP
979 *type = NULL;
980 return ret;
db02608b
VD
981 }
982 }
983
c58213f6 984 if (!(req->n.nlmsg_flags & NLM_F_CREATE)) {
1d934839 985 if (!dev) {
bb6ab47b
SH
986 fprintf(stderr,
987 "Not enough information: \"dev\" argument is required.\n");
1d934839
PM
988 exit(-1);
989 }
990
c58213f6
SP
991 req->i.ifi_index = ll_name_to_index(dev);
992 if (!req->i.ifi_index)
fe99adbc 993 return nodev(dev);
a24315ba
SP
994
995 /* Not renaming to the same name */
996 if (name == dev)
997 name = NULL;
1d934839 998 } else {
a24315ba
SP
999 if (name != dev) {
1000 fprintf(stderr,
1001 "both \"name\" and \"dev\" cannot be used when creating devices.\n");
1002 exit(-1);
1003 }
1d934839
PM
1004
1005 if (link) {
1006 int ifindex;
1007
1008 ifindex = ll_name_to_index(link);
fe99adbc
SP
1009 if (!ifindex)
1010 return nodev(link);
c58213f6 1011 addattr32(&req->n, sizeof(*req), IFLA_LINK, ifindex);
1d934839 1012 }
5e25cf77 1013
c58213f6 1014 req->i.ifi_index = index;
1d934839
PM
1015 }
1016
1017 if (name) {
c58213f6 1018 addattr_l(&req->n, sizeof(*req),
625df645 1019 IFLA_IFNAME, name, strlen(name) + 1);
1d934839
PM
1020 }
1021
c58213f6
SP
1022 return ret;
1023}
1024
1025static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
1026{
1027 char *type = NULL;
1028 struct iplink_req req = {
1029 .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
1030 .n.nlmsg_flags = NLM_F_REQUEST | flags,
1031 .n.nlmsg_type = cmd,
1032 .i.ifi_family = preferred_family,
1033 };
1034 int ret;
1035
1036 ret = iplink_parse(argc, argv, &req, &type);
1037 if (ret < 0)
1038 return ret;
1039
09fa3279 1040 if (type) {
c58213f6 1041 struct link_util *lu;
a1e2e5fc 1042 struct rtattr *linkinfo;
22a84711 1043 char *ulinep = strchr(type, '_');
620ddeda
NA
1044 int iflatype;
1045
a1e2e5fc 1046 linkinfo = addattr_nest(&req.n, sizeof(req), IFLA_LINKINFO);
09fa3279
SH
1047 addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type,
1048 strlen(type));
1049
22a84711
HL
1050 lu = get_link_kind(type);
1051 if (ulinep && !strcmp(ulinep, "_slave"))
620ddeda 1052 iflatype = IFLA_INFO_SLAVE_DATA;
22a84711 1053 else
620ddeda 1054 iflatype = IFLA_INFO_DATA;
c58213f6
SP
1055
1056 argc -= ret;
1057 argv += ret;
1058
09fa3279 1059 if (lu && argc) {
c14f9d92
SP
1060 struct rtattr *data;
1061
1062 data = addattr_nest(&req.n, sizeof(req), iflatype);
09fa3279
SH
1063
1064 if (lu->parse_opt &&
1065 lu->parse_opt(lu, argc, argv, &req.n))
1066 return -1;
1067
a1e2e5fc 1068 addattr_nest_end(&req.n, data);
09fa3279
SH
1069 } else if (argc) {
1070 if (matches(*argv, "help") == 0)
1071 usage();
6773bcc2
SH
1072 fprintf(stderr,
1073 "Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
1074 *argv);
09fa3279
SH
1075 return -1;
1076 }
a1e2e5fc 1077 addattr_nest_end(&req.n, linkinfo);
09fa3279 1078 } else if (flags & NLM_F_CREATE) {
bb6ab47b
SH
1079 fprintf(stderr,
1080 "Not enough information: \"type\" argument is required\n");
09fa3279
SH
1081 return -1;
1082 }
1083
86bf43c7 1084 if (rtnl_talk(&rth, &req.n, NULL) < 0)
f921f567 1085 return -2;
1d934839
PM
1086
1087 return 0;
1088}
1089
50b9950d
RP
1090int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
1091{
d17b136f
PS
1092 struct iplink_req req = {
1093 .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
1094 .n.nlmsg_flags = NLM_F_REQUEST | flags,
1095 .n.nlmsg_type = RTM_GETLINK,
1096 .i.ifi_family = preferred_family,
1097 };
86bf43c7 1098 struct nlmsghdr *answer;
50b9950d 1099
50b9950d 1100 if (name) {
625df645
PS
1101 addattr_l(&req.n, sizeof(req),
1102 IFLA_IFNAME, name, strlen(name) + 1);
50b9950d
RP
1103 }
1104 addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask);
1105
86bf43c7 1106 if (rtnl_talk(&rth, &req.n, &answer) < 0)
50b9950d
RP
1107 return -2;
1108
e4a1216a 1109 open_json_object(NULL);
c956e9a9 1110 print_linkinfo(NULL, answer, stdout);
e4a1216a 1111 close_json_object();
50b9950d 1112
86bf43c7 1113 free(answer);
50b9950d
RP
1114 return 0;
1115}
1116
1d934839 1117#if IPLINK_IOCTL_COMPAT
aba5acdf
SH
1118static int get_ctl_fd(void)
1119{
1120 int s_errno;
1121 int fd;
1122
1123 fd = socket(PF_INET, SOCK_DGRAM, 0);
1124 if (fd >= 0)
1125 return fd;
1126 s_errno = errno;
1127 fd = socket(PF_PACKET, SOCK_DGRAM, 0);
1128 if (fd >= 0)
1129 return fd;
1130 fd = socket(PF_INET6, SOCK_DGRAM, 0);
1131 if (fd >= 0)
1132 return fd;
1133 errno = s_errno;
1134 perror("Cannot create control socket");
1135 return -1;
1136}
1137
71058eb8 1138static int do_chflags(const char *dev, __u32 flags, __u32 mask)
aba5acdf
SH
1139{
1140 struct ifreq ifr;
1141 int fd;
1142 int err;
1143
fc9d755a 1144 strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
aba5acdf
SH
1145 fd = get_ctl_fd();
1146 if (fd < 0)
1147 return -1;
1148 err = ioctl(fd, SIOCGIFFLAGS, &ifr);
1149 if (err) {
1150 perror("SIOCGIFFLAGS");
1151 close(fd);
1152 return -1;
1153 }
1154 if ((ifr.ifr_flags^flags)&mask) {
1155 ifr.ifr_flags &= ~mask;
1156 ifr.ifr_flags |= mask&flags;
1157 err = ioctl(fd, SIOCSIFFLAGS, &ifr);
1158 if (err)
1159 perror("SIOCSIFFLAGS");
1160 }
1161 close(fd);
1162 return err;
1163}
1164
71058eb8 1165static int do_changename(const char *dev, const char *newdev)
aba5acdf
SH
1166{
1167 struct ifreq ifr;
1168 int fd;
1169 int err;
1170
fc9d755a
SH
1171 strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
1172 strlcpy(ifr.ifr_newname, newdev, IFNAMSIZ);
aba5acdf
SH
1173 fd = get_ctl_fd();
1174 if (fd < 0)
1175 return -1;
1176 err = ioctl(fd, SIOCSIFNAME, &ifr);
1177 if (err) {
1178 perror("SIOCSIFNAME");
1179 close(fd);
1180 return -1;
1181 }
1182 close(fd);
1183 return err;
1184}
1185
71058eb8 1186static int set_qlen(const char *dev, int qlen)
aba5acdf 1187{
d17b136f 1188 struct ifreq ifr = { .ifr_qlen = qlen };
aba5acdf
SH
1189 int s;
1190
1191 s = get_ctl_fd();
1192 if (s < 0)
1193 return -1;
1194
fc9d755a 1195 strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
aba5acdf
SH
1196 if (ioctl(s, SIOCSIFTXQLEN, &ifr) < 0) {
1197 perror("SIOCSIFXQLEN");
1198 close(s);
1199 return -1;
1200 }
1201 close(s);
1202
ae665a52 1203 return 0;
aba5acdf
SH
1204}
1205
71058eb8 1206static int set_mtu(const char *dev, int mtu)
aba5acdf 1207{
d17b136f 1208 struct ifreq ifr = { .ifr_mtu = mtu };
aba5acdf
SH
1209 int s;
1210
1211 s = get_ctl_fd();
1212 if (s < 0)
1213 return -1;
1214
fc9d755a 1215 strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
aba5acdf
SH
1216 if (ioctl(s, SIOCSIFMTU, &ifr) < 0) {
1217 perror("SIOCSIFMTU");
1218 close(s);
1219 return -1;
1220 }
1221 close(s);
1222
ae665a52 1223 return 0;
aba5acdf
SH
1224}
1225
71058eb8 1226static int get_address(const char *dev, int *htype)
aba5acdf 1227{
d17b136f
PS
1228 struct ifreq ifr = {};
1229 struct sockaddr_ll me = {
1230 .sll_family = AF_PACKET,
1231 .sll_protocol = htons(ETH_P_LOOP),
1232 };
f332d169 1233 socklen_t alen;
aba5acdf
SH
1234 int s;
1235
1236 s = socket(PF_PACKET, SOCK_DGRAM, 0);
ae665a52 1237 if (s < 0) {
aba5acdf
SH
1238 perror("socket(PF_PACKET)");
1239 return -1;
1240 }
1241
fc9d755a 1242 strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
aba5acdf
SH
1243 if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
1244 perror("SIOCGIFINDEX");
1245 close(s);
1246 return -1;
1247 }
1248
aba5acdf 1249 me.sll_ifindex = ifr.ifr_ifindex;
6c5ffb9a 1250 if (bind(s, (struct sockaddr *)&me, sizeof(me)) == -1) {
aba5acdf
SH
1251 perror("bind");
1252 close(s);
1253 return -1;
1254 }
1255
1256 alen = sizeof(me);
6c5ffb9a 1257 if (getsockname(s, (struct sockaddr *)&me, &alen) == -1) {
aba5acdf
SH
1258 perror("getsockname");
1259 close(s);
1260 return -1;
1261 }
1262 close(s);
1263 *htype = me.sll_hatype;
1264 return me.sll_halen;
1265}
1266
ae665a52 1267static int parse_address(const char *dev, int hatype, int halen,
7b565754 1268 char *lla, struct ifreq *ifr)
aba5acdf
SH
1269{
1270 int alen;
1271
1272 memset(ifr, 0, sizeof(*ifr));
fc9d755a 1273 strlcpy(ifr->ifr_name, dev, IFNAMSIZ);
aba5acdf
SH
1274 ifr->ifr_hwaddr.sa_family = hatype;
1275 alen = ll_addr_a2n(ifr->ifr_hwaddr.sa_data, 14, lla);
1276 if (alen < 0)
1277 return -1;
1278 if (alen != halen) {
bb6ab47b
SH
1279 fprintf(stderr,
1280 "Wrong address (%s) length: expected %d bytes\n",
ef0a738c 1281 lla, halen);
aba5acdf
SH
1282 return -1;
1283 }
ae665a52 1284 return 0;
aba5acdf
SH
1285}
1286
1287static int set_address(struct ifreq *ifr, int brd)
1288{
1289 int s;
1290
1291 s = get_ctl_fd();
1292 if (s < 0)
1293 return -1;
1294 if (ioctl(s, brd?SIOCSIFHWBROADCAST:SIOCSIFHWADDR, ifr) < 0) {
1295 perror(brd?"SIOCSIFHWBROADCAST":"SIOCSIFHWADDR");
1296 close(s);
1297 return -1;
1298 }
1299 close(s);
ae665a52 1300 return 0;
aba5acdf
SH
1301}
1302
aba5acdf
SH
1303static int do_set(int argc, char **argv)
1304{
1305 char *dev = NULL;
1306 __u32 mask = 0;
1307 __u32 flags = 0;
1308 int qlen = -1;
1309 int mtu = -1;
1310 char *newaddr = NULL;
1311 char *newbrd = NULL;
1312 struct ifreq ifr0, ifr1;
1313 char *newname = NULL;
1314 int htype, halen;
1315
1316 while (argc > 0) {
1317 if (strcmp(*argv, "up") == 0) {
1318 mask |= IFF_UP;
1319 flags |= IFF_UP;
1320 } else if (strcmp(*argv, "down") == 0) {
1321 mask |= IFF_UP;
1322 flags &= ~IFF_UP;
1323 } else if (strcmp(*argv, "name") == 0) {
1324 NEXT_ARG();
625df645
PS
1325 if (check_ifname(*argv))
1326 invarg("\"name\" not a valid ifname", *argv);
aba5acdf
SH
1327 newname = *argv;
1328 } else if (matches(*argv, "address") == 0) {
1329 NEXT_ARG();
1330 newaddr = *argv;
1331 } else if (matches(*argv, "broadcast") == 0 ||
1332 strcmp(*argv, "brd") == 0) {
1333 NEXT_ARG();
1334 newbrd = *argv;
1335 } else if (matches(*argv, "txqueuelen") == 0 ||
1336 strcmp(*argv, "qlen") == 0 ||
1337 matches(*argv, "txqlen") == 0) {
1338 NEXT_ARG();
1339 if (qlen != -1)
1340 duparg("txqueuelen", *argv);
1341 if (get_integer(&qlen, *argv, 0))
1342 invarg("Invalid \"txqueuelen\" value\n", *argv);
1343 } else if (strcmp(*argv, "mtu") == 0) {
1344 NEXT_ARG();
1345 if (mtu != -1)
1346 duparg("mtu", *argv);
1347 if (get_integer(&mtu, *argv, 0))
1348 invarg("Invalid \"mtu\" value\n", *argv);
1349 } else if (strcmp(*argv, "multicast") == 0) {
1350 NEXT_ARG();
1351 mask |= IFF_MULTICAST;
6c5ffb9a
SH
1352
1353 if (strcmp(*argv, "on") == 0)
aba5acdf 1354 flags |= IFF_MULTICAST;
6c5ffb9a 1355 else if (strcmp(*argv, "off") == 0)
aba5acdf 1356 flags &= ~IFF_MULTICAST;
6c5ffb9a 1357 else
14645ec2 1358 return on_off("multicast", *argv);
d27b1b5b 1359 } else if (strcmp(*argv, "allmulticast") == 0) {
1360 NEXT_ARG();
1361 mask |= IFF_ALLMULTI;
6c5ffb9a
SH
1362
1363 if (strcmp(*argv, "on") == 0)
d27b1b5b 1364 flags |= IFF_ALLMULTI;
6c5ffb9a 1365 else if (strcmp(*argv, "off") == 0)
d27b1b5b 1366 flags &= ~IFF_ALLMULTI;
6c5ffb9a 1367 else
14645ec2 1368 return on_off("allmulticast", *argv);
d27b1b5b 1369 } else if (strcmp(*argv, "promisc") == 0) {
1370 NEXT_ARG();
1371 mask |= IFF_PROMISC;
6c5ffb9a
SH
1372
1373 if (strcmp(*argv, "on") == 0)
d27b1b5b 1374 flags |= IFF_PROMISC;
6c5ffb9a 1375 else if (strcmp(*argv, "off") == 0)
d27b1b5b 1376 flags &= ~IFF_PROMISC;
6c5ffb9a 1377 else
14645ec2 1378 return on_off("promisc", *argv);
d27b1b5b 1379 } else if (strcmp(*argv, "trailers") == 0) {
1380 NEXT_ARG();
1381 mask |= IFF_NOTRAILERS;
6c5ffb9a
SH
1382
1383 if (strcmp(*argv, "off") == 0)
d27b1b5b 1384 flags |= IFF_NOTRAILERS;
6c5ffb9a 1385 else if (strcmp(*argv, "on") == 0)
d27b1b5b 1386 flags &= ~IFF_NOTRAILERS;
6c5ffb9a 1387 else
14645ec2 1388 return on_off("trailers", *argv);
aba5acdf
SH
1389 } else if (strcmp(*argv, "arp") == 0) {
1390 NEXT_ARG();
1391 mask |= IFF_NOARP;
6c5ffb9a
SH
1392
1393 if (strcmp(*argv, "on") == 0)
aba5acdf 1394 flags &= ~IFF_NOARP;
6c5ffb9a 1395 else if (strcmp(*argv, "off") == 0)
aba5acdf 1396 flags |= IFF_NOARP;
6c5ffb9a 1397 else
ff1e35ed 1398 return on_off("arp", *argv);
aba5acdf
SH
1399 } else if (matches(*argv, "dynamic") == 0) {
1400 NEXT_ARG();
1401 mask |= IFF_DYNAMIC;
6c5ffb9a
SH
1402
1403 if (strcmp(*argv, "on") == 0)
aba5acdf 1404 flags |= IFF_DYNAMIC;
6c5ffb9a 1405 else if (strcmp(*argv, "off") == 0)
aba5acdf 1406 flags &= ~IFF_DYNAMIC;
6c5ffb9a 1407 else
14645ec2 1408 return on_off("dynamic", *argv);
aba5acdf 1409 } else {
6c5ffb9a 1410 if (strcmp(*argv, "dev") == 0)
aba5acdf 1411 NEXT_ARG();
8aacb9bb 1412 else if (matches(*argv, "help") == 0)
aba5acdf 1413 usage();
6c5ffb9a 1414
aba5acdf
SH
1415 if (dev)
1416 duparg2("dev", *argv);
625df645
PS
1417 if (check_ifname(*argv))
1418 invarg("\"dev\" not a valid ifname", *argv);
aba5acdf
SH
1419 dev = *argv;
1420 }
1421 argc--; argv++;
1422 }
1423
1424 if (!dev) {
ef0a738c
SH
1425 fprintf(stderr,
1426 "Not enough of information: \"dev\" argument is required.\n");
aba5acdf
SH
1427 exit(-1);
1428 }
1429
1430 if (newaddr || newbrd) {
1431 halen = get_address(dev, &htype);
1432 if (halen < 0)
1433 return -1;
1434 if (newaddr) {
bb6ab47b
SH
1435 if (parse_address(dev, htype, halen,
1436 newaddr, &ifr0) < 0)
aba5acdf
SH
1437 return -1;
1438 }
1439 if (newbrd) {
bb6ab47b
SH
1440 if (parse_address(dev, htype, halen,
1441 newbrd, &ifr1) < 0)
ae665a52 1442 return -1;
aba5acdf
SH
1443 }
1444 }
1445
1446 if (newname && strcmp(dev, newname)) {
1447 if (do_changename(dev, newname) < 0)
1448 return -1;
1449 dev = newname;
1450 }
ae665a52 1451 if (qlen != -1) {
aba5acdf 1452 if (set_qlen(dev, qlen) < 0)
ae665a52 1453 return -1;
aba5acdf 1454 }
ae665a52 1455 if (mtu != -1) {
aba5acdf 1456 if (set_mtu(dev, mtu) < 0)
ae665a52 1457 return -1;
aba5acdf
SH
1458 }
1459 if (newaddr || newbrd) {
1460 if (newbrd) {
1461 if (set_address(&ifr1, 1) < 0)
ae665a52 1462 return -1;
aba5acdf
SH
1463 }
1464 if (newaddr) {
1465 if (set_address(&ifr0, 0) < 0)
1466 return -1;
1467 }
1468 }
1469 if (mask)
1470 return do_chflags(dev, flags, mask);
1471 return 0;
1472}
1d934839 1473#endif /* IPLINK_IOCTL_COMPAT */
aba5acdf 1474
837552b4
RS
1475static void print_mpls_stats(FILE *fp, struct rtattr *attr)
1476{
1477 struct rtattr *mrtb[MPLS_STATS_MAX+1];
1478 struct mpls_link_stats *stats;
1479
1480 parse_rtattr(mrtb, MPLS_STATS_MAX, RTA_DATA(attr),
1481 RTA_PAYLOAD(attr));
1482 if (!mrtb[MPLS_STATS_LINK])
1483 return;
1484
1485 stats = RTA_DATA(mrtb[MPLS_STATS_LINK]);
1486
1487 fprintf(fp, " mpls:\n");
1488 fprintf(fp, " RX: bytes packets errors dropped noroute\n");
1489 fprintf(fp, " ");
1490 print_num(fp, 10, stats->rx_bytes);
1491 print_num(fp, 8, stats->rx_packets);
1492 print_num(fp, 7, stats->rx_errors);
1493 print_num(fp, 8, stats->rx_dropped);
1494 print_num(fp, 7, stats->rx_noroute);
1495 fprintf(fp, "\n");
1496 fprintf(fp, " TX: bytes packets errors dropped\n");
1497 fprintf(fp, " ");
1498 print_num(fp, 10, stats->tx_bytes);
1499 print_num(fp, 8, stats->tx_packets);
1500 print_num(fp, 7, stats->tx_errors);
1501 print_num(fp, 7, stats->tx_dropped);
1502 fprintf(fp, "\n");
1503}
1504
1505static void print_af_stats_attr(FILE *fp, int ifindex, struct rtattr *attr)
1506{
1507 bool if_printed = false;
1508 struct rtattr *i;
1509 int rem;
1510
1511 rem = RTA_PAYLOAD(attr);
1512 for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
1513 if (preferred_family != AF_UNSPEC &&
1514 i->rta_type != preferred_family)
1515 continue;
1516
1517 if (!if_printed) {
1518 fprintf(fp, "%u: %s\n", ifindex,
1519 ll_index_to_name(ifindex));
1520 if_printed = true;
1521 }
1522
1523 switch (i->rta_type) {
1524 case AF_MPLS:
1525 print_mpls_stats(fp, i);
1526 break;
1527 default:
1528 fprintf(fp, " unknown af(%d)\n", i->rta_type);
1529 break;
1530 }
1531 }
1532}
1533
1534struct af_stats_ctx {
1535 FILE *fp;
1536 int ifindex;
1537};
1538
1539static int print_af_stats(const struct sockaddr_nl *who,
1540 struct nlmsghdr *n,
1541 void *arg)
1542{
1543 struct if_stats_msg *ifsm = NLMSG_DATA(n);
1544 struct rtattr *tb[IFLA_STATS_MAX+1];
1545 int len = n->nlmsg_len;
1546 struct af_stats_ctx *ctx = arg;
1547 FILE *fp = ctx->fp;
1548
1549 len -= NLMSG_LENGTH(sizeof(*ifsm));
1550 if (len < 0) {
1551 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
1552 return -1;
1553 }
1554
1555 if (ctx->ifindex && ifsm->ifindex != ctx->ifindex)
1556 return 0;
1557
1558 parse_rtattr(tb, IFLA_STATS_MAX, IFLA_STATS_RTA(ifsm), len);
1559
1560 if (tb[IFLA_STATS_AF_SPEC])
1561 print_af_stats_attr(fp, ifsm->ifindex, tb[IFLA_STATS_AF_SPEC]);
1562
1563 fflush(fp);
1564 return 0;
1565}
1566
1567static int iplink_afstats(int argc, char **argv)
1568{
1569 __u32 filt_mask = IFLA_STATS_FILTER_BIT(IFLA_STATS_AF_SPEC);
1570 const char *filter_dev = NULL;
1571 struct af_stats_ctx ctx = {
1572 .fp = stdout,
1573 .ifindex = 0,
1574 };
1575
1576 while (argc > 0) {
1577 if (strcmp(*argv, "dev") == 0) {
1578 NEXT_ARG();
1579 if (filter_dev)
1580 duparg2("dev", *argv);
1581 filter_dev = *argv;
1582 } else if (matches(*argv, "help") == 0) {
1583 usage();
1584 } else {
1585 fprintf(stderr,
1586 "Command \"%s\" is unknown, try \"ip link help\".\n",
1587 *argv);
1588 exit(-1);
1589 }
1590
1591 argv++; argc--;
1592 }
1593
1594 if (filter_dev) {
1595 ctx.ifindex = ll_name_to_index(filter_dev);
1596 if (ctx.ifindex <= 0) {
1597 fprintf(stderr,
1598 "Device \"%s\" does not exist.\n",
1599 filter_dev);
1600 return -1;
1601 }
1602 }
1603
56eeeda9 1604 if (rtnl_statsdump_req_filter(&rth, AF_UNSPEC, filt_mask) < 0) {
837552b4
RS
1605 perror("Cannont send dump request");
1606 return 1;
1607 }
1608
1609 if (rtnl_dump_filter(&rth, print_af_stats, &ctx) < 0) {
1610 fprintf(stderr, "Dump terminated\n");
1611 return 1;
1612 }
1613
1614 return 0;
1615}
1616
561e650e 1617static void do_help(int argc, char **argv)
1618{
1619 struct link_util *lu = NULL;
1620
1621 if (argc <= 0) {
1622 usage();
6c5ffb9a 1623 return;
561e650e 1624 }
1625
1626 lu = get_link_kind(*argv);
561e650e 1627 if (lu && lu->print_help)
1628 lu->print_help(lu, argc-1, argv+1, stdout);
1629 else
1630 usage();
1631}
1632
aba5acdf
SH
1633int do_iplink(int argc, char **argv)
1634{
6843d36e
ZS
1635 if (argc < 1)
1636 return ipaddr_list_link(0, NULL);
1637
1638 if (iplink_have_newlink()) {
1639 if (matches(*argv, "add") == 0)
1640 return iplink_modify(RTM_NEWLINK,
6c5ffb9a
SH
1641 NLM_F_CREATE|NLM_F_EXCL,
1642 argc-1, argv+1);
6843d36e 1643 if (matches(*argv, "set") == 0 ||
6c5ffb9a 1644 matches(*argv, "change") == 0)
6843d36e 1645 return iplink_modify(RTM_NEWLINK, 0,
6c5ffb9a 1646 argc-1, argv+1);
6843d36e
ZS
1647 if (matches(*argv, "replace") == 0)
1648 return iplink_modify(RTM_NEWLINK,
6c5ffb9a
SH
1649 NLM_F_CREATE|NLM_F_REPLACE,
1650 argc-1, argv+1);
6843d36e
ZS
1651 if (matches(*argv, "delete") == 0)
1652 return iplink_modify(RTM_DELLINK, 0,
6c5ffb9a 1653 argc-1, argv+1);
6843d36e 1654 } else {
1d934839 1655#if IPLINK_IOCTL_COMPAT
6843d36e
ZS
1656 if (matches(*argv, "set") == 0)
1657 return do_set(argc-1, argv+1);
1d934839 1658#endif
6843d36e 1659 }
6c5ffb9a 1660
6843d36e 1661 if (matches(*argv, "show") == 0 ||
6c5ffb9a
SH
1662 matches(*argv, "lst") == 0 ||
1663 matches(*argv, "list") == 0)
6843d36e 1664 return ipaddr_list_link(argc-1, argv+1);
6c5ffb9a 1665
94f1a22a
NA
1666 if (matches(*argv, "xstats") == 0)
1667 return iplink_ifla_xstats(argc-1, argv+1);
1668
837552b4
RS
1669 if (matches(*argv, "afstats") == 0) {
1670 iplink_afstats(argc-1, argv+1);
1671 return 0;
1672 }
1673
6843d36e
ZS
1674 if (matches(*argv, "help") == 0) {
1675 do_help(argc-1, argv+1);
1676 return 0;
1677 }
aba5acdf 1678
6843d36e 1679 fprintf(stderr, "Command \"%s\" is unknown, try \"ip link help\".\n",
6c5ffb9a 1680 *argv);
aba5acdf
SH
1681 exit(-1);
1682}