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