libnl 3.2.7
|
00001 /* 00002 * lib/route/link.c Links (Interfaces) 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 /** 00013 * @ingroup rtnl 00014 * @defgroup link Links (Interfaces) 00015 * 00016 * @details 00017 * @route_doc{route_link, Link Documentation} 00018 * @{ 00019 */ 00020 00021 #include <netlink-local.h> 00022 #include <netlink/netlink.h> 00023 #include <netlink/attr.h> 00024 #include <netlink/utils.h> 00025 #include <netlink/object.h> 00026 #include <netlink/route/rtnl.h> 00027 #include <netlink/route/link.h> 00028 #include <netlink/route/link/api.h> 00029 00030 /** @cond SKIP */ 00031 #define LINK_ATTR_MTU 0x0001 00032 #define LINK_ATTR_LINK 0x0002 00033 #define LINK_ATTR_TXQLEN 0x0004 00034 #define LINK_ATTR_WEIGHT 0x0008 00035 #define LINK_ATTR_MASTER 0x0010 00036 #define LINK_ATTR_QDISC 0x0020 00037 #define LINK_ATTR_MAP 0x0040 00038 #define LINK_ATTR_ADDR 0x0080 00039 #define LINK_ATTR_BRD 0x0100 00040 #define LINK_ATTR_FLAGS 0x0200 00041 #define LINK_ATTR_IFNAME 0x0400 00042 #define LINK_ATTR_IFINDEX 0x0800 00043 #define LINK_ATTR_FAMILY 0x1000 00044 #define LINK_ATTR_ARPTYPE 0x2000 00045 #define LINK_ATTR_STATS 0x4000 00046 #define LINK_ATTR_CHANGE 0x8000 00047 #define LINK_ATTR_OPERSTATE 0x10000 00048 #define LINK_ATTR_LINKMODE 0x20000 00049 #define LINK_ATTR_LINKINFO 0x40000 00050 #define LINK_ATTR_IFALIAS 0x80000 00051 #define LINK_ATTR_NUM_VF 0x100000 00052 00053 static struct nl_cache_ops rtnl_link_ops; 00054 static struct nl_object_ops link_obj_ops; 00055 /** @endcond */ 00056 00057 static struct rtnl_link_af_ops *af_lookup_and_alloc(struct rtnl_link *link, 00058 int family) 00059 { 00060 struct rtnl_link_af_ops *af_ops; 00061 void *data; 00062 00063 af_ops = rtnl_link_af_ops_lookup(family); 00064 if (!af_ops) 00065 return NULL; 00066 00067 if (!(data = rtnl_link_af_alloc(link, af_ops))) 00068 return NULL; 00069 00070 return af_ops; 00071 } 00072 00073 static int af_free(struct rtnl_link *link, struct rtnl_link_af_ops *ops, 00074 void *data, void *arg) 00075 { 00076 if (ops->ao_free) 00077 ops->ao_free(link, data); 00078 00079 rtnl_link_af_ops_put(ops); 00080 00081 return 0; 00082 } 00083 00084 static int af_clone(struct rtnl_link *link, struct rtnl_link_af_ops *ops, 00085 void *data, void *arg) 00086 { 00087 struct rtnl_link *dst = arg; 00088 00089 if (ops->ao_clone && 00090 !(dst->l_af_data[ops->ao_family] = ops->ao_clone(dst, data))) 00091 return -NLE_NOMEM; 00092 00093 return 0; 00094 } 00095 00096 static int af_fill(struct rtnl_link *link, struct rtnl_link_af_ops *ops, 00097 void *data, void *arg) 00098 { 00099 struct nl_msg *msg = arg; 00100 struct nlattr *af_attr; 00101 int err; 00102 00103 if (!ops->ao_fill_af) 00104 return 0; 00105 00106 if (!(af_attr = nla_nest_start(msg, ops->ao_family))) 00107 return -NLE_MSGSIZE; 00108 00109 if ((err = ops->ao_fill_af(link, arg, data)) < 0) 00110 return err; 00111 00112 nla_nest_end(msg, af_attr); 00113 00114 return 0; 00115 } 00116 00117 static int af_dump_line(struct rtnl_link *link, struct rtnl_link_af_ops *ops, 00118 void *data, void *arg) 00119 { 00120 struct nl_dump_params *p = arg; 00121 00122 if (ops->ao_dump[NL_DUMP_LINE]) 00123 ops->ao_dump[NL_DUMP_LINE](link, p, data); 00124 00125 return 0; 00126 } 00127 00128 static int af_dump_details(struct rtnl_link *link, struct rtnl_link_af_ops *ops, 00129 void *data, void *arg) 00130 { 00131 struct nl_dump_params *p = arg; 00132 00133 if (ops->ao_dump[NL_DUMP_DETAILS]) 00134 ops->ao_dump[NL_DUMP_DETAILS](link, p, data); 00135 00136 return 0; 00137 } 00138 00139 static int af_dump_stats(struct rtnl_link *link, struct rtnl_link_af_ops *ops, 00140 void *data, void *arg) 00141 { 00142 struct nl_dump_params *p = arg; 00143 00144 if (ops->ao_dump[NL_DUMP_STATS]) 00145 ops->ao_dump[NL_DUMP_STATS](link, p, data); 00146 00147 return 0; 00148 } 00149 00150 static int do_foreach_af(struct rtnl_link *link, 00151 int (*cb)(struct rtnl_link *, 00152 struct rtnl_link_af_ops *, void *, void *), 00153 void *arg) 00154 { 00155 int i, err; 00156 00157 for (i = 0; i < AF_MAX; i++) { 00158 if (link->l_af_data[i]) { 00159 struct rtnl_link_af_ops *ops; 00160 00161 if (!(ops = rtnl_link_af_ops_lookup(i))) 00162 BUG(); 00163 00164 if ((err = cb(link, ops, link->l_af_data[i], arg)) < 0) 00165 return err; 00166 } 00167 } 00168 00169 return 0; 00170 } 00171 00172 static void release_link_info(struct rtnl_link *link) 00173 { 00174 struct rtnl_link_info_ops *io = link->l_info_ops; 00175 00176 if (io != NULL) { 00177 if (io->io_free) 00178 io->io_free(link); 00179 rtnl_link_info_ops_put(io); 00180 link->l_info_ops = NULL; 00181 } 00182 } 00183 00184 static void link_free_data(struct nl_object *c) 00185 { 00186 struct rtnl_link *link = nl_object_priv(c); 00187 00188 if (link) { 00189 struct rtnl_link_info_ops *io; 00190 00191 if ((io = link->l_info_ops) != NULL) 00192 release_link_info(link); 00193 00194 nl_addr_put(link->l_addr); 00195 nl_addr_put(link->l_bcast); 00196 00197 free(link->l_ifalias); 00198 free(link->l_info_kind); 00199 00200 do_foreach_af(link, af_free, NULL); 00201 } 00202 } 00203 00204 static int link_clone(struct nl_object *_dst, struct nl_object *_src) 00205 { 00206 struct rtnl_link *dst = nl_object_priv(_dst); 00207 struct rtnl_link *src = nl_object_priv(_src); 00208 int err; 00209 00210 if (src->l_addr) 00211 if (!(dst->l_addr = nl_addr_clone(src->l_addr))) 00212 return -NLE_NOMEM; 00213 00214 if (src->l_bcast) 00215 if (!(dst->l_bcast = nl_addr_clone(src->l_bcast))) 00216 return -NLE_NOMEM; 00217 00218 if (src->l_ifalias) 00219 if (!(dst->l_ifalias = strdup(src->l_ifalias))) 00220 return -NLE_NOMEM; 00221 00222 if (src->l_info_kind) 00223 if (!(dst->l_info_kind = strdup(src->l_info_kind))) 00224 return -NLE_NOMEM; 00225 00226 if (src->l_info_ops && src->l_info_ops->io_clone) { 00227 err = src->l_info_ops->io_clone(dst, src); 00228 if (err < 0) 00229 return err; 00230 } 00231 00232 if ((err = do_foreach_af(src, af_clone, dst)) < 0) 00233 return err; 00234 00235 return 0; 00236 } 00237 00238 static struct nla_policy link_policy[IFLA_MAX+1] = { 00239 [IFLA_IFNAME] = { .type = NLA_STRING, 00240 .maxlen = IFNAMSIZ }, 00241 [IFLA_MTU] = { .type = NLA_U32 }, 00242 [IFLA_TXQLEN] = { .type = NLA_U32 }, 00243 [IFLA_LINK] = { .type = NLA_U32 }, 00244 [IFLA_WEIGHT] = { .type = NLA_U32 }, 00245 [IFLA_MASTER] = { .type = NLA_U32 }, 00246 [IFLA_OPERSTATE]= { .type = NLA_U8 }, 00247 [IFLA_LINKMODE] = { .type = NLA_U8 }, 00248 [IFLA_LINKINFO] = { .type = NLA_NESTED }, 00249 [IFLA_QDISC] = { .type = NLA_STRING, 00250 .maxlen = IFQDISCSIZ }, 00251 [IFLA_STATS] = { .minlen = sizeof(struct rtnl_link_stats) }, 00252 [IFLA_STATS64] = { .minlen = sizeof(struct rtnl_link_stats64) }, 00253 [IFLA_MAP] = { .minlen = sizeof(struct rtnl_link_ifmap) }, 00254 [IFLA_IFALIAS] = { .type = NLA_STRING, .maxlen = IFALIASZ }, 00255 [IFLA_NUM_VF] = { .type = NLA_U32 }, 00256 [IFLA_AF_SPEC] = { .type = NLA_NESTED }, 00257 }; 00258 00259 static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = { 00260 [IFLA_INFO_KIND] = { .type = NLA_STRING }, 00261 [IFLA_INFO_DATA] = { .type = NLA_NESTED }, 00262 [IFLA_INFO_XSTATS] = { .type = NLA_NESTED }, 00263 }; 00264 00265 static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 00266 struct nlmsghdr *n, struct nl_parser_param *pp) 00267 { 00268 struct rtnl_link *link; 00269 struct ifinfomsg *ifi; 00270 struct nlattr *tb[IFLA_MAX+1]; 00271 struct rtnl_link_af_ops *af_ops = NULL; 00272 int err, family; 00273 00274 link = rtnl_link_alloc(); 00275 if (link == NULL) { 00276 err = -NLE_NOMEM; 00277 goto errout; 00278 } 00279 00280 link->ce_msgtype = n->nlmsg_type; 00281 00282 if (!nlmsg_valid_hdr(n, sizeof(*ifi))) 00283 return -NLE_MSG_TOOSHORT; 00284 00285 ifi = nlmsg_data(n); 00286 link->l_family = family = ifi->ifi_family; 00287 link->l_arptype = ifi->ifi_type; 00288 link->l_index = ifi->ifi_index; 00289 link->l_flags = ifi->ifi_flags; 00290 link->l_change = ifi->ifi_change; 00291 link->ce_mask = (LINK_ATTR_IFNAME | LINK_ATTR_FAMILY | 00292 LINK_ATTR_ARPTYPE| LINK_ATTR_IFINDEX | 00293 LINK_ATTR_FLAGS | LINK_ATTR_CHANGE); 00294 00295 if ((af_ops = af_lookup_and_alloc(link, family))) { 00296 if (af_ops->ao_protinfo_policy) { 00297 memcpy(&link_policy[IFLA_PROTINFO], 00298 af_ops->ao_protinfo_policy, 00299 sizeof(struct nla_policy)); 00300 } 00301 } 00302 00303 err = nlmsg_parse(n, sizeof(*ifi), tb, IFLA_MAX, link_policy); 00304 if (err < 0) 00305 goto errout; 00306 00307 if (tb[IFLA_IFNAME] == NULL) { 00308 err = -NLE_MISSING_ATTR; 00309 goto errout; 00310 } 00311 00312 nla_strlcpy(link->l_name, tb[IFLA_IFNAME], IFNAMSIZ); 00313 00314 00315 if (tb[IFLA_STATS]) { 00316 struct rtnl_link_stats *st = nla_data(tb[IFLA_STATS]); 00317 00318 link->l_stats[RTNL_LINK_RX_PACKETS] = st->rx_packets; 00319 link->l_stats[RTNL_LINK_TX_PACKETS] = st->tx_packets; 00320 link->l_stats[RTNL_LINK_RX_BYTES] = st->rx_bytes; 00321 link->l_stats[RTNL_LINK_TX_BYTES] = st->tx_bytes; 00322 link->l_stats[RTNL_LINK_RX_ERRORS] = st->rx_errors; 00323 link->l_stats[RTNL_LINK_TX_ERRORS] = st->tx_errors; 00324 link->l_stats[RTNL_LINK_RX_DROPPED] = st->rx_dropped; 00325 link->l_stats[RTNL_LINK_TX_DROPPED] = st->tx_dropped; 00326 link->l_stats[RTNL_LINK_MULTICAST] = st->multicast; 00327 link->l_stats[RTNL_LINK_COLLISIONS] = st->collisions; 00328 00329 link->l_stats[RTNL_LINK_RX_LEN_ERR] = st->rx_length_errors; 00330 link->l_stats[RTNL_LINK_RX_OVER_ERR] = st->rx_over_errors; 00331 link->l_stats[RTNL_LINK_RX_CRC_ERR] = st->rx_crc_errors; 00332 link->l_stats[RTNL_LINK_RX_FRAME_ERR] = st->rx_frame_errors; 00333 link->l_stats[RTNL_LINK_RX_FIFO_ERR] = st->rx_fifo_errors; 00334 link->l_stats[RTNL_LINK_RX_MISSED_ERR] = st->rx_missed_errors; 00335 00336 link->l_stats[RTNL_LINK_TX_ABORT_ERR] = st->tx_aborted_errors; 00337 link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st->tx_carrier_errors; 00338 link->l_stats[RTNL_LINK_TX_FIFO_ERR] = st->tx_fifo_errors; 00339 link->l_stats[RTNL_LINK_TX_HBEAT_ERR] = st->tx_heartbeat_errors; 00340 link->l_stats[RTNL_LINK_TX_WIN_ERR] = st->tx_window_errors; 00341 00342 link->l_stats[RTNL_LINK_RX_COMPRESSED] = st->rx_compressed; 00343 link->l_stats[RTNL_LINK_TX_COMPRESSED] = st->tx_compressed; 00344 00345 link->ce_mask |= LINK_ATTR_STATS; 00346 } 00347 00348 if (tb[IFLA_STATS64]) { 00349 /* 00350 * This structure contains 64bit parameters, and per the 00351 * documentation in lib/attr.c, must not be accessed 00352 * directly (because of alignment to 4 instead of 8). 00353 * Therefore, copy the data to the stack and access it from 00354 * there, where it will be aligned to 8. 00355 */ 00356 struct rtnl_link_stats64 st; 00357 00358 nla_memcpy(&st, tb[IFLA_STATS64], 00359 sizeof(struct rtnl_link_stats64)); 00360 00361 link->l_stats[RTNL_LINK_RX_PACKETS] = st.rx_packets; 00362 link->l_stats[RTNL_LINK_TX_PACKETS] = st.tx_packets; 00363 link->l_stats[RTNL_LINK_RX_BYTES] = st.rx_bytes; 00364 link->l_stats[RTNL_LINK_TX_BYTES] = st.tx_bytes; 00365 link->l_stats[RTNL_LINK_RX_ERRORS] = st.rx_errors; 00366 link->l_stats[RTNL_LINK_TX_ERRORS] = st.tx_errors; 00367 link->l_stats[RTNL_LINK_RX_DROPPED] = st.rx_dropped; 00368 link->l_stats[RTNL_LINK_TX_DROPPED] = st.tx_dropped; 00369 link->l_stats[RTNL_LINK_MULTICAST] = st.multicast; 00370 link->l_stats[RTNL_LINK_COLLISIONS] = st.collisions; 00371 00372 link->l_stats[RTNL_LINK_RX_LEN_ERR] = st.rx_length_errors; 00373 link->l_stats[RTNL_LINK_RX_OVER_ERR] = st.rx_over_errors; 00374 link->l_stats[RTNL_LINK_RX_CRC_ERR] = st.rx_crc_errors; 00375 link->l_stats[RTNL_LINK_RX_FRAME_ERR] = st.rx_frame_errors; 00376 link->l_stats[RTNL_LINK_RX_FIFO_ERR] = st.rx_fifo_errors; 00377 link->l_stats[RTNL_LINK_RX_MISSED_ERR] = st.rx_missed_errors; 00378 00379 link->l_stats[RTNL_LINK_TX_ABORT_ERR] = st.tx_aborted_errors; 00380 link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st.tx_carrier_errors; 00381 link->l_stats[RTNL_LINK_TX_FIFO_ERR] = st.tx_fifo_errors; 00382 link->l_stats[RTNL_LINK_TX_HBEAT_ERR] = st.tx_heartbeat_errors; 00383 link->l_stats[RTNL_LINK_TX_WIN_ERR] = st.tx_window_errors; 00384 00385 link->l_stats[RTNL_LINK_RX_COMPRESSED] = st.rx_compressed; 00386 link->l_stats[RTNL_LINK_TX_COMPRESSED] = st.tx_compressed; 00387 00388 link->ce_mask |= LINK_ATTR_STATS; 00389 } 00390 00391 if (tb[IFLA_TXQLEN]) { 00392 link->l_txqlen = nla_get_u32(tb[IFLA_TXQLEN]); 00393 link->ce_mask |= LINK_ATTR_TXQLEN; 00394 } 00395 00396 if (tb[IFLA_MTU]) { 00397 link->l_mtu = nla_get_u32(tb[IFLA_MTU]); 00398 link->ce_mask |= LINK_ATTR_MTU; 00399 } 00400 00401 if (tb[IFLA_ADDRESS]) { 00402 link->l_addr = nl_addr_alloc_attr(tb[IFLA_ADDRESS], AF_UNSPEC); 00403 if (link->l_addr == NULL) { 00404 err = -NLE_NOMEM; 00405 goto errout; 00406 } 00407 nl_addr_set_family(link->l_addr, 00408 nl_addr_guess_family(link->l_addr)); 00409 link->ce_mask |= LINK_ATTR_ADDR; 00410 } 00411 00412 if (tb[IFLA_BROADCAST]) { 00413 link->l_bcast = nl_addr_alloc_attr(tb[IFLA_BROADCAST], 00414 AF_UNSPEC); 00415 if (link->l_bcast == NULL) { 00416 err = -NLE_NOMEM; 00417 goto errout; 00418 } 00419 nl_addr_set_family(link->l_bcast, 00420 nl_addr_guess_family(link->l_bcast)); 00421 link->ce_mask |= LINK_ATTR_BRD; 00422 } 00423 00424 if (tb[IFLA_LINK]) { 00425 link->l_link = nla_get_u32(tb[IFLA_LINK]); 00426 link->ce_mask |= LINK_ATTR_LINK; 00427 } 00428 00429 if (tb[IFLA_WEIGHT]) { 00430 link->l_weight = nla_get_u32(tb[IFLA_WEIGHT]); 00431 link->ce_mask |= LINK_ATTR_WEIGHT; 00432 } 00433 00434 if (tb[IFLA_QDISC]) { 00435 nla_strlcpy(link->l_qdisc, tb[IFLA_QDISC], IFQDISCSIZ); 00436 link->ce_mask |= LINK_ATTR_QDISC; 00437 } 00438 00439 if (tb[IFLA_MAP]) { 00440 nla_memcpy(&link->l_map, tb[IFLA_MAP], 00441 sizeof(struct rtnl_link_ifmap)); 00442 link->ce_mask |= LINK_ATTR_MAP; 00443 } 00444 00445 if (tb[IFLA_MASTER]) { 00446 link->l_master = nla_get_u32(tb[IFLA_MASTER]); 00447 link->ce_mask |= LINK_ATTR_MASTER; 00448 } 00449 00450 if (tb[IFLA_OPERSTATE]) { 00451 link->l_operstate = nla_get_u8(tb[IFLA_OPERSTATE]); 00452 link->ce_mask |= LINK_ATTR_OPERSTATE; 00453 } 00454 00455 if (tb[IFLA_LINKMODE]) { 00456 link->l_linkmode = nla_get_u8(tb[IFLA_LINKMODE]); 00457 link->ce_mask |= LINK_ATTR_LINKMODE; 00458 } 00459 00460 if (tb[IFLA_IFALIAS]) { 00461 link->l_ifalias = nla_strdup(tb[IFLA_IFALIAS]); 00462 if (link->l_ifalias == NULL) { 00463 err = -NLE_NOMEM; 00464 goto errout; 00465 } 00466 link->ce_mask |= LINK_ATTR_IFALIAS; 00467 } 00468 00469 if (tb[IFLA_NUM_VF]) { 00470 link->l_num_vf = nla_get_u32(tb[IFLA_NUM_VF]); 00471 link->ce_mask |= LINK_ATTR_NUM_VF; 00472 } 00473 00474 if (tb[IFLA_LINKINFO]) { 00475 struct nlattr *li[IFLA_INFO_MAX+1]; 00476 00477 err = nla_parse_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO], 00478 link_info_policy); 00479 if (err < 0) 00480 goto errout; 00481 00482 if (li[IFLA_INFO_KIND]) { 00483 struct rtnl_link_info_ops *ops; 00484 char *kind; 00485 00486 kind = nla_strdup(li[IFLA_INFO_KIND]); 00487 if (kind == NULL) { 00488 err = -NLE_NOMEM; 00489 goto errout; 00490 } 00491 link->l_info_kind = kind; 00492 link->ce_mask |= LINK_ATTR_LINKINFO; 00493 00494 ops = rtnl_link_info_ops_lookup(kind); 00495 link->l_info_ops = ops; 00496 00497 if (ops) { 00498 if (ops->io_parse && 00499 (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) { 00500 err = ops->io_parse(link, li[IFLA_INFO_DATA], 00501 li[IFLA_INFO_XSTATS]); 00502 if (err < 0) 00503 goto errout; 00504 } else { 00505 /* XXX: Warn about unparsed info? */ 00506 } 00507 } 00508 } 00509 } 00510 00511 if (tb[IFLA_PROTINFO] && af_ops && af_ops->ao_parse_protinfo) { 00512 err = af_ops->ao_parse_protinfo(link, tb[IFLA_PROTINFO], 00513 link->l_af_data[link->l_family]); 00514 if (err < 0) 00515 goto errout; 00516 } 00517 00518 if (tb[IFLA_AF_SPEC]) { 00519 struct nlattr *af_attr; 00520 int remaining; 00521 00522 nla_for_each_nested(af_attr, tb[IFLA_AF_SPEC], remaining) { 00523 af_ops = af_lookup_and_alloc(link, nla_type(af_attr)); 00524 if (af_ops && af_ops->ao_parse_af) { 00525 char *af_data = link->l_af_data[nla_type(af_attr)]; 00526 00527 err = af_ops->ao_parse_af(link, af_attr, af_data); 00528 00529 rtnl_link_af_ops_put(af_ops); 00530 00531 if (err < 0) 00532 goto errout; 00533 } 00534 00535 } 00536 } 00537 00538 err = pp->pp_cb((struct nl_object *) link, pp); 00539 errout: 00540 rtnl_link_af_ops_put(af_ops); 00541 rtnl_link_put(link); 00542 return err; 00543 } 00544 00545 static int link_event_filter(struct nl_cache *cache, struct nl_object *obj) 00546 { 00547 struct rtnl_link *link = (struct rtnl_link *) obj; 00548 00549 /* 00550 * Ignore bridging messages when keeping the cache manager up to date. 00551 */ 00552 if (link->l_family == AF_BRIDGE) 00553 return NL_SKIP; 00554 00555 return NL_OK; 00556 } 00557 00558 static int link_request_update(struct nl_cache *cache, struct nl_sock *sk) 00559 { 00560 int family = cache->c_iarg1; 00561 00562 return nl_rtgen_request(sk, RTM_GETLINK, family, NLM_F_DUMP); 00563 } 00564 00565 static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p) 00566 { 00567 char buf[128]; 00568 struct nl_cache *cache = dp_cache(obj); 00569 struct rtnl_link *link = (struct rtnl_link *) obj; 00570 00571 nl_dump_line(p, "%s %s ", link->l_name, 00572 nl_llproto2str(link->l_arptype, buf, sizeof(buf))); 00573 00574 if (link->l_addr && !nl_addr_iszero(link->l_addr)) 00575 nl_dump(p, "%s ", nl_addr2str(link->l_addr, buf, sizeof(buf))); 00576 00577 if (link->ce_mask & LINK_ATTR_MASTER) { 00578 struct rtnl_link *master = rtnl_link_get(cache, link->l_master); 00579 nl_dump(p, "master %s ", master ? master->l_name : "inv"); 00580 if (master) 00581 rtnl_link_put(master); 00582 } 00583 00584 rtnl_link_flags2str(link->l_flags, buf, sizeof(buf)); 00585 if (buf[0]) 00586 nl_dump(p, "<%s> ", buf); 00587 00588 if (link->ce_mask & LINK_ATTR_LINK) { 00589 struct rtnl_link *ll = rtnl_link_get(cache, link->l_link); 00590 nl_dump(p, "slave-of %s ", ll ? ll->l_name : "NONE"); 00591 if (ll) 00592 rtnl_link_put(ll); 00593 } 00594 00595 if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_LINE]) 00596 link->l_info_ops->io_dump[NL_DUMP_LINE](link, p); 00597 00598 do_foreach_af(link, af_dump_line, p); 00599 00600 nl_dump(p, "\n"); 00601 } 00602 00603 static void link_dump_details(struct nl_object *obj, struct nl_dump_params *p) 00604 { 00605 struct rtnl_link *link = (struct rtnl_link *) obj; 00606 char buf[64]; 00607 00608 link_dump_line(obj, p); 00609 00610 nl_dump_line(p, " mtu %u ", link->l_mtu); 00611 nl_dump(p, "txqlen %u weight %u ", link->l_txqlen, link->l_weight); 00612 00613 if (link->ce_mask & LINK_ATTR_QDISC) 00614 nl_dump(p, "qdisc %s ", link->l_qdisc); 00615 00616 if (link->ce_mask & LINK_ATTR_MAP && link->l_map.lm_irq) 00617 nl_dump(p, "irq %u ", link->l_map.lm_irq); 00618 00619 if (link->ce_mask & LINK_ATTR_IFINDEX) 00620 nl_dump(p, "index %u ", link->l_index); 00621 00622 00623 nl_dump(p, "\n"); 00624 00625 if (link->ce_mask & LINK_ATTR_IFALIAS) 00626 nl_dump_line(p, " alias %s\n", link->l_ifalias); 00627 00628 nl_dump_line(p, " "); 00629 00630 if (link->ce_mask & LINK_ATTR_BRD) 00631 nl_dump(p, "brd %s ", nl_addr2str(link->l_bcast, buf, 00632 sizeof(buf))); 00633 00634 if ((link->ce_mask & LINK_ATTR_OPERSTATE) && 00635 link->l_operstate != IF_OPER_UNKNOWN) { 00636 rtnl_link_operstate2str(link->l_operstate, buf, sizeof(buf)); 00637 nl_dump(p, "state %s ", buf); 00638 } 00639 00640 if (link->ce_mask & LINK_ATTR_NUM_VF) 00641 nl_dump(p, "num-vf %u ", link->l_num_vf); 00642 00643 nl_dump(p, "mode %s\n", 00644 rtnl_link_mode2str(link->l_linkmode, buf, sizeof(buf))); 00645 00646 if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_DETAILS]) 00647 link->l_info_ops->io_dump[NL_DUMP_DETAILS](link, p); 00648 00649 do_foreach_af(link, af_dump_details, p); 00650 } 00651 00652 static void link_dump_stats(struct nl_object *obj, struct nl_dump_params *p) 00653 { 00654 struct rtnl_link *link = (struct rtnl_link *) obj; 00655 char *unit, fmt[64]; 00656 float res; 00657 00658 link_dump_details(obj, p); 00659 00660 nl_dump_line(p, " Stats: bytes packets errors " 00661 " dropped fifo-err compressed\n"); 00662 00663 res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_RX_BYTES], &unit); 00664 00665 strcpy(fmt, " RX %X.2f %s %10llu %10llu %10llu %10llu %10llu\n"); 00666 fmt[9] = *unit == 'B' ? '9' : '7'; 00667 00668 nl_dump_line(p, fmt, res, unit, 00669 link->l_stats[RTNL_LINK_RX_PACKETS], 00670 link->l_stats[RTNL_LINK_RX_ERRORS], 00671 link->l_stats[RTNL_LINK_RX_DROPPED], 00672 link->l_stats[RTNL_LINK_RX_FIFO_ERR], 00673 link->l_stats[RTNL_LINK_RX_COMPRESSED]); 00674 00675 res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_TX_BYTES], &unit); 00676 00677 strcpy(fmt, " TX %X.2f %s %10llu %10llu %10llu %10llu %10llu\n"); 00678 fmt[9] = *unit == 'B' ? '9' : '7'; 00679 00680 nl_dump_line(p, fmt, res, unit, 00681 link->l_stats[RTNL_LINK_TX_PACKETS], 00682 link->l_stats[RTNL_LINK_TX_ERRORS], 00683 link->l_stats[RTNL_LINK_TX_DROPPED], 00684 link->l_stats[RTNL_LINK_TX_FIFO_ERR], 00685 link->l_stats[RTNL_LINK_TX_COMPRESSED]); 00686 00687 nl_dump_line(p, " Errors: length over crc " 00688 " frame missed multicast\n"); 00689 00690 nl_dump_line(p, " RX %10" PRIu64 " %10" PRIu64 " %10" 00691 PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" 00692 PRIu64 "\n", 00693 link->l_stats[RTNL_LINK_RX_LEN_ERR], 00694 link->l_stats[RTNL_LINK_RX_OVER_ERR], 00695 link->l_stats[RTNL_LINK_RX_CRC_ERR], 00696 link->l_stats[RTNL_LINK_RX_FRAME_ERR], 00697 link->l_stats[RTNL_LINK_RX_MISSED_ERR], 00698 link->l_stats[RTNL_LINK_MULTICAST]); 00699 00700 nl_dump_line(p, " aborted carrier heartbeat " 00701 " window collision\n"); 00702 00703 nl_dump_line(p, " TX %10" PRIu64 " %10" PRIu64 " %10" 00704 PRIu64 " %10" PRIu64 " %10" PRIu64 "\n", 00705 link->l_stats[RTNL_LINK_TX_ABORT_ERR], 00706 link->l_stats[RTNL_LINK_TX_CARRIER_ERR], 00707 link->l_stats[RTNL_LINK_TX_HBEAT_ERR], 00708 link->l_stats[RTNL_LINK_TX_WIN_ERR], 00709 link->l_stats[RTNL_LINK_COLLISIONS]); 00710 00711 if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_STATS]) 00712 link->l_info_ops->io_dump[NL_DUMP_STATS](link, p); 00713 00714 do_foreach_af(link, af_dump_stats, p); 00715 } 00716 00717 #if 0 00718 static int link_handle_event(struct nl_object *a, struct rtnl_link_event_cb *cb) 00719 { 00720 struct rtnl_link *l = (struct rtnl_link *) a; 00721 struct nl_cache *c = dp_cache(a); 00722 int nevents = 0; 00723 00724 if (l->l_change == ~0U) { 00725 if (l->ce_msgtype == RTM_NEWLINK) 00726 cb->le_register(l); 00727 else 00728 cb->le_unregister(l); 00729 00730 return 1; 00731 } 00732 00733 if (l->l_change & IFF_SLAVE) { 00734 if (l->l_flags & IFF_SLAVE) { 00735 struct rtnl_link *m = rtnl_link_get(c, l->l_master); 00736 cb->le_new_bonding(l, m); 00737 if (m) 00738 rtnl_link_put(m); 00739 } else 00740 cb->le_cancel_bonding(l); 00741 } 00742 00743 #if 0 00744 if (l->l_change & IFF_UP && l->l_change & IFF_RUNNING) 00745 dp_dump_line(p, line++, "link %s changed state to %s.\n", 00746 l->l_name, l->l_flags & IFF_UP ? "up" : "down"); 00747 00748 if (l->l_change & IFF_PROMISC) { 00749 dp_new_line(p, line++); 00750 dp_dump(p, "link %s %s promiscuous mode.\n", 00751 l->l_name, l->l_flags & IFF_PROMISC ? "entered" : "left"); 00752 } 00753 00754 if (line == 0) 00755 dp_dump_line(p, line++, "link %s sent unknown event.\n", 00756 l->l_name); 00757 #endif 00758 00759 return nevents; 00760 } 00761 #endif 00762 00763 static int link_compare(struct nl_object *_a, struct nl_object *_b, 00764 uint32_t attrs, int flags) 00765 { 00766 struct rtnl_link *a = (struct rtnl_link *) _a; 00767 struct rtnl_link *b = (struct rtnl_link *) _b; 00768 int diff = 0; 00769 00770 #define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR) 00771 00772 diff |= LINK_DIFF(IFINDEX, a->l_index != b->l_index); 00773 diff |= LINK_DIFF(MTU, a->l_mtu != b->l_mtu); 00774 diff |= LINK_DIFF(LINK, a->l_link != b->l_link); 00775 diff |= LINK_DIFF(TXQLEN, a->l_txqlen != b->l_txqlen); 00776 diff |= LINK_DIFF(WEIGHT, a->l_weight != b->l_weight); 00777 diff |= LINK_DIFF(MASTER, a->l_master != b->l_master); 00778 diff |= LINK_DIFF(FAMILY, a->l_family != b->l_family); 00779 diff |= LINK_DIFF(OPERSTATE, a->l_operstate != b->l_operstate); 00780 diff |= LINK_DIFF(LINKMODE, a->l_linkmode != b->l_linkmode); 00781 diff |= LINK_DIFF(QDISC, strcmp(a->l_qdisc, b->l_qdisc)); 00782 diff |= LINK_DIFF(IFNAME, strcmp(a->l_name, b->l_name)); 00783 diff |= LINK_DIFF(ADDR, nl_addr_cmp(a->l_addr, b->l_addr)); 00784 diff |= LINK_DIFF(BRD, nl_addr_cmp(a->l_bcast, b->l_bcast)); 00785 diff |= LINK_DIFF(IFALIAS, strcmp(a->l_ifalias, b->l_ifalias)); 00786 diff |= LINK_DIFF(NUM_VF, a->l_num_vf != b->l_num_vf); 00787 00788 if (flags & LOOSE_COMPARISON) 00789 diff |= LINK_DIFF(FLAGS, 00790 (a->l_flags ^ b->l_flags) & b->l_flag_mask); 00791 else 00792 diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags); 00793 00794 #undef LINK_DIFF 00795 00796 return diff; 00797 } 00798 00799 static const struct trans_tbl link_attrs[] = { 00800 __ADD(LINK_ATTR_MTU, mtu) 00801 __ADD(LINK_ATTR_LINK, link) 00802 __ADD(LINK_ATTR_TXQLEN, txqlen) 00803 __ADD(LINK_ATTR_WEIGHT, weight) 00804 __ADD(LINK_ATTR_MASTER, master) 00805 __ADD(LINK_ATTR_QDISC, qdisc) 00806 __ADD(LINK_ATTR_MAP, map) 00807 __ADD(LINK_ATTR_ADDR, address) 00808 __ADD(LINK_ATTR_BRD, broadcast) 00809 __ADD(LINK_ATTR_FLAGS, flags) 00810 __ADD(LINK_ATTR_IFNAME, name) 00811 __ADD(LINK_ATTR_IFINDEX, ifindex) 00812 __ADD(LINK_ATTR_FAMILY, family) 00813 __ADD(LINK_ATTR_ARPTYPE, arptype) 00814 __ADD(LINK_ATTR_STATS, stats) 00815 __ADD(LINK_ATTR_CHANGE, change) 00816 __ADD(LINK_ATTR_OPERSTATE, operstate) 00817 __ADD(LINK_ATTR_LINKMODE, linkmode) 00818 __ADD(LINK_ATTR_IFALIAS, ifalias) 00819 __ADD(LINK_ATTR_NUM_VF, num_vf) 00820 }; 00821 00822 static char *link_attrs2str(int attrs, char *buf, size_t len) 00823 { 00824 return __flags2str(attrs, buf, len, link_attrs, 00825 ARRAY_SIZE(link_attrs)); 00826 } 00827 00828 /** 00829 * @name Get / List 00830 * @{ 00831 */ 00832 00833 00834 /** 00835 * Allocate link cache and fill in all configured links. 00836 * @arg sk Netlink socket. 00837 * @arg family Link address family or AF_UNSPEC 00838 * @arg result Pointer to store resulting cache. 00839 * 00840 * Allocates and initializes a new link cache. A netlink message is sent to 00841 * the kernel requesting a full dump of all configured links. The returned 00842 * messages are parsed and filled into the cache. If the operation succeeds 00843 * the resulting cache will a link object for each link configured in the 00844 * kernel. 00845 * 00846 * If \c family is set to an address family other than \c AF_UNSPEC the 00847 * contents of the cache can be limited to a specific address family. 00848 * Currently the following address families are supported: 00849 * - AF_BRIDGE 00850 * - AF_INET6 00851 * 00852 * @route_doc{link_list, Get List of Links} 00853 * @see rtnl_link_get() 00854 * @see rtnl_link_get_by_name() 00855 * @return 0 on success or a negative error code. 00856 */ 00857 int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result) 00858 { 00859 struct nl_cache * cache; 00860 int err; 00861 00862 cache = nl_cache_alloc(&rtnl_link_ops); 00863 if (!cache) 00864 return -NLE_NOMEM; 00865 00866 cache->c_iarg1 = family; 00867 00868 if (sk && (err = nl_cache_refill(sk, cache)) < 0) { 00869 nl_cache_free(cache); 00870 return err; 00871 } 00872 00873 *result = cache; 00874 return 0; 00875 } 00876 00877 /** 00878 * Lookup link in cache by interface index 00879 * @arg cache Link cache 00880 * @arg ifindex Interface index 00881 * 00882 * Searches through the provided cache looking for a link with matching 00883 * interface index. 00884 * 00885 * @attention The reference counter of the returned link object will be 00886 * incremented. Use rtnl_link_put() to release the reference. 00887 * 00888 * @route_doc{link_list, Get List of Links} 00889 * @see rtnl_link_get_by_name() 00890 * @return Link object or NULL if no match was found. 00891 */ 00892 struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex) 00893 { 00894 struct rtnl_link *link; 00895 00896 if (cache->c_ops != &rtnl_link_ops) 00897 return NULL; 00898 00899 nl_list_for_each_entry(link, &cache->c_items, ce_list) { 00900 if (link->l_index == ifindex) { 00901 nl_object_get((struct nl_object *) link); 00902 return link; 00903 } 00904 } 00905 00906 return NULL; 00907 } 00908 00909 /** 00910 * Lookup link in cache by link name 00911 * @arg cache Link cache 00912 * @arg name Name of link 00913 * 00914 * Searches through the provided cache looking for a link with matching 00915 * link name 00916 * 00917 * @attention The reference counter of the returned link object will be 00918 * incremented. Use rtnl_link_put() to release the reference. 00919 * 00920 * @route_doc{link_list, Get List of Links} 00921 * @see rtnl_link_get() 00922 * @return Link object or NULL if no match was found. 00923 */ 00924 struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, 00925 const char *name) 00926 { 00927 struct rtnl_link *link; 00928 00929 if (cache->c_ops != &rtnl_link_ops) 00930 return NULL; 00931 00932 nl_list_for_each_entry(link, &cache->c_items, ce_list) { 00933 if (!strcmp(name, link->l_name)) { 00934 nl_object_get((struct nl_object *) link); 00935 return link; 00936 } 00937 } 00938 00939 return NULL; 00940 } 00941 00942 /** 00943 * Construct RTM_GETLINK netlink message 00944 * @arg ifindex Interface index 00945 * @arg name Name of link 00946 * @arg result Pointer to store resulting netlink message 00947 * 00948 * The behaviour of this function is identical to rtnl_link_get_kernel() 00949 * with the exception that it will not send the message but return it in 00950 * the provided return pointer instead. 00951 * 00952 * @see rtnl_link_get_kernel() 00953 * 00954 * @return 0 on success or a negative error code. 00955 */ 00956 int rtnl_link_build_get_request(int ifindex, const char *name, 00957 struct nl_msg **result) 00958 { 00959 struct ifinfomsg ifi; 00960 struct nl_msg *msg; 00961 00962 if (ifindex <= 0 && !name) { 00963 APPBUG("ifindex or name must be specified"); 00964 return -NLE_MISSING_ATTR; 00965 } 00966 00967 memset(&ifi, 0, sizeof(ifi)); 00968 00969 if (!(msg = nlmsg_alloc_simple(RTM_GETLINK, 0))) 00970 return -NLE_NOMEM; 00971 00972 if (ifindex > 0) 00973 ifi.ifi_index = ifindex; 00974 00975 if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) 00976 goto nla_put_failure; 00977 00978 if (name) 00979 NLA_PUT_STRING(msg, IFLA_IFNAME, name); 00980 00981 *result = msg; 00982 return 0; 00983 00984 nla_put_failure: 00985 nlmsg_free(msg); 00986 return -NLE_MSGSIZE; 00987 } 00988 00989 /** 00990 * Get a link object directly from kernel 00991 * @arg sk Netlink socket 00992 * @arg ifindex Interface index 00993 * @arg name Name of link 00994 * @arg result Pointer to store resulting link object 00995 * 00996 * This function builds a \c RTM_GETLINK netlink message to request 00997 * a specific link directly from the kernel. The returned answer is 00998 * parsed into a struct rtnl_link object and returned via the result 00999 * pointer or -NLE_OBJ_NOTFOUND is returned if no matching link was 01000 * found. 01001 * 01002 * @route_doc{link_direct_lookup, Lookup Single Link (Direct Lookup)} 01003 * @return 0 on success or a negative error code. 01004 */ 01005 int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, 01006 struct rtnl_link **result) 01007 { 01008 struct nl_msg *msg = NULL; 01009 struct nl_object *obj; 01010 int err; 01011 01012 if ((err = rtnl_link_build_get_request(ifindex, name, &msg)) < 0) 01013 return err; 01014 01015 err = nl_send_auto(sk, msg); 01016 nlmsg_free(msg); 01017 if (err < 0) 01018 return err; 01019 01020 if ((err = nl_pickup(sk, link_msg_parser, &obj)) < 0) 01021 return err; 01022 01023 /* We have used link_msg_parser(), object is definitely a link */ 01024 *result = (struct rtnl_link *) obj; 01025 01026 /* If an object has been returned, we also need to wait for the ACK */ 01027 if (err == 0 && obj) 01028 nl_wait_for_ack(sk); 01029 01030 return 0; 01031 } 01032 01033 /** 01034 * Translate interface index to corresponding link name 01035 * @arg cache Link cache 01036 * @arg ifindex Interface index 01037 * @arg dst String to store name 01038 * @arg len Length of destination string 01039 * 01040 * Translates the specified interface index to the corresponding 01041 * link name and stores the name in the destination string. 01042 * 01043 * @route_doc{link_translate_ifindex, Translating interface index to link name} 01044 * @see rtnl_link_name2i() 01045 * @return Name of link or NULL if no match was found. 01046 */ 01047 char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, 01048 size_t len) 01049 { 01050 struct rtnl_link *link = rtnl_link_get(cache, ifindex); 01051 01052 if (link) { 01053 strncpy(dst, link->l_name, len - 1); 01054 rtnl_link_put(link); 01055 return dst; 01056 } 01057 01058 return NULL; 01059 } 01060 01061 /** 01062 * Translate link name to corresponding interface index 01063 * @arg cache Link cache 01064 * @arg name Name of link 01065 * 01066 * @route_doc{link_translate_ifindex, Translating interface index to link name} 01067 * @see rtnl_link_i2name() 01068 * @return Interface index or 0 if no match was found. 01069 */ 01070 int rtnl_link_name2i(struct nl_cache *cache, const char *name) 01071 { 01072 int ifindex = 0; 01073 struct rtnl_link *link; 01074 01075 link = rtnl_link_get_by_name(cache, name); 01076 if (link) { 01077 ifindex = link->l_index; 01078 rtnl_link_put(link); 01079 } 01080 01081 return ifindex; 01082 } 01083 01084 /** @} */ 01085 01086 static int build_link_msg(int cmd, struct ifinfomsg *hdr, 01087 struct rtnl_link *link, int flags, struct nl_msg **result) 01088 { 01089 struct nl_msg *msg; 01090 struct nlattr *af_spec; 01091 01092 msg = nlmsg_alloc_simple(cmd, flags); 01093 if (!msg) 01094 return -NLE_NOMEM; 01095 01096 if (nlmsg_append(msg, hdr, sizeof(*hdr), NLMSG_ALIGNTO) < 0) 01097 goto nla_put_failure; 01098 01099 if (link->ce_mask & LINK_ATTR_ADDR) 01100 NLA_PUT_ADDR(msg, IFLA_ADDRESS, link->l_addr); 01101 01102 if (link->ce_mask & LINK_ATTR_BRD) 01103 NLA_PUT_ADDR(msg, IFLA_BROADCAST, link->l_bcast); 01104 01105 if (link->ce_mask & LINK_ATTR_MTU) 01106 NLA_PUT_U32(msg, IFLA_MTU, link->l_mtu); 01107 01108 if (link->ce_mask & LINK_ATTR_TXQLEN) 01109 NLA_PUT_U32(msg, IFLA_TXQLEN, link->l_txqlen); 01110 01111 if (link->ce_mask & LINK_ATTR_WEIGHT) 01112 NLA_PUT_U32(msg, IFLA_WEIGHT, link->l_weight); 01113 01114 if (link->ce_mask & LINK_ATTR_IFNAME) 01115 NLA_PUT_STRING(msg, IFLA_IFNAME, link->l_name); 01116 01117 if (link->ce_mask & LINK_ATTR_OPERSTATE) 01118 NLA_PUT_U8(msg, IFLA_OPERSTATE, link->l_operstate); 01119 01120 if (link->ce_mask & LINK_ATTR_LINKMODE) 01121 NLA_PUT_U8(msg, IFLA_LINKMODE, link->l_linkmode); 01122 01123 if (link->ce_mask & LINK_ATTR_IFALIAS) 01124 NLA_PUT_STRING(msg, IFLA_IFALIAS, link->l_ifalias); 01125 01126 if (link->ce_mask & LINK_ATTR_LINK) 01127 NLA_PUT_U32(msg, IFLA_LINK, link->l_link); 01128 01129 if (link->ce_mask & LINK_ATTR_MASTER) 01130 NLA_PUT_U32(msg, IFLA_MASTER, link->l_master); 01131 01132 if (link->ce_mask & LINK_ATTR_LINKINFO) { 01133 struct nlattr *info; 01134 01135 if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) 01136 goto nla_put_failure; 01137 01138 NLA_PUT_STRING(msg, IFLA_INFO_KIND, link->l_info_kind); 01139 01140 if (link->l_info_ops) { 01141 if (link->l_info_ops->io_put_attrs && 01142 link->l_info_ops->io_put_attrs(msg, link) < 0) 01143 goto nla_put_failure; 01144 } 01145 01146 nla_nest_end(msg, info); 01147 } 01148 01149 if (!(af_spec = nla_nest_start(msg, IFLA_AF_SPEC))) 01150 goto nla_put_failure; 01151 01152 if (do_foreach_af(link, af_fill, msg) < 0) 01153 goto nla_put_failure; 01154 01155 nla_nest_end(msg, af_spec); 01156 01157 *result = msg; 01158 return 0; 01159 01160 nla_put_failure: 01161 nlmsg_free(msg); 01162 return -NLE_MSGSIZE; 01163 } 01164 01165 /** 01166 * @name Add / Modify 01167 * @{ 01168 */ 01169 01170 /** 01171 * Build a netlink message requesting the addition of new virtual link 01172 * @arg link new link to add 01173 * @arg flags additional netlink message flags 01174 * @arg result pointer to store resulting netlink message 01175 * 01176 * The behaviour of this function is identical to rtnl_link_add() with 01177 * the exception that it will not send the message but return it in the 01178 * provided return pointer instead. 01179 * 01180 * @see rtnl_link_add() 01181 * 01182 * @note This operation is not supported on all kernel versions. 01183 * 01184 * @return 0 on success or a negative error code. 01185 */ 01186 int rtnl_link_build_add_request(struct rtnl_link *link, int flags, 01187 struct nl_msg **result) 01188 { 01189 struct ifinfomsg ifi = { 01190 .ifi_family = link->l_family, 01191 .ifi_index = link->l_index, 01192 .ifi_flags = link->l_flags, 01193 }; 01194 01195 return build_link_msg(RTM_NEWLINK, &ifi, link, flags, result); 01196 } 01197 01198 /** 01199 * Add virtual link 01200 * @arg sk netlink socket. 01201 * @arg link new link to add 01202 * @arg flags additional netlink message flags 01203 * 01204 * Builds a \c RTM_NEWLINK netlink message requesting the addition of 01205 * a new virtual link. 01206 * 01207 * After sending, the function will wait for the ACK or an eventual 01208 * error message to be received and will therefore block until the 01209 * operation has been completed. 01210 * 01211 * @copydoc auto_ack_warning 01212 * 01213 * @return 0 on success or a negative error code. 01214 */ 01215 int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags) 01216 { 01217 struct nl_msg *msg; 01218 int err; 01219 01220 err = rtnl_link_build_add_request(link, flags, &msg); 01221 if (err < 0) 01222 return err; 01223 01224 return nl_send_sync(sk, msg); 01225 } 01226 01227 /** 01228 * Build a netlink message requesting the modification of link 01229 * @arg orig original link to change 01230 * @arg changes link containing the changes to be made 01231 * @arg flags additional netlink message flags 01232 * @arg result pointer to store resulting netlink message 01233 * 01234 * The behaviour of this function is identical to rtnl_link_change() with 01235 * the exception that it will not send the message but return it in the 01236 * provided return pointer instead. 01237 * 01238 * @see rtnl_link_change() 01239 * 01240 * @note The resulting message will have message type set to RTM_NEWLINK 01241 * which may not work with older kernels. You may have to modify it 01242 * to RTM_SETLINK (does not allow changing link info attributes) to 01243 * have the change request work with older kernels. 01244 * 01245 * @return 0 on success or a negative error code. 01246 */ 01247 int rtnl_link_build_change_request(struct rtnl_link *orig, 01248 struct rtnl_link *changes, int flags, 01249 struct nl_msg **result) 01250 { 01251 struct ifinfomsg ifi = { 01252 .ifi_family = orig->l_family, 01253 .ifi_index = orig->l_index, 01254 }; 01255 int err; 01256 01257 if (changes->ce_mask & LINK_ATTR_FLAGS) { 01258 ifi.ifi_flags = orig->l_flags & ~changes->l_flag_mask; 01259 ifi.ifi_flags |= changes->l_flags; 01260 } 01261 01262 if (changes->l_family && changes->l_family != orig->l_family) { 01263 APPBUG("link change: family is immutable"); 01264 return -NLE_IMMUTABLE; 01265 } 01266 01267 /* Avoid unnecessary name change requests */ 01268 if (orig->ce_mask & LINK_ATTR_IFINDEX && 01269 orig->ce_mask & LINK_ATTR_IFNAME && 01270 changes->ce_mask & LINK_ATTR_IFNAME && 01271 !strcmp(orig->l_name, changes->l_name)) 01272 changes->ce_mask &= ~LINK_ATTR_IFNAME; 01273 01274 if ((err = build_link_msg(RTM_NEWLINK, &ifi, changes, flags, result)) < 0) 01275 goto errout; 01276 01277 return 0; 01278 01279 errout: 01280 return err; 01281 } 01282 01283 /** 01284 * Change link 01285 * @arg sk netlink socket. 01286 * @arg orig original link to be changed 01287 * @arg changes link containing the changes to be made 01288 * @arg flags additional netlink message flags 01289 * 01290 * Builds a \c RTM_NEWLINK netlink message requesting the change of 01291 * a network link. If -EOPNOTSUPP is returned by the kernel, the 01292 * message type will be changed to \c RTM_SETLINK and the message is 01293 * resent to work around older kernel versions. 01294 * 01295 * The link to be changed is looked up based on the interface index 01296 * supplied in the \p orig link. Optionaly the link name is used but 01297 * only if no interface index is provided, otherwise providing an 01298 * link name will result in the link name being changed. 01299 * 01300 * If no matching link exists, the function will return 01301 * -NLE_OBJ_NOTFOUND. 01302 * 01303 * After sending, the function will wait for the ACK or an eventual 01304 * error message to be received and will therefore block until the 01305 * operation has been completed. 01306 * 01307 * @copydoc auto_ack_warning 01308 * 01309 * @note The link name can only be changed if the link has been put 01310 * in opertional down state. (~IF_UP) 01311 * 01312 * @return 0 on success or a negative error code. 01313 */ 01314 int rtnl_link_change(struct nl_sock *sk, struct rtnl_link *orig, 01315 struct rtnl_link *changes, int flags) 01316 { 01317 struct nl_msg *msg; 01318 int err; 01319 01320 err = rtnl_link_build_change_request(orig, changes, flags, &msg); 01321 if (err < 0) 01322 return err; 01323 01324 retry: 01325 err = nl_send_auto_complete(sk, msg); 01326 if (err < 0) 01327 goto errout; 01328 01329 err = wait_for_ack(sk); 01330 if (err == -NLE_OPNOTSUPP && msg->nm_nlh->nlmsg_type == RTM_NEWLINK) { 01331 msg->nm_nlh->nlmsg_type = RTM_SETLINK; 01332 goto retry; 01333 } 01334 01335 errout: 01336 nlmsg_free(msg); 01337 return err; 01338 } 01339 01340 /** @} */ 01341 01342 /** 01343 * @name Delete 01344 * @{ 01345 */ 01346 01347 /** 01348 * Build a netlink message requesting the deletion of a link 01349 * @arg link Link to delete 01350 * @arg result Pointer to store resulting netlink message 01351 * 01352 * The behaviour of this function is identical to rtnl_link_delete() with 01353 * the exception that it will not send the message but return it in the 01354 * provided return pointer instead. 01355 * 01356 * @see rtnl_link_delete() 01357 * 01358 * @return 0 on success or a negative error code. 01359 */ 01360 int rtnl_link_build_delete_request(const struct rtnl_link *link, 01361 struct nl_msg **result) 01362 { 01363 struct nl_msg *msg; 01364 struct ifinfomsg ifi = { 01365 .ifi_index = link->l_index, 01366 }; 01367 01368 if (!(link->ce_mask & (LINK_ATTR_IFINDEX | LINK_ATTR_IFNAME))) { 01369 APPBUG("ifindex or name must be specified"); 01370 return -NLE_MISSING_ATTR; 01371 } 01372 01373 if (!(msg = nlmsg_alloc_simple(RTM_DELLINK, 0))) 01374 return -NLE_NOMEM; 01375 01376 if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) 01377 goto nla_put_failure; 01378 01379 if (link->ce_mask & LINK_ATTR_IFNAME) 01380 NLA_PUT_STRING(msg, IFLA_IFNAME, link->l_name); 01381 01382 *result = msg; 01383 return 0; 01384 01385 nla_put_failure: 01386 nlmsg_free(msg); 01387 return -NLE_MSGSIZE; 01388 } 01389 01390 /** 01391 * Delete link 01392 * @arg sk Netlink socket 01393 * @arg link Link to delete 01394 * 01395 * Builds a \c RTM_DELLINK netlink message requesting the deletion of 01396 * a network link which has been previously added to the kernel and 01397 * sends the message to the kernel. 01398 * 01399 * If no matching link exists, the function will return 01400 * -NLE_OBJ_NOTFOUND. 01401 * 01402 * After sending, the function will wait for the ACK or an eventual 01403 * error message to be received and will therefore block until the 01404 * operation has been completed. 01405 * 01406 * @copydoc auto_ack_warning 01407 * 01408 * @note Only virtual links such as dummy interface or vlan interfaces 01409 * can be deleted. It is not possible to delete physical interfaces 01410 * such as ethernet interfaces or the loopback device. 01411 * 01412 * @return 0 on success or a negative error code. 01413 */ 01414 int rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *link) 01415 { 01416 struct nl_msg *msg; 01417 int err; 01418 01419 if ((err = rtnl_link_build_delete_request(link, &msg)) < 0) 01420 return err; 01421 01422 return nl_send_sync(sk, msg); 01423 } 01424 01425 /** @} */ 01426 01427 /** 01428 * @name Link Object 01429 * @{ 01430 */ 01431 01432 /** 01433 * Allocate link object 01434 * 01435 * @see rtnl_link_put() 01436 * @return New link object or NULL if allocation failed 01437 */ 01438 struct rtnl_link *rtnl_link_alloc(void) 01439 { 01440 return (struct rtnl_link *) nl_object_alloc(&link_obj_ops); 01441 } 01442 01443 /** 01444 * Return a link object reference 01445 * 01446 * @copydetails nl_object_put() 01447 */ 01448 void rtnl_link_put(struct rtnl_link *link) 01449 { 01450 nl_object_put((struct nl_object *) link); 01451 } 01452 01453 /** 01454 * Set name of link object 01455 * @arg link Link object 01456 * @arg name New name 01457 * 01458 * @note To change the name of a link in the kernel, set the interface 01459 * index to the link you wish to change, modify the link name using 01460 * this function and pass the link object to rtnl_link_change() or 01461 * rtnl_link_add(). 01462 * 01463 * @route_doc{link_attr_name, Link Name} 01464 * @see rtnl_link_get_name() 01465 * @see rtnl_link_set_ifindex() 01466 */ 01467 void rtnl_link_set_name(struct rtnl_link *link, const char *name) 01468 { 01469 strncpy(link->l_name, name, sizeof(link->l_name) - 1); 01470 link->ce_mask |= LINK_ATTR_IFNAME; 01471 } 01472 01473 /** 01474 * Return name of link object 01475 * @arg link Link object 01476 * 01477 * @route_doc{link_attr_name, Link Name} 01478 * @see rtnl_link_set_name() 01479 * @return Link name or NULL if name is not specified 01480 */ 01481 char *rtnl_link_get_name(struct rtnl_link *link) 01482 { 01483 return link->ce_mask & LINK_ATTR_IFNAME ? link->l_name : NULL; 01484 } 01485 01486 static inline void __assign_addr(struct rtnl_link *link, struct nl_addr **pos, 01487 struct nl_addr *new, int flag) 01488 { 01489 if (*pos) 01490 nl_addr_put(*pos); 01491 01492 nl_addr_get(new); 01493 *pos = new; 01494 01495 link->ce_mask |= flag; 01496 } 01497 01498 /** 01499 * Set link layer address of link object 01500 * @arg link Link object 01501 * @arg addr New link layer address 01502 * 01503 * The function increments the reference counter of the address object 01504 * and overwrites any existing link layer address previously assigned. 01505 * 01506 * @route_doc{link_attr_address, Link layer address} 01507 * @see rtnl_link_get_addr() 01508 */ 01509 void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr) 01510 { 01511 __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR); 01512 } 01513 01514 /** 01515 * Return link layer address of link object 01516 * @arg link Link object 01517 * 01518 * @copydoc pointer_lifetime_warning 01519 * @route_doc{link_attr_address, Link Layer Address} 01520 * @see rtnl_link_set_addr() 01521 * @return Link layer address or NULL if not set. 01522 */ 01523 struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link) 01524 { 01525 return link->ce_mask & LINK_ATTR_ADDR ? link->l_addr : NULL; 01526 } 01527 01528 /** 01529 * Set link layer broadcast address of link object 01530 * @arg link Link object 01531 * @arg addr New broadcast address 01532 * 01533 * The function increments the reference counter of the address object 01534 * and overwrites any existing link layer broadcast address previously 01535 * assigned. 01536 * 01537 * @route_doc{link_attr_broadcast, Link Layer Broadcast Address} 01538 * @see rtnl_link_get_broadcast() 01539 */ 01540 void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *addr) 01541 { 01542 __assign_addr(link, &link->l_bcast, addr, LINK_ATTR_BRD); 01543 } 01544 01545 /** 01546 * Return link layer broadcast address of link object 01547 * @arg link Link object 01548 * 01549 * @copydoc pointer_lifetime_warning 01550 * @route_doc{link_attr_address, Link Layer Address} 01551 * @see rtnl_link_set_broadcast() 01552 * @return Link layer address or NULL if not set. 01553 */ 01554 struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link) 01555 { 01556 return link->ce_mask & LINK_ATTR_BRD ? link->l_bcast : NULL; 01557 } 01558 01559 /** 01560 * Set flags of link object 01561 * @arg link Link object 01562 * @arg flags Flags 01563 * 01564 * @see rtnl_link_get_flags() 01565 * @see rtnl_link_unset_flags() 01566 */ 01567 void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags) 01568 { 01569 link->l_flag_mask |= flags; 01570 link->l_flags |= flags; 01571 link->ce_mask |= LINK_ATTR_FLAGS; 01572 } 01573 01574 /** 01575 * Unset flags of link object 01576 * @arg link Link object 01577 * @arg flags Flags 01578 * 01579 * @see rtnl_link_set_flags() 01580 * @see rtnl_link_get_flags() 01581 */ 01582 void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags) 01583 { 01584 link->l_flag_mask |= flags; 01585 link->l_flags &= ~flags; 01586 link->ce_mask |= LINK_ATTR_FLAGS; 01587 } 01588 01589 /** 01590 * Return flags of link object 01591 * @arg link Link object 01592 * 01593 * @route_doc{link_attr_flags, Link Flags} 01594 * @see rtnl_link_set_flags() 01595 * @see rtnl_link_unset_flags() 01596 * @return Link flags or 0 if none have been set. 01597 */ 01598 unsigned int rtnl_link_get_flags(struct rtnl_link *link) 01599 { 01600 return link->l_flags; 01601 } 01602 01603 /** 01604 * Set address family of link object 01605 * 01606 * @see rtnl_link_get_family() 01607 */ 01608 void rtnl_link_set_family(struct rtnl_link *link, int family) 01609 { 01610 link->l_family = family; 01611 link->ce_mask |= LINK_ATTR_FAMILY; 01612 } 01613 01614 /** 01615 * Return address family of link object 01616 * @arg link Link object 01617 * 01618 * @see rtnl_link_set_family() 01619 * @return Address family or \c AF_UNSPEC if not specified. 01620 */ 01621 int rtnl_link_get_family(struct rtnl_link *link) 01622 { 01623 return link->ce_mask & LINK_ATTR_FAMILY ? link->l_family : AF_UNSPEC; 01624 } 01625 01626 /** 01627 * Set hardware type of link object 01628 * @arg link Link object 01629 * @arg arptype New hardware type \c (ARPHRD_*) 01630 * 01631 * @route_doc{link_attr_arptype, Hardware Type} 01632 * @copydoc read_only_attribute 01633 * @see rtnl_link_get_arptype() 01634 */ 01635 void rtnl_link_set_arptype(struct rtnl_link *link, unsigned int arptype) 01636 { 01637 link->l_arptype = arptype; 01638 link->ce_mask |= LINK_ATTR_ARPTYPE; 01639 } 01640 01641 /** 01642 * Get hardware type of link object 01643 * @arg link Link object 01644 * 01645 * @route_doc{link_attr_arptype, Hardware Type} 01646 * @see rtnl_link_set_arptype() 01647 * @return Hardware type \c (ARPHRD_ETHER *) or \c ARPHRD_VOID 01648 */ 01649 unsigned int rtnl_link_get_arptype(struct rtnl_link *link) 01650 { 01651 if (link->ce_mask & LINK_ATTR_ARPTYPE) 01652 return link->l_arptype; 01653 else 01654 return ARPHRD_VOID; 01655 } 01656 01657 /** 01658 * Set interface index of link object 01659 * @arg link Link object 01660 * @arg ifindex Interface index 01661 * 01662 * @route_doc{link_attr_ifindex, Interface Index} 01663 * @see rtnl_link_get_ifindex() 01664 */ 01665 void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex) 01666 { 01667 link->l_index = ifindex; 01668 link->ce_mask |= LINK_ATTR_IFINDEX; 01669 } 01670 01671 01672 /** 01673 * Return interface index of link object 01674 * @arg link Link object 01675 * 01676 * @route_doc{link_attr_ifindex, Interface Index} 01677 * @see rtnl_link_set_ifindex() 01678 * @return Interface index or 0 if not set. 01679 */ 01680 int rtnl_link_get_ifindex(struct rtnl_link *link) 01681 { 01682 return link->l_index; 01683 } 01684 01685 /** 01686 * Set Maximum Transmission Unit of link object 01687 * @arg link Link object 01688 * @arg mtu New MTU value in number of bytes 01689 * 01690 * @route_doc{link_attr_mtu, Maximum Transmission Unit} 01691 * @see rtnl_link_get_mtu() 01692 */ 01693 void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu) 01694 { 01695 link->l_mtu = mtu; 01696 link->ce_mask |= LINK_ATTR_MTU; 01697 } 01698 01699 /** 01700 * Return maximum transmission unit of link object 01701 * @arg link Link object 01702 * 01703 * @route_doc{link_attr_mtu, Maximum Transmission Unit} 01704 * @see rtnl_link_set_mtu() 01705 * @return MTU in bytes or 0 if not set 01706 */ 01707 unsigned int rtnl_link_get_mtu(struct rtnl_link *link) 01708 { 01709 return link->l_mtu; 01710 } 01711 01712 /** 01713 * Set transmission queue length 01714 * @arg link Link object 01715 * @arg txqlen New queue length 01716 * 01717 * The unit is dependant on the link type. The most common units is number 01718 * of packets. 01719 * 01720 * @route_doc{link_attr_txqlen, Transmission Queue Length} 01721 */ 01722 void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen) 01723 { 01724 link->l_txqlen = txqlen; 01725 link->ce_mask |= LINK_ATTR_TXQLEN; 01726 } 01727 01728 /** 01729 * Return transmission queue length 01730 * @arg link Link object 01731 * 01732 * The unit is dependant on the link type. The most common units is number 01733 * of packets. 01734 * 01735 * @route_doc{link_attr_txqlen, Transmission Queue Length} 01736 * @return queue length or 0 if not specified. 01737 */ 01738 unsigned int rtnl_link_get_txqlen(struct rtnl_link *link) 01739 { 01740 return link->ce_mask & LINK_ATTR_TXQLEN ? link->l_txqlen : 0; 01741 } 01742 01743 void rtnl_link_set_link(struct rtnl_link *link, int ifindex) 01744 { 01745 link->l_link = ifindex; 01746 link->ce_mask |= LINK_ATTR_LINK; 01747 } 01748 01749 int rtnl_link_get_link(struct rtnl_link *link) 01750 { 01751 return link->l_link; 01752 } 01753 01754 /** 01755 * Set master link of link object 01756 * @arg link Link object 01757 * @arg ifindex Interface index of master link 01758 * 01759 * @see rtnl_link_get_master() 01760 */ 01761 void rtnl_link_set_master(struct rtnl_link *link, int ifindex) 01762 { 01763 link->l_master = ifindex; 01764 link->ce_mask |= LINK_ATTR_MASTER; 01765 } 01766 01767 /** 01768 * Return master link of link object 01769 * @arg link Link object 01770 * 01771 * @see rtnl_link_set_master() 01772 * @return Interface index of master link or 0 if not specified 01773 */ 01774 int rtnl_link_get_master(struct rtnl_link *link) 01775 { 01776 return link->l_master; 01777 } 01778 01779 /** 01780 * Set operational status of link object 01781 * @arg link Link object 01782 * @arg status New opertional status 01783 * 01784 * @route_doc{link_attr_operstate, Operational Status}} 01785 * @see rtnl_link_get_operstate() 01786 */ 01787 void rtnl_link_set_operstate(struct rtnl_link *link, uint8_t status) 01788 { 01789 link->l_operstate = status; 01790 link->ce_mask |= LINK_ATTR_OPERSTATE; 01791 } 01792 01793 /** 01794 * Return operational status of link object 01795 * @arg link Link object 01796 * 01797 * @route_doc{link_attr_operstate, Operational Status} 01798 * @see rtnl_link_set_operstate() 01799 * @return Opertional state or \c IF_OPER_UNKNOWN 01800 */ 01801 uint8_t rtnl_link_get_operstate(struct rtnl_link *link) 01802 { 01803 return link->l_operstate; 01804 } 01805 01806 /** 01807 * Set link mode of link object 01808 * @arg link Link object 01809 * @arg mode New link mode 01810 * 01811 * @route_doc{link_attr_mode, Mode} 01812 * @see rtnl_link_get_linkmode() 01813 */ 01814 void rtnl_link_set_linkmode(struct rtnl_link *link, uint8_t mode) 01815 { 01816 link->l_linkmode = mode; 01817 link->ce_mask |= LINK_ATTR_LINKMODE; 01818 } 01819 01820 /** 01821 * Return link mode of link object 01822 * @arg link Link object 01823 * 01824 * @route_doc{link_attr_mode, Mode} 01825 * @see rtnl_link_get_linkmode() 01826 * @return Link mode or \c IF_LINK_MODE_DEFAULT 01827 */ 01828 uint8_t rtnl_link_get_linkmode(struct rtnl_link *link) 01829 { 01830 return link->l_linkmode; 01831 } 01832 01833 /** 01834 * Return alias name of link object (SNMP IfAlias) 01835 * @arg link Link object 01836 * 01837 * @route_doc{link_attr_alias, Alias} 01838 * @see rtnl_link_set_ifalias() 01839 * @return Alias name or NULL if not set. 01840 */ 01841 const char *rtnl_link_get_ifalias(struct rtnl_link *link) 01842 { 01843 return link->l_ifalias; 01844 } 01845 01846 /** 01847 * Set alias name of link object (SNMP IfAlias) 01848 * @arg link Link object 01849 * @arg alias Alias name or NULL to unset 01850 * 01851 * Sets the alias name of the link to the specified name. The alias 01852 * name can be unset by specyfing NULL as the alias. The name will 01853 * be strdup()ed, so no need to provide a persistent character string. 01854 * 01855 * @route_doc{link_attr_alias, Alias} 01856 * @see rtnl_link_get_ifalias() 01857 */ 01858 void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias) 01859 { 01860 free(link->l_ifalias); 01861 link->ce_mask &= ~LINK_ATTR_IFALIAS; 01862 01863 if (alias) { 01864 link->l_ifalias = strdup(alias); 01865 link->ce_mask |= LINK_ATTR_IFALIAS; 01866 } 01867 } 01868 01869 /** 01870 * Set queueing discipline name of link object 01871 * @arg link Link object 01872 * @arg name Name of queueing discipline 01873 * 01874 * @copydoc read_only_attribute 01875 * 01876 * For more information on how to modify the qdisc of a link, see section 01877 * @ref_route{route_tc, Traffic Control}. 01878 * 01879 * @route_doc{link_attr_qdisc, Queueing Discipline Name} 01880 * @see rtnl_link_get_qdisc() 01881 */ 01882 void rtnl_link_set_qdisc(struct rtnl_link *link, const char *name) 01883 { 01884 strncpy(link->l_qdisc, name, sizeof(link->l_qdisc) - 1); 01885 link->ce_mask |= LINK_ATTR_QDISC; 01886 } 01887 01888 /** 01889 * Return name of queueing discipline of link object 01890 * @arg link Link object 01891 * 01892 * @route_doc{link_attr_qdisc, Queueing Discipline Name} 01893 * @see rtnl_link_set_qdisc() 01894 * @return Name of qdisc or NULL if not specified. 01895 */ 01896 char *rtnl_link_get_qdisc(struct rtnl_link *link) 01897 { 01898 return link->ce_mask & LINK_ATTR_QDISC ? link->l_qdisc : NULL; 01899 } 01900 01901 01902 /** 01903 * Return number of PCI virtual functions of link object 01904 * @arg link Link object 01905 * @arg num_vf Pointer to store number of VFs 01906 * 01907 * @return 0 on success or -NLE_OPNOTSUPP if not available 01908 */ 01909 int rtnl_link_get_num_vf(struct rtnl_link *link, uint32_t *num_vf) 01910 { 01911 if (link->ce_mask & LINK_ATTR_NUM_VF) { 01912 *num_vf = link->l_num_vf; 01913 return 0; 01914 } else 01915 return -NLE_OPNOTSUPP; 01916 } 01917 01918 /** 01919 * Return value of link statistics counter 01920 * @arg link Link object 01921 * @arg id Identifier of statistical counter 01922 * 01923 * @return Value of counter or 0 if not specified. 01924 */ 01925 uint64_t rtnl_link_get_stat(struct rtnl_link *link, rtnl_link_stat_id_t id) 01926 { 01927 if (id > RTNL_LINK_STATS_MAX) 01928 return 0; 01929 01930 return link->l_stats[id]; 01931 } 01932 01933 /** 01934 * Set value of link statistics counter 01935 * @arg link Link object 01936 * @arg id Identifier of statistical counter 01937 * @arg value New value 01938 * 01939 * \note Changing the value of a statistical counter will not change the 01940 * value in the kernel. 01941 * 01942 * @return 0 on success or a negative error code 01943 */ 01944 int rtnl_link_set_stat(struct rtnl_link *link, rtnl_link_stat_id_t id, 01945 const uint64_t value) 01946 { 01947 if (id > RTNL_LINK_STATS_MAX) 01948 return -NLE_INVAL; 01949 01950 link->l_stats[id] = value; 01951 01952 return 0; 01953 } 01954 01955 /** 01956 * Set type of link object 01957 * @arg link Link object 01958 * @arg type Name of link type 01959 * 01960 * Looks up the link type module and prepares the link to store type 01961 * specific attributes. If a type has been assigned already it will 01962 * be released with all link type specific attributes lost. 01963 * 01964 * @route_doc{link_modules, Link Modules} 01965 * @return 0 on success or a negative errror code. 01966 */ 01967 int rtnl_link_set_type(struct rtnl_link *link, const char *type) 01968 { 01969 struct rtnl_link_info_ops *io; 01970 int err; 01971 char *kind; 01972 01973 free(link->l_info_kind); 01974 link->ce_mask &= ~LINK_ATTR_LINKINFO; 01975 if (link->l_info_ops) 01976 release_link_info(link); 01977 01978 if (!type) 01979 return 0; 01980 01981 kind = strdup(type); 01982 if (!kind) 01983 return -NLE_NOMEM; 01984 01985 io = rtnl_link_info_ops_lookup(type); 01986 if (io) { 01987 if (io->io_alloc && (err = io->io_alloc(link)) < 0) 01988 goto errout; 01989 01990 link->l_info_ops = io; 01991 } 01992 01993 link->l_info_kind = kind; 01994 link->ce_mask |= LINK_ATTR_LINKINFO; 01995 01996 return 0; 01997 01998 errout: 01999 free(kind); 02000 return err; 02001 } 02002 02003 /** 02004 * Return type of link 02005 * @arg link Link object 02006 * 02007 * @route_doc{link_modules, Link Modules} 02008 * @return Name of link type or NULL if not specified. 02009 */ 02010 char *rtnl_link_get_type(struct rtnl_link *link) 02011 { 02012 return link->l_info_kind; 02013 } 02014 02015 /** @} */ 02016 02017 /** 02018 * @name Master/Slave 02019 * @{ 02020 */ 02021 02022 /** 02023 * Enslave slave link to master link 02024 * @arg sock netlink socket 02025 * @arg master ifindex of master link 02026 * @arg slave ifindex of slave link 02027 * 02028 * This function is identical to rtnl_link_enslave() except that 02029 * it takes interface indices instead of rtnl_link objects. 02030 * 02031 * @see rtnl_link_enslave() 02032 * 02033 * @return 0 on success or a negative error code. 02034 */ 02035 int rtnl_link_enslave_ifindex(struct nl_sock *sock, int master, int slave) 02036 { 02037 struct rtnl_link *link; 02038 int err; 02039 02040 if (!(link = rtnl_link_alloc())) 02041 return -NLE_NOMEM; 02042 02043 rtnl_link_set_ifindex(link, slave); 02044 rtnl_link_set_master(link, master); 02045 02046 if ((err = rtnl_link_change(sock, link, link, 0)) < 0) 02047 goto errout; 02048 02049 rtnl_link_put(link); 02050 02051 /* 02052 * Due to the kernel not signaling whether this opertion is 02053 * supported or not, we will retrieve the attribute to see if the 02054 * request was successful. If the master assigned remains unchanged 02055 * we will return NLE_OPNOTSUPP to allow performing backwards 02056 * compatibility of some sort. 02057 */ 02058 if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0) 02059 return err; 02060 02061 if (rtnl_link_get_master(link) != master) 02062 err = -NLE_OPNOTSUPP; 02063 02064 errout: 02065 rtnl_link_put(link); 02066 02067 return err; 02068 } 02069 02070 /** 02071 * Enslave slave link to master link 02072 * @arg sock netlink socket 02073 * @arg master master link 02074 * @arg slave slave link 02075 * 02076 * Constructs a RTM_NEWLINK or RTM_SETLINK message adding the slave to 02077 * the master and sends the request via the specified netlink socket. 02078 * 02079 * @note The feature of enslaving/releasing via netlink has only been added 02080 * recently to the kernel (Feb 2011). Also, the kernel does not signal 02081 * if the operation is not supported. Therefore this function will 02082 * verify if the master assignment has changed and will return 02083 * -NLE_OPNOTSUPP if it did not. 02084 * 02085 * @see rtnl_link_enslave_ifindex() 02086 * @see rtnl_link_release() 02087 * 02088 * @return 0 on success or a negative error code. 02089 */ 02090 int rtnl_link_enslave(struct nl_sock *sock, struct rtnl_link *master, 02091 struct rtnl_link *slave) 02092 { 02093 return rtnl_link_enslave_ifindex(sock, rtnl_link_get_ifindex(master), 02094 rtnl_link_get_ifindex(slave)); 02095 } 02096 02097 /** 02098 * Release slave link from its master 02099 * @arg sock netlink socket 02100 * @arg slave slave link 02101 * 02102 * This function is identical to rtnl_link_release() except that 02103 * it takes an interface index instead of a rtnl_link object. 02104 * 02105 * @see rtnl_link_release() 02106 * 02107 * @return 0 on success or a negative error code. 02108 */ 02109 int rtnl_link_release_ifindex(struct nl_sock *sock, int slave) 02110 { 02111 return rtnl_link_enslave_ifindex(sock, 0, slave); 02112 } 02113 02114 /** 02115 * Release slave link from its master 02116 * @arg sock netlink socket 02117 * @arg slave slave link 02118 * 02119 * Constructs a RTM_NEWLINK or RTM_SETLINK message releasing the slave from 02120 * its master and sends the request via the specified netlink socket. 02121 * 02122 * @note The feature of enslaving/releasing via netlink has only been added 02123 * recently to the kernel (Feb 2011). Also, the kernel does not signal 02124 * if the operation is not supported. Therefore this function will 02125 * verify if the master assignment has changed and will return 02126 * -NLE_OPNOTSUPP if it did not. 02127 * 02128 * @see rtnl_link_release_ifindex() 02129 * @see rtnl_link_enslave() 02130 * 02131 * @return 0 on success or a negative error code. 02132 */ 02133 int rtnl_link_release(struct nl_sock *sock, struct rtnl_link *slave) 02134 { 02135 return rtnl_link_release_ifindex(sock, rtnl_link_get_ifindex(slave)); 02136 } 02137 02138 /** @} */ 02139 02140 /** 02141 * @name Utilities 02142 * @{ 02143 */ 02144 02145 static const struct trans_tbl link_flags[] = { 02146 __ADD(IFF_LOOPBACK, loopback) 02147 __ADD(IFF_BROADCAST, broadcast) 02148 __ADD(IFF_POINTOPOINT, pointopoint) 02149 __ADD(IFF_MULTICAST, multicast) 02150 __ADD(IFF_NOARP, noarp) 02151 __ADD(IFF_ALLMULTI, allmulti) 02152 __ADD(IFF_PROMISC, promisc) 02153 __ADD(IFF_MASTER, master) 02154 __ADD(IFF_SLAVE, slave) 02155 __ADD(IFF_DEBUG, debug) 02156 __ADD(IFF_DYNAMIC, dynamic) 02157 __ADD(IFF_AUTOMEDIA, automedia) 02158 __ADD(IFF_PORTSEL, portsel) 02159 __ADD(IFF_NOTRAILERS, notrailers) 02160 __ADD(IFF_UP, up) 02161 __ADD(IFF_RUNNING, running) 02162 __ADD(IFF_LOWER_UP, lowerup) 02163 __ADD(IFF_DORMANT, dormant) 02164 __ADD(IFF_ECHO, echo) 02165 }; 02166 02167 char *rtnl_link_flags2str(int flags, char *buf, size_t len) 02168 { 02169 return __flags2str(flags, buf, len, link_flags, 02170 ARRAY_SIZE(link_flags)); 02171 } 02172 02173 int rtnl_link_str2flags(const char *name) 02174 { 02175 return __str2flags(name, link_flags, ARRAY_SIZE(link_flags)); 02176 } 02177 02178 static const struct trans_tbl link_stats[] = { 02179 __ADD(RTNL_LINK_RX_PACKETS, rx_packets) 02180 __ADD(RTNL_LINK_TX_PACKETS, tx_packets) 02181 __ADD(RTNL_LINK_RX_BYTES, rx_bytes) 02182 __ADD(RTNL_LINK_TX_BYTES, tx_bytes) 02183 __ADD(RTNL_LINK_RX_ERRORS, rx_errors) 02184 __ADD(RTNL_LINK_TX_ERRORS, tx_errors) 02185 __ADD(RTNL_LINK_RX_DROPPED, rx_dropped) 02186 __ADD(RTNL_LINK_TX_DROPPED, tx_dropped) 02187 __ADD(RTNL_LINK_RX_COMPRESSED, rx_compressed) 02188 __ADD(RTNL_LINK_TX_COMPRESSED, tx_compressed) 02189 __ADD(RTNL_LINK_RX_FIFO_ERR, rx_fifo_err) 02190 __ADD(RTNL_LINK_TX_FIFO_ERR, tx_fifo_err) 02191 __ADD(RTNL_LINK_RX_LEN_ERR, rx_len_err) 02192 __ADD(RTNL_LINK_RX_OVER_ERR, rx_over_err) 02193 __ADD(RTNL_LINK_RX_CRC_ERR, rx_crc_err) 02194 __ADD(RTNL_LINK_RX_FRAME_ERR, rx_frame_err) 02195 __ADD(RTNL_LINK_RX_MISSED_ERR, rx_missed_err) 02196 __ADD(RTNL_LINK_TX_ABORT_ERR, tx_abort_err) 02197 __ADD(RTNL_LINK_TX_CARRIER_ERR, tx_carrier_err) 02198 __ADD(RTNL_LINK_TX_HBEAT_ERR, tx_hbeat_err) 02199 __ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err) 02200 __ADD(RTNL_LINK_COLLISIONS, collisions) 02201 __ADD(RTNL_LINK_MULTICAST, multicast) 02202 __ADD(RTNL_LINK_IP6_INPKTS, Ip6InReceives) 02203 __ADD(RTNL_LINK_IP6_INHDRERRORS, Ip6InHdrErrors) 02204 __ADD(RTNL_LINK_IP6_INTOOBIGERRORS, Ip6InTooBigErrors) 02205 __ADD(RTNL_LINK_IP6_INNOROUTES, Ip6InNoRoutes) 02206 __ADD(RTNL_LINK_IP6_INADDRERRORS, Ip6InAddrErrors) 02207 __ADD(RTNL_LINK_IP6_INUNKNOWNPROTOS, Ip6InUnknownProtos) 02208 __ADD(RTNL_LINK_IP6_INTRUNCATEDPKTS, Ip6InTruncatedPkts) 02209 __ADD(RTNL_LINK_IP6_INDISCARDS, Ip6InDiscards) 02210 __ADD(RTNL_LINK_IP6_INDELIVERS, Ip6InDelivers) 02211 __ADD(RTNL_LINK_IP6_OUTFORWDATAGRAMS, Ip6OutForwDatagrams) 02212 __ADD(RTNL_LINK_IP6_OUTPKTS, Ip6OutRequests) 02213 __ADD(RTNL_LINK_IP6_OUTDISCARDS, Ip6OutDiscards) 02214 __ADD(RTNL_LINK_IP6_OUTNOROUTES, Ip6OutNoRoutes) 02215 __ADD(RTNL_LINK_IP6_REASMTIMEOUT, Ip6ReasmTimeout) 02216 __ADD(RTNL_LINK_IP6_REASMREQDS, Ip6ReasmReqds) 02217 __ADD(RTNL_LINK_IP6_REASMOKS, Ip6ReasmOKs) 02218 __ADD(RTNL_LINK_IP6_REASMFAILS, Ip6ReasmFails) 02219 __ADD(RTNL_LINK_IP6_FRAGOKS, Ip6FragOKs) 02220 __ADD(RTNL_LINK_IP6_FRAGFAILS, Ip6FragFails) 02221 __ADD(RTNL_LINK_IP6_FRAGCREATES, Ip6FragCreates) 02222 __ADD(RTNL_LINK_IP6_INMCASTPKTS, Ip6InMcastPkts) 02223 __ADD(RTNL_LINK_IP6_OUTMCASTPKTS, Ip6OutMcastPkts) 02224 __ADD(RTNL_LINK_IP6_INBCASTPKTS, Ip6InBcastPkts) 02225 __ADD(RTNL_LINK_IP6_OUTBCASTPKTS, Ip6OutBcastPkts) 02226 __ADD(RTNL_LINK_IP6_INOCTETS, Ip6InOctets) 02227 __ADD(RTNL_LINK_IP6_OUTOCTETS, Ip6OutOctets) 02228 __ADD(RTNL_LINK_IP6_INMCASTOCTETS, Ip6InMcastOctets) 02229 __ADD(RTNL_LINK_IP6_OUTMCASTOCTETS, Ip6OutMcastOctets) 02230 __ADD(RTNL_LINK_IP6_INBCASTOCTETS, Ip6InBcastOctets) 02231 __ADD(RTNL_LINK_IP6_OUTBCASTOCTETS, Ip6OutBcastOctets) 02232 __ADD(RTNL_LINK_ICMP6_INMSGS, ICMP6_InMsgs) 02233 __ADD(RTNL_LINK_ICMP6_INERRORS, ICMP6_InErrors) 02234 __ADD(RTNL_LINK_ICMP6_OUTMSGS, ICMP6_OutMsgs) 02235 __ADD(RTNL_LINK_ICMP6_OUTERRORS, ICMP6_OutErrors) 02236 }; 02237 02238 char *rtnl_link_stat2str(int st, char *buf, size_t len) 02239 { 02240 return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats)); 02241 } 02242 02243 int rtnl_link_str2stat(const char *name) 02244 { 02245 return __str2type(name, link_stats, ARRAY_SIZE(link_stats)); 02246 } 02247 02248 static const struct trans_tbl link_operstates[] = { 02249 __ADD(IF_OPER_UNKNOWN, unknown) 02250 __ADD(IF_OPER_NOTPRESENT, notpresent) 02251 __ADD(IF_OPER_DOWN, down) 02252 __ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown) 02253 __ADD(IF_OPER_TESTING, testing) 02254 __ADD(IF_OPER_DORMANT, dormant) 02255 __ADD(IF_OPER_UP, up) 02256 }; 02257 02258 char *rtnl_link_operstate2str(uint8_t st, char *buf, size_t len) 02259 { 02260 return __type2str(st, buf, len, link_operstates, 02261 ARRAY_SIZE(link_operstates)); 02262 } 02263 02264 int rtnl_link_str2operstate(const char *name) 02265 { 02266 return __str2type(name, link_operstates, 02267 ARRAY_SIZE(link_operstates)); 02268 } 02269 02270 static const struct trans_tbl link_modes[] = { 02271 __ADD(IF_LINK_MODE_DEFAULT, default) 02272 __ADD(IF_LINK_MODE_DORMANT, dormant) 02273 }; 02274 02275 char *rtnl_link_mode2str(uint8_t st, char *buf, size_t len) 02276 { 02277 return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes)); 02278 } 02279 02280 int rtnl_link_str2mode(const char *name) 02281 { 02282 return __str2type(name, link_modes, ARRAY_SIZE(link_modes)); 02283 } 02284 02285 /** @} */ 02286 02287 /** 02288 * @name Deprecated Functions 02289 */ 02290 02291 /** 02292 * @deprecated Use of this function is deprecated, use rtnl_link_set_type() 02293 */ 02294 int rtnl_link_set_info_type(struct rtnl_link *link, const char *type) 02295 { 02296 return rtnl_link_set_type(link, type); 02297 } 02298 02299 /** 02300 * @deprecated Use of this function is deprecated, use rtnl_link_get_type() 02301 */ 02302 char *rtnl_link_get_info_type(struct rtnl_link *link) 02303 { 02304 return rtnl_link_get_type(link); 02305 } 02306 02307 /** 02308 * @deprecated The weight attribute is unused and obsoleted in all recent kernels 02309 */ 02310 void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight) 02311 { 02312 link->l_weight = weight; 02313 link->ce_mask |= LINK_ATTR_WEIGHT; 02314 } 02315 02316 /** 02317 * @deprecated The weight attribute is unused and obsoleted in all recent kernels 02318 */ 02319 unsigned int rtnl_link_get_weight(struct rtnl_link *link) 02320 { 02321 return link->l_weight; 02322 } 02323 02324 /** @} */ 02325 02326 static struct nl_object_ops link_obj_ops = { 02327 .oo_name = "route/link", 02328 .oo_size = sizeof(struct rtnl_link), 02329 .oo_free_data = link_free_data, 02330 .oo_clone = link_clone, 02331 .oo_dump = { 02332 [NL_DUMP_LINE] = link_dump_line, 02333 [NL_DUMP_DETAILS] = link_dump_details, 02334 [NL_DUMP_STATS] = link_dump_stats, 02335 }, 02336 .oo_compare = link_compare, 02337 .oo_attrs2str = link_attrs2str, 02338 .oo_id_attrs = LINK_ATTR_IFINDEX, 02339 }; 02340 02341 static struct nl_af_group link_groups[] = { 02342 { AF_UNSPEC, RTNLGRP_LINK }, 02343 { END_OF_GROUP_LIST }, 02344 }; 02345 02346 static struct nl_cache_ops rtnl_link_ops = { 02347 .co_name = "route/link", 02348 .co_hdrsize = sizeof(struct ifinfomsg), 02349 .co_msgtypes = { 02350 { RTM_NEWLINK, NL_ACT_NEW, "new" }, 02351 { RTM_DELLINK, NL_ACT_DEL, "del" }, 02352 { RTM_GETLINK, NL_ACT_GET, "get" }, 02353 { RTM_SETLINK, NL_ACT_CHANGE, "set" }, 02354 END_OF_MSGTYPES_LIST, 02355 }, 02356 .co_protocol = NETLINK_ROUTE, 02357 .co_groups = link_groups, 02358 .co_request_update = link_request_update, 02359 .co_msg_parser = link_msg_parser, 02360 .co_event_filter = link_event_filter, 02361 .co_obj_ops = &link_obj_ops, 02362 }; 02363 02364 static void __init link_init(void) 02365 { 02366 nl_cache_mngt_register(&rtnl_link_ops); 02367 } 02368 02369 static void __exit link_exit(void) 02370 { 02371 nl_cache_mngt_unregister(&rtnl_link_ops); 02372 } 02373 02374 /** @} */