1/* 2 * lib/route/link.c Links (Interfaces) 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch> 10 */ 11 12/** 13 * @ingroup rtnl 14 * @defgroup link Links (Interfaces) 15 * 16 * @details 17 * @route_doc{route_link, Link Documentation} 18 * @{ 19 */ 20 21#include <netlink-private/netlink.h> 22#include <netlink/netlink.h> 23#include <netlink/attr.h> 24#include <netlink/utils.h> 25#include <netlink/object.h> 26#include <netlink/hashtable.h> 27#include <netlink/data.h> 28#include <netlink/route/rtnl.h> 29#include <netlink/route/link.h> 30#include <netlink-private/route/link/api.h> 31 32/** @cond SKIP */ 33#define LINK_ATTR_MTU (1 << 0) 34#define LINK_ATTR_LINK (1 << 1) 35#define LINK_ATTR_TXQLEN (1 << 2) 36#define LINK_ATTR_WEIGHT (1 << 3) 37#define LINK_ATTR_MASTER (1 << 4) 38#define LINK_ATTR_QDISC (1 << 5) 39#define LINK_ATTR_MAP (1 << 6) 40#define LINK_ATTR_ADDR (1 << 7) 41#define LINK_ATTR_BRD (1 << 8) 42#define LINK_ATTR_FLAGS (1 << 9) 43#define LINK_ATTR_IFNAME (1 << 10) 44#define LINK_ATTR_IFINDEX (1 << 11) 45#define LINK_ATTR_FAMILY (1 << 12) 46#define LINK_ATTR_ARPTYPE (1 << 13) 47#define LINK_ATTR_STATS (1 << 14) 48#define LINK_ATTR_CHANGE (1 << 15) 49#define LINK_ATTR_OPERSTATE (1 << 16) 50#define LINK_ATTR_LINKMODE (1 << 17) 51#define LINK_ATTR_LINKINFO (1 << 18) 52#define LINK_ATTR_IFALIAS (1 << 19) 53#define LINK_ATTR_NUM_VF (1 << 20) 54#define LINK_ATTR_PROMISCUITY (1 << 21) 55#define LINK_ATTR_NUM_TX_QUEUES (1 << 22) 56#define LINK_ATTR_NUM_RX_QUEUES (1 << 23) 57#define LINK_ATTR_GROUP (1 << 24) 58#define LINK_ATTR_CARRIER (1 << 25) 59#define LINK_ATTR_PROTINFO (1 << 26) 60#define LINK_ATTR_AF_SPEC (1 << 27) 61#define LINK_ATTR_PHYS_PORT_ID (1 << 28) 62#define LINK_ATTR_NS_FD (1 << 29) 63#define LINK_ATTR_NS_PID (1 << 30) 64 65static struct nl_cache_ops rtnl_link_ops; 66static struct nl_object_ops link_obj_ops; 67/** @endcond */ 68 69static struct rtnl_link_af_ops *af_lookup_and_alloc(struct rtnl_link *link, 70 int family) 71{ 72 struct rtnl_link_af_ops *af_ops; 73 void *data; 74 75 af_ops = rtnl_link_af_ops_lookup(family); 76 if (!af_ops) 77 return NULL; 78 79 if (!(data = rtnl_link_af_alloc(link, af_ops))) { 80 rtnl_link_af_ops_put(af_ops); 81 return NULL; 82 } 83 84 return af_ops; 85} 86 87static int af_free(struct rtnl_link *link, struct rtnl_link_af_ops *ops, 88 void *data, void *arg) 89{ 90 if (ops->ao_free) 91 ops->ao_free(link, data); 92 93 rtnl_link_af_ops_put(ops); 94 95 return 0; 96} 97 98static int af_clone(struct rtnl_link *link, struct rtnl_link_af_ops *ops, 99 void *data, void *arg) 100{ 101 struct rtnl_link *dst = arg; 102 103 if (ops->ao_clone && 104 !(dst->l_af_data[ops->ao_family] = ops->ao_clone(dst, data))) 105 return -NLE_NOMEM; 106 107 return 0; 108} 109 110static int af_fill(struct rtnl_link *link, struct rtnl_link_af_ops *ops, 111 void *data, void *arg) 112{ 113 struct nl_msg *msg = arg; 114 struct nlattr *af_attr; 115 int err; 116 117 if (!ops->ao_fill_af) 118 return 0; 119 120 if (!(af_attr = nla_nest_start(msg, ops->ao_family))) 121 return -NLE_MSGSIZE; 122 123 if ((err = ops->ao_fill_af(link, arg, data)) < 0) 124 return err; 125 126 nla_nest_end(msg, af_attr); 127 128 return 0; 129} 130 131static int af_dump_line(struct rtnl_link *link, struct rtnl_link_af_ops *ops, 132 void *data, void *arg) 133{ 134 struct nl_dump_params *p = arg; 135 136 if (ops->ao_dump[NL_DUMP_LINE]) 137 ops->ao_dump[NL_DUMP_LINE](link, p, data); 138 139 return 0; 140} 141 142static int af_dump_details(struct rtnl_link *link, struct rtnl_link_af_ops *ops, 143 void *data, void *arg) 144{ 145 struct nl_dump_params *p = arg; 146 147 if (ops->ao_dump[NL_DUMP_DETAILS]) 148 ops->ao_dump[NL_DUMP_DETAILS](link, p, data); 149 150 return 0; 151} 152 153static int af_dump_stats(struct rtnl_link *link, struct rtnl_link_af_ops *ops, 154 void *data, void *arg) 155{ 156 struct nl_dump_params *p = arg; 157 158 if (ops->ao_dump[NL_DUMP_STATS]) 159 ops->ao_dump[NL_DUMP_STATS](link, p, data); 160 161 return 0; 162} 163 164static int do_foreach_af(struct rtnl_link *link, 165 int (*cb)(struct rtnl_link *, 166 struct rtnl_link_af_ops *, void *, void *), 167 void *arg) 168{ 169 int i, err; 170 171 for (i = 0; i < AF_MAX; i++) { 172 if (link->l_af_data[i]) { 173 struct rtnl_link_af_ops *ops; 174 175 if (!(ops = rtnl_link_af_ops_lookup(i))) 176 BUG(); 177 178 err = cb(link, ops, link->l_af_data[i], arg); 179 180 rtnl_link_af_ops_put(ops); 181 182 if (err < 0) 183 return err; 184 } 185 } 186 187 return 0; 188} 189 190static void release_link_info(struct rtnl_link *link) 191{ 192 struct rtnl_link_info_ops *io = link->l_info_ops; 193 194 if (io != NULL) { 195 if (io->io_free) 196 io->io_free(link); 197 else { 198 /* Catch missing io_free() implementations */ 199 BUG_ON(link->l_info); 200 } 201 rtnl_link_info_ops_put(io); 202 link->l_info_ops = NULL; 203 } 204} 205 206static void link_free_data(struct nl_object *c) 207{ 208 struct rtnl_link *link = nl_object_priv(c); 209 210 if (link) { 211 struct rtnl_link_info_ops *io; 212 213 if ((io = link->l_info_ops) != NULL) 214 release_link_info(link); 215 216 /* proto info af reference */ 217 rtnl_link_af_ops_put(link->l_af_ops); 218 219 nl_addr_put(link->l_addr); 220 nl_addr_put(link->l_bcast); 221 222 free(link->l_ifalias); 223 free(link->l_info_kind); 224 225 do_foreach_af(link, af_free, NULL); 226 227 nl_data_free(link->l_phys_port_id); 228 } 229} 230 231static int link_clone(struct nl_object *_dst, struct nl_object *_src) 232{ 233 struct rtnl_link *dst = nl_object_priv(_dst); 234 struct rtnl_link *src = nl_object_priv(_src); 235 int err; 236 237 if (src->l_addr) 238 if (!(dst->l_addr = nl_addr_clone(src->l_addr))) 239 return -NLE_NOMEM; 240 241 if (src->l_bcast) 242 if (!(dst->l_bcast = nl_addr_clone(src->l_bcast))) 243 return -NLE_NOMEM; 244 245 if (src->l_ifalias) 246 if (!(dst->l_ifalias = strdup(src->l_ifalias))) 247 return -NLE_NOMEM; 248 249 if (src->l_info_kind) 250 if (!(dst->l_info_kind = strdup(src->l_info_kind))) 251 return -NLE_NOMEM; 252 253 if (src->l_info_ops && src->l_info_ops->io_clone) { 254 err = src->l_info_ops->io_clone(dst, src); 255 if (err < 0) 256 return err; 257 } 258 259 if ((err = do_foreach_af(src, af_clone, dst)) < 0) 260 return err; 261 262 if (src->l_phys_port_id) 263 if (!(dst->l_phys_port_id = nl_data_clone(src->l_phys_port_id))) 264 return -NLE_NOMEM; 265 266 return 0; 267} 268 269struct nla_policy rtln_link_policy[IFLA_MAX+1] = { 270 [IFLA_IFNAME] = { .type = NLA_STRING, 271 .maxlen = IFNAMSIZ }, 272 [IFLA_MTU] = { .type = NLA_U32 }, 273 [IFLA_TXQLEN] = { .type = NLA_U32 }, 274 [IFLA_LINK] = { .type = NLA_U32 }, 275 [IFLA_WEIGHT] = { .type = NLA_U32 }, 276 [IFLA_MASTER] = { .type = NLA_U32 }, 277 [IFLA_OPERSTATE] = { .type = NLA_U8 }, 278 [IFLA_LINKMODE] = { .type = NLA_U8 }, 279 [IFLA_LINKINFO] = { .type = NLA_NESTED }, 280 [IFLA_QDISC] = { .type = NLA_STRING, 281 .maxlen = IFQDISCSIZ }, 282 [IFLA_STATS] = { .minlen = sizeof(struct rtnl_link_stats) }, 283 [IFLA_STATS64] = { .minlen = sizeof(struct rtnl_link_stats64)}, 284 [IFLA_MAP] = { .minlen = sizeof(struct rtnl_link_ifmap) }, 285 [IFLA_IFALIAS] = { .type = NLA_STRING, .maxlen = IFALIASZ }, 286 [IFLA_NUM_VF] = { .type = NLA_U32 }, 287 [IFLA_AF_SPEC] = { .type = NLA_NESTED }, 288 [IFLA_PROMISCUITY] = { .type = NLA_U32 }, 289 [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, 290 [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, 291 [IFLA_GROUP] = { .type = NLA_U32 }, 292 [IFLA_CARRIER] = { .type = NLA_U8 }, 293 [IFLA_PHYS_PORT_ID] = { .type = NLA_UNSPEC }, 294 [IFLA_NET_NS_PID] = { .type = NLA_U32 }, 295 [IFLA_NET_NS_FD] = { .type = NLA_U32 }, 296}; 297 298static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = { 299 [IFLA_INFO_KIND] = { .type = NLA_STRING }, 300 [IFLA_INFO_DATA] = { .type = NLA_NESTED }, 301 [IFLA_INFO_XSTATS] = { .type = NLA_NESTED }, 302}; 303 304int rtnl_link_info_parse(struct rtnl_link *link, struct nlattr **tb) 305{ 306 if (tb[IFLA_IFNAME] == NULL) 307 return -NLE_MISSING_ATTR; 308 309 nla_strlcpy(link->l_name, tb[IFLA_IFNAME], IFNAMSIZ); 310 311 312 if (tb[IFLA_STATS]) { 313 struct rtnl_link_stats *st = nla_data(tb[IFLA_STATS]); 314 315 link->l_stats[RTNL_LINK_RX_PACKETS] = st->rx_packets; 316 link->l_stats[RTNL_LINK_TX_PACKETS] = st->tx_packets; 317 link->l_stats[RTNL_LINK_RX_BYTES] = st->rx_bytes; 318 link->l_stats[RTNL_LINK_TX_BYTES] = st->tx_bytes; 319 link->l_stats[RTNL_LINK_RX_ERRORS] = st->rx_errors; 320 link->l_stats[RTNL_LINK_TX_ERRORS] = st->tx_errors; 321 link->l_stats[RTNL_LINK_RX_DROPPED] = st->rx_dropped; 322 link->l_stats[RTNL_LINK_TX_DROPPED] = st->tx_dropped; 323 link->l_stats[RTNL_LINK_MULTICAST] = st->multicast; 324 link->l_stats[RTNL_LINK_COLLISIONS] = st->collisions; 325 326 link->l_stats[RTNL_LINK_RX_LEN_ERR] = st->rx_length_errors; 327 link->l_stats[RTNL_LINK_RX_OVER_ERR] = st->rx_over_errors; 328 link->l_stats[RTNL_LINK_RX_CRC_ERR] = st->rx_crc_errors; 329 link->l_stats[RTNL_LINK_RX_FRAME_ERR] = st->rx_frame_errors; 330 link->l_stats[RTNL_LINK_RX_FIFO_ERR] = st->rx_fifo_errors; 331 link->l_stats[RTNL_LINK_RX_MISSED_ERR] = st->rx_missed_errors; 332 333 link->l_stats[RTNL_LINK_TX_ABORT_ERR] = st->tx_aborted_errors; 334 link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st->tx_carrier_errors; 335 link->l_stats[RTNL_LINK_TX_FIFO_ERR] = st->tx_fifo_errors; 336 link->l_stats[RTNL_LINK_TX_HBEAT_ERR] = st->tx_heartbeat_errors; 337 link->l_stats[RTNL_LINK_TX_WIN_ERR] = st->tx_window_errors; 338 339 link->l_stats[RTNL_LINK_RX_COMPRESSED] = st->rx_compressed; 340 link->l_stats[RTNL_LINK_TX_COMPRESSED] = st->tx_compressed; 341 342 link->ce_mask |= LINK_ATTR_STATS; 343 } 344 345 if (tb[IFLA_STATS64]) { 346 /* 347 * This structure contains 64bit parameters, and per the 348 * documentation in lib/attr.c, must not be accessed 349 * directly (because of alignment to 4 instead of 8). 350 * Therefore, copy the data to the stack and access it from 351 * there, where it will be aligned to 8. 352 */ 353 struct rtnl_link_stats64 st; 354 355 nla_memcpy(&st, tb[IFLA_STATS64], 356 sizeof(struct rtnl_link_stats64)); 357 358 link->l_stats[RTNL_LINK_RX_PACKETS] = st.rx_packets; 359 link->l_stats[RTNL_LINK_TX_PACKETS] = st.tx_packets; 360 link->l_stats[RTNL_LINK_RX_BYTES] = st.rx_bytes; 361 link->l_stats[RTNL_LINK_TX_BYTES] = st.tx_bytes; 362 link->l_stats[RTNL_LINK_RX_ERRORS] = st.rx_errors; 363 link->l_stats[RTNL_LINK_TX_ERRORS] = st.tx_errors; 364 link->l_stats[RTNL_LINK_RX_DROPPED] = st.rx_dropped; 365 link->l_stats[RTNL_LINK_TX_DROPPED] = st.tx_dropped; 366 link->l_stats[RTNL_LINK_MULTICAST] = st.multicast; 367 link->l_stats[RTNL_LINK_COLLISIONS] = st.collisions; 368 369 link->l_stats[RTNL_LINK_RX_LEN_ERR] = st.rx_length_errors; 370 link->l_stats[RTNL_LINK_RX_OVER_ERR] = st.rx_over_errors; 371 link->l_stats[RTNL_LINK_RX_CRC_ERR] = st.rx_crc_errors; 372 link->l_stats[RTNL_LINK_RX_FRAME_ERR] = st.rx_frame_errors; 373 link->l_stats[RTNL_LINK_RX_FIFO_ERR] = st.rx_fifo_errors; 374 link->l_stats[RTNL_LINK_RX_MISSED_ERR] = st.rx_missed_errors; 375 376 link->l_stats[RTNL_LINK_TX_ABORT_ERR] = st.tx_aborted_errors; 377 link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st.tx_carrier_errors; 378 link->l_stats[RTNL_LINK_TX_FIFO_ERR] = st.tx_fifo_errors; 379 link->l_stats[RTNL_LINK_TX_HBEAT_ERR] = st.tx_heartbeat_errors; 380 link->l_stats[RTNL_LINK_TX_WIN_ERR] = st.tx_window_errors; 381 382 link->l_stats[RTNL_LINK_RX_COMPRESSED] = st.rx_compressed; 383 link->l_stats[RTNL_LINK_TX_COMPRESSED] = st.tx_compressed; 384 385 link->ce_mask |= LINK_ATTR_STATS; 386 } 387 388 if (tb[IFLA_TXQLEN]) { 389 link->l_txqlen = nla_get_u32(tb[IFLA_TXQLEN]); 390 link->ce_mask |= LINK_ATTR_TXQLEN; 391 } 392 393 if (tb[IFLA_MTU]) { 394 link->l_mtu = nla_get_u32(tb[IFLA_MTU]); 395 link->ce_mask |= LINK_ATTR_MTU; 396 } 397 398 if (tb[IFLA_ADDRESS]) { 399 link->l_addr = nl_addr_alloc_attr(tb[IFLA_ADDRESS], AF_UNSPEC); 400 if (link->l_addr == NULL) 401 return -NLE_NOMEM; 402 nl_addr_set_family(link->l_addr, 403 nl_addr_guess_family(link->l_addr)); 404 link->ce_mask |= LINK_ATTR_ADDR; 405 } 406 407 if (tb[IFLA_BROADCAST]) { 408 link->l_bcast = nl_addr_alloc_attr(tb[IFLA_BROADCAST], 409 AF_UNSPEC); 410 if (link->l_bcast == NULL) 411 return -NLE_NOMEM; 412 nl_addr_set_family(link->l_bcast, 413 nl_addr_guess_family(link->l_bcast)); 414 link->ce_mask |= LINK_ATTR_BRD; 415 } 416 417 if (tb[IFLA_LINK]) { 418 link->l_link = nla_get_u32(tb[IFLA_LINK]); 419 link->ce_mask |= LINK_ATTR_LINK; 420 } 421 422 if (tb[IFLA_WEIGHT]) { 423 link->l_weight = nla_get_u32(tb[IFLA_WEIGHT]); 424 link->ce_mask |= LINK_ATTR_WEIGHT; 425 } 426 427 if (tb[IFLA_QDISC]) { 428 nla_strlcpy(link->l_qdisc, tb[IFLA_QDISC], IFQDISCSIZ); 429 link->ce_mask |= LINK_ATTR_QDISC; 430 } 431 432 if (tb[IFLA_MAP]) { 433 nla_memcpy(&link->l_map, tb[IFLA_MAP], 434 sizeof(struct rtnl_link_ifmap)); 435 link->ce_mask |= LINK_ATTR_MAP; 436 } 437 438 if (tb[IFLA_MASTER]) { 439 link->l_master = nla_get_u32(tb[IFLA_MASTER]); 440 link->ce_mask |= LINK_ATTR_MASTER; 441 } 442 443 if (tb[IFLA_CARRIER]) { 444 link->l_carrier = nla_get_u8(tb[IFLA_CARRIER]); 445 link->ce_mask |= LINK_ATTR_CARRIER; 446 } 447 448 if (tb[IFLA_OPERSTATE]) { 449 link->l_operstate = nla_get_u8(tb[IFLA_OPERSTATE]); 450 link->ce_mask |= LINK_ATTR_OPERSTATE; 451 } 452 453 if (tb[IFLA_LINKMODE]) { 454 link->l_linkmode = nla_get_u8(tb[IFLA_LINKMODE]); 455 link->ce_mask |= LINK_ATTR_LINKMODE; 456 } 457 458 if (tb[IFLA_IFALIAS]) { 459 link->l_ifalias = nla_strdup(tb[IFLA_IFALIAS]); 460 if (link->l_ifalias == NULL) 461 return -NLE_NOMEM; 462 link->ce_mask |= LINK_ATTR_IFALIAS; 463 } 464 465 if (tb[IFLA_NET_NS_FD]) { 466 link->l_ns_fd = nla_get_u32(tb[IFLA_NET_NS_FD]); 467 link->ce_mask |= LINK_ATTR_NS_FD; 468 } 469 470 if (tb[IFLA_NET_NS_PID]) { 471 link->l_ns_pid = nla_get_u32(tb[IFLA_NET_NS_PID]); 472 link->ce_mask |= LINK_ATTR_NS_PID; 473 } 474 475 return 0; 476} 477 478static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 479 struct nlmsghdr *n, struct nl_parser_param *pp) 480{ 481 struct rtnl_link *link; 482 struct ifinfomsg *ifi; 483 struct nlattr *tb[IFLA_MAX+1]; 484 struct rtnl_link_af_ops *af_ops = NULL; 485 int err, family; 486 struct nla_policy real_link_policy[IFLA_MAX+1]; 487 488 memcpy(&real_link_policy, rtln_link_policy, sizeof(rtln_link_policy)); 489 490 link = rtnl_link_alloc(); 491 if (link == NULL) { 492 err = -NLE_NOMEM; 493 goto errout; 494 } 495 496 link->ce_msgtype = n->nlmsg_type; 497 498 if (!nlmsg_valid_hdr(n, sizeof(*ifi))) 499 return -NLE_MSG_TOOSHORT; 500 501 ifi = nlmsg_data(n); 502 link->l_family = family = ifi->ifi_family; 503 link->l_arptype = ifi->ifi_type; 504 link->l_index = ifi->ifi_index; 505 link->l_flags = ifi->ifi_flags; 506 link->l_change = ifi->ifi_change; 507 link->ce_mask = (LINK_ATTR_IFNAME | LINK_ATTR_FAMILY | 508 LINK_ATTR_ARPTYPE| LINK_ATTR_IFINDEX | 509 LINK_ATTR_FLAGS | LINK_ATTR_CHANGE); 510 511 if ((af_ops = af_lookup_and_alloc(link, family))) { 512 if (af_ops->ao_protinfo_policy) { 513 memcpy(&real_link_policy[IFLA_PROTINFO], 514 af_ops->ao_protinfo_policy, 515 sizeof(struct nla_policy)); 516 } 517 518 link->l_af_ops = af_ops; 519 } 520 521 err = nlmsg_parse(n, sizeof(*ifi), tb, IFLA_MAX, real_link_policy); 522 if (err < 0) 523 return err; 524 525 err = rtnl_link_info_parse(link, tb); 526 if (err < 0) 527 return err; 528 529 if (tb[IFLA_NUM_VF]) { 530 link->l_num_vf = nla_get_u32(tb[IFLA_NUM_VF]); 531 link->ce_mask |= LINK_ATTR_NUM_VF; 532 } 533 534 if (tb[IFLA_LINKINFO]) { 535 struct nlattr *li[IFLA_INFO_MAX+1]; 536 537 err = nla_parse_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO], 538 link_info_policy); 539 if (err < 0) 540 goto errout; 541 542 if (li[IFLA_INFO_KIND]) { 543 struct rtnl_link_info_ops *ops; 544 char *kind = nla_get_string(li[IFLA_INFO_KIND]); 545 int af; 546 547 err = rtnl_link_set_type(link, kind); 548 if (err < 0) 549 goto errout; 550 551 if ((af = nl_str2af(kind)) >= 0 && 552 !af_ops && (af_ops = af_lookup_and_alloc(link, af))) { 553 554 if (af_ops->ao_protinfo_policy) { 555 tb[IFLA_PROTINFO] = (struct nlattr *)af_ops->ao_protinfo_policy; 556 } 557 link->l_family = family = af; 558 link->l_af_ops = af_ops; 559 } 560 561 ops = rtnl_link_info_ops_lookup(kind); 562 link->l_info_ops = ops; 563 564 if (ops) { 565 if (ops->io_parse && 566 (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) { 567 err = ops->io_parse(link, li[IFLA_INFO_DATA], 568 li[IFLA_INFO_XSTATS]); 569 if (err < 0) 570 goto errout; 571 } else { 572 /* XXX: Warn about unparsed info? */ 573 } 574 } 575 } 576 link->ce_mask |= LINK_ATTR_LINKINFO; 577 } 578 579 if (tb[IFLA_PROTINFO] && af_ops && af_ops->ao_parse_protinfo) { 580 err = af_ops->ao_parse_protinfo(link, tb[IFLA_PROTINFO], 581 link->l_af_data[link->l_family]); 582 if (err < 0) 583 goto errout; 584 link->ce_mask |= LINK_ATTR_PROTINFO; 585 } 586 587 if (tb[IFLA_AF_SPEC]) { 588 struct nlattr *af_attr; 589 int remaining; 590 591 nla_for_each_nested(af_attr, tb[IFLA_AF_SPEC], remaining) { 592 af_ops = af_lookup_and_alloc(link, nla_type(af_attr)); 593 if (af_ops && af_ops->ao_parse_af) { 594 char *af_data = link->l_af_data[nla_type(af_attr)]; 595 596 err = af_ops->ao_parse_af(link, af_attr, af_data); 597 if (err < 0) 598 goto errout; 599 } 600 601 } 602 link->ce_mask |= LINK_ATTR_AF_SPEC; 603 } 604 605 if (tb[IFLA_PROMISCUITY]) { 606 link->l_promiscuity = nla_get_u32(tb[IFLA_PROMISCUITY]); 607 link->ce_mask |= LINK_ATTR_PROMISCUITY; 608 } 609 610 if (tb[IFLA_NUM_TX_QUEUES]) { 611 link->l_num_tx_queues = nla_get_u32(tb[IFLA_NUM_TX_QUEUES]); 612 link->ce_mask |= LINK_ATTR_NUM_TX_QUEUES; 613 } 614 615 if (tb[IFLA_NUM_RX_QUEUES]) { 616 link->l_num_rx_queues = nla_get_u32(tb[IFLA_NUM_RX_QUEUES]); 617 link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES; 618 } 619 620 if (tb[IFLA_GROUP]) { 621 link->l_group = nla_get_u32(tb[IFLA_GROUP]); 622 link->ce_mask |= LINK_ATTR_GROUP; 623 } 624 625 if (tb[IFLA_PHYS_PORT_ID]) { 626 link->l_phys_port_id = nl_data_alloc_attr(tb[IFLA_PHYS_PORT_ID]); 627 if (link->l_phys_port_id == NULL) { 628 err = -NLE_NOMEM; 629 goto errout; 630 } 631 link->ce_mask |= LINK_ATTR_PHYS_PORT_ID; 632 } 633 634 err = pp->pp_cb((struct nl_object *) link, pp); 635errout: 636 rtnl_link_af_ops_put(af_ops); 637 rtnl_link_put(link); 638 return err; 639} 640 641static int link_request_update(struct nl_cache *cache, struct nl_sock *sk) 642{ 643 int family = cache->c_iarg1; 644 645 return nl_rtgen_request(sk, RTM_GETLINK, family, NLM_F_DUMP); 646} 647 648static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p) 649{ 650 char buf[128]; 651 struct nl_cache *cache = obj->ce_cache; 652 struct rtnl_link *link = (struct rtnl_link *) obj; 653 int fetched_cache = 0; 654 655 if (!cache) { 656 cache = nl_cache_mngt_require_safe("route/link"); 657 fetched_cache = 1; 658 } 659 660 nl_dump_line(p, "%s %s ", link->l_name, 661 nl_llproto2str(link->l_arptype, buf, sizeof(buf))); 662 663 if (link->l_addr && !nl_addr_iszero(link->l_addr)) 664 nl_dump(p, "%s ", nl_addr2str(link->l_addr, buf, sizeof(buf))); 665 666 if (link->ce_mask & LINK_ATTR_MASTER) { 667 if (cache) { 668 struct rtnl_link *master = rtnl_link_get(cache, link->l_master); 669 nl_dump(p, "master %s ", master ? master->l_name : "inv"); 670 if (master) 671 rtnl_link_put(master); 672 } else 673 nl_dump(p, "master %d ", link->l_master); 674 } 675 676 rtnl_link_flags2str(link->l_flags, buf, sizeof(buf)); 677 if (buf[0]) 678 nl_dump(p, "<%s> ", buf); 679 680 if (link->ce_mask & LINK_ATTR_LINK) { 681 if (cache) { 682 struct rtnl_link *ll = rtnl_link_get(cache, link->l_link); 683 nl_dump(p, "slave-of %s ", ll ? ll->l_name : "NONE"); 684 if (ll) 685 rtnl_link_put(ll); 686 } else 687 nl_dump(p, "slave-of %d ", link->l_link); 688 } 689 690 if (link->ce_mask & LINK_ATTR_GROUP) 691 nl_dump(p, "group %u ", link->l_group); 692 693 if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_LINE]) 694 link->l_info_ops->io_dump[NL_DUMP_LINE](link, p); 695 696 do_foreach_af(link, af_dump_line, p); 697 698 nl_dump(p, "\n"); 699 700 if (fetched_cache) 701 nl_cache_put(cache); 702} 703 704static void link_dump_details(struct nl_object *obj, struct nl_dump_params *p) 705{ 706 struct rtnl_link *link = (struct rtnl_link *) obj; 707 char buf[64]; 708 709 link_dump_line(obj, p); 710 711 nl_dump_line(p, " mtu %u ", link->l_mtu); 712 nl_dump(p, "txqlen %u weight %u ", link->l_txqlen, link->l_weight); 713 714 if (link->ce_mask & LINK_ATTR_QDISC) 715 nl_dump(p, "qdisc %s ", link->l_qdisc); 716 717 if (link->ce_mask & LINK_ATTR_MAP && link->l_map.lm_irq) 718 nl_dump(p, "irq %u ", link->l_map.lm_irq); 719 720 if (link->ce_mask & LINK_ATTR_IFINDEX) 721 nl_dump(p, "index %u ", link->l_index); 722 723 if (link->ce_mask & LINK_ATTR_PROMISCUITY && link->l_promiscuity > 0) 724 nl_dump(p, "promisc-mode (%u users) ", link->l_promiscuity); 725 726 nl_dump(p, "\n"); 727 728 if (link->ce_mask & LINK_ATTR_IFALIAS) 729 nl_dump_line(p, " alias %s\n", link->l_ifalias); 730 731 nl_dump_line(p, " "); 732 733 if (link->ce_mask & LINK_ATTR_NUM_TX_QUEUES) 734 nl_dump(p, "txq %u ", link->l_num_tx_queues); 735 736 if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES) 737 nl_dump(p, "rxq %u ", link->l_num_rx_queues); 738 739 if (link->ce_mask & LINK_ATTR_BRD) 740 nl_dump(p, "brd %s ", nl_addr2str(link->l_bcast, buf, 741 sizeof(buf))); 742 743 if ((link->ce_mask & LINK_ATTR_OPERSTATE) && 744 link->l_operstate != IF_OPER_UNKNOWN) { 745 rtnl_link_operstate2str(link->l_operstate, buf, sizeof(buf)); 746 nl_dump(p, "state %s ", buf); 747 } 748 749 if (link->ce_mask & LINK_ATTR_NUM_VF) 750 nl_dump(p, "num-vf %u ", link->l_num_vf); 751 752 nl_dump(p, "mode %s ", 753 rtnl_link_mode2str(link->l_linkmode, buf, sizeof(buf))); 754 755 nl_dump(p, "carrier %s", 756 rtnl_link_carrier2str(link->l_carrier, buf, sizeof(buf))); 757 758 nl_dump(p, "\n"); 759 760 if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_DETAILS]) 761 link->l_info_ops->io_dump[NL_DUMP_DETAILS](link, p); 762 763 do_foreach_af(link, af_dump_details, p); 764} 765 766static void link_dump_stats(struct nl_object *obj, struct nl_dump_params *p) 767{ 768 struct rtnl_link *link = (struct rtnl_link *) obj; 769 char *unit, fmt[64]; 770 float res; 771 772 link_dump_details(obj, p); 773 774 nl_dump_line(p, " Stats: bytes packets errors " 775 " dropped fifo-err compressed\n"); 776 777 res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_RX_BYTES], &unit); 778 779 strcpy(fmt, " RX %X.2f %s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n"); 780 fmt[9] = *unit == 'B' ? '9' : '7'; 781 782 nl_dump_line(p, fmt, res, unit, 783 link->l_stats[RTNL_LINK_RX_PACKETS], 784 link->l_stats[RTNL_LINK_RX_ERRORS], 785 link->l_stats[RTNL_LINK_RX_DROPPED], 786 link->l_stats[RTNL_LINK_RX_FIFO_ERR], 787 link->l_stats[RTNL_LINK_RX_COMPRESSED]); 788 789 res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_TX_BYTES], &unit); 790 791 strcpy(fmt, " TX %X.2f %s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n"); 792 fmt[9] = *unit == 'B' ? '9' : '7'; 793 794 nl_dump_line(p, fmt, res, unit, 795 link->l_stats[RTNL_LINK_TX_PACKETS], 796 link->l_stats[RTNL_LINK_TX_ERRORS], 797 link->l_stats[RTNL_LINK_TX_DROPPED], 798 link->l_stats[RTNL_LINK_TX_FIFO_ERR], 799 link->l_stats[RTNL_LINK_TX_COMPRESSED]); 800 801 nl_dump_line(p, " Errors: length over crc " 802 " frame missed multicast\n"); 803 804 nl_dump_line(p, " RX %10" PRIu64 " %10" PRIu64 " %10" 805 PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" 806 PRIu64 "\n", 807 link->l_stats[RTNL_LINK_RX_LEN_ERR], 808 link->l_stats[RTNL_LINK_RX_OVER_ERR], 809 link->l_stats[RTNL_LINK_RX_CRC_ERR], 810 link->l_stats[RTNL_LINK_RX_FRAME_ERR], 811 link->l_stats[RTNL_LINK_RX_MISSED_ERR], 812 link->l_stats[RTNL_LINK_MULTICAST]); 813 814 nl_dump_line(p, " aborted carrier heartbeat " 815 " window collision\n"); 816 817 nl_dump_line(p, " TX %10" PRIu64 " %10" PRIu64 " %10" 818 PRIu64 " %10" PRIu64 " %10" PRIu64 "\n", 819 link->l_stats[RTNL_LINK_TX_ABORT_ERR], 820 link->l_stats[RTNL_LINK_TX_CARRIER_ERR], 821 link->l_stats[RTNL_LINK_TX_HBEAT_ERR], 822 link->l_stats[RTNL_LINK_TX_WIN_ERR], 823 link->l_stats[RTNL_LINK_COLLISIONS]); 824 825 if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_STATS]) 826 link->l_info_ops->io_dump[NL_DUMP_STATS](link, p); 827 828 do_foreach_af(link, af_dump_stats, p); 829} 830 831#if 0 832static int link_handle_event(struct nl_object *a, struct rtnl_link_event_cb *cb) 833{ 834 struct rtnl_link *l = (struct rtnl_link *) a; 835 struct nl_cache *c = dp_cache(a); 836 int nevents = 0; 837 838 if (l->l_change == ~0U) { 839 if (l->ce_msgtype == RTM_NEWLINK) 840 cb->le_register(l); 841 else 842 cb->le_unregister(l); 843 844 return 1; 845 } 846 847 if (l->l_change & IFF_SLAVE) { 848 if (l->l_flags & IFF_SLAVE) { 849 struct rtnl_link *m = rtnl_link_get(c, l->l_master); 850 cb->le_new_bonding(l, m); 851 if (m) 852 rtnl_link_put(m); 853 } else 854 cb->le_cancel_bonding(l); 855 } 856 857#if 0 858 if (l->l_change & IFF_UP && l->l_change & IFF_RUNNING) 859 dp_dump_line(p, line++, "link %s changed state to %s.\n", 860 l->l_name, l->l_flags & IFF_UP ? "up" : "down"); 861 862 if (l->l_change & IFF_PROMISC) { 863 dp_new_line(p, line++); 864 dp_dump(p, "link %s %s promiscuous mode.\n", 865 l->l_name, l->l_flags & IFF_PROMISC ? "entered" : "left"); 866 } 867 868 if (line == 0) 869 dp_dump_line(p, line++, "link %s sent unknown event.\n", 870 l->l_name); 871#endif 872 873 return nevents; 874} 875#endif 876 877 878static void link_keygen(struct nl_object *obj, uint32_t *hashkey, 879 uint32_t table_sz) 880{ 881 struct rtnl_link *link = (struct rtnl_link *) obj; 882 unsigned int lkey_sz; 883 struct link_hash_key { 884 uint32_t l_index; 885 uint32_t l_family; 886 } __attribute__((packed)) lkey; 887 888 lkey_sz = sizeof(lkey); 889 lkey.l_index = link->l_index; 890 lkey.l_family = link->l_family; 891 892 *hashkey = nl_hash(&lkey, lkey_sz, 0) % table_sz; 893 894 NL_DBG(5, "link %p key (dev %d fam %d) keysz %d, hash 0x%x\n", 895 link, lkey.l_index, lkey.l_family, lkey_sz, *hashkey); 896 897 return; 898} 899 900static int link_compare(struct nl_object *_a, struct nl_object *_b, 901 uint32_t attrs, int flags) 902{ 903 struct rtnl_link *a = (struct rtnl_link *) _a; 904 struct rtnl_link *b = (struct rtnl_link *) _b; 905 int diff = 0; 906 907#define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR) 908 909 diff |= LINK_DIFF(IFINDEX, a->l_index != b->l_index); 910 diff |= LINK_DIFF(MTU, a->l_mtu != b->l_mtu); 911 diff |= LINK_DIFF(LINK, a->l_link != b->l_link); 912 diff |= LINK_DIFF(TXQLEN, a->l_txqlen != b->l_txqlen); 913 diff |= LINK_DIFF(WEIGHT, a->l_weight != b->l_weight); 914 diff |= LINK_DIFF(MASTER, a->l_master != b->l_master); 915 diff |= LINK_DIFF(FAMILY, a->l_family != b->l_family); 916 diff |= LINK_DIFF(OPERSTATE, a->l_operstate != b->l_operstate); 917 diff |= LINK_DIFF(LINKMODE, a->l_linkmode != b->l_linkmode); 918 diff |= LINK_DIFF(QDISC, strcmp(a->l_qdisc, b->l_qdisc)); 919 diff |= LINK_DIFF(IFNAME, strcmp(a->l_name, b->l_name)); 920 diff |= LINK_DIFF(ADDR, nl_addr_cmp(a->l_addr, b->l_addr)); 921 diff |= LINK_DIFF(BRD, nl_addr_cmp(a->l_bcast, b->l_bcast)); 922 diff |= LINK_DIFF(IFALIAS, strcmp(a->l_ifalias, b->l_ifalias)); 923 diff |= LINK_DIFF(NUM_VF, a->l_num_vf != b->l_num_vf); 924 diff |= LINK_DIFF(PROMISCUITY, a->l_promiscuity != b->l_promiscuity); 925 diff |= LINK_DIFF(NUM_TX_QUEUES,a->l_num_tx_queues != b->l_num_tx_queues); 926 diff |= LINK_DIFF(NUM_RX_QUEUES,a->l_num_rx_queues != b->l_num_rx_queues); 927 diff |= LINK_DIFF(GROUP, a->l_group != b->l_group); 928 929 if (flags & LOOSE_COMPARISON) 930 diff |= LINK_DIFF(FLAGS, 931 (a->l_flags ^ b->l_flags) & b->l_flag_mask); 932 else 933 diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags); 934 935 /* 936 * Compare LINK_ATTR_PROTINFO af_data 937 */ 938 if (a->l_family == b->l_family) { 939 if (rtnl_link_af_data_compare(a, b, a->l_family) != 0) 940 goto protinfo_mismatch; 941 } 942 943out: 944 return diff; 945 946protinfo_mismatch: 947 diff |= LINK_DIFF(PROTINFO, 1); 948 goto out; 949 950#undef LINK_DIFF 951} 952 953static const struct trans_tbl link_attrs[] = { 954 __ADD(LINK_ATTR_MTU, mtu) 955 __ADD(LINK_ATTR_LINK, link) 956 __ADD(LINK_ATTR_TXQLEN, txqlen) 957 __ADD(LINK_ATTR_WEIGHT, weight) 958 __ADD(LINK_ATTR_MASTER, master) 959 __ADD(LINK_ATTR_QDISC, qdisc) 960 __ADD(LINK_ATTR_MAP, map) 961 __ADD(LINK_ATTR_ADDR, address) 962 __ADD(LINK_ATTR_BRD, broadcast) 963 __ADD(LINK_ATTR_FLAGS, flags) 964 __ADD(LINK_ATTR_IFNAME, name) 965 __ADD(LINK_ATTR_IFINDEX, ifindex) 966 __ADD(LINK_ATTR_FAMILY, family) 967 __ADD(LINK_ATTR_ARPTYPE, arptype) 968 __ADD(LINK_ATTR_STATS, stats) 969 __ADD(LINK_ATTR_CHANGE, change) 970 __ADD(LINK_ATTR_OPERSTATE, operstate) 971 __ADD(LINK_ATTR_LINKMODE, linkmode) 972 __ADD(LINK_ATTR_IFALIAS, ifalias) 973 __ADD(LINK_ATTR_NUM_VF, num_vf) 974 __ADD(LINK_ATTR_PROMISCUITY, promiscuity) 975 __ADD(LINK_ATTR_NUM_TX_QUEUES, num_tx_queues) 976 __ADD(LINK_ATTR_NUM_RX_QUEUES, num_rx_queues) 977 __ADD(LINK_ATTR_GROUP, group) 978 __ADD(LINK_ATTR_CARRIER, carrier) 979 __ADD(LINK_ATTR_PHYS_PORT_ID, phys_port_id) 980}; 981 982static char *link_attrs2str(int attrs, char *buf, size_t len) 983{ 984 return __flags2str(attrs, buf, len, link_attrs, 985 ARRAY_SIZE(link_attrs)); 986} 987 988/** 989 * @name Get / List 990 * @{ 991 */ 992 993 994/** 995 * Allocate link cache and fill in all configured links. 996 * @arg sk Netlink socket. 997 * @arg family Link address family or AF_UNSPEC 998 * @arg result Pointer to store resulting cache. 999 * 1000 * Allocates and initializes a new link cache. If \c sk is valid, a netlink 1001 * message is sent to the kernel requesting a full dump of all configured 1002 * links. The returned messages are parsed and filled into the cache. If 1003 * the operation succeeds, the resulting cache will contain a link object for 1004 * each link configured in the kernel. If \c sk is NULL, returns 0 but the 1005 * cache is still empty. 1006 * 1007 * If \c family is set to an address family other than \c AF_UNSPEC the 1008 * contents of the cache can be limited to a specific address family. 1009 * Currently the following address families are supported: 1010 * - AF_BRIDGE 1011 * - AF_INET6 1012 * 1013 * @route_doc{link_list, Get List of Links} 1014 * @see rtnl_link_get() 1015 * @see rtnl_link_get_by_name() 1016 * @return 0 on success or a negative error code. 1017 */ 1018int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result) 1019{ 1020 struct nl_cache * cache; 1021 int err; 1022 1023 cache = nl_cache_alloc(&rtnl_link_ops); 1024 if (!cache) 1025 return -NLE_NOMEM; 1026 1027 cache->c_iarg1 = family; 1028 1029 if (sk && (err = nl_cache_refill(sk, cache)) < 0) { 1030 nl_cache_free(cache); 1031 return err; 1032 } 1033 1034 *result = cache; 1035 return 0; 1036} 1037 1038/** 1039 * Lookup link in cache by interface index 1040 * @arg cache Link cache 1041 * @arg ifindex Interface index 1042 * 1043 * Searches through the provided cache looking for a link with matching 1044 * interface index. 1045 * 1046 * @attention The reference counter of the returned link object will be 1047 * incremented. Use rtnl_link_put() to release the reference. 1048 * 1049 * @route_doc{link_list, Get List of Links} 1050 * @see rtnl_link_get_by_name() 1051 * @return Link object or NULL if no match was found. 1052 */ 1053struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex) 1054{ 1055 struct rtnl_link *link; 1056 1057 if (cache->c_ops != &rtnl_link_ops) 1058 return NULL; 1059 1060 nl_list_for_each_entry(link, &cache->c_items, ce_list) { 1061 if (link->l_index == ifindex) { 1062 nl_object_get((struct nl_object *) link); 1063 return link; 1064 } 1065 } 1066 1067 return NULL; 1068} 1069 1070/** 1071 * Lookup link in cache by link name 1072 * @arg cache Link cache 1073 * @arg name Name of link 1074 * 1075 * Searches through the provided cache looking for a link with matching 1076 * link name 1077 * 1078 * @attention The reference counter of the returned link object will be 1079 * incremented. Use rtnl_link_put() to release the reference. 1080 * 1081 * @route_doc{link_list, Get List of Links} 1082 * @see rtnl_link_get() 1083 * @return Link object or NULL if no match was found. 1084 */ 1085struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, 1086 const char *name) 1087{ 1088 struct rtnl_link *link; 1089 1090 if (cache->c_ops != &rtnl_link_ops) 1091 return NULL; 1092 1093 nl_list_for_each_entry(link, &cache->c_items, ce_list) { 1094 if (!strcmp(name, link->l_name)) { 1095 nl_object_get((struct nl_object *) link); 1096 return link; 1097 } 1098 } 1099 1100 return NULL; 1101} 1102 1103/** 1104 * Construct RTM_GETLINK netlink message 1105 * @arg ifindex Interface index 1106 * @arg name Name of link 1107 * @arg result Pointer to store resulting netlink message 1108 * 1109 * The behaviour of this function is identical to rtnl_link_get_kernel() 1110 * with the exception that it will not send the message but return it in 1111 * the provided return pointer instead. 1112 * 1113 * @see rtnl_link_get_kernel() 1114 * 1115 * @return 0 on success or a negative error code. 1116 */ 1117int rtnl_link_build_get_request(int ifindex, const char *name, 1118 struct nl_msg **result) 1119{ 1120 struct ifinfomsg ifi; 1121 struct nl_msg *msg; 1122 1123 if (ifindex <= 0 && !name) { 1124 APPBUG("ifindex or name must be specified"); 1125 return -NLE_MISSING_ATTR; 1126 } 1127 1128 memset(&ifi, 0, sizeof(ifi)); 1129 1130 if (!(msg = nlmsg_alloc_simple(RTM_GETLINK, 0))) 1131 return -NLE_NOMEM; 1132 1133 if (ifindex > 0) 1134 ifi.ifi_index = ifindex; 1135 1136 if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) 1137 goto nla_put_failure; 1138 1139 if (name) 1140 NLA_PUT_STRING(msg, IFLA_IFNAME, name); 1141 1142 *result = msg; 1143 return 0; 1144 1145nla_put_failure: 1146 nlmsg_free(msg); 1147 return -NLE_MSGSIZE; 1148} 1149 1150/** 1151 * Get a link object directly from kernel 1152 * @arg sk Netlink socket 1153 * @arg ifindex Interface index 1154 * @arg name Name of link 1155 * @arg result Pointer to store resulting link object 1156 * 1157 * This function builds a \c RTM_GETLINK netlink message to request 1158 * a specific link directly from the kernel. The returned answer is 1159 * parsed into a struct rtnl_link object and returned via the result 1160 * pointer or -NLE_OBJ_NOTFOUND is returned if no matching link was 1161 * found. 1162 * 1163 * @route_doc{link_direct_lookup, Lookup Single Link (Direct Lookup)} 1164 * @return 0 on success or a negative error code. 1165 */ 1166int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, 1167 struct rtnl_link **result) 1168{ 1169 struct nl_msg *msg = NULL; 1170 struct nl_object *obj; 1171 int err; 1172 1173 if ((err = rtnl_link_build_get_request(ifindex, name, &msg)) < 0) 1174 return err; 1175 1176 err = nl_send_auto(sk, msg); 1177 nlmsg_free(msg); 1178 if (err < 0) 1179 return err; 1180 1181 if ((err = nl_pickup(sk, link_msg_parser, &obj)) < 0) 1182 return err; 1183 1184 /* We have used link_msg_parser(), object is definitely a link */ 1185 *result = (struct rtnl_link *) obj; 1186 1187 /* If an object has been returned, we also need to wait for the ACK */ 1188 if (err == 0 && obj) 1189 wait_for_ack(sk); 1190 1191 return 0; 1192} 1193 1194/** 1195 * Translate interface index to corresponding link name 1196 * @arg cache Link cache 1197 * @arg ifindex Interface index 1198 * @arg dst String to store name 1199 * @arg len Length of destination string 1200 * 1201 * Translates the specified interface index to the corresponding 1202 * link name and stores the name in the destination string. 1203 * 1204 * @route_doc{link_translate_ifindex, Translating interface index to link name} 1205 * @see rtnl_link_name2i() 1206 * @return Name of link or NULL if no match was found. 1207 */ 1208char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, 1209 size_t len) 1210{ 1211 struct rtnl_link *link = rtnl_link_get(cache, ifindex); 1212 1213 if (link) { 1214 strncpy(dst, link->l_name, len - 1); 1215 rtnl_link_put(link); 1216 return dst; 1217 } 1218 1219 return NULL; 1220} 1221 1222/** 1223 * Translate link name to corresponding interface index 1224 * @arg cache Link cache 1225 * @arg name Name of link 1226 * 1227 * @route_doc{link_translate_ifindex, Translating interface index to link name} 1228 * @see rtnl_link_i2name() 1229 * @return Interface index or 0 if no match was found. 1230 */ 1231int rtnl_link_name2i(struct nl_cache *cache, const char *name) 1232{ 1233 int ifindex = 0; 1234 struct rtnl_link *link; 1235 1236 link = rtnl_link_get_by_name(cache, name); 1237 if (link) { 1238 ifindex = link->l_index; 1239 rtnl_link_put(link); 1240 } 1241 1242 return ifindex; 1243} 1244 1245/** @} */ 1246 1247int rtnl_link_fill_info(struct nl_msg *msg, struct rtnl_link *link) 1248{ 1249 if (link->ce_mask & LINK_ATTR_ADDR) 1250 NLA_PUT_ADDR(msg, IFLA_ADDRESS, link->l_addr); 1251 1252 if (link->ce_mask & LINK_ATTR_BRD) 1253 NLA_PUT_ADDR(msg, IFLA_BROADCAST, link->l_bcast); 1254 1255 if (link->ce_mask & LINK_ATTR_MTU) 1256 NLA_PUT_U32(msg, IFLA_MTU, link->l_mtu); 1257 1258 if (link->ce_mask & LINK_ATTR_TXQLEN) 1259 NLA_PUT_U32(msg, IFLA_TXQLEN, link->l_txqlen); 1260 1261 if (link->ce_mask & LINK_ATTR_WEIGHT) 1262 NLA_PUT_U32(msg, IFLA_WEIGHT, link->l_weight); 1263 1264 if (link->ce_mask & LINK_ATTR_IFNAME) 1265 NLA_PUT_STRING(msg, IFLA_IFNAME, link->l_name); 1266 1267 if (link->ce_mask & LINK_ATTR_OPERSTATE) 1268 NLA_PUT_U8(msg, IFLA_OPERSTATE, link->l_operstate); 1269 1270 if (link->ce_mask & LINK_ATTR_CARRIER) 1271 NLA_PUT_U8(msg, IFLA_CARRIER, link->l_carrier); 1272 1273 if (link->ce_mask & LINK_ATTR_LINKMODE) 1274 NLA_PUT_U8(msg, IFLA_LINKMODE, link->l_linkmode); 1275 1276 if (link->ce_mask & LINK_ATTR_IFALIAS) 1277 NLA_PUT_STRING(msg, IFLA_IFALIAS, link->l_ifalias); 1278 1279 if (link->ce_mask & LINK_ATTR_LINK) 1280 NLA_PUT_U32(msg, IFLA_LINK, link->l_link); 1281 1282 if (link->ce_mask & LINK_ATTR_MASTER) 1283 NLA_PUT_U32(msg, IFLA_MASTER, link->l_master); 1284 1285 if (link->ce_mask & LINK_ATTR_NUM_TX_QUEUES) 1286 NLA_PUT_U32(msg, IFLA_NUM_TX_QUEUES, link->l_num_tx_queues); 1287 1288 if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES) 1289 NLA_PUT_U32(msg, IFLA_NUM_RX_QUEUES, link->l_num_rx_queues); 1290 1291 if (link->ce_mask & LINK_ATTR_NS_FD) 1292 NLA_PUT_U32(msg, IFLA_NET_NS_FD, link->l_ns_fd); 1293 1294 if (link->ce_mask & LINK_ATTR_NS_PID) 1295 NLA_PUT_U32(msg, IFLA_NET_NS_PID, link->l_ns_pid); 1296 1297 return 0; 1298 1299nla_put_failure: 1300 return -NLE_MSGSIZE; 1301} 1302 1303static int build_link_msg(int cmd, struct ifinfomsg *hdr, 1304 struct rtnl_link *link, int flags, struct nl_msg **result) 1305{ 1306 struct nl_msg *msg; 1307 struct nlattr *af_spec; 1308 1309 msg = nlmsg_alloc_simple(cmd, flags); 1310 if (!msg) 1311 return -NLE_NOMEM; 1312 1313 if (nlmsg_append(msg, hdr, sizeof(*hdr), NLMSG_ALIGNTO) < 0) 1314 goto nla_put_failure; 1315 1316 if (rtnl_link_fill_info(msg, link)) 1317 goto nla_put_failure; 1318 1319 if (link->ce_mask & LINK_ATTR_GROUP) 1320 NLA_PUT_U32(msg, IFLA_GROUP, link->l_group); 1321 1322 if (link->ce_mask & LINK_ATTR_LINKINFO) { 1323 struct nlattr *info; 1324 1325 if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) 1326 goto nla_put_failure; 1327 1328 NLA_PUT_STRING(msg, IFLA_INFO_KIND, link->l_info_kind); 1329 1330 if (link->l_info_ops) { 1331 if (link->l_info_ops->io_put_attrs && 1332 link->l_info_ops->io_put_attrs(msg, link) < 0) 1333 goto nla_put_failure; 1334 } 1335 1336 nla_nest_end(msg, info); 1337 } 1338 1339 if (!(af_spec = nla_nest_start(msg, IFLA_AF_SPEC))) 1340 goto nla_put_failure; 1341 1342 if (do_foreach_af(link, af_fill, msg) < 0) 1343 goto nla_put_failure; 1344 1345 nla_nest_end(msg, af_spec); 1346 1347 *result = msg; 1348 return 0; 1349 1350nla_put_failure: 1351 nlmsg_free(msg); 1352 return -NLE_MSGSIZE; 1353} 1354 1355/** 1356 * @name Add / Modify 1357 * @{ 1358 */ 1359 1360/** 1361 * Build a netlink message requesting the addition of new virtual link 1362 * @arg link new link to add 1363 * @arg flags additional netlink message flags 1364 * @arg result pointer to store resulting netlink message 1365 * 1366 * The behaviour of this function is identical to rtnl_link_add() with 1367 * the exception that it will not send the message but return it in the 1368 * provided return pointer instead. 1369 * 1370 * @see rtnl_link_add() 1371 * 1372 * @note This operation is not supported on all kernel versions. 1373 * 1374 * @return 0 on success or a negative error code. 1375 */ 1376int rtnl_link_build_add_request(struct rtnl_link *link, int flags, 1377 struct nl_msg **result) 1378{ 1379 struct ifinfomsg ifi = { 1380 .ifi_family = link->l_family, 1381 .ifi_index = link->l_index, 1382 .ifi_flags = link->l_flags, 1383 }; 1384 1385 return build_link_msg(RTM_NEWLINK, &ifi, link, flags, result); 1386} 1387 1388/** 1389 * Add virtual link 1390 * @arg sk netlink socket. 1391 * @arg link new link to add 1392 * @arg flags additional netlink message flags 1393 * 1394 * Builds a \c RTM_NEWLINK netlink message requesting the addition of 1395 * a new virtual link. 1396 * 1397 * After sending, the function will wait for the ACK or an eventual 1398 * error message to be received and will therefore block until the 1399 * operation has been completed. 1400 * 1401 * @copydoc auto_ack_warning 1402 * 1403 * @return 0 on success or a negative error code. 1404 */ 1405int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags) 1406{ 1407 struct nl_msg *msg; 1408 int err; 1409 1410 err = rtnl_link_build_add_request(link, flags, &msg); 1411 if (err < 0) 1412 return err; 1413 1414 return nl_send_sync(sk, msg); 1415} 1416 1417/** 1418 * Build a netlink message requesting the modification of link 1419 * @arg orig original link to change 1420 * @arg changes link containing the changes to be made 1421 * @arg flags additional netlink message flags 1422 * @arg result pointer to store resulting netlink message 1423 * 1424 * The behaviour of this function is identical to rtnl_link_change() with 1425 * the exception that it will not send the message but return it in the 1426 * provided return pointer instead. 1427 * 1428 * @see rtnl_link_change() 1429 * 1430 * @note The resulting message will have message type set to RTM_NEWLINK 1431 * which may not work with older kernels. You may have to modify it 1432 * to RTM_SETLINK (does not allow changing link info attributes) to 1433 * have the change request work with older kernels. 1434 * 1435 * @return 0 on success or a negative error code. 1436 */ 1437int rtnl_link_build_change_request(struct rtnl_link *orig, 1438 struct rtnl_link *changes, int flags, 1439 struct nl_msg **result) 1440{ 1441 struct ifinfomsg ifi = { 1442 .ifi_family = orig->l_family, 1443 .ifi_index = orig->l_index, 1444 }; 1445 int err; 1446 1447 if (changes->ce_mask & LINK_ATTR_FLAGS) { 1448 ifi.ifi_flags = orig->l_flags & ~changes->l_flag_mask; 1449 ifi.ifi_flags |= changes->l_flags; 1450 } 1451 1452 if (changes->l_family && changes->l_family != orig->l_family) { 1453 APPBUG("link change: family is immutable"); 1454 return -NLE_IMMUTABLE; 1455 } 1456 1457 /* Avoid unnecessary name change requests */ 1458 if (orig->ce_mask & LINK_ATTR_IFINDEX && 1459 orig->ce_mask & LINK_ATTR_IFNAME && 1460 changes->ce_mask & LINK_ATTR_IFNAME && 1461 !strcmp(orig->l_name, changes->l_name)) 1462 changes->ce_mask &= ~LINK_ATTR_IFNAME; 1463 1464 if ((err = build_link_msg(RTM_NEWLINK, &ifi, changes, flags, result)) < 0) 1465 goto errout; 1466 1467 return 0; 1468 1469errout: 1470 return err; 1471} 1472 1473/** 1474 * Change link 1475 * @arg sk netlink socket. 1476 * @arg orig original link to be changed 1477 * @arg changes link containing the changes to be made 1478 * @arg flags additional netlink message flags 1479 * 1480 * Builds a \c RTM_NEWLINK netlink message requesting the change of 1481 * a network link. If -EOPNOTSUPP is returned by the kernel, the 1482 * message type will be changed to \c RTM_SETLINK and the message is 1483 * resent to work around older kernel versions. 1484 * 1485 * The link to be changed is looked up based on the interface index 1486 * supplied in the \p orig link. Optionaly the link name is used but 1487 * only if no interface index is provided, otherwise providing an 1488 * link name will result in the link name being changed. 1489 * 1490 * If no matching link exists, the function will return 1491 * -NLE_OBJ_NOTFOUND. 1492 * 1493 * After sending, the function will wait for the ACK or an eventual 1494 * error message to be received and will therefore block until the 1495 * operation has been completed. 1496 * 1497 * @copydoc auto_ack_warning 1498 * 1499 * @note The link name can only be changed if the link has been put 1500 * in opertional down state. (~IF_UP) 1501 * 1502 * @return 0 on success or a negative error code. 1503 */ 1504int rtnl_link_change(struct nl_sock *sk, struct rtnl_link *orig, 1505 struct rtnl_link *changes, int flags) 1506{ 1507 struct nl_msg *msg; 1508 int err; 1509 1510 err = rtnl_link_build_change_request(orig, changes, flags, &msg); 1511 if (err < 0) 1512 return err; 1513 1514retry: 1515 err = nl_send_auto_complete(sk, msg); 1516 if (err < 0) 1517 goto errout; 1518 1519 err = wait_for_ack(sk); 1520 if (err == -NLE_OPNOTSUPP && msg->nm_nlh->nlmsg_type == RTM_NEWLINK) { 1521 msg->nm_nlh->nlmsg_type = RTM_SETLINK; 1522 goto retry; 1523 } 1524 1525errout: 1526 nlmsg_free(msg); 1527 return err; 1528} 1529 1530/** @} */ 1531 1532/** 1533 * @name Delete 1534 * @{ 1535 */ 1536 1537/** 1538 * Build a netlink message requesting the deletion of a link 1539 * @arg link Link to delete 1540 * @arg result Pointer to store resulting netlink message 1541 * 1542 * The behaviour of this function is identical to rtnl_link_delete() with 1543 * the exception that it will not send the message but return it in the 1544 * provided return pointer instead. 1545 * 1546 * @see rtnl_link_delete() 1547 * 1548 * @return 0 on success or a negative error code. 1549 */ 1550int rtnl_link_build_delete_request(const struct rtnl_link *link, 1551 struct nl_msg **result) 1552{ 1553 struct nl_msg *msg; 1554 struct ifinfomsg ifi = { 1555 .ifi_index = link->l_index, 1556 }; 1557 1558 if (!(link->ce_mask & (LINK_ATTR_IFINDEX | LINK_ATTR_IFNAME))) { 1559 APPBUG("ifindex or name must be specified"); 1560 return -NLE_MISSING_ATTR; 1561 } 1562 1563 if (!(msg = nlmsg_alloc_simple(RTM_DELLINK, 0))) 1564 return -NLE_NOMEM; 1565 1566 if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) 1567 goto nla_put_failure; 1568 1569 if (link->ce_mask & LINK_ATTR_IFNAME) 1570 NLA_PUT_STRING(msg, IFLA_IFNAME, link->l_name); 1571 1572 *result = msg; 1573 return 0; 1574 1575nla_put_failure: 1576 nlmsg_free(msg); 1577 return -NLE_MSGSIZE; 1578} 1579 1580/** 1581 * Delete link 1582 * @arg sk Netlink socket 1583 * @arg link Link to delete 1584 * 1585 * Builds a \c RTM_DELLINK netlink message requesting the deletion of 1586 * a network link which has been previously added to the kernel and 1587 * sends the message to the kernel. 1588 * 1589 * If no matching link exists, the function will return 1590 * -NLE_OBJ_NOTFOUND. 1591 * 1592 * After sending, the function will wait for the ACK or an eventual 1593 * error message to be received and will therefore block until the 1594 * operation has been completed. 1595 * 1596 * @copydoc auto_ack_warning 1597 * 1598 * @note Only virtual links such as dummy interface or vlan interfaces 1599 * can be deleted. It is not possible to delete physical interfaces 1600 * such as ethernet interfaces or the loopback device. 1601 * 1602 * @return 0 on success or a negative error code. 1603 */ 1604int rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *link) 1605{ 1606 struct nl_msg *msg; 1607 int err; 1608 1609 if ((err = rtnl_link_build_delete_request(link, &msg)) < 0) 1610 return err; 1611 1612 return nl_send_sync(sk, msg); 1613} 1614 1615/** @} */ 1616 1617/** 1618 * @name Link Object 1619 * @{ 1620 */ 1621 1622/** 1623 * Allocate link object 1624 * 1625 * @see rtnl_link_put() 1626 * @return New link object or NULL if allocation failed 1627 */ 1628struct rtnl_link *rtnl_link_alloc(void) 1629{ 1630 return (struct rtnl_link *) nl_object_alloc(&link_obj_ops); 1631} 1632 1633/** 1634 * Return a link object reference 1635 * @arg link Link object 1636 */ 1637void rtnl_link_put(struct rtnl_link *link) 1638{ 1639 nl_object_put((struct nl_object *) link); 1640} 1641 1642/** 1643 * Set name of link object 1644 * @arg link Link object 1645 * @arg name New name 1646 * 1647 * @note To change the name of a link in the kernel, set the interface 1648 * index to the link you wish to change, modify the link name using 1649 * this function and pass the link object to rtnl_link_change() or 1650 * rtnl_link_add(). 1651 * 1652 * @route_doc{link_attr_name, Link Name} 1653 * @see rtnl_link_get_name() 1654 * @see rtnl_link_set_ifindex() 1655 */ 1656void rtnl_link_set_name(struct rtnl_link *link, const char *name) 1657{ 1658 strncpy(link->l_name, name, sizeof(link->l_name) - 1); 1659 link->ce_mask |= LINK_ATTR_IFNAME; 1660} 1661 1662/** 1663 * Return name of link object 1664 * @arg link Link object 1665 * 1666 * @route_doc{link_attr_name, Link Name} 1667 * @see rtnl_link_set_name() 1668 * @return Link name or NULL if name is not specified 1669 */ 1670char *rtnl_link_get_name(struct rtnl_link *link) 1671{ 1672 return link->ce_mask & LINK_ATTR_IFNAME ? link->l_name : NULL; 1673} 1674 1675/** 1676 * Set the group identifier of a link object 1677 * @arg link Link object 1678 * @arg group Group identifier 1679 */ 1680void rtnl_link_set_group(struct rtnl_link *link, uint32_t group) 1681{ 1682 link->l_group = group; 1683 link->ce_mask |= LINK_ATTR_GROUP; 1684} 1685 1686/** 1687 * Return the group identifier of link object 1688 * @arg link Link object 1689 * 1690 * @return Group identifier or 0 if not set. 1691 */ 1692uint32_t rtnl_link_get_group(struct rtnl_link *link) 1693{ 1694 return link->l_group; 1695} 1696 1697static inline void __assign_addr(struct rtnl_link *link, struct nl_addr **pos, 1698 struct nl_addr *new, int flag) 1699{ 1700 if (*pos) 1701 nl_addr_put(*pos); 1702 1703 nl_addr_get(new); 1704 *pos = new; 1705 1706 link->ce_mask |= flag; 1707} 1708 1709/** 1710 * Set link layer address of link object 1711 * @arg link Link object 1712 * @arg addr New link layer address 1713 * 1714 * The function increments the reference counter of the address object 1715 * and overwrites any existing link layer address previously assigned. 1716 * 1717 * @route_doc{link_attr_address, Link layer address} 1718 * @see rtnl_link_get_addr() 1719 */ 1720void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr) 1721{ 1722 __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR); 1723} 1724 1725/** 1726 * Return link layer address of link object 1727 * @arg link Link object 1728 * 1729 * @copydoc pointer_lifetime_warning 1730 * @route_doc{link_attr_address, Link Layer Address} 1731 * @see rtnl_link_set_addr() 1732 * @return Link layer address or NULL if not set. 1733 */ 1734struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link) 1735{ 1736 return link->ce_mask & LINK_ATTR_ADDR ? link->l_addr : NULL; 1737} 1738 1739/** 1740 * Set link layer broadcast address of link object 1741 * @arg link Link object 1742 * @arg addr New broadcast address 1743 * 1744 * The function increments the reference counter of the address object 1745 * and overwrites any existing link layer broadcast address previously 1746 * assigned. 1747 * 1748 * @route_doc{link_attr_broadcast, Link Layer Broadcast Address} 1749 * @see rtnl_link_get_broadcast() 1750 */ 1751void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *addr) 1752{ 1753 __assign_addr(link, &link->l_bcast, addr, LINK_ATTR_BRD); 1754} 1755 1756/** 1757 * Return link layer broadcast address of link object 1758 * @arg link Link object 1759 * 1760 * @copydoc pointer_lifetime_warning 1761 * @route_doc{link_attr_address, Link Layer Address} 1762 * @see rtnl_link_set_broadcast() 1763 * @return Link layer address or NULL if not set. 1764 */ 1765struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link) 1766{ 1767 return link->ce_mask & LINK_ATTR_BRD ? link->l_bcast : NULL; 1768} 1769 1770/** 1771 * Set flags of link object 1772 * @arg link Link object 1773 * @arg flags Flags 1774 * 1775 * @see rtnl_link_get_flags() 1776 * @see rtnl_link_unset_flags() 1777 */ 1778void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags) 1779{ 1780 link->l_flag_mask |= flags; 1781 link->l_flags |= flags; 1782 link->ce_mask |= LINK_ATTR_FLAGS; 1783} 1784 1785/** 1786 * Unset flags of link object 1787 * @arg link Link object 1788 * @arg flags Flags 1789 * 1790 * @see rtnl_link_set_flags() 1791 * @see rtnl_link_get_flags() 1792 */ 1793void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags) 1794{ 1795 link->l_flag_mask |= flags; 1796 link->l_flags &= ~flags; 1797 link->ce_mask |= LINK_ATTR_FLAGS; 1798} 1799 1800/** 1801 * Return flags of link object 1802 * @arg link Link object 1803 * 1804 * @route_doc{link_attr_flags, Link Flags} 1805 * @see rtnl_link_set_flags() 1806 * @see rtnl_link_unset_flags() 1807 * @return Link flags or 0 if none have been set. 1808 */ 1809unsigned int rtnl_link_get_flags(struct rtnl_link *link) 1810{ 1811 return link->l_flags; 1812} 1813 1814/** 1815 * Set address family of link object 1816 * 1817 * @see rtnl_link_get_family() 1818 */ 1819void rtnl_link_set_family(struct rtnl_link *link, int family) 1820{ 1821 link->l_family = family; 1822 link->ce_mask |= LINK_ATTR_FAMILY; 1823 1824 if (link->l_af_ops) { 1825 af_free(link, link->l_af_ops, 1826 link->l_af_data[link->l_af_ops->ao_family], NULL); 1827 link->l_af_data[link->l_af_ops->ao_family] = NULL; 1828 } 1829 1830 link->l_af_ops = af_lookup_and_alloc(link, family); 1831} 1832 1833/** 1834 * Return address family of link object 1835 * @arg link Link object 1836 * 1837 * @see rtnl_link_set_family() 1838 * @return Address family or \c AF_UNSPEC if not specified. 1839 */ 1840int rtnl_link_get_family(struct rtnl_link *link) 1841{ 1842 return link->ce_mask & LINK_ATTR_FAMILY ? link->l_family : AF_UNSPEC; 1843} 1844 1845/** 1846 * Set hardware type of link object 1847 * @arg link Link object 1848 * @arg arptype New hardware type \c (ARPHRD_*) 1849 * 1850 * @route_doc{link_attr_arptype, Hardware Type} 1851 * @copydoc read_only_attribute 1852 * @see rtnl_link_get_arptype() 1853 */ 1854void rtnl_link_set_arptype(struct rtnl_link *link, unsigned int arptype) 1855{ 1856 link->l_arptype = arptype; 1857 link->ce_mask |= LINK_ATTR_ARPTYPE; 1858} 1859 1860/** 1861 * Get hardware type of link object 1862 * @arg link Link object 1863 * 1864 * @route_doc{link_attr_arptype, Hardware Type} 1865 * @see rtnl_link_set_arptype() 1866 * @return Hardware type \c (ARPHRD_ETHER *) or \c ARPHRD_VOID 1867 */ 1868unsigned int rtnl_link_get_arptype(struct rtnl_link *link) 1869{ 1870 if (link->ce_mask & LINK_ATTR_ARPTYPE) 1871 return link->l_arptype; 1872 else 1873 return ARPHRD_VOID; 1874} 1875 1876/** 1877 * Set interface index of link object 1878 * @arg link Link object 1879 * @arg ifindex Interface index 1880 * 1881 * @route_doc{link_attr_ifindex, Interface Index} 1882 * @see rtnl_link_get_ifindex() 1883 */ 1884void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex) 1885{ 1886 link->l_index = ifindex; 1887 link->ce_mask |= LINK_ATTR_IFINDEX; 1888} 1889 1890 1891/** 1892 * Return interface index of link object 1893 * @arg link Link object 1894 * 1895 * @route_doc{link_attr_ifindex, Interface Index} 1896 * @see rtnl_link_set_ifindex() 1897 * @return Interface index or 0 if not set. 1898 */ 1899int rtnl_link_get_ifindex(struct rtnl_link *link) 1900{ 1901 return link->l_index; 1902} 1903 1904/** 1905 * Set Maximum Transmission Unit of link object 1906 * @arg link Link object 1907 * @arg mtu New MTU value in number of bytes 1908 * 1909 * @route_doc{link_attr_mtu, Maximum Transmission Unit} 1910 * @see rtnl_link_get_mtu() 1911 */ 1912void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu) 1913{ 1914 link->l_mtu = mtu; 1915 link->ce_mask |= LINK_ATTR_MTU; 1916} 1917 1918/** 1919 * Return maximum transmission unit of link object 1920 * @arg link Link object 1921 * 1922 * @route_doc{link_attr_mtu, Maximum Transmission Unit} 1923 * @see rtnl_link_set_mtu() 1924 * @return MTU in bytes or 0 if not set 1925 */ 1926unsigned int rtnl_link_get_mtu(struct rtnl_link *link) 1927{ 1928 return link->l_mtu; 1929} 1930 1931/** 1932 * Set transmission queue length 1933 * @arg link Link object 1934 * @arg txqlen New queue length 1935 * 1936 * The unit is dependant on the link type. The most common units is number 1937 * of packets. 1938 * 1939 * @route_doc{link_attr_txqlen, Transmission Queue Length} 1940 */ 1941void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen) 1942{ 1943 link->l_txqlen = txqlen; 1944 link->ce_mask |= LINK_ATTR_TXQLEN; 1945} 1946 1947/** 1948 * Return transmission queue length 1949 * @arg link Link object 1950 * 1951 * The unit is dependant on the link type. The most common units is number 1952 * of packets. 1953 * 1954 * @route_doc{link_attr_txqlen, Transmission Queue Length} 1955 * @return queue length or 0 if not specified. 1956 */ 1957unsigned int rtnl_link_get_txqlen(struct rtnl_link *link) 1958{ 1959 return link->ce_mask & LINK_ATTR_TXQLEN ? link->l_txqlen : 0; 1960} 1961 1962void rtnl_link_set_link(struct rtnl_link *link, int ifindex) 1963{ 1964 link->l_link = ifindex; 1965 link->ce_mask |= LINK_ATTR_LINK; 1966} 1967 1968int rtnl_link_get_link(struct rtnl_link *link) 1969{ 1970 return link->l_link; 1971} 1972 1973/** 1974 * Set master link of link object 1975 * @arg link Link object 1976 * @arg ifindex Interface index of master link 1977 * 1978 * @see rtnl_link_get_master() 1979 */ 1980void rtnl_link_set_master(struct rtnl_link *link, int ifindex) 1981{ 1982 link->l_master = ifindex; 1983 link->ce_mask |= LINK_ATTR_MASTER; 1984} 1985 1986/** 1987 * Return master link of link object 1988 * @arg link Link object 1989 * 1990 * @see rtnl_link_set_master() 1991 * @return Interface index of master link or 0 if not specified 1992 */ 1993int rtnl_link_get_master(struct rtnl_link *link) 1994{ 1995 return link->l_master; 1996} 1997 1998/** 1999 * Set carrier of link object 2000 * @arg link Link object 2001 * @arg status New carrier status 2002 * 2003 * @see rtnl_link_get_carrier() 2004 */ 2005void rtnl_link_set_carrier(struct rtnl_link *link, uint8_t status) 2006{ 2007 link->l_carrier = status; 2008 link->ce_mask |= LINK_ATTR_CARRIER; 2009} 2010 2011/** 2012 * Return carrier status of link object 2013 * @arg link Link object 2014 * 2015 * @see rtnl_link_set_master() 2016 * @return Carrier state. 2017 */ 2018uint8_t rtnl_link_get_carrier(struct rtnl_link *link) 2019{ 2020 return link->l_carrier; 2021} 2022 2023/** 2024 * Set operational status of link object 2025 * @arg link Link object 2026 * @arg status New opertional status 2027 * 2028 * @route_doc{link_attr_operstate, Operational Status}} 2029 * @see rtnl_link_get_operstate() 2030 */ 2031void rtnl_link_set_operstate(struct rtnl_link *link, uint8_t status) 2032{ 2033 link->l_operstate = status; 2034 link->ce_mask |= LINK_ATTR_OPERSTATE; 2035} 2036 2037/** 2038 * Return operational status of link object 2039 * @arg link Link object 2040 * 2041 * @route_doc{link_attr_operstate, Operational Status} 2042 * @see rtnl_link_set_operstate() 2043 * @return Opertional state or \c IF_OPER_UNKNOWN 2044 */ 2045uint8_t rtnl_link_get_operstate(struct rtnl_link *link) 2046{ 2047 return link->l_operstate; 2048} 2049 2050/** 2051 * Set link mode of link object 2052 * @arg link Link object 2053 * @arg mode New link mode 2054 * 2055 * @route_doc{link_attr_mode, Mode} 2056 * @see rtnl_link_get_linkmode() 2057 */ 2058void rtnl_link_set_linkmode(struct rtnl_link *link, uint8_t mode) 2059{ 2060 link->l_linkmode = mode; 2061 link->ce_mask |= LINK_ATTR_LINKMODE; 2062} 2063 2064/** 2065 * Return link mode of link object 2066 * @arg link Link object 2067 * 2068 * @route_doc{link_attr_mode, Mode} 2069 * @see rtnl_link_get_linkmode() 2070 * @return Link mode or \c IF_LINK_MODE_DEFAULT 2071 */ 2072uint8_t rtnl_link_get_linkmode(struct rtnl_link *link) 2073{ 2074 return link->l_linkmode; 2075} 2076 2077/** 2078 * Return alias name of link object (SNMP IfAlias) 2079 * @arg link Link object 2080 * 2081 * @route_doc{link_attr_alias, Alias} 2082 * @see rtnl_link_set_ifalias() 2083 * @return Alias name or NULL if not set. 2084 */ 2085const char *rtnl_link_get_ifalias(struct rtnl_link *link) 2086{ 2087 return link->l_ifalias; 2088} 2089 2090/** 2091 * Set alias name of link object (SNMP IfAlias) 2092 * @arg link Link object 2093 * @arg alias Alias name or NULL to unset 2094 * 2095 * Sets the alias name of the link to the specified name. The alias 2096 * name can be unset by specyfing NULL as the alias. The name will 2097 * be strdup()ed, so no need to provide a persistent character string. 2098 * 2099 * @route_doc{link_attr_alias, Alias} 2100 * @see rtnl_link_get_ifalias() 2101 */ 2102void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias) 2103{ 2104 free(link->l_ifalias); 2105 2106 if (alias) { 2107 link->l_ifalias = strdup(alias); 2108 link->ce_mask |= LINK_ATTR_IFALIAS; 2109 } else { 2110 link->l_ifalias = NULL; 2111 link->ce_mask &= ~LINK_ATTR_IFALIAS; 2112 } 2113} 2114 2115/** 2116 * Set queueing discipline name of link object 2117 * @arg link Link object 2118 * @arg name Name of queueing discipline 2119 * 2120 * @copydoc read_only_attribute 2121 * 2122 * For more information on how to modify the qdisc of a link, see section 2123 * @ref_route{route_tc, Traffic Control}. 2124 * 2125 * @route_doc{link_attr_qdisc, Queueing Discipline Name} 2126 * @see rtnl_link_get_qdisc() 2127 */ 2128void rtnl_link_set_qdisc(struct rtnl_link *link, const char *name) 2129{ 2130 strncpy(link->l_qdisc, name, sizeof(link->l_qdisc) - 1); 2131 link->ce_mask |= LINK_ATTR_QDISC; 2132} 2133 2134/** 2135 * Return name of queueing discipline of link object 2136 * @arg link Link object 2137 * 2138 * @route_doc{link_attr_qdisc, Queueing Discipline Name} 2139 * @see rtnl_link_set_qdisc() 2140 * @return Name of qdisc or NULL if not specified. 2141 */ 2142char *rtnl_link_get_qdisc(struct rtnl_link *link) 2143{ 2144 return link->ce_mask & LINK_ATTR_QDISC ? link->l_qdisc : NULL; 2145} 2146 2147 2148/** 2149 * Return number of PCI virtual functions of link object 2150 * @arg link Link object 2151 * @arg num_vf Pointer to store number of VFs 2152 * 2153 * @return 0 on success or -NLE_OPNOTSUPP if not available 2154 */ 2155int rtnl_link_get_num_vf(struct rtnl_link *link, uint32_t *num_vf) 2156{ 2157 if (link->ce_mask & LINK_ATTR_NUM_VF) { 2158 *num_vf = link->l_num_vf; 2159 return 0; 2160 } else 2161 return -NLE_OPNOTSUPP; 2162} 2163 2164/** 2165 * Return value of link statistics counter 2166 * @arg link Link object 2167 * @arg id Identifier of statistical counter 2168 * 2169 * @return Value of counter or 0 if not specified. 2170 */ 2171uint64_t rtnl_link_get_stat(struct rtnl_link *link, rtnl_link_stat_id_t id) 2172{ 2173 if (id > RTNL_LINK_STATS_MAX) 2174 return 0; 2175 2176 return link->l_stats[id]; 2177} 2178 2179/** 2180 * Set value of link statistics counter 2181 * @arg link Link object 2182 * @arg id Identifier of statistical counter 2183 * @arg value New value 2184 * 2185 * \note Changing the value of a statistical counter will not change the 2186 * value in the kernel. 2187 * 2188 * @return 0 on success or a negative error code 2189 */ 2190int rtnl_link_set_stat(struct rtnl_link *link, rtnl_link_stat_id_t id, 2191 const uint64_t value) 2192{ 2193 if (id > RTNL_LINK_STATS_MAX) 2194 return -NLE_INVAL; 2195 2196 link->l_stats[id] = value; 2197 2198 return 0; 2199} 2200 2201/** 2202 * Set type of link object 2203 * @arg link Link object 2204 * @arg type Name of link type 2205 * 2206 * Looks up the link type module and prepares the link to store type 2207 * specific attributes. If a type has been assigned already it will 2208 * be released with all link type specific attributes lost. 2209 * 2210 * @route_doc{link_modules, Link Modules} 2211 * @return 0 on success or a negative errror code. 2212 */ 2213int rtnl_link_set_type(struct rtnl_link *link, const char *type) 2214{ 2215 struct rtnl_link_info_ops *io; 2216 int err; 2217 char *kind; 2218 2219 free(link->l_info_kind); 2220 link->ce_mask &= ~LINK_ATTR_LINKINFO; 2221 if (link->l_info_ops) 2222 release_link_info(link); 2223 2224 if (!type) 2225 return 0; 2226 2227 kind = strdup(type); 2228 if (!kind) 2229 return -NLE_NOMEM; 2230 2231 io = rtnl_link_info_ops_lookup(type); 2232 if (io) { 2233 if (io->io_alloc && (err = io->io_alloc(link)) < 0) 2234 goto errout; 2235 2236 link->l_info_ops = io; 2237 } 2238 2239 link->l_info_kind = kind; 2240 link->ce_mask |= LINK_ATTR_LINKINFO; 2241 2242 return 0; 2243 2244errout: 2245 free(kind); 2246 return err; 2247} 2248 2249/** 2250 * Return type of link 2251 * @arg link Link object 2252 * 2253 * @route_doc{link_modules, Link Modules} 2254 * @return Name of link type or NULL if not specified. 2255 */ 2256char *rtnl_link_get_type(struct rtnl_link *link) 2257{ 2258 return link->l_info_kind; 2259} 2260 2261/** 2262 * Set link promiscuity count 2263 * @arg link Link object 2264 * @arg count New promiscuity count 2265 * 2266 * @copydoc read_only_attribute 2267 * 2268 * @see rtnl_link_get_promiscuity() 2269 */ 2270void rtnl_link_set_promiscuity(struct rtnl_link *link, uint32_t count) 2271{ 2272 link->l_promiscuity = count; 2273 link->ce_mask |= LINK_ATTR_PROMISCUITY; 2274} 2275 2276/** 2277 * Return link promiscuity count 2278 * @arg link Link object 2279 * 2280 * @see rtnl_link_set_promiscuity() 2281 * @return Link promiscuity count or 0 2282 */ 2283uint32_t rtnl_link_get_promiscuity(struct rtnl_link *link) 2284{ 2285 return link->l_promiscuity; 2286} 2287 2288/** 2289 * Set number of TX queues 2290 * @arg link Link object 2291 * @arg nqueues Number of queues 2292 * 2293 * Sets the number of TX queues of the link object. The value is considered 2294 * by the kernel when creating network devices that can be created via 2295 * netlink. The value will be passed on to alloc_netdev_mqs() 2296 * 2297 * Therefore use of rtnl_link_set_num_tx_queues() only makes sense in 2298 * combination with rtnl_link_add() or if the link object is used as a filter. 2299 * 2300 * @see rtnl_link_get_num_tx_queues() 2301 */ 2302void rtnl_link_set_num_tx_queues(struct rtnl_link *link, uint32_t nqueues) 2303{ 2304 link->l_num_tx_queues = nqueues; 2305 link->ce_mask |= LINK_ATTR_NUM_TX_QUEUES; 2306} 2307 2308/** 2309 * Return number of TX queues 2310 * @arg link Link object 2311 * 2312 * @return Number of TX queues or 0 2313 */ 2314uint32_t rtnl_link_get_num_tx_queues(struct rtnl_link *link) 2315{ 2316 return link->l_num_tx_queues; 2317} 2318 2319/** 2320 * Set number of RX queues 2321 * @arg link Link object 2322 * @arg nqueues Number of queues 2323 * 2324 * Sets the number of RX queues of the link object. The value is considered 2325 * by the kernel when creating network devices that can be created via 2326 * netlink. The value will be passed on to alloc_netdev_mqs() 2327 * 2328 * Therefore use of rtnl_link_set_num_rx_queues() only makes sense in 2329 * combination with rtnl_link_add() or if the link object is used as a filter. 2330 * 2331 * @see rtnl_link_get_num_rx_queues() 2332 */ 2333void rtnl_link_set_num_rx_queues(struct rtnl_link *link, uint32_t nqueues) 2334{ 2335 link->l_num_rx_queues = nqueues; 2336 link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES; 2337} 2338 2339/** 2340 * Return number of RX queues 2341 * @arg link Link object 2342 * 2343 * @return Number of RX queues or 0 2344 */ 2345uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *link) 2346{ 2347 return link->l_num_rx_queues; 2348} 2349 2350/** 2351 * Return physical port id of link object 2352 * @arg link Link object 2353 * 2354 * @return Physical port id or NULL if not set. 2355 */ 2356struct nl_data *rtnl_link_get_phys_port_id(struct rtnl_link *link) 2357{ 2358 return link->l_phys_port_id; 2359} 2360 2361void rtnl_link_set_ns_fd(struct rtnl_link *link, int fd) 2362{ 2363 link->l_ns_fd = fd; 2364 link->ce_mask |= LINK_ATTR_NS_FD; 2365} 2366 2367int rtnl_link_get_ns_fd(struct rtnl_link *link) 2368{ 2369 return link->l_ns_fd; 2370} 2371 2372void rtnl_link_set_ns_pid(struct rtnl_link *link, pid_t pid) 2373{ 2374 link->l_ns_pid = pid; 2375 link->ce_mask |= LINK_ATTR_NS_PID; 2376} 2377 2378pid_t rtnl_link_get_ns_pid(struct rtnl_link *link) 2379{ 2380 return link->l_ns_pid; 2381} 2382 2383/** @} */ 2384 2385/** 2386 * @name Master/Slave 2387 * @{ 2388 */ 2389 2390/** 2391 * Enslave slave link to master link 2392 * @arg sock netlink socket 2393 * @arg master ifindex of master link 2394 * @arg slave ifindex of slave link 2395 * 2396 * This function is identical to rtnl_link_enslave() except that 2397 * it takes interface indices instead of rtnl_link objects. 2398 * 2399 * @see rtnl_link_enslave() 2400 * 2401 * @return 0 on success or a negative error code. 2402 */ 2403int rtnl_link_enslave_ifindex(struct nl_sock *sock, int master, int slave) 2404{ 2405 struct rtnl_link *link; 2406 int err; 2407 2408 if (!(link = rtnl_link_alloc())) 2409 return -NLE_NOMEM; 2410 2411 rtnl_link_set_ifindex(link, slave); 2412 rtnl_link_set_master(link, master); 2413 2414 if ((err = rtnl_link_change(sock, link, link, 0)) < 0) 2415 goto errout; 2416 2417 rtnl_link_put(link); 2418 2419 /* 2420 * Due to the kernel not signaling whether this opertion is 2421 * supported or not, we will retrieve the attribute to see if the 2422 * request was successful. If the master assigned remains unchanged 2423 * we will return NLE_OPNOTSUPP to allow performing backwards 2424 * compatibility of some sort. 2425 */ 2426 if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0) 2427 return err; 2428 2429 if (rtnl_link_get_master(link) != master) 2430 err = -NLE_OPNOTSUPP; 2431 2432errout: 2433 rtnl_link_put(link); 2434 2435 return err; 2436} 2437 2438/** 2439 * Enslave slave link to master link 2440 * @arg sock netlink socket 2441 * @arg master master link 2442 * @arg slave slave link 2443 * 2444 * Constructs a RTM_NEWLINK or RTM_SETLINK message adding the slave to 2445 * the master and sends the request via the specified netlink socket. 2446 * 2447 * @note The feature of enslaving/releasing via netlink has only been added 2448 * recently to the kernel (Feb 2011). Also, the kernel does not signal 2449 * if the operation is not supported. Therefore this function will 2450 * verify if the master assignment has changed and will return 2451 * -NLE_OPNOTSUPP if it did not. 2452 * 2453 * @see rtnl_link_enslave_ifindex() 2454 * @see rtnl_link_release() 2455 * 2456 * @return 0 on success or a negative error code. 2457 */ 2458int rtnl_link_enslave(struct nl_sock *sock, struct rtnl_link *master, 2459 struct rtnl_link *slave) 2460{ 2461 return rtnl_link_enslave_ifindex(sock, rtnl_link_get_ifindex(master), 2462 rtnl_link_get_ifindex(slave)); 2463} 2464 2465/** 2466 * Release slave link from its master 2467 * @arg sock netlink socket 2468 * @arg slave slave link 2469 * 2470 * This function is identical to rtnl_link_release() except that 2471 * it takes an interface index instead of a rtnl_link object. 2472 * 2473 * @see rtnl_link_release() 2474 * 2475 * @return 0 on success or a negative error code. 2476 */ 2477int rtnl_link_release_ifindex(struct nl_sock *sock, int slave) 2478{ 2479 return rtnl_link_enslave_ifindex(sock, 0, slave); 2480} 2481 2482/** 2483 * Release slave link from its master 2484 * @arg sock netlink socket 2485 * @arg slave slave link 2486 * 2487 * Constructs a RTM_NEWLINK or RTM_SETLINK message releasing the slave from 2488 * its master and sends the request via the specified netlink socket. 2489 * 2490 * @note The feature of enslaving/releasing via netlink has only been added 2491 * recently to the kernel (Feb 2011). Also, the kernel does not signal 2492 * if the operation is not supported. Therefore this function will 2493 * verify if the master assignment has changed and will return 2494 * -NLE_OPNOTSUPP if it did not. 2495 * 2496 * @see rtnl_link_release_ifindex() 2497 * @see rtnl_link_enslave() 2498 * 2499 * @return 0 on success or a negative error code. 2500 */ 2501int rtnl_link_release(struct nl_sock *sock, struct rtnl_link *slave) 2502{ 2503 return rtnl_link_release_ifindex(sock, rtnl_link_get_ifindex(slave)); 2504} 2505 2506/** @} */ 2507 2508/** 2509 * @name Utilities 2510 * @{ 2511 */ 2512 2513static const struct trans_tbl link_flags[] = { 2514 __ADD(IFF_LOOPBACK, loopback) 2515 __ADD(IFF_BROADCAST, broadcast) 2516 __ADD(IFF_POINTOPOINT, pointopoint) 2517 __ADD(IFF_MULTICAST, multicast) 2518 __ADD(IFF_NOARP, noarp) 2519 __ADD(IFF_ALLMULTI, allmulti) 2520 __ADD(IFF_PROMISC, promisc) 2521 __ADD(IFF_MASTER, master) 2522 __ADD(IFF_SLAVE, slave) 2523 __ADD(IFF_DEBUG, debug) 2524 __ADD(IFF_DYNAMIC, dynamic) 2525 __ADD(IFF_AUTOMEDIA, automedia) 2526 __ADD(IFF_PORTSEL, portsel) 2527 __ADD(IFF_NOTRAILERS, notrailers) 2528 __ADD(IFF_UP, up) 2529 __ADD(IFF_RUNNING, running) 2530 __ADD(IFF_LOWER_UP, lowerup) 2531 __ADD(IFF_DORMANT, dormant) 2532 __ADD(IFF_ECHO, echo) 2533}; 2534 2535char *rtnl_link_flags2str(int flags, char *buf, size_t len) 2536{ 2537 return __flags2str(flags, buf, len, link_flags, 2538 ARRAY_SIZE(link_flags)); 2539} 2540 2541int rtnl_link_str2flags(const char *name) 2542{ 2543 return __str2flags(name, link_flags, ARRAY_SIZE(link_flags)); 2544} 2545 2546static const struct trans_tbl link_stats[] = { 2547 __ADD(RTNL_LINK_RX_PACKETS, rx_packets) 2548 __ADD(RTNL_LINK_TX_PACKETS, tx_packets) 2549 __ADD(RTNL_LINK_RX_BYTES, rx_bytes) 2550 __ADD(RTNL_LINK_TX_BYTES, tx_bytes) 2551 __ADD(RTNL_LINK_RX_ERRORS, rx_errors) 2552 __ADD(RTNL_LINK_TX_ERRORS, tx_errors) 2553 __ADD(RTNL_LINK_RX_DROPPED, rx_dropped) 2554 __ADD(RTNL_LINK_TX_DROPPED, tx_dropped) 2555 __ADD(RTNL_LINK_RX_COMPRESSED, rx_compressed) 2556 __ADD(RTNL_LINK_TX_COMPRESSED, tx_compressed) 2557 __ADD(RTNL_LINK_RX_FIFO_ERR, rx_fifo_err) 2558 __ADD(RTNL_LINK_TX_FIFO_ERR, tx_fifo_err) 2559 __ADD(RTNL_LINK_RX_LEN_ERR, rx_len_err) 2560 __ADD(RTNL_LINK_RX_OVER_ERR, rx_over_err) 2561 __ADD(RTNL_LINK_RX_CRC_ERR, rx_crc_err) 2562 __ADD(RTNL_LINK_RX_FRAME_ERR, rx_frame_err) 2563 __ADD(RTNL_LINK_RX_MISSED_ERR, rx_missed_err) 2564 __ADD(RTNL_LINK_TX_ABORT_ERR, tx_abort_err) 2565 __ADD(RTNL_LINK_TX_CARRIER_ERR, tx_carrier_err) 2566 __ADD(RTNL_LINK_TX_HBEAT_ERR, tx_hbeat_err) 2567 __ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err) 2568 __ADD(RTNL_LINK_COLLISIONS, collisions) 2569 __ADD(RTNL_LINK_MULTICAST, multicast) 2570 __ADD(RTNL_LINK_IP6_INPKTS, Ip6InReceives) 2571 __ADD(RTNL_LINK_IP6_INHDRERRORS, Ip6InHdrErrors) 2572 __ADD(RTNL_LINK_IP6_INTOOBIGERRORS, Ip6InTooBigErrors) 2573 __ADD(RTNL_LINK_IP6_INNOROUTES, Ip6InNoRoutes) 2574 __ADD(RTNL_LINK_IP6_INADDRERRORS, Ip6InAddrErrors) 2575 __ADD(RTNL_LINK_IP6_INUNKNOWNPROTOS, Ip6InUnknownProtos) 2576 __ADD(RTNL_LINK_IP6_INTRUNCATEDPKTS, Ip6InTruncatedPkts) 2577 __ADD(RTNL_LINK_IP6_INDISCARDS, Ip6InDiscards) 2578 __ADD(RTNL_LINK_IP6_INDELIVERS, Ip6InDelivers) 2579 __ADD(RTNL_LINK_IP6_OUTFORWDATAGRAMS, Ip6OutForwDatagrams) 2580 __ADD(RTNL_LINK_IP6_OUTPKTS, Ip6OutRequests) 2581 __ADD(RTNL_LINK_IP6_OUTDISCARDS, Ip6OutDiscards) 2582 __ADD(RTNL_LINK_IP6_OUTNOROUTES, Ip6OutNoRoutes) 2583 __ADD(RTNL_LINK_IP6_REASMTIMEOUT, Ip6ReasmTimeout) 2584 __ADD(RTNL_LINK_IP6_REASMREQDS, Ip6ReasmReqds) 2585 __ADD(RTNL_LINK_IP6_REASMOKS, Ip6ReasmOKs) 2586 __ADD(RTNL_LINK_IP6_REASMFAILS, Ip6ReasmFails) 2587 __ADD(RTNL_LINK_IP6_FRAGOKS, Ip6FragOKs) 2588 __ADD(RTNL_LINK_IP6_FRAGFAILS, Ip6FragFails) 2589 __ADD(RTNL_LINK_IP6_FRAGCREATES, Ip6FragCreates) 2590 __ADD(RTNL_LINK_IP6_INMCASTPKTS, Ip6InMcastPkts) 2591 __ADD(RTNL_LINK_IP6_OUTMCASTPKTS, Ip6OutMcastPkts) 2592 __ADD(RTNL_LINK_IP6_INBCASTPKTS, Ip6InBcastPkts) 2593 __ADD(RTNL_LINK_IP6_OUTBCASTPKTS, Ip6OutBcastPkts) 2594 __ADD(RTNL_LINK_IP6_INOCTETS, Ip6InOctets) 2595 __ADD(RTNL_LINK_IP6_OUTOCTETS, Ip6OutOctets) 2596 __ADD(RTNL_LINK_IP6_INMCASTOCTETS, Ip6InMcastOctets) 2597 __ADD(RTNL_LINK_IP6_OUTMCASTOCTETS, Ip6OutMcastOctets) 2598 __ADD(RTNL_LINK_IP6_INBCASTOCTETS, Ip6InBcastOctets) 2599 __ADD(RTNL_LINK_IP6_OUTBCASTOCTETS, Ip6OutBcastOctets) 2600 __ADD(RTNL_LINK_ICMP6_INMSGS, ICMP6_InMsgs) 2601 __ADD(RTNL_LINK_ICMP6_INERRORS, ICMP6_InErrors) 2602 __ADD(RTNL_LINK_ICMP6_OUTMSGS, ICMP6_OutMsgs) 2603 __ADD(RTNL_LINK_ICMP6_OUTERRORS, ICMP6_OutErrors) 2604 __ADD(RTNL_LINK_ICMP6_CSUMERRORS, ICMP6_InCsumErrors) 2605 __ADD(RTNL_LINK_IP6_CSUMERRORS, Ip6_InCsumErrors) 2606 __ADD(RTNL_LINK_IP6_NOECTPKTS, Ip6_InNoECTPkts) 2607 __ADD(RTNL_LINK_IP6_ECT1PKTS, Ip6_InECT1Pkts) 2608 __ADD(RTNL_LINK_IP6_ECT0PKTS, Ip6_InECT0Pkts) 2609 __ADD(RTNL_LINK_IP6_CEPKTS, Ip6_InCEPkts) 2610}; 2611 2612char *rtnl_link_stat2str(int st, char *buf, size_t len) 2613{ 2614 return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats)); 2615} 2616 2617int rtnl_link_str2stat(const char *name) 2618{ 2619 return __str2type(name, link_stats, ARRAY_SIZE(link_stats)); 2620} 2621 2622static const struct trans_tbl link_operstates[] = { 2623 __ADD(IF_OPER_UNKNOWN, unknown) 2624 __ADD(IF_OPER_NOTPRESENT, notpresent) 2625 __ADD(IF_OPER_DOWN, down) 2626 __ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown) 2627 __ADD(IF_OPER_TESTING, testing) 2628 __ADD(IF_OPER_DORMANT, dormant) 2629 __ADD(IF_OPER_UP, up) 2630}; 2631 2632char *rtnl_link_operstate2str(uint8_t st, char *buf, size_t len) 2633{ 2634 return __type2str(st, buf, len, link_operstates, 2635 ARRAY_SIZE(link_operstates)); 2636} 2637 2638int rtnl_link_str2operstate(const char *name) 2639{ 2640 return __str2type(name, link_operstates, 2641 ARRAY_SIZE(link_operstates)); 2642} 2643 2644static const struct trans_tbl link_modes[] = { 2645 __ADD(IF_LINK_MODE_DEFAULT, default) 2646 __ADD(IF_LINK_MODE_DORMANT, dormant) 2647}; 2648 2649static const struct trans_tbl carrier_states[] = { 2650 __ADD(IF_CARRIER_DOWN, down) 2651 __ADD(IF_CARRIER_UP, up) 2652}; 2653 2654char *rtnl_link_mode2str(uint8_t st, char *buf, size_t len) 2655{ 2656 return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes)); 2657} 2658 2659int rtnl_link_str2mode(const char *name) 2660{ 2661 return __str2type(name, link_modes, ARRAY_SIZE(link_modes)); 2662} 2663 2664char *rtnl_link_carrier2str(uint8_t st, char *buf, size_t len) 2665{ 2666 return __type2str(st, buf, len, carrier_states, 2667 ARRAY_SIZE(carrier_states)); 2668} 2669 2670int rtnl_link_str2carrier(const char *name) 2671{ 2672 return __str2type(name, carrier_states, ARRAY_SIZE(carrier_states)); 2673} 2674 2675/** @} */ 2676 2677/** 2678 * @name Deprecated Functions 2679 */ 2680 2681/** 2682 * @deprecated Use of this function is deprecated, use rtnl_link_set_type() 2683 */ 2684int rtnl_link_set_info_type(struct rtnl_link *link, const char *type) 2685{ 2686 return rtnl_link_set_type(link, type); 2687} 2688 2689/** 2690 * @deprecated Use of this function is deprecated, use rtnl_link_get_type() 2691 */ 2692char *rtnl_link_get_info_type(struct rtnl_link *link) 2693{ 2694 return rtnl_link_get_type(link); 2695} 2696 2697/** 2698 * @deprecated The weight attribute is unused and obsoleted in all recent kernels 2699 */ 2700void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight) 2701{ 2702 link->l_weight = weight; 2703 link->ce_mask |= LINK_ATTR_WEIGHT; 2704} 2705 2706/** 2707 * @deprecated The weight attribute is unused and obsoleted in all recent kernels 2708 */ 2709unsigned int rtnl_link_get_weight(struct rtnl_link *link) 2710{ 2711 return link->l_weight; 2712} 2713 2714/** @} */ 2715 2716static struct nl_object_ops link_obj_ops = { 2717 .oo_name = "route/link", 2718 .oo_size = sizeof(struct rtnl_link), 2719 .oo_free_data = link_free_data, 2720 .oo_clone = link_clone, 2721 .oo_dump = { 2722 [NL_DUMP_LINE] = link_dump_line, 2723 [NL_DUMP_DETAILS] = link_dump_details, 2724 [NL_DUMP_STATS] = link_dump_stats, 2725 }, 2726 .oo_compare = link_compare, 2727 .oo_keygen = link_keygen, 2728 .oo_attrs2str = link_attrs2str, 2729 .oo_id_attrs = LINK_ATTR_IFINDEX | LINK_ATTR_FAMILY, 2730}; 2731 2732static struct nl_af_group link_groups[] = { 2733 { AF_UNSPEC, RTNLGRP_LINK }, 2734 { AF_BRIDGE, RTNLGRP_LINK }, 2735 { END_OF_GROUP_LIST }, 2736}; 2737 2738static struct nl_cache_ops rtnl_link_ops = { 2739 .co_name = "route/link", 2740 .co_hdrsize = sizeof(struct ifinfomsg), 2741 .co_msgtypes = { 2742 { RTM_NEWLINK, NL_ACT_NEW, "new" }, 2743 { RTM_DELLINK, NL_ACT_DEL, "del" }, 2744 { RTM_GETLINK, NL_ACT_GET, "get" }, 2745 { RTM_SETLINK, NL_ACT_CHANGE, "set" }, 2746 END_OF_MSGTYPES_LIST, 2747 }, 2748 .co_protocol = NETLINK_ROUTE, 2749 .co_groups = link_groups, 2750 .co_request_update = link_request_update, 2751 .co_msg_parser = link_msg_parser, 2752 .co_obj_ops = &link_obj_ops, 2753}; 2754 2755static void __init link_init(void) 2756{ 2757 nl_cache_mngt_register(&rtnl_link_ops); 2758} 2759 2760static void __exit link_exit(void) 2761{ 2762 nl_cache_mngt_unregister(&rtnl_link_ops); 2763} 2764 2765/** @} */ 2766