21 #include <netlink-local.h>
22 #include <netlink/netlink.h>
23 #include <netlink/attr.h>
24 #include <netlink/utils.h>
25 #include <netlink/object.h>
26 #include <netlink/route/rtnl.h>
27 #include <netlink/route/link.h>
28 #include <netlink/route/link/api.h>
31 #define LINK_ATTR_MTU (1 << 0)
32 #define LINK_ATTR_LINK (1 << 1)
33 #define LINK_ATTR_TXQLEN (1 << 2)
34 #define LINK_ATTR_WEIGHT (1 << 3)
35 #define LINK_ATTR_MASTER (1 << 4)
36 #define LINK_ATTR_QDISC (1 << 5)
37 #define LINK_ATTR_MAP (1 << 6)
38 #define LINK_ATTR_ADDR (1 << 7)
39 #define LINK_ATTR_BRD (1 << 8)
40 #define LINK_ATTR_FLAGS (1 << 9)
41 #define LINK_ATTR_IFNAME (1 << 10)
42 #define LINK_ATTR_IFINDEX (1 << 11)
43 #define LINK_ATTR_FAMILY (1 << 12)
44 #define LINK_ATTR_ARPTYPE (1 << 13)
45 #define LINK_ATTR_STATS (1 << 14)
46 #define LINK_ATTR_CHANGE (1 << 15)
47 #define LINK_ATTR_OPERSTATE (1 << 16)
48 #define LINK_ATTR_LINKMODE (1 << 17)
49 #define LINK_ATTR_LINKINFO (1 << 18)
50 #define LINK_ATTR_IFALIAS (1 << 19)
51 #define LINK_ATTR_NUM_VF (1 << 20)
52 #define LINK_ATTR_PROMISCUITY (1 << 21)
53 #define LINK_ATTR_NUM_TX_QUEUES (1 << 22)
54 #define LINK_ATTR_NUM_RX_QUEUES (1 << 23)
55 #define LINK_ATTR_GROUP (1 << 24)
78 void *data,
void *arg)
89 void *data,
void *arg)
101 void *data,
void *arg)
103 struct nl_msg *msg = arg;
104 struct nlattr *af_attr;
113 if ((err = ops->
ao_fill_af(link, arg, data)) < 0)
122 void *data,
void *arg)
133 void *data,
void *arg)
144 void *data,
void *arg)
154 static int do_foreach_af(
struct rtnl_link *link,
161 for (i = 0; i < AF_MAX; i++) {
162 if (link->l_af_data[i]) {
168 if ((err = cb(link, ops, link->l_af_data[i], arg)) < 0)
176 static void release_link_info(
struct rtnl_link *link)
184 link->l_info_ops = NULL;
188 static void link_free_data(
struct nl_object *c)
190 struct rtnl_link *link = nl_object_priv(c);
195 if ((io = link->l_info_ops) != NULL)
196 release_link_info(link);
198 nl_addr_put(link->l_addr);
199 nl_addr_put(link->l_bcast);
201 free(link->l_ifalias);
202 free(link->l_info_kind);
204 do_foreach_af(link, af_free, NULL);
210 struct rtnl_link *dst = nl_object_priv(_dst);
211 struct rtnl_link *src = nl_object_priv(_src);
223 if (!(dst->l_ifalias = strdup(src->l_ifalias)))
226 if (src->l_info_kind)
227 if (!(dst->l_info_kind = strdup(src->l_info_kind)))
230 if (src->l_info_ops && src->l_info_ops->io_clone) {
231 err = src->l_info_ops->io_clone(dst, src);
236 if ((err = do_foreach_af(src, af_clone, dst)) < 0)
242 static struct nla_policy link_policy[IFLA_MAX+1] = {
244 .maxlen = IFNAMSIZ },
245 [IFLA_MTU] = { .type =
NLA_U32 },
246 [IFLA_TXQLEN] = { .type =
NLA_U32 },
247 [IFLA_LINK] = { .type =
NLA_U32 },
248 [IFLA_WEIGHT] = { .type =
NLA_U32 },
249 [IFLA_MASTER] = { .type =
NLA_U32 },
250 [IFLA_OPERSTATE] = { .type =
NLA_U8 },
251 [IFLA_LINKMODE] = { .type =
NLA_U8 },
254 .maxlen = IFQDISCSIZ },
255 [IFLA_STATS] = { .minlen =
sizeof(
struct rtnl_link_stats) },
256 [IFLA_STATS64] = { .minlen =
sizeof(
struct rtnl_link_stats64)},
257 [IFLA_MAP] = { .minlen =
sizeof(
struct rtnl_link_ifmap) },
258 [IFLA_IFALIAS] = { .type =
NLA_STRING, .maxlen = IFALIASZ },
259 [IFLA_NUM_VF] = { .type =
NLA_U32 },
261 [IFLA_PROMISCUITY] = { .type =
NLA_U32 },
262 [IFLA_NUM_TX_QUEUES] = { .type =
NLA_U32 },
263 [IFLA_NUM_RX_QUEUES] = { .type =
NLA_U32 },
264 [IFLA_GROUP] = { .type =
NLA_U32 },
267 static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = {
273 static int link_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
277 struct ifinfomsg *ifi;
278 struct nlattr *tb[IFLA_MAX+1];
288 link->ce_msgtype = n->nlmsg_type;
290 if (!nlmsg_valid_hdr(n,
sizeof(*ifi)))
291 return -NLE_MSG_TOOSHORT;
294 link->l_family = family = ifi->ifi_family;
295 link->l_arptype = ifi->ifi_type;
296 link->l_index = ifi->ifi_index;
297 link->l_flags = ifi->ifi_flags;
298 link->l_change = ifi->ifi_change;
299 link->ce_mask = (LINK_ATTR_IFNAME | LINK_ATTR_FAMILY |
300 LINK_ATTR_ARPTYPE| LINK_ATTR_IFINDEX |
301 LINK_ATTR_FLAGS | LINK_ATTR_CHANGE);
303 if ((af_ops = af_lookup_and_alloc(link, family))) {
305 memcpy(&link_policy[IFLA_PROTINFO],
311 err =
nlmsg_parse(n,
sizeof(*ifi), tb, IFLA_MAX, link_policy);
315 if (tb[IFLA_IFNAME] == NULL) {
316 err = -NLE_MISSING_ATTR;
320 nla_strlcpy(link->l_name, tb[IFLA_IFNAME], IFNAMSIZ);
323 if (tb[IFLA_STATS]) {
324 struct rtnl_link_stats *st =
nla_data(tb[IFLA_STATS]);
353 link->ce_mask |= LINK_ATTR_STATS;
356 if (tb[IFLA_STATS64]) {
364 struct rtnl_link_stats64 st;
367 sizeof(
struct rtnl_link_stats64));
396 link->ce_mask |= LINK_ATTR_STATS;
399 if (tb[IFLA_TXQLEN]) {
401 link->ce_mask |= LINK_ATTR_TXQLEN;
406 link->ce_mask |= LINK_ATTR_MTU;
409 if (tb[IFLA_ADDRESS]) {
411 if (link->l_addr == NULL) {
415 nl_addr_set_family(link->l_addr,
417 link->ce_mask |= LINK_ATTR_ADDR;
420 if (tb[IFLA_BROADCAST]) {
423 if (link->l_bcast == NULL) {
427 nl_addr_set_family(link->l_bcast,
429 link->ce_mask |= LINK_ATTR_BRD;
434 link->ce_mask |= LINK_ATTR_LINK;
437 if (tb[IFLA_WEIGHT]) {
439 link->ce_mask |= LINK_ATTR_WEIGHT;
442 if (tb[IFLA_QDISC]) {
443 nla_strlcpy(link->l_qdisc, tb[IFLA_QDISC], IFQDISCSIZ);
444 link->ce_mask |= LINK_ATTR_QDISC;
449 sizeof(
struct rtnl_link_ifmap));
450 link->ce_mask |= LINK_ATTR_MAP;
453 if (tb[IFLA_MASTER]) {
455 link->ce_mask |= LINK_ATTR_MASTER;
458 if (tb[IFLA_OPERSTATE]) {
459 link->l_operstate =
nla_get_u8(tb[IFLA_OPERSTATE]);
460 link->ce_mask |= LINK_ATTR_OPERSTATE;
463 if (tb[IFLA_LINKMODE]) {
464 link->l_linkmode =
nla_get_u8(tb[IFLA_LINKMODE]);
465 link->ce_mask |= LINK_ATTR_LINKMODE;
468 if (tb[IFLA_IFALIAS]) {
469 link->l_ifalias = nla_strdup(tb[IFLA_IFALIAS]);
470 if (link->l_ifalias == NULL) {
474 link->ce_mask |= LINK_ATTR_IFALIAS;
477 if (tb[IFLA_NUM_VF]) {
479 link->ce_mask |= LINK_ATTR_NUM_VF;
482 if (tb[IFLA_LINKINFO]) {
483 struct nlattr *li[IFLA_INFO_MAX+1];
490 if (li[IFLA_INFO_KIND]) {
494 kind = nla_strdup(li[IFLA_INFO_KIND]);
499 link->l_info_kind = kind;
500 link->ce_mask |= LINK_ATTR_LINKINFO;
503 link->l_info_ops = ops;
507 (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) {
508 err = ops->
io_parse(link, li[IFLA_INFO_DATA],
509 li[IFLA_INFO_XSTATS]);
521 link->l_af_data[link->l_family]);
526 if (tb[IFLA_AF_SPEC]) {
527 struct nlattr *af_attr;
531 af_ops = af_lookup_and_alloc(link,
nla_type(af_attr));
533 char *af_data = link->l_af_data[
nla_type(af_attr)];
546 if (tb[IFLA_PROMISCUITY]) {
547 link->l_promiscuity =
nla_get_u32(tb[IFLA_PROMISCUITY]);
548 link->ce_mask |= LINK_ATTR_PROMISCUITY;
551 if (tb[IFLA_NUM_TX_QUEUES]) {
552 link->l_num_tx_queues =
nla_get_u32(tb[IFLA_NUM_TX_QUEUES]);
553 link->ce_mask |= LINK_ATTR_NUM_TX_QUEUES;
556 if (tb[IFLA_NUM_RX_QUEUES]) {
557 link->l_num_rx_queues =
nla_get_u32(tb[IFLA_NUM_RX_QUEUES]);
558 link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES;
561 if (tb[IFLA_GROUP]) {
563 link->ce_mask |= LINK_ATTR_GROUP;
573 static int link_event_filter(
struct nl_cache *cache,
struct nl_object *obj)
580 if (link->l_family == AF_BRIDGE)
586 static int link_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
588 int family = cache->c_iarg1;
596 struct nl_cache *cache = dp_cache(obj);
599 nl_dump_line(p,
"%s %s ", link->l_name,
600 nl_llproto2str(link->l_arptype, buf,
sizeof(buf)));
605 if (link->ce_mask & LINK_ATTR_MASTER) {
607 nl_dump(p,
"master %s ", master ? master->l_name :
"inv");
612 rtnl_link_flags2str(link->l_flags, buf,
sizeof(buf));
616 if (link->ce_mask & LINK_ATTR_LINK) {
618 nl_dump(p,
"slave-of %s ", ll ? ll->l_name :
"NONE");
623 if (link->ce_mask & LINK_ATTR_GROUP)
624 nl_dump(p,
"group %u ", link->l_group);
626 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_LINE])
629 do_foreach_af(link, af_dump_line, p);
639 link_dump_line(obj, p);
641 nl_dump_line(p,
" mtu %u ", link->l_mtu);
642 nl_dump(p,
"txqlen %u weight %u ", link->l_txqlen, link->l_weight);
644 if (link->ce_mask & LINK_ATTR_QDISC)
645 nl_dump(p,
"qdisc %s ", link->l_qdisc);
647 if (link->ce_mask & LINK_ATTR_MAP && link->l_map.lm_irq)
648 nl_dump(p,
"irq %u ", link->l_map.lm_irq);
650 if (link->ce_mask & LINK_ATTR_IFINDEX)
651 nl_dump(p,
"index %u ", link->l_index);
653 if (link->ce_mask & LINK_ATTR_PROMISCUITY && link->l_promiscuity > 0)
654 nl_dump(p,
"promisc-mode (%u users) ", link->l_promiscuity);
658 if (link->ce_mask & LINK_ATTR_IFALIAS)
659 nl_dump_line(p,
" alias %s\n", link->l_ifalias);
661 nl_dump_line(p,
" ");
663 if (link->ce_mask & LINK_ATTR_NUM_TX_QUEUES)
664 nl_dump(p,
"txq %u ", link->l_num_tx_queues);
666 if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES)
667 nl_dump(p,
"rxq %u ", link->l_num_rx_queues);
669 if (link->ce_mask & LINK_ATTR_BRD)
673 if ((link->ce_mask & LINK_ATTR_OPERSTATE) &&
674 link->l_operstate != IF_OPER_UNKNOWN) {
675 rtnl_link_operstate2str(link->l_operstate, buf,
sizeof(buf));
679 if (link->ce_mask & LINK_ATTR_NUM_VF)
680 nl_dump(p,
"num-vf %u ", link->l_num_vf);
683 rtnl_link_mode2str(link->l_linkmode, buf,
sizeof(buf)));
688 do_foreach_af(link, af_dump_details, p);
697 link_dump_details(obj, p);
699 nl_dump_line(p,
" Stats: bytes packets errors "
700 " dropped fifo-err compressed\n");
704 strcpy(fmt,
" RX %X.2f %s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n");
705 fmt[9] = *unit ==
'B' ?
'9' :
'7';
707 nl_dump_line(p, fmt, res, unit,
716 strcpy(fmt,
" TX %X.2f %s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n");
717 fmt[9] = *unit ==
'B' ?
'9' :
'7';
719 nl_dump_line(p, fmt, res, unit,
726 nl_dump_line(p,
" Errors: length over crc "
727 " frame missed multicast\n");
729 nl_dump_line(p,
" RX %10" PRIu64
" %10" PRIu64
" %10"
730 PRIu64
" %10" PRIu64
" %10" PRIu64
" %10"
739 nl_dump_line(p,
" aborted carrier heartbeat "
740 " window collision\n");
742 nl_dump_line(p,
" TX %10" PRIu64
" %10" PRIu64
" %10"
743 PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
750 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_STATS])
753 do_foreach_af(link, af_dump_stats, p);
757 static int link_handle_event(
struct nl_object *a,
struct rtnl_link_event_cb *cb)
760 struct nl_cache *c = dp_cache(a);
763 if (l->l_change == ~0U) {
764 if (l->ce_msgtype == RTM_NEWLINK)
767 cb->le_unregister(l);
772 if (l->l_change & IFF_SLAVE) {
773 if (l->l_flags & IFF_SLAVE) {
775 cb->le_new_bonding(l, m);
779 cb->le_cancel_bonding(l);
783 if (l->l_change & IFF_UP && l->l_change & IFF_RUNNING)
784 dp_dump_line(p, line++,
"link %s changed state to %s.\n",
785 l->l_name, l->l_flags & IFF_UP ?
"up" :
"down");
787 if (l->l_change & IFF_PROMISC) {
788 dp_new_line(p, line++);
789 dp_dump(p,
"link %s %s promiscuous mode.\n",
790 l->l_name, l->l_flags & IFF_PROMISC ?
"entered" :
"left");
794 dp_dump_line(p, line++,
"link %s sent unknown event.\n",
803 uint32_t attrs,
int flags)
809 #define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR)
811 diff |= LINK_DIFF(IFINDEX, a->l_index != b->l_index);
812 diff |= LINK_DIFF(MTU, a->l_mtu != b->l_mtu);
813 diff |= LINK_DIFF(LINK, a->l_link != b->l_link);
814 diff |= LINK_DIFF(TXQLEN, a->l_txqlen != b->l_txqlen);
815 diff |= LINK_DIFF(WEIGHT, a->l_weight != b->l_weight);
816 diff |= LINK_DIFF(MASTER, a->l_master != b->l_master);
817 diff |= LINK_DIFF(FAMILY, a->l_family != b->l_family);
818 diff |= LINK_DIFF(OPERSTATE, a->l_operstate != b->l_operstate);
819 diff |= LINK_DIFF(LINKMODE, a->l_linkmode != b->l_linkmode);
820 diff |= LINK_DIFF(QDISC, strcmp(a->l_qdisc, b->l_qdisc));
821 diff |= LINK_DIFF(IFNAME, strcmp(a->l_name, b->l_name));
822 diff |= LINK_DIFF(ADDR,
nl_addr_cmp(a->l_addr, b->l_addr));
823 diff |= LINK_DIFF(BRD,
nl_addr_cmp(a->l_bcast, b->l_bcast));
824 diff |= LINK_DIFF(IFALIAS, strcmp(a->l_ifalias, b->l_ifalias));
825 diff |= LINK_DIFF(NUM_VF, a->l_num_vf != b->l_num_vf);
826 diff |= LINK_DIFF(PROMISCUITY, a->l_promiscuity != b->l_promiscuity);
827 diff |= LINK_DIFF(NUM_TX_QUEUES,a->l_num_tx_queues != b->l_num_tx_queues);
828 diff |= LINK_DIFF(NUM_RX_QUEUES,a->l_num_rx_queues != b->l_num_rx_queues);
829 diff |= LINK_DIFF(GROUP, a->l_group != b->l_group);
831 if (flags & LOOSE_COMPARISON)
832 diff |= LINK_DIFF(FLAGS,
833 (a->l_flags ^ b->l_flags) & b->l_flag_mask);
835 diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags);
842 static const struct trans_tbl link_attrs[] = {
843 __ADD(LINK_ATTR_MTU, mtu)
844 __ADD(LINK_ATTR_LINK, link)
845 __ADD(LINK_ATTR_TXQLEN, txqlen)
846 __ADD(LINK_ATTR_WEIGHT, weight)
847 __ADD(LINK_ATTR_MASTER, master)
848 __ADD(LINK_ATTR_QDISC, qdisc)
849 __ADD(LINK_ATTR_MAP, map)
850 __ADD(LINK_ATTR_ADDR, address)
851 __ADD(LINK_ATTR_BRD, broadcast)
852 __ADD(LINK_ATTR_FLAGS, flags)
853 __ADD(LINK_ATTR_IFNAME, name)
854 __ADD(LINK_ATTR_IFINDEX, ifindex)
855 __ADD(LINK_ATTR_FAMILY, family)
856 __ADD(LINK_ATTR_ARPTYPE, arptype)
857 __ADD(LINK_ATTR_STATS, stats)
858 __ADD(LINK_ATTR_CHANGE, change)
859 __ADD(LINK_ATTR_OPERSTATE, operstate)
860 __ADD(LINK_ATTR_LINKMODE, linkmode)
861 __ADD(LINK_ATTR_IFALIAS, ifalias)
862 __ADD(LINK_ATTR_NUM_VF, num_vf)
863 __ADD(LINK_ATTR_PROMISCUITY, promiscuity)
864 __ADD(LINK_ATTR_NUM_TX_QUEUES, num_tx_queues)
865 __ADD(LINK_ATTR_NUM_RX_QUEUES, num_rx_queues)
866 __ADD(LINK_ATTR_GROUP, group)
869 static
char *link_attrs2str(
int attrs,
char *buf,
size_t len)
871 return __flags2str(attrs, buf, len, link_attrs,
872 ARRAY_SIZE(link_attrs));
906 struct nl_cache * cache;
913 cache->c_iarg1 = family;
943 if (cache->c_ops != &rtnl_link_ops)
946 nl_list_for_each_entry(link, &cache->c_items, ce_list) {
947 if (link->l_index == ifindex) {
976 if (cache->c_ops != &rtnl_link_ops)
979 nl_list_for_each_entry(link, &cache->c_items, ce_list) {
980 if (!strcmp(name, link->l_name)) {
1004 struct nl_msg **result)
1006 struct ifinfomsg ifi;
1009 if (ifindex <= 0 && !name) {
1010 APPBUG(
"ifindex or name must be specified");
1011 return -NLE_MISSING_ATTR;
1014 memset(&ifi, 0,
sizeof(ifi));
1020 ifi.ifi_index = ifindex;
1022 if (
nlmsg_append(msg, &ifi,
sizeof(ifi), NLMSG_ALIGNTO) < 0)
1023 goto nla_put_failure;
1033 return -NLE_MSGSIZE;
1055 struct nl_msg *msg = NULL;
1067 if ((err =
nl_pickup(sk, link_msg_parser, &obj)) < 0)
1074 if (err == 0 && obj)
1100 strncpy(dst, link->l_name, len - 1);
1124 ifindex = link->l_index;
1133 static int build_link_msg(
int cmd,
struct ifinfomsg *hdr,
1134 struct rtnl_link *link,
int flags,
struct nl_msg **result)
1137 struct nlattr *af_spec;
1143 if (
nlmsg_append(msg, hdr,
sizeof(*hdr), NLMSG_ALIGNTO) < 0)
1144 goto nla_put_failure;
1146 if (link->ce_mask & LINK_ATTR_ADDR)
1149 if (link->ce_mask & LINK_ATTR_BRD)
1152 if (link->ce_mask & LINK_ATTR_MTU)
1155 if (link->ce_mask & LINK_ATTR_TXQLEN)
1158 if (link->ce_mask & LINK_ATTR_WEIGHT)
1161 if (link->ce_mask & LINK_ATTR_IFNAME)
1164 if (link->ce_mask & LINK_ATTR_OPERSTATE)
1165 NLA_PUT_U8(msg, IFLA_OPERSTATE, link->l_operstate);
1167 if (link->ce_mask & LINK_ATTR_LINKMODE)
1168 NLA_PUT_U8(msg, IFLA_LINKMODE, link->l_linkmode);
1170 if (link->ce_mask & LINK_ATTR_IFALIAS)
1173 if (link->ce_mask & LINK_ATTR_LINK)
1176 if (link->ce_mask & LINK_ATTR_MASTER)
1179 if (link->ce_mask & LINK_ATTR_NUM_TX_QUEUES)
1180 NLA_PUT_U32(msg, IFLA_NUM_TX_QUEUES, link->l_num_tx_queues);
1182 if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES)
1183 NLA_PUT_U32(msg, IFLA_NUM_RX_QUEUES, link->l_num_rx_queues);
1185 if (link->ce_mask & LINK_ATTR_GROUP)
1188 if (link->ce_mask & LINK_ATTR_LINKINFO) {
1189 struct nlattr *info;
1192 goto nla_put_failure;
1196 if (link->l_info_ops) {
1197 if (link->l_info_ops->io_put_attrs &&
1198 link->l_info_ops->io_put_attrs(msg, link) < 0)
1199 goto nla_put_failure;
1206 goto nla_put_failure;
1208 if (do_foreach_af(link, af_fill, msg) < 0)
1209 goto nla_put_failure;
1218 return -NLE_MSGSIZE;
1243 struct nl_msg **result)
1245 struct ifinfomsg ifi = {
1246 .ifi_family = link->l_family,
1247 .ifi_index = link->l_index,
1248 .ifi_flags = link->l_flags,
1251 return build_link_msg(RTM_NEWLINK, &ifi, link, flags, result);
1305 struct nl_msg **result)
1307 struct ifinfomsg ifi = {
1308 .ifi_family = orig->l_family,
1309 .ifi_index = orig->l_index,
1313 if (changes->ce_mask & LINK_ATTR_FLAGS) {
1314 ifi.ifi_flags = orig->l_flags & ~changes->l_flag_mask;
1315 ifi.ifi_flags |= changes->l_flags;
1318 if (changes->l_family && changes->l_family != orig->l_family) {
1319 APPBUG(
"link change: family is immutable");
1320 return -NLE_IMMUTABLE;
1324 if (orig->ce_mask & LINK_ATTR_IFINDEX &&
1325 orig->ce_mask & LINK_ATTR_IFNAME &&
1326 changes->ce_mask & LINK_ATTR_IFNAME &&
1327 !strcmp(orig->l_name, changes->l_name))
1328 changes->ce_mask &= ~LINK_ATTR_IFNAME;
1330 if ((err = build_link_msg(RTM_NEWLINK, &ifi, changes, flags, result)) < 0)
1381 err = nl_send_auto_complete(sk, msg);
1385 err = wait_for_ack(sk);
1386 if (err == -NLE_OPNOTSUPP && msg->nm_nlh->nlmsg_type == RTM_NEWLINK) {
1387 msg->nm_nlh->nlmsg_type = RTM_SETLINK;
1417 struct nl_msg **result)
1420 struct ifinfomsg ifi = {
1421 .ifi_index = link->l_index,
1424 if (!(link->ce_mask & (LINK_ATTR_IFINDEX | LINK_ATTR_IFNAME))) {
1425 APPBUG(
"ifindex or name must be specified");
1426 return -NLE_MISSING_ATTR;
1432 if (
nlmsg_append(msg, &ifi,
sizeof(ifi), NLMSG_ALIGNTO) < 0)
1433 goto nla_put_failure;
1435 if (link->ce_mask & LINK_ATTR_IFNAME)
1443 return -NLE_MSGSIZE;
1524 strncpy(link->l_name, name,
sizeof(link->l_name) - 1);
1525 link->ce_mask |= LINK_ATTR_IFNAME;
1538 return link->ce_mask & LINK_ATTR_IFNAME ? link->l_name : NULL;
1548 link->l_group = group;
1549 link->ce_mask |= LINK_ATTR_GROUP;
1560 return link->l_group;
1563 static inline void __assign_addr(
struct rtnl_link *link,
struct nl_addr **pos,
1564 struct nl_addr *
new,
int flag)
1572 link->ce_mask |= flag;
1588 __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR);
1602 return link->ce_mask & LINK_ATTR_ADDR ? link->l_addr : NULL;
1619 __assign_addr(link, &link->l_bcast, addr, LINK_ATTR_BRD);
1633 return link->ce_mask & LINK_ATTR_BRD ? link->l_bcast : NULL;
1646 link->l_flag_mask |= flags;
1647 link->l_flags |= flags;
1648 link->ce_mask |= LINK_ATTR_FLAGS;
1661 link->l_flag_mask |= flags;
1662 link->l_flags &= ~flags;
1663 link->ce_mask |= LINK_ATTR_FLAGS;
1677 return link->l_flags;
1687 link->l_family = family;
1688 link->ce_mask |= LINK_ATTR_FAMILY;
1700 return link->ce_mask & LINK_ATTR_FAMILY ? link->l_family : AF_UNSPEC;
1714 link->l_arptype = arptype;
1715 link->ce_mask |= LINK_ATTR_ARPTYPE;
1728 if (link->ce_mask & LINK_ATTR_ARPTYPE)
1729 return link->l_arptype;
1744 link->l_index = ifindex;
1745 link->ce_mask |= LINK_ATTR_IFINDEX;
1759 return link->l_index;
1773 link->ce_mask |= LINK_ATTR_MTU;
1801 link->l_txqlen = txqlen;
1802 link->ce_mask |= LINK_ATTR_TXQLEN;
1817 return link->ce_mask & LINK_ATTR_TXQLEN ? link->l_txqlen : 0;
1820 void rtnl_link_set_link(
struct rtnl_link *link,
int ifindex)
1822 link->l_link = ifindex;
1823 link->ce_mask |= LINK_ATTR_LINK;
1826 int rtnl_link_get_link(
struct rtnl_link *link)
1828 return link->l_link;
1840 link->l_master = ifindex;
1841 link->ce_mask |= LINK_ATTR_MASTER;
1853 return link->l_master;
1866 link->l_operstate = status;
1867 link->ce_mask |= LINK_ATTR_OPERSTATE;
1880 return link->l_operstate;
1893 link->l_linkmode = mode;
1894 link->ce_mask |= LINK_ATTR_LINKMODE;
1907 return link->l_linkmode;
1920 return link->l_ifalias;
1937 free(link->l_ifalias);
1938 link->ce_mask &= ~LINK_ATTR_IFALIAS;
1941 link->l_ifalias = strdup(alias);
1942 link->ce_mask |= LINK_ATTR_IFALIAS;
1961 strncpy(link->l_qdisc, name,
sizeof(link->l_qdisc) - 1);
1962 link->ce_mask |= LINK_ATTR_QDISC;
1975 return link->ce_mask & LINK_ATTR_QDISC ? link->l_qdisc : NULL;
1988 if (link->ce_mask & LINK_ATTR_NUM_VF) {
1989 *num_vf = link->l_num_vf;
1992 return -NLE_OPNOTSUPP;
2004 if (
id > RTNL_LINK_STATS_MAX)
2007 return link->l_stats[id];
2022 const uint64_t value)
2024 if (
id > RTNL_LINK_STATS_MAX)
2027 link->l_stats[id] = value;
2050 free(link->l_info_kind);
2051 link->ce_mask &= ~LINK_ATTR_LINKINFO;
2052 if (link->l_info_ops)
2053 release_link_info(link);
2058 kind = strdup(type);
2067 link->l_info_ops = io;
2070 link->l_info_kind = kind;
2071 link->ce_mask |= LINK_ATTR_LINKINFO;
2089 return link->l_info_kind;
2103 link->l_promiscuity = count;
2104 link->ce_mask |= LINK_ATTR_PROMISCUITY;
2116 return link->l_promiscuity;
2135 link->l_num_tx_queues = nqueues;
2136 link->ce_mask |= LINK_ATTR_NUM_TX_QUEUES;
2147 return link->l_num_tx_queues;
2166 link->l_num_rx_queues = nqueues;
2167 link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES;
2178 return link->l_num_rx_queues;
2228 err = -NLE_OPNOTSUPP;
2311 static const struct trans_tbl link_flags[] = {
2312 __ADD(IFF_LOOPBACK, loopback)
2313 __ADD(IFF_BROADCAST, broadcast)
2314 __ADD(IFF_POINTOPOINT, pointopoint)
2315 __ADD(IFF_MULTICAST, multicast)
2316 __ADD(IFF_NOARP, noarp)
2317 __ADD(IFF_ALLMULTI, allmulti)
2318 __ADD(IFF_PROMISC, promisc)
2319 __ADD(IFF_MASTER, master)
2320 __ADD(IFF_SLAVE, slave)
2321 __ADD(IFF_DEBUG, debug)
2322 __ADD(IFF_DYNAMIC, dynamic)
2323 __ADD(IFF_AUTOMEDIA, automedia)
2324 __ADD(IFF_PORTSEL, portsel)
2325 __ADD(IFF_NOTRAILERS, notrailers)
2327 __ADD(IFF_RUNNING, running)
2328 __ADD(IFF_LOWER_UP, lowerup)
2329 __ADD(IFF_DORMANT, dormant)
2330 __ADD(IFF_ECHO, echo)
2333 char *rtnl_link_flags2str(
int flags,
char *buf,
size_t len)
2335 return __flags2str(flags, buf, len, link_flags,
2336 ARRAY_SIZE(link_flags));
2339 int rtnl_link_str2flags(
const char *name)
2341 return __str2flags(name, link_flags, ARRAY_SIZE(link_flags));
2344 static const struct trans_tbl link_stats[] = {
2404 char *rtnl_link_stat2str(
int st,
char *buf,
size_t len)
2406 return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats));
2409 int rtnl_link_str2stat(
const char *name)
2411 return __str2type(name, link_stats, ARRAY_SIZE(link_stats));
2414 static const struct trans_tbl link_operstates[] = {
2415 __ADD(IF_OPER_UNKNOWN, unknown)
2416 __ADD(IF_OPER_NOTPRESENT, notpresent)
2417 __ADD(IF_OPER_DOWN, down)
2418 __ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown)
2419 __ADD(IF_OPER_TESTING, testing)
2420 __ADD(IF_OPER_DORMANT, dormant)
2421 __ADD(IF_OPER_UP, up)
2424 char *rtnl_link_operstate2str(uint8_t st,
char *buf,
size_t len)
2426 return __type2str(st, buf, len, link_operstates,
2427 ARRAY_SIZE(link_operstates));
2430 int rtnl_link_str2operstate(
const char *name)
2432 return __str2type(name, link_operstates,
2433 ARRAY_SIZE(link_operstates));
2436 static const struct trans_tbl link_modes[] = {
2437 __ADD(IF_LINK_MODE_DEFAULT,
default)
2438 __ADD(IF_LINK_MODE_DORMANT, dormant)
2441 char *rtnl_link_mode2str(uint8_t st,
char *buf,
size_t len)
2443 return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes));
2446 int rtnl_link_str2mode(
const char *name)
2448 return __str2type(name, link_modes, ARRAY_SIZE(link_modes));
2478 link->l_weight = weight;
2479 link->ce_mask |= LINK_ATTR_WEIGHT;
2487 return link->l_weight;
2495 .oo_free_data = link_free_data,
2496 .oo_clone = link_clone,
2502 .oo_compare = link_compare,
2503 .oo_attrs2str = link_attrs2str,
2504 .oo_id_attrs = LINK_ATTR_IFINDEX,
2508 { AF_UNSPEC, RTNLGRP_LINK },
2509 { END_OF_GROUP_LIST },
2514 .co_hdrsize =
sizeof(
struct ifinfomsg),
2516 { RTM_NEWLINK, NL_ACT_NEW,
"new" },
2517 { RTM_DELLINK, NL_ACT_DEL,
"del" },
2518 { RTM_GETLINK, NL_ACT_GET,
"get" },
2519 { RTM_SETLINK, NL_ACT_CHANGE,
"set" },
2520 END_OF_MSGTYPES_LIST,
2522 .co_protocol = NETLINK_ROUTE,
2523 .co_groups = link_groups,
2524 .co_request_update = link_request_update,
2525 .co_msg_parser = link_msg_parser,
2526 .co_event_filter = link_event_filter,
2527 .co_obj_ops = &link_obj_ops,
2530 static void __init link_init(
void)
2535 static void __exit link_exit(
void)