/build/buildd/libnl-1.0~pre6/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-2006 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup rtnl
00014  * @defgroup link Links (Interfaces)
00015  * @brief
00016  *
00017  * @par Link Identification
00018  * A link can be identified by either its interface index or by its
00019  * name. The kernel favours the interface index but falls back to the
00020  * interface name if the interface index is lesser-than 0 for kernels
00021  * >= 2.6.11. Therefore you can request changes without mapping a
00022  * interface name to the corresponding index first.
00023  *
00024  * @par Changeable Attributes
00025  * @anchor link_changeable
00026  *  - Link layer address
00027  *  - Link layer broadcast address
00028  *  - device mapping (ifmap) (>= 2.6.9)
00029  *  - MTU (>= 2.6.9)
00030  *  - Transmission queue length (>= 2.6.9)
00031  *  - Weight (>= 2.6.9)
00032  *  - Link name (only via access through interface index) (>= 2.6.9)
00033  *  - Flags (>= 2.6.9)
00034  *    - IFF_DEBUG
00035  *    - IFF_NOTRAILERS
00036  *    - IFF_NOARP
00037  *    - IFF_DYNAMIC
00038  *    - IFF_MULTICAST
00039  *    - IFF_PORTSEL
00040  *    - IFF_AUTOMEDIA
00041  *    - IFF_UP
00042  *    - IFF_PROMISC
00043  *    - IFF_ALLMULTI
00044  *
00045  * @par Link Flags (linux/if.h)
00046  * @anchor link_flags
00047  * @code
00048  *   IFF_UP            Status of link (up|down)
00049  *   IFF_BROADCAST     Indicates this link allows broadcasting
00050  *   IFF_MULTICAST     Indicates this link allows multicasting
00051  *   IFF_ALLMULTI      Indicates this link is doing multicast routing
00052  *   IFF_DEBUG         Tell the driver to do debugging (currently unused)
00053  *   IFF_LOOPBACK      This is the loopback link
00054  *   IFF_POINTOPOINT   Point-to-point link
00055  *   IFF_NOARP         Link is unable to perform ARP
00056  *   IFF_PROMISC       Status of promiscious mode flag
00057  *   IFF_MASTER        Used by teql
00058  *   IFF_SLAVE         Used by teql
00059  *   IFF_PORTSEL       Indicates this link allows port selection
00060  *   IFF_AUTOMEDIA     Indicates this link selects port automatically
00061  *   IFF_DYNAMIC       Indicates the address of this link is dynamic
00062  *   IFF_RUNNING       Link is running and carrier is ok.
00063  *   IFF_NOTRAILERS    Unused, BSD compat.
00064  * @endcode
00065  *
00066  * @par Notes on IFF_PROMISC and IFF_ALLMULTI flags
00067  * Although you can query the status of IFF_PROMISC and IFF_ALLMULTI
00068  * they do not represent the actual state in the kernel but rather
00069  * whether the flag has been enabled/disabled by userspace. The link
00070  * may be in promiscious mode even if IFF_PROMISC is not set in a link
00071  * dump request response because promiscity might be needed by the driver
00072  * for a period of time.
00073  *
00074  * @par 1) Retrieving information about available links
00075  * @code
00076  * // The first step is to retrieve a list of all available interfaces within
00077  * // the kernel and put them into a cache.
00078  * struct nl_cache *cache = rtnl_link_alloc_cache(nl_handle);
00079  *
00080  * // In a second step, a specific link may be looked up by either interface
00081  * // index or interface name.
00082  * struct rtnl_link *link = rtnl_link_get_by_name(cache, "lo");
00083  *
00084  * // rtnl_link_get_by_name() is the short version for translating the
00085  * // interface name to an interface index first like this:
00086  * int ifindex = rtnl_link_name2i(cache, "lo");
00087  * struct rtnl_link *link = rtnl_link_get(cache, ifindex);
00088  *
00089  * // After successful usage, the object must be given back to the cache
00090  * rtnl_link_put(link);
00091  * @endcode
00092  *
00093  * @par 2) Changing link attributes
00094  * @code
00095  * // In order to change any attributes of an existing link, we must allocate
00096  * // a new link to hold the change requests:
00097  * struct rtnl_link *request = rtnl_link_alloc();
00098  *
00099  * // Now we can go on and specify the attributes we want to change:
00100  * rtnl_link_set_weight(request, 300);
00101  * rtnl_link_set_mtu(request, 1360);
00102  *
00103  * // We can also shut an interface down administratively
00104  * rtnl_link_unset_flags(request, rtnl_link_str2flags("up"));
00105  *
00106  * // Actually, we should know which link to change, so let's look it up
00107  * struct rtnl_link *old = rtnl_link_get(cache, "eth0");
00108  *
00109  * // Two ways exist to commit this change request, the first one is to
00110  * // build the required netlink message and send it out in one single
00111  * // step:
00112  * rtnl_link_change(nl_handle, old, request);
00113  *
00114  * // An alternative way is to build the netlink message and send it
00115  * // out yourself using nl_send_auto_complete()
00116  * struct nl_msg *msg = rtnl_link_build_change_request(old, request);
00117  * nl_send_auto_complete(nl_handle, nlmsg_hdr(msg));
00118  * nlmsg_free(msg);
00119  *
00120  * // Don't forget to give back the link object ;->
00121  * rtnl_link_put(old);
00122  * @endcode
00123  * @{
00124  */
00125 
00126 #include <netlink-local.h>
00127 #include <netlink/netlink.h>
00128 #include <netlink/attr.h>
00129 #include <netlink/utils.h>
00130 #include <netlink/object.h>
00131 #include <netlink/route/rtnl.h>
00132 #include <netlink/route/link.h>
00133 
00134 /** @cond SKIP */
00135 #define LINK_ATTR_MTU     0x0001
00136 #define LINK_ATTR_LINK    0x0002
00137 #define LINK_ATTR_TXQLEN  0x0004
00138 #define LINK_ATTR_WEIGHT  0x0008
00139 #define LINK_ATTR_MASTER  0x0010
00140 #define LINK_ATTR_QDISC   0x0020
00141 #define LINK_ATTR_MAP     0x0040
00142 #define LINK_ATTR_ADDR    0x0080
00143 #define LINK_ATTR_BRD     0x0100
00144 #define LINK_ATTR_FLAGS   0x0200
00145 #define LINK_ATTR_IFNAME  0x0400
00146 #define LINK_ATTR_IFINDEX 0x0800
00147 #define LINK_ATTR_FAMILY  0x1000
00148 #define LINK_ATTR_ARPTYPE 0x2000
00149 #define LINK_ATTR_STATS   0x4000
00150 #define LINK_ATTR_CHANGE  0x8000
00151 
00152 static struct nl_cache_ops rtnl_link_ops;
00153 /** @endcond */
00154 
00155 static void link_free_data(struct nl_object *c)
00156 {
00157         struct rtnl_link *link = nl_object_priv(c);
00158 
00159         if (link) {
00160                 nl_addr_put(link->l_addr);
00161                 nl_addr_put(link->l_bcast);
00162         }
00163 }
00164 
00165 static struct nla_policy link_policy[IFLA_MAX+1] = {
00166         [IFLA_IFNAME]   = { .type = NLA_STRING,
00167                             .maxlen = IFNAMSIZ },
00168         [IFLA_MTU]      = { .type = NLA_U32 },
00169         [IFLA_TXQLEN]   = { .type = NLA_U32 },
00170         [IFLA_LINK]     = { .type = NLA_U32 },
00171         [IFLA_WEIGHT]   = { .type = NLA_U32 },
00172         [IFLA_MASTER]   = { .type = NLA_U32 },
00173         [IFLA_QDISC]    = { .type = NLA_STRING,
00174                             .maxlen = IFQDISCSIZ },
00175         [IFLA_STATS]    = { .minlen = sizeof(struct rtnl_link_stats) },
00176         [IFLA_MAP]      = { .minlen = sizeof(struct rtnl_link_ifmap) },
00177 };
00178 
00179 static int link_msg_parser(struct sockaddr_nl *who, struct nlmsghdr *n,
00180                            void *arg)
00181 {
00182         struct rtnl_link *link;
00183         struct ifinfomsg *ifi;
00184         struct nlattr *tb[IFLA_MAX+1];
00185         struct nl_parser_param *pp = arg;
00186         int err;
00187 
00188         link = rtnl_link_alloc();
00189         if (link == NULL) {
00190                 err = nl_errno(ENOMEM);
00191                 goto errout;
00192         }
00193                 
00194         link->ce_msgtype = n->nlmsg_type;
00195 
00196         err = nlmsg_parse(n, sizeof(*ifi), tb, IFLA_MAX, link_policy);
00197         if (err < 0)
00198                 goto errout;
00199 
00200         if (tb[IFLA_IFNAME] == NULL) {
00201                 err = nl_error(EINVAL, "Missing link name TLV");
00202                 goto errout;
00203         }
00204 
00205         nla_strlcpy(link->l_name, tb[IFLA_IFNAME], IFNAMSIZ);
00206 
00207         ifi = nlmsg_data(n);
00208         link->l_family = ifi->ifi_family;
00209         link->l_arptype = ifi->ifi_type;
00210         link->l_index = ifi->ifi_index;
00211         link->l_flags = ifi->ifi_flags;
00212         link->l_change = ifi->ifi_change;
00213         link->l_mask = (LINK_ATTR_IFNAME | LINK_ATTR_FAMILY | LINK_ATTR_ARPTYPE|
00214                         LINK_ATTR_IFINDEX | LINK_ATTR_FLAGS | LINK_ATTR_CHANGE);
00215 
00216         if (tb[IFLA_STATS]) {
00217                 struct rtnl_link_stats *st = nla_data(tb[IFLA_STATS]);
00218                 
00219                 link->l_stats[RTNL_LINK_RX_PACKETS]     = st->rx_packets;
00220                 link->l_stats[RTNL_LINK_RX_BYTES]       = st->rx_bytes;
00221                 link->l_stats[RTNL_LINK_RX_ERRORS]      = st->rx_errors;
00222                 link->l_stats[RTNL_LINK_RX_DROPPED]     = st->rx_dropped;
00223                 link->l_stats[RTNL_LINK_RX_COMPRESSED]  = st->rx_compressed;
00224                 link->l_stats[RTNL_LINK_RX_FIFO_ERR]    = st->rx_fifo_errors;
00225                 link->l_stats[RTNL_LINK_TX_PACKETS]     = st->tx_packets;
00226                 link->l_stats[RTNL_LINK_TX_BYTES]       = st->tx_bytes;
00227                 link->l_stats[RTNL_LINK_TX_ERRORS]      = st->tx_errors;
00228                 link->l_stats[RTNL_LINK_TX_DROPPED]     = st->tx_dropped;
00229                 link->l_stats[RTNL_LINK_TX_COMPRESSED]  = st->tx_compressed;
00230                 link->l_stats[RTNL_LINK_TX_FIFO_ERR]    = st->tx_fifo_errors;
00231                 link->l_stats[RTNL_LINK_RX_LEN_ERR]     = st->rx_length_errors;
00232                 link->l_stats[RTNL_LINK_RX_OVER_ERR]    = st->rx_over_errors;
00233                 link->l_stats[RTNL_LINK_RX_CRC_ERR]     = st->rx_crc_errors;
00234                 link->l_stats[RTNL_LINK_RX_FRAME_ERR]   = st->rx_frame_errors;
00235                 link->l_stats[RTNL_LINK_RX_MISSED_ERR]  = st->rx_missed_errors;
00236                 link->l_stats[RTNL_LINK_TX_ABORT_ERR]   = st->tx_aborted_errors;
00237                 link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st->tx_carrier_errors;
00238                 link->l_stats[RTNL_LINK_TX_HBEAT_ERR]   = st->tx_heartbeat_errors;
00239                 link->l_stats[RTNL_LINK_TX_WIN_ERR]     = st->tx_window_errors;
00240                 link->l_stats[RTNL_LINK_MULTICAST]      = st->multicast;
00241 
00242                 link->l_mask |= LINK_ATTR_STATS;
00243         }
00244 
00245         if (tb[IFLA_TXQLEN]) {
00246                 link->l_txqlen = nla_get_u32(tb[IFLA_TXQLEN]);
00247                 link->l_mask |= LINK_ATTR_TXQLEN;
00248         }
00249 
00250         if (tb[IFLA_MTU]) {
00251                 link->l_mtu = nla_get_u32(tb[IFLA_MTU]);
00252                 link->l_mask |= LINK_ATTR_MTU;
00253         }
00254 
00255         if (tb[IFLA_ADDRESS]) {
00256                 link->l_addr = nla_get_addr(tb[IFLA_ADDRESS], AF_UNSPEC);
00257                 if (link->l_addr == NULL)
00258                         goto errout;
00259                 nl_addr_set_family(link->l_addr,
00260                                    nl_addr_guess_family(link->l_addr));
00261                 link->l_mask |= LINK_ATTR_ADDR;
00262         }
00263 
00264         if (tb[IFLA_BROADCAST]) {
00265                 link->l_bcast = nla_get_addr(tb[IFLA_BROADCAST], AF_UNSPEC);
00266                 if (link->l_bcast == NULL)
00267                         goto errout;
00268                 nl_addr_set_family(link->l_bcast,
00269                                    nl_addr_guess_family(link->l_bcast));
00270                 link->l_mask |= LINK_ATTR_BRD;
00271         }
00272 
00273         if (tb[IFLA_LINK]) {
00274                 link->l_link = nla_get_u32(tb[IFLA_LINK]);
00275                 link->l_mask |= LINK_ATTR_LINK;
00276         }
00277 
00278         if (tb[IFLA_WEIGHT]) {
00279                 link->l_weight = nla_get_u32(tb[IFLA_WEIGHT]);
00280                 link->l_mask |= LINK_ATTR_WEIGHT;
00281         }
00282 
00283         if (tb[IFLA_QDISC]) {
00284                 nla_strlcpy(link->l_qdisc, tb[IFLA_QDISC], IFQDISCSIZ);
00285                 link->l_mask |= LINK_ATTR_QDISC;
00286         }
00287 
00288         if (tb[IFLA_MAP]) {
00289                 struct rtnl_link_ifmap *map =  nla_data(tb[IFLA_MAP]);
00290                 link->l_map.lm_mem_start = map->mem_start;
00291                 link->l_map.lm_mem_end   = map->mem_end;
00292                 link->l_map.lm_base_addr = map->base_addr;
00293                 link->l_map.lm_irq       = map->irq;
00294                 link->l_map.lm_dma       = map->dma;
00295                 link->l_map.lm_port      = map->port;
00296                 link->l_mask |= LINK_ATTR_MAP;
00297         }
00298 
00299         if (tb[IFLA_MASTER]) {
00300                 link->l_master = nla_get_u32(tb[IFLA_MASTER]);
00301                 link->l_mask |= LINK_ATTR_MASTER;
00302         }
00303 
00304         err = pp->pp_cb((struct nl_object *) link, pp);
00305         if (err < 0)
00306                 goto errout;
00307 
00308         return P_ACCEPT;
00309 
00310 errout:
00311         rtnl_link_put(link);
00312         return err;
00313 }
00314 
00315 static int link_request_update(struct nl_cache *c, struct nl_handle *h)
00316 {
00317         return nl_rtgen_request(h, RTM_GETLINK, AF_UNSPEC, NLM_F_DUMP);
00318 }
00319 
00320 static int link_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
00321 {
00322         char buf[128];
00323         struct nl_cache *cache = dp_cache(obj);
00324         struct rtnl_link *link = (struct rtnl_link *) obj;
00325         int line = 1;
00326 
00327         dp_dump(p, "%s ", link->l_name);
00328 
00329         if (link->l_mask & LINK_ATTR_LINK) {
00330                 struct rtnl_link *ll = rtnl_link_get(cache, link->l_link);
00331                 dp_dump(p, "@%s", ll ? ll->l_name : "NONE");
00332                 if (ll)
00333                         rtnl_link_put(ll);
00334         }
00335 
00336         dp_dump(p, "%s ", nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
00337         dp_dump(p, "%s ", link->l_addr ?  nl_addr2str(link->l_addr, buf,
00338                                                      sizeof(buf)) : "none");
00339         dp_dump(p, "mtu %u ", link->l_mtu);
00340 
00341         if (link->l_mask & LINK_ATTR_MASTER) {
00342                 struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
00343                 dp_dump(p, "master %s ", master ? master->l_name : "inv");
00344                 if (master)
00345                         rtnl_link_put(master);
00346         }
00347 
00348         rtnl_link_flags2str(link->l_flags, buf, sizeof(buf));
00349         if (buf[0])
00350                 dp_dump(p, "<%s>", buf);
00351 
00352         dp_dump(p, "\n");
00353 
00354         return line;
00355 }
00356 
00357 static int link_dump_full(struct nl_object *obj, struct nl_dump_params *p)
00358 {
00359         struct rtnl_link *link = (struct rtnl_link *) obj;
00360         char buf[64];
00361         int line;
00362 
00363         line = link_dump_brief(obj, p);
00364         dp_new_line(p, line++);
00365 
00366         dp_dump(p, "    txqlen %u weight %u ", link->l_txqlen, link->l_weight);
00367 
00368         if (link->l_mask & LINK_ATTR_QDISC)
00369                 dp_dump(p, "qdisc %s ", link->l_qdisc);
00370 
00371         if (link->l_mask & LINK_ATTR_MAP && link->l_map.lm_irq)
00372                 dp_dump(p, "irq %u ", link->l_map.lm_irq);
00373 
00374         if (link->l_mask & LINK_ATTR_IFINDEX)
00375                 dp_dump(p, "index %u ", link->l_index);
00376 
00377         if (link->l_mask & LINK_ATTR_BRD)
00378                 dp_dump(p, "brd %s", nl_addr2str(link->l_bcast, buf,
00379                                                    sizeof(buf)));
00380 
00381         dp_dump(p, "\n");
00382 
00383         return line;
00384 }
00385 
00386 static int link_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
00387 {
00388         struct rtnl_link *link = (struct rtnl_link *) obj;
00389         char *unit, fmt[64];
00390         float res;
00391         int line;
00392         
00393         line = link_dump_full(obj, p);
00394 
00395         dp_dump_line(p, line++, "    Stats:    bytes    packets     errors "
00396                                 "   dropped   fifo-err compressed\n");
00397 
00398         res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_RX_BYTES], &unit);
00399 
00400         strcpy(fmt, "    RX  %X.2f %s %10llu %10llu %10llu %10llu %10llu\n");
00401         fmt[9] = *unit == 'B' ? '9' : '7';
00402         
00403         dp_dump_line(p, line++, fmt,
00404                 res, unit,
00405                 link->l_stats[RTNL_LINK_RX_PACKETS],
00406                 link->l_stats[RTNL_LINK_RX_ERRORS],
00407                 link->l_stats[RTNL_LINK_RX_DROPPED],
00408                 link->l_stats[RTNL_LINK_RX_FIFO_ERR],
00409                 link->l_stats[RTNL_LINK_RX_COMPRESSED]);
00410 
00411         res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_TX_BYTES], &unit);
00412 
00413         strcpy(fmt, "    TX  %X.2f %s %10llu %10llu %10llu %10llu %10llu\n");
00414         fmt[9] = *unit == 'B' ? '9' : '7';
00415         
00416         dp_dump_line(p, line++, fmt,
00417                 res, unit,
00418                 link->l_stats[RTNL_LINK_TX_PACKETS],
00419                 link->l_stats[RTNL_LINK_TX_ERRORS],
00420                 link->l_stats[RTNL_LINK_TX_DROPPED],
00421                 link->l_stats[RTNL_LINK_TX_FIFO_ERR],
00422                 link->l_stats[RTNL_LINK_TX_COMPRESSED]);
00423 
00424         dp_dump_line(p, line++, "    Errors:  length       over        crc "
00425                                 "     frame     missed  multicast\n");
00426 
00427         dp_dump_line(p, line++, "    RX   %10" PRIu64 " %10" PRIu64 " %10"
00428                                 PRIu64 " %10" PRIu64 " %10" PRIu64 " %10"
00429                                 PRIu64 "\n",
00430                 link->l_stats[RTNL_LINK_RX_LEN_ERR],
00431                 link->l_stats[RTNL_LINK_RX_OVER_ERR],
00432                 link->l_stats[RTNL_LINK_RX_CRC_ERR],
00433                 link->l_stats[RTNL_LINK_RX_FRAME_ERR],
00434                 link->l_stats[RTNL_LINK_RX_MISSED_ERR],
00435                 link->l_stats[RTNL_LINK_MULTICAST]);
00436 
00437         dp_dump_line(p, line++, "    Errors: aborted    carrier  heartbeat "
00438                                 "    window  collision\n");
00439         
00440         dp_dump_line(p, line++, "    TX   %10" PRIu64 " %10" PRIu64 " %10"
00441                                 PRIu64 " %10" PRIu64 " %10" PRIu64 "\n",
00442                 link->l_stats[RTNL_LINK_TX_ABORT_ERR],
00443                 link->l_stats[RTNL_LINK_TX_CARRIER_ERR],
00444                 link->l_stats[RTNL_LINK_TX_HBEAT_ERR],
00445                 link->l_stats[RTNL_LINK_TX_WIN_ERR],
00446                 link->l_stats[RTNL_LINK_TX_COLLISIONS]);
00447 
00448         return line;
00449 }
00450 
00451 static int link_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
00452 {
00453         struct rtnl_link *link = (struct rtnl_link *) obj;
00454         struct nl_cache *cache = dp_cache(obj);
00455         char buf[128];
00456         int i, line = 0;
00457 
00458         dp_dump_line(p, line++, "<link name=\"%s\" index=\"%u\">\n",
00459                      link->l_name, link->l_index);
00460         dp_dump_line(p, line++, "  <family>%s</family>\n",
00461                      nl_af2str(link->l_family, buf, sizeof(buf)));
00462         dp_dump_line(p, line++, "  <arptype>%s</arptype>\n",
00463                      nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
00464         dp_dump_line(p, line++, "  <address>%s</address>\n",
00465                      nl_addr2str(link->l_addr, buf, sizeof(buf)));
00466         dp_dump_line(p, line++, "  <mtu>%u</mtu>\n", link->l_mtu);
00467         dp_dump_line(p, line++, "  <txqlen>%u</txqlen>\n", link->l_txqlen);
00468         dp_dump_line(p, line++, "  <weight>%u</weight>\n", link->l_weight);
00469 
00470         rtnl_link_flags2str(link->l_flags, buf, sizeof(buf));
00471         if (buf[0])
00472                 dp_dump_line(p, line++, "  <flags>%s</flags>\n", buf);
00473 
00474         if (link->l_mask & LINK_ATTR_QDISC)
00475                 dp_dump_line(p, line++, "  <qdisc>%s</qdisc>\n", link->l_qdisc);
00476 
00477         if (link->l_mask & LINK_ATTR_LINK) {
00478                 struct rtnl_link *ll = rtnl_link_get(cache, link->l_link);
00479                 dp_dump_line(p, line++, "  <link>%s</link>\n",
00480                              ll ? ll->l_name : "none");
00481                 if (ll)
00482                         rtnl_link_put(ll);
00483         }
00484 
00485         if (link->l_mask & LINK_ATTR_MASTER) {
00486                 struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
00487                 dp_dump_line(p, line++, "  <master>%s</master>\n",
00488                              master ? master->l_name : "none");
00489                 if (master)
00490                         rtnl_link_put(master);
00491         }
00492 
00493         if (link->l_mask & LINK_ATTR_BRD)
00494                 dp_dump_line(p, line++, "  <broadcast>%s</broadcast>\n",
00495                              nl_addr2str(link->l_bcast, buf, sizeof(buf)));
00496 
00497         if (link->l_mask & LINK_ATTR_STATS) {
00498                 dp_dump_line(p, line++, "  <stats>\n");
00499                 for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) {
00500                         rtnl_link_stat2str(i, buf, sizeof(buf));
00501                         dp_dump_line(p, line++,
00502                                      "    <%s>%" PRIu64 "</%s>\n",
00503                                      buf, link->l_stats[i], buf);
00504                 }
00505                 dp_dump_line(p, line++, "  </stats>\n");
00506         }
00507 
00508         dp_dump_line(p, line++, "</link>\n");
00509 
00510 #if 0
00511         uint32_t        l_change;       /**< Change mask */
00512         struct rtnl_lifmap l_map;       /**< Interface device mapping */
00513 #endif
00514 
00515         return line;
00516 }
00517 
00518 static int link_dump_env(struct nl_object *obj, struct nl_dump_params *p)
00519 {
00520         struct rtnl_link *link = (struct rtnl_link *) obj;
00521         struct nl_cache *cache = dp_cache(obj);
00522         char buf[128];
00523         int i, line = 0;
00524 
00525         dp_dump_line(p, line++, "LINK_NAME=%s\n", link->l_name);
00526         dp_dump_line(p, line++, "LINK_IFINDEX=%u\n", link->l_index);
00527         dp_dump_line(p, line++, "LINK_FAMILY=%s\n",
00528                      nl_af2str(link->l_family, buf, sizeof(buf)));
00529         dp_dump_line(p, line++, "LINK_TYPE=%s\n",
00530                      nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
00531         if (link->l_mask & LINK_ATTR_ADDR)
00532                 dp_dump_line(p, line++, "LINK_ADDRESS=%s\n",
00533                              nl_addr2str(link->l_addr, buf, sizeof(buf)));
00534         dp_dump_line(p, line++, "LINK_MTU=%u\n", link->l_mtu);
00535         dp_dump_line(p, line++, "LINK_TXQUEUELEN=%u\n", link->l_txqlen);
00536         dp_dump_line(p, line++, "LINK_WEIGHT=%u\n", link->l_weight);
00537 
00538         rtnl_link_flags2str(link->l_flags & ~IFF_RUNNING, buf, sizeof(buf));
00539         if (buf[0])
00540                 dp_dump_line(p, line++, "LINK_FLAGS=%s\n", buf);
00541 
00542         if (link->l_mask & LINK_ATTR_QDISC)
00543                 dp_dump_line(p, line++, "LINK_QDISC=%s\n", link->l_qdisc);
00544 
00545         if (link->l_mask & LINK_ATTR_LINK) {
00546                 struct rtnl_link *ll = rtnl_link_get(cache, link->l_link);
00547 
00548                 dp_dump_line(p, line++, "LINK_LINK_IFINDEX=%d\n", link->l_link);
00549                 if (ll) {
00550                         dp_dump_line(p, line++, "LINK_LINK_IFNAME=%s\n",
00551                                      ll->l_name);
00552                         rtnl_link_put(ll);
00553                 }
00554         }
00555 
00556         if (link->l_mask & LINK_ATTR_MASTER) {
00557                 struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
00558                 dp_dump_line(p, line++, "LINK_MASTER=%s\n",
00559                              master ? master->l_name : "none");
00560                 if (master)
00561                         rtnl_link_put(master);
00562         }
00563 
00564         if (link->l_mask & LINK_ATTR_BRD)
00565                 dp_dump_line(p, line++, "LINK_BROADCAST=%s\n",
00566                              nl_addr2str(link->l_bcast, buf, sizeof(buf)));
00567 
00568         if (link->l_mask & LINK_ATTR_STATS) {
00569                 for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) {
00570                         char *c = buf;
00571 
00572                         sprintf(buf, "LINK_");
00573                         rtnl_link_stat2str(i, buf + 5, sizeof(buf) - 5);
00574                         while (*c) {
00575                                 *c = toupper(*c);
00576                                 c++;
00577                         }
00578                         dp_dump_line(p, line++,
00579                                      "%s=%" PRIu64 "\n", buf, link->l_stats[i]);
00580                 }
00581         }
00582 
00583         return line;
00584 }
00585 
00586 #if 0
00587 static int link_handle_event(struct nl_object *a, struct rtnl_link_event_cb *cb)
00588 {
00589         struct rtnl_link *l = (struct rtnl_link *) a;
00590         struct nl_cache *c = dp_cache(a);
00591         int nevents = 0;
00592 
00593         if (l->l_change == ~0U) {
00594                 if (l->ce_msgtype == RTM_NEWLINK)
00595                         cb->le_register(l);
00596                 else
00597                         cb->le_unregister(l);
00598 
00599                 return 1;
00600         }
00601 
00602         if (l->l_change & IFF_SLAVE) {
00603                 if (l->l_flags & IFF_SLAVE) {
00604                         struct rtnl_link *m = rtnl_link_get(c, l->l_master);
00605                         cb->le_new_bonding(l, m);
00606                         if (m)
00607                                 rtnl_link_put(m);
00608                 } else
00609                         cb->le_cancel_bonding(l);
00610         }
00611 
00612 #if 0
00613         if (l->l_change & IFF_UP && l->l_change & IFF_RUNNING)
00614                 dp_dump_line(p, line++, "link %s changed state to %s.\n",
00615                         l->l_name, l->l_flags & IFF_UP ? "up" : "down");
00616 
00617         if (l->l_change & IFF_PROMISC) {
00618                 dp_new_line(p, line++);
00619                 dp_dump(p, "link %s %s promiscuous mode.\n",
00620                     l->l_name, l->l_flags & IFF_PROMISC ? "entered" : "left");
00621         }
00622 
00623         if (line == 0)
00624                 dp_dump_line(p, line++, "link %s sent unknown event.\n",
00625                              l->l_name);
00626 #endif
00627 
00628         return nevents;
00629 }
00630 #endif
00631 
00632 static int link_filter(struct nl_object *obj, struct nl_object *filter)
00633 {
00634         struct rtnl_link *o = (struct rtnl_link *) obj;
00635         struct rtnl_link *f = (struct rtnl_link *) filter;
00636 
00637 #define REQ(F) (f->l_mask & LINK_ATTR_##F)
00638 #define AVAIL(F) (o->l_mask & LINK_ATTR_##F)
00639 #define F_CUS(F, EXPR) (REQ(F) && (!AVAIL(F) || (EXPR)))
00640 #define F_INT(F, N) (REQ(F) && (!AVAIL(F) || (o->N != f->N)))
00641         if (F_INT(MTU,  l_mtu)                                          ||
00642             F_INT(LINK, l_link)                                         ||
00643             F_INT(TXQLEN,       l_txqlen)                               ||
00644             F_INT(WEIGHT,       l_weight)                               ||
00645             F_INT(MASTER,       l_master)                               ||
00646             F_INT(IFINDEX,      l_index)                                ||
00647             F_INT(FAMILY,       l_family)                               ||
00648             F_CUS(QDISC,        strcmp(o->l_qdisc, f->l_qdisc))         ||
00649             F_CUS(IFNAME,       strcmp(o->l_name, f->l_name))           ||
00650             F_CUS(ADDR, nl_addr_cmp(o->l_addr, f->l_addr))              ||
00651             F_CUS(BRD,  nl_addr_cmp(o->l_bcast, f->l_bcast))            ||
00652             F_CUS(FLAGS,        f->l_flags ^ (o->l_flags & f->l_flag_mask)))
00653                 return 0;
00654 #undef REQ
00655 #undef AVAIL
00656 #undef F_CUS
00657 #undef F_INT
00658 
00659         return 1;
00660 }
00661 
00662 /**
00663  * @name Link Object Allocation/Freeage
00664  * @{
00665  */
00666 
00667 /**
00668  * Allocate and initialize new link object.
00669  * @note Free the memory after usage using rtnl_link_put() or rtnl_link_free().
00670  * @return Newly allocated link object or NULL if an error occured.
00671  */
00672 struct rtnl_link *rtnl_link_alloc(void)
00673 {
00674         return (struct rtnl_link *) nl_object_alloc_from_ops(&rtnl_link_ops);
00675 }
00676 
00677 /**
00678  * Give back reference on link object.
00679  * @arg link            Link object to be given back.
00680  *
00681  * Decrements the reference counter and frees the object if the
00682  * last reference has been released.
00683  */
00684 void rtnl_link_put(struct rtnl_link *link)
00685 {
00686         nl_object_put((struct nl_object *) link);
00687 }
00688 /**
00689  * Free link object.
00690  * @arg link            Link object to be freed.
00691  *
00692  * @note Always use rtnl_link_put() unless you're absolutely sure
00693  *       that no other user may have a reference on this object.
00694  */
00695 void rtnl_link_free(struct rtnl_link *link)
00696 {
00697         nl_object_free((struct nl_object *) link);
00698 }
00699 
00700 /** @} */
00701 
00702 /**
00703  * @name Link Cache Management
00704  * @{
00705  */
00706 
00707 
00708 /**
00709  * Allocate link cache and fill in all configured links.
00710  * @arg handle          Netlink handle.
00711  *
00712  * Allocates a new link cache, initializes it properly and updates it
00713  * to include all links currently configured in the kernel.
00714  *
00715  * @note Free the memory after usage.
00716  * @return Newly allocated cache or NULL if an error occured.
00717  */
00718 struct nl_cache *rtnl_link_alloc_cache(struct nl_handle *handle)
00719 {
00720         struct nl_cache * cache;
00721         
00722         cache = nl_cache_alloc_from_ops(&rtnl_link_ops);
00723         if (cache == NULL)
00724                 return NULL;
00725         
00726         if (nl_cache_update(handle, cache) < 0) {
00727                 nl_cache_free(cache);
00728                 return NULL;
00729         }
00730 
00731         return cache;
00732 }
00733 
00734 /**
00735  * Look up link by interface index in the provided cache
00736  * @arg cache           link cache
00737  * @arg ifindex         link interface index
00738  *
00739  * The caller owns a reference on the returned object and
00740  * must give the object back via rtnl_link_put().
00741  *
00742  * @return pointer to link inside the cache or NULL if no match was found.
00743  */
00744 struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex)
00745 {
00746         struct rtnl_link *link;
00747 
00748         if (cache->c_ops != &rtnl_link_ops)
00749                 return NULL;
00750 
00751         nl_list_for_each_entry(link, &cache->c_items, ce_list) {
00752                 if (link->l_index == ifindex) {
00753                         nl_object_get((struct nl_object *) link);
00754                         return link;
00755                 }
00756         }
00757 
00758         return NULL;
00759 }
00760 
00761 /**
00762  * Look up link by link name in the provided cache
00763  * @arg cache           link cache
00764  * @arg name            link name
00765  *
00766  * The caller owns a reference on the returned object and
00767  * must give the object back via rtnl_link_put().
00768  *
00769  * @return pointer to link inside the cache or NULL if no match was found.
00770  */
00771 struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache,
00772                                          const char *name)
00773 {
00774         struct rtnl_link *link;
00775 
00776         if (cache->c_ops != &rtnl_link_ops)
00777                 return NULL;
00778 
00779         nl_list_for_each_entry(link, &cache->c_items, ce_list) {
00780                 if (!strcmp(name, link->l_name)) {
00781                         nl_object_get((struct nl_object *) link);
00782                         return link;
00783                 }
00784         }
00785 
00786         return NULL;
00787 }
00788 
00789 /** @} */
00790 
00791 /**
00792  * @name Link Modifications
00793  * @{
00794  */
00795 
00796 /**
00797  * Builds a netlink change request message to change link attributes
00798  * @arg old             link to be changed
00799  * @arg tmpl            template with requested changes
00800  * @arg flags           additional netlink message flags
00801  *
00802  * Builds a new netlink message requesting a change of link attributes.
00803  * The netlink message header isn't fully equipped with all relevant
00804  * fields and must be sent out via nl_send_auto_complete() or
00805  * supplemented as needed.
00806  * \a old must point to a link currently configured in the kernel
00807  * and \a tmpl must contain the attributes to be changed set via
00808  * \c rtnl_link_set_* functions.
00809  *
00810  * @return New netlink message
00811  * @note Not all attributes can be changed, see
00812  *       \ref link_changeable "Changeable Attributes" for more details.
00813  */
00814 struct nl_msg * rtnl_link_build_change_request(struct rtnl_link *old,
00815                                                struct rtnl_link *tmpl,
00816                                                int flags)
00817 {
00818         struct nl_msg *msg;
00819         struct ifinfomsg ifi = {
00820                 .ifi_family = old->l_family,
00821                 .ifi_index = old->l_index,
00822         };
00823 
00824         if (tmpl->l_mask & LINK_ATTR_FLAGS) {
00825                 ifi.ifi_flags = old->l_flags & ~tmpl->l_flag_mask;
00826                 ifi.ifi_flags |= tmpl->l_flags;
00827         }
00828 
00829         msg = nlmsg_build_simple(RTM_SETLINK, flags);
00830         if (!msg)
00831                 goto nla_put_failure;
00832 
00833         if (nlmsg_append(msg, &ifi, sizeof(ifi), 1) < 0)
00834                 goto nla_put_failure;
00835 
00836         if (tmpl->l_mask & LINK_ATTR_ADDR)
00837                 NLA_PUT_ADDR(msg, IFLA_ADDRESS, tmpl->l_addr);
00838 
00839         if (tmpl->l_mask & LINK_ATTR_BRD)
00840                 NLA_PUT_ADDR(msg, IFLA_BROADCAST, tmpl->l_bcast);
00841 
00842         if (tmpl->l_mask & LINK_ATTR_MTU)
00843                 NLA_PUT_U32(msg, IFLA_MTU, tmpl->l_mtu);
00844 
00845         if (tmpl->l_mask & LINK_ATTR_TXQLEN)
00846                 NLA_PUT_U32(msg, IFLA_TXQLEN, tmpl->l_txqlen);
00847 
00848         if (tmpl->l_mask & LINK_ATTR_WEIGHT)
00849                 NLA_PUT_U32(msg, IFLA_WEIGHT, tmpl->l_weight);
00850 
00851         if (tmpl->l_mask & LINK_ATTR_IFNAME)
00852                 NLA_PUT_STRING(msg, IFLA_IFNAME, tmpl->l_name);
00853 
00854         return msg;
00855 
00856 nla_put_failure:
00857         nlmsg_free(msg);
00858         return NULL;
00859 }
00860 
00861 /**
00862  * Change link attributes
00863  * @arg handle          netlink handle
00864  * @arg old             link to be changed
00865  * @arg tmpl            template with requested changes
00866  * @arg flags           additional netlink message flags
00867  *
00868  * Builds a new netlink message by calling rtnl_link_build_change_request(),
00869  * sends the request to the kernel and waits for the next ACK to be
00870  * received, i.e. blocks until the request has been processed.
00871  *
00872  * @return 0 on success or a negative error code
00873  * @note Not all attributes can be changed, see
00874  *       \ref link_changeable "Changeable Attributes" for more details.
00875  */
00876 int rtnl_link_change(struct nl_handle *handle, struct rtnl_link *old,
00877                      struct rtnl_link *tmpl, int flags)
00878 {
00879         int err;
00880         struct nl_msg *msg;
00881         
00882         msg = rtnl_link_build_change_request(old, tmpl, flags);
00883         if (!msg)
00884                 return nl_errno(ENOMEM);
00885         
00886         err = nl_send_auto_complete(handle, msg);
00887         if (err < 0)
00888                 return err;
00889 
00890         nlmsg_free(msg);
00891         return nl_wait_for_ack(handle);
00892 }
00893 
00894 /** @} */
00895 
00896 /**
00897  * @name Name <-> Index Translations
00898  * @{
00899  */
00900 
00901 /**
00902  * Translate an interface index to the corresponding link name
00903  * @arg cache           link cache
00904  * @arg ifindex         link interface index
00905  * @arg dst             destination buffer
00906  * @arg len             length of destination buffer
00907  *
00908  * Translates the specified interface index to the corresponding
00909  * link name and stores the name in the destination buffer.
00910  *
00911  * @return link name or NULL if no match was found.
00912  */
00913 char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst,
00914                         size_t len)
00915 {
00916         struct rtnl_link *link = rtnl_link_get(cache, ifindex);
00917 
00918         if (link) {
00919                 strncpy(dst, link->l_name, len - 1);
00920                 rtnl_link_put(link);
00921                 return dst;
00922         }
00923 
00924         return NULL;
00925 }
00926 
00927 /**
00928  * Translate a link name to the corresponding interface index
00929  * @arg cache           link cache
00930  * @arg name            link name
00931  *
00932  * @return interface index or RTNL_LINK_NOT_FOUND if no match was found.
00933  */
00934 int rtnl_link_name2i(struct nl_cache *cache, const char *name)
00935 {
00936         int ifindex = RTNL_LINK_NOT_FOUND;
00937         struct rtnl_link *link;
00938         
00939         link = rtnl_link_get_by_name(cache, name);
00940         if (link) {
00941                 ifindex = link->l_index;
00942                 rtnl_link_put(link);
00943         }
00944 
00945         return ifindex;
00946 }
00947 
00948 /** @} */
00949 
00950 /**
00951  * @name Link Flags Translations
00952  * @{
00953  */
00954 
00955 static struct trans_tbl link_flags[] = {
00956         __ADD(IFF_LOOPBACK, loopback)
00957         __ADD(IFF_BROADCAST, broadcast)
00958         __ADD(IFF_POINTOPOINT, pointopoint)
00959         __ADD(IFF_MULTICAST, multicast)
00960         __ADD(IFF_NOARP, noarp)
00961         __ADD(IFF_ALLMULTI, allmulti)
00962         __ADD(IFF_PROMISC, promisc)
00963         __ADD(IFF_MASTER, master)
00964         __ADD(IFF_SLAVE, slave)
00965         __ADD(IFF_DEBUG, debug)
00966         __ADD(IFF_DYNAMIC, dynamic)
00967         __ADD(IFF_AUTOMEDIA, automedia)
00968         __ADD(IFF_PORTSEL, portsel)
00969         __ADD(IFF_NOTRAILERS, notrailers)
00970         __ADD(IFF_UP, up)
00971         __ADD(IFF_RUNNING, running)
00972         __ADD(IFF_LOWER_UP, lowerup)
00973         __ADD(IFF_DORMANT, dormant)
00974 };
00975 
00976 /**
00977  * Convert link flags to a character string (Reentrant).
00978  * @arg flags           link flags
00979  * @arg buf             destination buffer
00980  * @arg len             buffer length
00981  *
00982  * Converts link flags to a character string separated by
00983  * commands and stores it in the specified destination buffer.
00984  *
00985  * \return The destination buffer
00986  */
00987 char * rtnl_link_flags2str(int flags, char *buf, size_t len)
00988 {
00989         return __flags2str(flags, buf, len, link_flags,
00990                            ARRAY_SIZE(link_flags));
00991 }
00992 
00993 /**
00994  * Convert a character string to a link flag
00995  * @arg name            Name of link flag
00996  *
00997  * Converts the provided character string specifying a link
00998  * link the corresponding numeric value.
00999  *
01000  * \return Link flag or a negative value if none was found.
01001  */
01002 int rtnl_link_str2flags(const char *name)
01003 {
01004         return __str2flags(name, link_flags, ARRAY_SIZE(link_flags));
01005 }
01006 
01007 /** @} */
01008 
01009 /**
01010  * @name Link Statistics Translations
01011  * @{
01012  */
01013 
01014 static struct trans_tbl link_stats[] = {
01015         __ADD(RTNL_LINK_RX_PACKETS, rx_packets)
01016         __ADD(RTNL_LINK_TX_PACKETS, tx_packets)
01017         __ADD(RTNL_LINK_RX_BYTES, rx_bytes)
01018         __ADD(RTNL_LINK_TX_BYTES, tx_bytes)
01019         __ADD(RTNL_LINK_RX_ERRORS, rx_errors)
01020         __ADD(RTNL_LINK_TX_ERRORS, tx_errors)
01021         __ADD(RTNL_LINK_RX_DROPPED, rx_dropped)
01022         __ADD(RTNL_LINK_TX_DROPPED, tx_dropped)
01023         __ADD(RTNL_LINK_RX_COMPRESSED, rx_compressed)
01024         __ADD(RTNL_LINK_TX_COMPRESSED, tx_compressed)
01025         __ADD(RTNL_LINK_RX_FIFO_ERR, rx_fifo_err)
01026         __ADD(RTNL_LINK_TX_FIFO_ERR, tx_fifo_err)
01027         __ADD(RTNL_LINK_RX_LEN_ERR, rx_len_err)
01028         __ADD(RTNL_LINK_RX_OVER_ERR, rx_over_err)
01029         __ADD(RTNL_LINK_RX_CRC_ERR, rx_crc_err)
01030         __ADD(RTNL_LINK_RX_FRAME_ERR, rx_frame_err)
01031         __ADD(RTNL_LINK_RX_MISSED_ERR, rx_missed_err)
01032         __ADD(RTNL_LINK_TX_ABORT_ERR, tx_abort_err)
01033         __ADD(RTNL_LINK_TX_CARRIER_ERR, tx_carrier_err)
01034         __ADD(RTNL_LINK_TX_HBEAT_ERR, tx_hbeat_err)
01035         __ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err)
01036         __ADD(RTNL_LINK_TX_COLLISIONS, tx_collision)
01037         __ADD(RTNL_LINK_MULTICAST, multicast)
01038 };
01039 
01040 /**
01041  * Convert a link statistic to a character string (Reentrant).
01042  * @arg st              link statistic
01043  * @arg buf             destination buffer
01044  * @arg len             buffer length
01045  *
01046  * Converts a link statistic to a character string and stores it in
01047  * the specified destination buffer.
01048  *
01049  * @return The destination buffer or the statistic encoded in
01050  *         hexidecimal form if no match was found.
01051  */
01052 char *rtnl_link_stat2str(int st, char *buf, size_t len)
01053 {
01054         return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats));
01055 }
01056 
01057 /**
01058  * Convert a character string to a link statistic
01059  * @arg name            name of link statistic
01060  *
01061  * Converts the provided character string specifying a link
01062  * statistic to the corresponding numeric value.
01063  *
01064  * @return Link statistic or a negative value if none was found.
01065  */
01066 int rtnl_link_str2stat(const char *name)
01067 {
01068         return __str2type(name, link_stats, ARRAY_SIZE(link_stats));
01069 }
01070 
01071 /** @} */
01072 
01073 /**
01074  * @name Attribute Modification
01075  * @{
01076  */
01077 
01078 /**
01079  * Set QDisc name
01080  * @arg link            link to change
01081  * @arg qdisc           qdisc name
01082  */
01083 void rtnl_link_set_qdisc(struct rtnl_link *link, const char *qdisc)
01084 {
01085         strncpy(link->l_qdisc, qdisc, sizeof(link->l_qdisc) - 1);
01086         link->l_mask |= LINK_ATTR_QDISC;
01087 }
01088 
01089 /**
01090  * Get QDisc name
01091  * @arg link            link handle
01092  * @return Name of the qdisc or NULL if not set.
01093  */
01094 char *rtnl_link_get_qdisc(struct rtnl_link *link)
01095 {
01096         if (link->l_mask & LINK_ATTR_QDISC)
01097                 return link->l_qdisc;
01098         else
01099                 return NULL;
01100 }
01101 
01102 /**
01103  * Set new link name
01104  * @arg link            link to change
01105  * @arg name            new link name
01106  */
01107 void rtnl_link_set_name(struct rtnl_link *link, const char *name)
01108 {
01109         strncpy(link->l_name, name, sizeof(link->l_name) - 1);
01110         link->l_mask |= LINK_ATTR_IFNAME;
01111 }
01112 
01113 /**
01114  * Get link name
01115  * @arg link            link handle
01116  * @return Name of the link or NULL if not set.
01117  */
01118 char *rtnl_link_get_name(struct rtnl_link *link)
01119 {
01120         if (link->l_mask & LINK_ATTR_IFNAME)
01121                 return link->l_name;
01122         else
01123                 return NULL;
01124 }
01125 
01126 static inline void __assign_addr(struct rtnl_link *link, struct nl_addr **pos,
01127                                  struct nl_addr *new, int flag)
01128 {
01129         if (*pos)
01130                 nl_addr_put(*pos);
01131 
01132         nl_addr_get(new);
01133         *pos = new;
01134 
01135         link->l_mask |= flag;
01136 }
01137 
01138 /**
01139  * Set link layer address
01140  * @arg link            link to change
01141  * @arg addr            new link layer address
01142  */
01143 void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr)
01144 {
01145         __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR);
01146 }
01147 
01148 /**
01149  * Get link layer address
01150  * @arg link            link handle
01151  * @return link layer address or NULL if not set
01152  */
01153 struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link)
01154 {
01155         if (link->l_mask & LINK_ATTR_ADDR)
01156                 return link->l_addr;
01157         else
01158                 return NULL;
01159 }
01160 
01161 /**
01162  * Set link layer broadcast address
01163  * @arg link            link to change
01164  * @arg brd             new link layer broadcast address
01165  *
01166  * Assigns the new broadcast address to the specified link handle.
01167  *
01168  * @note The prefix length of the address will be ignored.
01169  */
01170 void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *brd)
01171 {
01172         __assign_addr(link, &link->l_bcast, brd, LINK_ATTR_BRD);
01173 }
01174 
01175 /**
01176  * Get link layer broadcast address
01177  * @arg link            link handle
01178  * @return Link layer broadcast address or NULL if not set
01179  */
01180 struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link)
01181 {
01182         if (link->l_mask & LINK_ATTR_BRD)
01183                 return link->l_bcast;
01184         else
01185                 return NULL;
01186 }
01187 
01188 /**
01189  * Set flags
01190  * @arg link            link to change
01191  * @arg flags           flags to set (see \ref link_flags "Link Flags")
01192  */
01193 void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags)
01194 {
01195         link->l_flag_mask |= flags;
01196         link->l_flags |= flags;
01197         link->l_mask |= LINK_ATTR_FLAGS;
01198 }
01199 
01200 /**
01201  * Unset flags
01202  * @arg link            link to change
01203  * @arg flags           flags to unset (see \ref link_flags "Link Flags")
01204  */
01205 void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags)
01206 {
01207         link->l_flag_mask |= flags;
01208         link->l_flags &= ~flags;
01209         link->l_mask |= LINK_ATTR_FLAGS;
01210 }
01211 
01212 /**
01213  * Get flags
01214  * @arg link            link handle
01215  * @return Link flags
01216  */
01217 unsigned int rtnl_link_get_flags(struct rtnl_link *link)
01218 {
01219         return link->l_flags;
01220 }
01221 
01222 /**
01223  * Set link layer address family
01224  * @arg link            link to change
01225  * @arg family          new address family
01226  */
01227 void rtnl_link_set_family(struct rtnl_link *link, int family)
01228 {
01229         link->l_family = family;
01230         link->l_mask |= LINK_ATTR_FAMILY;
01231 }
01232 
01233 /**
01234  * Get link layer address family
01235  * @arg link            link handle
01236  * @return Link layer address family or AF_UNSPEC if not set.
01237  */
01238 int rtnl_link_get_family(struct rtnl_link *link)
01239 {
01240         if (link->l_family & LINK_ATTR_FAMILY)
01241                 return link->l_family;
01242         else
01243                 return AF_UNSPEC;
01244 }
01245 
01246 /**
01247  * Set link layer type
01248  * @arg link            link handle
01249  * @arg arptype         Link layer type.
01250  */
01251 void rtnl_link_set_type(struct rtnl_link *link, unsigned int arptype)
01252 {
01253         link->l_arptype = arptype;
01254 }
01255 
01256 /**
01257  * Get link layer type
01258  * @arg link            link handle
01259  * @return Link layer type.
01260  */
01261 unsigned int rtnl_link_get_arptype(struct rtnl_link *link)
01262 {
01263         return link->l_arptype;
01264 }
01265 
01266 /**
01267  * Set interface index
01268  * @arg link            link to change
01269  * @arg ifindex         new interface index
01270  */
01271 void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex)
01272 {
01273         link->l_index = ifindex;
01274         link->l_mask |= LINK_ATTR_IFINDEX;
01275 }
01276 
01277 /**
01278  * Get interface index
01279  * @arg link            link handle
01280  * @return interface index or RTNL_LINK_NOT_FOUND if not set.
01281  */
01282 int rtnl_link_get_ifindex(struct rtnl_link *link)
01283 {
01284         if (link->l_mask & LINK_ATTR_IFINDEX)
01285                 return link->l_index;
01286         else
01287                 return RTNL_LINK_NOT_FOUND;
01288 }
01289 
01290 /**
01291  * Set Maximum Transmission Unit
01292  * @arg link            link to change
01293  * @arg mtu             new MTU
01294  */
01295 void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu)
01296 {
01297         link->l_mtu = mtu;
01298         link->l_mask |= LINK_ATTR_MTU;
01299 }
01300 
01301 /**
01302  * Get Maximum Transmission Unit
01303  * @arg link            link handle
01304  * @return Link MTU or 0 if MTU is not set.
01305  */
01306 unsigned int rtnl_link_get_mtu(struct rtnl_link *link)
01307 {
01308         if (link->l_mask & LINK_ATTR_MTU)
01309                 return link->l_mtu;
01310         else
01311                 return 0;
01312 }
01313 
01314 /**
01315  * Set Transmission Queue Length
01316  * @arg link            link to change
01317  * @arg txqlen          new TX queue length
01318  * @note The unit of the transmission queue length depends on the
01319  *       link type, a common unit is \a packets.
01320  */
01321 void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen)
01322 {
01323         link->l_txqlen = txqlen;
01324         link->l_mask |= LINK_ATTR_TXQLEN;
01325 }
01326 
01327 /**
01328  * Get Transmission Queue Length
01329  * @arg link            link handle
01330  * @return Transmission Queue Length or UINT_MAX if not set.
01331  */
01332 unsigned int rtnl_link_get_txqlen(struct rtnl_link *link)
01333 {
01334         if (link->l_mask & LINK_ATTR_TXQLEN)
01335                 return link->l_txqlen;
01336         else
01337                 return UINT_MAX;
01338 }
01339 
01340 /**
01341  * Set Weight
01342  * @arg link            link to change
01343  * @arg weight          new weight
01344  */
01345 void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight)
01346 {
01347         link->l_weight = weight;
01348         link->l_mask |= LINK_ATTR_WEIGHT;
01349 }
01350 
01351 /**
01352  * Get Weight
01353  * @arg link            link handle
01354  * @return Link weight or UINT_MAX if not set.
01355  */
01356 unsigned int rtnl_link_get_weight(struct rtnl_link *link)
01357 {
01358         if (link->l_mask & LINK_ATTR_WEIGHT)
01359                 return link->l_weight;
01360         else
01361                 return UINT_MAX;
01362 }
01363 
01364 /**
01365  * Set parent interface index
01366  * @arg link            link to change
01367  * @arg ifindex         new parent's interface index
01368  */
01369 void rtnl_link_set_link(struct rtnl_link *link, int ifindex)
01370 {
01371         link->l_link = ifindex;
01372         link->l_mask |= LINK_ATTR_LINK;
01373 }
01374 
01375 /**
01376  * Get parent interface index
01377  * @arg link            link handle
01378  * @return Parent interface index or RTNL_LINK_NOT_FOUND if not set
01379  */
01380 int rtnl_link_get_link(struct rtnl_link *link)
01381 {
01382         if (link->l_mask & LINK_ATTR_LINK)
01383                 return link->l_link;
01384         else
01385                 return RTNL_LINK_NOT_FOUND;
01386 }
01387 
01388 /**
01389  * Set master interface index
01390  * @arg link            link to change
01391  * @arg ifindex         new master's interface index
01392  */
01393 void rtnl_link_set_master(struct rtnl_link *link, int ifindex)
01394 {
01395         link->l_master = ifindex;
01396         link->l_mask |= LINK_ATTR_MASTER;
01397 }
01398 
01399 /**
01400  * Get master interface index
01401  * @arg link            link handle
01402  * @return Interface index of master or RTNL_LINK_NOT_FOUND if not set
01403  */
01404 int rtnl_link_get_master(struct rtnl_link *link)
01405 {
01406         if (link->l_mask & LINK_ATTR_MASTER)
01407                 return link->l_master;
01408         else
01409                 return RTNL_LINK_NOT_FOUND;
01410 }
01411 
01412 /**
01413  * Get the statistic specified by the id
01414  * @arg link            link handle
01415  * @arg id              statistic id
01416  * @return The current counter of the specified statistic
01417  */
01418 uint64_t rtnl_link_get_stat(struct rtnl_link *link, int id)
01419 {
01420         if (id < 0 || id > RTNL_LINK_STATS_MAX)
01421                 return 0;
01422 
01423         return link->l_stats[id];
01424 }
01425 
01426 /** @} */
01427 
01428 static struct nl_cache_ops rtnl_link_ops = {
01429         .co_name                = "route/link",
01430         .co_size                = sizeof(struct rtnl_link),
01431         .co_hdrsize             = sizeof(struct ifinfomsg),
01432         .co_msgtypes            = {
01433                                         { RTM_NEWLINK, "new" },
01434                                         { RTM_DELLINK, "delete" },
01435                                         { RTM_GETLINK, "get" },
01436                                         { -1, NULL },
01437                                   },
01438         .co_protocol            = NETLINK_ROUTE,
01439         .co_request_update      = link_request_update,
01440         .co_msg_parser          = link_msg_parser,
01441         .co_free_data           = link_free_data,
01442         .co_dump[NL_DUMP_BRIEF] = link_dump_brief,
01443         .co_dump[NL_DUMP_FULL]  = link_dump_full,
01444         .co_dump[NL_DUMP_STATS] = link_dump_stats,
01445         .co_dump[NL_DUMP_XML]   = link_dump_xml,
01446         .co_dump[NL_DUMP_ENV]   = link_dump_env,
01447         .co_filter              = link_filter,
01448 };
01449 
01450 static void __init link_init(void)
01451 {
01452         nl_cache_mngt_register(&rtnl_link_ops);
01453 }
01454 
01455 static void __exit link_exit(void)
01456 {
01457         nl_cache_mngt_unregister(&rtnl_link_ops);
01458 }
01459 
01460 /** @} */

Generated on Fri Apr 27 14:14:07 2007 for libnl by  doxygen 1.5.1