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