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