1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker * Copyright (c) 2003-2012 Thomas Graf <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker * Copyright (c) 2003-2006 Baruch Even <[email protected]>
5*4dc78e53SAndroid Build Coastguard Worker * Copyright (c) 2003-2006 Mediatrix Telecom, inc. <[email protected]>
6*4dc78e53SAndroid Build Coastguard Worker */
7*4dc78e53SAndroid Build Coastguard Worker
8*4dc78e53SAndroid Build Coastguard Worker /**
9*4dc78e53SAndroid Build Coastguard Worker * @ingroup rtnl
10*4dc78e53SAndroid Build Coastguard Worker * @defgroup rtaddr Addresses
11*4dc78e53SAndroid Build Coastguard Worker * @brief
12*4dc78e53SAndroid Build Coastguard Worker *
13*4dc78e53SAndroid Build Coastguard Worker * @note The maximum size of an address label is IFNAMSIZ.
14*4dc78e53SAndroid Build Coastguard Worker *
15*4dc78e53SAndroid Build Coastguard Worker * @note The address may not contain a prefix length if the peer address
16*4dc78e53SAndroid Build Coastguard Worker * has been specified already.
17*4dc78e53SAndroid Build Coastguard Worker *
18*4dc78e53SAndroid Build Coastguard Worker * @par 1) Address Addition
19*4dc78e53SAndroid Build Coastguard Worker * @code
20*4dc78e53SAndroid Build Coastguard Worker * // Allocate an empty address object to be filled out with the attributes
21*4dc78e53SAndroid Build Coastguard Worker * // of the new address.
22*4dc78e53SAndroid Build Coastguard Worker * struct rtnl_addr *addr = rtnl_addr_alloc();
23*4dc78e53SAndroid Build Coastguard Worker *
24*4dc78e53SAndroid Build Coastguard Worker * // Fill out the mandatory attributes of the new address. Setting the
25*4dc78e53SAndroid Build Coastguard Worker * // local address will automatically set the address family and the
26*4dc78e53SAndroid Build Coastguard Worker * // prefix length to the correct values.
27*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_set_ifindex(addr, ifindex);
28*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_set_local(addr, local_addr);
29*4dc78e53SAndroid Build Coastguard Worker *
30*4dc78e53SAndroid Build Coastguard Worker * // The label of the address can be specified, currently only supported
31*4dc78e53SAndroid Build Coastguard Worker * // by IPv4 and DECnet.
32*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_set_label(addr, "mylabel");
33*4dc78e53SAndroid Build Coastguard Worker *
34*4dc78e53SAndroid Build Coastguard Worker * // The peer address can be specified if necessary, in either case a peer
35*4dc78e53SAndroid Build Coastguard Worker * // address will be sent to the kernel in order to fullfil the interface
36*4dc78e53SAndroid Build Coastguard Worker * // requirements. If none is set, it will equal the local address.
37*4dc78e53SAndroid Build Coastguard Worker * // Note: Real peer addresses are only supported by IPv4 for now.
38*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_set_peer(addr, peer_addr);
39*4dc78e53SAndroid Build Coastguard Worker *
40*4dc78e53SAndroid Build Coastguard Worker * // In case you want to have the address have a scope other than global
41*4dc78e53SAndroid Build Coastguard Worker * // it may be overwritten using rtnl_addr_set_scope(). The scope currently
42*4dc78e53SAndroid Build Coastguard Worker * // cannot be set for IPv6 addresses.
43*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_set_scope(addr, rtnl_str2scope("site"));
44*4dc78e53SAndroid Build Coastguard Worker *
45*4dc78e53SAndroid Build Coastguard Worker * // Broadcast address may be specified using the relevant
46*4dc78e53SAndroid Build Coastguard Worker * // functions, the address family will be verified if one of the other
47*4dc78e53SAndroid Build Coastguard Worker * // addresses has been set already. Currently only works for IPv4.
48*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_set_broadcast(addr, broadcast_addr);
49*4dc78e53SAndroid Build Coastguard Worker *
50*4dc78e53SAndroid Build Coastguard Worker * // Build the netlink message and send it to the kernel, the operation will
51*4dc78e53SAndroid Build Coastguard Worker * // block until the operation has been completed. Alternatively the required
52*4dc78e53SAndroid Build Coastguard Worker * // netlink message can be built using rtnl_addr_build_add_request() to be
53*4dc78e53SAndroid Build Coastguard Worker * // sent out using nl_send_auto_complete().
54*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_add(sk, addr, 0);
55*4dc78e53SAndroid Build Coastguard Worker *
56*4dc78e53SAndroid Build Coastguard Worker * // Free the memory
57*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_put(addr);
58*4dc78e53SAndroid Build Coastguard Worker * @endcode
59*4dc78e53SAndroid Build Coastguard Worker *
60*4dc78e53SAndroid Build Coastguard Worker * @par 2) Address Deletion
61*4dc78e53SAndroid Build Coastguard Worker * @code
62*4dc78e53SAndroid Build Coastguard Worker * // Allocate an empty address object to be filled out with the attributes
63*4dc78e53SAndroid Build Coastguard Worker * // matching the address to be deleted. Alternatively a fully equipped
64*4dc78e53SAndroid Build Coastguard Worker * // address object out of a cache can be used instead.
65*4dc78e53SAndroid Build Coastguard Worker * struct rtnl_addr *addr = rtnl_addr_alloc();
66*4dc78e53SAndroid Build Coastguard Worker *
67*4dc78e53SAndroid Build Coastguard Worker * // The only mandatory parameter besides the address family is the interface
68*4dc78e53SAndroid Build Coastguard Worker * // index the address is on, i.e. leaving out all other parameters will
69*4dc78e53SAndroid Build Coastguard Worker * // result in all addresses of the specified address family interface tuple
70*4dc78e53SAndroid Build Coastguard Worker * // to be deleted.
71*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_set_ifindex(addr, ifindex);
72*4dc78e53SAndroid Build Coastguard Worker *
73*4dc78e53SAndroid Build Coastguard Worker * // Specyfing the address family manually is only required if neither the
74*4dc78e53SAndroid Build Coastguard Worker * // local nor peer address have been specified.
75*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_set_family(addr, AF_INET);
76*4dc78e53SAndroid Build Coastguard Worker *
77*4dc78e53SAndroid Build Coastguard Worker * // Specyfing the local address is optional but the best choice to delete
78*4dc78e53SAndroid Build Coastguard Worker * // specific addresses.
79*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_set_local(addr, local_addr);
80*4dc78e53SAndroid Build Coastguard Worker *
81*4dc78e53SAndroid Build Coastguard Worker * // The label of the address can be specified, currently only supported
82*4dc78e53SAndroid Build Coastguard Worker * // by IPv4 and DECnet.
83*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_set_label(addr, "mylabel");
84*4dc78e53SAndroid Build Coastguard Worker *
85*4dc78e53SAndroid Build Coastguard Worker * // The peer address can be specified if necessary, in either case a peer
86*4dc78e53SAndroid Build Coastguard Worker * // address will be sent to the kernel in order to fullfil the interface
87*4dc78e53SAndroid Build Coastguard Worker * // requirements. If none is set, it will equal the local address.
88*4dc78e53SAndroid Build Coastguard Worker * // Note: Real peer addresses are only supported by IPv4 for now.
89*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_set_peer(addr, peer_addr);
90*4dc78e53SAndroid Build Coastguard Worker *
91*4dc78e53SAndroid Build Coastguard Worker * // Build the netlink message and send it to the kernel, the operation will
92*4dc78e53SAndroid Build Coastguard Worker * // block until the operation has been completed. Alternatively the required
93*4dc78e53SAndroid Build Coastguard Worker * // netlink message can be built using rtnl_addr_build_delete_request()
94*4dc78e53SAndroid Build Coastguard Worker * // to be sent out using nl_send_auto_complete().
95*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_delete(sk, addr, 0);
96*4dc78e53SAndroid Build Coastguard Worker *
97*4dc78e53SAndroid Build Coastguard Worker * // Free the memory
98*4dc78e53SAndroid Build Coastguard Worker * rtnl_addr_put(addr);
99*4dc78e53SAndroid Build Coastguard Worker * @endcode
100*4dc78e53SAndroid Build Coastguard Worker * @{
101*4dc78e53SAndroid Build Coastguard Worker */
102*4dc78e53SAndroid Build Coastguard Worker
103*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
104*4dc78e53SAndroid Build Coastguard Worker
105*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
106*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/rtnl.h>
107*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/addr.h>
108*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/route.h>
109*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/link.h>
110*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
111*4dc78e53SAndroid Build Coastguard Worker
112*4dc78e53SAndroid Build Coastguard Worker #include "nl-route.h"
113*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/nl-core.h"
114*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/cache-api.h"
115*4dc78e53SAndroid Build Coastguard Worker
116*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
117*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr_cacheinfo {
118*4dc78e53SAndroid Build Coastguard Worker /* Preferred lifetime in seconds, ticking from when the message gets constructed */
119*4dc78e53SAndroid Build Coastguard Worker uint32_t aci_prefered;
120*4dc78e53SAndroid Build Coastguard Worker
121*4dc78e53SAndroid Build Coastguard Worker /* Valid lifetime in seconds, ticking from when the message gets constructed */
122*4dc78e53SAndroid Build Coastguard Worker uint32_t aci_valid;
123*4dc78e53SAndroid Build Coastguard Worker
124*4dc78e53SAndroid Build Coastguard Worker /* Timestamp of creation in 1/100s since boottime, clock_gettime(CLOCK_MONOTONIC) */
125*4dc78e53SAndroid Build Coastguard Worker uint32_t aci_cstamp;
126*4dc78e53SAndroid Build Coastguard Worker
127*4dc78e53SAndroid Build Coastguard Worker /* Timestamp of last update in 1/100s since boottime, clock_gettime(CLOCK_MONOTONIC) */
128*4dc78e53SAndroid Build Coastguard Worker uint32_t aci_tstamp;
129*4dc78e53SAndroid Build Coastguard Worker };
130*4dc78e53SAndroid Build Coastguard Worker
131*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr {
132*4dc78e53SAndroid Build Coastguard Worker NLHDR_COMMON
133*4dc78e53SAndroid Build Coastguard Worker
134*4dc78e53SAndroid Build Coastguard Worker uint8_t a_family;
135*4dc78e53SAndroid Build Coastguard Worker uint8_t a_prefixlen;
136*4dc78e53SAndroid Build Coastguard Worker uint8_t a_scope;
137*4dc78e53SAndroid Build Coastguard Worker uint32_t a_flags;
138*4dc78e53SAndroid Build Coastguard Worker uint32_t a_ifindex;
139*4dc78e53SAndroid Build Coastguard Worker
140*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *a_peer;
141*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *a_local;
142*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *a_bcast;
143*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *a_anycast;
144*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *a_multicast;
145*4dc78e53SAndroid Build Coastguard Worker
146*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr_cacheinfo a_cacheinfo;
147*4dc78e53SAndroid Build Coastguard Worker
148*4dc78e53SAndroid Build Coastguard Worker char a_label[IFNAMSIZ];
149*4dc78e53SAndroid Build Coastguard Worker uint32_t a_flag_mask;
150*4dc78e53SAndroid Build Coastguard Worker struct rtnl_link *a_link;
151*4dc78e53SAndroid Build Coastguard Worker };
152*4dc78e53SAndroid Build Coastguard Worker
153*4dc78e53SAndroid Build Coastguard Worker #define ADDR_ATTR_FAMILY 0x0001
154*4dc78e53SAndroid Build Coastguard Worker #define ADDR_ATTR_PREFIXLEN 0x0002
155*4dc78e53SAndroid Build Coastguard Worker #define ADDR_ATTR_FLAGS 0x0004
156*4dc78e53SAndroid Build Coastguard Worker #define ADDR_ATTR_SCOPE 0x0008
157*4dc78e53SAndroid Build Coastguard Worker #define ADDR_ATTR_IFINDEX 0x0010
158*4dc78e53SAndroid Build Coastguard Worker #define ADDR_ATTR_LABEL 0x0020
159*4dc78e53SAndroid Build Coastguard Worker #define ADDR_ATTR_CACHEINFO 0x0040
160*4dc78e53SAndroid Build Coastguard Worker #define ADDR_ATTR_PEER 0x0080
161*4dc78e53SAndroid Build Coastguard Worker #define ADDR_ATTR_LOCAL 0x0100
162*4dc78e53SAndroid Build Coastguard Worker #define ADDR_ATTR_BROADCAST 0x0200
163*4dc78e53SAndroid Build Coastguard Worker #define ADDR_ATTR_MULTICAST 0x0400
164*4dc78e53SAndroid Build Coastguard Worker #define ADDR_ATTR_ANYCAST 0x0800
165*4dc78e53SAndroid Build Coastguard Worker
166*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_addr_ops;
167*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops addr_obj_ops;
168*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
169*4dc78e53SAndroid Build Coastguard Worker
addr_constructor(struct nl_object * obj)170*4dc78e53SAndroid Build Coastguard Worker static void addr_constructor(struct nl_object *obj)
171*4dc78e53SAndroid Build Coastguard Worker {
172*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr *addr = nl_object_priv(obj);
173*4dc78e53SAndroid Build Coastguard Worker
174*4dc78e53SAndroid Build Coastguard Worker addr->a_scope = RT_SCOPE_NOWHERE;
175*4dc78e53SAndroid Build Coastguard Worker }
176*4dc78e53SAndroid Build Coastguard Worker
addr_free_data(struct nl_object * obj)177*4dc78e53SAndroid Build Coastguard Worker static void addr_free_data(struct nl_object *obj)
178*4dc78e53SAndroid Build Coastguard Worker {
179*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr *addr = nl_object_priv(obj);
180*4dc78e53SAndroid Build Coastguard Worker
181*4dc78e53SAndroid Build Coastguard Worker if (!addr)
182*4dc78e53SAndroid Build Coastguard Worker return;
183*4dc78e53SAndroid Build Coastguard Worker
184*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(addr->a_peer);
185*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(addr->a_local);
186*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(addr->a_bcast);
187*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(addr->a_multicast);
188*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(addr->a_anycast);
189*4dc78e53SAndroid Build Coastguard Worker rtnl_link_put(addr->a_link);
190*4dc78e53SAndroid Build Coastguard Worker }
191*4dc78e53SAndroid Build Coastguard Worker
addr_clone(struct nl_object * _dst,struct nl_object * _src)192*4dc78e53SAndroid Build Coastguard Worker static int addr_clone(struct nl_object *_dst, struct nl_object *_src)
193*4dc78e53SAndroid Build Coastguard Worker {
194*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr *dst = nl_object_priv(_dst);
195*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr *src = nl_object_priv(_src);
196*4dc78e53SAndroid Build Coastguard Worker
197*4dc78e53SAndroid Build Coastguard Worker dst->a_peer = NULL;
198*4dc78e53SAndroid Build Coastguard Worker dst->a_local = NULL;
199*4dc78e53SAndroid Build Coastguard Worker dst->a_bcast = NULL;
200*4dc78e53SAndroid Build Coastguard Worker dst->a_anycast = NULL;
201*4dc78e53SAndroid Build Coastguard Worker dst->a_multicast = NULL;
202*4dc78e53SAndroid Build Coastguard Worker dst->a_link = NULL;
203*4dc78e53SAndroid Build Coastguard Worker
204*4dc78e53SAndroid Build Coastguard Worker if (src->a_link) {
205*4dc78e53SAndroid Build Coastguard Worker nl_object_get(OBJ_CAST(src->a_link));
206*4dc78e53SAndroid Build Coastguard Worker dst->a_link = src->a_link;
207*4dc78e53SAndroid Build Coastguard Worker }
208*4dc78e53SAndroid Build Coastguard Worker
209*4dc78e53SAndroid Build Coastguard Worker if (src->a_peer)
210*4dc78e53SAndroid Build Coastguard Worker if (!(dst->a_peer = nl_addr_clone(src->a_peer)))
211*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
212*4dc78e53SAndroid Build Coastguard Worker
213*4dc78e53SAndroid Build Coastguard Worker if (src->a_local)
214*4dc78e53SAndroid Build Coastguard Worker if (!(dst->a_local = nl_addr_clone(src->a_local)))
215*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
216*4dc78e53SAndroid Build Coastguard Worker
217*4dc78e53SAndroid Build Coastguard Worker if (src->a_bcast)
218*4dc78e53SAndroid Build Coastguard Worker if (!(dst->a_bcast = nl_addr_clone(src->a_bcast)))
219*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
220*4dc78e53SAndroid Build Coastguard Worker
221*4dc78e53SAndroid Build Coastguard Worker if (src->a_multicast)
222*4dc78e53SAndroid Build Coastguard Worker if (!(dst->a_multicast = nl_addr_clone(src->a_multicast)))
223*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
224*4dc78e53SAndroid Build Coastguard Worker
225*4dc78e53SAndroid Build Coastguard Worker if (src->a_anycast)
226*4dc78e53SAndroid Build Coastguard Worker if (!(dst->a_anycast = nl_addr_clone(src->a_anycast)))
227*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
228*4dc78e53SAndroid Build Coastguard Worker
229*4dc78e53SAndroid Build Coastguard Worker return 0;
230*4dc78e53SAndroid Build Coastguard Worker }
231*4dc78e53SAndroid Build Coastguard Worker
232*4dc78e53SAndroid Build Coastguard Worker static struct nla_policy addr_policy[IFA_MAX+1] = {
233*4dc78e53SAndroid Build Coastguard Worker [IFA_LABEL] = { .type = NLA_STRING,
234*4dc78e53SAndroid Build Coastguard Worker .maxlen = IFNAMSIZ },
235*4dc78e53SAndroid Build Coastguard Worker [IFA_CACHEINFO] = { .minlen = sizeof(struct ifa_cacheinfo) },
236*4dc78e53SAndroid Build Coastguard Worker };
237*4dc78e53SAndroid Build Coastguard Worker
addr_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * nlh,struct nl_parser_param * pp)238*4dc78e53SAndroid Build Coastguard Worker static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
239*4dc78e53SAndroid Build Coastguard Worker struct nlmsghdr *nlh, struct nl_parser_param *pp)
240*4dc78e53SAndroid Build Coastguard Worker {
241*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr *addr;
242*4dc78e53SAndroid Build Coastguard Worker struct ifaddrmsg *ifa;
243*4dc78e53SAndroid Build Coastguard Worker struct nlattr *tb[IFA_MAX+1];
244*4dc78e53SAndroid Build Coastguard Worker int err, family;
245*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *link_cache;
246*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *plen_addr = NULL;
247*4dc78e53SAndroid Build Coastguard Worker
248*4dc78e53SAndroid Build Coastguard Worker addr = rtnl_addr_alloc();
249*4dc78e53SAndroid Build Coastguard Worker if (!addr)
250*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
251*4dc78e53SAndroid Build Coastguard Worker
252*4dc78e53SAndroid Build Coastguard Worker addr->ce_msgtype = nlh->nlmsg_type;
253*4dc78e53SAndroid Build Coastguard Worker
254*4dc78e53SAndroid Build Coastguard Worker err = nlmsg_parse(nlh, sizeof(*ifa), tb, IFA_MAX, addr_policy);
255*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
256*4dc78e53SAndroid Build Coastguard Worker goto errout;
257*4dc78e53SAndroid Build Coastguard Worker
258*4dc78e53SAndroid Build Coastguard Worker ifa = nlmsg_data(nlh);
259*4dc78e53SAndroid Build Coastguard Worker addr->a_family = family = ifa->ifa_family;
260*4dc78e53SAndroid Build Coastguard Worker addr->a_prefixlen = ifa->ifa_prefixlen;
261*4dc78e53SAndroid Build Coastguard Worker addr->a_scope = ifa->ifa_scope;
262*4dc78e53SAndroid Build Coastguard Worker addr->a_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) :
263*4dc78e53SAndroid Build Coastguard Worker ifa->ifa_flags;
264*4dc78e53SAndroid Build Coastguard Worker addr->a_ifindex = ifa->ifa_index;
265*4dc78e53SAndroid Build Coastguard Worker
266*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask = (ADDR_ATTR_FAMILY | ADDR_ATTR_PREFIXLEN |
267*4dc78e53SAndroid Build Coastguard Worker ADDR_ATTR_FLAGS | ADDR_ATTR_SCOPE | ADDR_ATTR_IFINDEX);
268*4dc78e53SAndroid Build Coastguard Worker
269*4dc78e53SAndroid Build Coastguard Worker if (tb[IFA_LABEL]) {
270*4dc78e53SAndroid Build Coastguard Worker nla_strlcpy(addr->a_label, tb[IFA_LABEL], IFNAMSIZ);
271*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_LABEL;
272*4dc78e53SAndroid Build Coastguard Worker }
273*4dc78e53SAndroid Build Coastguard Worker
274*4dc78e53SAndroid Build Coastguard Worker /* IPv6 only */
275*4dc78e53SAndroid Build Coastguard Worker if (tb[IFA_CACHEINFO]) {
276*4dc78e53SAndroid Build Coastguard Worker struct ifa_cacheinfo *ca;
277*4dc78e53SAndroid Build Coastguard Worker
278*4dc78e53SAndroid Build Coastguard Worker ca = nla_data(tb[IFA_CACHEINFO]);
279*4dc78e53SAndroid Build Coastguard Worker addr->a_cacheinfo.aci_prefered = ca->ifa_prefered;
280*4dc78e53SAndroid Build Coastguard Worker addr->a_cacheinfo.aci_valid = ca->ifa_valid;
281*4dc78e53SAndroid Build Coastguard Worker addr->a_cacheinfo.aci_cstamp = ca->cstamp;
282*4dc78e53SAndroid Build Coastguard Worker addr->a_cacheinfo.aci_tstamp = ca->tstamp;
283*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_CACHEINFO;
284*4dc78e53SAndroid Build Coastguard Worker }
285*4dc78e53SAndroid Build Coastguard Worker
286*4dc78e53SAndroid Build Coastguard Worker if (family == AF_INET) {
287*4dc78e53SAndroid Build Coastguard Worker uint32_t null = 0;
288*4dc78e53SAndroid Build Coastguard Worker
289*4dc78e53SAndroid Build Coastguard Worker /* for IPv4/AF_INET, kernel always sets IFA_LOCAL and IFA_ADDRESS, unless it
290*4dc78e53SAndroid Build Coastguard Worker * is effectively 0.0.0.0. */
291*4dc78e53SAndroid Build Coastguard Worker if (tb[IFA_LOCAL])
292*4dc78e53SAndroid Build Coastguard Worker addr->a_local = nl_addr_alloc_attr(tb[IFA_LOCAL], family);
293*4dc78e53SAndroid Build Coastguard Worker else
294*4dc78e53SAndroid Build Coastguard Worker addr->a_local = nl_addr_build(family, &null, sizeof (null));
295*4dc78e53SAndroid Build Coastguard Worker if (!addr->a_local)
296*4dc78e53SAndroid Build Coastguard Worker goto errout_nomem;
297*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_LOCAL;
298*4dc78e53SAndroid Build Coastguard Worker
299*4dc78e53SAndroid Build Coastguard Worker if (tb[IFA_ADDRESS])
300*4dc78e53SAndroid Build Coastguard Worker addr->a_peer = nl_addr_alloc_attr(tb[IFA_ADDRESS], family);
301*4dc78e53SAndroid Build Coastguard Worker else
302*4dc78e53SAndroid Build Coastguard Worker addr->a_peer = nl_addr_build(family, &null, sizeof (null));
303*4dc78e53SAndroid Build Coastguard Worker if (!addr->a_peer)
304*4dc78e53SAndroid Build Coastguard Worker goto errout_nomem;
305*4dc78e53SAndroid Build Coastguard Worker
306*4dc78e53SAndroid Build Coastguard Worker if (!nl_addr_cmp (addr->a_local, addr->a_peer)) {
307*4dc78e53SAndroid Build Coastguard Worker /* having IFA_ADDRESS equal to IFA_LOCAL does not really mean
308*4dc78e53SAndroid Build Coastguard Worker * there is no peer. It means the peer is equal to the local address,
309*4dc78e53SAndroid Build Coastguard Worker * which is the case for "normal" addresses.
310*4dc78e53SAndroid Build Coastguard Worker *
311*4dc78e53SAndroid Build Coastguard Worker * Still, clear the peer and pretend it is unset for backward
312*4dc78e53SAndroid Build Coastguard Worker * compatibility. */
313*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(addr->a_peer);
314*4dc78e53SAndroid Build Coastguard Worker addr->a_peer = NULL;
315*4dc78e53SAndroid Build Coastguard Worker } else
316*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_PEER;
317*4dc78e53SAndroid Build Coastguard Worker
318*4dc78e53SAndroid Build Coastguard Worker plen_addr = addr->a_local;
319*4dc78e53SAndroid Build Coastguard Worker } else {
320*4dc78e53SAndroid Build Coastguard Worker if (tb[IFA_LOCAL]) {
321*4dc78e53SAndroid Build Coastguard Worker addr->a_local = nl_addr_alloc_attr(tb[IFA_LOCAL], family);
322*4dc78e53SAndroid Build Coastguard Worker if (!addr->a_local)
323*4dc78e53SAndroid Build Coastguard Worker goto errout_nomem;
324*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_LOCAL;
325*4dc78e53SAndroid Build Coastguard Worker plen_addr = addr->a_local;
326*4dc78e53SAndroid Build Coastguard Worker }
327*4dc78e53SAndroid Build Coastguard Worker
328*4dc78e53SAndroid Build Coastguard Worker if (tb[IFA_ADDRESS]) {
329*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *a;
330*4dc78e53SAndroid Build Coastguard Worker
331*4dc78e53SAndroid Build Coastguard Worker a = nl_addr_alloc_attr(tb[IFA_ADDRESS], family);
332*4dc78e53SAndroid Build Coastguard Worker if (!a)
333*4dc78e53SAndroid Build Coastguard Worker goto errout_nomem;
334*4dc78e53SAndroid Build Coastguard Worker
335*4dc78e53SAndroid Build Coastguard Worker /* IPv6 sends the local address as IFA_ADDRESS with
336*4dc78e53SAndroid Build Coastguard Worker * no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS
337*4dc78e53SAndroid Build Coastguard Worker * with IFA_ADDRESS being the peer address if they differ */
338*4dc78e53SAndroid Build Coastguard Worker if (!tb[IFA_LOCAL] || !nl_addr_cmp(a, addr->a_local)) {
339*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(addr->a_local);
340*4dc78e53SAndroid Build Coastguard Worker addr->a_local = a;
341*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_LOCAL;
342*4dc78e53SAndroid Build Coastguard Worker } else {
343*4dc78e53SAndroid Build Coastguard Worker addr->a_peer = a;
344*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_PEER;
345*4dc78e53SAndroid Build Coastguard Worker }
346*4dc78e53SAndroid Build Coastguard Worker
347*4dc78e53SAndroid Build Coastguard Worker plen_addr = a;
348*4dc78e53SAndroid Build Coastguard Worker }
349*4dc78e53SAndroid Build Coastguard Worker }
350*4dc78e53SAndroid Build Coastguard Worker
351*4dc78e53SAndroid Build Coastguard Worker if (plen_addr)
352*4dc78e53SAndroid Build Coastguard Worker nl_addr_set_prefixlen(plen_addr, addr->a_prefixlen);
353*4dc78e53SAndroid Build Coastguard Worker
354*4dc78e53SAndroid Build Coastguard Worker /* IPv4 only */
355*4dc78e53SAndroid Build Coastguard Worker if (tb[IFA_BROADCAST]) {
356*4dc78e53SAndroid Build Coastguard Worker addr->a_bcast = nl_addr_alloc_attr(tb[IFA_BROADCAST], family);
357*4dc78e53SAndroid Build Coastguard Worker if (!addr->a_bcast)
358*4dc78e53SAndroid Build Coastguard Worker goto errout_nomem;
359*4dc78e53SAndroid Build Coastguard Worker
360*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_BROADCAST;
361*4dc78e53SAndroid Build Coastguard Worker }
362*4dc78e53SAndroid Build Coastguard Worker
363*4dc78e53SAndroid Build Coastguard Worker /* IPv6 only */
364*4dc78e53SAndroid Build Coastguard Worker if (tb[IFA_MULTICAST]) {
365*4dc78e53SAndroid Build Coastguard Worker addr->a_multicast = nl_addr_alloc_attr(tb[IFA_MULTICAST],
366*4dc78e53SAndroid Build Coastguard Worker family);
367*4dc78e53SAndroid Build Coastguard Worker if (!addr->a_multicast)
368*4dc78e53SAndroid Build Coastguard Worker goto errout_nomem;
369*4dc78e53SAndroid Build Coastguard Worker
370*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_MULTICAST;
371*4dc78e53SAndroid Build Coastguard Worker }
372*4dc78e53SAndroid Build Coastguard Worker
373*4dc78e53SAndroid Build Coastguard Worker /* IPv6 only */
374*4dc78e53SAndroid Build Coastguard Worker if (tb[IFA_ANYCAST]) {
375*4dc78e53SAndroid Build Coastguard Worker addr->a_anycast = nl_addr_alloc_attr(tb[IFA_ANYCAST],
376*4dc78e53SAndroid Build Coastguard Worker family);
377*4dc78e53SAndroid Build Coastguard Worker if (!addr->a_anycast)
378*4dc78e53SAndroid Build Coastguard Worker goto errout_nomem;
379*4dc78e53SAndroid Build Coastguard Worker
380*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_ANYCAST;
381*4dc78e53SAndroid Build Coastguard Worker }
382*4dc78e53SAndroid Build Coastguard Worker
383*4dc78e53SAndroid Build Coastguard Worker if ((link_cache = __nl_cache_mngt_require("route/link"))) {
384*4dc78e53SAndroid Build Coastguard Worker struct rtnl_link *link;
385*4dc78e53SAndroid Build Coastguard Worker
386*4dc78e53SAndroid Build Coastguard Worker if ((link = rtnl_link_get(link_cache, addr->a_ifindex))) {
387*4dc78e53SAndroid Build Coastguard Worker rtnl_addr_set_link(addr, link);
388*4dc78e53SAndroid Build Coastguard Worker
389*4dc78e53SAndroid Build Coastguard Worker /* rtnl_addr_set_link incs refcnt */
390*4dc78e53SAndroid Build Coastguard Worker rtnl_link_put(link);
391*4dc78e53SAndroid Build Coastguard Worker }
392*4dc78e53SAndroid Build Coastguard Worker }
393*4dc78e53SAndroid Build Coastguard Worker
394*4dc78e53SAndroid Build Coastguard Worker err = pp->pp_cb((struct nl_object *) addr, pp);
395*4dc78e53SAndroid Build Coastguard Worker errout:
396*4dc78e53SAndroid Build Coastguard Worker rtnl_addr_put(addr);
397*4dc78e53SAndroid Build Coastguard Worker
398*4dc78e53SAndroid Build Coastguard Worker return err;
399*4dc78e53SAndroid Build Coastguard Worker
400*4dc78e53SAndroid Build Coastguard Worker errout_nomem:
401*4dc78e53SAndroid Build Coastguard Worker err = -NLE_NOMEM;
402*4dc78e53SAndroid Build Coastguard Worker goto errout;
403*4dc78e53SAndroid Build Coastguard Worker }
404*4dc78e53SAndroid Build Coastguard Worker
addr_request_update(struct nl_cache * cache,struct nl_sock * sk)405*4dc78e53SAndroid Build Coastguard Worker static int addr_request_update(struct nl_cache *cache, struct nl_sock *sk)
406*4dc78e53SAndroid Build Coastguard Worker {
407*4dc78e53SAndroid Build Coastguard Worker return nl_rtgen_request(sk, RTM_GETADDR, AF_UNSPEC, NLM_F_DUMP);
408*4dc78e53SAndroid Build Coastguard Worker }
409*4dc78e53SAndroid Build Coastguard Worker
addr_dump_line(struct nl_object * obj,struct nl_dump_params * p)410*4dc78e53SAndroid Build Coastguard Worker static void addr_dump_line(struct nl_object *obj, struct nl_dump_params *p)
411*4dc78e53SAndroid Build Coastguard Worker {
412*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr *addr = (struct rtnl_addr *) obj;
413*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *link_cache;
414*4dc78e53SAndroid Build Coastguard Worker char buf[128];
415*4dc78e53SAndroid Build Coastguard Worker
416*4dc78e53SAndroid Build Coastguard Worker link_cache = nl_cache_mngt_require_safe("route/link");
417*4dc78e53SAndroid Build Coastguard Worker
418*4dc78e53SAndroid Build Coastguard Worker if (addr->ce_mask & ADDR_ATTR_LOCAL)
419*4dc78e53SAndroid Build Coastguard Worker nl_dump_line(p, "%s",
420*4dc78e53SAndroid Build Coastguard Worker nl_addr2str(addr->a_local, buf, sizeof(buf)));
421*4dc78e53SAndroid Build Coastguard Worker else
422*4dc78e53SAndroid Build Coastguard Worker nl_dump_line(p, "none");
423*4dc78e53SAndroid Build Coastguard Worker
424*4dc78e53SAndroid Build Coastguard Worker if (addr->ce_mask & ADDR_ATTR_PEER)
425*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " peer %s",
426*4dc78e53SAndroid Build Coastguard Worker nl_addr2str(addr->a_peer, buf, sizeof(buf)));
427*4dc78e53SAndroid Build Coastguard Worker
428*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " %s ", nl_af2str(addr->a_family, buf, sizeof(buf)));
429*4dc78e53SAndroid Build Coastguard Worker
430*4dc78e53SAndroid Build Coastguard Worker if (link_cache)
431*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "dev %s ",
432*4dc78e53SAndroid Build Coastguard Worker rtnl_link_i2name(link_cache, addr->a_ifindex,
433*4dc78e53SAndroid Build Coastguard Worker buf, sizeof(buf)));
434*4dc78e53SAndroid Build Coastguard Worker else
435*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "dev %d ", addr->a_ifindex);
436*4dc78e53SAndroid Build Coastguard Worker
437*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "scope %s",
438*4dc78e53SAndroid Build Coastguard Worker rtnl_scope2str(addr->a_scope, buf, sizeof(buf)));
439*4dc78e53SAndroid Build Coastguard Worker
440*4dc78e53SAndroid Build Coastguard Worker rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf));
441*4dc78e53SAndroid Build Coastguard Worker if (buf[0])
442*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " <%s>", buf);
443*4dc78e53SAndroid Build Coastguard Worker
444*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "\n");
445*4dc78e53SAndroid Build Coastguard Worker
446*4dc78e53SAndroid Build Coastguard Worker if (link_cache)
447*4dc78e53SAndroid Build Coastguard Worker nl_cache_put(link_cache);
448*4dc78e53SAndroid Build Coastguard Worker }
449*4dc78e53SAndroid Build Coastguard Worker
addr_dump_details(struct nl_object * obj,struct nl_dump_params * p)450*4dc78e53SAndroid Build Coastguard Worker static void addr_dump_details(struct nl_object *obj, struct nl_dump_params *p)
451*4dc78e53SAndroid Build Coastguard Worker {
452*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr *addr = (struct rtnl_addr *) obj;
453*4dc78e53SAndroid Build Coastguard Worker char buf[128];
454*4dc78e53SAndroid Build Coastguard Worker
455*4dc78e53SAndroid Build Coastguard Worker addr_dump_line(obj, p);
456*4dc78e53SAndroid Build Coastguard Worker
457*4dc78e53SAndroid Build Coastguard Worker if (addr->ce_mask & (ADDR_ATTR_LABEL | ADDR_ATTR_BROADCAST |
458*4dc78e53SAndroid Build Coastguard Worker ADDR_ATTR_MULTICAST)) {
459*4dc78e53SAndroid Build Coastguard Worker nl_dump_line(p, " ");
460*4dc78e53SAndroid Build Coastguard Worker
461*4dc78e53SAndroid Build Coastguard Worker if (addr->ce_mask & ADDR_ATTR_LABEL)
462*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " label %s", addr->a_label);
463*4dc78e53SAndroid Build Coastguard Worker
464*4dc78e53SAndroid Build Coastguard Worker if (addr->ce_mask & ADDR_ATTR_BROADCAST)
465*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " broadcast %s",
466*4dc78e53SAndroid Build Coastguard Worker nl_addr2str(addr->a_bcast, buf, sizeof(buf)));
467*4dc78e53SAndroid Build Coastguard Worker
468*4dc78e53SAndroid Build Coastguard Worker if (addr->ce_mask & ADDR_ATTR_MULTICAST)
469*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " multicast %s",
470*4dc78e53SAndroid Build Coastguard Worker nl_addr2str(addr->a_multicast, buf,
471*4dc78e53SAndroid Build Coastguard Worker sizeof(buf)));
472*4dc78e53SAndroid Build Coastguard Worker
473*4dc78e53SAndroid Build Coastguard Worker if (addr->ce_mask & ADDR_ATTR_ANYCAST)
474*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " anycast %s",
475*4dc78e53SAndroid Build Coastguard Worker nl_addr2str(addr->a_anycast, buf,
476*4dc78e53SAndroid Build Coastguard Worker sizeof(buf)));
477*4dc78e53SAndroid Build Coastguard Worker
478*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "\n");
479*4dc78e53SAndroid Build Coastguard Worker }
480*4dc78e53SAndroid Build Coastguard Worker
481*4dc78e53SAndroid Build Coastguard Worker if (addr->ce_mask & ADDR_ATTR_CACHEINFO) {
482*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo;
483*4dc78e53SAndroid Build Coastguard Worker
484*4dc78e53SAndroid Build Coastguard Worker nl_dump_line(p, " valid-lifetime %s",
485*4dc78e53SAndroid Build Coastguard Worker ci->aci_valid == 0xFFFFFFFFU ? "forever" :
486*4dc78e53SAndroid Build Coastguard Worker nl_msec2str(ci->aci_valid * 1000,
487*4dc78e53SAndroid Build Coastguard Worker buf, sizeof(buf)));
488*4dc78e53SAndroid Build Coastguard Worker
489*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " preferred-lifetime %s\n",
490*4dc78e53SAndroid Build Coastguard Worker ci->aci_prefered == 0xFFFFFFFFU ? "forever" :
491*4dc78e53SAndroid Build Coastguard Worker nl_msec2str(ci->aci_prefered * 1000,
492*4dc78e53SAndroid Build Coastguard Worker buf, sizeof(buf)));
493*4dc78e53SAndroid Build Coastguard Worker
494*4dc78e53SAndroid Build Coastguard Worker nl_dump_line(p, " created boot-time+%s ",
495*4dc78e53SAndroid Build Coastguard Worker nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10,
496*4dc78e53SAndroid Build Coastguard Worker buf, sizeof(buf)));
497*4dc78e53SAndroid Build Coastguard Worker
498*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "last-updated boot-time+%s\n",
499*4dc78e53SAndroid Build Coastguard Worker nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10,
500*4dc78e53SAndroid Build Coastguard Worker buf, sizeof(buf)));
501*4dc78e53SAndroid Build Coastguard Worker }
502*4dc78e53SAndroid Build Coastguard Worker }
503*4dc78e53SAndroid Build Coastguard Worker
addr_dump_stats(struct nl_object * obj,struct nl_dump_params * p)504*4dc78e53SAndroid Build Coastguard Worker static void addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
505*4dc78e53SAndroid Build Coastguard Worker {
506*4dc78e53SAndroid Build Coastguard Worker addr_dump_details(obj, p);
507*4dc78e53SAndroid Build Coastguard Worker }
508*4dc78e53SAndroid Build Coastguard Worker
addr_id_attrs_get(struct nl_object * obj)509*4dc78e53SAndroid Build Coastguard Worker static uint32_t addr_id_attrs_get(struct nl_object *obj)
510*4dc78e53SAndroid Build Coastguard Worker {
511*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr *addr = (struct rtnl_addr *)obj;
512*4dc78e53SAndroid Build Coastguard Worker uint32_t rv;
513*4dc78e53SAndroid Build Coastguard Worker
514*4dc78e53SAndroid Build Coastguard Worker switch (addr->a_family) {
515*4dc78e53SAndroid Build Coastguard Worker case AF_INET:
516*4dc78e53SAndroid Build Coastguard Worker rv = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX |
517*4dc78e53SAndroid Build Coastguard Worker ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN);
518*4dc78e53SAndroid Build Coastguard Worker if (addr->a_peer)
519*4dc78e53SAndroid Build Coastguard Worker rv |= ADDR_ATTR_PEER;
520*4dc78e53SAndroid Build Coastguard Worker return rv;
521*4dc78e53SAndroid Build Coastguard Worker case AF_INET6:
522*4dc78e53SAndroid Build Coastguard Worker return (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX |
523*4dc78e53SAndroid Build Coastguard Worker ADDR_ATTR_LOCAL);
524*4dc78e53SAndroid Build Coastguard Worker default:
525*4dc78e53SAndroid Build Coastguard Worker return (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX |
526*4dc78e53SAndroid Build Coastguard Worker ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN);
527*4dc78e53SAndroid Build Coastguard Worker }
528*4dc78e53SAndroid Build Coastguard Worker }
529*4dc78e53SAndroid Build Coastguard Worker
addr_compare(struct nl_object * _a,struct nl_object * _b,uint64_t attrs,int flags)530*4dc78e53SAndroid Build Coastguard Worker static uint64_t addr_compare(struct nl_object *_a, struct nl_object *_b,
531*4dc78e53SAndroid Build Coastguard Worker uint64_t attrs, int flags)
532*4dc78e53SAndroid Build Coastguard Worker {
533*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr *a = (struct rtnl_addr *) _a;
534*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr *b = (struct rtnl_addr *) _b;
535*4dc78e53SAndroid Build Coastguard Worker uint64_t diff = 0;
536*4dc78e53SAndroid Build Coastguard Worker
537*4dc78e53SAndroid Build Coastguard Worker #define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
538*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(ADDR_ATTR_IFINDEX, a->a_ifindex != b->a_ifindex);
539*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(ADDR_ATTR_FAMILY, a->a_family != b->a_family);
540*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(ADDR_ATTR_SCOPE, a->a_scope != b->a_scope);
541*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(ADDR_ATTR_LABEL, strcmp(a->a_label, b->a_label));
542*4dc78e53SAndroid Build Coastguard Worker if (attrs & ADDR_ATTR_PEER) {
543*4dc78e53SAndroid Build Coastguard Worker if ((flags & ID_COMPARISON) && a->a_family == AF_INET &&
544*4dc78e53SAndroid Build Coastguard Worker b->a_family == AF_INET && a->a_peer && b->a_peer &&
545*4dc78e53SAndroid Build Coastguard Worker a->a_prefixlen == b->a_prefixlen) {
546*4dc78e53SAndroid Build Coastguard Worker /* when comparing two IPv4 addresses for id-equality, the network part
547*4dc78e53SAndroid Build Coastguard Worker * of the PEER address shall be compared.
548*4dc78e53SAndroid Build Coastguard Worker */
549*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(ADDR_ATTR_PEER,
550*4dc78e53SAndroid Build Coastguard Worker nl_addr_cmp_prefix(a->a_peer, b->a_peer));
551*4dc78e53SAndroid Build Coastguard Worker } else
552*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(ADDR_ATTR_PEER,
553*4dc78e53SAndroid Build Coastguard Worker nl_addr_cmp(a->a_peer, b->a_peer));
554*4dc78e53SAndroid Build Coastguard Worker }
555*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(ADDR_ATTR_LOCAL, nl_addr_cmp(a->a_local, b->a_local));
556*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(ADDR_ATTR_MULTICAST,
557*4dc78e53SAndroid Build Coastguard Worker nl_addr_cmp(a->a_multicast, b->a_multicast));
558*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(ADDR_ATTR_BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast));
559*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(ADDR_ATTR_ANYCAST,
560*4dc78e53SAndroid Build Coastguard Worker nl_addr_cmp(a->a_anycast, b->a_anycast));
561*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(ADDR_ATTR_CACHEINFO,
562*4dc78e53SAndroid Build Coastguard Worker memcmp(&a->a_cacheinfo, &b->a_cacheinfo,
563*4dc78e53SAndroid Build Coastguard Worker sizeof(a->a_cacheinfo)));
564*4dc78e53SAndroid Build Coastguard Worker
565*4dc78e53SAndroid Build Coastguard Worker if (flags & LOOSE_COMPARISON)
566*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(ADDR_ATTR_FLAGS,
567*4dc78e53SAndroid Build Coastguard Worker (a->a_flags ^ b->a_flags) & b->a_flag_mask);
568*4dc78e53SAndroid Build Coastguard Worker else
569*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(ADDR_ATTR_FLAGS, a->a_flags != b->a_flags);
570*4dc78e53SAndroid Build Coastguard Worker #undef _DIFF
571*4dc78e53SAndroid Build Coastguard Worker
572*4dc78e53SAndroid Build Coastguard Worker return diff;
573*4dc78e53SAndroid Build Coastguard Worker }
574*4dc78e53SAndroid Build Coastguard Worker
575*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl addr_attrs[] = {
576*4dc78e53SAndroid Build Coastguard Worker __ADD(ADDR_ATTR_FAMILY, family),
577*4dc78e53SAndroid Build Coastguard Worker __ADD(ADDR_ATTR_PREFIXLEN, prefixlen),
578*4dc78e53SAndroid Build Coastguard Worker __ADD(ADDR_ATTR_FLAGS, flags),
579*4dc78e53SAndroid Build Coastguard Worker __ADD(ADDR_ATTR_SCOPE, scope),
580*4dc78e53SAndroid Build Coastguard Worker __ADD(ADDR_ATTR_IFINDEX, ifindex),
581*4dc78e53SAndroid Build Coastguard Worker __ADD(ADDR_ATTR_LABEL, label),
582*4dc78e53SAndroid Build Coastguard Worker __ADD(ADDR_ATTR_CACHEINFO, cacheinfo),
583*4dc78e53SAndroid Build Coastguard Worker __ADD(ADDR_ATTR_PEER, peer),
584*4dc78e53SAndroid Build Coastguard Worker __ADD(ADDR_ATTR_LOCAL, local),
585*4dc78e53SAndroid Build Coastguard Worker __ADD(ADDR_ATTR_BROADCAST, broadcast),
586*4dc78e53SAndroid Build Coastguard Worker __ADD(ADDR_ATTR_MULTICAST, multicast),
587*4dc78e53SAndroid Build Coastguard Worker };
588*4dc78e53SAndroid Build Coastguard Worker
addr_attrs2str(int attrs,char * buf,size_t len)589*4dc78e53SAndroid Build Coastguard Worker static char *addr_attrs2str(int attrs, char *buf, size_t len)
590*4dc78e53SAndroid Build Coastguard Worker {
591*4dc78e53SAndroid Build Coastguard Worker return __flags2str(attrs, buf, len, addr_attrs,
592*4dc78e53SAndroid Build Coastguard Worker ARRAY_SIZE(addr_attrs));
593*4dc78e53SAndroid Build Coastguard Worker }
594*4dc78e53SAndroid Build Coastguard Worker
595*4dc78e53SAndroid Build Coastguard Worker /**
596*4dc78e53SAndroid Build Coastguard Worker * @name Allocation/Freeing
597*4dc78e53SAndroid Build Coastguard Worker * @{
598*4dc78e53SAndroid Build Coastguard Worker */
599*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_alloc(void)600*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr *rtnl_addr_alloc(void)
601*4dc78e53SAndroid Build Coastguard Worker {
602*4dc78e53SAndroid Build Coastguard Worker return (struct rtnl_addr *) nl_object_alloc(&addr_obj_ops);
603*4dc78e53SAndroid Build Coastguard Worker }
604*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_put(struct rtnl_addr * addr)605*4dc78e53SAndroid Build Coastguard Worker void rtnl_addr_put(struct rtnl_addr *addr)
606*4dc78e53SAndroid Build Coastguard Worker {
607*4dc78e53SAndroid Build Coastguard Worker nl_object_put((struct nl_object *) addr);
608*4dc78e53SAndroid Build Coastguard Worker }
609*4dc78e53SAndroid Build Coastguard Worker
610*4dc78e53SAndroid Build Coastguard Worker /** @} */
611*4dc78e53SAndroid Build Coastguard Worker
612*4dc78e53SAndroid Build Coastguard Worker /**
613*4dc78e53SAndroid Build Coastguard Worker * @name Cache Management
614*4dc78e53SAndroid Build Coastguard Worker * @{
615*4dc78e53SAndroid Build Coastguard Worker */
616*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_alloc_cache(struct nl_sock * sk,struct nl_cache ** result)617*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
618*4dc78e53SAndroid Build Coastguard Worker {
619*4dc78e53SAndroid Build Coastguard Worker return nl_cache_alloc_and_fill(&rtnl_addr_ops, sk, result);
620*4dc78e53SAndroid Build Coastguard Worker }
621*4dc78e53SAndroid Build Coastguard Worker
622*4dc78e53SAndroid Build Coastguard Worker /**
623*4dc78e53SAndroid Build Coastguard Worker * Search address in cache
624*4dc78e53SAndroid Build Coastguard Worker * @arg cache Address cache
625*4dc78e53SAndroid Build Coastguard Worker * @arg ifindex Interface index of address
626*4dc78e53SAndroid Build Coastguard Worker * @arg addr Local address part
627*4dc78e53SAndroid Build Coastguard Worker *
628*4dc78e53SAndroid Build Coastguard Worker * Searches address cache previously allocated with rtnl_addr_alloc_cache()
629*4dc78e53SAndroid Build Coastguard Worker * for an address with a matching local address.
630*4dc78e53SAndroid Build Coastguard Worker *
631*4dc78e53SAndroid Build Coastguard Worker * The reference counter is incremented before returning the address, therefore
632*4dc78e53SAndroid Build Coastguard Worker * the reference must be given back with rtnl_addr_put() after usage.
633*4dc78e53SAndroid Build Coastguard Worker *
634*4dc78e53SAndroid Build Coastguard Worker * @return Address object or NULL if no match was found.
635*4dc78e53SAndroid Build Coastguard Worker */
rtnl_addr_get(struct nl_cache * cache,int ifindex,struct nl_addr * addr)636*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr *rtnl_addr_get(struct nl_cache *cache, int ifindex,
637*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *addr)
638*4dc78e53SAndroid Build Coastguard Worker {
639*4dc78e53SAndroid Build Coastguard Worker struct rtnl_addr *a;
640*4dc78e53SAndroid Build Coastguard Worker
641*4dc78e53SAndroid Build Coastguard Worker if (cache->c_ops != &rtnl_addr_ops)
642*4dc78e53SAndroid Build Coastguard Worker return NULL;
643*4dc78e53SAndroid Build Coastguard Worker
644*4dc78e53SAndroid Build Coastguard Worker nl_list_for_each_entry(a, &cache->c_items, ce_list) {
645*4dc78e53SAndroid Build Coastguard Worker if (ifindex != 0 && a->a_ifindex != ((unsigned)ifindex))
646*4dc78e53SAndroid Build Coastguard Worker continue;
647*4dc78e53SAndroid Build Coastguard Worker
648*4dc78e53SAndroid Build Coastguard Worker if (a->ce_mask & ADDR_ATTR_LOCAL &&
649*4dc78e53SAndroid Build Coastguard Worker !nl_addr_cmp(a->a_local, addr)) {
650*4dc78e53SAndroid Build Coastguard Worker nl_object_get((struct nl_object *) a);
651*4dc78e53SAndroid Build Coastguard Worker return a;
652*4dc78e53SAndroid Build Coastguard Worker }
653*4dc78e53SAndroid Build Coastguard Worker }
654*4dc78e53SAndroid Build Coastguard Worker
655*4dc78e53SAndroid Build Coastguard Worker return NULL;
656*4dc78e53SAndroid Build Coastguard Worker }
657*4dc78e53SAndroid Build Coastguard Worker
658*4dc78e53SAndroid Build Coastguard Worker /** @} */
659*4dc78e53SAndroid Build Coastguard Worker
build_addr_msg(struct rtnl_addr * tmpl,int cmd,int flags,struct nl_msg ** result)660*4dc78e53SAndroid Build Coastguard Worker static int build_addr_msg(struct rtnl_addr *tmpl, int cmd, int flags,
661*4dc78e53SAndroid Build Coastguard Worker struct nl_msg **result)
662*4dc78e53SAndroid Build Coastguard Worker {
663*4dc78e53SAndroid Build Coastguard Worker struct nl_msg *msg;
664*4dc78e53SAndroid Build Coastguard Worker struct ifaddrmsg am = {
665*4dc78e53SAndroid Build Coastguard Worker .ifa_family = tmpl->a_family,
666*4dc78e53SAndroid Build Coastguard Worker .ifa_index = tmpl->a_ifindex,
667*4dc78e53SAndroid Build Coastguard Worker .ifa_prefixlen = tmpl->a_prefixlen,
668*4dc78e53SAndroid Build Coastguard Worker .ifa_flags = tmpl->a_flags,
669*4dc78e53SAndroid Build Coastguard Worker };
670*4dc78e53SAndroid Build Coastguard Worker
671*4dc78e53SAndroid Build Coastguard Worker if (tmpl->ce_mask & ADDR_ATTR_SCOPE)
672*4dc78e53SAndroid Build Coastguard Worker am.ifa_scope = tmpl->a_scope;
673*4dc78e53SAndroid Build Coastguard Worker else {
674*4dc78e53SAndroid Build Coastguard Worker /* compatibility hack */
675*4dc78e53SAndroid Build Coastguard Worker if (tmpl->a_family == AF_INET &&
676*4dc78e53SAndroid Build Coastguard Worker tmpl->ce_mask & ADDR_ATTR_LOCAL &&
677*4dc78e53SAndroid Build Coastguard Worker *((char *) nl_addr_get_binary_addr(tmpl->a_local)) == 127)
678*4dc78e53SAndroid Build Coastguard Worker am.ifa_scope = RT_SCOPE_HOST;
679*4dc78e53SAndroid Build Coastguard Worker else
680*4dc78e53SAndroid Build Coastguard Worker am.ifa_scope = RT_SCOPE_UNIVERSE;
681*4dc78e53SAndroid Build Coastguard Worker }
682*4dc78e53SAndroid Build Coastguard Worker
683*4dc78e53SAndroid Build Coastguard Worker msg = nlmsg_alloc_simple(cmd, flags);
684*4dc78e53SAndroid Build Coastguard Worker if (!msg)
685*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
686*4dc78e53SAndroid Build Coastguard Worker
687*4dc78e53SAndroid Build Coastguard Worker if (nlmsg_append(msg, &am, sizeof(am), NLMSG_ALIGNTO) < 0)
688*4dc78e53SAndroid Build Coastguard Worker goto nla_put_failure;
689*4dc78e53SAndroid Build Coastguard Worker
690*4dc78e53SAndroid Build Coastguard Worker if (tmpl->ce_mask & ADDR_ATTR_LOCAL)
691*4dc78e53SAndroid Build Coastguard Worker NLA_PUT_ADDR(msg, IFA_LOCAL, tmpl->a_local);
692*4dc78e53SAndroid Build Coastguard Worker
693*4dc78e53SAndroid Build Coastguard Worker if (tmpl->ce_mask & ADDR_ATTR_PEER)
694*4dc78e53SAndroid Build Coastguard Worker NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_peer);
695*4dc78e53SAndroid Build Coastguard Worker else if (tmpl->ce_mask & ADDR_ATTR_LOCAL)
696*4dc78e53SAndroid Build Coastguard Worker NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_local);
697*4dc78e53SAndroid Build Coastguard Worker
698*4dc78e53SAndroid Build Coastguard Worker if (tmpl->ce_mask & ADDR_ATTR_LABEL)
699*4dc78e53SAndroid Build Coastguard Worker NLA_PUT_STRING(msg, IFA_LABEL, tmpl->a_label);
700*4dc78e53SAndroid Build Coastguard Worker
701*4dc78e53SAndroid Build Coastguard Worker if (tmpl->ce_mask & ADDR_ATTR_BROADCAST)
702*4dc78e53SAndroid Build Coastguard Worker NLA_PUT_ADDR(msg, IFA_BROADCAST, tmpl->a_bcast);
703*4dc78e53SAndroid Build Coastguard Worker
704*4dc78e53SAndroid Build Coastguard Worker if (tmpl->ce_mask & ADDR_ATTR_CACHEINFO) {
705*4dc78e53SAndroid Build Coastguard Worker struct ifa_cacheinfo ca = {
706*4dc78e53SAndroid Build Coastguard Worker .ifa_valid = tmpl->a_cacheinfo.aci_valid,
707*4dc78e53SAndroid Build Coastguard Worker .ifa_prefered = tmpl->a_cacheinfo.aci_prefered,
708*4dc78e53SAndroid Build Coastguard Worker };
709*4dc78e53SAndroid Build Coastguard Worker
710*4dc78e53SAndroid Build Coastguard Worker NLA_PUT(msg, IFA_CACHEINFO, sizeof(ca), &ca);
711*4dc78e53SAndroid Build Coastguard Worker }
712*4dc78e53SAndroid Build Coastguard Worker
713*4dc78e53SAndroid Build Coastguard Worker if (tmpl->a_flags & ~0xFF) {
714*4dc78e53SAndroid Build Coastguard Worker /* only set the IFA_FLAGS attribute, if they actually contain additional
715*4dc78e53SAndroid Build Coastguard Worker * flags that are not already set to am.ifa_flags.
716*4dc78e53SAndroid Build Coastguard Worker *
717*4dc78e53SAndroid Build Coastguard Worker * Older kernels refuse RTM_NEWADDR and RTM_NEWROUTE messages with EINVAL
718*4dc78e53SAndroid Build Coastguard Worker * if they contain unknown netlink attributes. See net/core/rtnetlink.c, which
719*4dc78e53SAndroid Build Coastguard Worker * was fixed by kernel commit 661d2967b3f1b34eeaa7e212e7b9bbe8ee072b59.
720*4dc78e53SAndroid Build Coastguard Worker *
721*4dc78e53SAndroid Build Coastguard Worker * With this workaround, libnl will function correctly with older kernels,
722*4dc78e53SAndroid Build Coastguard Worker * unless there is a new libnl user that wants to set these flags. In this
723*4dc78e53SAndroid Build Coastguard Worker * case it's up to the user to workaround this issue. */
724*4dc78e53SAndroid Build Coastguard Worker NLA_PUT_U32(msg, IFA_FLAGS, tmpl->a_flags);
725*4dc78e53SAndroid Build Coastguard Worker }
726*4dc78e53SAndroid Build Coastguard Worker
727*4dc78e53SAndroid Build Coastguard Worker *result = msg;
728*4dc78e53SAndroid Build Coastguard Worker return 0;
729*4dc78e53SAndroid Build Coastguard Worker
730*4dc78e53SAndroid Build Coastguard Worker nla_put_failure:
731*4dc78e53SAndroid Build Coastguard Worker nlmsg_free(msg);
732*4dc78e53SAndroid Build Coastguard Worker return -NLE_MSGSIZE;
733*4dc78e53SAndroid Build Coastguard Worker }
734*4dc78e53SAndroid Build Coastguard Worker
735*4dc78e53SAndroid Build Coastguard Worker /**
736*4dc78e53SAndroid Build Coastguard Worker * @name Addition
737*4dc78e53SAndroid Build Coastguard Worker * @{
738*4dc78e53SAndroid Build Coastguard Worker */
739*4dc78e53SAndroid Build Coastguard Worker
740*4dc78e53SAndroid Build Coastguard Worker /**
741*4dc78e53SAndroid Build Coastguard Worker * Build netlink request message to request addition of new address
742*4dc78e53SAndroid Build Coastguard Worker * @arg addr Address object representing the new address.
743*4dc78e53SAndroid Build Coastguard Worker * @arg flags Additional netlink message flags.
744*4dc78e53SAndroid Build Coastguard Worker * @arg result Pointer to store resulting message.
745*4dc78e53SAndroid Build Coastguard Worker *
746*4dc78e53SAndroid Build Coastguard Worker * Builds a new netlink message requesting the addition of a new
747*4dc78e53SAndroid Build Coastguard Worker * address. The netlink message header isn't fully equipped with
748*4dc78e53SAndroid Build Coastguard Worker * all relevant fields and must thus be sent out via nl_send_auto_complete()
749*4dc78e53SAndroid Build Coastguard Worker * or supplemented as needed.
750*4dc78e53SAndroid Build Coastguard Worker *
751*4dc78e53SAndroid Build Coastguard Worker * Minimal required attributes:
752*4dc78e53SAndroid Build Coastguard Worker * - interface index (rtnl_addr_set_ifindex())
753*4dc78e53SAndroid Build Coastguard Worker * - local address (rtnl_addr_set_local())
754*4dc78e53SAndroid Build Coastguard Worker *
755*4dc78e53SAndroid Build Coastguard Worker * The scope will default to universe except for loopback addresses in
756*4dc78e53SAndroid Build Coastguard Worker * which case a host scope is used if not specified otherwise.
757*4dc78e53SAndroid Build Coastguard Worker *
758*4dc78e53SAndroid Build Coastguard Worker * @note Free the memory after usage using nlmsg_free().
759*4dc78e53SAndroid Build Coastguard Worker *
760*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
761*4dc78e53SAndroid Build Coastguard Worker */
rtnl_addr_build_add_request(struct rtnl_addr * addr,int flags,struct nl_msg ** result)762*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags,
763*4dc78e53SAndroid Build Coastguard Worker struct nl_msg **result)
764*4dc78e53SAndroid Build Coastguard Worker {
765*4dc78e53SAndroid Build Coastguard Worker uint32_t required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY |
766*4dc78e53SAndroid Build Coastguard Worker ADDR_ATTR_PREFIXLEN | ADDR_ATTR_LOCAL;
767*4dc78e53SAndroid Build Coastguard Worker
768*4dc78e53SAndroid Build Coastguard Worker if ((addr->ce_mask & required) != required)
769*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
770*4dc78e53SAndroid Build Coastguard Worker
771*4dc78e53SAndroid Build Coastguard Worker return build_addr_msg(addr, RTM_NEWADDR, NLM_F_CREATE | flags, result);
772*4dc78e53SAndroid Build Coastguard Worker }
773*4dc78e53SAndroid Build Coastguard Worker
774*4dc78e53SAndroid Build Coastguard Worker /**
775*4dc78e53SAndroid Build Coastguard Worker * Request addition of new address
776*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket.
777*4dc78e53SAndroid Build Coastguard Worker * @arg addr Address object representing the new address.
778*4dc78e53SAndroid Build Coastguard Worker * @arg flags Additional netlink message flags.
779*4dc78e53SAndroid Build Coastguard Worker *
780*4dc78e53SAndroid Build Coastguard Worker * Builds a netlink message by calling rtnl_addr_build_add_request(),
781*4dc78e53SAndroid Build Coastguard Worker * sends the request to the kernel and waits for the next ACK to be
782*4dc78e53SAndroid Build Coastguard Worker * received and thus blocks until the request has been fullfilled.
783*4dc78e53SAndroid Build Coastguard Worker *
784*4dc78e53SAndroid Build Coastguard Worker * @see rtnl_addr_build_add_request()
785*4dc78e53SAndroid Build Coastguard Worker *
786*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error if an error occured.
787*4dc78e53SAndroid Build Coastguard Worker */
rtnl_addr_add(struct nl_sock * sk,struct rtnl_addr * addr,int flags)788*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_add(struct nl_sock *sk, struct rtnl_addr *addr, int flags)
789*4dc78e53SAndroid Build Coastguard Worker {
790*4dc78e53SAndroid Build Coastguard Worker struct nl_msg *msg;
791*4dc78e53SAndroid Build Coastguard Worker int err;
792*4dc78e53SAndroid Build Coastguard Worker
793*4dc78e53SAndroid Build Coastguard Worker if ((err = rtnl_addr_build_add_request(addr, flags, &msg)) < 0)
794*4dc78e53SAndroid Build Coastguard Worker return err;
795*4dc78e53SAndroid Build Coastguard Worker
796*4dc78e53SAndroid Build Coastguard Worker err = nl_send_auto_complete(sk, msg);
797*4dc78e53SAndroid Build Coastguard Worker nlmsg_free(msg);
798*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
799*4dc78e53SAndroid Build Coastguard Worker return err;
800*4dc78e53SAndroid Build Coastguard Worker
801*4dc78e53SAndroid Build Coastguard Worker return wait_for_ack(sk);
802*4dc78e53SAndroid Build Coastguard Worker }
803*4dc78e53SAndroid Build Coastguard Worker
804*4dc78e53SAndroid Build Coastguard Worker /** @} */
805*4dc78e53SAndroid Build Coastguard Worker
806*4dc78e53SAndroid Build Coastguard Worker /**
807*4dc78e53SAndroid Build Coastguard Worker * @name Deletion
808*4dc78e53SAndroid Build Coastguard Worker * @{
809*4dc78e53SAndroid Build Coastguard Worker */
810*4dc78e53SAndroid Build Coastguard Worker
811*4dc78e53SAndroid Build Coastguard Worker /**
812*4dc78e53SAndroid Build Coastguard Worker * Build a netlink request message to request deletion of an address
813*4dc78e53SAndroid Build Coastguard Worker * @arg addr Address object to be deleteted.
814*4dc78e53SAndroid Build Coastguard Worker * @arg flags Additional netlink message flags.
815*4dc78e53SAndroid Build Coastguard Worker * @arg result Pointer to store resulting message.
816*4dc78e53SAndroid Build Coastguard Worker *
817*4dc78e53SAndroid Build Coastguard Worker * Builds a new netlink message requesting a deletion of an address.
818*4dc78e53SAndroid Build Coastguard Worker * The netlink message header isn't fully equipped with all relevant
819*4dc78e53SAndroid Build Coastguard Worker * fields and must thus be sent out via nl_send_auto_complete()
820*4dc78e53SAndroid Build Coastguard Worker * or supplemented as needed.
821*4dc78e53SAndroid Build Coastguard Worker *
822*4dc78e53SAndroid Build Coastguard Worker * Minimal required attributes:
823*4dc78e53SAndroid Build Coastguard Worker * - interface index (rtnl_addr_set_ifindex())
824*4dc78e53SAndroid Build Coastguard Worker * - address family (rtnl_addr_set_family())
825*4dc78e53SAndroid Build Coastguard Worker *
826*4dc78e53SAndroid Build Coastguard Worker * Optional attributes:
827*4dc78e53SAndroid Build Coastguard Worker * - local address (rtnl_addr_set_local())
828*4dc78e53SAndroid Build Coastguard Worker * - label (rtnl_addr_set_label(), IPv4/DECnet only)
829*4dc78e53SAndroid Build Coastguard Worker * - peer address (rtnl_addr_set_peer(), IPv4 only)
830*4dc78e53SAndroid Build Coastguard Worker *
831*4dc78e53SAndroid Build Coastguard Worker * @note Free the memory after usage using nlmsg_free().
832*4dc78e53SAndroid Build Coastguard Worker *
833*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
834*4dc78e53SAndroid Build Coastguard Worker */
rtnl_addr_build_delete_request(struct rtnl_addr * addr,int flags,struct nl_msg ** result)835*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_build_delete_request(struct rtnl_addr *addr, int flags,
836*4dc78e53SAndroid Build Coastguard Worker struct nl_msg **result)
837*4dc78e53SAndroid Build Coastguard Worker {
838*4dc78e53SAndroid Build Coastguard Worker uint32_t required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY;
839*4dc78e53SAndroid Build Coastguard Worker
840*4dc78e53SAndroid Build Coastguard Worker if ((addr->ce_mask & required) != required)
841*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
842*4dc78e53SAndroid Build Coastguard Worker
843*4dc78e53SAndroid Build Coastguard Worker return build_addr_msg(addr, RTM_DELADDR, flags, result);
844*4dc78e53SAndroid Build Coastguard Worker }
845*4dc78e53SAndroid Build Coastguard Worker
846*4dc78e53SAndroid Build Coastguard Worker /**
847*4dc78e53SAndroid Build Coastguard Worker * Request deletion of an address
848*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket.
849*4dc78e53SAndroid Build Coastguard Worker * @arg addr Address object to be deleted.
850*4dc78e53SAndroid Build Coastguard Worker * @arg flags Additional netlink message flags.
851*4dc78e53SAndroid Build Coastguard Worker *
852*4dc78e53SAndroid Build Coastguard Worker * Builds a netlink message by calling rtnl_addr_build_delete_request(),
853*4dc78e53SAndroid Build Coastguard Worker * sends the request to the kernel and waits for the next ACK to be
854*4dc78e53SAndroid Build Coastguard Worker * received and thus blocks until the request has been fullfilled.
855*4dc78e53SAndroid Build Coastguard Worker *
856*4dc78e53SAndroid Build Coastguard Worker * @see rtnl_addr_build_delete_request();
857*4dc78e53SAndroid Build Coastguard Worker *
858*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error if an error occured.
859*4dc78e53SAndroid Build Coastguard Worker */
rtnl_addr_delete(struct nl_sock * sk,struct rtnl_addr * addr,int flags)860*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_delete(struct nl_sock *sk, struct rtnl_addr *addr, int flags)
861*4dc78e53SAndroid Build Coastguard Worker {
862*4dc78e53SAndroid Build Coastguard Worker struct nl_msg *msg;
863*4dc78e53SAndroid Build Coastguard Worker int err;
864*4dc78e53SAndroid Build Coastguard Worker
865*4dc78e53SAndroid Build Coastguard Worker if ((err = rtnl_addr_build_delete_request(addr, flags, &msg)) < 0)
866*4dc78e53SAndroid Build Coastguard Worker return err;
867*4dc78e53SAndroid Build Coastguard Worker
868*4dc78e53SAndroid Build Coastguard Worker err = nl_send_auto_complete(sk, msg);
869*4dc78e53SAndroid Build Coastguard Worker nlmsg_free(msg);
870*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
871*4dc78e53SAndroid Build Coastguard Worker return err;
872*4dc78e53SAndroid Build Coastguard Worker
873*4dc78e53SAndroid Build Coastguard Worker return wait_for_ack(sk);
874*4dc78e53SAndroid Build Coastguard Worker }
875*4dc78e53SAndroid Build Coastguard Worker
876*4dc78e53SAndroid Build Coastguard Worker /** @} */
877*4dc78e53SAndroid Build Coastguard Worker
878*4dc78e53SAndroid Build Coastguard Worker /**
879*4dc78e53SAndroid Build Coastguard Worker * @name Attributes
880*4dc78e53SAndroid Build Coastguard Worker * @{
881*4dc78e53SAndroid Build Coastguard Worker */
882*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_set_label(struct rtnl_addr * addr,const char * label)883*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_set_label(struct rtnl_addr *addr, const char *label)
884*4dc78e53SAndroid Build Coastguard Worker {
885*4dc78e53SAndroid Build Coastguard Worker if (strlen(label) > sizeof(addr->a_label) - 1)
886*4dc78e53SAndroid Build Coastguard Worker return -NLE_RANGE;
887*4dc78e53SAndroid Build Coastguard Worker
888*4dc78e53SAndroid Build Coastguard Worker strcpy(addr->a_label, label);
889*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_LABEL;
890*4dc78e53SAndroid Build Coastguard Worker
891*4dc78e53SAndroid Build Coastguard Worker return 0;
892*4dc78e53SAndroid Build Coastguard Worker }
893*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_label(struct rtnl_addr * addr)894*4dc78e53SAndroid Build Coastguard Worker char *rtnl_addr_get_label(struct rtnl_addr *addr)
895*4dc78e53SAndroid Build Coastguard Worker {
896*4dc78e53SAndroid Build Coastguard Worker if (addr->ce_mask & ADDR_ATTR_LABEL)
897*4dc78e53SAndroid Build Coastguard Worker return addr->a_label;
898*4dc78e53SAndroid Build Coastguard Worker else
899*4dc78e53SAndroid Build Coastguard Worker return NULL;
900*4dc78e53SAndroid Build Coastguard Worker }
901*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_set_ifindex(struct rtnl_addr * addr,int ifindex)902*4dc78e53SAndroid Build Coastguard Worker void rtnl_addr_set_ifindex(struct rtnl_addr *addr, int ifindex)
903*4dc78e53SAndroid Build Coastguard Worker {
904*4dc78e53SAndroid Build Coastguard Worker addr->a_ifindex = ifindex;
905*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_IFINDEX;
906*4dc78e53SAndroid Build Coastguard Worker }
907*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_ifindex(struct rtnl_addr * addr)908*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_get_ifindex(struct rtnl_addr *addr)
909*4dc78e53SAndroid Build Coastguard Worker {
910*4dc78e53SAndroid Build Coastguard Worker return addr->a_ifindex;
911*4dc78e53SAndroid Build Coastguard Worker }
912*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_set_link(struct rtnl_addr * addr,struct rtnl_link * link)913*4dc78e53SAndroid Build Coastguard Worker void rtnl_addr_set_link(struct rtnl_addr *addr, struct rtnl_link *link)
914*4dc78e53SAndroid Build Coastguard Worker {
915*4dc78e53SAndroid Build Coastguard Worker rtnl_link_put(addr->a_link);
916*4dc78e53SAndroid Build Coastguard Worker
917*4dc78e53SAndroid Build Coastguard Worker if (!link)
918*4dc78e53SAndroid Build Coastguard Worker return;
919*4dc78e53SAndroid Build Coastguard Worker
920*4dc78e53SAndroid Build Coastguard Worker nl_object_get(OBJ_CAST(link));
921*4dc78e53SAndroid Build Coastguard Worker addr->a_link = link;
922*4dc78e53SAndroid Build Coastguard Worker addr->a_ifindex = link->l_index;
923*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_IFINDEX;
924*4dc78e53SAndroid Build Coastguard Worker }
925*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_link(struct rtnl_addr * addr)926*4dc78e53SAndroid Build Coastguard Worker struct rtnl_link *rtnl_addr_get_link(struct rtnl_addr *addr)
927*4dc78e53SAndroid Build Coastguard Worker {
928*4dc78e53SAndroid Build Coastguard Worker if (addr->a_link) {
929*4dc78e53SAndroid Build Coastguard Worker nl_object_get(OBJ_CAST(addr->a_link));
930*4dc78e53SAndroid Build Coastguard Worker return addr->a_link;
931*4dc78e53SAndroid Build Coastguard Worker }
932*4dc78e53SAndroid Build Coastguard Worker
933*4dc78e53SAndroid Build Coastguard Worker return NULL;
934*4dc78e53SAndroid Build Coastguard Worker }
935*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_set_family(struct rtnl_addr * addr,int family)936*4dc78e53SAndroid Build Coastguard Worker void rtnl_addr_set_family(struct rtnl_addr *addr, int family)
937*4dc78e53SAndroid Build Coastguard Worker {
938*4dc78e53SAndroid Build Coastguard Worker addr->a_family = family;
939*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_FAMILY;
940*4dc78e53SAndroid Build Coastguard Worker }
941*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_family(struct rtnl_addr * addr)942*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_get_family(struct rtnl_addr *addr)
943*4dc78e53SAndroid Build Coastguard Worker {
944*4dc78e53SAndroid Build Coastguard Worker return addr->a_family;
945*4dc78e53SAndroid Build Coastguard Worker }
946*4dc78e53SAndroid Build Coastguard Worker
947*4dc78e53SAndroid Build Coastguard Worker /**
948*4dc78e53SAndroid Build Coastguard Worker * Set the prefix length / netmask
949*4dc78e53SAndroid Build Coastguard Worker * @arg addr Address
950*4dc78e53SAndroid Build Coastguard Worker * @arg prefixlen Length of prefix (netmask)
951*4dc78e53SAndroid Build Coastguard Worker *
952*4dc78e53SAndroid Build Coastguard Worker * Modifies the length of the prefix. If the address object contains a peer
953*4dc78e53SAndroid Build Coastguard Worker * address the prefix length will apply to it, otherwise the prefix length
954*4dc78e53SAndroid Build Coastguard Worker * will apply to the local address of the address.
955*4dc78e53SAndroid Build Coastguard Worker *
956*4dc78e53SAndroid Build Coastguard Worker * If the address object contains a peer or local address the corresponding
957*4dc78e53SAndroid Build Coastguard Worker * `struct nl_addr` will be updated with the new prefix length.
958*4dc78e53SAndroid Build Coastguard Worker *
959*4dc78e53SAndroid Build Coastguard Worker * @note Specifying a length of 0 will remove the prefix length alltogether.
960*4dc78e53SAndroid Build Coastguard Worker *
961*4dc78e53SAndroid Build Coastguard Worker * @see rtnl_addr_get_prefixlen()
962*4dc78e53SAndroid Build Coastguard Worker */
rtnl_addr_set_prefixlen(struct rtnl_addr * addr,int prefixlen)963*4dc78e53SAndroid Build Coastguard Worker void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefixlen)
964*4dc78e53SAndroid Build Coastguard Worker {
965*4dc78e53SAndroid Build Coastguard Worker addr->a_prefixlen = prefixlen;
966*4dc78e53SAndroid Build Coastguard Worker
967*4dc78e53SAndroid Build Coastguard Worker if (prefixlen)
968*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_PREFIXLEN;
969*4dc78e53SAndroid Build Coastguard Worker else
970*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask &= ~ADDR_ATTR_PREFIXLEN;
971*4dc78e53SAndroid Build Coastguard Worker
972*4dc78e53SAndroid Build Coastguard Worker /*
973*4dc78e53SAndroid Build Coastguard Worker * The prefix length always applies to the peer address if
974*4dc78e53SAndroid Build Coastguard Worker * a peer address is present.
975*4dc78e53SAndroid Build Coastguard Worker */
976*4dc78e53SAndroid Build Coastguard Worker if (addr->a_peer)
977*4dc78e53SAndroid Build Coastguard Worker nl_addr_set_prefixlen(addr->a_peer, prefixlen);
978*4dc78e53SAndroid Build Coastguard Worker else if (addr->a_local)
979*4dc78e53SAndroid Build Coastguard Worker nl_addr_set_prefixlen(addr->a_local, prefixlen);
980*4dc78e53SAndroid Build Coastguard Worker }
981*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_prefixlen(struct rtnl_addr * addr)982*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_get_prefixlen(struct rtnl_addr *addr)
983*4dc78e53SAndroid Build Coastguard Worker {
984*4dc78e53SAndroid Build Coastguard Worker return addr->a_prefixlen;
985*4dc78e53SAndroid Build Coastguard Worker }
986*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_set_scope(struct rtnl_addr * addr,int scope)987*4dc78e53SAndroid Build Coastguard Worker void rtnl_addr_set_scope(struct rtnl_addr *addr, int scope)
988*4dc78e53SAndroid Build Coastguard Worker {
989*4dc78e53SAndroid Build Coastguard Worker addr->a_scope = scope;
990*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_SCOPE;
991*4dc78e53SAndroid Build Coastguard Worker }
992*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_scope(struct rtnl_addr * addr)993*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_get_scope(struct rtnl_addr *addr)
994*4dc78e53SAndroid Build Coastguard Worker {
995*4dc78e53SAndroid Build Coastguard Worker return addr->a_scope;
996*4dc78e53SAndroid Build Coastguard Worker }
997*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_set_flags(struct rtnl_addr * addr,unsigned int flags)998*4dc78e53SAndroid Build Coastguard Worker void rtnl_addr_set_flags(struct rtnl_addr *addr, unsigned int flags)
999*4dc78e53SAndroid Build Coastguard Worker {
1000*4dc78e53SAndroid Build Coastguard Worker addr->a_flag_mask |= flags;
1001*4dc78e53SAndroid Build Coastguard Worker addr->a_flags |= flags;
1002*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_FLAGS;
1003*4dc78e53SAndroid Build Coastguard Worker }
1004*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_unset_flags(struct rtnl_addr * addr,unsigned int flags)1005*4dc78e53SAndroid Build Coastguard Worker void rtnl_addr_unset_flags(struct rtnl_addr *addr, unsigned int flags)
1006*4dc78e53SAndroid Build Coastguard Worker {
1007*4dc78e53SAndroid Build Coastguard Worker addr->a_flag_mask |= flags;
1008*4dc78e53SAndroid Build Coastguard Worker addr->a_flags &= ~flags;
1009*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_FLAGS;
1010*4dc78e53SAndroid Build Coastguard Worker }
1011*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_flags(struct rtnl_addr * addr)1012*4dc78e53SAndroid Build Coastguard Worker unsigned int rtnl_addr_get_flags(struct rtnl_addr *addr)
1013*4dc78e53SAndroid Build Coastguard Worker {
1014*4dc78e53SAndroid Build Coastguard Worker return addr->a_flags;
1015*4dc78e53SAndroid Build Coastguard Worker }
1016*4dc78e53SAndroid Build Coastguard Worker
__assign_addr(struct rtnl_addr * addr,struct nl_addr ** pos,struct nl_addr * new,int flag)1017*4dc78e53SAndroid Build Coastguard Worker static inline int __assign_addr(struct rtnl_addr *addr, struct nl_addr **pos,
1018*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *new, int flag)
1019*4dc78e53SAndroid Build Coastguard Worker {
1020*4dc78e53SAndroid Build Coastguard Worker if (new) {
1021*4dc78e53SAndroid Build Coastguard Worker if (addr->ce_mask & ADDR_ATTR_FAMILY) {
1022*4dc78e53SAndroid Build Coastguard Worker if (new->a_family != addr->a_family)
1023*4dc78e53SAndroid Build Coastguard Worker return -NLE_AF_MISMATCH;
1024*4dc78e53SAndroid Build Coastguard Worker } else
1025*4dc78e53SAndroid Build Coastguard Worker addr->a_family = new->a_family;
1026*4dc78e53SAndroid Build Coastguard Worker
1027*4dc78e53SAndroid Build Coastguard Worker if (*pos)
1028*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(*pos);
1029*4dc78e53SAndroid Build Coastguard Worker
1030*4dc78e53SAndroid Build Coastguard Worker *pos = nl_addr_get(new);
1031*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= (flag | ADDR_ATTR_FAMILY);
1032*4dc78e53SAndroid Build Coastguard Worker } else {
1033*4dc78e53SAndroid Build Coastguard Worker if (*pos)
1034*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(*pos);
1035*4dc78e53SAndroid Build Coastguard Worker
1036*4dc78e53SAndroid Build Coastguard Worker *pos = NULL;
1037*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask &= ~flag;
1038*4dc78e53SAndroid Build Coastguard Worker }
1039*4dc78e53SAndroid Build Coastguard Worker
1040*4dc78e53SAndroid Build Coastguard Worker return 0;
1041*4dc78e53SAndroid Build Coastguard Worker }
1042*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_set_local(struct rtnl_addr * addr,struct nl_addr * local)1043*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_set_local(struct rtnl_addr *addr, struct nl_addr *local)
1044*4dc78e53SAndroid Build Coastguard Worker {
1045*4dc78e53SAndroid Build Coastguard Worker int err;
1046*4dc78e53SAndroid Build Coastguard Worker
1047*4dc78e53SAndroid Build Coastguard Worker /* Prohibit local address with prefix length if peer address is present */
1048*4dc78e53SAndroid Build Coastguard Worker if ((addr->ce_mask & ADDR_ATTR_PEER) && local &&
1049*4dc78e53SAndroid Build Coastguard Worker nl_addr_get_prefixlen(local))
1050*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
1051*4dc78e53SAndroid Build Coastguard Worker
1052*4dc78e53SAndroid Build Coastguard Worker err = __assign_addr(addr, &addr->a_local, local, ADDR_ATTR_LOCAL);
1053*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
1054*4dc78e53SAndroid Build Coastguard Worker return err;
1055*4dc78e53SAndroid Build Coastguard Worker
1056*4dc78e53SAndroid Build Coastguard Worker /* Never overwrite the prefix length if a peer address is present */
1057*4dc78e53SAndroid Build Coastguard Worker if (!(addr->ce_mask & ADDR_ATTR_PEER))
1058*4dc78e53SAndroid Build Coastguard Worker rtnl_addr_set_prefixlen(addr, local ? nl_addr_get_prefixlen(local) : 0);
1059*4dc78e53SAndroid Build Coastguard Worker
1060*4dc78e53SAndroid Build Coastguard Worker return 0;
1061*4dc78e53SAndroid Build Coastguard Worker }
1062*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_local(struct rtnl_addr * addr)1063*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr)
1064*4dc78e53SAndroid Build Coastguard Worker {
1065*4dc78e53SAndroid Build Coastguard Worker return addr->a_local;
1066*4dc78e53SAndroid Build Coastguard Worker }
1067*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_set_peer(struct rtnl_addr * addr,struct nl_addr * peer)1068*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_set_peer(struct rtnl_addr *addr, struct nl_addr *peer)
1069*4dc78e53SAndroid Build Coastguard Worker {
1070*4dc78e53SAndroid Build Coastguard Worker int err;
1071*4dc78e53SAndroid Build Coastguard Worker
1072*4dc78e53SAndroid Build Coastguard Worker if (peer && peer->a_family != AF_INET)
1073*4dc78e53SAndroid Build Coastguard Worker return -NLE_AF_NOSUPPORT;
1074*4dc78e53SAndroid Build Coastguard Worker
1075*4dc78e53SAndroid Build Coastguard Worker err = __assign_addr(addr, &addr->a_peer, peer, ADDR_ATTR_PEER);
1076*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
1077*4dc78e53SAndroid Build Coastguard Worker return err;
1078*4dc78e53SAndroid Build Coastguard Worker
1079*4dc78e53SAndroid Build Coastguard Worker rtnl_addr_set_prefixlen(addr, peer ? nl_addr_get_prefixlen(peer) : 0);
1080*4dc78e53SAndroid Build Coastguard Worker
1081*4dc78e53SAndroid Build Coastguard Worker return 0;
1082*4dc78e53SAndroid Build Coastguard Worker }
1083*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_peer(struct rtnl_addr * addr)1084*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr)
1085*4dc78e53SAndroid Build Coastguard Worker {
1086*4dc78e53SAndroid Build Coastguard Worker return addr->a_peer;
1087*4dc78e53SAndroid Build Coastguard Worker }
1088*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_set_broadcast(struct rtnl_addr * addr,struct nl_addr * bcast)1089*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_set_broadcast(struct rtnl_addr *addr, struct nl_addr *bcast)
1090*4dc78e53SAndroid Build Coastguard Worker {
1091*4dc78e53SAndroid Build Coastguard Worker if (bcast && bcast->a_family != AF_INET)
1092*4dc78e53SAndroid Build Coastguard Worker return -NLE_AF_NOSUPPORT;
1093*4dc78e53SAndroid Build Coastguard Worker
1094*4dc78e53SAndroid Build Coastguard Worker return __assign_addr(addr, &addr->a_bcast, bcast, ADDR_ATTR_BROADCAST);
1095*4dc78e53SAndroid Build Coastguard Worker }
1096*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_broadcast(struct rtnl_addr * addr)1097*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *addr)
1098*4dc78e53SAndroid Build Coastguard Worker {
1099*4dc78e53SAndroid Build Coastguard Worker return addr->a_bcast;
1100*4dc78e53SAndroid Build Coastguard Worker }
1101*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_set_multicast(struct rtnl_addr * addr,struct nl_addr * multicast)1102*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_set_multicast(struct rtnl_addr *addr, struct nl_addr *multicast)
1103*4dc78e53SAndroid Build Coastguard Worker {
1104*4dc78e53SAndroid Build Coastguard Worker if (multicast && multicast->a_family != AF_INET6)
1105*4dc78e53SAndroid Build Coastguard Worker return -NLE_AF_NOSUPPORT;
1106*4dc78e53SAndroid Build Coastguard Worker
1107*4dc78e53SAndroid Build Coastguard Worker return __assign_addr(addr, &addr->a_multicast, multicast,
1108*4dc78e53SAndroid Build Coastguard Worker ADDR_ATTR_MULTICAST);
1109*4dc78e53SAndroid Build Coastguard Worker }
1110*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_multicast(struct rtnl_addr * addr)1111*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr)
1112*4dc78e53SAndroid Build Coastguard Worker {
1113*4dc78e53SAndroid Build Coastguard Worker return addr->a_multicast;
1114*4dc78e53SAndroid Build Coastguard Worker }
1115*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_set_anycast(struct rtnl_addr * addr,struct nl_addr * anycast)1116*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_set_anycast(struct rtnl_addr *addr, struct nl_addr *anycast)
1117*4dc78e53SAndroid Build Coastguard Worker {
1118*4dc78e53SAndroid Build Coastguard Worker if (anycast && anycast->a_family != AF_INET6)
1119*4dc78e53SAndroid Build Coastguard Worker return -NLE_AF_NOSUPPORT;
1120*4dc78e53SAndroid Build Coastguard Worker
1121*4dc78e53SAndroid Build Coastguard Worker return __assign_addr(addr, &addr->a_anycast, anycast,
1122*4dc78e53SAndroid Build Coastguard Worker ADDR_ATTR_ANYCAST);
1123*4dc78e53SAndroid Build Coastguard Worker }
1124*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_anycast(struct rtnl_addr * addr)1125*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *addr)
1126*4dc78e53SAndroid Build Coastguard Worker {
1127*4dc78e53SAndroid Build Coastguard Worker return addr->a_anycast;
1128*4dc78e53SAndroid Build Coastguard Worker }
1129*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_valid_lifetime(struct rtnl_addr * addr)1130*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_addr_get_valid_lifetime(struct rtnl_addr *addr)
1131*4dc78e53SAndroid Build Coastguard Worker {
1132*4dc78e53SAndroid Build Coastguard Worker if (addr->ce_mask & ADDR_ATTR_CACHEINFO)
1133*4dc78e53SAndroid Build Coastguard Worker return addr->a_cacheinfo.aci_valid;
1134*4dc78e53SAndroid Build Coastguard Worker else
1135*4dc78e53SAndroid Build Coastguard Worker return 0xFFFFFFFFU;
1136*4dc78e53SAndroid Build Coastguard Worker }
1137*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_set_valid_lifetime(struct rtnl_addr * addr,uint32_t lifetime)1138*4dc78e53SAndroid Build Coastguard Worker void rtnl_addr_set_valid_lifetime(struct rtnl_addr *addr, uint32_t lifetime)
1139*4dc78e53SAndroid Build Coastguard Worker {
1140*4dc78e53SAndroid Build Coastguard Worker addr->a_cacheinfo.aci_valid = lifetime;
1141*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_CACHEINFO;
1142*4dc78e53SAndroid Build Coastguard Worker }
1143*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_preferred_lifetime(struct rtnl_addr * addr)1144*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_addr_get_preferred_lifetime(struct rtnl_addr *addr)
1145*4dc78e53SAndroid Build Coastguard Worker {
1146*4dc78e53SAndroid Build Coastguard Worker if (addr->ce_mask & ADDR_ATTR_CACHEINFO)
1147*4dc78e53SAndroid Build Coastguard Worker return addr->a_cacheinfo.aci_prefered;
1148*4dc78e53SAndroid Build Coastguard Worker else
1149*4dc78e53SAndroid Build Coastguard Worker return 0xFFFFFFFFU;
1150*4dc78e53SAndroid Build Coastguard Worker }
1151*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_set_preferred_lifetime(struct rtnl_addr * addr,uint32_t lifetime)1152*4dc78e53SAndroid Build Coastguard Worker void rtnl_addr_set_preferred_lifetime(struct rtnl_addr *addr, uint32_t lifetime)
1153*4dc78e53SAndroid Build Coastguard Worker {
1154*4dc78e53SAndroid Build Coastguard Worker addr->a_cacheinfo.aci_prefered = lifetime;
1155*4dc78e53SAndroid Build Coastguard Worker addr->ce_mask |= ADDR_ATTR_CACHEINFO;
1156*4dc78e53SAndroid Build Coastguard Worker }
1157*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_create_time(struct rtnl_addr * addr)1158*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_addr_get_create_time(struct rtnl_addr *addr)
1159*4dc78e53SAndroid Build Coastguard Worker {
1160*4dc78e53SAndroid Build Coastguard Worker return addr->a_cacheinfo.aci_cstamp;
1161*4dc78e53SAndroid Build Coastguard Worker }
1162*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_get_last_update_time(struct rtnl_addr * addr)1163*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_addr_get_last_update_time(struct rtnl_addr *addr)
1164*4dc78e53SAndroid Build Coastguard Worker {
1165*4dc78e53SAndroid Build Coastguard Worker return addr->a_cacheinfo.aci_tstamp;
1166*4dc78e53SAndroid Build Coastguard Worker }
1167*4dc78e53SAndroid Build Coastguard Worker
1168*4dc78e53SAndroid Build Coastguard Worker /** @} */
1169*4dc78e53SAndroid Build Coastguard Worker
1170*4dc78e53SAndroid Build Coastguard Worker /**
1171*4dc78e53SAndroid Build Coastguard Worker * @name Flags Translations
1172*4dc78e53SAndroid Build Coastguard Worker * @{
1173*4dc78e53SAndroid Build Coastguard Worker */
1174*4dc78e53SAndroid Build Coastguard Worker
1175*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl addr_flags[] = {
1176*4dc78e53SAndroid Build Coastguard Worker __ADD(IFA_F_SECONDARY, secondary),
1177*4dc78e53SAndroid Build Coastguard Worker __ADD(IFA_F_NODAD, nodad),
1178*4dc78e53SAndroid Build Coastguard Worker __ADD(IFA_F_OPTIMISTIC, optimistic),
1179*4dc78e53SAndroid Build Coastguard Worker __ADD(IFA_F_DADFAILED, dadfailed),
1180*4dc78e53SAndroid Build Coastguard Worker __ADD(IFA_F_HOMEADDRESS, homeaddress),
1181*4dc78e53SAndroid Build Coastguard Worker __ADD(IFA_F_DEPRECATED, deprecated),
1182*4dc78e53SAndroid Build Coastguard Worker __ADD(IFA_F_TENTATIVE, tentative),
1183*4dc78e53SAndroid Build Coastguard Worker __ADD(IFA_F_PERMANENT, permanent),
1184*4dc78e53SAndroid Build Coastguard Worker __ADD(IFA_F_MANAGETEMPADDR, mngtmpaddr),
1185*4dc78e53SAndroid Build Coastguard Worker __ADD(IFA_F_NOPREFIXROUTE, noprefixroute),
1186*4dc78e53SAndroid Build Coastguard Worker };
1187*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_flags2str(int flags,char * buf,size_t size)1188*4dc78e53SAndroid Build Coastguard Worker char *rtnl_addr_flags2str(int flags, char *buf, size_t size)
1189*4dc78e53SAndroid Build Coastguard Worker {
1190*4dc78e53SAndroid Build Coastguard Worker return __flags2str(flags, buf, size, addr_flags,
1191*4dc78e53SAndroid Build Coastguard Worker ARRAY_SIZE(addr_flags));
1192*4dc78e53SAndroid Build Coastguard Worker }
1193*4dc78e53SAndroid Build Coastguard Worker
rtnl_addr_str2flags(const char * name)1194*4dc78e53SAndroid Build Coastguard Worker int rtnl_addr_str2flags(const char *name)
1195*4dc78e53SAndroid Build Coastguard Worker {
1196*4dc78e53SAndroid Build Coastguard Worker return __str2flags(name, addr_flags, ARRAY_SIZE(addr_flags));
1197*4dc78e53SAndroid Build Coastguard Worker }
1198*4dc78e53SAndroid Build Coastguard Worker
1199*4dc78e53SAndroid Build Coastguard Worker /** @} */
1200*4dc78e53SAndroid Build Coastguard Worker
1201*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops addr_obj_ops = {
1202*4dc78e53SAndroid Build Coastguard Worker .oo_name = "route/addr",
1203*4dc78e53SAndroid Build Coastguard Worker .oo_size = sizeof(struct rtnl_addr),
1204*4dc78e53SAndroid Build Coastguard Worker .oo_constructor = addr_constructor,
1205*4dc78e53SAndroid Build Coastguard Worker .oo_free_data = addr_free_data,
1206*4dc78e53SAndroid Build Coastguard Worker .oo_clone = addr_clone,
1207*4dc78e53SAndroid Build Coastguard Worker .oo_dump = {
1208*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_LINE] = addr_dump_line,
1209*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_DETAILS] = addr_dump_details,
1210*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_STATS] = addr_dump_stats,
1211*4dc78e53SAndroid Build Coastguard Worker },
1212*4dc78e53SAndroid Build Coastguard Worker .oo_compare = addr_compare,
1213*4dc78e53SAndroid Build Coastguard Worker .oo_attrs2str = addr_attrs2str,
1214*4dc78e53SAndroid Build Coastguard Worker .oo_id_attrs_get = addr_id_attrs_get,
1215*4dc78e53SAndroid Build Coastguard Worker .oo_id_attrs = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX |
1216*4dc78e53SAndroid Build Coastguard Worker ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN),
1217*4dc78e53SAndroid Build Coastguard Worker };
1218*4dc78e53SAndroid Build Coastguard Worker
1219*4dc78e53SAndroid Build Coastguard Worker static struct nl_af_group addr_groups[] = {
1220*4dc78e53SAndroid Build Coastguard Worker { AF_INET, RTNLGRP_IPV4_IFADDR },
1221*4dc78e53SAndroid Build Coastguard Worker { AF_INET6, RTNLGRP_IPV6_IFADDR },
1222*4dc78e53SAndroid Build Coastguard Worker { END_OF_GROUP_LIST },
1223*4dc78e53SAndroid Build Coastguard Worker };
1224*4dc78e53SAndroid Build Coastguard Worker
1225*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_addr_ops = {
1226*4dc78e53SAndroid Build Coastguard Worker .co_name = "route/addr",
1227*4dc78e53SAndroid Build Coastguard Worker .co_hdrsize = sizeof(struct ifaddrmsg),
1228*4dc78e53SAndroid Build Coastguard Worker .co_msgtypes = {
1229*4dc78e53SAndroid Build Coastguard Worker { RTM_NEWADDR, NL_ACT_NEW, "new" },
1230*4dc78e53SAndroid Build Coastguard Worker { RTM_DELADDR, NL_ACT_DEL, "del" },
1231*4dc78e53SAndroid Build Coastguard Worker { RTM_GETADDR, NL_ACT_GET, "get" },
1232*4dc78e53SAndroid Build Coastguard Worker END_OF_MSGTYPES_LIST,
1233*4dc78e53SAndroid Build Coastguard Worker },
1234*4dc78e53SAndroid Build Coastguard Worker .co_protocol = NETLINK_ROUTE,
1235*4dc78e53SAndroid Build Coastguard Worker .co_groups = addr_groups,
1236*4dc78e53SAndroid Build Coastguard Worker .co_request_update = addr_request_update,
1237*4dc78e53SAndroid Build Coastguard Worker .co_msg_parser = addr_msg_parser,
1238*4dc78e53SAndroid Build Coastguard Worker .co_obj_ops = &addr_obj_ops,
1239*4dc78e53SAndroid Build Coastguard Worker };
1240*4dc78e53SAndroid Build Coastguard Worker
addr_init(void)1241*4dc78e53SAndroid Build Coastguard Worker static void _nl_init addr_init(void)
1242*4dc78e53SAndroid Build Coastguard Worker {
1243*4dc78e53SAndroid Build Coastguard Worker nl_cache_mngt_register(&rtnl_addr_ops);
1244*4dc78e53SAndroid Build Coastguard Worker }
1245*4dc78e53SAndroid Build Coastguard Worker
addr_exit(void)1246*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit addr_exit(void)
1247*4dc78e53SAndroid Build Coastguard Worker {
1248*4dc78e53SAndroid Build Coastguard Worker nl_cache_mngt_unregister(&rtnl_addr_ops);
1249*4dc78e53SAndroid Build Coastguard Worker }
1250*4dc78e53SAndroid Build Coastguard Worker
1251*4dc78e53SAndroid Build Coastguard Worker /** @} */
1252