libnl 2.0
|
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-2008 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 } 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 /* IPv6 sends the local address as IFA_ADDRESS with 00249 * no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS 00250 * with IFA_ADDRESS being the peer address if they differ */ 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 void addr_dump_env(struct nl_object *obj, struct nl_dump_params *p) 00404 { 00405 struct rtnl_addr *addr = (struct rtnl_addr *) obj; 00406 struct nl_cache *link_cache; 00407 char buf[128]; 00408 00409 nl_dump_line(p, "ADDR_FAMILY=%s\n", 00410 nl_af2str(addr->a_family, buf, sizeof(buf))); 00411 00412 if (addr->ce_mask & ADDR_ATTR_LOCAL) 00413 nl_dump_line(p, "ADDR_LOCAL=%s\n", 00414 nl_addr2str(addr->a_local, buf, sizeof(buf))); 00415 00416 if (addr->ce_mask & ADDR_ATTR_PEER) 00417 nl_dump_line(p, "ADDR_PEER=%s\n", 00418 nl_addr2str(addr->a_peer, buf, sizeof(buf))); 00419 00420 if (addr->ce_mask & ADDR_ATTR_BROADCAST) 00421 nl_dump_line(p, "ADDR_BROADCAST=%s\n", 00422 nl_addr2str(addr->a_bcast, buf, sizeof(buf))); 00423 00424 if (addr->ce_mask & ADDR_ATTR_ANYCAST) 00425 nl_dump_line(p, "ADDR_ANYCAST=%s\n", 00426 nl_addr2str(addr->a_anycast, buf, sizeof(buf))); 00427 00428 if (addr->ce_mask & ADDR_ATTR_MULTICAST) 00429 nl_dump_line(p, "ADDR_MULTICAST=%s\n", 00430 nl_addr2str(addr->a_multicast, buf, 00431 sizeof(buf))); 00432 00433 if (addr->ce_mask & ADDR_ATTR_PREFIXLEN) 00434 nl_dump_line(p, "ADDR_PREFIXLEN=%u\n", 00435 addr->a_prefixlen); 00436 link_cache = nl_cache_mngt_require("route/link"); 00437 00438 nl_dump_line(p, "ADDR_IFINDEX=%u\n", addr->a_ifindex); 00439 if (link_cache) 00440 nl_dump_line(p, "ADDR_IFNAME=%s\n", 00441 rtnl_link_i2name(link_cache, addr->a_ifindex, 00442 buf, sizeof(buf))); 00443 00444 if (addr->ce_mask & ADDR_ATTR_SCOPE) 00445 nl_dump_line(p, "ADDR_SCOPE=%s\n", 00446 rtnl_scope2str(addr->a_scope, buf, sizeof(buf))); 00447 00448 if (addr->ce_mask & ADDR_ATTR_LABEL) 00449 nl_dump_line(p, "ADDR_LABEL=%s\n", addr->a_label); 00450 00451 rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf)); 00452 if (buf[0]) 00453 nl_dump_line(p, "ADDR_FLAGS=%s\n", buf); 00454 00455 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) { 00456 struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo; 00457 00458 nl_dump_line(p, "ADDR_CACHEINFO_VALID=%s\n", 00459 ci->aci_valid == 0xFFFFFFFFU ? "forever" : 00460 nl_msec2str(ci->aci_valid * 1000, 00461 buf, sizeof(buf))); 00462 00463 nl_dump_line(p, "ADDR_CACHEINFO_PREFERED=%s\n", 00464 ci->aci_prefered == 0xFFFFFFFFU ? "forever" : 00465 nl_msec2str(ci->aci_prefered * 1000, 00466 buf, sizeof(buf))); 00467 00468 nl_dump_line(p, "ADDR_CACHEINFO_CREATED=%s\n", 00469 nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10, 00470 buf, sizeof(buf))); 00471 00472 nl_dump_line(p, "ADDR_CACHEINFO_LASTUPDATE=%s\n", 00473 nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10, 00474 buf, sizeof(buf))); 00475 } 00476 } 00477 00478 static int addr_compare(struct nl_object *_a, struct nl_object *_b, 00479 uint32_t attrs, int flags) 00480 { 00481 struct rtnl_addr *a = (struct rtnl_addr *) _a; 00482 struct rtnl_addr *b = (struct rtnl_addr *) _b; 00483 int diff = 0; 00484 00485 #define ADDR_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ADDR_ATTR_##ATTR, a, b, EXPR) 00486 00487 diff |= ADDR_DIFF(IFINDEX, a->a_ifindex != b->a_ifindex); 00488 diff |= ADDR_DIFF(FAMILY, a->a_family != b->a_family); 00489 diff |= ADDR_DIFF(SCOPE, a->a_scope != b->a_scope); 00490 diff |= ADDR_DIFF(LABEL, strcmp(a->a_label, b->a_label)); 00491 diff |= ADDR_DIFF(PEER, nl_addr_cmp(a->a_peer, b->a_peer)); 00492 diff |= ADDR_DIFF(LOCAL, nl_addr_cmp(a->a_local, b->a_local)); 00493 diff |= ADDR_DIFF(MULTICAST, nl_addr_cmp(a->a_multicast, 00494 b->a_multicast)); 00495 diff |= ADDR_DIFF(BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast)); 00496 diff |= ADDR_DIFF(ANYCAST, nl_addr_cmp(a->a_anycast, b->a_anycast)); 00497 00498 if (flags & LOOSE_COMPARISON) 00499 diff |= ADDR_DIFF(FLAGS, 00500 (a->a_flags ^ b->a_flags) & b->a_flag_mask); 00501 else 00502 diff |= ADDR_DIFF(FLAGS, a->a_flags != b->a_flags); 00503 00504 #undef ADDR_DIFF 00505 00506 return diff; 00507 } 00508 00509 static struct trans_tbl addr_attrs[] = { 00510 __ADD(ADDR_ATTR_FAMILY, family) 00511 __ADD(ADDR_ATTR_PREFIXLEN, prefixlen) 00512 __ADD(ADDR_ATTR_FLAGS, flags) 00513 __ADD(ADDR_ATTR_SCOPE, scope) 00514 __ADD(ADDR_ATTR_IFINDEX, ifindex) 00515 __ADD(ADDR_ATTR_LABEL, label) 00516 __ADD(ADDR_ATTR_CACHEINFO, cacheinfo) 00517 __ADD(ADDR_ATTR_PEER, peer) 00518 __ADD(ADDR_ATTR_LOCAL, local) 00519 __ADD(ADDR_ATTR_BROADCAST, broadcast) 00520 __ADD(ADDR_ATTR_MULTICAST, multicast) 00521 }; 00522 00523 static char *addr_attrs2str(int attrs, char *buf, size_t len) 00524 { 00525 return __flags2str(attrs, buf, len, addr_attrs, 00526 ARRAY_SIZE(addr_attrs)); 00527 } 00528 00529 /** 00530 * @name Allocation/Freeing 00531 * @{ 00532 */ 00533 00534 struct rtnl_addr *rtnl_addr_alloc(void) 00535 { 00536 return (struct rtnl_addr *) nl_object_alloc(&addr_obj_ops); 00537 } 00538 00539 void rtnl_addr_put(struct rtnl_addr *addr) 00540 { 00541 nl_object_put((struct nl_object *) addr); 00542 } 00543 00544 /** @} */ 00545 00546 /** 00547 * @name Cache Management 00548 * @{ 00549 */ 00550 00551 int rtnl_addr_alloc_cache(struct nl_sock *sk, struct nl_cache **result) 00552 { 00553 return nl_cache_alloc_and_fill(&rtnl_addr_ops, sk, result); 00554 } 00555 00556 /** @} */ 00557 00558 static int build_addr_msg(struct rtnl_addr *tmpl, int cmd, int flags, 00559 struct nl_msg **result) 00560 { 00561 struct nl_msg *msg; 00562 struct ifaddrmsg am = { 00563 .ifa_family = tmpl->a_family, 00564 .ifa_index = tmpl->a_ifindex, 00565 .ifa_prefixlen = tmpl->a_prefixlen, 00566 }; 00567 00568 if (tmpl->ce_mask & ADDR_ATTR_SCOPE) 00569 am.ifa_scope = tmpl->a_scope; 00570 else { 00571 /* compatibility hack */ 00572 if (tmpl->a_family == AF_INET && 00573 tmpl->ce_mask & ADDR_ATTR_LOCAL && 00574 *((char *) nl_addr_get_binary_addr(tmpl->a_local)) == 127) 00575 am.ifa_scope = RT_SCOPE_HOST; 00576 else 00577 am.ifa_scope = RT_SCOPE_UNIVERSE; 00578 } 00579 00580 msg = nlmsg_alloc_simple(cmd, flags); 00581 if (!msg) 00582 return -NLE_NOMEM; 00583 00584 if (nlmsg_append(msg, &am, sizeof(am), NLMSG_ALIGNTO) < 0) 00585 goto nla_put_failure; 00586 00587 if (tmpl->ce_mask & ADDR_ATTR_LOCAL) 00588 NLA_PUT_ADDR(msg, IFA_LOCAL, tmpl->a_local); 00589 00590 if (tmpl->ce_mask & ADDR_ATTR_PEER) 00591 NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_peer); 00592 else if (tmpl->ce_mask & ADDR_ATTR_LOCAL) 00593 NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_local); 00594 00595 if (tmpl->ce_mask & ADDR_ATTR_LABEL) 00596 NLA_PUT_STRING(msg, IFA_LABEL, tmpl->a_label); 00597 00598 if (tmpl->ce_mask & ADDR_ATTR_BROADCAST) 00599 NLA_PUT_ADDR(msg, IFA_BROADCAST, tmpl->a_bcast); 00600 00601 if (tmpl->ce_mask & ADDR_ATTR_CACHEINFO) { 00602 struct ifa_cacheinfo ca = { 00603 .ifa_valid = tmpl->a_cacheinfo.aci_valid, 00604 .ifa_prefered = tmpl->a_cacheinfo.aci_prefered, 00605 }; 00606 00607 NLA_PUT(msg, IFA_CACHEINFO, sizeof(ca), &ca); 00608 } 00609 00610 00611 *result = msg; 00612 return 0; 00613 00614 nla_put_failure: 00615 nlmsg_free(msg); 00616 return -NLE_MSGSIZE; 00617 } 00618 00619 /** 00620 * @name Addition 00621 * @{ 00622 */ 00623 00624 /** 00625 * Build netlink request message to request addition of new address 00626 * @arg addr Address object representing the new address. 00627 * @arg flags Additional netlink message flags. 00628 * @arg result Pointer to store resulting message. 00629 * 00630 * Builds a new netlink message requesting the addition of a new 00631 * address. The netlink message header isn't fully equipped with 00632 * all relevant fields and must thus be sent out via nl_send_auto_complete() 00633 * or supplemented as needed. 00634 * 00635 * Minimal required attributes: 00636 * - interface index (rtnl_addr_set_ifindex()) 00637 * - local address (rtnl_addr_set_local()) 00638 * 00639 * The scope will default to universe except for loopback addresses in 00640 * which case a host scope is used if not specified otherwise. 00641 * 00642 * @note Free the memory after usage using nlmsg_free(). 00643 * 00644 * @return 0 on success or a negative error code. 00645 */ 00646 int rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags, 00647 struct nl_msg **result) 00648 { 00649 int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY | 00650 ADDR_ATTR_PREFIXLEN | ADDR_ATTR_LOCAL; 00651 00652 if ((addr->ce_mask & required) != required) 00653 return -NLE_MISSING_ATTR; 00654 00655 return build_addr_msg(addr, RTM_NEWADDR, NLM_F_CREATE | flags, result); 00656 } 00657 00658 /** 00659 * Request addition of new address 00660 * @arg sk Netlink socket. 00661 * @arg addr Address object representing the new address. 00662 * @arg flags Additional netlink message flags. 00663 * 00664 * Builds a netlink message by calling rtnl_addr_build_add_request(), 00665 * sends the request to the kernel and waits for the next ACK to be 00666 * received and thus blocks until the request has been fullfilled. 00667 * 00668 * @see rtnl_addr_build_add_request() 00669 * 00670 * @return 0 on sucess or a negative error if an error occured. 00671 */ 00672 int rtnl_addr_add(struct nl_sock *sk, struct rtnl_addr *addr, int flags) 00673 { 00674 struct nl_msg *msg; 00675 int err; 00676 00677 if ((err = rtnl_addr_build_add_request(addr, flags, &msg)) < 0) 00678 return err; 00679 00680 err = nl_send_auto_complete(sk, msg); 00681 nlmsg_free(msg); 00682 if (err < 0) 00683 return err; 00684 00685 return wait_for_ack(sk); 00686 } 00687 00688 /** @} */ 00689 00690 /** 00691 * @name Deletion 00692 * @{ 00693 */ 00694 00695 /** 00696 * Build a netlink request message to request deletion of an address 00697 * @arg addr Address object to be deleteted. 00698 * @arg flags Additional netlink message flags. 00699 * @arg result Pointer to store resulting message. 00700 * 00701 * Builds a new netlink message requesting a deletion of an address. 00702 * The netlink message header isn't fully equipped with all relevant 00703 * fields and must thus be sent out via nl_send_auto_complete() 00704 * or supplemented as needed. 00705 * 00706 * Minimal required attributes: 00707 * - interface index (rtnl_addr_set_ifindex()) 00708 * - address family (rtnl_addr_set_family()) 00709 * 00710 * Optional attributes: 00711 * - local address (rtnl_addr_set_local()) 00712 * - label (rtnl_addr_set_label(), IPv4/DECnet only) 00713 * - peer address (rtnl_addr_set_peer(), IPv4 only) 00714 * 00715 * @note Free the memory after usage using nlmsg_free(). 00716 * 00717 * @return 0 on success or a negative error code. 00718 */ 00719 int rtnl_addr_build_delete_request(struct rtnl_addr *addr, int flags, 00720 struct nl_msg **result) 00721 { 00722 int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY; 00723 00724 if ((addr->ce_mask & required) != required) 00725 return -NLE_MISSING_ATTR; 00726 00727 return build_addr_msg(addr, RTM_DELADDR, flags, result); 00728 } 00729 00730 /** 00731 * Request deletion of an address 00732 * @arg sk Netlink socket. 00733 * @arg addr Address object to be deleted. 00734 * @arg flags Additional netlink message flags. 00735 * 00736 * Builds a netlink message by calling rtnl_addr_build_delete_request(), 00737 * sends the request to the kernel and waits for the next ACK to be 00738 * received and thus blocks until the request has been fullfilled. 00739 * 00740 * @see rtnl_addr_build_delete_request(); 00741 * 00742 * @return 0 on sucess or a negative error if an error occured. 00743 */ 00744 int rtnl_addr_delete(struct nl_sock *sk, struct rtnl_addr *addr, int flags) 00745 { 00746 struct nl_msg *msg; 00747 int err; 00748 00749 if ((err = rtnl_addr_build_delete_request(addr, flags, &msg)) < 0) 00750 return err; 00751 00752 err = nl_send_auto_complete(sk, msg); 00753 nlmsg_free(msg); 00754 if (err < 0) 00755 return err; 00756 00757 return wait_for_ack(sk); 00758 } 00759 00760 /** @} */ 00761 00762 /** 00763 * @name Attributes 00764 * @{ 00765 */ 00766 00767 int rtnl_addr_set_label(struct rtnl_addr *addr, const char *label) 00768 { 00769 if (strlen(label) > sizeof(addr->a_label) - 1) 00770 return -NLE_RANGE; 00771 00772 strcpy(addr->a_label, label); 00773 addr->ce_mask |= ADDR_ATTR_LABEL; 00774 00775 return 0; 00776 } 00777 00778 char *rtnl_addr_get_label(struct rtnl_addr *addr) 00779 { 00780 if (addr->ce_mask & ADDR_ATTR_LABEL) 00781 return addr->a_label; 00782 else 00783 return NULL; 00784 } 00785 00786 void rtnl_addr_set_ifindex(struct rtnl_addr *addr, int ifindex) 00787 { 00788 addr->a_ifindex = ifindex; 00789 addr->ce_mask |= ADDR_ATTR_IFINDEX; 00790 } 00791 00792 int rtnl_addr_get_ifindex(struct rtnl_addr *addr) 00793 { 00794 return addr->a_ifindex; 00795 } 00796 00797 void rtnl_addr_set_family(struct rtnl_addr *addr, int family) 00798 { 00799 addr->a_family = family; 00800 addr->ce_mask |= ADDR_ATTR_FAMILY; 00801 } 00802 00803 int rtnl_addr_get_family(struct rtnl_addr *addr) 00804 { 00805 return addr->a_family; 00806 } 00807 00808 void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefix) 00809 { 00810 addr->a_prefixlen = prefix; 00811 addr->ce_mask |= ADDR_ATTR_PREFIXLEN; 00812 } 00813 00814 int rtnl_addr_get_prefixlen(struct rtnl_addr *addr) 00815 { 00816 return addr->a_prefixlen; 00817 } 00818 00819 void rtnl_addr_set_scope(struct rtnl_addr *addr, int scope) 00820 { 00821 addr->a_scope = scope; 00822 addr->ce_mask |= ADDR_ATTR_SCOPE; 00823 } 00824 00825 int rtnl_addr_get_scope(struct rtnl_addr *addr) 00826 { 00827 return addr->a_scope; 00828 } 00829 00830 void rtnl_addr_set_flags(struct rtnl_addr *addr, unsigned int flags) 00831 { 00832 addr->a_flag_mask |= flags; 00833 addr->a_flags |= flags; 00834 addr->ce_mask |= ADDR_ATTR_FLAGS; 00835 } 00836 00837 void rtnl_addr_unset_flags(struct rtnl_addr *addr, unsigned int flags) 00838 { 00839 addr->a_flag_mask |= flags; 00840 addr->a_flags &= ~flags; 00841 addr->ce_mask |= ADDR_ATTR_FLAGS; 00842 } 00843 00844 unsigned int rtnl_addr_get_flags(struct rtnl_addr *addr) 00845 { 00846 return addr->a_flags; 00847 } 00848 00849 static inline int __assign_addr(struct rtnl_addr *addr, struct nl_addr **pos, 00850 struct nl_addr *new, int flag) 00851 { 00852 if (addr->ce_mask & ADDR_ATTR_FAMILY) { 00853 if (new->a_family != addr->a_family) 00854 return -NLE_AF_MISMATCH; 00855 } else 00856 addr->a_family = new->a_family; 00857 00858 if (*pos) 00859 nl_addr_put(*pos); 00860 00861 *pos = nl_addr_get(new); 00862 addr->ce_mask |= (flag | ADDR_ATTR_FAMILY); 00863 00864 return 0; 00865 } 00866 00867 int rtnl_addr_set_local(struct rtnl_addr *addr, struct nl_addr *local) 00868 { 00869 int err; 00870 00871 err = __assign_addr(addr, &addr->a_local, local, ADDR_ATTR_LOCAL); 00872 if (err < 0) 00873 return err; 00874 00875 if (!(addr->ce_mask & ADDR_ATTR_PEER)) { 00876 addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_local); 00877 addr->ce_mask |= ADDR_ATTR_PREFIXLEN; 00878 } 00879 00880 return 0; 00881 } 00882 00883 struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr) 00884 { 00885 return addr->a_local; 00886 } 00887 00888 int rtnl_addr_set_peer(struct rtnl_addr *addr, struct nl_addr *peer) 00889 { 00890 return __assign_addr(addr, &addr->a_peer, peer, ADDR_ATTR_PEER); 00891 00892 addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_peer); 00893 addr->ce_mask |= ADDR_ATTR_PREFIXLEN; 00894 00895 return 0; 00896 } 00897 00898 struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr) 00899 { 00900 return addr->a_peer; 00901 } 00902 00903 int rtnl_addr_set_broadcast(struct rtnl_addr *addr, struct nl_addr *bcast) 00904 { 00905 return __assign_addr(addr, &addr->a_bcast, bcast, ADDR_ATTR_BROADCAST); 00906 } 00907 00908 struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *addr) 00909 { 00910 return addr->a_bcast; 00911 } 00912 00913 int rtnl_addr_set_multicast(struct rtnl_addr *addr, struct nl_addr *multicast) 00914 { 00915 return __assign_addr(addr, &addr->a_multicast, multicast, 00916 ADDR_ATTR_MULTICAST); 00917 } 00918 00919 struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr) 00920 { 00921 return addr->a_multicast; 00922 } 00923 00924 int rtnl_addr_set_anycast(struct rtnl_addr *addr, struct nl_addr *anycast) 00925 { 00926 return __assign_addr(addr, &addr->a_anycast, anycast, 00927 ADDR_ATTR_ANYCAST); 00928 } 00929 00930 struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *addr) 00931 { 00932 return addr->a_anycast; 00933 } 00934 00935 uint32_t rtnl_addr_get_valid_lifetime(struct rtnl_addr *addr) 00936 { 00937 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) 00938 return addr->a_cacheinfo.aci_valid; 00939 else 00940 return 0xFFFFFFFFU; 00941 } 00942 00943 void rtnl_addr_set_valid_lifetime(struct rtnl_addr *addr, uint32_t lifetime) 00944 { 00945 addr->a_cacheinfo.aci_valid = lifetime; 00946 addr->ce_mask |= ADDR_ATTR_CACHEINFO; 00947 } 00948 00949 uint32_t rtnl_addr_get_preferred_lifetime(struct rtnl_addr *addr) 00950 { 00951 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) 00952 return addr->a_cacheinfo.aci_prefered; 00953 else 00954 return 0xFFFFFFFFU; 00955 } 00956 00957 void rtnl_addr_set_preferred_lifetime(struct rtnl_addr *addr, uint32_t lifetime) 00958 { 00959 addr->a_cacheinfo.aci_prefered = lifetime; 00960 addr->ce_mask |= ADDR_ATTR_CACHEINFO; 00961 } 00962 00963 uint32_t rtnl_addr_get_create_time(struct rtnl_addr *addr) 00964 { 00965 return addr->a_cacheinfo.aci_cstamp; 00966 } 00967 00968 uint32_t rtnl_addr_get_last_update_time(struct rtnl_addr *addr) 00969 { 00970 return addr->a_cacheinfo.aci_tstamp; 00971 } 00972 00973 /** @} */ 00974 00975 /** 00976 * @name Flags Translations 00977 * @{ 00978 */ 00979 00980 static struct trans_tbl addr_flags[] = { 00981 __ADD(IFA_F_SECONDARY, secondary) 00982 __ADD(IFA_F_NODAD, nodad) 00983 __ADD(IFA_F_OPTIMISTIC, optimistic) 00984 __ADD(IFA_F_HOMEADDRESS, homeaddress) 00985 __ADD(IFA_F_DEPRECATED, deprecated) 00986 __ADD(IFA_F_TENTATIVE, tentative) 00987 __ADD(IFA_F_PERMANENT, permanent) 00988 }; 00989 00990 char *rtnl_addr_flags2str(int flags, char *buf, size_t size) 00991 { 00992 return __flags2str(flags, buf, size, addr_flags, 00993 ARRAY_SIZE(addr_flags)); 00994 } 00995 00996 int rtnl_addr_str2flags(const char *name) 00997 { 00998 return __str2flags(name, addr_flags, ARRAY_SIZE(addr_flags)); 00999 } 01000 01001 /** @} */ 01002 01003 static struct nl_object_ops addr_obj_ops = { 01004 .oo_name = "route/addr", 01005 .oo_size = sizeof(struct rtnl_addr), 01006 .oo_constructor = addr_constructor, 01007 .oo_free_data = addr_free_data, 01008 .oo_clone = addr_clone, 01009 .oo_dump = { 01010 [NL_DUMP_LINE] = addr_dump_line, 01011 [NL_DUMP_DETAILS] = addr_dump_details, 01012 [NL_DUMP_STATS] = addr_dump_stats, 01013 [NL_DUMP_ENV] = addr_dump_env, 01014 }, 01015 .oo_compare = addr_compare, 01016 .oo_attrs2str = addr_attrs2str, 01017 .oo_id_attrs = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX | 01018 ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN), 01019 }; 01020 01021 static struct nl_af_group addr_groups[] = { 01022 { AF_INET, RTNLGRP_IPV4_IFADDR }, 01023 { AF_INET6, RTNLGRP_IPV6_IFADDR }, 01024 { END_OF_GROUP_LIST }, 01025 }; 01026 01027 static struct nl_cache_ops rtnl_addr_ops = { 01028 .co_name = "route/addr", 01029 .co_hdrsize = sizeof(struct ifaddrmsg), 01030 .co_msgtypes = { 01031 { RTM_NEWADDR, NL_ACT_NEW, "new" }, 01032 { RTM_DELADDR, NL_ACT_DEL, "del" }, 01033 { RTM_GETADDR, NL_ACT_GET, "get" }, 01034 END_OF_MSGTYPES_LIST, 01035 }, 01036 .co_protocol = NETLINK_ROUTE, 01037 .co_groups = addr_groups, 01038 .co_request_update = addr_request_update, 01039 .co_msg_parser = addr_msg_parser, 01040 .co_obj_ops = &addr_obj_ops, 01041 }; 01042 01043 static void __init addr_init(void) 01044 { 01045 nl_cache_mngt_register(&rtnl_addr_ops); 01046 } 01047 01048 static void __exit addr_exit(void) 01049 { 01050 nl_cache_mngt_unregister(&rtnl_addr_ops); 01051 } 01052 01053 /** @} */