libnl 1.1
|
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-2006 Thomas Graf <tgraf@suug.ch> 00010 * 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 and anycast 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 * rtnl_addr_set_anycast(addr, anycast_addr); 00056 * 00057 * // Build the netlink message and send it to the kernel, the operation will 00058 * // block until the operation has been completed. Alternatively the required 00059 * // netlink message can be built using rtnl_addr_build_add_request() to be 00060 * // sent out using nl_send_auto_complete(). 00061 * rtnl_addr_add(handle, addr, 0); 00062 * 00063 * // Free the memory 00064 * rtnl_addr_put(addr); 00065 * @endcode 00066 * 00067 * @par 2) Address Deletion 00068 * @code 00069 * // Allocate an empty address object to be filled out with the attributes 00070 * // matching the address to be deleted. Alternatively a fully equipped 00071 * // address object out of a cache can be used instead. 00072 * struct rtnl_addr *addr = rtnl_addr_alloc(); 00073 * 00074 * // The only mandatory parameter besides the address family is the interface 00075 * // index the address is on, i.e. leaving out all other parameters will 00076 * // result in all addresses of the specified address family interface tuple 00077 * // to be deleted. 00078 * rtnl_addr_set_ifindex(addr, ifindex); 00079 * 00080 * // Specyfing the address family manually is only required if neither the 00081 * // local nor peer address have been specified. 00082 * rtnl_addr_set_family(addr, AF_INET); 00083 * 00084 * // Specyfing the local address is optional but the best choice to delete 00085 * // specific addresses. 00086 * rtnl_addr_set_local(addr, local_addr); 00087 * 00088 * // The label of the address can be specified, currently only supported 00089 * // by IPv4 and DECnet. 00090 * rtnl_addr_set_label(addr, "mylabel"); 00091 * 00092 * // The peer address can be specified if necessary, in either case a peer 00093 * // address will be sent to the kernel in order to fullfil the interface 00094 * // requirements. If none is set, it will equal the local address. 00095 * // Note: Real peer addresses are only supported by IPv4 for now. 00096 * rtnl_addr_set_peer(addr, peer_addr); 00097 * 00098 * // Build the netlink message and send it to the kernel, the operation will 00099 * // block until the operation has been completed. Alternatively the required 00100 * // netlink message can be built using rtnl_addr_build_delete_request() 00101 * // to be sent out using nl_send_auto_complete(). 00102 * rtnl_addr_delete(handle, addr, 0); 00103 * 00104 * // Free the memory 00105 * rtnl_addr_put(addr); 00106 * @endcode 00107 * @{ 00108 */ 00109 00110 #include <netlink-local.h> 00111 #include <netlink/netlink.h> 00112 #include <netlink/route/rtnl.h> 00113 #include <netlink/route/addr.h> 00114 #include <netlink/route/route.h> 00115 #include <netlink/route/link.h> 00116 #include <netlink/utils.h> 00117 00118 /** @cond SKIP */ 00119 #define ADDR_ATTR_FAMILY 0x0001 00120 #define ADDR_ATTR_PREFIXLEN 0x0002 00121 #define ADDR_ATTR_FLAGS 0x0004 00122 #define ADDR_ATTR_SCOPE 0x0008 00123 #define ADDR_ATTR_IFINDEX 0x0010 00124 #define ADDR_ATTR_LABEL 0x0020 00125 #define ADDR_ATTR_CACHEINFO 0x0040 00126 #define ADDR_ATTR_PEER 0x0080 00127 #define ADDR_ATTR_LOCAL 0x0100 00128 #define ADDR_ATTR_BROADCAST 0x0200 00129 #define ADDR_ATTR_ANYCAST 0x0400 00130 #define ADDR_ATTR_MULTICAST 0x0800 00131 00132 static struct nl_cache_ops rtnl_addr_ops; 00133 static struct nl_object_ops addr_obj_ops; 00134 /** @endcond */ 00135 00136 static void addr_free_data(struct nl_object *obj) 00137 { 00138 struct rtnl_addr *addr = nl_object_priv(obj); 00139 00140 if (!addr) 00141 return; 00142 00143 nl_addr_put(addr->a_peer); 00144 nl_addr_put(addr->a_local); 00145 nl_addr_put(addr->a_bcast); 00146 nl_addr_put(addr->a_anycast); 00147 nl_addr_put(addr->a_multicast); 00148 } 00149 00150 static int addr_clone(struct nl_object *_dst, struct nl_object *_src) 00151 { 00152 struct rtnl_addr *dst = nl_object_priv(_dst); 00153 struct rtnl_addr *src = nl_object_priv(_src); 00154 00155 if (src->a_peer) 00156 if (!(dst->a_peer = nl_addr_clone(src->a_peer))) 00157 goto errout; 00158 00159 if (src->a_local) 00160 if (!(dst->a_local = nl_addr_clone(src->a_local))) 00161 goto errout; 00162 00163 if (src->a_bcast) 00164 if (!(dst->a_bcast = nl_addr_clone(src->a_bcast))) 00165 goto errout; 00166 00167 if (src->a_anycast) 00168 if (!(dst->a_anycast = nl_addr_clone(src->a_anycast))) 00169 goto errout; 00170 00171 if (src->a_multicast) 00172 if (!(dst->a_multicast = nl_addr_clone(src->a_multicast))) 00173 goto errout; 00174 00175 return 0; 00176 errout: 00177 return nl_get_errno(); 00178 } 00179 00180 static struct nla_policy addr_policy[IFA_MAX+1] = { 00181 [IFA_LABEL] = { .type = NLA_STRING, 00182 .maxlen = IFNAMSIZ }, 00183 [IFA_CACHEINFO] = { .minlen = sizeof(struct ifa_cacheinfo) }, 00184 }; 00185 00186 static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 00187 struct nlmsghdr *nlh, struct nl_parser_param *pp) 00188 { 00189 struct rtnl_addr *addr; 00190 struct ifaddrmsg *ifa; 00191 struct nlattr *tb[IFA_MAX+1]; 00192 int err = -ENOMEM, peer_prefix = 0; 00193 00194 addr = rtnl_addr_alloc(); 00195 if (!addr) { 00196 err = nl_errno(ENOMEM); 00197 goto errout; 00198 } 00199 addr->ce_msgtype = nlh->nlmsg_type; 00200 00201 err = nlmsg_parse(nlh, sizeof(*ifa), tb, IFA_MAX, addr_policy); 00202 if (err < 0) 00203 goto errout_free; 00204 00205 ifa = nlmsg_data(nlh); 00206 addr->a_family = ifa->ifa_family; 00207 addr->a_prefixlen = ifa->ifa_prefixlen; 00208 addr->a_flags = ifa->ifa_flags; 00209 addr->a_scope = ifa->ifa_scope; 00210 addr->a_ifindex = ifa->ifa_index; 00211 00212 addr->ce_mask = (ADDR_ATTR_FAMILY | ADDR_ATTR_PREFIXLEN | 00213 ADDR_ATTR_FLAGS | ADDR_ATTR_SCOPE | ADDR_ATTR_IFINDEX); 00214 00215 if (tb[IFA_LABEL]) { 00216 nla_strlcpy(addr->a_label, tb[IFA_LABEL], IFNAMSIZ); 00217 addr->ce_mask |= ADDR_ATTR_LABEL; 00218 } 00219 00220 if (tb[IFA_CACHEINFO]) { 00221 struct ifa_cacheinfo *ca; 00222 00223 ca = nla_data(tb[IFA_CACHEINFO]); 00224 addr->a_cacheinfo.aci_prefered = ca->ifa_prefered; 00225 addr->a_cacheinfo.aci_valid = ca->ifa_valid; 00226 addr->a_cacheinfo.aci_cstamp = ca->cstamp; 00227 addr->a_cacheinfo.aci_tstamp = ca->tstamp; 00228 addr->ce_mask |= ADDR_ATTR_CACHEINFO; 00229 } 00230 00231 if (tb[IFA_LOCAL]) { 00232 addr->a_local = nla_get_addr(tb[IFA_LOCAL], addr->a_family); 00233 if (!addr->a_local) 00234 goto errout_free; 00235 addr->ce_mask |= ADDR_ATTR_LOCAL; 00236 } 00237 00238 if (tb[IFA_ADDRESS]) { 00239 struct nl_addr *a; 00240 00241 a = nla_get_addr(tb[IFA_ADDRESS], addr->a_family); 00242 if (!a) 00243 goto errout_free; 00244 00245 /* IPv6 sends the local address as IFA_ADDRESS with 00246 * no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS 00247 * with IFA_ADDRESS being the peer address if they differ */ 00248 if (!tb[IFA_LOCAL] || !nl_addr_cmp(a, addr->a_local)) { 00249 nl_addr_put(addr->a_local); 00250 addr->a_local = a; 00251 addr->ce_mask |= ADDR_ATTR_LOCAL; 00252 } else { 00253 addr->a_peer = a; 00254 addr->ce_mask |= ADDR_ATTR_PEER; 00255 peer_prefix = 1; 00256 } 00257 } 00258 00259 nl_addr_set_prefixlen(peer_prefix ? addr->a_peer : addr->a_local, 00260 addr->a_prefixlen); 00261 00262 if (tb[IFA_BROADCAST]) { 00263 addr->a_bcast = nla_get_addr(tb[IFA_BROADCAST], addr->a_family); 00264 if (!addr->a_bcast) 00265 goto errout_free; 00266 00267 addr->ce_mask |= ADDR_ATTR_BROADCAST; 00268 } 00269 00270 if (tb[IFA_ANYCAST]) { 00271 addr->a_anycast = nla_get_addr(tb[IFA_ANYCAST], addr->a_family); 00272 if (!addr->a_anycast) 00273 goto errout_free; 00274 00275 addr->ce_mask |= ADDR_ATTR_ANYCAST; 00276 } 00277 00278 if (tb[IFA_MULTICAST]) { 00279 addr->a_multicast = nla_get_addr(tb[IFA_MULTICAST], 00280 addr->a_family); 00281 if (!addr->a_multicast) 00282 goto errout_free; 00283 00284 addr->ce_mask |= ADDR_ATTR_MULTICAST; 00285 } 00286 00287 err = pp->pp_cb((struct nl_object *) addr, pp); 00288 if (err < 0) 00289 goto errout_free; 00290 00291 err = P_ACCEPT; 00292 00293 errout_free: 00294 rtnl_addr_put(addr); 00295 errout: 00296 return err; 00297 } 00298 00299 static int addr_request_update(struct nl_cache *cache, struct nl_handle *handle) 00300 { 00301 return nl_rtgen_request(handle, RTM_GETADDR, AF_UNSPEC, NLM_F_DUMP); 00302 } 00303 00304 static int addr_dump_brief(struct nl_object *obj, struct nl_dump_params *p) 00305 { 00306 struct rtnl_addr *addr = (struct rtnl_addr *) obj; 00307 struct nl_cache *link_cache; 00308 char buf[128]; 00309 00310 link_cache = nl_cache_mngt_require("route/link"); 00311 00312 if (addr->ce_mask & ADDR_ATTR_LOCAL) 00313 dp_dump(p, "%s", 00314 nl_addr2str(addr->a_local, buf, sizeof(buf))); 00315 else 00316 dp_dump(p, "none"); 00317 00318 if (addr->ce_mask & ADDR_ATTR_PEER) 00319 dp_dump(p, " peer %s", 00320 nl_addr2str(addr->a_peer, buf, sizeof(buf))); 00321 00322 dp_dump(p, " %s ", nl_af2str(addr->a_family, buf, sizeof(buf))); 00323 00324 if (link_cache) 00325 dp_dump(p, "dev %s ", 00326 rtnl_link_i2name(link_cache, addr->a_ifindex, 00327 buf, sizeof(buf))); 00328 else 00329 dp_dump(p, "dev %d ", addr->a_ifindex); 00330 00331 dp_dump(p, "scope %s", 00332 rtnl_scope2str(addr->a_scope, buf, sizeof(buf))); 00333 00334 rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf)); 00335 if (buf[0]) 00336 dp_dump(p, " <%s>", buf); 00337 00338 dp_dump(p, "\n"); 00339 00340 return 1; 00341 } 00342 00343 static int addr_dump_full(struct nl_object *obj, struct nl_dump_params *p) 00344 { 00345 struct rtnl_addr *addr = (struct rtnl_addr *) obj; 00346 int line = addr_dump_brief(obj, p); 00347 char buf[128]; 00348 00349 if (addr->ce_mask & (ADDR_ATTR_LABEL | ADDR_ATTR_BROADCAST | 00350 ADDR_ATTR_ANYCAST | ADDR_ATTR_MULTICAST)) { 00351 dp_dump_line(p, line++, " "); 00352 00353 if (addr->ce_mask & ADDR_ATTR_LABEL) 00354 dp_dump(p, " label %s", addr->a_label); 00355 00356 if (addr->ce_mask & ADDR_ATTR_BROADCAST) 00357 dp_dump(p, " broadcast %s", 00358 nl_addr2str(addr->a_bcast, buf, sizeof(buf))); 00359 00360 if (addr->ce_mask & ADDR_ATTR_ANYCAST) 00361 dp_dump(p, " anycast %s", 00362 nl_addr2str(addr->a_anycast, buf, 00363 sizeof(buf))); 00364 00365 if (addr->ce_mask & ADDR_ATTR_MULTICAST) 00366 dp_dump(p, " multicast %s", 00367 nl_addr2str(addr->a_multicast, buf, 00368 sizeof(buf))); 00369 00370 dp_dump(p, "\n"); 00371 } 00372 00373 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) { 00374 struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo; 00375 00376 dp_dump_line(p, line++, " valid-lifetime %s", 00377 ci->aci_valid == 0xFFFFFFFFU ? "forever" : 00378 nl_msec2str(ci->aci_valid * 1000, 00379 buf, sizeof(buf))); 00380 00381 dp_dump(p, " preferred-lifetime %s\n", 00382 ci->aci_prefered == 0xFFFFFFFFU ? "forever" : 00383 nl_msec2str(ci->aci_prefered * 1000, 00384 buf, sizeof(buf))); 00385 00386 dp_dump_line(p, line++, " created boot-time+%s ", 00387 nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10, 00388 buf, sizeof(buf))); 00389 00390 dp_dump(p, "last-updated boot-time+%s\n", 00391 nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10, 00392 buf, sizeof(buf))); 00393 } 00394 00395 return line; 00396 } 00397 00398 static int addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p) 00399 { 00400 return addr_dump_full(obj, p); 00401 } 00402 00403 static int addr_dump_xml(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 int line = 0; 00409 00410 dp_dump_line(p, line++, "<address>\n"); 00411 dp_dump_line(p, line++, " <family>%s</family>\n", 00412 nl_af2str(addr->a_family, buf, sizeof(buf))); 00413 00414 if (addr->ce_mask & ADDR_ATTR_LOCAL) 00415 dp_dump_line(p, line++, " <local>%s</local>\n", 00416 nl_addr2str(addr->a_local, buf, sizeof(buf))); 00417 00418 if (addr->ce_mask & ADDR_ATTR_PEER) 00419 dp_dump_line(p, line++, " <peer>%s</peer>\n", 00420 nl_addr2str(addr->a_peer, buf, sizeof(buf))); 00421 00422 if (addr->ce_mask & ADDR_ATTR_BROADCAST) 00423 dp_dump_line(p, line++, " <broadcast>%s</broadcast>\n", 00424 nl_addr2str(addr->a_bcast, buf, sizeof(buf))); 00425 00426 if (addr->ce_mask & ADDR_ATTR_ANYCAST) 00427 dp_dump_line(p, line++, " <anycast>%s</anycast>\n", 00428 nl_addr2str(addr->a_anycast, buf, sizeof(buf))); 00429 00430 if (addr->ce_mask & ADDR_ATTR_MULTICAST) 00431 dp_dump_line(p, line++, " <multicast>%s</multicast>\n", 00432 nl_addr2str(addr->a_multicast, buf, 00433 sizeof(buf))); 00434 00435 if (addr->ce_mask & ADDR_ATTR_PREFIXLEN) 00436 dp_dump_line(p, line++, " <prefixlen>%u</prefixlen>\n", 00437 addr->a_prefixlen); 00438 link_cache = nl_cache_mngt_require("route/link"); 00439 00440 if (link_cache) 00441 dp_dump_line(p, line++, " <device>%s</device>\n", 00442 rtnl_link_i2name(link_cache, addr->a_ifindex, 00443 buf, sizeof(buf))); 00444 else 00445 dp_dump_line(p, line++, " <device>%u</device>\n", 00446 addr->a_ifindex); 00447 00448 if (addr->ce_mask & ADDR_ATTR_SCOPE) 00449 dp_dump_line(p, line++, " <scope>%s</scope>\n", 00450 rtnl_scope2str(addr->a_scope, buf, sizeof(buf))); 00451 00452 if (addr->ce_mask & ADDR_ATTR_LABEL) 00453 dp_dump_line(p, line++, " <label>%s</label>\n", addr->a_label); 00454 00455 rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf)); 00456 if (buf[0]) 00457 dp_dump_line(p, line++, " <flags>%s</flags>\n", buf); 00458 00459 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) { 00460 struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo; 00461 00462 dp_dump_line(p, line++, " <cacheinfo>\n"); 00463 00464 dp_dump_line(p, line++, " <valid>%s</valid>\n", 00465 ci->aci_valid == 0xFFFFFFFFU ? "forever" : 00466 nl_msec2str(ci->aci_valid * 1000, 00467 buf, sizeof(buf))); 00468 00469 dp_dump_line(p, line++, " <prefered>%s</prefered>\n", 00470 ci->aci_prefered == 0xFFFFFFFFU ? "forever" : 00471 nl_msec2str(ci->aci_prefered * 1000, 00472 buf, sizeof(buf))); 00473 00474 dp_dump_line(p, line++, " <created>%s</created>\n", 00475 nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10, 00476 buf, sizeof(buf))); 00477 00478 dp_dump_line(p, line++, " <last-update>%s</last-update>\n", 00479 nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10, 00480 buf, sizeof(buf))); 00481 00482 dp_dump_line(p, line++, " </cacheinfo>\n"); 00483 } 00484 00485 dp_dump_line(p, line++, "</address>\n"); 00486 00487 return line; 00488 } 00489 00490 static int addr_dump_env(struct nl_object *obj, struct nl_dump_params *p) 00491 { 00492 struct rtnl_addr *addr = (struct rtnl_addr *) obj; 00493 struct nl_cache *link_cache; 00494 char buf[128]; 00495 int line = 0; 00496 00497 dp_dump_line(p, line++, "ADDR_FAMILY=%s\n", 00498 nl_af2str(addr->a_family, buf, sizeof(buf))); 00499 00500 if (addr->ce_mask & ADDR_ATTR_LOCAL) 00501 dp_dump_line(p, line++, "ADDR_LOCAL=%s\n", 00502 nl_addr2str(addr->a_local, buf, sizeof(buf))); 00503 00504 if (addr->ce_mask & ADDR_ATTR_PEER) 00505 dp_dump_line(p, line++, "ADDR_PEER=%s\n", 00506 nl_addr2str(addr->a_peer, buf, sizeof(buf))); 00507 00508 if (addr->ce_mask & ADDR_ATTR_BROADCAST) 00509 dp_dump_line(p, line++, "ADDR_BROADCAST=%s\n", 00510 nl_addr2str(addr->a_bcast, buf, sizeof(buf))); 00511 00512 if (addr->ce_mask & ADDR_ATTR_ANYCAST) 00513 dp_dump_line(p, line++, "ADDR_ANYCAST=%s\n", 00514 nl_addr2str(addr->a_anycast, buf, sizeof(buf))); 00515 00516 if (addr->ce_mask & ADDR_ATTR_MULTICAST) 00517 dp_dump_line(p, line++, "ADDR_MULTICAST=%s\n", 00518 nl_addr2str(addr->a_multicast, buf, 00519 sizeof(buf))); 00520 00521 if (addr->ce_mask & ADDR_ATTR_PREFIXLEN) 00522 dp_dump_line(p, line++, "ADDR_PREFIXLEN=%u\n", 00523 addr->a_prefixlen); 00524 link_cache = nl_cache_mngt_require("route/link"); 00525 00526 dp_dump_line(p, line++, "ADDR_IFINDEX=%u\n", addr->a_ifindex); 00527 if (link_cache) 00528 dp_dump_line(p, line++, "ADDR_IFNAME=%s\n", 00529 rtnl_link_i2name(link_cache, addr->a_ifindex, 00530 buf, sizeof(buf))); 00531 00532 if (addr->ce_mask & ADDR_ATTR_SCOPE) 00533 dp_dump_line(p, line++, "ADDR_SCOPE=%s\n", 00534 rtnl_scope2str(addr->a_scope, buf, sizeof(buf))); 00535 00536 if (addr->ce_mask & ADDR_ATTR_LABEL) 00537 dp_dump_line(p, line++, "ADDR_LABEL=%s\n", addr->a_label); 00538 00539 rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf)); 00540 if (buf[0]) 00541 dp_dump_line(p, line++, "ADDR_FLAGS=%s\n", buf); 00542 00543 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) { 00544 struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo; 00545 00546 dp_dump_line(p, line++, "ADDR_CACHEINFO_VALID=%s\n", 00547 ci->aci_valid == 0xFFFFFFFFU ? "forever" : 00548 nl_msec2str(ci->aci_valid * 1000, 00549 buf, sizeof(buf))); 00550 00551 dp_dump_line(p, line++, "ADDR_CACHEINFO_PREFERED=%s\n", 00552 ci->aci_prefered == 0xFFFFFFFFU ? "forever" : 00553 nl_msec2str(ci->aci_prefered * 1000, 00554 buf, sizeof(buf))); 00555 00556 dp_dump_line(p, line++, "ADDR_CACHEINFO_CREATED=%s\n", 00557 nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10, 00558 buf, sizeof(buf))); 00559 00560 dp_dump_line(p, line++, "ADDR_CACHEINFO_LASTUPDATE=%s\n", 00561 nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10, 00562 buf, sizeof(buf))); 00563 } 00564 00565 return line; 00566 } 00567 00568 static int addr_compare(struct nl_object *_a, struct nl_object *_b, 00569 uint32_t attrs, int flags) 00570 { 00571 struct rtnl_addr *a = (struct rtnl_addr *) _a; 00572 struct rtnl_addr *b = (struct rtnl_addr *) _b; 00573 int diff = 0; 00574 00575 #define ADDR_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ADDR_ATTR_##ATTR, a, b, EXPR) 00576 00577 diff |= ADDR_DIFF(IFINDEX, a->a_ifindex != b->a_ifindex); 00578 diff |= ADDR_DIFF(FAMILY, a->a_family != b->a_family); 00579 diff |= ADDR_DIFF(SCOPE, a->a_scope != b->a_scope); 00580 diff |= ADDR_DIFF(LABEL, strcmp(a->a_label, b->a_label)); 00581 diff |= ADDR_DIFF(PEER, nl_addr_cmp(a->a_peer, b->a_peer)); 00582 diff |= ADDR_DIFF(LOCAL, nl_addr_cmp(a->a_local, b->a_local)); 00583 diff |= ADDR_DIFF(ANYCAST, nl_addr_cmp(a->a_anycast,b->a_anycast)); 00584 diff |= ADDR_DIFF(MULTICAST, nl_addr_cmp(a->a_multicast, 00585 b->a_multicast)); 00586 diff |= ADDR_DIFF(BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast)); 00587 00588 if (flags & LOOSE_FLAG_COMPARISON) 00589 diff |= ADDR_DIFF(FLAGS, 00590 (a->a_flags ^ b->a_flags) & b->a_flag_mask); 00591 else 00592 diff |= ADDR_DIFF(FLAGS, a->a_flags != b->a_flags); 00593 00594 #undef ADDR_DIFF 00595 00596 return diff; 00597 } 00598 00599 static struct trans_tbl addr_attrs[] = { 00600 __ADD(ADDR_ATTR_FAMILY, family) 00601 __ADD(ADDR_ATTR_PREFIXLEN, prefixlen) 00602 __ADD(ADDR_ATTR_FLAGS, flags) 00603 __ADD(ADDR_ATTR_SCOPE, scope) 00604 __ADD(ADDR_ATTR_IFINDEX, ifindex) 00605 __ADD(ADDR_ATTR_LABEL, label) 00606 __ADD(ADDR_ATTR_CACHEINFO, cacheinfo) 00607 __ADD(ADDR_ATTR_PEER, peer) 00608 __ADD(ADDR_ATTR_LOCAL, local) 00609 __ADD(ADDR_ATTR_BROADCAST, broadcast) 00610 __ADD(ADDR_ATTR_ANYCAST, anycast) 00611 __ADD(ADDR_ATTR_MULTICAST, multicast) 00612 }; 00613 00614 static char *addr_attrs2str(int attrs, char *buf, size_t len) 00615 { 00616 return __flags2str(attrs, buf, len, addr_attrs, 00617 ARRAY_SIZE(addr_attrs)); 00618 } 00619 00620 /** 00621 * @name Allocation/Freeing 00622 * @{ 00623 */ 00624 00625 struct rtnl_addr *rtnl_addr_alloc(void) 00626 { 00627 return (struct rtnl_addr *) nl_object_alloc(&addr_obj_ops); 00628 } 00629 00630 void rtnl_addr_put(struct rtnl_addr *addr) 00631 { 00632 nl_object_put((struct nl_object *) addr); 00633 } 00634 00635 /** @} */ 00636 00637 /** 00638 * @name Cache Management 00639 * @{ 00640 */ 00641 00642 struct nl_cache *rtnl_addr_alloc_cache(struct nl_handle *handle) 00643 { 00644 struct nl_cache *cache; 00645 00646 cache = nl_cache_alloc(&rtnl_addr_ops); 00647 if (!cache) 00648 return NULL; 00649 00650 if (handle && nl_cache_refill(handle, cache) < 0) { 00651 nl_cache_free(cache); 00652 return NULL; 00653 } 00654 00655 return cache; 00656 } 00657 00658 /** @} */ 00659 00660 static struct nl_msg *build_addr_msg(struct rtnl_addr *tmpl, int cmd, int flags) 00661 { 00662 struct nl_msg *msg; 00663 struct ifaddrmsg am = { 00664 .ifa_family = tmpl->a_family, 00665 .ifa_index = tmpl->a_ifindex, 00666 .ifa_prefixlen = tmpl->a_prefixlen, 00667 }; 00668 00669 if (tmpl->ce_mask & ADDR_ATTR_SCOPE) 00670 am.ifa_scope = tmpl->a_scope; 00671 else { 00672 /* compatibility hack */ 00673 if (tmpl->a_family == AF_INET && 00674 tmpl->ce_mask & ADDR_ATTR_LOCAL && 00675 *((char *) nl_addr_get_binary_addr(tmpl->a_local)) == 127) 00676 am.ifa_scope = RT_SCOPE_HOST; 00677 else 00678 am.ifa_scope = RT_SCOPE_UNIVERSE; 00679 } 00680 00681 msg = nlmsg_alloc_simple(cmd, flags); 00682 if (!msg) 00683 goto nla_put_failure; 00684 00685 if (nlmsg_append(msg, &am, sizeof(am), NLMSG_ALIGNTO) < 0) 00686 goto nla_put_failure; 00687 00688 if (tmpl->ce_mask & ADDR_ATTR_LOCAL) 00689 NLA_PUT_ADDR(msg, IFA_LOCAL, tmpl->a_local); 00690 00691 if (tmpl->ce_mask & ADDR_ATTR_PEER) 00692 NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_peer); 00693 else 00694 NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_local); 00695 00696 if (tmpl->ce_mask & ADDR_ATTR_LABEL) 00697 NLA_PUT_STRING(msg, IFA_LABEL, tmpl->a_label); 00698 00699 if (tmpl->ce_mask & ADDR_ATTR_BROADCAST) 00700 NLA_PUT_ADDR(msg, IFA_BROADCAST, tmpl->a_bcast); 00701 00702 if (tmpl->ce_mask & ADDR_ATTR_ANYCAST) 00703 NLA_PUT_ADDR(msg, IFA_ANYCAST, tmpl->a_anycast); 00704 00705 return msg; 00706 00707 nla_put_failure: 00708 nlmsg_free(msg); 00709 return NULL; 00710 } 00711 00712 /** 00713 * @name Addition 00714 * @{ 00715 */ 00716 00717 /** 00718 * Build netlink request message to request addition of new address 00719 * @arg addr Address object representing the new address. 00720 * @arg flags Additional netlink message flags. 00721 * 00722 * Builds a new netlink message requesting the addition of a new 00723 * address. The netlink message header isn't fully equipped with 00724 * all relevant fields and must thus be sent out via nl_send_auto_complete() 00725 * or supplemented as needed. 00726 * 00727 * Minimal required attributes: 00728 * - interface index (rtnl_addr_set_ifindex()) 00729 * - local address (rtnl_addr_set_local()) 00730 * 00731 * The scope will default to universe except for loopback addresses in 00732 * which case a host scope is used if not specified otherwise. 00733 * 00734 * @note Free the memory after usage using nlmsg_free(). 00735 * @return Newly allocated netlink message or NULL if an error occured. 00736 */ 00737 struct nl_msg *rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags) 00738 { 00739 int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY | 00740 ADDR_ATTR_PREFIXLEN | ADDR_ATTR_LOCAL; 00741 00742 if ((addr->ce_mask & required) != required) { 00743 nl_error(EINVAL, "Missing mandatory attributes, required are: " 00744 "ifindex, family, prefixlen, local address."); 00745 return NULL; 00746 } 00747 00748 return build_addr_msg(addr, RTM_NEWADDR, NLM_F_CREATE | flags); 00749 } 00750 00751 /** 00752 * Request addition of new address 00753 * @arg handle Netlink handle. 00754 * @arg addr Address object representing the new address. 00755 * @arg flags Additional netlink message flags. 00756 * 00757 * Builds a netlink message by calling rtnl_addr_build_add_request(), 00758 * sends the request to the kernel and waits for the next ACK to be 00759 * received and thus blocks until the request has been fullfilled. 00760 * 00761 * @see rtnl_addr_build_add_request() 00762 * 00763 * @return 0 on sucess or a negative error if an error occured. 00764 */ 00765 int rtnl_addr_add(struct nl_handle *handle, struct rtnl_addr *addr, int flags) 00766 { 00767 struct nl_msg *msg; 00768 int err; 00769 00770 msg = rtnl_addr_build_add_request(addr, flags); 00771 if (!msg) 00772 return nl_get_errno(); 00773 00774 err = nl_send_auto_complete(handle, msg); 00775 nlmsg_free(msg); 00776 if (err < 0) 00777 return err; 00778 00779 return nl_wait_for_ack(handle); 00780 } 00781 00782 /** @} */ 00783 00784 /** 00785 * @name Deletion 00786 * @{ 00787 */ 00788 00789 /** 00790 * Build a netlink request message to request deletion of an address 00791 * @arg addr Address object to be deleteted. 00792 * @arg flags Additional netlink message flags. 00793 * 00794 * Builds a new netlink message requesting a deletion of an address. 00795 * The netlink message header isn't fully equipped with all relevant 00796 * fields and must thus be sent out via nl_send_auto_complete() 00797 * or supplemented as needed. 00798 * 00799 * Minimal required attributes: 00800 * - interface index (rtnl_addr_set_ifindex()) 00801 * - address family (rtnl_addr_set_family()) 00802 * 00803 * Optional attributes: 00804 * - local address (rtnl_addr_set_local()) 00805 * - label (rtnl_addr_set_label(), IPv4/DECnet only) 00806 * - peer address (rtnl_addr_set_peer(), IPv4 only) 00807 * 00808 * @note Free the memory after usage using nlmsg_free(). 00809 * @return Newly allocated netlink message or NULL if an error occured. 00810 */ 00811 struct nl_msg *rtnl_addr_build_delete_request(struct rtnl_addr *addr, int flags) 00812 { 00813 int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY; 00814 00815 if ((addr->ce_mask & required) != required) { 00816 nl_error(EINVAL, "Missing mandatory attributes, required are: " 00817 "ifindex, family"); 00818 return NULL; 00819 } 00820 00821 return build_addr_msg(addr, RTM_DELADDR, flags); 00822 } 00823 00824 /** 00825 * Request deletion of an address 00826 * @arg handle Netlink handle. 00827 * @arg addr Address object to be deleted. 00828 * @arg flags Additional netlink message flags. 00829 * 00830 * Builds a netlink message by calling rtnl_addr_build_delete_request(), 00831 * sends the request to the kernel and waits for the next ACK to be 00832 * received and thus blocks until the request has been fullfilled. 00833 * 00834 * @see rtnl_addr_build_delete_request(); 00835 * 00836 * @return 0 on sucess or a negative error if an error occured. 00837 */ 00838 int rtnl_addr_delete(struct nl_handle *handle, struct rtnl_addr *addr, 00839 int flags) 00840 { 00841 struct nl_msg *msg; 00842 int err; 00843 00844 msg = rtnl_addr_build_delete_request(addr, flags); 00845 if (!msg) 00846 return nl_get_errno(); 00847 00848 err = nl_send_auto_complete(handle, msg); 00849 nlmsg_free(msg); 00850 if (err < 0) 00851 return err; 00852 00853 return nl_wait_for_ack(handle); 00854 } 00855 00856 /** @} */ 00857 00858 /** 00859 * @name Attributes 00860 * @{ 00861 */ 00862 00863 void rtnl_addr_set_label(struct rtnl_addr *addr, const char *label) 00864 { 00865 strncpy(addr->a_label, label, sizeof(addr->a_label) - 1); 00866 addr->ce_mask |= ADDR_ATTR_LABEL; 00867 } 00868 00869 char *rtnl_addr_get_label(struct rtnl_addr *addr) 00870 { 00871 if (addr->ce_mask & ADDR_ATTR_LABEL) 00872 return addr->a_label; 00873 else 00874 return NULL; 00875 } 00876 00877 void rtnl_addr_set_ifindex(struct rtnl_addr *addr, int ifindex) 00878 { 00879 addr->a_ifindex = ifindex; 00880 addr->ce_mask |= ADDR_ATTR_IFINDEX; 00881 } 00882 00883 int rtnl_addr_get_ifindex(struct rtnl_addr *addr) 00884 { 00885 if (addr->ce_mask & ADDR_ATTR_IFINDEX) 00886 return addr->a_ifindex; 00887 else 00888 return RTNL_LINK_NOT_FOUND; 00889 } 00890 00891 void rtnl_addr_set_family(struct rtnl_addr *addr, int family) 00892 { 00893 addr->a_family = family; 00894 addr->ce_mask |= ADDR_ATTR_FAMILY; 00895 } 00896 00897 int rtnl_addr_get_family(struct rtnl_addr *addr) 00898 { 00899 if (addr->ce_mask & ADDR_ATTR_FAMILY) 00900 return addr->a_family; 00901 else 00902 return AF_UNSPEC; 00903 } 00904 00905 void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefix) 00906 { 00907 addr->a_prefixlen = prefix; 00908 addr->ce_mask |= ADDR_ATTR_PREFIXLEN; 00909 } 00910 00911 int rtnl_addr_get_prefixlen(struct rtnl_addr *addr) 00912 { 00913 if (addr->ce_mask & ADDR_ATTR_PREFIXLEN) 00914 return addr->a_prefixlen; 00915 else 00916 return -1; 00917 } 00918 00919 void rtnl_addr_set_scope(struct rtnl_addr *addr, int scope) 00920 { 00921 addr->a_scope = scope; 00922 addr->ce_mask |= ADDR_ATTR_SCOPE; 00923 } 00924 00925 int rtnl_addr_get_scope(struct rtnl_addr *addr) 00926 { 00927 if (addr->ce_mask & ADDR_ATTR_SCOPE) 00928 return addr->a_scope; 00929 else 00930 return -1; 00931 } 00932 00933 void rtnl_addr_set_flags(struct rtnl_addr *addr, unsigned int flags) 00934 { 00935 addr->a_flag_mask |= flags; 00936 addr->a_flags |= flags; 00937 addr->ce_mask |= ADDR_ATTR_FLAGS; 00938 } 00939 00940 void rtnl_addr_unset_flags(struct rtnl_addr *addr, unsigned int flags) 00941 { 00942 addr->a_flag_mask |= flags; 00943 addr->a_flags &= ~flags; 00944 addr->ce_mask |= ADDR_ATTR_FLAGS; 00945 } 00946 00947 unsigned int rtnl_addr_get_flags(struct rtnl_addr *addr) 00948 { 00949 return addr->a_flags; 00950 } 00951 00952 static inline int __assign_addr(struct rtnl_addr *addr, struct nl_addr **pos, 00953 struct nl_addr *new, int flag) 00954 { 00955 if (addr->ce_mask & ADDR_ATTR_FAMILY) { 00956 if (new->a_family != addr->a_family) 00957 return nl_error(EINVAL, "Address family mismatch"); 00958 } else 00959 addr->a_family = new->a_family; 00960 00961 if (*pos) 00962 nl_addr_put(*pos); 00963 00964 *pos = nl_addr_get(new); 00965 addr->ce_mask |= (flag | ADDR_ATTR_FAMILY); 00966 00967 return 0; 00968 } 00969 00970 int rtnl_addr_set_local(struct rtnl_addr *addr, struct nl_addr *local) 00971 { 00972 int err; 00973 00974 err = __assign_addr(addr, &addr->a_local, local, ADDR_ATTR_LOCAL); 00975 if (err < 0) 00976 return err; 00977 00978 if (!(addr->ce_mask & ADDR_ATTR_PEER)) { 00979 addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_local); 00980 addr->ce_mask |= ADDR_ATTR_PREFIXLEN; 00981 } 00982 00983 return 0; 00984 } 00985 00986 struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr) 00987 { 00988 if (addr->ce_mask & ADDR_ATTR_LOCAL) 00989 return addr->a_local; 00990 else 00991 return NULL; 00992 } 00993 00994 int rtnl_addr_set_peer(struct rtnl_addr *addr, struct nl_addr *peer) 00995 { 00996 return __assign_addr(addr, &addr->a_peer, peer, ADDR_ATTR_PEER); 00997 00998 addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_peer); 00999 addr->ce_mask |= ADDR_ATTR_PREFIXLEN; 01000 01001 return 0; 01002 } 01003 01004 struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr) 01005 { 01006 if (addr->ce_mask & ADDR_ATTR_PEER) 01007 return addr->a_peer; 01008 else 01009 return NULL; 01010 } 01011 01012 int rtnl_addr_set_broadcast(struct rtnl_addr *addr, struct nl_addr *bcast) 01013 { 01014 return __assign_addr(addr, &addr->a_bcast, bcast, ADDR_ATTR_BROADCAST); 01015 } 01016 01017 struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *addr) 01018 { 01019 if (addr->ce_mask & ADDR_ATTR_BROADCAST) 01020 return addr->a_bcast; 01021 else 01022 return NULL; 01023 } 01024 01025 int rtnl_addr_set_anycast(struct rtnl_addr *addr, struct nl_addr *anycast) 01026 { 01027 return __assign_addr(addr, &addr->a_anycast, anycast, 01028 ADDR_ATTR_ANYCAST); 01029 } 01030 01031 struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *addr) 01032 { 01033 if (addr->ce_mask & ADDR_ATTR_ANYCAST) 01034 return addr->a_anycast; 01035 else 01036 return NULL; 01037 } 01038 01039 int rtnl_addr_set_multicast(struct rtnl_addr *addr, struct nl_addr *multicast) 01040 { 01041 return __assign_addr(addr, &addr->a_multicast, multicast, 01042 ADDR_ATTR_MULTICAST); 01043 } 01044 01045 struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr) 01046 { 01047 if (addr->ce_mask & ADDR_ATTR_MULTICAST) 01048 return addr->a_multicast; 01049 else 01050 return NULL; 01051 } 01052 01053 /** @} */ 01054 01055 /** 01056 * @name Flags Translations 01057 * @{ 01058 */ 01059 01060 static struct trans_tbl addr_flags[] = { 01061 __ADD(IFA_F_SECONDARY, secondary) 01062 __ADD(IFA_F_DEPRECATED, deprecated) 01063 __ADD(IFA_F_TENTATIVE, tentative) 01064 __ADD(IFA_F_PERMANENT, permanent) 01065 }; 01066 01067 char *rtnl_addr_flags2str(int flags, char *buf, size_t size) 01068 { 01069 return __flags2str(flags, buf, size, addr_flags, 01070 ARRAY_SIZE(addr_flags)); 01071 } 01072 01073 int rtnl_addr_str2flags(const char *name) 01074 { 01075 return __str2flags(name, addr_flags, ARRAY_SIZE(addr_flags)); 01076 } 01077 01078 /** @} */ 01079 01080 static struct nl_object_ops addr_obj_ops = { 01081 .oo_name = "route/addr", 01082 .oo_size = sizeof(struct rtnl_addr), 01083 .oo_free_data = addr_free_data, 01084 .oo_clone = addr_clone, 01085 .oo_dump[NL_DUMP_BRIEF] = addr_dump_brief, 01086 .oo_dump[NL_DUMP_FULL] = addr_dump_full, 01087 .oo_dump[NL_DUMP_STATS] = addr_dump_stats, 01088 .oo_dump[NL_DUMP_XML] = addr_dump_xml, 01089 .oo_dump[NL_DUMP_ENV] = addr_dump_env, 01090 .oo_compare = addr_compare, 01091 .oo_attrs2str = addr_attrs2str, 01092 .oo_id_attrs = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX | 01093 ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN | 01094 ADDR_ATTR_PEER), 01095 }; 01096 01097 static struct nl_af_group addr_groups[] = { 01098 { AF_INET, RTNLGRP_IPV4_IFADDR }, 01099 { AF_INET6, RTNLGRP_IPV6_IFADDR }, 01100 { END_OF_GROUP_LIST }, 01101 }; 01102 01103 static struct nl_cache_ops rtnl_addr_ops = { 01104 .co_name = "route/addr", 01105 .co_hdrsize = sizeof(struct ifaddrmsg), 01106 .co_msgtypes = { 01107 { RTM_NEWADDR, NL_ACT_NEW, "new" }, 01108 { RTM_DELADDR, NL_ACT_DEL, "del" }, 01109 { RTM_GETADDR, NL_ACT_GET, "get" }, 01110 END_OF_MSGTYPES_LIST, 01111 }, 01112 .co_protocol = NETLINK_ROUTE, 01113 .co_groups = addr_groups, 01114 .co_request_update = addr_request_update, 01115 .co_msg_parser = addr_msg_parser, 01116 .co_obj_ops = &addr_obj_ops, 01117 }; 01118 01119 static void __init addr_init(void) 01120 { 01121 nl_cache_mngt_register(&rtnl_addr_ops); 01122 } 01123 01124 static void __exit addr_exit(void) 01125 { 01126 nl_cache_mngt_unregister(&rtnl_addr_ops); 01127 } 01128 01129 /** @} */