144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/route/addr.c Addresses 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 108a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2006 Baruch Even <baruch@ev-en.org>, 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Mediatrix Telecom, inc. <ericb@mediatrix.com> 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup rtnl 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup rtaddr Addresses 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @brief 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @note The maximum size of an address label is IFNAMSIZ. 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @note The address may not contain a prefix length if the peer address 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf * has been specified already. 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 1) Address Addition 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Allocate an empty address object to be filled out with the attributes 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // of the new address. 2844d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct rtnl_addr *addr = rtnl_addr_alloc(); 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Fill out the mandatory attributes of the new address. Setting the 3144d362409d5469aed47d19e7908d19bd194493aThomas Graf * // local address will automatically set the address family and the 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // prefix length to the correct values. 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_addr_set_ifindex(addr, ifindex); 3444d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_addr_set_local(addr, local_addr); 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 3644d362409d5469aed47d19e7908d19bd194493aThomas Graf * // The label of the address can be specified, currently only supported 3744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // by IPv4 and DECnet. 3844d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_addr_set_label(addr, "mylabel"); 3944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 4044d362409d5469aed47d19e7908d19bd194493aThomas Graf * // The peer address can be specified if necessary, in either case a peer 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf * // address will be sent to the kernel in order to fullfil the interface 4244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // requirements. If none is set, it will equal the local address. 4344d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Note: Real peer addresses are only supported by IPv4 for now. 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_addr_set_peer(addr, peer_addr); 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf * // In case you want to have the address have a scope other than global 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // it may be overwritten using rtnl_addr_set_scope(). The scope currently 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // cannot be set for IPv6 addresses. 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_addr_set_scope(addr, rtnl_str2scope("site")); 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 510d925c58069b2d29f17c2bde14192b6f35ccac4dThomas Graf * // Broadcast address may be specified using the relevant 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // functions, the address family will be verified if one of the other 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf * // addresses has been set already. Currently only works for IPv4. 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_addr_set_broadcast(addr, broadcast_addr); 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Build the netlink message and send it to the kernel, the operation will 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // block until the operation has been completed. Alternatively the required 5844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // netlink message can be built using rtnl_addr_build_add_request() to be 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf * // sent out using nl_send_auto_complete(). 601155370f520cb64657e25153255cf7dc1424317fThomas Graf * rtnl_addr_add(sk, addr, 0); 6144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Free the memory 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_addr_put(addr); 6444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 6644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 2) Address Deletion 6744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Allocate an empty address object to be filled out with the attributes 6944d362409d5469aed47d19e7908d19bd194493aThomas Graf * // matching the address to be deleted. Alternatively a fully equipped 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf * // address object out of a cache can be used instead. 7144d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct rtnl_addr *addr = rtnl_addr_alloc(); 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf * // The only mandatory parameter besides the address family is the interface 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf * // index the address is on, i.e. leaving out all other parameters will 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf * // result in all addresses of the specified address family interface tuple 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf * // to be deleted. 7744d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_addr_set_ifindex(addr, ifindex); 7844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 7944d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Specyfing the address family manually is only required if neither the 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf * // local nor peer address have been specified. 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_addr_set_family(addr, AF_INET); 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 8344d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Specyfing the local address is optional but the best choice to delete 8444d362409d5469aed47d19e7908d19bd194493aThomas Graf * // specific addresses. 8544d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_addr_set_local(addr, local_addr); 8644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // The label of the address can be specified, currently only supported 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // by IPv4 and DECnet. 8944d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_addr_set_label(addr, "mylabel"); 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf * // The peer address can be specified if necessary, in either case a peer 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // address will be sent to the kernel in order to fullfil the interface 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf * // requirements. If none is set, it will equal the local address. 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Note: Real peer addresses are only supported by IPv4 for now. 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_addr_set_peer(addr, peer_addr); 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Build the netlink message and send it to the kernel, the operation will 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // block until the operation has been completed. Alternatively the required 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf * // netlink message can be built using rtnl_addr_build_delete_request() 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf * // to be sent out using nl_send_auto_complete(). 1011155370f520cb64657e25153255cf7dc1424317fThomas Graf * rtnl_addr_delete(sk, addr, 0); 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Free the memory 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_addr_put(addr); 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h> 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/rtnl.h> 11244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/addr.h> 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/route.h> 11444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/link.h> 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 11644d362409d5469aed47d19e7908d19bd194493aThomas Graf 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @cond SKIP */ 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf#define ADDR_ATTR_FAMILY 0x0001 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf#define ADDR_ATTR_PREFIXLEN 0x0002 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf#define ADDR_ATTR_FLAGS 0x0004 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf#define ADDR_ATTR_SCOPE 0x0008 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf#define ADDR_ATTR_IFINDEX 0x0010 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define ADDR_ATTR_LABEL 0x0020 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf#define ADDR_ATTR_CACHEINFO 0x0040 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define ADDR_ATTR_PEER 0x0080 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf#define ADDR_ATTR_LOCAL 0x0100 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf#define ADDR_ATTR_BROADCAST 0x0200 1280d925c58069b2d29f17c2bde14192b6f35ccac4dThomas Graf#define ADDR_ATTR_MULTICAST 0x0400 129f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy#define ADDR_ATTR_ANYCAST 0x0800 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf 13144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops rtnl_addr_ops; 13244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_object_ops addr_obj_ops; 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @endcond */ 13444d362409d5469aed47d19e7908d19bd194493aThomas Graf 135ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Grafstatic void addr_constructor(struct nl_object *obj) 136ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf{ 137ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf struct rtnl_addr *addr = nl_object_priv(obj); 138ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf 139ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf addr->a_scope = RT_SCOPE_NOWHERE; 140ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf} 141ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf 14244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void addr_free_data(struct nl_object *obj) 14344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_addr *addr = nl_object_priv(obj); 14544d362409d5469aed47d19e7908d19bd194493aThomas Graf 14644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!addr) 14744d362409d5469aed47d19e7908d19bd194493aThomas Graf return; 14844d362409d5469aed47d19e7908d19bd194493aThomas Graf 14944d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(addr->a_peer); 15044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(addr->a_local); 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(addr->a_bcast); 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(addr->a_multicast); 153f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy nl_addr_put(addr->a_anycast); 15444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 15544d362409d5469aed47d19e7908d19bd194493aThomas Graf 15644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int addr_clone(struct nl_object *_dst, struct nl_object *_src) 15744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 15844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_addr *dst = nl_object_priv(_dst); 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_addr *src = nl_object_priv(_src); 16044d362409d5469aed47d19e7908d19bd194493aThomas Graf 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (src->a_peer) 16244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!(dst->a_peer = nl_addr_clone(src->a_peer))) 1638a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 16444d362409d5469aed47d19e7908d19bd194493aThomas Graf 16544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (src->a_local) 16644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!(dst->a_local = nl_addr_clone(src->a_local))) 1678a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 16844d362409d5469aed47d19e7908d19bd194493aThomas Graf 16944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (src->a_bcast) 17044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!(dst->a_bcast = nl_addr_clone(src->a_bcast))) 1718a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 17244d362409d5469aed47d19e7908d19bd194493aThomas Graf 17344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (src->a_multicast) 17444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!(dst->a_multicast = nl_addr_clone(src->a_multicast))) 1758a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 17644d362409d5469aed47d19e7908d19bd194493aThomas Graf 177f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy if (src->a_anycast) 178f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy if (!(dst->a_anycast = nl_addr_clone(src->a_anycast))) 179f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy return -NLE_NOMEM; 180f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 18344d362409d5469aed47d19e7908d19bd194493aThomas Graf 18444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy addr_policy[IFA_MAX+1] = { 18544d362409d5469aed47d19e7908d19bd194493aThomas Graf [IFA_LABEL] = { .type = NLA_STRING, 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf .maxlen = IFNAMSIZ }, 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf [IFA_CACHEINFO] = { .minlen = sizeof(struct ifa_cacheinfo) }, 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf 19044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 1913040a1d6254465bed9e44e4d1bf279c2c50cd16aThomas Graf struct nlmsghdr *nlh, struct nl_parser_param *pp) 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_addr *addr; 19444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct ifaddrmsg *ifa; 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tb[IFA_MAX+1]; 196eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf int err, peer_prefix = 0, family; 19744d362409d5469aed47d19e7908d19bd194493aThomas Graf 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf addr = rtnl_addr_alloc(); 199eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf if (!addr) 200eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf return -NLE_NOMEM; 201eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_msgtype = nlh->nlmsg_type; 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nlmsg_parse(nlh, sizeof(*ifa), tb, IFA_MAX, addr_policy); 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 206eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf goto errout; 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf 20844d362409d5469aed47d19e7908d19bd194493aThomas Graf ifa = nlmsg_data(nlh); 209eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf addr->a_family = family = ifa->ifa_family; 21044d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_prefixlen = ifa->ifa_prefixlen; 21144d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_flags = ifa->ifa_flags; 21244d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_scope = ifa->ifa_scope; 21344d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_ifindex = ifa->ifa_index; 21444d362409d5469aed47d19e7908d19bd194493aThomas Graf 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask = (ADDR_ATTR_FAMILY | ADDR_ATTR_PREFIXLEN | 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf ADDR_ATTR_FLAGS | ADDR_ATTR_SCOPE | ADDR_ATTR_IFINDEX); 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[IFA_LABEL]) { 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_strlcpy(addr->a_label, tb[IFA_LABEL], IFNAMSIZ); 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_LABEL; 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 22244d362409d5469aed47d19e7908d19bd194493aThomas Graf 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[IFA_CACHEINFO]) { 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct ifa_cacheinfo *ca; 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf ca = nla_data(tb[IFA_CACHEINFO]); 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_cacheinfo.aci_prefered = ca->ifa_prefered; 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_cacheinfo.aci_valid = ca->ifa_valid; 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_cacheinfo.aci_cstamp = ca->cstamp; 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_cacheinfo.aci_tstamp = ca->tstamp; 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_CACHEINFO; 23244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 23344d362409d5469aed47d19e7908d19bd194493aThomas Graf 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[IFA_LOCAL]) { 235eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf addr->a_local = nl_addr_alloc_attr(tb[IFA_LOCAL], family); 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!addr->a_local) 237eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf goto errout_nomem; 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_LOCAL; 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[IFA_ADDRESS]) { 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_addr *a; 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf 244eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf a = nl_addr_alloc_attr(tb[IFA_ADDRESS], family); 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!a) 246eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf goto errout_nomem; 24744d362409d5469aed47d19e7908d19bd194493aThomas Graf 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf /* IPv6 sends the local address as IFA_ADDRESS with 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf * no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS 25044d362409d5469aed47d19e7908d19bd194493aThomas Graf * with IFA_ADDRESS being the peer address if they differ */ 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!tb[IFA_LOCAL] || !nl_addr_cmp(a, addr->a_local)) { 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(addr->a_local); 25344d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_local = a; 25444d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_LOCAL; 25544d362409d5469aed47d19e7908d19bd194493aThomas Graf } else { 25644d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_peer = a; 25744d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_PEER; 25844d362409d5469aed47d19e7908d19bd194493aThomas Graf peer_prefix = 1; 25944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 26044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 26144d362409d5469aed47d19e7908d19bd194493aThomas Graf 26244d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_set_prefixlen(peer_prefix ? addr->a_peer : addr->a_local, 26344d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_prefixlen); 26444d362409d5469aed47d19e7908d19bd194493aThomas Graf 26544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[IFA_BROADCAST]) { 266eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf addr->a_bcast = nl_addr_alloc_attr(tb[IFA_BROADCAST], family); 26744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!addr->a_bcast) 268eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf goto errout_nomem; 26944d362409d5469aed47d19e7908d19bd194493aThomas Graf 27044d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_BROADCAST; 27144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 27244d362409d5469aed47d19e7908d19bd194493aThomas Graf 27344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[IFA_MULTICAST]) { 274eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf addr->a_multicast = nl_addr_alloc_attr(tb[IFA_MULTICAST], 275eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf family); 27644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!addr->a_multicast) 277eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf goto errout_nomem; 27844d362409d5469aed47d19e7908d19bd194493aThomas Graf 27944d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_MULTICAST; 28044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 28144d362409d5469aed47d19e7908d19bd194493aThomas Graf 282f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy if (tb[IFA_ANYCAST]) { 283f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy addr->a_anycast = nl_addr_alloc_attr(tb[IFA_ANYCAST], 284f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy family); 285f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy if (!addr->a_anycast) 286f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy goto errout_nomem; 287f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy 288f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy addr->ce_mask |= ADDR_ATTR_ANYCAST; 289f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy } 290f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy 29144d362409d5469aed47d19e7908d19bd194493aThomas Graf err = pp->pp_cb((struct nl_object *) addr, pp); 29244d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 293eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf rtnl_addr_put(addr); 294eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf 29544d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 296eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf 297eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graferrout_nomem: 298eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf err = -NLE_NOMEM; 299eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf goto errout; 30044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 30144d362409d5469aed47d19e7908d19bd194493aThomas Graf 3021155370f520cb64657e25153255cf7dc1424317fThomas Grafstatic int addr_request_update(struct nl_cache *cache, struct nl_sock *sk) 30344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 3041155370f520cb64657e25153255cf7dc1424317fThomas Graf return nl_rtgen_request(sk, RTM_GETADDR, AF_UNSPEC, NLM_F_DUMP); 30544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 30644d362409d5469aed47d19e7908d19bd194493aThomas Graf 307d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void addr_dump_line(struct nl_object *obj, struct nl_dump_params *p) 30844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 30944d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_addr *addr = (struct rtnl_addr *) obj; 31044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache *link_cache; 31144d362409d5469aed47d19e7908d19bd194493aThomas Graf char buf[128]; 31244d362409d5469aed47d19e7908d19bd194493aThomas Graf 31344d362409d5469aed47d19e7908d19bd194493aThomas Graf link_cache = nl_cache_mngt_require("route/link"); 31444d362409d5469aed47d19e7908d19bd194493aThomas Graf 31544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr->ce_mask & ADDR_ATTR_LOCAL) 316d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, "%s", 31744d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr2str(addr->a_local, buf, sizeof(buf))); 31844d362409d5469aed47d19e7908d19bd194493aThomas Graf else 319d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, "none"); 32044d362409d5469aed47d19e7908d19bd194493aThomas Graf 32144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr->ce_mask & ADDR_ATTR_PEER) 322d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " peer %s", 32344d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr2str(addr->a_peer, buf, sizeof(buf))); 32444d362409d5469aed47d19e7908d19bd194493aThomas Graf 325d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " %s ", nl_af2str(addr->a_family, buf, sizeof(buf))); 32644d362409d5469aed47d19e7908d19bd194493aThomas Graf 32744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (link_cache) 328d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "dev %s ", 32944d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_link_i2name(link_cache, addr->a_ifindex, 33044d362409d5469aed47d19e7908d19bd194493aThomas Graf buf, sizeof(buf))); 33144d362409d5469aed47d19e7908d19bd194493aThomas Graf else 332d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "dev %d ", addr->a_ifindex); 33344d362409d5469aed47d19e7908d19bd194493aThomas Graf 334d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "scope %s", 33544d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_scope2str(addr->a_scope, buf, sizeof(buf))); 33644d362409d5469aed47d19e7908d19bd194493aThomas Graf 33744d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf)); 33844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (buf[0]) 339d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " <%s>", buf); 34044d362409d5469aed47d19e7908d19bd194493aThomas Graf 341d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "\n"); 34244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 34344d362409d5469aed47d19e7908d19bd194493aThomas Graf 344d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void addr_dump_details(struct nl_object *obj, struct nl_dump_params *p) 34544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 34644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_addr *addr = (struct rtnl_addr *) obj; 34744d362409d5469aed47d19e7908d19bd194493aThomas Graf char buf[128]; 34844d362409d5469aed47d19e7908d19bd194493aThomas Graf 349d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf addr_dump_line(obj, p); 350d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf 35144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr->ce_mask & (ADDR_ATTR_LABEL | ADDR_ATTR_BROADCAST | 3520d925c58069b2d29f17c2bde14192b6f35ccac4dThomas Graf ADDR_ATTR_MULTICAST)) { 353d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, " "); 35444d362409d5469aed47d19e7908d19bd194493aThomas Graf 35544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr->ce_mask & ADDR_ATTR_LABEL) 356d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " label %s", addr->a_label); 35744d362409d5469aed47d19e7908d19bd194493aThomas Graf 35844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr->ce_mask & ADDR_ATTR_BROADCAST) 359d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " broadcast %s", 36044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr2str(addr->a_bcast, buf, sizeof(buf))); 36144d362409d5469aed47d19e7908d19bd194493aThomas Graf 36244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr->ce_mask & ADDR_ATTR_MULTICAST) 363d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " multicast %s", 36444d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr2str(addr->a_multicast, buf, 36544d362409d5469aed47d19e7908d19bd194493aThomas Graf sizeof(buf))); 36644d362409d5469aed47d19e7908d19bd194493aThomas Graf 367f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy if (addr->ce_mask & ADDR_ATTR_ANYCAST) 368f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy nl_dump(p, " anycast %s", 369f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy nl_addr2str(addr->a_anycast, buf, 370f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy sizeof(buf))); 371f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy 372d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "\n"); 37344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 37444d362409d5469aed47d19e7908d19bd194493aThomas Graf 37544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr->ce_mask & ADDR_ATTR_CACHEINFO) { 37644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo; 37744d362409d5469aed47d19e7908d19bd194493aThomas Graf 378d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, " valid-lifetime %s", 37944d362409d5469aed47d19e7908d19bd194493aThomas Graf ci->aci_valid == 0xFFFFFFFFU ? "forever" : 38044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_msec2str(ci->aci_valid * 1000, 38144d362409d5469aed47d19e7908d19bd194493aThomas Graf buf, sizeof(buf))); 38244d362409d5469aed47d19e7908d19bd194493aThomas Graf 383d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " preferred-lifetime %s\n", 38444d362409d5469aed47d19e7908d19bd194493aThomas Graf ci->aci_prefered == 0xFFFFFFFFU ? "forever" : 38544d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_msec2str(ci->aci_prefered * 1000, 38644d362409d5469aed47d19e7908d19bd194493aThomas Graf buf, sizeof(buf))); 38744d362409d5469aed47d19e7908d19bd194493aThomas Graf 388d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, " created boot-time+%s ", 38944d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10, 39044d362409d5469aed47d19e7908d19bd194493aThomas Graf buf, sizeof(buf))); 39144d362409d5469aed47d19e7908d19bd194493aThomas Graf 392d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "last-updated boot-time+%s\n", 39344d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10, 39444d362409d5469aed47d19e7908d19bd194493aThomas Graf buf, sizeof(buf))); 39544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 39644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 39744d362409d5469aed47d19e7908d19bd194493aThomas Graf 398d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p) 39944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 400d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf addr_dump_details(obj, p); 40144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 40244d362409d5469aed47d19e7908d19bd194493aThomas Graf 4030e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardystatic void addr_dump_env(struct nl_object *obj, struct nl_dump_params *p) 4040e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy{ 4050e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy struct rtnl_addr *addr = (struct rtnl_addr *) obj; 4060e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy struct nl_cache *link_cache; 4070e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy char buf[128]; 4080e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4090e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_FAMILY=%s\n", 4100e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_af2str(addr->a_family, buf, sizeof(buf))); 4110e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4120e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy if (addr->ce_mask & ADDR_ATTR_LOCAL) 4130e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_LOCAL=%s\n", 4140e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_addr2str(addr->a_local, buf, sizeof(buf))); 4150e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4160e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy if (addr->ce_mask & ADDR_ATTR_PEER) 4170e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_PEER=%s\n", 4180e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_addr2str(addr->a_peer, buf, sizeof(buf))); 4190e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4200e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy if (addr->ce_mask & ADDR_ATTR_BROADCAST) 4210e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_BROADCAST=%s\n", 4220e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_addr2str(addr->a_bcast, buf, sizeof(buf))); 4230e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4240e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy if (addr->ce_mask & ADDR_ATTR_ANYCAST) 4250e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_ANYCAST=%s\n", 4260e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_addr2str(addr->a_anycast, buf, sizeof(buf))); 4270e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4280e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy if (addr->ce_mask & ADDR_ATTR_MULTICAST) 4290e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_MULTICAST=%s\n", 4300e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_addr2str(addr->a_multicast, buf, 4310e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy sizeof(buf))); 4320e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4330e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy if (addr->ce_mask & ADDR_ATTR_PREFIXLEN) 4340e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_PREFIXLEN=%u\n", 4350e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy addr->a_prefixlen); 4360e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy link_cache = nl_cache_mngt_require("route/link"); 4370e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4380e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_IFINDEX=%u\n", addr->a_ifindex); 4390e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy if (link_cache) 4400e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_IFNAME=%s\n", 4410e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy rtnl_link_i2name(link_cache, addr->a_ifindex, 4420e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy buf, sizeof(buf))); 4430e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4440e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy if (addr->ce_mask & ADDR_ATTR_SCOPE) 4450e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_SCOPE=%s\n", 4460e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy rtnl_scope2str(addr->a_scope, buf, sizeof(buf))); 4470e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4480e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy if (addr->ce_mask & ADDR_ATTR_LABEL) 4490e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_LABEL=%s\n", addr->a_label); 4500e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4510e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf)); 4520e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy if (buf[0]) 4530e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_FLAGS=%s\n", buf); 4540e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4550e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy if (addr->ce_mask & ADDR_ATTR_CACHEINFO) { 4560e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo; 4570e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4580e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_CACHEINFO_VALID=%s\n", 4590e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy ci->aci_valid == 0xFFFFFFFFU ? "forever" : 4600e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_msec2str(ci->aci_valid * 1000, 4610e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy buf, sizeof(buf))); 4620e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4630e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_CACHEINFO_PREFERED=%s\n", 4640e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy ci->aci_prefered == 0xFFFFFFFFU ? "forever" : 4650e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_msec2str(ci->aci_prefered * 1000, 4660e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy buf, sizeof(buf))); 4670e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4680e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_CACHEINFO_CREATED=%s\n", 4690e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10, 4700e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy buf, sizeof(buf))); 4710e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 4720e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_dump_line(p, "ADDR_CACHEINFO_LASTUPDATE=%s\n", 4730e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10, 4740e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy buf, sizeof(buf))); 4750e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy } 4760e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy} 4770e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy 47844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int addr_compare(struct nl_object *_a, struct nl_object *_b, 47944d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t attrs, int flags) 48044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 48144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_addr *a = (struct rtnl_addr *) _a; 48244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_addr *b = (struct rtnl_addr *) _b; 48344d362409d5469aed47d19e7908d19bd194493aThomas Graf int diff = 0; 48444d362409d5469aed47d19e7908d19bd194493aThomas Graf 48544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define ADDR_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ADDR_ATTR_##ATTR, a, b, EXPR) 48644d362409d5469aed47d19e7908d19bd194493aThomas Graf 48744d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= ADDR_DIFF(IFINDEX, a->a_ifindex != b->a_ifindex); 48844d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= ADDR_DIFF(FAMILY, a->a_family != b->a_family); 48944d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= ADDR_DIFF(SCOPE, a->a_scope != b->a_scope); 49044d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= ADDR_DIFF(LABEL, strcmp(a->a_label, b->a_label)); 49144d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= ADDR_DIFF(PEER, nl_addr_cmp(a->a_peer, b->a_peer)); 49244d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= ADDR_DIFF(LOCAL, nl_addr_cmp(a->a_local, b->a_local)); 49344d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= ADDR_DIFF(MULTICAST, nl_addr_cmp(a->a_multicast, 49444d362409d5469aed47d19e7908d19bd194493aThomas Graf b->a_multicast)); 49544d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= ADDR_DIFF(BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast)); 496f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy diff |= ADDR_DIFF(ANYCAST, nl_addr_cmp(a->a_anycast, b->a_anycast)); 49744d362409d5469aed47d19e7908d19bd194493aThomas Graf 498535e83162249ed6274ba46bc72d8cc683ba20e17Thomas Graf if (flags & LOOSE_COMPARISON) 49944d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= ADDR_DIFF(FLAGS, 50044d362409d5469aed47d19e7908d19bd194493aThomas Graf (a->a_flags ^ b->a_flags) & b->a_flag_mask); 50144d362409d5469aed47d19e7908d19bd194493aThomas Graf else 50244d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= ADDR_DIFF(FLAGS, a->a_flags != b->a_flags); 50344d362409d5469aed47d19e7908d19bd194493aThomas Graf 50444d362409d5469aed47d19e7908d19bd194493aThomas Graf#undef ADDR_DIFF 50544d362409d5469aed47d19e7908d19bd194493aThomas Graf 50644d362409d5469aed47d19e7908d19bd194493aThomas Graf return diff; 50744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 50844d362409d5469aed47d19e7908d19bd194493aThomas Graf 50944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct trans_tbl addr_attrs[] = { 51044d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(ADDR_ATTR_FAMILY, family) 51144d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(ADDR_ATTR_PREFIXLEN, prefixlen) 51244d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(ADDR_ATTR_FLAGS, flags) 51344d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(ADDR_ATTR_SCOPE, scope) 51444d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(ADDR_ATTR_IFINDEX, ifindex) 51544d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(ADDR_ATTR_LABEL, label) 51644d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(ADDR_ATTR_CACHEINFO, cacheinfo) 51744d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(ADDR_ATTR_PEER, peer) 51844d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(ADDR_ATTR_LOCAL, local) 51944d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(ADDR_ATTR_BROADCAST, broadcast) 52044d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(ADDR_ATTR_MULTICAST, multicast) 52144d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 52244d362409d5469aed47d19e7908d19bd194493aThomas Graf 52344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic char *addr_attrs2str(int attrs, char *buf, size_t len) 52444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 52544d362409d5469aed47d19e7908d19bd194493aThomas Graf return __flags2str(attrs, buf, len, addr_attrs, 52644d362409d5469aed47d19e7908d19bd194493aThomas Graf ARRAY_SIZE(addr_attrs)); 52744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 52844d362409d5469aed47d19e7908d19bd194493aThomas Graf 52944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 53044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Allocation/Freeing 53144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 53244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 53344d362409d5469aed47d19e7908d19bd194493aThomas Graf 53444d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct rtnl_addr *rtnl_addr_alloc(void) 53544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 53644d362409d5469aed47d19e7908d19bd194493aThomas Graf return (struct rtnl_addr *) nl_object_alloc(&addr_obj_ops); 53744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 53844d362409d5469aed47d19e7908d19bd194493aThomas Graf 53944d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_addr_put(struct rtnl_addr *addr) 54044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 54144d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_object_put((struct nl_object *) addr); 54244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 54344d362409d5469aed47d19e7908d19bd194493aThomas Graf 54444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 54544d362409d5469aed47d19e7908d19bd194493aThomas Graf 54644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 54744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Cache Management 54844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 54944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 55044d362409d5469aed47d19e7908d19bd194493aThomas Graf 5511155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_addr_alloc_cache(struct nl_sock *sk, struct nl_cache **result) 55244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 5531155370f520cb64657e25153255cf7dc1424317fThomas Graf return nl_cache_alloc_and_fill(&rtnl_addr_ops, sk, result); 55444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 55544d362409d5469aed47d19e7908d19bd194493aThomas Graf 55644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 55744d362409d5469aed47d19e7908d19bd194493aThomas Graf 5588a3efffa5b3fde252675239914118664d36a2c24Thomas Grafstatic int build_addr_msg(struct rtnl_addr *tmpl, int cmd, int flags, 5598a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 56044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 56144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *msg; 56244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct ifaddrmsg am = { 56344d362409d5469aed47d19e7908d19bd194493aThomas Graf .ifa_family = tmpl->a_family, 56444d362409d5469aed47d19e7908d19bd194493aThomas Graf .ifa_index = tmpl->a_ifindex, 56544d362409d5469aed47d19e7908d19bd194493aThomas Graf .ifa_prefixlen = tmpl->a_prefixlen, 56644d362409d5469aed47d19e7908d19bd194493aThomas Graf }; 56744d362409d5469aed47d19e7908d19bd194493aThomas Graf 56844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tmpl->ce_mask & ADDR_ATTR_SCOPE) 56944d362409d5469aed47d19e7908d19bd194493aThomas Graf am.ifa_scope = tmpl->a_scope; 57044d362409d5469aed47d19e7908d19bd194493aThomas Graf else { 57144d362409d5469aed47d19e7908d19bd194493aThomas Graf /* compatibility hack */ 57244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tmpl->a_family == AF_INET && 57344d362409d5469aed47d19e7908d19bd194493aThomas Graf tmpl->ce_mask & ADDR_ATTR_LOCAL && 57444d362409d5469aed47d19e7908d19bd194493aThomas Graf *((char *) nl_addr_get_binary_addr(tmpl->a_local)) == 127) 57544d362409d5469aed47d19e7908d19bd194493aThomas Graf am.ifa_scope = RT_SCOPE_HOST; 57644d362409d5469aed47d19e7908d19bd194493aThomas Graf else 57744d362409d5469aed47d19e7908d19bd194493aThomas Graf am.ifa_scope = RT_SCOPE_UNIVERSE; 57844d362409d5469aed47d19e7908d19bd194493aThomas Graf } 57944d362409d5469aed47d19e7908d19bd194493aThomas Graf 58044d362409d5469aed47d19e7908d19bd194493aThomas Graf msg = nlmsg_alloc_simple(cmd, flags); 58144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!msg) 5828a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 58344d362409d5469aed47d19e7908d19bd194493aThomas Graf 58444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (nlmsg_append(msg, &am, sizeof(am), NLMSG_ALIGNTO) < 0) 58544d362409d5469aed47d19e7908d19bd194493aThomas Graf goto nla_put_failure; 58644d362409d5469aed47d19e7908d19bd194493aThomas Graf 58744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tmpl->ce_mask & ADDR_ATTR_LOCAL) 58844d362409d5469aed47d19e7908d19bd194493aThomas Graf NLA_PUT_ADDR(msg, IFA_LOCAL, tmpl->a_local); 58944d362409d5469aed47d19e7908d19bd194493aThomas Graf 59044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tmpl->ce_mask & ADDR_ATTR_PEER) 59144d362409d5469aed47d19e7908d19bd194493aThomas Graf NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_peer); 5925702d4c1b97616f5212da31db01a2f3c79c15b7cWolfgang Steudel else if (tmpl->ce_mask & ADDR_ATTR_LOCAL) 59344d362409d5469aed47d19e7908d19bd194493aThomas Graf NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_local); 59444d362409d5469aed47d19e7908d19bd194493aThomas Graf 59544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tmpl->ce_mask & ADDR_ATTR_LABEL) 59644d362409d5469aed47d19e7908d19bd194493aThomas Graf NLA_PUT_STRING(msg, IFA_LABEL, tmpl->a_label); 59744d362409d5469aed47d19e7908d19bd194493aThomas Graf 59844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tmpl->ce_mask & ADDR_ATTR_BROADCAST) 59944d362409d5469aed47d19e7908d19bd194493aThomas Graf NLA_PUT_ADDR(msg, IFA_BROADCAST, tmpl->a_bcast); 60044d362409d5469aed47d19e7908d19bd194493aThomas Graf 601ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf if (tmpl->ce_mask & ADDR_ATTR_CACHEINFO) { 602ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf struct ifa_cacheinfo ca = { 603ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf .ifa_valid = tmpl->a_cacheinfo.aci_valid, 604ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf .ifa_prefered = tmpl->a_cacheinfo.aci_prefered, 605ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf }; 606ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf 607ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf NLA_PUT(msg, IFA_CACHEINFO, sizeof(ca), &ca); 608ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf } 609ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf 610ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf 6118a3efffa5b3fde252675239914118664d36a2c24Thomas Graf *result = msg; 6128a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return 0; 61344d362409d5469aed47d19e7908d19bd194493aThomas Graf 61444d362409d5469aed47d19e7908d19bd194493aThomas Grafnla_put_failure: 61544d362409d5469aed47d19e7908d19bd194493aThomas Graf nlmsg_free(msg); 6168a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MSGSIZE; 61744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 61844d362409d5469aed47d19e7908d19bd194493aThomas Graf 61944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 62044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Addition 62144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 62244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 62344d362409d5469aed47d19e7908d19bd194493aThomas Graf 62444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 62544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Build netlink request message to request addition of new address 62644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Address object representing the new address. 62744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags Additional netlink message flags. 6288a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @arg result Pointer to store resulting message. 62944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 63044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a new netlink message requesting the addition of a new 63144d362409d5469aed47d19e7908d19bd194493aThomas Graf * address. The netlink message header isn't fully equipped with 63244d362409d5469aed47d19e7908d19bd194493aThomas Graf * all relevant fields and must thus be sent out via nl_send_auto_complete() 63344d362409d5469aed47d19e7908d19bd194493aThomas Graf * or supplemented as needed. 63444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 63544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Minimal required attributes: 63644d362409d5469aed47d19e7908d19bd194493aThomas Graf * - interface index (rtnl_addr_set_ifindex()) 63744d362409d5469aed47d19e7908d19bd194493aThomas Graf * - local address (rtnl_addr_set_local()) 63844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 63944d362409d5469aed47d19e7908d19bd194493aThomas Graf * The scope will default to universe except for loopback addresses in 64044d362409d5469aed47d19e7908d19bd194493aThomas Graf * which case a host scope is used if not specified otherwise. 64144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 64244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @note Free the memory after usage using nlmsg_free(). 6438a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * 6448a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @return 0 on success or a negative error code. 64544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 6468a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags, 6478a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 64844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 64944d362409d5469aed47d19e7908d19bd194493aThomas Graf int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY | 65044d362409d5469aed47d19e7908d19bd194493aThomas Graf ADDR_ATTR_PREFIXLEN | ADDR_ATTR_LOCAL; 65144d362409d5469aed47d19e7908d19bd194493aThomas Graf 6528a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((addr->ce_mask & required) != required) 6538a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MISSING_ATTR; 65444d362409d5469aed47d19e7908d19bd194493aThomas Graf 6558a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return build_addr_msg(addr, RTM_NEWADDR, NLM_F_CREATE | flags, result); 65644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 65744d362409d5469aed47d19e7908d19bd194493aThomas Graf 65844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 65944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Request addition of new address 6601155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 66144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Address object representing the new address. 66244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags Additional netlink message flags. 66344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 66444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a netlink message by calling rtnl_addr_build_add_request(), 66544d362409d5469aed47d19e7908d19bd194493aThomas Graf * sends the request to the kernel and waits for the next ACK to be 66644d362409d5469aed47d19e7908d19bd194493aThomas Graf * received and thus blocks until the request has been fullfilled. 66744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 66844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @see rtnl_addr_build_add_request() 66944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 67044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on sucess or a negative error if an error occured. 67144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 6721155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_addr_add(struct nl_sock *sk, struct rtnl_addr *addr, int flags) 67344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 67444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *msg; 67544d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 67644d362409d5469aed47d19e7908d19bd194493aThomas Graf 6778a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((err = rtnl_addr_build_add_request(addr, flags, &msg)) < 0) 6788a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 67944d362409d5469aed47d19e7908d19bd194493aThomas Graf 6801155370f520cb64657e25153255cf7dc1424317fThomas Graf err = nl_send_auto_complete(sk, msg); 68144d362409d5469aed47d19e7908d19bd194493aThomas Graf nlmsg_free(msg); 68244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 68344d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 68444d362409d5469aed47d19e7908d19bd194493aThomas Graf 685cfcfca070355b246028df60da79813f09ed65755Thomas Graf return wait_for_ack(sk); 68644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 68744d362409d5469aed47d19e7908d19bd194493aThomas Graf 68844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 68944d362409d5469aed47d19e7908d19bd194493aThomas Graf 69044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 69144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Deletion 69244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 69344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 69444d362409d5469aed47d19e7908d19bd194493aThomas Graf 69544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 69644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Build a netlink request message to request deletion of an address 69744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Address object to be deleteted. 69844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags Additional netlink message flags. 6998a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @arg result Pointer to store resulting message. 70044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 70144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a new netlink message requesting a deletion of an address. 70244d362409d5469aed47d19e7908d19bd194493aThomas Graf * The netlink message header isn't fully equipped with all relevant 70344d362409d5469aed47d19e7908d19bd194493aThomas Graf * fields and must thus be sent out via nl_send_auto_complete() 70444d362409d5469aed47d19e7908d19bd194493aThomas Graf * or supplemented as needed. 70544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 70644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Minimal required attributes: 70744d362409d5469aed47d19e7908d19bd194493aThomas Graf * - interface index (rtnl_addr_set_ifindex()) 70844d362409d5469aed47d19e7908d19bd194493aThomas Graf * - address family (rtnl_addr_set_family()) 70944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 71044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Optional attributes: 71144d362409d5469aed47d19e7908d19bd194493aThomas Graf * - local address (rtnl_addr_set_local()) 71244d362409d5469aed47d19e7908d19bd194493aThomas Graf * - label (rtnl_addr_set_label(), IPv4/DECnet only) 71344d362409d5469aed47d19e7908d19bd194493aThomas Graf * - peer address (rtnl_addr_set_peer(), IPv4 only) 71444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 71544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @note Free the memory after usage using nlmsg_free(). 7168a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * 7178a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @return 0 on success or a negative error code. 71844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 7198a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint rtnl_addr_build_delete_request(struct rtnl_addr *addr, int flags, 7208a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 72144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 72244d362409d5469aed47d19e7908d19bd194493aThomas Graf int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY; 72344d362409d5469aed47d19e7908d19bd194493aThomas Graf 7248a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((addr->ce_mask & required) != required) 7258a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MISSING_ATTR; 7268a3efffa5b3fde252675239914118664d36a2c24Thomas Graf 7278a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return build_addr_msg(addr, RTM_DELADDR, flags, result); 72844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 72944d362409d5469aed47d19e7908d19bd194493aThomas Graf 73044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 73144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Request deletion of an address 7321155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 73344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg addr Address object to be deleted. 73444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags Additional netlink message flags. 73544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 73644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a netlink message by calling rtnl_addr_build_delete_request(), 73744d362409d5469aed47d19e7908d19bd194493aThomas Graf * sends the request to the kernel and waits for the next ACK to be 73844d362409d5469aed47d19e7908d19bd194493aThomas Graf * received and thus blocks until the request has been fullfilled. 73944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 74044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @see rtnl_addr_build_delete_request(); 74144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 74244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on sucess or a negative error if an error occured. 74344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 7441155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_addr_delete(struct nl_sock *sk, struct rtnl_addr *addr, int flags) 74544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 74644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *msg; 74744d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 74844d362409d5469aed47d19e7908d19bd194493aThomas Graf 7498a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((err = rtnl_addr_build_delete_request(addr, flags, &msg)) < 0) 7508a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 75144d362409d5469aed47d19e7908d19bd194493aThomas Graf 7521155370f520cb64657e25153255cf7dc1424317fThomas Graf err = nl_send_auto_complete(sk, msg); 75344d362409d5469aed47d19e7908d19bd194493aThomas Graf nlmsg_free(msg); 75444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 75544d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 75644d362409d5469aed47d19e7908d19bd194493aThomas Graf 757cfcfca070355b246028df60da79813f09ed65755Thomas Graf return wait_for_ack(sk); 75844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 75944d362409d5469aed47d19e7908d19bd194493aThomas Graf 76044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 76144d362409d5469aed47d19e7908d19bd194493aThomas Graf 76244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 76344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Attributes 76444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 76544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 76644d362409d5469aed47d19e7908d19bd194493aThomas Graf 7670cf780859cbce363a6e2cd4b8d19c5498a3530f5Thomas Grafint rtnl_addr_set_label(struct rtnl_addr *addr, const char *label) 76844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 7690cf780859cbce363a6e2cd4b8d19c5498a3530f5Thomas Graf if (strlen(label) > sizeof(addr->a_label) - 1) 7700cf780859cbce363a6e2cd4b8d19c5498a3530f5Thomas Graf return -NLE_RANGE; 7710cf780859cbce363a6e2cd4b8d19c5498a3530f5Thomas Graf 7720cf780859cbce363a6e2cd4b8d19c5498a3530f5Thomas Graf strcpy(addr->a_label, label); 77344d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_LABEL; 7740cf780859cbce363a6e2cd4b8d19c5498a3530f5Thomas Graf 7750cf780859cbce363a6e2cd4b8d19c5498a3530f5Thomas Graf return 0; 77644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 77744d362409d5469aed47d19e7908d19bd194493aThomas Graf 77844d362409d5469aed47d19e7908d19bd194493aThomas Grafchar *rtnl_addr_get_label(struct rtnl_addr *addr) 77944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 78044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr->ce_mask & ADDR_ATTR_LABEL) 78144d362409d5469aed47d19e7908d19bd194493aThomas Graf return addr->a_label; 78244d362409d5469aed47d19e7908d19bd194493aThomas Graf else 78344d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 78444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 78544d362409d5469aed47d19e7908d19bd194493aThomas Graf 78644d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_addr_set_ifindex(struct rtnl_addr *addr, int ifindex) 78744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 78844d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_ifindex = ifindex; 78944d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_IFINDEX; 79044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 79144d362409d5469aed47d19e7908d19bd194493aThomas Graf 79244d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_addr_get_ifindex(struct rtnl_addr *addr) 79344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 794b4fbe1d34d6f54045b5c6236d86aacd4340ec83dThomas Graf return addr->a_ifindex; 79544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 79644d362409d5469aed47d19e7908d19bd194493aThomas Graf 79744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_addr_set_family(struct rtnl_addr *addr, int family) 79844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 79944d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_family = family; 80044d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_FAMILY; 80144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 80244d362409d5469aed47d19e7908d19bd194493aThomas Graf 80344d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_addr_get_family(struct rtnl_addr *addr) 80444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 805b4fbe1d34d6f54045b5c6236d86aacd4340ec83dThomas Graf return addr->a_family; 80644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 80744d362409d5469aed47d19e7908d19bd194493aThomas Graf 80844d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefix) 80944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 81044d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_prefixlen = prefix; 81144d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_PREFIXLEN; 81244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 81344d362409d5469aed47d19e7908d19bd194493aThomas Graf 81444d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_addr_get_prefixlen(struct rtnl_addr *addr) 81544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 816ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf return addr->a_prefixlen; 81744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 81844d362409d5469aed47d19e7908d19bd194493aThomas Graf 81944d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_addr_set_scope(struct rtnl_addr *addr, int scope) 82044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 82144d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_scope = scope; 82244d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_SCOPE; 82344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 82444d362409d5469aed47d19e7908d19bd194493aThomas Graf 82544d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_addr_get_scope(struct rtnl_addr *addr) 82644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 827ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf return addr->a_scope; 82844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 82944d362409d5469aed47d19e7908d19bd194493aThomas Graf 83044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_addr_set_flags(struct rtnl_addr *addr, unsigned int flags) 83144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 83244d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_flag_mask |= flags; 83344d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_flags |= flags; 83444d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_FLAGS; 83544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 83644d362409d5469aed47d19e7908d19bd194493aThomas Graf 83744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_addr_unset_flags(struct rtnl_addr *addr, unsigned int flags) 83844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 83944d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_flag_mask |= flags; 84044d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_flags &= ~flags; 84144d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_FLAGS; 84244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 84344d362409d5469aed47d19e7908d19bd194493aThomas Graf 84444d362409d5469aed47d19e7908d19bd194493aThomas Grafunsigned int rtnl_addr_get_flags(struct rtnl_addr *addr) 84544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 84644d362409d5469aed47d19e7908d19bd194493aThomas Graf return addr->a_flags; 84744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 84844d362409d5469aed47d19e7908d19bd194493aThomas Graf 84944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline int __assign_addr(struct rtnl_addr *addr, struct nl_addr **pos, 85044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_addr *new, int flag) 85144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 85244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr->ce_mask & ADDR_ATTR_FAMILY) { 85344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (new->a_family != addr->a_family) 8548a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_AF_MISMATCH; 85544d362409d5469aed47d19e7908d19bd194493aThomas Graf } else 85644d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_family = new->a_family; 85744d362409d5469aed47d19e7908d19bd194493aThomas Graf 85844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (*pos) 85944d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(*pos); 86044d362409d5469aed47d19e7908d19bd194493aThomas Graf 86144d362409d5469aed47d19e7908d19bd194493aThomas Graf *pos = nl_addr_get(new); 86244d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= (flag | ADDR_ATTR_FAMILY); 86344d362409d5469aed47d19e7908d19bd194493aThomas Graf 86444d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 86544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 86644d362409d5469aed47d19e7908d19bd194493aThomas Graf 86744d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_addr_set_local(struct rtnl_addr *addr, struct nl_addr *local) 86844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 86944d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 87044d362409d5469aed47d19e7908d19bd194493aThomas Graf 87144d362409d5469aed47d19e7908d19bd194493aThomas Graf err = __assign_addr(addr, &addr->a_local, local, ADDR_ATTR_LOCAL); 87244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 87344d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 87444d362409d5469aed47d19e7908d19bd194493aThomas Graf 87544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!(addr->ce_mask & ADDR_ATTR_PEER)) { 87644d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_local); 87744d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_PREFIXLEN; 87844d362409d5469aed47d19e7908d19bd194493aThomas Graf } 87944d362409d5469aed47d19e7908d19bd194493aThomas Graf 88044d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 88144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 88244d362409d5469aed47d19e7908d19bd194493aThomas Graf 88344d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr) 88444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 885ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf return addr->a_local; 88644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 88744d362409d5469aed47d19e7908d19bd194493aThomas Graf 88844d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_addr_set_peer(struct rtnl_addr *addr, struct nl_addr *peer) 88944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 89044d362409d5469aed47d19e7908d19bd194493aThomas Graf return __assign_addr(addr, &addr->a_peer, peer, ADDR_ATTR_PEER); 89144d362409d5469aed47d19e7908d19bd194493aThomas Graf 89244d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_peer); 89344d362409d5469aed47d19e7908d19bd194493aThomas Graf addr->ce_mask |= ADDR_ATTR_PREFIXLEN; 89444d362409d5469aed47d19e7908d19bd194493aThomas Graf 89544d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 89644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 89744d362409d5469aed47d19e7908d19bd194493aThomas Graf 89844d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr) 89944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 900ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf return addr->a_peer; 90144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 90244d362409d5469aed47d19e7908d19bd194493aThomas Graf 90344d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_addr_set_broadcast(struct rtnl_addr *addr, struct nl_addr *bcast) 90444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 90544d362409d5469aed47d19e7908d19bd194493aThomas Graf return __assign_addr(addr, &addr->a_bcast, bcast, ADDR_ATTR_BROADCAST); 90644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 90744d362409d5469aed47d19e7908d19bd194493aThomas Graf 90844d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *addr) 90944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 910ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf return addr->a_bcast; 91144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 91244d362409d5469aed47d19e7908d19bd194493aThomas Graf 91344d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_addr_set_multicast(struct rtnl_addr *addr, struct nl_addr *multicast) 91444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 91544d362409d5469aed47d19e7908d19bd194493aThomas Graf return __assign_addr(addr, &addr->a_multicast, multicast, 91644d362409d5469aed47d19e7908d19bd194493aThomas Graf ADDR_ATTR_MULTICAST); 91744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 91844d362409d5469aed47d19e7908d19bd194493aThomas Graf 91944d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr) 92044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 921ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf return addr->a_multicast; 922ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf} 923ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf 924f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardyint rtnl_addr_set_anycast(struct rtnl_addr *addr, struct nl_addr *anycast) 925f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy{ 926f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy return __assign_addr(addr, &addr->a_anycast, anycast, 927f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy ADDR_ATTR_ANYCAST); 928f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy} 929f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy 930f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardystruct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *addr) 931f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy{ 932f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy return addr->a_anycast; 933f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy} 934f5f49c224835c555df9e2c1f79ac5adf4640f4a8Patrick McHardy 935ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Grafuint32_t rtnl_addr_get_valid_lifetime(struct rtnl_addr *addr) 936ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf{ 937ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf if (addr->ce_mask & ADDR_ATTR_CACHEINFO) 938ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf return addr->a_cacheinfo.aci_valid; 93944d362409d5469aed47d19e7908d19bd194493aThomas Graf else 940ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf return 0xFFFFFFFFU; 941ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf} 942ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf 943ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Grafvoid rtnl_addr_set_valid_lifetime(struct rtnl_addr *addr, uint32_t lifetime) 944ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf{ 945ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf addr->a_cacheinfo.aci_valid = lifetime; 946ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf addr->ce_mask |= ADDR_ATTR_CACHEINFO; 947ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf} 948ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf 949ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Grafuint32_t rtnl_addr_get_preferred_lifetime(struct rtnl_addr *addr) 950ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf{ 951ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf if (addr->ce_mask & ADDR_ATTR_CACHEINFO) 952ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf return addr->a_cacheinfo.aci_prefered; 953ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf else 954ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf return 0xFFFFFFFFU; 955ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf} 956ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf 957ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Grafvoid rtnl_addr_set_preferred_lifetime(struct rtnl_addr *addr, uint32_t lifetime) 958ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf{ 959ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf addr->a_cacheinfo.aci_prefered = lifetime; 960ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf addr->ce_mask |= ADDR_ATTR_CACHEINFO; 961ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf} 962ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf 963ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Grafuint32_t rtnl_addr_get_create_time(struct rtnl_addr *addr) 964ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf{ 965ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf return addr->a_cacheinfo.aci_cstamp; 966ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf} 967ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf 968ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Grafuint32_t rtnl_addr_get_last_update_time(struct rtnl_addr *addr) 969ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf{ 970ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf return addr->a_cacheinfo.aci_tstamp; 97144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 97244d362409d5469aed47d19e7908d19bd194493aThomas Graf 97344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 97444d362409d5469aed47d19e7908d19bd194493aThomas Graf 97544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 97644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Flags Translations 97744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 97844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 97944d362409d5469aed47d19e7908d19bd194493aThomas Graf 98044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct trans_tbl addr_flags[] = { 98144d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(IFA_F_SECONDARY, secondary) 982ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf __ADD(IFA_F_NODAD, nodad) 983ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf __ADD(IFA_F_OPTIMISTIC, optimistic) 984ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf __ADD(IFA_F_HOMEADDRESS, homeaddress) 98544d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(IFA_F_DEPRECATED, deprecated) 98644d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(IFA_F_TENTATIVE, tentative) 98744d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(IFA_F_PERMANENT, permanent) 98844d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 98944d362409d5469aed47d19e7908d19bd194493aThomas Graf 99044d362409d5469aed47d19e7908d19bd194493aThomas Grafchar *rtnl_addr_flags2str(int flags, char *buf, size_t size) 99144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 99244d362409d5469aed47d19e7908d19bd194493aThomas Graf return __flags2str(flags, buf, size, addr_flags, 99344d362409d5469aed47d19e7908d19bd194493aThomas Graf ARRAY_SIZE(addr_flags)); 99444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 99544d362409d5469aed47d19e7908d19bd194493aThomas Graf 99644d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_addr_str2flags(const char *name) 99744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 99844d362409d5469aed47d19e7908d19bd194493aThomas Graf return __str2flags(name, addr_flags, ARRAY_SIZE(addr_flags)); 99944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 100044d362409d5469aed47d19e7908d19bd194493aThomas Graf 100144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 100244d362409d5469aed47d19e7908d19bd194493aThomas Graf 100344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_object_ops addr_obj_ops = { 100444d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_name = "route/addr", 100544d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_size = sizeof(struct rtnl_addr), 1006ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf .oo_constructor = addr_constructor, 100744d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_free_data = addr_free_data, 100844d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_clone = addr_clone, 1009d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf .oo_dump = { 1010d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_LINE] = addr_dump_line, 1011d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_DETAILS] = addr_dump_details, 1012d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_STATS] = addr_dump_stats, 10130e4f54d288b8d1d06ee40122d6bf3ed971870d47Patrick McHardy [NL_DUMP_ENV] = addr_dump_env, 1014d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf }, 101544d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_compare = addr_compare, 101644d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_attrs2str = addr_attrs2str, 101744d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_id_attrs = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX | 1018e0af9e1802d4f0c49e838ff94a187f590eb9e2cdDan Winship ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN), 101944d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 102044d362409d5469aed47d19e7908d19bd194493aThomas Graf 102144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_af_group addr_groups[] = { 102244d362409d5469aed47d19e7908d19bd194493aThomas Graf { AF_INET, RTNLGRP_IPV4_IFADDR }, 102344d362409d5469aed47d19e7908d19bd194493aThomas Graf { AF_INET6, RTNLGRP_IPV6_IFADDR }, 102444d362409d5469aed47d19e7908d19bd194493aThomas Graf { END_OF_GROUP_LIST }, 102544d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 102644d362409d5469aed47d19e7908d19bd194493aThomas Graf 102744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops rtnl_addr_ops = { 102844d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_name = "route/addr", 102944d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_hdrsize = sizeof(struct ifaddrmsg), 103044d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_msgtypes = { 103144d362409d5469aed47d19e7908d19bd194493aThomas Graf { RTM_NEWADDR, NL_ACT_NEW, "new" }, 103244d362409d5469aed47d19e7908d19bd194493aThomas Graf { RTM_DELADDR, NL_ACT_DEL, "del" }, 103344d362409d5469aed47d19e7908d19bd194493aThomas Graf { RTM_GETADDR, NL_ACT_GET, "get" }, 103444d362409d5469aed47d19e7908d19bd194493aThomas Graf END_OF_MSGTYPES_LIST, 103544d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 103644d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_protocol = NETLINK_ROUTE, 103744d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_groups = addr_groups, 103844d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_request_update = addr_request_update, 103944d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_msg_parser = addr_msg_parser, 104044d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_obj_ops = &addr_obj_ops, 104144d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 104244d362409d5469aed47d19e7908d19bd194493aThomas Graf 104344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __init addr_init(void) 104444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 104544d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cache_mngt_register(&rtnl_addr_ops); 104644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 104744d362409d5469aed47d19e7908d19bd194493aThomas Graf 104844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __exit addr_exit(void) 104944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 105044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cache_mngt_unregister(&rtnl_addr_ops); 105144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 105244d362409d5469aed47d19e7908d19bd194493aThomas Graf 105344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 1054