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