00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 #include <netlink-local.h>
00111 #include <netlink/netlink.h>
00112 #include <netlink/route/rtnl.h>
00113 #include <netlink/route/addr.h>
00114 #include <netlink/route/route.h>
00115 #include <netlink/route/link.h>
00116 #include <netlink/utils.h>
00117
00118
00119 #define ADDR_ATTR_FAMILY 0x0001
00120 #define ADDR_ATTR_PREFIXLEN 0x0002
00121 #define ADDR_ATTR_FLAGS 0x0004
00122 #define ADDR_ATTR_SCOPE 0x0008
00123 #define ADDR_ATTR_IFINDEX 0x0010
00124 #define ADDR_ATTR_LABEL 0x0020
00125 #define ADDR_ATTR_CACHEINFO 0x0040
00126 #define ADDR_ATTR_PEER 0x0080
00127 #define ADDR_ATTR_LOCAL 0x0100
00128 #define ADDR_ATTR_BROADCAST 0x0200
00129 #define ADDR_ATTR_ANYCAST 0x0400
00130 #define ADDR_ATTR_MULTICAST 0x0800
00131
00132 static struct nl_cache_ops rtnl_addr_ops;
00133 static struct nl_object_ops addr_obj_ops;
00134
00135
00136 static void addr_free_data(struct nl_object *obj)
00137 {
00138 struct rtnl_addr *addr = nl_object_priv(obj);
00139
00140 if (!addr)
00141 return;
00142
00143 nl_addr_put(addr->a_peer);
00144 nl_addr_put(addr->a_local);
00145 nl_addr_put(addr->a_bcast);
00146 nl_addr_put(addr->a_anycast);
00147 nl_addr_put(addr->a_multicast);
00148 }
00149
00150 static int addr_clone(struct nl_object *_dst, struct nl_object *_src)
00151 {
00152 struct rtnl_addr *dst = nl_object_priv(_dst);
00153 struct rtnl_addr *src = nl_object_priv(_src);
00154
00155 if (src->a_peer)
00156 if (!(dst->a_peer = nl_addr_clone(src->a_peer)))
00157 goto errout;
00158
00159 if (src->a_local)
00160 if (!(dst->a_local = nl_addr_clone(src->a_local)))
00161 goto errout;
00162
00163 if (src->a_bcast)
00164 if (!(dst->a_bcast = nl_addr_clone(src->a_bcast)))
00165 goto errout;
00166
00167 if (src->a_anycast)
00168 if (!(dst->a_anycast = nl_addr_clone(src->a_anycast)))
00169 goto errout;
00170
00171 if (src->a_multicast)
00172 if (!(dst->a_multicast = nl_addr_clone(src->a_multicast)))
00173 goto errout;
00174
00175 return 0;
00176 errout:
00177 return nl_get_errno();
00178 }
00179
00180 static struct nla_policy addr_policy[IFA_MAX+1] = {
00181 [IFA_LABEL] = { .type = NLA_STRING,
00182 .maxlen = IFNAMSIZ },
00183 [IFA_CACHEINFO] = { .minlen = sizeof(struct ifa_cacheinfo) },
00184 };
00185
00186 static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
00187 struct nlmsghdr *nlh, struct nl_parser_param *pp)
00188 {
00189 struct rtnl_addr *addr;
00190 struct ifaddrmsg *ifa;
00191 struct nlattr *tb[IFA_MAX+1];
00192 int err = -ENOMEM, peer_prefix = 0;
00193
00194 addr = rtnl_addr_alloc();
00195 if (!addr) {
00196 err = nl_errno(ENOMEM);
00197 goto errout;
00198 }
00199 addr->ce_msgtype = nlh->nlmsg_type;
00200
00201 err = nlmsg_parse(nlh, sizeof(*ifa), tb, IFA_MAX, addr_policy);
00202 if (err < 0)
00203 goto errout_free;
00204
00205 ifa = nlmsg_data(nlh);
00206 addr->a_family = ifa->ifa_family;
00207 addr->a_prefixlen = ifa->ifa_prefixlen;
00208 addr->a_flags = ifa->ifa_flags;
00209 addr->a_scope = ifa->ifa_scope;
00210 addr->a_ifindex = ifa->ifa_index;
00211
00212 addr->ce_mask = (ADDR_ATTR_FAMILY | ADDR_ATTR_PREFIXLEN |
00213 ADDR_ATTR_FLAGS | ADDR_ATTR_SCOPE | ADDR_ATTR_IFINDEX);
00214
00215 if (tb[IFA_LABEL]) {
00216 nla_strlcpy(addr->a_label, tb[IFA_LABEL], IFNAMSIZ);
00217 addr->ce_mask |= ADDR_ATTR_LABEL;
00218 }
00219
00220 if (tb[IFA_CACHEINFO]) {
00221 struct ifa_cacheinfo *ca;
00222
00223 ca = nla_data(tb[IFA_CACHEINFO]);
00224 addr->a_cacheinfo.aci_prefered = ca->ifa_prefered;
00225 addr->a_cacheinfo.aci_valid = ca->ifa_valid;
00226 addr->a_cacheinfo.aci_cstamp = ca->cstamp;
00227 addr->a_cacheinfo.aci_tstamp = ca->tstamp;
00228 addr->ce_mask |= ADDR_ATTR_CACHEINFO;
00229 }
00230
00231 if (tb[IFA_LOCAL]) {
00232 addr->a_local = nla_get_addr(tb[IFA_LOCAL], addr->a_family);
00233 if (!addr->a_local)
00234 goto errout_free;
00235 addr->ce_mask |= ADDR_ATTR_LOCAL;
00236 }
00237
00238 if (tb[IFA_ADDRESS]) {
00239 struct nl_addr *a;
00240
00241 a = nla_get_addr(tb[IFA_ADDRESS], addr->a_family);
00242 if (!a)
00243 goto errout_free;
00244
00245
00246
00247
00248 if (!tb[IFA_LOCAL] || !nl_addr_cmp(a, addr->a_local)) {
00249 nl_addr_put(addr->a_local);
00250 addr->a_local = a;
00251 addr->ce_mask |= ADDR_ATTR_LOCAL;
00252 } else {
00253 addr->a_peer = a;
00254 addr->ce_mask |= ADDR_ATTR_PEER;
00255 peer_prefix = 1;
00256 }
00257 }
00258
00259 nl_addr_set_prefixlen(peer_prefix ? addr->a_peer : addr->a_local,
00260 addr->a_prefixlen);
00261
00262 if (tb[IFA_BROADCAST]) {
00263 addr->a_bcast = nla_get_addr(tb[IFA_BROADCAST], addr->a_family);
00264 if (!addr->a_bcast)
00265 goto errout_free;
00266
00267 addr->ce_mask |= ADDR_ATTR_BROADCAST;
00268 }
00269
00270 if (tb[IFA_ANYCAST]) {
00271 addr->a_anycast = nla_get_addr(tb[IFA_ANYCAST], addr->a_family);
00272 if (!addr->a_anycast)
00273 goto errout_free;
00274
00275 addr->ce_mask |= ADDR_ATTR_ANYCAST;
00276 }
00277
00278 if (tb[IFA_MULTICAST]) {
00279 addr->a_multicast = nla_get_addr(tb[IFA_MULTICAST],
00280 addr->a_family);
00281 if (!addr->a_multicast)
00282 goto errout_free;
00283
00284 addr->ce_mask |= ADDR_ATTR_MULTICAST;
00285 }
00286
00287 err = pp->pp_cb((struct nl_object *) addr, pp);
00288 if (err < 0)
00289 goto errout_free;
00290
00291 err = P_ACCEPT;
00292
00293 errout_free:
00294 rtnl_addr_put(addr);
00295 errout:
00296 return err;
00297 }
00298
00299 static int addr_request_update(struct nl_cache *cache, struct nl_handle *handle)
00300 {
00301 return nl_rtgen_request(handle, RTM_GETADDR, AF_UNSPEC, NLM_F_DUMP);
00302 }
00303
00304 static int addr_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
00305 {
00306 struct rtnl_addr *addr = (struct rtnl_addr *) obj;
00307 struct nl_cache *link_cache;
00308 char buf[128];
00309
00310 link_cache = nl_cache_mngt_require("route/link");
00311
00312 if (addr->ce_mask & ADDR_ATTR_LOCAL)
00313 dp_dump(p, "%s",
00314 nl_addr2str(addr->a_local, buf, sizeof(buf)));
00315 else
00316 dp_dump(p, "none");
00317
00318 if (addr->ce_mask & ADDR_ATTR_PEER)
00319 dp_dump(p, " peer %s",
00320 nl_addr2str(addr->a_peer, buf, sizeof(buf)));
00321
00322 dp_dump(p, " %s ", nl_af2str(addr->a_family, buf, sizeof(buf)));
00323
00324 if (link_cache)
00325 dp_dump(p, "dev %s ",
00326 rtnl_link_i2name(link_cache, addr->a_ifindex,
00327 buf, sizeof(buf)));
00328 else
00329 dp_dump(p, "dev %d ", addr->a_ifindex);
00330
00331 dp_dump(p, "scope %s",
00332 rtnl_scope2str(addr->a_scope, buf, sizeof(buf)));
00333
00334 rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf));
00335 if (buf[0])
00336 dp_dump(p, " <%s>", buf);
00337
00338 dp_dump(p, "\n");
00339
00340 return 1;
00341 }
00342
00343 static int addr_dump_full(struct nl_object *obj, struct nl_dump_params *p)
00344 {
00345 struct rtnl_addr *addr = (struct rtnl_addr *) obj;
00346 int line = addr_dump_brief(obj, p);
00347 char buf[128];
00348
00349 if (addr->ce_mask & (ADDR_ATTR_LABEL | ADDR_ATTR_BROADCAST |
00350 ADDR_ATTR_ANYCAST | ADDR_ATTR_MULTICAST)) {
00351 dp_dump_line(p, line++, " ");
00352
00353 if (addr->ce_mask & ADDR_ATTR_LABEL)
00354 dp_dump(p, " label %s", addr->a_label);
00355
00356 if (addr->ce_mask & ADDR_ATTR_BROADCAST)
00357 dp_dump(p, " broadcast %s",
00358 nl_addr2str(addr->a_bcast, buf, sizeof(buf)));
00359
00360 if (addr->ce_mask & ADDR_ATTR_ANYCAST)
00361 dp_dump(p, " anycast %s",
00362 nl_addr2str(addr->a_anycast, buf,
00363 sizeof(buf)));
00364
00365 if (addr->ce_mask & ADDR_ATTR_MULTICAST)
00366 dp_dump(p, " multicast %s",
00367 nl_addr2str(addr->a_multicast, buf,
00368 sizeof(buf)));
00369
00370 dp_dump(p, "\n");
00371 }
00372
00373 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) {
00374 struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo;
00375
00376 dp_dump_line(p, line++, " valid-lifetime %s",
00377 ci->aci_valid == 0xFFFFFFFFU ? "forever" :
00378 nl_msec2str(ci->aci_valid * 1000,
00379 buf, sizeof(buf)));
00380
00381 dp_dump(p, " preferred-lifetime %s\n",
00382 ci->aci_prefered == 0xFFFFFFFFU ? "forever" :
00383 nl_msec2str(ci->aci_prefered * 1000,
00384 buf, sizeof(buf)));
00385
00386 dp_dump_line(p, line++, " created boot-time+%s ",
00387 nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10,
00388 buf, sizeof(buf)));
00389
00390 dp_dump(p, "last-updated boot-time+%s\n",
00391 nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10,
00392 buf, sizeof(buf)));
00393 }
00394
00395 return line;
00396 }
00397
00398 static int addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
00399 {
00400 return addr_dump_full(obj, p);
00401 }
00402
00403 static int addr_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
00404 {
00405 struct rtnl_addr *addr = (struct rtnl_addr *) obj;
00406 struct nl_cache *link_cache;
00407 char buf[128];
00408 int line = 0;
00409
00410 dp_dump_line(p, line++, "<address>\n");
00411 dp_dump_line(p, line++, " <family>%s</family>\n",
00412 nl_af2str(addr->a_family, buf, sizeof(buf)));
00413
00414 if (addr->ce_mask & ADDR_ATTR_LOCAL)
00415 dp_dump_line(p, line++, " <local>%s</local>\n",
00416 nl_addr2str(addr->a_local, buf, sizeof(buf)));
00417
00418 if (addr->ce_mask & ADDR_ATTR_PEER)
00419 dp_dump_line(p, line++, " <peer>%s</peer>\n",
00420 nl_addr2str(addr->a_peer, buf, sizeof(buf)));
00421
00422 if (addr->ce_mask & ADDR_ATTR_BROADCAST)
00423 dp_dump_line(p, line++, " <broadcast>%s</broadcast>\n",
00424 nl_addr2str(addr->a_bcast, buf, sizeof(buf)));
00425
00426 if (addr->ce_mask & ADDR_ATTR_ANYCAST)
00427 dp_dump_line(p, line++, " <anycast>%s</anycast>\n",
00428 nl_addr2str(addr->a_anycast, buf, sizeof(buf)));
00429
00430 if (addr->ce_mask & ADDR_ATTR_MULTICAST)
00431 dp_dump_line(p, line++, " <multicast>%s</multicast>\n",
00432 nl_addr2str(addr->a_multicast, buf,
00433 sizeof(buf)));
00434
00435 if (addr->ce_mask & ADDR_ATTR_PREFIXLEN)
00436 dp_dump_line(p, line++, " <prefixlen>%u</prefixlen>\n",
00437 addr->a_prefixlen);
00438 link_cache = nl_cache_mngt_require("route/link");
00439
00440 if (link_cache)
00441 dp_dump_line(p, line++, " <device>%s</device>\n",
00442 rtnl_link_i2name(link_cache, addr->a_ifindex,
00443 buf, sizeof(buf)));
00444 else
00445 dp_dump_line(p, line++, " <device>%u</device>\n",
00446 addr->a_ifindex);
00447
00448 if (addr->ce_mask & ADDR_ATTR_SCOPE)
00449 dp_dump_line(p, line++, " <scope>%s</scope>\n",
00450 rtnl_scope2str(addr->a_scope, buf, sizeof(buf)));
00451
00452 if (addr->ce_mask & ADDR_ATTR_LABEL)
00453 dp_dump_line(p, line++, " <label>%s</label>\n", addr->a_label);
00454
00455 rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf));
00456 if (buf[0])
00457 dp_dump_line(p, line++, " <flags>%s</flags>\n", buf);
00458
00459 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) {
00460 struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo;
00461
00462 dp_dump_line(p, line++, " <cacheinfo>\n");
00463
00464 dp_dump_line(p, line++, " <valid>%s</valid>\n",
00465 ci->aci_valid == 0xFFFFFFFFU ? "forever" :
00466 nl_msec2str(ci->aci_valid * 1000,
00467 buf, sizeof(buf)));
00468
00469 dp_dump_line(p, line++, " <prefered>%s</prefered>\n",
00470 ci->aci_prefered == 0xFFFFFFFFU ? "forever" :
00471 nl_msec2str(ci->aci_prefered * 1000,
00472 buf, sizeof(buf)));
00473
00474 dp_dump_line(p, line++, " <created>%s</created>\n",
00475 nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10,
00476 buf, sizeof(buf)));
00477
00478 dp_dump_line(p, line++, " <last-update>%s</last-update>\n",
00479 nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10,
00480 buf, sizeof(buf)));
00481
00482 dp_dump_line(p, line++, " </cacheinfo>\n");
00483 }
00484
00485 dp_dump_line(p, line++, "</address>\n");
00486
00487 return line;
00488 }
00489
00490 static int addr_dump_env(struct nl_object *obj, struct nl_dump_params *p)
00491 {
00492 struct rtnl_addr *addr = (struct rtnl_addr *) obj;
00493 struct nl_cache *link_cache;
00494 char buf[128];
00495 int line = 0;
00496
00497 dp_dump_line(p, line++, "ADDR_FAMILY=%s\n",
00498 nl_af2str(addr->a_family, buf, sizeof(buf)));
00499
00500 if (addr->ce_mask & ADDR_ATTR_LOCAL)
00501 dp_dump_line(p, line++, "ADDR_LOCAL=%s\n",
00502 nl_addr2str(addr->a_local, buf, sizeof(buf)));
00503
00504 if (addr->ce_mask & ADDR_ATTR_PEER)
00505 dp_dump_line(p, line++, "ADDR_PEER=%s\n",
00506 nl_addr2str(addr->a_peer, buf, sizeof(buf)));
00507
00508 if (addr->ce_mask & ADDR_ATTR_BROADCAST)
00509 dp_dump_line(p, line++, "ADDR_BROADCAST=%s\n",
00510 nl_addr2str(addr->a_bcast, buf, sizeof(buf)));
00511
00512 if (addr->ce_mask & ADDR_ATTR_ANYCAST)
00513 dp_dump_line(p, line++, "ADDR_ANYCAST=%s\n",
00514 nl_addr2str(addr->a_anycast, buf, sizeof(buf)));
00515
00516 if (addr->ce_mask & ADDR_ATTR_MULTICAST)
00517 dp_dump_line(p, line++, "ADDR_MULTICAST=%s\n",
00518 nl_addr2str(addr->a_multicast, buf,
00519 sizeof(buf)));
00520
00521 if (addr->ce_mask & ADDR_ATTR_PREFIXLEN)
00522 dp_dump_line(p, line++, "ADDR_PREFIXLEN=%u\n",
00523 addr->a_prefixlen);
00524 link_cache = nl_cache_mngt_require("route/link");
00525
00526 dp_dump_line(p, line++, "ADDR_IFINDEX=%u\n", addr->a_ifindex);
00527 if (link_cache)
00528 dp_dump_line(p, line++, "ADDR_IFNAME=%s\n",
00529 rtnl_link_i2name(link_cache, addr->a_ifindex,
00530 buf, sizeof(buf)));
00531
00532 if (addr->ce_mask & ADDR_ATTR_SCOPE)
00533 dp_dump_line(p, line++, "ADDR_SCOPE=%s\n",
00534 rtnl_scope2str(addr->a_scope, buf, sizeof(buf)));
00535
00536 if (addr->ce_mask & ADDR_ATTR_LABEL)
00537 dp_dump_line(p, line++, "ADDR_LABEL=%s\n", addr->a_label);
00538
00539 rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf));
00540 if (buf[0])
00541 dp_dump_line(p, line++, "ADDR_FLAGS=%s\n", buf);
00542
00543 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) {
00544 struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo;
00545
00546 dp_dump_line(p, line++, "ADDR_CACHEINFO_VALID=%s\n",
00547 ci->aci_valid == 0xFFFFFFFFU ? "forever" :
00548 nl_msec2str(ci->aci_valid * 1000,
00549 buf, sizeof(buf)));
00550
00551 dp_dump_line(p, line++, "ADDR_CACHEINFO_PREFERED=%s\n",
00552 ci->aci_prefered == 0xFFFFFFFFU ? "forever" :
00553 nl_msec2str(ci->aci_prefered * 1000,
00554 buf, sizeof(buf)));
00555
00556 dp_dump_line(p, line++, "ADDR_CACHEINFO_CREATED=%s\n",
00557 nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10,
00558 buf, sizeof(buf)));
00559
00560 dp_dump_line(p, line++, "ADDR_CACHEINFO_LASTUPDATE=%s\n",
00561 nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10,
00562 buf, sizeof(buf)));
00563 }
00564
00565 return line;
00566 }
00567
00568 static int addr_compare(struct nl_object *_a, struct nl_object *_b,
00569 uint32_t attrs, int flags)
00570 {
00571 struct rtnl_addr *a = (struct rtnl_addr *) _a;
00572 struct rtnl_addr *b = (struct rtnl_addr *) _b;
00573 int diff = 0;
00574
00575 #define ADDR_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ADDR_ATTR_##ATTR, a, b, EXPR)
00576
00577 diff |= ADDR_DIFF(IFINDEX, a->a_ifindex != b->a_ifindex);
00578 diff |= ADDR_DIFF(FAMILY, a->a_family != b->a_family);
00579 diff |= ADDR_DIFF(SCOPE, a->a_scope != b->a_scope);
00580 diff |= ADDR_DIFF(LABEL, strcmp(a->a_label, b->a_label));
00581 diff |= ADDR_DIFF(PEER, nl_addr_cmp(a->a_peer, b->a_peer));
00582 diff |= ADDR_DIFF(LOCAL, nl_addr_cmp(a->a_local, b->a_local));
00583 diff |= ADDR_DIFF(ANYCAST, nl_addr_cmp(a->a_anycast,b->a_anycast));
00584 diff |= ADDR_DIFF(MULTICAST, nl_addr_cmp(a->a_multicast,
00585 b->a_multicast));
00586 diff |= ADDR_DIFF(BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast));
00587
00588 if (flags & LOOSE_FLAG_COMPARISON)
00589 diff |= ADDR_DIFF(FLAGS,
00590 (a->a_flags ^ b->a_flags) & b->a_flag_mask);
00591 else
00592 diff |= ADDR_DIFF(FLAGS, a->a_flags != b->a_flags);
00593
00594 #undef ADDR_DIFF
00595
00596 return diff;
00597 }
00598
00599 static struct trans_tbl addr_attrs[] = {
00600 __ADD(ADDR_ATTR_FAMILY, family)
00601 __ADD(ADDR_ATTR_PREFIXLEN, prefixlen)
00602 __ADD(ADDR_ATTR_FLAGS, flags)
00603 __ADD(ADDR_ATTR_SCOPE, scope)
00604 __ADD(ADDR_ATTR_IFINDEX, ifindex)
00605 __ADD(ADDR_ATTR_LABEL, label)
00606 __ADD(ADDR_ATTR_CACHEINFO, cacheinfo)
00607 __ADD(ADDR_ATTR_PEER, peer)
00608 __ADD(ADDR_ATTR_LOCAL, local)
00609 __ADD(ADDR_ATTR_BROADCAST, broadcast)
00610 __ADD(ADDR_ATTR_ANYCAST, anycast)
00611 __ADD(ADDR_ATTR_MULTICAST, multicast)
00612 };
00613
00614 static char *addr_attrs2str(int attrs, char *buf, size_t len)
00615 {
00616 return __flags2str(attrs, buf, len, addr_attrs,
00617 ARRAY_SIZE(addr_attrs));
00618 }
00619
00620
00621
00622
00623
00624
00625 struct rtnl_addr *rtnl_addr_alloc(void)
00626 {
00627 return (struct rtnl_addr *) nl_object_alloc(&addr_obj_ops);
00628 }
00629
00630 void rtnl_addr_put(struct rtnl_addr *addr)
00631 {
00632 nl_object_put((struct nl_object *) addr);
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642 struct nl_cache *rtnl_addr_alloc_cache(struct nl_handle *handle)
00643 {
00644 struct nl_cache *cache;
00645
00646 cache = nl_cache_alloc(&rtnl_addr_ops);
00647 if (!cache)
00648 return NULL;
00649
00650 if (handle && nl_cache_refill(handle, cache) < 0) {
00651 nl_cache_free(cache);
00652 return NULL;
00653 }
00654
00655 return cache;
00656 }
00657
00658
00659
00660 static struct nl_msg *build_addr_msg(struct rtnl_addr *tmpl, int cmd, int flags)
00661 {
00662 struct nl_msg *msg;
00663 struct ifaddrmsg am = {
00664 .ifa_family = tmpl->a_family,
00665 .ifa_index = tmpl->a_ifindex,
00666 .ifa_prefixlen = tmpl->a_prefixlen,
00667 };
00668
00669 if (tmpl->ce_mask & ADDR_ATTR_SCOPE)
00670 am.ifa_scope = tmpl->a_scope;
00671 else {
00672
00673 if (tmpl->a_family == AF_INET &&
00674 tmpl->ce_mask & ADDR_ATTR_LOCAL &&
00675 *((char *) nl_addr_get_binary_addr(tmpl->a_local)) == 127)
00676 am.ifa_scope = RT_SCOPE_HOST;
00677 else
00678 am.ifa_scope = RT_SCOPE_UNIVERSE;
00679 }
00680
00681 msg = nlmsg_alloc_simple(cmd, flags);
00682 if (!msg)
00683 goto nla_put_failure;
00684
00685 if (nlmsg_append(msg, &am, sizeof(am), NLMSG_ALIGNTO) < 0)
00686 goto nla_put_failure;
00687
00688 if (tmpl->ce_mask & ADDR_ATTR_LOCAL)
00689 NLA_PUT_ADDR(msg, IFA_LOCAL, tmpl->a_local);
00690
00691 if (tmpl->ce_mask & ADDR_ATTR_PEER)
00692 NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_peer);
00693 else
00694 NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_local);
00695
00696 if (tmpl->ce_mask & ADDR_ATTR_LABEL)
00697 NLA_PUT_STRING(msg, IFA_LABEL, tmpl->a_label);
00698
00699 if (tmpl->ce_mask & ADDR_ATTR_BROADCAST)
00700 NLA_PUT_ADDR(msg, IFA_BROADCAST, tmpl->a_bcast);
00701
00702 if (tmpl->ce_mask & ADDR_ATTR_ANYCAST)
00703 NLA_PUT_ADDR(msg, IFA_ANYCAST, tmpl->a_anycast);
00704
00705 return msg;
00706
00707 nla_put_failure:
00708 nlmsg_free(msg);
00709 return NULL;
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737 struct nl_msg *rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags)
00738 {
00739 int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY |
00740 ADDR_ATTR_PREFIXLEN | ADDR_ATTR_LOCAL;
00741
00742 if ((addr->ce_mask & required) != required) {
00743 nl_error(EINVAL, "Missing mandatory attributes, required are: "
00744 "ifindex, family, prefixlen, local address.");
00745 return NULL;
00746 }
00747
00748 return build_addr_msg(addr, RTM_NEWADDR, NLM_F_CREATE | flags);
00749 }
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765 int rtnl_addr_add(struct nl_handle *handle, struct rtnl_addr *addr, int flags)
00766 {
00767 struct nl_msg *msg;
00768 int err;
00769
00770 msg = rtnl_addr_build_add_request(addr, flags);
00771 if (!msg)
00772 return nl_get_errno();
00773
00774 err = nl_send_auto_complete(handle, msg);
00775 nlmsg_free(msg);
00776 if (err < 0)
00777 return err;
00778
00779 return nl_wait_for_ack(handle);
00780 }
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 struct nl_msg *rtnl_addr_build_delete_request(struct rtnl_addr *addr, int flags)
00812 {
00813 int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY;
00814
00815 if ((addr->ce_mask & required) != required) {
00816 nl_error(EINVAL, "Missing mandatory attributes, required are: "
00817 "ifindex, family");
00818 return NULL;
00819 }
00820
00821 return build_addr_msg(addr, RTM_DELADDR, flags);
00822 }
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838 int rtnl_addr_delete(struct nl_handle *handle, struct rtnl_addr *addr,
00839 int flags)
00840 {
00841 struct nl_msg *msg;
00842 int err;
00843
00844 msg = rtnl_addr_build_delete_request(addr, flags);
00845 if (!msg)
00846 return nl_get_errno();
00847
00848 err = nl_send_auto_complete(handle, msg);
00849 nlmsg_free(msg);
00850 if (err < 0)
00851 return err;
00852
00853 return nl_wait_for_ack(handle);
00854 }
00855
00856
00857
00858
00859
00860
00861
00862
00863 void rtnl_addr_set_label(struct rtnl_addr *addr, const char *label)
00864 {
00865 strncpy(addr->a_label, label, sizeof(addr->a_label) - 1);
00866 addr->ce_mask |= ADDR_ATTR_LABEL;
00867 }
00868
00869 char *rtnl_addr_get_label(struct rtnl_addr *addr)
00870 {
00871 if (addr->ce_mask & ADDR_ATTR_LABEL)
00872 return addr->a_label;
00873 else
00874 return NULL;
00875 }
00876
00877 void rtnl_addr_set_ifindex(struct rtnl_addr *addr, int ifindex)
00878 {
00879 addr->a_ifindex = ifindex;
00880 addr->ce_mask |= ADDR_ATTR_IFINDEX;
00881 }
00882
00883 int rtnl_addr_get_ifindex(struct rtnl_addr *addr)
00884 {
00885 if (addr->ce_mask & ADDR_ATTR_IFINDEX)
00886 return addr->a_ifindex;
00887 else
00888 return RTNL_LINK_NOT_FOUND;
00889 }
00890
00891 void rtnl_addr_set_family(struct rtnl_addr *addr, int family)
00892 {
00893 addr->a_family = family;
00894 addr->ce_mask |= ADDR_ATTR_FAMILY;
00895 }
00896
00897 int rtnl_addr_get_family(struct rtnl_addr *addr)
00898 {
00899 if (addr->ce_mask & ADDR_ATTR_FAMILY)
00900 return addr->a_family;
00901 else
00902 return AF_UNSPEC;
00903 }
00904
00905 void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefix)
00906 {
00907 addr->a_prefixlen = prefix;
00908 addr->ce_mask |= ADDR_ATTR_PREFIXLEN;
00909 }
00910
00911 int rtnl_addr_get_prefixlen(struct rtnl_addr *addr)
00912 {
00913 if (addr->ce_mask & ADDR_ATTR_PREFIXLEN)
00914 return addr->a_prefixlen;
00915 else
00916 return -1;
00917 }
00918
00919 void rtnl_addr_set_scope(struct rtnl_addr *addr, int scope)
00920 {
00921 addr->a_scope = scope;
00922 addr->ce_mask |= ADDR_ATTR_SCOPE;
00923 }
00924
00925 int rtnl_addr_get_scope(struct rtnl_addr *addr)
00926 {
00927 if (addr->ce_mask & ADDR_ATTR_SCOPE)
00928 return addr->a_scope;
00929 else
00930 return -1;
00931 }
00932
00933 void rtnl_addr_set_flags(struct rtnl_addr *addr, unsigned int flags)
00934 {
00935 addr->a_flag_mask |= flags;
00936 addr->a_flags |= flags;
00937 addr->ce_mask |= ADDR_ATTR_FLAGS;
00938 }
00939
00940 void rtnl_addr_unset_flags(struct rtnl_addr *addr, unsigned int flags)
00941 {
00942 addr->a_flag_mask |= flags;
00943 addr->a_flags &= ~flags;
00944 addr->ce_mask |= ADDR_ATTR_FLAGS;
00945 }
00946
00947 unsigned int rtnl_addr_get_flags(struct rtnl_addr *addr)
00948 {
00949 return addr->a_flags;
00950 }
00951
00952 static inline int __assign_addr(struct rtnl_addr *addr, struct nl_addr **pos,
00953 struct nl_addr *new, int flag)
00954 {
00955 if (addr->ce_mask & ADDR_ATTR_FAMILY) {
00956 if (new->a_family != addr->a_family)
00957 return nl_error(EINVAL, "Address family mismatch");
00958 } else
00959 addr->a_family = new->a_family;
00960
00961 if (*pos)
00962 nl_addr_put(*pos);
00963
00964 *pos = nl_addr_get(new);
00965 addr->ce_mask |= (flag | ADDR_ATTR_FAMILY);
00966
00967 return 0;
00968 }
00969
00970 int rtnl_addr_set_local(struct rtnl_addr *addr, struct nl_addr *local)
00971 {
00972 int err;
00973
00974 err = __assign_addr(addr, &addr->a_local, local, ADDR_ATTR_LOCAL);
00975 if (err < 0)
00976 return err;
00977
00978 if (!(addr->ce_mask & ADDR_ATTR_PEER)) {
00979 addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_local);
00980 addr->ce_mask |= ADDR_ATTR_PREFIXLEN;
00981 }
00982
00983 return 0;
00984 }
00985
00986 struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr)
00987 {
00988 if (addr->ce_mask & ADDR_ATTR_LOCAL)
00989 return addr->a_local;
00990 else
00991 return NULL;
00992 }
00993
00994 int rtnl_addr_set_peer(struct rtnl_addr *addr, struct nl_addr *peer)
00995 {
00996 return __assign_addr(addr, &addr->a_peer, peer, ADDR_ATTR_PEER);
00997
00998 addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_peer);
00999 addr->ce_mask |= ADDR_ATTR_PREFIXLEN;
01000
01001 return 0;
01002 }
01003
01004 struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr)
01005 {
01006 if (addr->ce_mask & ADDR_ATTR_PEER)
01007 return addr->a_peer;
01008 else
01009 return NULL;
01010 }
01011
01012 int rtnl_addr_set_broadcast(struct rtnl_addr *addr, struct nl_addr *bcast)
01013 {
01014 return __assign_addr(addr, &addr->a_bcast, bcast, ADDR_ATTR_BROADCAST);
01015 }
01016
01017 struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *addr)
01018 {
01019 if (addr->ce_mask & ADDR_ATTR_BROADCAST)
01020 return addr->a_bcast;
01021 else
01022 return NULL;
01023 }
01024
01025 int rtnl_addr_set_anycast(struct rtnl_addr *addr, struct nl_addr *anycast)
01026 {
01027 return __assign_addr(addr, &addr->a_anycast, anycast,
01028 ADDR_ATTR_ANYCAST);
01029 }
01030
01031 struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *addr)
01032 {
01033 if (addr->ce_mask & ADDR_ATTR_ANYCAST)
01034 return addr->a_anycast;
01035 else
01036 return NULL;
01037 }
01038
01039 int rtnl_addr_set_multicast(struct rtnl_addr *addr, struct nl_addr *multicast)
01040 {
01041 return __assign_addr(addr, &addr->a_multicast, multicast,
01042 ADDR_ATTR_MULTICAST);
01043 }
01044
01045 struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr)
01046 {
01047 if (addr->ce_mask & ADDR_ATTR_MULTICAST)
01048 return addr->a_multicast;
01049 else
01050 return NULL;
01051 }
01052
01053
01054
01055
01056
01057
01058
01059
01060 static struct trans_tbl addr_flags[] = {
01061 __ADD(IFA_F_SECONDARY, secondary)
01062 __ADD(IFA_F_DEPRECATED, deprecated)
01063 __ADD(IFA_F_TENTATIVE, tentative)
01064 __ADD(IFA_F_PERMANENT, permanent)
01065 };
01066
01067 char *rtnl_addr_flags2str(int flags, char *buf, size_t size)
01068 {
01069 return __flags2str(flags, buf, size, addr_flags,
01070 ARRAY_SIZE(addr_flags));
01071 }
01072
01073 int rtnl_addr_str2flags(const char *name)
01074 {
01075 return __str2flags(name, addr_flags, ARRAY_SIZE(addr_flags));
01076 }
01077
01078
01079
01080 static struct nl_object_ops addr_obj_ops = {
01081 .oo_name = "route/addr",
01082 .oo_size = sizeof(struct rtnl_addr),
01083 .oo_free_data = addr_free_data,
01084 .oo_clone = addr_clone,
01085 .oo_dump[NL_DUMP_BRIEF] = addr_dump_brief,
01086 .oo_dump[NL_DUMP_FULL] = addr_dump_full,
01087 .oo_dump[NL_DUMP_STATS] = addr_dump_stats,
01088 .oo_dump[NL_DUMP_XML] = addr_dump_xml,
01089 .oo_dump[NL_DUMP_ENV] = addr_dump_env,
01090 .oo_compare = addr_compare,
01091 .oo_attrs2str = addr_attrs2str,
01092 .oo_id_attrs = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX |
01093 ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN |
01094 ADDR_ATTR_PEER),
01095 };
01096
01097 static struct nl_af_group addr_groups[] = {
01098 { AF_INET, RTNLGRP_IPV4_IFADDR },
01099 { AF_INET6, RTNLGRP_IPV6_IFADDR },
01100 { END_OF_GROUP_LIST },
01101 };
01102
01103 static struct nl_cache_ops rtnl_addr_ops = {
01104 .co_name = "route/addr",
01105 .co_hdrsize = sizeof(struct ifaddrmsg),
01106 .co_msgtypes = {
01107 { RTM_NEWADDR, NL_ACT_NEW, "new" },
01108 { RTM_DELADDR, NL_ACT_DEL, "del" },
01109 { RTM_GETADDR, NL_ACT_GET, "get" },
01110 END_OF_MSGTYPES_LIST,
01111 },
01112 .co_protocol = NETLINK_ROUTE,
01113 .co_groups = addr_groups,
01114 .co_request_update = addr_request_update,
01115 .co_msg_parser = addr_msg_parser,
01116 .co_obj_ops = &addr_obj_ops,
01117 };
01118
01119 static void __init addr_init(void)
01120 {
01121 nl_cache_mngt_register(&rtnl_addr_ops);
01122 }
01123
01124 static void __exit addr_exit(void)
01125 {
01126 nl_cache_mngt_unregister(&rtnl_addr_ops);
01127 }
01128
01129