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