/build/buildd/libnl-1.0~pre6/lib/route/addr.c

00001 /*
00002  * lib/route/addr.c             Addresses
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  *                         Baruch Even <baruch@ev-en.org>,
00011  *                         Mediatrix Telecom, inc. <ericb@mediatrix.com>
00012  */
00013 
00014 /**
00015  * @ingroup rtnl
00016  * @defgroup rtaddr Addresses
00017  * @brief
00018  *
00019  * @par 1) Address Addition
00020  * @code
00021  * // Allocate an empty address object to be filled out with the attributes
00022  * // of the new address.
00023  * struct rtnl_addr *addr = rtnl_addr_alloc();
00024  *
00025  * // Fill out the mandatory attributes of the new address. Setting the
00026  * // local address will automatically set the address family and the
00027  * // prefix length to the correct values.
00028  * rtnl_addr_set_ifindex(addr, ifindex);
00029  * rtnl_addr_set_local(addr, local_addr);
00030  *
00031  * // The label of the address can be specified, currently only supported
00032  * // by IPv4 and DECnet.
00033  * rtnl_addr_set_label(addr, "mylabel");
00034  *
00035  * // The peer address can be specified if necessary, in either case a peer
00036  * // address will be sent to the kernel in order to fullfil the interface
00037  * // requirements. If none is set, it will equal the local address.
00038  * // Note: Real peer addresses are only supported by IPv4 for now.
00039  * rtnl_addr_set_peer(addr, peer_addr);
00040  *
00041  * // In case you want to have the address have a scope other than global
00042  * // it may be overwritten using rtnl_addr_set_scope(). The scope currently
00043  * // cannot be set for IPv6 addresses.
00044  * rtnl_addr_set_scope(addr, rtnl_str2scope("site"));
00045  *
00046  * // Broadcast and anycast address may be specified using the relevant
00047  * // functions, the address family will be verified if one of the other
00048  * // addresses has been set already. Currently only works for IPv4.
00049  * rtnl_addr_set_broadcast(addr, broadcast_addr);
00050  * rtnl_addr_set_anycast(addr, anycast_addr);
00051  *
00052  * // Build the netlink message and send it to the kernel, the operation will
00053  * // block until the operation has been completed. Alternatively the required
00054  * // netlink message can be built using rtnl_addr_build_add_request() to be
00055  * // sent out using nl_send_auto_complete().
00056  * rtnl_addr_add(handle, addr, 0);
00057  *
00058  * // Free the memory
00059  * rtnl_addr_put(addr);
00060  * @endcode
00061  *
00062  * @par 2) Address Deletion
00063  * @code
00064  * // Allocate an empty address object to be filled out with the attributes
00065  * // matching the address to be deleted. Alternatively a fully equipped
00066  * // address object out of a cache can be used instead.
00067  * struct rtnl_addr *addr = rtnl_addr_alloc();
00068  *
00069  * // The only mandatory parameter besides the address family is the interface
00070  * // index the address is on, i.e. leaving out all other parameters will
00071  * // result in all addresses of the specified address family interface tuple
00072  * // to be deleted.
00073  * rtnl_addr_set_ifindex(addr, ifindex);
00074  *
00075  * // Specyfing the address family manually is only required if neither the
00076  * // local nor peer address have been specified.
00077  * rtnl_addr_set_family(addr, AF_INET);
00078  *
00079  * // Specyfing the local address is optional but the best choice to delete
00080  * // specific addresses.
00081  * rtnl_addr_set_local(addr, local_addr);
00082  *
00083  * // The label of the address can be specified, currently only supported
00084  * // by IPv4 and DECnet.
00085  * rtnl_addr_set_label(addr, "mylabel");
00086  *
00087  * // The peer address can be specified if necessary, in either case a peer
00088  * // address will be sent to the kernel in order to fullfil the interface
00089  * // requirements. If none is set, it will equal the local address.
00090  * // Note: Real peer addresses are only supported by IPv4 for now.
00091  * rtnl_addr_set_peer(addr, peer_addr);
00092  *
00093  * // Build the netlink message and send it to the kernel, the operation will
00094  * // block until the operation has been completed. Alternatively the required
00095  * // netlink message can be built using rtnl_addr_build_delete_request()
00096  * // to be sent out using nl_send_auto_complete().
00097  * rtnl_addr_delete(handle, addr, 0);
00098  *
00099  * // Free the memory
00100  * rtnl_addr_put(addr);
00101  * @endcode
00102  * @{
00103  */
00104 
00105 #include <netlink-local.h>
00106 #include <netlink/netlink.h>
00107 #include <netlink/route/rtnl.h>
00108 #include <netlink/route/addr.h>
00109 #include <netlink/route/route.h>
00110 #include <netlink/route/link.h>
00111 #include <netlink/utils.h>
00112 
00113 /** @cond SKIP */
00114 #define ADDR_ATTR_FAMILY        0x0001
00115 #define ADDR_ATTR_PREFIXLEN     0x0002
00116 #define ADDR_ATTR_FLAGS         0x0004
00117 #define ADDR_ATTR_SCOPE         0x0008
00118 #define ADDR_ATTR_IFINDEX       0x0010
00119 #define ADDR_ATTR_LABEL         0x0020
00120 #define ADDR_ATTR_CACHEINFO     0x0040
00121 #define ADDR_ATTR_PEER          0x0080
00122 #define ADDR_ATTR_LOCAL         0x0100
00123 #define ADDR_ATTR_BROADCAST     0x0200
00124 #define ADDR_ATTR_ANYCAST       0x0400
00125 #define ADDR_ATTR_MULTICAST     0x0800
00126 
00127 static struct nl_cache_ops rtnl_addr_ops;
00128 /** @endcond */
00129 
00130 static void addr_free_data(struct nl_object *obj)
00131 {
00132         struct rtnl_addr *addr = nl_object_priv(obj);
00133 
00134         if (!addr)
00135                 return;
00136 
00137         nl_addr_put(addr->a_peer);
00138         nl_addr_put(addr->a_local);
00139         nl_addr_put(addr->a_bcast);
00140         nl_addr_put(addr->a_anycast);
00141         nl_addr_put(addr->a_multicast);
00142 }
00143 
00144 static struct nla_policy addr_policy[IFA_MAX+1] = {
00145         [IFA_LABEL]     = { .type = NLA_STRING,
00146                             .maxlen = IFNAMSIZ },
00147         [IFA_CACHEINFO] = { .minlen = sizeof(struct ifa_cacheinfo) },
00148 };
00149 
00150 static int addr_msg_parser(struct sockaddr_nl *who, struct nlmsghdr *nlh,
00151                            void *arg)
00152 {
00153         struct rtnl_addr *addr;
00154         struct nl_parser_param *pp = arg;
00155         struct ifaddrmsg *ifa;
00156         struct nlattr *tb[IFA_MAX+1];
00157         int err = -ENOMEM, peer_prefix = 0;
00158 
00159         addr = rtnl_addr_alloc();
00160         if (!addr) {
00161                 err = nl_errno(ENOMEM);
00162                 goto errout;
00163         }
00164         addr->ce_msgtype = nlh->nlmsg_type;
00165 
00166         err = nlmsg_parse(nlh, sizeof(*ifa), tb, IFA_MAX, addr_policy);
00167         if (err < 0)
00168                 goto errout_free;
00169 
00170         ifa = nlmsg_data(nlh);
00171         addr->a_family = ifa->ifa_family;
00172         addr->a_prefixlen = ifa->ifa_prefixlen;
00173         addr->a_flags = ifa->ifa_flags;
00174         addr->a_scope = ifa->ifa_scope;
00175         addr->a_ifindex = ifa->ifa_index;
00176 
00177         addr->a_mask = (ADDR_ATTR_FAMILY | ADDR_ATTR_PREFIXLEN |
00178                         ADDR_ATTR_FLAGS | ADDR_ATTR_SCOPE | ADDR_ATTR_IFINDEX);
00179 
00180         if (tb[IFA_LABEL]) {
00181                 nla_strlcpy(addr->a_label, tb[IFA_LABEL], IFNAMSIZ);
00182                 addr->a_mask |= ADDR_ATTR_LABEL;
00183         }
00184 
00185         if (tb[IFA_CACHEINFO]) {
00186                 struct ifa_cacheinfo *ca;
00187                 
00188                 ca = nla_data(tb[IFA_CACHEINFO]);
00189                 addr->a_cacheinfo.aci_prefered = ca->ifa_prefered;
00190                 addr->a_cacheinfo.aci_valid = ca->ifa_valid;
00191                 addr->a_cacheinfo.aci_cstamp = ca->cstamp;
00192                 addr->a_cacheinfo.aci_tstamp = ca->tstamp;
00193                 addr->a_mask |= ADDR_ATTR_CACHEINFO;
00194         }
00195 
00196         if (tb[IFA_LOCAL]) {
00197                 addr->a_local = nla_get_addr(tb[IFA_LOCAL], addr->a_family);
00198                 if (!addr->a_local)
00199                         goto errout_free;
00200                 addr->a_mask |= ADDR_ATTR_LOCAL;
00201         }
00202 
00203         if (tb[IFA_ADDRESS]) {
00204                 struct nl_addr *a;
00205 
00206                 a = nla_get_addr(tb[IFA_ADDRESS], addr->a_family);
00207                 if (!a)
00208                         goto errout_free;
00209 
00210                 /* IPv6 sends the local address as IFA_ADDRESS with
00211                  * no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS
00212                  * with IFA_ADDRESS being the peer address if they differ */
00213                 if (!tb[IFA_LOCAL] || !nl_addr_cmp(a, addr->a_local)) {
00214                         nl_addr_put(addr->a_local);
00215                         addr->a_local = a;
00216                         addr->a_mask |= ADDR_ATTR_LOCAL;
00217                 } else {
00218                         addr->a_peer = a;
00219                         addr->a_mask |= ADDR_ATTR_PEER;
00220                         peer_prefix = 1;
00221                 }
00222         }
00223 
00224         nl_addr_set_prefixlen(peer_prefix ? addr->a_peer : addr->a_local,
00225                               addr->a_prefixlen);
00226 
00227         if (tb[IFA_BROADCAST]) {
00228                 addr->a_bcast = nla_get_addr(tb[IFA_BROADCAST], addr->a_family);
00229                 if (!addr->a_bcast)
00230                         goto errout_free;
00231 
00232                 addr->a_mask |= ADDR_ATTR_BROADCAST;
00233         }
00234 
00235         if (tb[IFA_ANYCAST]) {
00236                 addr->a_anycast = nla_get_addr(tb[IFA_ANYCAST], addr->a_family);
00237                 if (!addr->a_anycast)
00238                         goto errout_free;
00239 
00240                 addr->a_mask |= ADDR_ATTR_ANYCAST;
00241         }
00242 
00243         if (tb[IFA_MULTICAST]) {
00244                 addr->a_multicast = nla_get_addr(tb[IFA_MULTICAST],
00245                                                  addr->a_family);
00246                 if (!addr->a_multicast)
00247                         goto errout_free;
00248 
00249                 addr->a_mask |= ADDR_ATTR_MULTICAST;
00250         }
00251 
00252         err = pp->pp_cb((struct nl_object *) addr, pp);
00253         if (err < 0)
00254                 goto errout_free;
00255 
00256         return P_ACCEPT;
00257 
00258 errout_free:
00259         rtnl_addr_free(addr);
00260 errout:
00261         return err;
00262 }
00263 
00264 static int addr_request_update(struct nl_cache *cache, struct nl_handle *handle)
00265 {
00266         return nl_rtgen_request(handle, RTM_GETADDR, AF_UNSPEC, NLM_F_DUMP);
00267 }
00268 
00269 static int addr_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
00270 {
00271         struct rtnl_addr *addr = (struct rtnl_addr *) obj;
00272         struct nl_cache *link_cache;
00273         char buf[128];
00274 
00275         link_cache = nl_cache_mngt_require("route/link");
00276 
00277         if (addr->a_mask & ADDR_ATTR_LOCAL)
00278                 dp_dump(p, "%s",
00279                         nl_addr2str(addr->a_local, buf, sizeof(buf)));
00280         else
00281                 dp_dump(p, "none");
00282 
00283         if (addr->a_mask & ADDR_ATTR_PEER)
00284                 dp_dump(p, " peer %s",
00285                         nl_addr2str(addr->a_peer, buf, sizeof(buf)));
00286 
00287         dp_dump(p, " %s ", nl_af2str(addr->a_family, buf, sizeof(buf)));
00288 
00289         if (link_cache)
00290                 dp_dump(p, "dev %s ",
00291                         rtnl_link_i2name(link_cache, addr->a_ifindex,
00292                                          buf, sizeof(buf)));
00293         else
00294                 dp_dump(p, "dev %d ", addr->a_ifindex);
00295 
00296         dp_dump(p, "scope %s",
00297                 rtnl_scope2str(addr->a_scope, buf, sizeof(buf)));
00298 
00299         rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf));
00300         if (buf[0])
00301                 dp_dump(p, " <%s>", buf);
00302 
00303         dp_dump(p, "\n");
00304 
00305         return 1;
00306 }
00307 
00308 static int addr_dump_full(struct nl_object *obj, struct nl_dump_params *p)
00309 {
00310         struct rtnl_addr *addr = (struct rtnl_addr *) obj;
00311         int line = addr_dump_brief(obj, p);
00312         char buf[128];
00313 
00314         if (addr->a_mask & (ADDR_ATTR_LABEL | ADDR_ATTR_BROADCAST |
00315                             ADDR_ATTR_ANYCAST | ADDR_ATTR_MULTICAST)) {
00316                 dp_dump_line(p, line++, "  ");
00317 
00318                 if (addr->a_mask & ADDR_ATTR_LABEL)
00319                         dp_dump(p, " label %s", addr->a_label);
00320 
00321                 if (addr->a_mask & ADDR_ATTR_BROADCAST)
00322                         dp_dump(p, " broadcast %s",
00323                                 nl_addr2str(addr->a_bcast, buf, sizeof(buf)));
00324 
00325                 if (addr->a_mask & ADDR_ATTR_ANYCAST)
00326                         dp_dump(p, " anycast %s",
00327                                 nl_addr2str(addr->a_anycast, buf,
00328                                               sizeof(buf)));
00329 
00330                 if (addr->a_mask & ADDR_ATTR_MULTICAST)
00331                         dp_dump(p, " multicast %s",
00332                                 nl_addr2str(addr->a_multicast, buf,
00333                                               sizeof(buf)));
00334 
00335                 dp_dump(p, "\n");
00336         }
00337 
00338         if (addr->a_mask & ADDR_ATTR_CACHEINFO) {
00339                 struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo;
00340 
00341                 dp_dump_line(p, line++, "   valid-lifetime %s",
00342                              ci->aci_valid == 0xFFFFFFFFU ? "forever" :
00343                              nl_msec2str(ci->aci_valid * 1000,
00344                                            buf, sizeof(buf)));
00345 
00346                 dp_dump(p, " preferred-lifetime %s\n",
00347                         ci->aci_prefered == 0xFFFFFFFFU ? "forever" :
00348                         nl_msec2str(ci->aci_prefered * 1000,
00349                                       buf, sizeof(buf)));
00350 
00351                 dp_dump_line(p, line++, "   created boot-time+%s ",
00352                              nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10,
00353                                            buf, sizeof(buf)));
00354                     
00355                 dp_dump(p, "last-updated boot-time+%s\n",
00356                         nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10,
00357                                       buf, sizeof(buf)));
00358         }
00359 
00360         return line;
00361 }
00362 
00363 static int addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
00364 {
00365         return addr_dump_full(obj, p);
00366 }
00367 
00368 static int addr_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
00369 {
00370         struct rtnl_addr *addr = (struct rtnl_addr *) obj;
00371         struct nl_cache *link_cache;
00372         char buf[128];
00373         int line = 0;
00374 
00375         dp_dump_line(p, line++, "<address>\n");
00376         dp_dump_line(p, line++, "  <family>%s</family>\n",
00377                      nl_af2str(addr->a_family, buf, sizeof(buf)));
00378 
00379         if (addr->a_mask & ADDR_ATTR_LOCAL)
00380                 dp_dump_line(p, line++, "  <local>%s</local>\n",
00381                              nl_addr2str(addr->a_local, buf, sizeof(buf)));
00382 
00383         if (addr->a_mask & ADDR_ATTR_PEER)
00384                 dp_dump_line(p, line++, "  <peer>%s</peer>\n",
00385                              nl_addr2str(addr->a_peer, buf, sizeof(buf)));
00386 
00387         if (addr->a_mask & ADDR_ATTR_BROADCAST)
00388                 dp_dump_line(p, line++, "  <broadcast>%s</broadcast>\n",
00389                              nl_addr2str(addr->a_bcast, buf, sizeof(buf)));
00390 
00391         if (addr->a_mask & ADDR_ATTR_ANYCAST)
00392                 dp_dump_line(p, line++, "  <anycast>%s</anycast>\n",
00393                              nl_addr2str(addr->a_anycast, buf, sizeof(buf)));
00394 
00395         if (addr->a_mask & ADDR_ATTR_MULTICAST)
00396                 dp_dump_line(p, line++, "  <multicast>%s</multicast>\n",
00397                              nl_addr2str(addr->a_multicast, buf,
00398                                            sizeof(buf)));
00399 
00400         if (addr->a_mask & ADDR_ATTR_PREFIXLEN)
00401                 dp_dump_line(p, line++, "  <prefixlen>%u</prefixlen>\n",
00402                              addr->a_prefixlen);
00403         link_cache = nl_cache_mngt_require("route/link");
00404 
00405         if (link_cache)
00406                 dp_dump_line(p, line++, "  <device>%s</device>\n",
00407                              rtnl_link_i2name(link_cache, addr->a_ifindex,
00408                                               buf, sizeof(buf)));
00409         else
00410                 dp_dump_line(p, line++, "  <device>%u</device>\n",
00411                              addr->a_ifindex);
00412 
00413         if (addr->a_mask & ADDR_ATTR_SCOPE)
00414                 dp_dump_line(p, line++, "  <scope>%s</scope>\n",
00415                              rtnl_scope2str(addr->a_scope, buf, sizeof(buf)));
00416 
00417         if (addr->a_mask & ADDR_ATTR_LABEL)
00418                 dp_dump_line(p, line++, "  <label>%s</label>\n", addr->a_label);
00419 
00420         rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf));
00421         if (buf[0])
00422                 dp_dump_line(p, line++, "  <flags>%s</flags>\n", buf);
00423 
00424         if (addr->a_mask & ADDR_ATTR_CACHEINFO) {
00425                 struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo;
00426 
00427                 dp_dump_line(p, line++, "  <cacheinfo>\n");
00428 
00429                 dp_dump_line(p, line++, "    <valid>%s</valid>\n",
00430                              ci->aci_valid == 0xFFFFFFFFU ? "forever" :
00431                              nl_msec2str(ci->aci_valid * 1000,
00432                                            buf, sizeof(buf)));
00433 
00434                 dp_dump_line(p, line++, "    <prefered>%s</prefered>\n",
00435                              ci->aci_prefered == 0xFFFFFFFFU ? "forever" :
00436                              nl_msec2str(ci->aci_prefered * 1000,
00437                                          buf, sizeof(buf)));
00438 
00439                 dp_dump_line(p, line++, "    <created>%s</created>\n",
00440                              nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10,
00441                                          buf, sizeof(buf)));
00442 
00443                 dp_dump_line(p, line++, "    <last-update>%s</last-update>\n",
00444                              nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10,
00445                                          buf, sizeof(buf)));
00446 
00447                 dp_dump_line(p, line++, "  </cacheinfo>\n");
00448         }
00449 
00450         dp_dump_line(p, line++, "</address>\n");
00451 
00452         return line;
00453 }
00454 
00455 static int addr_dump_env(struct nl_object *obj, struct nl_dump_params *p)
00456 {
00457         struct rtnl_addr *addr = (struct rtnl_addr *) obj;
00458         struct nl_cache *link_cache;
00459         char buf[128];
00460         int line = 0;
00461 
00462         dp_dump_line(p, line++, "ADDR_FAMILY=%s\n",
00463                      nl_af2str(addr->a_family, buf, sizeof(buf)));
00464 
00465         if (addr->a_mask & ADDR_ATTR_LOCAL)
00466                 dp_dump_line(p, line++, "ADDR_LOCAL=%s\n",
00467                              nl_addr2str(addr->a_local, buf, sizeof(buf)));
00468 
00469         if (addr->a_mask & ADDR_ATTR_PEER)
00470                 dp_dump_line(p, line++, "ADDR_PEER=%s\n",
00471                              nl_addr2str(addr->a_peer, buf, sizeof(buf)));
00472 
00473         if (addr->a_mask & ADDR_ATTR_BROADCAST)
00474                 dp_dump_line(p, line++, "ADDR_BROADCAST=%s\n",
00475                              nl_addr2str(addr->a_bcast, buf, sizeof(buf)));
00476 
00477         if (addr->a_mask & ADDR_ATTR_ANYCAST)
00478                 dp_dump_line(p, line++, "ADDR_ANYCAST=%s\n",
00479                              nl_addr2str(addr->a_anycast, buf, sizeof(buf)));
00480 
00481         if (addr->a_mask & ADDR_ATTR_MULTICAST)
00482                 dp_dump_line(p, line++, "ADDR_MULTICAST=%s\n",
00483                              nl_addr2str(addr->a_multicast, buf,
00484                                            sizeof(buf)));
00485 
00486         if (addr->a_mask & ADDR_ATTR_PREFIXLEN)
00487                 dp_dump_line(p, line++, "ADDR_PREFIXLEN=%u\n",
00488                              addr->a_prefixlen);
00489         link_cache = nl_cache_mngt_require("route/link");
00490 
00491         dp_dump_line(p, line++, "ADDR_IFINDEX=%u\n", addr->a_ifindex);
00492         if (link_cache)
00493                 dp_dump_line(p, line++, "ADDR_IFNAME=%s\n",
00494                              rtnl_link_i2name(link_cache, addr->a_ifindex,
00495                                               buf, sizeof(buf)));
00496 
00497         if (addr->a_mask & ADDR_ATTR_SCOPE)
00498                 dp_dump_line(p, line++, "ADDR_SCOPE=%s\n",
00499                              rtnl_scope2str(addr->a_scope, buf, sizeof(buf)));
00500 
00501         if (addr->a_mask & ADDR_ATTR_LABEL)
00502                 dp_dump_line(p, line++, "ADDR_LABEL=%s\n", addr->a_label);
00503 
00504         rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf));
00505         if (buf[0])
00506                 dp_dump_line(p, line++, "ADDR_FLAGS=%s\n", buf);
00507 
00508         if (addr->a_mask & ADDR_ATTR_CACHEINFO) {
00509                 struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo;
00510 
00511                 dp_dump_line(p, line++, "ADDR_CACHEINFO_VALID=%s\n",
00512                              ci->aci_valid == 0xFFFFFFFFU ? "forever" :
00513                              nl_msec2str(ci->aci_valid * 1000,
00514                                            buf, sizeof(buf)));
00515 
00516                 dp_dump_line(p, line++, "ADDR_CACHEINFO_PREFERED=%s\n",
00517                              ci->aci_prefered == 0xFFFFFFFFU ? "forever" :
00518                              nl_msec2str(ci->aci_prefered * 1000,
00519                                          buf, sizeof(buf)));
00520 
00521                 dp_dump_line(p, line++, "ADDR_CACHEINFO_CREATED=%s\n",
00522                              nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10,
00523                                          buf, sizeof(buf)));
00524 
00525                 dp_dump_line(p, line++, "ADDR_CACHEINFO_LASTUPDATE=%s\n",
00526                              nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10,
00527                                          buf, sizeof(buf)));
00528         }
00529 
00530         return line;
00531 }
00532 
00533 static int addr_filter(struct nl_object *obj, struct nl_object *filter)
00534 {
00535         struct rtnl_addr *o = (struct rtnl_addr *) obj;
00536         struct rtnl_addr *f = (struct rtnl_addr *) filter;
00537 
00538 #define REQ(F) (f->a_mask & ADDR_ATTR_##F)
00539 #define AVAIL(F) (o->a_mask & ADDR_ATTR_##F)
00540 #define _O(F, EXPR) (REQ(F) && (!AVAIL(F) || (EXPR)))
00541 #define _C(F, N) (REQ(F) && (!AVAIL(F) || (o->N != f->N)))
00542         if (_C(IFINDEX,    a_ifindex)                                   ||
00543             _C(FAMILY,     a_family)                                    ||
00544             _C(SCOPE,      a_scope)                                     ||
00545             _O(FLAGS,      f->a_flags ^ (o->a_flags & f->a_flag_mask))  ||
00546             _O(LABEL,      strcmp(o->a_label, f->a_label))              ||
00547             _O(PEER,       nl_addr_cmp(o->a_peer, f->a_peer))           ||
00548             _O(LOCAL,      nl_addr_cmp(o->a_local, f->a_local))         ||
00549             _O(ANYCAST,    nl_addr_cmp(o->a_anycast, f->a_anycast))     ||
00550             _O(MULTICAST,  nl_addr_cmp(o->a_multicast, f->a_multicast)) ||
00551             _O(BROADCAST,  nl_addr_cmp(o->a_bcast, f->a_bcast)))
00552                 return 0;
00553 #undef REQ
00554 #undef AVAIL
00555 #undef _O
00556 #undef _C
00557 
00558         return 1;
00559 }
00560 
00561 /**
00562  * @name Address Object Creation/Deletion
00563  * @{
00564  */
00565 
00566 /**
00567  * Allocate and initialize a new address object
00568  * @note Free the memory after usage using rtnl_addr_put() or rtnl_addr_free().
00569  * @return Newly allocated address object or NULL if an error occured.
00570  */
00571 struct rtnl_addr *rtnl_addr_alloc(void)
00572 {
00573         return (struct rtnl_addr *) nl_object_alloc_from_ops(&rtnl_addr_ops);
00574 }
00575 
00576 /**
00577  * Give back a reference on a address object.
00578  * @arg addr            Address object to be given back.
00579  *
00580  * Decrements the reference counter and frees the object if the
00581  * last reference has been released.
00582  */
00583 void rtnl_addr_put(struct rtnl_addr *addr)
00584 {
00585         nl_object_put((struct nl_object *) addr);
00586 }
00587 
00588 /**
00589  * Free an address object
00590  * @arg addr            Address object to be freed.
00591  *
00592  * @note Always use rtnl_addr_put() unless you're absolutely sure
00593  *       that no other user may have a reference on this object.
00594  */
00595 void rtnl_addr_free(struct rtnl_addr *addr)
00596 {
00597         nl_object_free((struct nl_object *) addr);
00598 }
00599 
00600 /** @} */
00601 
00602 /**
00603  * @name Address Cache Management
00604  * @{
00605  */
00606 
00607 /**
00608  * Allocate address cache and fill in all configured addresses
00609  * @arg handle          Netlink handle.
00610  *
00611  * Allocates a new address cache, initializes it properly and updates it
00612  * to include all addresses currently configured in the kernel.
00613  *
00614  * @note Free the memory after usage.
00615  * @return Newly allocated cache or NULL if an error occured.
00616  */
00617 struct nl_cache *rtnl_addr_alloc_cache(struct nl_handle *handle)
00618 {
00619         struct nl_cache *cache;
00620         
00621         cache = nl_cache_alloc_from_ops(&rtnl_addr_ops);
00622         if (!cache)
00623                 return NULL;
00624 
00625         if (nl_cache_update(handle, cache) < 0) {
00626                 nl_cache_free(cache);
00627                 return NULL;
00628         }
00629 
00630         return cache;
00631 }
00632 
00633 /** @} */
00634 
00635 static struct nl_msg *build_addr_msg(struct rtnl_addr *tmpl, int cmd, int flags)
00636 {
00637         struct nl_msg *msg;
00638         struct ifaddrmsg am = {
00639                 .ifa_family = tmpl->a_family,
00640                 .ifa_index = tmpl->a_ifindex,
00641                 .ifa_prefixlen = tmpl->a_prefixlen,
00642         };
00643 
00644         if (tmpl->a_mask & ADDR_ATTR_SCOPE)
00645                 am.ifa_scope = tmpl->a_scope;
00646         else {
00647                 /* compatibility hack */
00648                 if (tmpl->a_family == AF_INET &&
00649                     tmpl->a_mask & ADDR_ATTR_LOCAL &&
00650                     *((char *) nl_addr_get_binary_addr(tmpl->a_local)) == 127)
00651                         am.ifa_scope = RT_SCOPE_HOST;
00652                 else
00653                         am.ifa_scope = RT_SCOPE_UNIVERSE;
00654         }
00655 
00656         msg = nlmsg_build_simple(cmd, flags);
00657         if (!msg)
00658                 goto nla_put_failure;
00659 
00660         if (nlmsg_append(msg, &am, sizeof(am), 1) < 0)
00661                 goto nla_put_failure;
00662 
00663         if (tmpl->a_mask & ADDR_ATTR_LOCAL)
00664                 NLA_PUT_ADDR(msg, IFA_LOCAL, tmpl->a_local);
00665 
00666         if (tmpl->a_mask & ADDR_ATTR_PEER)
00667                 NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_peer);
00668         else
00669                 NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_local);
00670 
00671         if (tmpl->a_mask & ADDR_ATTR_LABEL)
00672                 NLA_PUT_STRING(msg, IFA_LABEL, tmpl->a_label);
00673 
00674         if (tmpl->a_mask & ADDR_ATTR_BROADCAST)
00675                 NLA_PUT_ADDR(msg, IFA_BROADCAST, tmpl->a_bcast);
00676 
00677         if (tmpl->a_mask & ADDR_ATTR_ANYCAST)
00678                 NLA_PUT_ADDR(msg, IFA_ANYCAST, tmpl->a_anycast);
00679 
00680         return msg;
00681 
00682 nla_put_failure:
00683         nlmsg_free(msg);
00684         return NULL;
00685 }
00686 
00687 /**
00688  * @name Address Addition
00689  * @{
00690  */
00691 
00692 /**
00693  * Build netlink request message to request addition of new address
00694  * @arg addr            Address object representing the new address.
00695  * @arg flags           Additional netlink message flags.
00696  *
00697  * Builds a new netlink message requesting the addition of a new
00698  * address. The netlink message header isn't fully equipped with
00699  * all relevant fields and must thus be sent out via nl_send_auto_complete()
00700  * or supplemented as needed.
00701  *
00702  * Minimal required attributes:
00703  *   - interface index (rtnl_addr_set_ifindex())
00704  *   - local address (rtnl_addr_set_local())
00705  *
00706  * The scope will default to universe except for loopback addresses in
00707  * which case a host scope is used if not specified otherwise.
00708  *
00709  * @note Free the memory after usage using nlmsg_free().
00710  * @return Newly allocated netlink message or NULL if an error occured.
00711  */
00712 struct nl_msg *rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags)
00713 {
00714         int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY |
00715                        ADDR_ATTR_PREFIXLEN | ADDR_ATTR_LOCAL;
00716 
00717         if ((addr->a_mask & required) != required) {
00718                 nl_error(EINVAL, "Missing mandatory attributes, required are: "
00719                                  "ifindex, family, prefixlen, local address.");
00720                 return NULL;
00721         }
00722         
00723         return build_addr_msg(addr, RTM_NEWADDR, NLM_F_CREATE | flags);
00724 }
00725 
00726 /**
00727  * Request addition of new address
00728  * @arg handle          Netlink handle.
00729  * @arg addr            Address object representing the new address.
00730  * @arg flags           Additional netlink message flags.
00731  *
00732  * Builds a netlink message by calling rtnl_addr_build_add_request(),
00733  * sends the request to the kernel and waits for the next ACK to be
00734  * received and thus blocks until the request has been fullfilled.
00735  *
00736  * @see rtnl_addr_build_add_request()
00737  *
00738  * @return 0 on sucess or a negative error if an error occured.
00739  */
00740 int rtnl_addr_add(struct nl_handle *handle, struct rtnl_addr *addr, int flags)
00741 {
00742         struct nl_msg *msg;
00743         int err;
00744 
00745         msg = rtnl_addr_build_add_request(addr, flags);
00746         if (!msg)
00747                 return nl_get_errno();
00748 
00749         err = nl_send_auto_complete(handle, msg);
00750         nlmsg_free(msg);
00751         if (err < 0)
00752                 return err;
00753 
00754         return nl_wait_for_ack(handle);
00755 }
00756 
00757 /** @} */
00758 
00759 /**
00760  * @name Address Deletion
00761  * @{
00762  */
00763 
00764 /**
00765  * Build a netlink request message to request deletion of an address
00766  * @arg addr            Address object to be deleteted.
00767  * @arg flags           Additional netlink message flags.
00768  *
00769  * Builds a new netlink message requesting a deletion of an address.
00770  * The netlink message header isn't fully equipped with all relevant
00771  * fields and must thus be sent out via nl_send_auto_complete()
00772  * or supplemented as needed.
00773  *
00774  * Minimal required attributes:
00775  *   - interface index (rtnl_addr_set_ifindex())
00776  *   - address family (rtnl_addr_set_family())
00777  *
00778  * Optional attributes:
00779  *   - local address (rtnl_addr_set_local())
00780  *   - label (rtnl_addr_set_label(), IPv4/DECnet only)
00781  *   - peer address (rtnl_addr_set_peer(), IPv4 only)
00782  *
00783  * @note Free the memory after usage using nlmsg_free().
00784  * @return Newly allocated netlink message or NULL if an error occured.
00785  */
00786 struct nl_msg *rtnl_addr_build_delete_request(struct rtnl_addr *addr, int flags)
00787 {
00788         int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY;
00789 
00790         if ((addr->a_mask & required) != required) {
00791                 nl_error(EINVAL, "Missing mandatory attributes, required are: "
00792                                  "ifindex, family");
00793                 return NULL;
00794         }
00795         
00796         return build_addr_msg(addr, RTM_DELADDR, flags);
00797 }
00798 
00799 /**
00800  * Request deletion of an address
00801  * @arg handle          Netlink handle.
00802  * @arg addr            Address object to be deleted.
00803  * @arg flags           Additional netlink message flags.
00804  *
00805  * Builds a netlink message by calling rtnl_addr_build_delete_request(),
00806  * sends the request to the kernel and waits for the next ACK to be
00807  * received and thus blocks until the request has been fullfilled.
00808  *
00809  * @see rtnl_addr_build_delete_request();
00810  *
00811  * @return 0 on sucess or a negative error if an error occured.
00812  */
00813 int rtnl_addr_delete(struct nl_handle *handle, struct rtnl_addr *addr,
00814                      int flags)
00815 {
00816         struct nl_msg *msg;
00817         int err;
00818 
00819         msg = rtnl_addr_build_delete_request(addr, flags);
00820         if (!msg)
00821                 return nl_get_errno();
00822 
00823         err = nl_send_auto_complete(handle, msg);
00824         nlmsg_free(msg);
00825         if (err < 0)
00826                 return err;
00827 
00828         return nl_wait_for_ack(handle);
00829 }
00830 
00831 /** @} */
00832 
00833 /**
00834  * @name Attribute Access
00835  * @{
00836  */
00837 
00838 /**
00839  * Set label of address object
00840  * @arg addr            Address object to be modified.
00841  * @arg label           New address label.
00842  * 
00843  * @note The maximum size of an address label is IFNAMSIZ.
00844  */
00845 void rtnl_addr_set_label(struct rtnl_addr *addr, const char *label)
00846 {
00847         strncpy(addr->a_label, label, sizeof(addr->a_label) - 1);
00848         addr->a_mask |= ADDR_ATTR_LABEL;
00849 }
00850 
00851 /**
00852  * Get label of address object
00853  * @arg addr            Address object.
00854  * @return Address label or NULL if not set.
00855  */
00856 char *rtnl_addr_get_label(struct rtnl_addr *addr)
00857 {
00858         if (addr->a_mask & ADDR_ATTR_LABEL)
00859                 return addr->a_label;
00860         else
00861                 return NULL;
00862 }
00863 
00864 /**
00865  * Set interface index of address object
00866  * @arg addr            Address object ot be modified.
00867  * @arg ifindex         New interface index this address is on.
00868  */
00869 void rtnl_addr_set_ifindex(struct rtnl_addr *addr, int ifindex)
00870 {
00871         addr->a_ifindex = ifindex;
00872         addr->a_mask |= ADDR_ATTR_IFINDEX;
00873 }
00874 
00875 /**
00876  * Get interface index of address object
00877  * @arg addr            Address object.
00878  * @return Interface index address is on or RTNL_LINK_NOT_FOUND if not set.
00879  */
00880 int rtnl_addr_get_ifindex(struct rtnl_addr *addr)
00881 {
00882         if (addr->a_mask & ADDR_ATTR_IFINDEX)
00883                 return addr->a_ifindex;
00884         else
00885                 return RTNL_LINK_NOT_FOUND;
00886 }
00887 
00888 /**
00889  * Set address family of address object.
00890  * @arg addr            Address object to be modified.
00891  * @arg family          New address family
00892  *
00893  * @note The address family is set automatically if one of the addresses
00894  *       is set and the family hasn't been specified yet. Setting it manually
00895  *       can be used to enforce family validation while setting addresses.
00896  */
00897 void rtnl_addr_set_family(struct rtnl_addr *addr, int family)
00898 {
00899         addr->a_family = family;
00900         addr->a_mask |= ADDR_ATTR_FAMILY;
00901 }
00902 
00903 /**
00904  * Get address family of address object.
00905  * @arg addr            Address object.
00906  * @return Address family or AF_UNSPEC if not set.
00907  */
00908 int rtnl_addr_get_family(struct rtnl_addr *addr)
00909 {
00910         if (addr->a_mask & ADDR_ATTR_FAMILY)
00911                 return addr->a_family;
00912         else
00913                 return AF_UNSPEC;
00914 }
00915 
00916 /**
00917  * Set prefix length of address object.
00918  * @arg addr            Address object to be modified.
00919  * @arg prefix          New prefix length.
00920  */
00921 void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefix)
00922 {
00923         addr->a_prefixlen = prefix;
00924         addr->a_mask |= ADDR_ATTR_PREFIXLEN;
00925 }
00926 
00927 /**
00928  * Get prefix length of address object.
00929  * @arg addr            Address object.
00930  * @return Prefix length or a negative number if not set.
00931  */
00932 int rtnl_addr_get_prefixlen(struct rtnl_addr *addr)
00933 {
00934         if (addr->a_mask & ADDR_ATTR_PREFIXLEN)
00935                 return addr->a_prefixlen;
00936         else
00937                 return -1;
00938 }
00939 
00940 /**
00941  * Set scope of address object.
00942  * @arg addr            Address object to be modified.
00943  * @arg scope           New scope.
00944  */
00945 void rtnl_addr_set_scope(struct rtnl_addr *addr, int scope)
00946 {
00947         addr->a_scope = scope;
00948         addr->a_mask |= ADDR_ATTR_SCOPE;
00949 }
00950 
00951 /**
00952  * Get scope of address object.
00953  * @arg addr            Address object.
00954  * @return Scope or a negative number if not set.
00955  */
00956 int rtnl_addr_get_scope(struct rtnl_addr *addr)
00957 {
00958         if (addr->a_mask & ADDR_ATTR_SCOPE)
00959                 return addr->a_scope;
00960         else
00961                 return -1;
00962 }
00963 
00964 /**
00965  * Set flags of address object.
00966  * @arg addr            Address object to be modified.
00967  * @arg flags           Additional flags to set.
00968  *
00969  * @note Existing flags that have been set will not be overwritten.
00970  */
00971 void rtnl_addr_set_flags(struct rtnl_addr *addr, unsigned int flags)
00972 {
00973         addr->a_flag_mask |= flags;
00974         addr->a_flags |= flags;
00975         addr->a_mask |= ADDR_ATTR_FLAGS;
00976 }
00977 
00978 /**
00979  * Unset flags of address object.
00980  * @arg addr            Address object to be modified.
00981  * @arg flags           Flags to unset.
00982  */
00983 void rtnl_addr_unset_flags(struct rtnl_addr *addr, unsigned int flags)
00984 {
00985         addr->a_flag_mask |= flags;
00986         addr->a_flags &= ~flags;
00987         addr->a_mask |= ADDR_ATTR_FLAGS;
00988 }
00989 
00990 /**
00991  * Get flags of address object.
00992  * @arg addr            Address object.
00993  * @return Flags in form of a bitmask.
00994  */
00995 unsigned int rtnl_addr_get_flags(struct rtnl_addr *addr)
00996 {
00997         return addr->a_flags;
00998 }
00999 
01000 static inline int __assign_addr(struct rtnl_addr *addr, struct nl_addr **pos,
01001                                 struct nl_addr *new, int flag)
01002 {
01003         if (addr->a_mask & ADDR_ATTR_FAMILY) {
01004                 if (new->a_family != addr->a_family)
01005                         return nl_error(EINVAL, "Address family mismatch");
01006         } else
01007                 addr->a_family = new->a_family;
01008 
01009         if (*pos)
01010                 nl_addr_put(*pos);
01011 
01012         *pos = nl_addr_get(new);
01013         addr->a_mask |= (flag | ADDR_ATTR_FAMILY);
01014 
01015         return 0;
01016 }
01017 
01018 /**
01019  * Set local address of address object.
01020  * @arg addr            Address object to be modified.
01021  * @arg local           New local address.
01022  *
01023  * Assigns the new local address to the specified address object. The
01024  * address is validated against the address family if set already via
01025  * either rtnl_addr_set_family() or by setting one of the other addresses.
01026  * The assignment fails if the address families mismatch. In case the
01027  * address family has not been specified yet, the address family of the
01028  * new address is elected to be the new requirement.
01029  *
01030  * @note The address may not contain a prefix length if the peer address
01031  *       has been specified already.
01032  * 
01033  * @return 0 on success or a negative error code.
01034  */
01035 int rtnl_addr_set_local(struct rtnl_addr *addr, struct nl_addr *local)
01036 {
01037         int err;
01038 
01039         err = __assign_addr(addr, &addr->a_local, local, ADDR_ATTR_LOCAL);
01040         if (err < 0)
01041                 return err;
01042 
01043         if (!(addr->a_mask & ADDR_ATTR_PEER)) {
01044                 addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_local);
01045                 addr->a_mask |= ADDR_ATTR_PREFIXLEN;
01046         }
01047 
01048         return 0;
01049 }
01050 
01051 /**
01052  * Get local address of address object.
01053  * @arg addr            Address object.
01054  * @return Local address or NULL if not set.
01055  */
01056 struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr)
01057 {
01058         if (addr->a_mask & ADDR_ATTR_LOCAL)
01059                 return addr->a_local;
01060         else
01061                 return NULL;
01062 }
01063 
01064 /**
01065  * Set peer address of address object.
01066  * @arg addr            Address object to be modified.
01067  * @arg peer            New peer address.
01068  *
01069  * Assigns the new peer address to the specified address object. The
01070  * address is validated against the address family if set already via
01071  * either rtnl_addr_set_family() or by setting one of the other addresses.
01072  * The assignment fails if the address families mismatch. In case the
01073  * address family has not been specified yet, the address family of this
01074  * new address is elected to be the requirement.
01075  * 
01076  * @return 0 on success or a negative error code.
01077  */
01078 int rtnl_addr_set_peer(struct rtnl_addr *addr, struct nl_addr *peer)
01079 {
01080         return __assign_addr(addr, &addr->a_peer, peer, ADDR_ATTR_PEER);
01081 
01082         addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_peer);
01083         addr->a_mask |= ADDR_ATTR_PREFIXLEN;
01084 
01085         return 0;
01086 }
01087 
01088 /**
01089  * Get peer address of address object.
01090  * @arg addr            Adress object.
01091  * @return Peer address or NULL if not set.
01092  */
01093 struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr)
01094 {
01095         if (addr->a_mask & ADDR_ATTR_PEER)
01096                 return addr->a_peer;
01097         else
01098                 return NULL;
01099 }
01100 
01101 /**
01102  * Set broadcast address of address object.
01103  * @arg addr            Address object to be modified.
01104  * @arg bcast           New broadcast address.
01105  *
01106  * Assigns the new broadcast address to the specified address object. The
01107  * address is validated against the address family if set already via
01108  * either rtnl_addr_set_family() or by setting one of the other addresses.
01109  * The assignment fails if the address families mismatch. In case the
01110  * address family has not been specified yet, the address family of this
01111  * new address is elected to be the requirement.
01112  * 
01113  * @return 0 on success or a negative error code.
01114  */
01115 int rtnl_addr_set_broadcast(struct rtnl_addr *addr, struct nl_addr *bcast)
01116 {
01117         return __assign_addr(addr, &addr->a_bcast, bcast, ADDR_ATTR_BROADCAST);
01118 }
01119 
01120 /**
01121  * Get broadcast address of address object.
01122  * @arg addr            Address object.
01123  * @return Broadcast address or NULL if not set.
01124  */
01125 struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *addr)
01126 {
01127         if (addr->a_mask & ADDR_ATTR_BROADCAST)
01128                 return addr->a_bcast;
01129         else
01130                 return NULL;
01131 }
01132 
01133 /**
01134  * Set anycast address of address object.
01135  * @arg addr            Address object to be modified.
01136  * @arg anycast         New anycast address.
01137  *
01138  * Assigns the new anycast address to the specified address object. The
01139  * address is validated against the address family if set already via
01140  * either rtnl_addr_set_family() or by setting one of the other addresses.
01141  * The assignment fails if the address families mismatch. In case the
01142  * address family has not been specified yet, the address family of this
01143  * new address is elected to be the requirement.
01144  * 
01145  * @return 0 on success or a negative error code.
01146  */
01147 int rtnl_addr_set_anycast(struct rtnl_addr *addr, struct nl_addr *anycast)
01148 {
01149         return __assign_addr(addr, &addr->a_anycast, anycast,
01150                              ADDR_ATTR_ANYCAST);
01151 }
01152 
01153 /**
01154  * Get anycast address of address object.
01155  * @arg addr            Address object.
01156  * @return Anycast address or NULL if not set.
01157  */
01158 struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *addr)
01159 {
01160         if (addr->a_mask & ADDR_ATTR_ANYCAST)
01161                 return addr->a_anycast;
01162         else
01163                 return NULL;
01164 }
01165 
01166 /**
01167  * Set multicast address of address object.
01168  * @arg addr            Address object to be modified.
01169  * @arg multicast       New multicast address.
01170  *
01171  * Assigns the new multicast address to the specified address object. The
01172  * address is validated against the address family if set already via
01173  * either rtnl_addr_set_family() or by setting one of the other addresses.
01174  * The assignment fails if the address families mismatch. In case the
01175  * address family has not been specified yet, the address family of this
01176  * new address is elected to be the requirement.
01177  * 
01178  * @return 0 on success or a negative error code.
01179  */
01180 int rtnl_addr_set_multicast(struct rtnl_addr *addr, struct nl_addr *multicast)
01181 {
01182         return __assign_addr(addr, &addr->a_multicast, multicast,
01183                              ADDR_ATTR_MULTICAST);
01184 }
01185 
01186 /**
01187  * Get multicast address of address object.
01188  * @arg addr            Address object.
01189  * @return Multicast address or NULL if not set.
01190  */
01191 struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr)
01192 {
01193         if (addr->a_mask & ADDR_ATTR_MULTICAST)
01194                 return addr->a_multicast;
01195         else
01196                 return NULL;
01197 }
01198 
01199 /** @} */
01200 
01201 /**
01202  * @name Address Flags Translations
01203  * @{
01204  */
01205 
01206 static struct trans_tbl addr_flags[] = {
01207         __ADD(IFA_F_SECONDARY, secondary)
01208         __ADD(IFA_F_DEPRECATED, deprecated)
01209         __ADD(IFA_F_TENTATIVE, tentative)
01210         __ADD(IFA_F_PERMANENT, permanent)
01211 };
01212 
01213 /**
01214  * Convert address flags to character string.
01215  * @arg flags           Address flags.
01216  * @arg buf             Destination buffer.
01217  * @arg size            Size of destination buffer.
01218  *
01219  * Converts address flags to a character string separated by commas and
01220  * stores the resulting character string in the specified destination buffer.
01221  *
01222  * @return Formatted flags as character string.
01223  */
01224 char *rtnl_addr_flags2str(int flags, char *buf, size_t size)
01225 {
01226         return __flags2str(flags, buf, size, addr_flags,
01227                            ARRAY_SIZE(addr_flags));
01228 }
01229 
01230 /**
01231  * Convert character string to address flags.
01232  * @arg name            Name of address flags.
01233  *
01234  * Converts the provided character string specifying any number of address
01235  * flags separated by commas to the corresponding numeric bitmask.
01236  *
01237  * @return Address flags in form of a bitmask.
01238  */
01239 int rtnl_addr_str2flags(const char *name)
01240 {
01241         return __str2flags(name, addr_flags, ARRAY_SIZE(addr_flags));
01242 }
01243 
01244 /** @} */
01245 
01246 static struct nl_cache_ops rtnl_addr_ops = {
01247         .co_name                = "route/addr",
01248         .co_size                = sizeof(struct rtnl_addr),
01249         .co_hdrsize             = sizeof(struct ifaddrmsg),
01250         .co_msgtypes            = {
01251                                         { RTM_NEWADDR, "new" },
01252                                         { RTM_DELADDR, "delete" },
01253                                         { RTM_GETADDR, "get" },
01254                                         { -1, NULL },
01255                                   },
01256         .co_protocol            = NETLINK_ROUTE,
01257         .co_request_update      = addr_request_update,
01258         .co_msg_parser          = addr_msg_parser,
01259         .co_free_data           = addr_free_data,
01260         .co_dump[NL_DUMP_BRIEF] = addr_dump_brief,
01261         .co_dump[NL_DUMP_FULL]  = addr_dump_full,
01262         .co_dump[NL_DUMP_STATS] = addr_dump_stats,
01263         .co_dump[NL_DUMP_XML]   = addr_dump_xml,
01264         .co_dump[NL_DUMP_ENV]   = addr_dump_env,
01265         .co_filter              = addr_filter,
01266 };
01267 
01268 static void __init addr_init(void)
01269 {
01270         nl_cache_mngt_register(&rtnl_addr_ops);
01271 }
01272 
01273 static void __exit neigh_exit(void)
01274 {
01275         nl_cache_mngt_unregister(&rtnl_addr_ops);
01276 }
01277 
01278 /** @} */

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