libnl
3.2.3
|
00001 /* 00002 * lib/route/addr.c Addresses 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch> 00010 * Copyright (c) 2003-2006 Baruch Even <baruch@ev-en.org>, 00011 * Mediatrix Telecom, inc. <ericb@mediatrix.com> 00012 */ 00013 00014 /** 00015 * @ingroup rtnl 00016 * @defgroup rtaddr Addresses 00017 * @brief 00018 * 00019 * @note The maximum size of an address label is IFNAMSIZ. 00020 * 00021 * @note The address may not contain a prefix length if the peer address 00022 * has been specified already. 00023 * 00024 * @par 1) Address Addition 00025 * @code 00026 * // Allocate an empty address object to be filled out with the attributes 00027 * // of the new address. 00028 * struct rtnl_addr *addr = rtnl_addr_alloc(); 00029 * 00030 * // Fill out the mandatory attributes of the new address. Setting the 00031 * // local address will automatically set the address family and the 00032 * // prefix length to the correct values. 00033 * rtnl_addr_set_ifindex(addr, ifindex); 00034 * rtnl_addr_set_local(addr, local_addr); 00035 * 00036 * // The label of the address can be specified, currently only supported 00037 * // by IPv4 and DECnet. 00038 * rtnl_addr_set_label(addr, "mylabel"); 00039 * 00040 * // The peer address can be specified if necessary, in either case a peer 00041 * // address will be sent to the kernel in order to fullfil the interface 00042 * // requirements. If none is set, it will equal the local address. 00043 * // Note: Real peer addresses are only supported by IPv4 for now. 00044 * rtnl_addr_set_peer(addr, peer_addr); 00045 * 00046 * // In case you want to have the address have a scope other than global 00047 * // it may be overwritten using rtnl_addr_set_scope(). The scope currently 00048 * // cannot be set for IPv6 addresses. 00049 * rtnl_addr_set_scope(addr, rtnl_str2scope("site")); 00050 * 00051 * // Broadcast address may be specified using the relevant 00052 * // functions, the address family will be verified if one of the other 00053 * // addresses has been set already. Currently only works for IPv4. 00054 * rtnl_addr_set_broadcast(addr, broadcast_addr); 00055 * 00056 * // Build the netlink message and send it to the kernel, the operation will 00057 * // block until the operation has been completed. Alternatively the required 00058 * // netlink message can be built using rtnl_addr_build_add_request() to be 00059 * // sent out using nl_send_auto_complete(). 00060 * rtnl_addr_add(sk, addr, 0); 00061 * 00062 * // Free the memory 00063 * rtnl_addr_put(addr); 00064 * @endcode 00065 * 00066 * @par 2) Address Deletion 00067 * @code 00068 * // Allocate an empty address object to be filled out with the attributes 00069 * // matching the address to be deleted. Alternatively a fully equipped 00070 * // address object out of a cache can be used instead. 00071 * struct rtnl_addr *addr = rtnl_addr_alloc(); 00072 * 00073 * // The only mandatory parameter besides the address family is the interface 00074 * // index the address is on, i.e. leaving out all other parameters will 00075 * // result in all addresses of the specified address family interface tuple 00076 * // to be deleted. 00077 * rtnl_addr_set_ifindex(addr, ifindex); 00078 * 00079 * // Specyfing the address family manually is only required if neither the 00080 * // local nor peer address have been specified. 00081 * rtnl_addr_set_family(addr, AF_INET); 00082 * 00083 * // Specyfing the local address is optional but the best choice to delete 00084 * // specific addresses. 00085 * rtnl_addr_set_local(addr, local_addr); 00086 * 00087 * // The label of the address can be specified, currently only supported 00088 * // by IPv4 and DECnet. 00089 * rtnl_addr_set_label(addr, "mylabel"); 00090 * 00091 * // The peer address can be specified if necessary, in either case a peer 00092 * // address will be sent to the kernel in order to fullfil the interface 00093 * // requirements. If none is set, it will equal the local address. 00094 * // Note: Real peer addresses are only supported by IPv4 for now. 00095 * rtnl_addr_set_peer(addr, peer_addr); 00096 * 00097 * // Build the netlink message and send it to the kernel, the operation will 00098 * // block until the operation has been completed. Alternatively the required 00099 * // netlink message can be built using rtnl_addr_build_delete_request() 00100 * // to be sent out using nl_send_auto_complete(). 00101 * rtnl_addr_delete(sk, addr, 0); 00102 * 00103 * // Free the memory 00104 * rtnl_addr_put(addr); 00105 * @endcode 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 /** @cond SKIP */ 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 /** @endcond */ 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 /* IPv6 sends the local address as IFA_ADDRESS with 00256 * no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS 00257 * with IFA_ADDRESS being the peer address if they differ */ 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 /* rtnl_addr_set_link incs refcnt */ 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 * @name Allocation/Freeing 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 * @name Cache Management 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 * Search address in cache 00501 * @arg cache Address cache 00502 * @arg ifindex Interface index of address 00503 * @arg addr Local address part 00504 * 00505 * Searches address cache previously allocated with rtnl_addr_alloc_cache() 00506 * for an address with a matching local address. 00507 * 00508 * The reference counter is incremented before returning the address, therefore 00509 * the reference must be given back with rtnl_addr_put() after usage. 00510 * 00511 * @return Address object or NULL if no match was found. 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 /* compatibility hack */ 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 * @name Addition 00600 * @{ 00601 */ 00602 00603 /** 00604 * Build netlink request message to request addition of new address 00605 * @arg addr Address object representing the new address. 00606 * @arg flags Additional netlink message flags. 00607 * @arg result Pointer to store resulting message. 00608 * 00609 * Builds a new netlink message requesting the addition of a new 00610 * address. The netlink message header isn't fully equipped with 00611 * all relevant fields and must thus be sent out via nl_send_auto_complete() 00612 * or supplemented as needed. 00613 * 00614 * Minimal required attributes: 00615 * - interface index (rtnl_addr_set_ifindex()) 00616 * - local address (rtnl_addr_set_local()) 00617 * 00618 * The scope will default to universe except for loopback addresses in 00619 * which case a host scope is used if not specified otherwise. 00620 * 00621 * @note Free the memory after usage using nlmsg_free(). 00622 * 00623 * @return 0 on success or a negative error code. 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 * Request addition of new address 00639 * @arg sk Netlink socket. 00640 * @arg addr Address object representing the new address. 00641 * @arg flags Additional netlink message flags. 00642 * 00643 * Builds a netlink message by calling rtnl_addr_build_add_request(), 00644 * sends the request to the kernel and waits for the next ACK to be 00645 * received and thus blocks until the request has been fullfilled. 00646 * 00647 * @see rtnl_addr_build_add_request() 00648 * 00649 * @return 0 on sucess or a negative error if an error occured. 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 * @name Deletion 00671 * @{ 00672 */ 00673 00674 /** 00675 * Build a netlink request message to request deletion of an address 00676 * @arg addr Address object to be deleteted. 00677 * @arg flags Additional netlink message flags. 00678 * @arg result Pointer to store resulting message. 00679 * 00680 * Builds a new netlink message requesting a deletion of an address. 00681 * The netlink message header isn't fully equipped with all relevant 00682 * fields and must thus be sent out via nl_send_auto_complete() 00683 * or supplemented as needed. 00684 * 00685 * Minimal required attributes: 00686 * - interface index (rtnl_addr_set_ifindex()) 00687 * - address family (rtnl_addr_set_family()) 00688 * 00689 * Optional attributes: 00690 * - local address (rtnl_addr_set_local()) 00691 * - label (rtnl_addr_set_label(), IPv4/DECnet only) 00692 * - peer address (rtnl_addr_set_peer(), IPv4 only) 00693 * 00694 * @note Free the memory after usage using nlmsg_free(). 00695 * 00696 * @return 0 on success or a negative error code. 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 * Request deletion of an address 00711 * @arg sk Netlink socket. 00712 * @arg addr Address object to be deleted. 00713 * @arg flags Additional netlink message flags. 00714 * 00715 * Builds a netlink message by calling rtnl_addr_build_delete_request(), 00716 * sends the request to the kernel and waits for the next ACK to be 00717 * received and thus blocks until the request has been fullfilled. 00718 * 00719 * @see rtnl_addr_build_delete_request(); 00720 * 00721 * @return 0 on sucess or a negative error if an error occured. 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 * @name Attributes 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 * @name Flags Translations 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 /** @} */