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