xref: /aosp_15_r20/external/libnl/lib/route/neigh.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
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-2008 Thomas Graf <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker  */
5*4dc78e53SAndroid Build Coastguard Worker 
6*4dc78e53SAndroid Build Coastguard Worker /**
7*4dc78e53SAndroid Build Coastguard Worker  * @ingroup rtnl
8*4dc78e53SAndroid Build Coastguard Worker  * @defgroup neigh Neighbours
9*4dc78e53SAndroid Build Coastguard Worker  * @brief
10*4dc78e53SAndroid Build Coastguard Worker  *
11*4dc78e53SAndroid Build Coastguard Worker  * The neighbour table establishes bindings between protocol addresses and
12*4dc78e53SAndroid Build Coastguard Worker  * link layer addresses for hosts sharing the same physical link. This
13*4dc78e53SAndroid Build Coastguard Worker  * module allows you to access and manipulate the content of these tables.
14*4dc78e53SAndroid Build Coastguard Worker  *
15*4dc78e53SAndroid Build Coastguard Worker  * @par Neighbour States
16*4dc78e53SAndroid Build Coastguard Worker  * @code
17*4dc78e53SAndroid Build Coastguard Worker  * NUD_INCOMPLETE
18*4dc78e53SAndroid Build Coastguard Worker  * NUD_REACHABLE
19*4dc78e53SAndroid Build Coastguard Worker  * NUD_STALE
20*4dc78e53SAndroid Build Coastguard Worker  * NUD_DELAY
21*4dc78e53SAndroid Build Coastguard Worker  * NUD_PROBE
22*4dc78e53SAndroid Build Coastguard Worker  * NUD_FAILED
23*4dc78e53SAndroid Build Coastguard Worker  * NUD_NOARP
24*4dc78e53SAndroid Build Coastguard Worker  * NUD_PERMANENT
25*4dc78e53SAndroid Build Coastguard Worker  * @endcode
26*4dc78e53SAndroid Build Coastguard Worker  *
27*4dc78e53SAndroid Build Coastguard Worker  * @par Neighbour Flags
28*4dc78e53SAndroid Build Coastguard Worker  * @code
29*4dc78e53SAndroid Build Coastguard Worker  * NTF_USE
30*4dc78e53SAndroid Build Coastguard Worker  * NTF_PROXY
31*4dc78e53SAndroid Build Coastguard Worker  * NTF_ROUTER
32*4dc78e53SAndroid Build Coastguard Worker  * NTF_SELF
33*4dc78e53SAndroid Build Coastguard Worker  * @endcode
34*4dc78e53SAndroid Build Coastguard Worker  *
35*4dc78e53SAndroid Build Coastguard Worker  * @par Neighbour Identification
36*4dc78e53SAndroid Build Coastguard Worker  * A neighbour is uniquely identified by the attributes listed below, whenever
37*4dc78e53SAndroid Build Coastguard Worker  * you refer to an existing neighbour all of the attributes must be set.
38*4dc78e53SAndroid Build Coastguard Worker  * Neighbours from caches automatically have all required attributes set.
39*4dc78e53SAndroid Build Coastguard Worker  *   - interface index (rtnl_neigh_set_ifindex())
40*4dc78e53SAndroid Build Coastguard Worker  *   - destination address (rtnl_neigh_set_dst())
41*4dc78e53SAndroid Build Coastguard Worker  *
42*4dc78e53SAndroid Build Coastguard Worker  * @par Changeable Attributes
43*4dc78e53SAndroid Build Coastguard Worker  * \anchor neigh_changeable
44*4dc78e53SAndroid Build Coastguard Worker  *  - state (rtnl_neigh_set_state())
45*4dc78e53SAndroid Build Coastguard Worker  *  - link layer address (rtnl_neigh_set_lladdr())
46*4dc78e53SAndroid Build Coastguard Worker  *
47*4dc78e53SAndroid Build Coastguard Worker  * @par Required Caches for Dumping
48*4dc78e53SAndroid Build Coastguard Worker  * In order to dump neighbour attributes you must provide the following
49*4dc78e53SAndroid Build Coastguard Worker  * caches via nl_cache_provide()
50*4dc78e53SAndroid Build Coastguard Worker  *  - link cache holding all links
51*4dc78e53SAndroid Build Coastguard Worker  *
52*4dc78e53SAndroid Build Coastguard Worker  * @par TODO
53*4dc78e53SAndroid Build Coastguard Worker  *   - Document proxy settings
54*4dc78e53SAndroid Build Coastguard Worker  *   - Document states and their influence
55*4dc78e53SAndroid Build Coastguard Worker  *
56*4dc78e53SAndroid Build Coastguard Worker  * @par 1) Retrieving information about configured neighbours
57*4dc78e53SAndroid Build Coastguard Worker  * @code
58*4dc78e53SAndroid Build Coastguard Worker  * // The first step is to retrieve a list of all available neighbour within
59*4dc78e53SAndroid Build Coastguard Worker  * // the kernel and put them into a cache.
60*4dc78e53SAndroid Build Coastguard Worker  * struct nl_cache *cache = rtnl_neigh_alloc_cache(sk);
61*4dc78e53SAndroid Build Coastguard Worker  *
62*4dc78e53SAndroid Build Coastguard Worker  * // Neighbours can then be looked up by the interface and destination
63*4dc78e53SAndroid Build Coastguard Worker  * // address:
64*4dc78e53SAndroid Build Coastguard Worker  * struct rtnl_neigh *neigh = rtnl_neigh_get(cache, ifindex, dst_addr);
65*4dc78e53SAndroid Build Coastguard Worker  *
66*4dc78e53SAndroid Build Coastguard Worker  * // After successful usage, the object must be given back to the cache
67*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_put(neigh);
68*4dc78e53SAndroid Build Coastguard Worker  * @endcode
69*4dc78e53SAndroid Build Coastguard Worker  *
70*4dc78e53SAndroid Build Coastguard Worker  * @par 2) Adding new neighbours
71*4dc78e53SAndroid Build Coastguard Worker  * @code
72*4dc78e53SAndroid Build Coastguard Worker  * // Allocate an empty neighbour handle to be filled out with the attributes
73*4dc78e53SAndroid Build Coastguard Worker  * // of the new neighbour.
74*4dc78e53SAndroid Build Coastguard Worker  * struct rtnl_neigh *neigh = rtnl_neigh_alloc();
75*4dc78e53SAndroid Build Coastguard Worker  *
76*4dc78e53SAndroid Build Coastguard Worker  * // Fill out the attributes of the new neighbour
77*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_set_ifindex(neigh, ifindex);
78*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_set_dst(neigh, dst_addr);
79*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_set_state(neigh, rtnl_neigh_str2state("permanent"));
80*4dc78e53SAndroid Build Coastguard Worker  *
81*4dc78e53SAndroid Build Coastguard Worker  * // Build the netlink message and send it to the kernel, the operation will
82*4dc78e53SAndroid Build Coastguard Worker  * // block until the operation has been completed. Alternatively the required
83*4dc78e53SAndroid Build Coastguard Worker  * // netlink message can be built using rtnl_neigh_build_add_request()
84*4dc78e53SAndroid Build Coastguard Worker  * // to be sent out using nl_send_auto_complete().
85*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_add(sk, neigh, NLM_F_CREATE);
86*4dc78e53SAndroid Build Coastguard Worker  *
87*4dc78e53SAndroid Build Coastguard Worker  * // Free the memory
88*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_put(neigh);
89*4dc78e53SAndroid Build Coastguard Worker  * @endcode
90*4dc78e53SAndroid Build Coastguard Worker  *
91*4dc78e53SAndroid Build Coastguard Worker  * @par 3) Deleting an existing neighbour
92*4dc78e53SAndroid Build Coastguard Worker  * @code
93*4dc78e53SAndroid Build Coastguard Worker  * // Allocate an empty neighbour object to be filled out with the attributes
94*4dc78e53SAndroid Build Coastguard Worker  * // matching the neighbour to be deleted. Alternatively a fully equipped
95*4dc78e53SAndroid Build Coastguard Worker  * // neighbour object out of a cache can be used instead.
96*4dc78e53SAndroid Build Coastguard Worker  * struct rtnl_neigh *neigh = rtnl_neigh_alloc();
97*4dc78e53SAndroid Build Coastguard Worker  *
98*4dc78e53SAndroid Build Coastguard Worker  * // Neighbours are uniquely identified by their interface index and
99*4dc78e53SAndroid Build Coastguard Worker  * // destination address, you may fill out other attributes but they
100*4dc78e53SAndroid Build Coastguard Worker  * // will have no influence.
101*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_set_ifindex(neigh, ifindex);
102*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_set_dst(neigh, dst_addr);
103*4dc78e53SAndroid Build Coastguard Worker  *
104*4dc78e53SAndroid Build Coastguard Worker  * // Build the netlink message and send it to the kernel, the operation will
105*4dc78e53SAndroid Build Coastguard Worker  * // block until the operation has been completed. Alternatively the required
106*4dc78e53SAndroid Build Coastguard Worker  * // netlink message can be built using rtnl_neigh_build_delete_request()
107*4dc78e53SAndroid Build Coastguard Worker  * // to be sent out using nl_send_auto_complete().
108*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_delete(sk, neigh, 0);
109*4dc78e53SAndroid Build Coastguard Worker  *
110*4dc78e53SAndroid Build Coastguard Worker  * // Free the memory
111*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_put(neigh);
112*4dc78e53SAndroid Build Coastguard Worker  * @endcode
113*4dc78e53SAndroid Build Coastguard Worker  *
114*4dc78e53SAndroid Build Coastguard Worker  * @par 4) Changing neighbour attributes
115*4dc78e53SAndroid Build Coastguard Worker  * @code
116*4dc78e53SAndroid Build Coastguard Worker  * // Allocate an empty neighbour object to be filled out with the attributes
117*4dc78e53SAndroid Build Coastguard Worker  * // matching the neighbour to be changed and the new parameters. Alternatively
118*4dc78e53SAndroid Build Coastguard Worker  * // a fully equipped modified neighbour object out of a cache can be used.
119*4dc78e53SAndroid Build Coastguard Worker  * struct rtnl_neigh *neigh = rtnl_neigh_alloc();
120*4dc78e53SAndroid Build Coastguard Worker  *
121*4dc78e53SAndroid Build Coastguard Worker  * // Identify the neighbour to be changed by its interface index and
122*4dc78e53SAndroid Build Coastguard Worker  * // destination address
123*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_set_ifindex(neigh, ifindex);
124*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_set_dst(neigh, dst_addr);
125*4dc78e53SAndroid Build Coastguard Worker  *
126*4dc78e53SAndroid Build Coastguard Worker  * // The link layer address may be modified, if so it is wise to change
127*4dc78e53SAndroid Build Coastguard Worker  * // its state to "permanent" in order to avoid having it overwritten.
128*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_set_lladdr(neigh, lladdr);
129*4dc78e53SAndroid Build Coastguard Worker  *
130*4dc78e53SAndroid Build Coastguard Worker  * // Secondly the state can be modified allowing normal neighbours to be
131*4dc78e53SAndroid Build Coastguard Worker  * // converted into permanent entries or to manually confirm a neighbour.
132*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_set_state(neigh, state);
133*4dc78e53SAndroid Build Coastguard Worker  *
134*4dc78e53SAndroid Build Coastguard Worker  * // Build the netlink message and send it to the kernel, the operation will
135*4dc78e53SAndroid Build Coastguard Worker  * // block until the operation has been completed. Alternatively the required
136*4dc78e53SAndroid Build Coastguard Worker  * // netlink message can be built using rtnl_neigh_build_change_request()
137*4dc78e53SAndroid Build Coastguard Worker  * // to be sent out using nl_send_auto_complete().
138*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_add(sk, neigh, NLM_F_REPLACE);
139*4dc78e53SAndroid Build Coastguard Worker  *
140*4dc78e53SAndroid Build Coastguard Worker  * // Free the memory
141*4dc78e53SAndroid Build Coastguard Worker  * rtnl_neigh_put(neigh);
142*4dc78e53SAndroid Build Coastguard Worker  * @endcode
143*4dc78e53SAndroid Build Coastguard Worker  * @{
144*4dc78e53SAndroid Build Coastguard Worker  */
145*4dc78e53SAndroid Build Coastguard Worker 
146*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
147*4dc78e53SAndroid Build Coastguard Worker 
148*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
149*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
150*4dc78e53SAndroid Build Coastguard Worker #include <netlink/hashtable.h>
151*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/rtnl.h>
152*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/neighbour.h>
153*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/link.h>
154*4dc78e53SAndroid Build Coastguard Worker #include <netlink/hashtable.h>
155*4dc78e53SAndroid Build Coastguard Worker 
156*4dc78e53SAndroid Build Coastguard Worker #include "nl-route.h"
157*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/nl-core.h"
158*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/cache-api.h"
159*4dc78e53SAndroid Build Coastguard Worker 
160*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
161*4dc78e53SAndroid Build Coastguard Worker struct rtnl_ncacheinfo {
162*4dc78e53SAndroid Build Coastguard Worker 	uint32_t nci_confirmed; /**< Time since neighbour validty was last confirmed */
163*4dc78e53SAndroid Build Coastguard Worker 	uint32_t nci_used; /**< Time since neighbour entry was last ued */
164*4dc78e53SAndroid Build Coastguard Worker 	uint32_t nci_updated; /**< Time since last update */
165*4dc78e53SAndroid Build Coastguard Worker 	uint32_t nci_refcnt; /**< Reference counter */
166*4dc78e53SAndroid Build Coastguard Worker };
167*4dc78e53SAndroid Build Coastguard Worker 
168*4dc78e53SAndroid Build Coastguard Worker struct rtnl_neigh {
169*4dc78e53SAndroid Build Coastguard Worker 	NLHDR_COMMON
170*4dc78e53SAndroid Build Coastguard Worker 	uint32_t n_family;
171*4dc78e53SAndroid Build Coastguard Worker 	uint32_t n_ifindex;
172*4dc78e53SAndroid Build Coastguard Worker 	uint16_t n_state;
173*4dc78e53SAndroid Build Coastguard Worker 	uint8_t n_flags;
174*4dc78e53SAndroid Build Coastguard Worker 	uint8_t n_type;
175*4dc78e53SAndroid Build Coastguard Worker 	struct nl_addr *n_lladdr;
176*4dc78e53SAndroid Build Coastguard Worker 	struct nl_addr *n_dst;
177*4dc78e53SAndroid Build Coastguard Worker 	uint32_t n_nhid;
178*4dc78e53SAndroid Build Coastguard Worker 	uint32_t n_probes;
179*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_ncacheinfo n_cacheinfo;
180*4dc78e53SAndroid Build Coastguard Worker 	uint32_t n_state_mask;
181*4dc78e53SAndroid Build Coastguard Worker 	uint32_t n_flag_mask;
182*4dc78e53SAndroid Build Coastguard Worker 	uint32_t n_master;
183*4dc78e53SAndroid Build Coastguard Worker 	uint16_t n_vlan;
184*4dc78e53SAndroid Build Coastguard Worker };
185*4dc78e53SAndroid Build Coastguard Worker 
186*4dc78e53SAndroid Build Coastguard Worker #define NEIGH_ATTR_FLAGS        0x01
187*4dc78e53SAndroid Build Coastguard Worker #define NEIGH_ATTR_STATE        0x02
188*4dc78e53SAndroid Build Coastguard Worker #define NEIGH_ATTR_LLADDR       0x04
189*4dc78e53SAndroid Build Coastguard Worker #define NEIGH_ATTR_DST          0x08
190*4dc78e53SAndroid Build Coastguard Worker #define NEIGH_ATTR_CACHEINFO    0x10
191*4dc78e53SAndroid Build Coastguard Worker #define NEIGH_ATTR_IFINDEX      0x20
192*4dc78e53SAndroid Build Coastguard Worker #define NEIGH_ATTR_FAMILY       0x40
193*4dc78e53SAndroid Build Coastguard Worker #define NEIGH_ATTR_TYPE         0x80
194*4dc78e53SAndroid Build Coastguard Worker #define NEIGH_ATTR_PROBES       0x100
195*4dc78e53SAndroid Build Coastguard Worker #define NEIGH_ATTR_MASTER       0x200
196*4dc78e53SAndroid Build Coastguard Worker #define NEIGH_ATTR_VLAN         0x400
197*4dc78e53SAndroid Build Coastguard Worker #define NEIGH_ATTR_NHID         0x800
198*4dc78e53SAndroid Build Coastguard Worker 
199*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_neigh_ops;
200*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops neigh_obj_ops;
201*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
202*4dc78e53SAndroid Build Coastguard Worker 
neigh_free_data(struct nl_object * c)203*4dc78e53SAndroid Build Coastguard Worker static void neigh_free_data(struct nl_object *c)
204*4dc78e53SAndroid Build Coastguard Worker {
205*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_neigh *neigh = nl_object_priv(c);
206*4dc78e53SAndroid Build Coastguard Worker 
207*4dc78e53SAndroid Build Coastguard Worker 	if (!neigh)
208*4dc78e53SAndroid Build Coastguard Worker 		return;
209*4dc78e53SAndroid Build Coastguard Worker 
210*4dc78e53SAndroid Build Coastguard Worker 	nl_addr_put(neigh->n_lladdr);
211*4dc78e53SAndroid Build Coastguard Worker 	nl_addr_put(neigh->n_dst);
212*4dc78e53SAndroid Build Coastguard Worker }
213*4dc78e53SAndroid Build Coastguard Worker 
neigh_clone(struct nl_object * _dst,struct nl_object * _src)214*4dc78e53SAndroid Build Coastguard Worker static int neigh_clone(struct nl_object *_dst, struct nl_object *_src)
215*4dc78e53SAndroid Build Coastguard Worker {
216*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_neigh *dst = nl_object_priv(_dst);
217*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_neigh *src = nl_object_priv(_src);
218*4dc78e53SAndroid Build Coastguard Worker 
219*4dc78e53SAndroid Build Coastguard Worker 	dst->n_lladdr = NULL;
220*4dc78e53SAndroid Build Coastguard Worker 	dst->n_dst = NULL;
221*4dc78e53SAndroid Build Coastguard Worker 
222*4dc78e53SAndroid Build Coastguard Worker 	if (src->n_lladdr)
223*4dc78e53SAndroid Build Coastguard Worker 		if (!(dst->n_lladdr = nl_addr_clone(src->n_lladdr)))
224*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
225*4dc78e53SAndroid Build Coastguard Worker 
226*4dc78e53SAndroid Build Coastguard Worker 	if (src->n_dst)
227*4dc78e53SAndroid Build Coastguard Worker 		if (!(dst->n_dst = nl_addr_clone(src->n_dst)))
228*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
229*4dc78e53SAndroid Build Coastguard Worker 
230*4dc78e53SAndroid Build Coastguard Worker 	return 0;
231*4dc78e53SAndroid Build Coastguard Worker }
232*4dc78e53SAndroid Build Coastguard Worker 
neigh_keygen(struct nl_object * obj,uint32_t * hashkey,uint32_t table_sz)233*4dc78e53SAndroid Build Coastguard Worker static void neigh_keygen(struct nl_object *obj, uint32_t *hashkey,
234*4dc78e53SAndroid Build Coastguard Worker 			 uint32_t table_sz)
235*4dc78e53SAndroid Build Coastguard Worker {
236*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_neigh *neigh = (struct rtnl_neigh *) obj;
237*4dc78e53SAndroid Build Coastguard Worker 	unsigned int nkey_sz;
238*4dc78e53SAndroid Build Coastguard Worker 	struct nl_addr *addr = NULL;
239*4dc78e53SAndroid Build Coastguard Worker 	struct neigh_hash_key {
240*4dc78e53SAndroid Build Coastguard Worker 		uint32_t	n_family;
241*4dc78e53SAndroid Build Coastguard Worker 		uint32_t	n_ifindex;
242*4dc78e53SAndroid Build Coastguard Worker 		uint16_t	n_vlan;
243*4dc78e53SAndroid Build Coastguard Worker 		char		n_addr[0];
244*4dc78e53SAndroid Build Coastguard Worker 	} _nl_packed *nkey;
245*4dc78e53SAndroid Build Coastguard Worker 	char buf[INET6_ADDRSTRLEN+5];
246*4dc78e53SAndroid Build Coastguard Worker 
247*4dc78e53SAndroid Build Coastguard Worker 	if (neigh->n_family == AF_BRIDGE) {
248*4dc78e53SAndroid Build Coastguard Worker 		if (neigh->n_lladdr)
249*4dc78e53SAndroid Build Coastguard Worker 			addr = neigh->n_lladdr;
250*4dc78e53SAndroid Build Coastguard Worker 	} else if (neigh->n_dst) {
251*4dc78e53SAndroid Build Coastguard Worker 		addr = neigh->n_dst;
252*4dc78e53SAndroid Build Coastguard Worker 	}
253*4dc78e53SAndroid Build Coastguard Worker 
254*4dc78e53SAndroid Build Coastguard Worker 	nkey_sz = sizeof(*nkey);
255*4dc78e53SAndroid Build Coastguard Worker 	if (addr)
256*4dc78e53SAndroid Build Coastguard Worker 		nkey_sz += nl_addr_get_len(addr);
257*4dc78e53SAndroid Build Coastguard Worker 
258*4dc78e53SAndroid Build Coastguard Worker 	nkey = calloc(1, nkey_sz);
259*4dc78e53SAndroid Build Coastguard Worker 	if (!nkey) {
260*4dc78e53SAndroid Build Coastguard Worker 		*hashkey = 0;
261*4dc78e53SAndroid Build Coastguard Worker 		return;
262*4dc78e53SAndroid Build Coastguard Worker 	}
263*4dc78e53SAndroid Build Coastguard Worker 	nkey->n_family = neigh->n_family;
264*4dc78e53SAndroid Build Coastguard Worker 	if (neigh->n_family == AF_BRIDGE) {
265*4dc78e53SAndroid Build Coastguard Worker 		nkey->n_vlan = neigh->n_vlan;
266*4dc78e53SAndroid Build Coastguard Worker 		if (neigh->n_flags & NTF_SELF)
267*4dc78e53SAndroid Build Coastguard Worker 			nkey->n_ifindex = neigh->n_ifindex;
268*4dc78e53SAndroid Build Coastguard Worker 		else
269*4dc78e53SAndroid Build Coastguard Worker 			nkey->n_ifindex = neigh->n_master;
270*4dc78e53SAndroid Build Coastguard Worker 	} else
271*4dc78e53SAndroid Build Coastguard Worker 		nkey->n_ifindex = neigh->n_ifindex;
272*4dc78e53SAndroid Build Coastguard Worker 
273*4dc78e53SAndroid Build Coastguard Worker 	if (addr)
274*4dc78e53SAndroid Build Coastguard Worker 		memcpy(nkey->n_addr,
275*4dc78e53SAndroid Build Coastguard Worker 			nl_addr_get_binary_addr(addr),
276*4dc78e53SAndroid Build Coastguard Worker 			nl_addr_get_len(addr));
277*4dc78e53SAndroid Build Coastguard Worker 
278*4dc78e53SAndroid Build Coastguard Worker 	*hashkey = nl_hash(nkey, nkey_sz, 0) % table_sz;
279*4dc78e53SAndroid Build Coastguard Worker 
280*4dc78e53SAndroid Build Coastguard Worker 	NL_DBG(5, "neigh %p key (fam %d dev %d addr %s) keysz %d hash 0x%x\n",
281*4dc78e53SAndroid Build Coastguard Worker 		neigh, nkey->n_family, nkey->n_ifindex,
282*4dc78e53SAndroid Build Coastguard Worker 		nl_addr2str(addr, buf, sizeof(buf)),
283*4dc78e53SAndroid Build Coastguard Worker 		nkey_sz, *hashkey);
284*4dc78e53SAndroid Build Coastguard Worker 
285*4dc78e53SAndroid Build Coastguard Worker 	free(nkey);
286*4dc78e53SAndroid Build Coastguard Worker 
287*4dc78e53SAndroid Build Coastguard Worker 	return;
288*4dc78e53SAndroid Build Coastguard Worker }
289*4dc78e53SAndroid Build Coastguard Worker 
neigh_compare(struct nl_object * _a,struct nl_object * _b,uint64_t attrs,int flags)290*4dc78e53SAndroid Build Coastguard Worker static uint64_t neigh_compare(struct nl_object *_a, struct nl_object *_b,
291*4dc78e53SAndroid Build Coastguard Worker 			      uint64_t attrs, int flags)
292*4dc78e53SAndroid Build Coastguard Worker {
293*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_neigh *a = (struct rtnl_neigh *) _a;
294*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_neigh *b = (struct rtnl_neigh *) _b;
295*4dc78e53SAndroid Build Coastguard Worker 	uint64_t diff = 0;
296*4dc78e53SAndroid Build Coastguard Worker 
297*4dc78e53SAndroid Build Coastguard Worker #define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
298*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(NEIGH_ATTR_IFINDEX, a->n_ifindex != b->n_ifindex);
299*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(NEIGH_ATTR_FAMILY, a->n_family != b->n_family);
300*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(NEIGH_ATTR_TYPE, a->n_type != b->n_type);
301*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(NEIGH_ATTR_LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr));
302*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(NEIGH_ATTR_DST, nl_addr_cmp(a->n_dst, b->n_dst));
303*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(NEIGH_ATTR_MASTER, a->n_master != b->n_master);
304*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(NEIGH_ATTR_VLAN, a->n_vlan != b->n_vlan);
305*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(NEIGH_ATTR_NHID, a->n_nhid != b->n_nhid);
306*4dc78e53SAndroid Build Coastguard Worker 
307*4dc78e53SAndroid Build Coastguard Worker 	if (flags & LOOSE_COMPARISON) {
308*4dc78e53SAndroid Build Coastguard Worker 		diff |= _DIFF(NEIGH_ATTR_STATE,
309*4dc78e53SAndroid Build Coastguard Worker 			      (a->n_state ^ b->n_state) & b->n_state_mask);
310*4dc78e53SAndroid Build Coastguard Worker 		diff |= _DIFF(NEIGH_ATTR_FLAGS,
311*4dc78e53SAndroid Build Coastguard Worker 			      (a->n_flags ^ b->n_flags) & b->n_flag_mask);
312*4dc78e53SAndroid Build Coastguard Worker 	} else {
313*4dc78e53SAndroid Build Coastguard Worker 		diff |= _DIFF(NEIGH_ATTR_STATE, a->n_state != b->n_state);
314*4dc78e53SAndroid Build Coastguard Worker 		diff |= _DIFF(NEIGH_ATTR_FLAGS, a->n_flags != b->n_flags);
315*4dc78e53SAndroid Build Coastguard Worker 	}
316*4dc78e53SAndroid Build Coastguard Worker #undef _DIFF
317*4dc78e53SAndroid Build Coastguard Worker 
318*4dc78e53SAndroid Build Coastguard Worker 	return diff;
319*4dc78e53SAndroid Build Coastguard Worker }
320*4dc78e53SAndroid Build Coastguard Worker 
321*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl neigh_attrs[] = {
322*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NEIGH_ATTR_FLAGS, flags),
323*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NEIGH_ATTR_STATE, state),
324*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NEIGH_ATTR_LLADDR, lladdr),
325*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NEIGH_ATTR_DST, dst),
326*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NEIGH_ATTR_CACHEINFO, cacheinfo),
327*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NEIGH_ATTR_IFINDEX, ifindex),
328*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NEIGH_ATTR_FAMILY, family),
329*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NEIGH_ATTR_TYPE, type),
330*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NEIGH_ATTR_PROBES, probes),
331*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NEIGH_ATTR_MASTER, master),
332*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NEIGH_ATTR_VLAN, vlan),
333*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NEIGH_ATTR_NHID, nhid),
334*4dc78e53SAndroid Build Coastguard Worker };
335*4dc78e53SAndroid Build Coastguard Worker 
neigh_attrs2str(int attrs,char * buf,size_t len)336*4dc78e53SAndroid Build Coastguard Worker static char *neigh_attrs2str(int attrs, char *buf, size_t len)
337*4dc78e53SAndroid Build Coastguard Worker {
338*4dc78e53SAndroid Build Coastguard Worker 	return __flags2str(attrs, buf, len, neigh_attrs,
339*4dc78e53SAndroid Build Coastguard Worker 			   ARRAY_SIZE(neigh_attrs));
340*4dc78e53SAndroid Build Coastguard Worker }
341*4dc78e53SAndroid Build Coastguard Worker 
neigh_id_attrs_get(struct nl_object * obj)342*4dc78e53SAndroid Build Coastguard Worker static uint32_t neigh_id_attrs_get(struct nl_object *obj)
343*4dc78e53SAndroid Build Coastguard Worker {
344*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_neigh *neigh = (struct rtnl_neigh *)obj;
345*4dc78e53SAndroid Build Coastguard Worker 
346*4dc78e53SAndroid Build Coastguard Worker 	if (neigh->n_family == AF_BRIDGE) {
347*4dc78e53SAndroid Build Coastguard Worker 		if (neigh->n_flags & NTF_SELF)
348*4dc78e53SAndroid Build Coastguard Worker 			return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX |
349*4dc78e53SAndroid Build Coastguard Worker 				       ((neigh->ce_mask & NEIGH_ATTR_DST) ? NEIGH_ATTR_DST: 0) |
350*4dc78e53SAndroid Build Coastguard Worker 				       ((neigh->ce_mask & NEIGH_ATTR_NHID) ? NEIGH_ATTR_NHID: 0) |
351*4dc78e53SAndroid Build Coastguard Worker 				       ((neigh->ce_mask & NEIGH_ATTR_VLAN) ? NEIGH_ATTR_VLAN : 0));
352*4dc78e53SAndroid Build Coastguard Worker 		else
353*4dc78e53SAndroid Build Coastguard Worker 			return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_MASTER | NEIGH_ATTR_VLAN);
354*4dc78e53SAndroid Build Coastguard Worker 	} else
355*4dc78e53SAndroid Build Coastguard Worker 		return neigh_obj_ops.oo_id_attrs;
356*4dc78e53SAndroid Build Coastguard Worker }
357*4dc78e53SAndroid Build Coastguard Worker 
358*4dc78e53SAndroid Build Coastguard Worker static struct nla_policy neigh_policy[NDA_MAX+1] = {
359*4dc78e53SAndroid Build Coastguard Worker 	[NDA_CACHEINFO]	= { .minlen = sizeof(struct nda_cacheinfo) },
360*4dc78e53SAndroid Build Coastguard Worker 	[NDA_PROBES]	= { .type = NLA_U32 },
361*4dc78e53SAndroid Build Coastguard Worker };
362*4dc78e53SAndroid Build Coastguard Worker 
neigh_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * n,struct nl_parser_param * pp)363*4dc78e53SAndroid Build Coastguard Worker static int neigh_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
364*4dc78e53SAndroid Build Coastguard Worker 			    struct nlmsghdr *n, struct nl_parser_param *pp)
365*4dc78e53SAndroid Build Coastguard Worker {
366*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_neigh *neigh;
367*4dc78e53SAndroid Build Coastguard Worker 	int err;
368*4dc78e53SAndroid Build Coastguard Worker 
369*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_neigh_parse(n, &neigh)) < 0)
370*4dc78e53SAndroid Build Coastguard Worker 		return err;
371*4dc78e53SAndroid Build Coastguard Worker 
372*4dc78e53SAndroid Build Coastguard Worker 	err = pp->pp_cb((struct nl_object *) neigh, pp);
373*4dc78e53SAndroid Build Coastguard Worker 
374*4dc78e53SAndroid Build Coastguard Worker 	rtnl_neigh_put(neigh);
375*4dc78e53SAndroid Build Coastguard Worker 	return err;
376*4dc78e53SAndroid Build Coastguard Worker }
377*4dc78e53SAndroid Build Coastguard Worker 
378*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_parse(struct nlmsghdr * n,struct rtnl_neigh ** result)379*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_parse(struct nlmsghdr *n, struct rtnl_neigh **result)
380*4dc78e53SAndroid Build Coastguard Worker {
381*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_neigh *neigh;
382*4dc78e53SAndroid Build Coastguard Worker 	struct nlattr *tb[NDA_MAX + 1];
383*4dc78e53SAndroid Build Coastguard Worker 	struct ndmsg *nm;
384*4dc78e53SAndroid Build Coastguard Worker 	int err;
385*4dc78e53SAndroid Build Coastguard Worker 
386*4dc78e53SAndroid Build Coastguard Worker 	neigh = rtnl_neigh_alloc();
387*4dc78e53SAndroid Build Coastguard Worker 	if (!neigh) {
388*4dc78e53SAndroid Build Coastguard Worker 		err = -NLE_NOMEM;
389*4dc78e53SAndroid Build Coastguard Worker 		goto errout;
390*4dc78e53SAndroid Build Coastguard Worker 	}
391*4dc78e53SAndroid Build Coastguard Worker 
392*4dc78e53SAndroid Build Coastguard Worker 	neigh->ce_msgtype = n->nlmsg_type;
393*4dc78e53SAndroid Build Coastguard Worker 	nm = nlmsg_data(n);
394*4dc78e53SAndroid Build Coastguard Worker 
395*4dc78e53SAndroid Build Coastguard Worker 	err = nlmsg_parse(n, sizeof(*nm), tb, NDA_MAX, neigh_policy);
396*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
397*4dc78e53SAndroid Build Coastguard Worker 		goto errout;
398*4dc78e53SAndroid Build Coastguard Worker 
399*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_family  = nm->ndm_family;
400*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_ifindex = nm->ndm_ifindex;
401*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_state   = nm->ndm_state;
402*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_flags   = nm->ndm_flags;
403*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_type    = nm->ndm_type;
404*4dc78e53SAndroid Build Coastguard Worker 
405*4dc78e53SAndroid Build Coastguard Worker 	neigh->ce_mask |= (NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX |
406*4dc78e53SAndroid Build Coastguard Worker 			   NEIGH_ATTR_STATE | NEIGH_ATTR_FLAGS |
407*4dc78e53SAndroid Build Coastguard Worker 			   NEIGH_ATTR_TYPE);
408*4dc78e53SAndroid Build Coastguard Worker 
409*4dc78e53SAndroid Build Coastguard Worker 	if (tb[NDA_LLADDR]) {
410*4dc78e53SAndroid Build Coastguard Worker 		neigh->n_lladdr = nl_addr_alloc_attr(tb[NDA_LLADDR], AF_UNSPEC);
411*4dc78e53SAndroid Build Coastguard Worker 		if (!neigh->n_lladdr) {
412*4dc78e53SAndroid Build Coastguard Worker 			err = -NLE_NOMEM;
413*4dc78e53SAndroid Build Coastguard Worker 			goto errout;
414*4dc78e53SAndroid Build Coastguard Worker 		}
415*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_set_family(neigh->n_lladdr,
416*4dc78e53SAndroid Build Coastguard Worker 				   nl_addr_guess_family(neigh->n_lladdr));
417*4dc78e53SAndroid Build Coastguard Worker 		neigh->ce_mask |= NEIGH_ATTR_LLADDR;
418*4dc78e53SAndroid Build Coastguard Worker 	}
419*4dc78e53SAndroid Build Coastguard Worker 
420*4dc78e53SAndroid Build Coastguard Worker 	if (tb[NDA_DST]) {
421*4dc78e53SAndroid Build Coastguard Worker 		neigh->n_dst = nl_addr_alloc_attr(tb[NDA_DST], AF_UNSPEC);
422*4dc78e53SAndroid Build Coastguard Worker 		if (!neigh->n_dst) {
423*4dc78e53SAndroid Build Coastguard Worker 			err = -NLE_NOMEM;
424*4dc78e53SAndroid Build Coastguard Worker 			goto errout;
425*4dc78e53SAndroid Build Coastguard Worker 		}
426*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_set_family(neigh->n_dst,
427*4dc78e53SAndroid Build Coastguard Worker 				   nl_addr_guess_family(neigh->n_dst));
428*4dc78e53SAndroid Build Coastguard Worker 		neigh->ce_mask |= NEIGH_ATTR_DST;
429*4dc78e53SAndroid Build Coastguard Worker 	}
430*4dc78e53SAndroid Build Coastguard Worker 
431*4dc78e53SAndroid Build Coastguard Worker 	if (tb[NDA_CACHEINFO]) {
432*4dc78e53SAndroid Build Coastguard Worker 		struct nda_cacheinfo *ci = nla_data(tb[NDA_CACHEINFO]);
433*4dc78e53SAndroid Build Coastguard Worker 
434*4dc78e53SAndroid Build Coastguard Worker 		neigh->n_cacheinfo.nci_confirmed = ci->ndm_confirmed;
435*4dc78e53SAndroid Build Coastguard Worker 		neigh->n_cacheinfo.nci_used = ci->ndm_used;
436*4dc78e53SAndroid Build Coastguard Worker 		neigh->n_cacheinfo.nci_updated = ci->ndm_updated;
437*4dc78e53SAndroid Build Coastguard Worker 		neigh->n_cacheinfo.nci_refcnt = ci->ndm_refcnt;
438*4dc78e53SAndroid Build Coastguard Worker 
439*4dc78e53SAndroid Build Coastguard Worker 		neigh->ce_mask |= NEIGH_ATTR_CACHEINFO;
440*4dc78e53SAndroid Build Coastguard Worker 	}
441*4dc78e53SAndroid Build Coastguard Worker 
442*4dc78e53SAndroid Build Coastguard Worker 	if (tb[NDA_PROBES]) {
443*4dc78e53SAndroid Build Coastguard Worker 		neigh->n_probes = nla_get_u32(tb[NDA_PROBES]);
444*4dc78e53SAndroid Build Coastguard Worker 		neigh->ce_mask |= NEIGH_ATTR_PROBES;
445*4dc78e53SAndroid Build Coastguard Worker 	}
446*4dc78e53SAndroid Build Coastguard Worker 
447*4dc78e53SAndroid Build Coastguard Worker 	if (tb[NDA_VLAN]) {
448*4dc78e53SAndroid Build Coastguard Worker 		neigh->n_vlan = nla_get_u16(tb[NDA_VLAN]);
449*4dc78e53SAndroid Build Coastguard Worker 		neigh->ce_mask |= NEIGH_ATTR_VLAN;
450*4dc78e53SAndroid Build Coastguard Worker 	}
451*4dc78e53SAndroid Build Coastguard Worker 
452*4dc78e53SAndroid Build Coastguard Worker 	if (tb[NDA_NH_ID]) {
453*4dc78e53SAndroid Build Coastguard Worker 		neigh->n_nhid = nla_get_u32(tb[NDA_NH_ID]);
454*4dc78e53SAndroid Build Coastguard Worker 		neigh->ce_mask |= NEIGH_ATTR_NHID;
455*4dc78e53SAndroid Build Coastguard Worker 	}
456*4dc78e53SAndroid Build Coastguard Worker 
457*4dc78e53SAndroid Build Coastguard Worker 	/*
458*4dc78e53SAndroid Build Coastguard Worker 	 * Get the bridge index for AF_BRIDGE family entries
459*4dc78e53SAndroid Build Coastguard Worker 	 */
460*4dc78e53SAndroid Build Coastguard Worker 	if (neigh->n_family == AF_BRIDGE) {
461*4dc78e53SAndroid Build Coastguard Worker 		if (tb[NDA_MASTER]) {
462*4dc78e53SAndroid Build Coastguard Worker 			neigh->n_master = nla_get_u32(tb[NDA_MASTER]);
463*4dc78e53SAndroid Build Coastguard Worker 			neigh->ce_mask |= NEIGH_ATTR_MASTER;
464*4dc78e53SAndroid Build Coastguard Worker 		} else {
465*4dc78e53SAndroid Build Coastguard Worker 			struct nl_cache *lcache = nl_cache_mngt_require_safe("route/link");
466*4dc78e53SAndroid Build Coastguard Worker 			if (lcache ) {
467*4dc78e53SAndroid Build Coastguard Worker 				struct rtnl_link *link = rtnl_link_get(lcache,
468*4dc78e53SAndroid Build Coastguard Worker 								       neigh->n_ifindex);
469*4dc78e53SAndroid Build Coastguard Worker 				if (link) {
470*4dc78e53SAndroid Build Coastguard Worker 					neigh->n_master = link->l_master;
471*4dc78e53SAndroid Build Coastguard Worker 					rtnl_link_put(link);
472*4dc78e53SAndroid Build Coastguard Worker 					neigh->ce_mask |= NEIGH_ATTR_MASTER;
473*4dc78e53SAndroid Build Coastguard Worker 				}
474*4dc78e53SAndroid Build Coastguard Worker 				nl_cache_put(lcache);
475*4dc78e53SAndroid Build Coastguard Worker 			}
476*4dc78e53SAndroid Build Coastguard Worker 		}
477*4dc78e53SAndroid Build Coastguard Worker 	}
478*4dc78e53SAndroid Build Coastguard Worker 
479*4dc78e53SAndroid Build Coastguard Worker 	*result = neigh;
480*4dc78e53SAndroid Build Coastguard Worker 	return 0;
481*4dc78e53SAndroid Build Coastguard Worker 
482*4dc78e53SAndroid Build Coastguard Worker errout:
483*4dc78e53SAndroid Build Coastguard Worker 	rtnl_neigh_put(neigh);
484*4dc78e53SAndroid Build Coastguard Worker 	return err;
485*4dc78e53SAndroid Build Coastguard Worker }
486*4dc78e53SAndroid Build Coastguard Worker 
neigh_request_update(struct nl_cache * c,struct nl_sock * h)487*4dc78e53SAndroid Build Coastguard Worker static int neigh_request_update(struct nl_cache *c, struct nl_sock *h)
488*4dc78e53SAndroid Build Coastguard Worker {
489*4dc78e53SAndroid Build Coastguard Worker 	int family = c->c_iarg1;
490*4dc78e53SAndroid Build Coastguard Worker 
491*4dc78e53SAndroid Build Coastguard Worker 	if (family == AF_UNSPEC) {
492*4dc78e53SAndroid Build Coastguard Worker 		return nl_rtgen_request(h, RTM_GETNEIGH, family, NLM_F_DUMP);
493*4dc78e53SAndroid Build Coastguard Worker 	} else if (family == AF_BRIDGE) {
494*4dc78e53SAndroid Build Coastguard Worker 		struct ifinfomsg hdr = {.ifi_family = family};
495*4dc78e53SAndroid Build Coastguard Worker 		struct nl_msg *msg;
496*4dc78e53SAndroid Build Coastguard Worker 		int err;
497*4dc78e53SAndroid Build Coastguard Worker 
498*4dc78e53SAndroid Build Coastguard Worker 		msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_DUMP);
499*4dc78e53SAndroid Build Coastguard Worker 		if (!msg)
500*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
501*4dc78e53SAndroid Build Coastguard Worker 
502*4dc78e53SAndroid Build Coastguard Worker 		err = -NLE_MSGSIZE;
503*4dc78e53SAndroid Build Coastguard Worker 		if (nlmsg_append(msg, &hdr, sizeof(hdr), NLMSG_ALIGNTO) < 0)
504*4dc78e53SAndroid Build Coastguard Worker 			goto nla_put_failure;
505*4dc78e53SAndroid Build Coastguard Worker 
506*4dc78e53SAndroid Build Coastguard Worker 		err = nl_send_auto(h, msg);
507*4dc78e53SAndroid Build Coastguard Worker 		if (err > 0)
508*4dc78e53SAndroid Build Coastguard Worker 			err = 0;
509*4dc78e53SAndroid Build Coastguard Worker 
510*4dc78e53SAndroid Build Coastguard Worker 	nla_put_failure:
511*4dc78e53SAndroid Build Coastguard Worker 		nlmsg_free(msg);
512*4dc78e53SAndroid Build Coastguard Worker 		return err;
513*4dc78e53SAndroid Build Coastguard Worker 	}
514*4dc78e53SAndroid Build Coastguard Worker 
515*4dc78e53SAndroid Build Coastguard Worker 	return -NLE_INVAL;
516*4dc78e53SAndroid Build Coastguard Worker }
517*4dc78e53SAndroid Build Coastguard Worker 
518*4dc78e53SAndroid Build Coastguard Worker 
neigh_dump_line(struct nl_object * a,struct nl_dump_params * p)519*4dc78e53SAndroid Build Coastguard Worker static void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p)
520*4dc78e53SAndroid Build Coastguard Worker {
521*4dc78e53SAndroid Build Coastguard Worker 	char dst[INET6_ADDRSTRLEN+5], lladdr[INET6_ADDRSTRLEN+5];
522*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_neigh *n = (struct rtnl_neigh *) a;
523*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache *link_cache;
524*4dc78e53SAndroid Build Coastguard Worker 	char state[128], flags[64];
525*4dc78e53SAndroid Build Coastguard Worker 	char buf[128];
526*4dc78e53SAndroid Build Coastguard Worker 
527*4dc78e53SAndroid Build Coastguard Worker 	link_cache = nl_cache_mngt_require_safe("route/link");
528*4dc78e53SAndroid Build Coastguard Worker 
529*4dc78e53SAndroid Build Coastguard Worker 	if (n->n_family != AF_UNSPEC)
530*4dc78e53SAndroid Build Coastguard Worker 		nl_dump_line(p, "%s ", nl_af2str(n->n_family, buf, sizeof(buf)));
531*4dc78e53SAndroid Build Coastguard Worker 
532*4dc78e53SAndroid Build Coastguard Worker 	if (n->ce_mask & NEIGH_ATTR_DST)
533*4dc78e53SAndroid Build Coastguard Worker 		nl_dump_line(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst)));
534*4dc78e53SAndroid Build Coastguard Worker 
535*4dc78e53SAndroid Build Coastguard Worker 	if (link_cache)
536*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "dev %s ",
537*4dc78e53SAndroid Build Coastguard Worker 			rtnl_link_i2name(link_cache, n->n_ifindex,
538*4dc78e53SAndroid Build Coastguard Worker 					 state, sizeof(state)));
539*4dc78e53SAndroid Build Coastguard Worker 	else
540*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "dev %d ", n->n_ifindex);
541*4dc78e53SAndroid Build Coastguard Worker 
542*4dc78e53SAndroid Build Coastguard Worker 	if (n->ce_mask & NEIGH_ATTR_LLADDR)
543*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "lladdr %s ",
544*4dc78e53SAndroid Build Coastguard Worker 			nl_addr2str(n->n_lladdr, lladdr, sizeof(lladdr)));
545*4dc78e53SAndroid Build Coastguard Worker 
546*4dc78e53SAndroid Build Coastguard Worker 	if (n->ce_mask & NEIGH_ATTR_VLAN)
547*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "vlan %d ", n->n_vlan);
548*4dc78e53SAndroid Build Coastguard Worker 
549*4dc78e53SAndroid Build Coastguard Worker 	if (n->ce_mask & NEIGH_ATTR_NHID)
550*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "nhid %u ", n->n_nhid);
551*4dc78e53SAndroid Build Coastguard Worker 
552*4dc78e53SAndroid Build Coastguard Worker 	if (n->ce_mask & NEIGH_ATTR_MASTER) {
553*4dc78e53SAndroid Build Coastguard Worker 		if (link_cache)
554*4dc78e53SAndroid Build Coastguard Worker 			nl_dump(p, "%s ", rtnl_link_i2name(link_cache, n->n_master,
555*4dc78e53SAndroid Build Coastguard Worker 							   state, sizeof(state)));
556*4dc78e53SAndroid Build Coastguard Worker 		else
557*4dc78e53SAndroid Build Coastguard Worker 			nl_dump(p, "%d ", n->n_master);
558*4dc78e53SAndroid Build Coastguard Worker 	}
559*4dc78e53SAndroid Build Coastguard Worker 
560*4dc78e53SAndroid Build Coastguard Worker 	rtnl_neigh_state2str(n->n_state, state, sizeof(state));
561*4dc78e53SAndroid Build Coastguard Worker 	rtnl_neigh_flags2str(n->n_flags, flags, sizeof(flags));
562*4dc78e53SAndroid Build Coastguard Worker 
563*4dc78e53SAndroid Build Coastguard Worker 	if (state[0])
564*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "<%s", state);
565*4dc78e53SAndroid Build Coastguard Worker 	if (flags[0])
566*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "%s%s", state[0] ? "," : "<", flags);
567*4dc78e53SAndroid Build Coastguard Worker 	if (state[0] || flags[0])
568*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, ">");
569*4dc78e53SAndroid Build Coastguard Worker 	nl_dump(p, "\n");
570*4dc78e53SAndroid Build Coastguard Worker 
571*4dc78e53SAndroid Build Coastguard Worker 	if (link_cache)
572*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_put(link_cache);
573*4dc78e53SAndroid Build Coastguard Worker }
574*4dc78e53SAndroid Build Coastguard Worker 
neigh_dump_details(struct nl_object * a,struct nl_dump_params * p)575*4dc78e53SAndroid Build Coastguard Worker static void neigh_dump_details(struct nl_object *a, struct nl_dump_params *p)
576*4dc78e53SAndroid Build Coastguard Worker {
577*4dc78e53SAndroid Build Coastguard Worker 	char rtn_type[32];
578*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_neigh *n = (struct rtnl_neigh *) a;
579*4dc78e53SAndroid Build Coastguard Worker 	int hz = nl_get_user_hz();
580*4dc78e53SAndroid Build Coastguard Worker 
581*4dc78e53SAndroid Build Coastguard Worker 	neigh_dump_line(a, p);
582*4dc78e53SAndroid Build Coastguard Worker 
583*4dc78e53SAndroid Build Coastguard Worker 	nl_dump_line(p, "    refcnt %u type %s confirmed %u used "
584*4dc78e53SAndroid Build Coastguard Worker 				"%u updated %u\n",
585*4dc78e53SAndroid Build Coastguard Worker 		n->n_cacheinfo.nci_refcnt,
586*4dc78e53SAndroid Build Coastguard Worker 		nl_rtntype2str(n->n_type, rtn_type, sizeof(rtn_type)),
587*4dc78e53SAndroid Build Coastguard Worker 		n->n_cacheinfo.nci_confirmed/hz,
588*4dc78e53SAndroid Build Coastguard Worker 		n->n_cacheinfo.nci_used/hz, n->n_cacheinfo.nci_updated/hz);
589*4dc78e53SAndroid Build Coastguard Worker }
590*4dc78e53SAndroid Build Coastguard Worker 
neigh_dump_stats(struct nl_object * a,struct nl_dump_params * p)591*4dc78e53SAndroid Build Coastguard Worker static void neigh_dump_stats(struct nl_object *a, struct nl_dump_params *p)
592*4dc78e53SAndroid Build Coastguard Worker {
593*4dc78e53SAndroid Build Coastguard Worker 	neigh_dump_details(a, p);
594*4dc78e53SAndroid Build Coastguard Worker }
595*4dc78e53SAndroid Build Coastguard Worker 
596*4dc78e53SAndroid Build Coastguard Worker /**
597*4dc78e53SAndroid Build Coastguard Worker  * @name Neighbour Object Allocation/Freeage
598*4dc78e53SAndroid Build Coastguard Worker  * @{
599*4dc78e53SAndroid Build Coastguard Worker  */
600*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_alloc(void)601*4dc78e53SAndroid Build Coastguard Worker struct rtnl_neigh *rtnl_neigh_alloc(void)
602*4dc78e53SAndroid Build Coastguard Worker {
603*4dc78e53SAndroid Build Coastguard Worker 	return (struct rtnl_neigh *) nl_object_alloc(&neigh_obj_ops);
604*4dc78e53SAndroid Build Coastguard Worker }
605*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_put(struct rtnl_neigh * neigh)606*4dc78e53SAndroid Build Coastguard Worker void rtnl_neigh_put(struct rtnl_neigh *neigh)
607*4dc78e53SAndroid Build Coastguard Worker {
608*4dc78e53SAndroid Build Coastguard Worker 	nl_object_put((struct nl_object *) neigh);
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 /**
614*4dc78e53SAndroid Build Coastguard Worker  * @name Neighbour Cache Managament
615*4dc78e53SAndroid Build Coastguard Worker  * @{
616*4dc78e53SAndroid Build Coastguard Worker  */
617*4dc78e53SAndroid Build Coastguard Worker 
618*4dc78e53SAndroid Build Coastguard Worker /**
619*4dc78e53SAndroid Build Coastguard Worker  * Build a neighbour cache including all neighbours currently configured in the kernel.
620*4dc78e53SAndroid Build Coastguard Worker  * @arg sock		Netlink socket.
621*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting cache.
622*4dc78e53SAndroid Build Coastguard Worker  *
623*4dc78e53SAndroid Build Coastguard Worker  * Allocates a new neighbour cache, initializes it properly and updates it
624*4dc78e53SAndroid Build Coastguard Worker  * to include all neighbours currently configured in the kernel.
625*4dc78e53SAndroid Build Coastguard Worker  *
626*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
627*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_neigh_alloc_cache(struct nl_sock * sock,struct nl_cache ** result)628*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_alloc_cache(struct nl_sock *sock, struct nl_cache **result)
629*4dc78e53SAndroid Build Coastguard Worker {
630*4dc78e53SAndroid Build Coastguard Worker 	return nl_cache_alloc_and_fill(&rtnl_neigh_ops, sock, result);
631*4dc78e53SAndroid Build Coastguard Worker }
632*4dc78e53SAndroid Build Coastguard Worker 
633*4dc78e53SAndroid Build Coastguard Worker /**
634*4dc78e53SAndroid Build Coastguard Worker  * Build a neighbour cache including all neighbours currently configured in the kernel.
635*4dc78e53SAndroid Build Coastguard Worker  * @arg sock		Netlink socket.
636*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting cache.
637*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		Flags to apply to cache before filling
638*4dc78e53SAndroid Build Coastguard Worker  *
639*4dc78e53SAndroid Build Coastguard Worker  * Allocates a new neighbour cache, initializes it properly and updates it
640*4dc78e53SAndroid Build Coastguard Worker  * to include all neighbours currently configured in the kernel.
641*4dc78e53SAndroid Build Coastguard Worker  *
642*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
643*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_neigh_alloc_cache_flags(struct nl_sock * sock,struct nl_cache ** result,unsigned int flags)644*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_alloc_cache_flags(struct nl_sock *sock, struct nl_cache **result,
645*4dc78e53SAndroid Build Coastguard Worker 				 unsigned int flags)
646*4dc78e53SAndroid Build Coastguard Worker {
647*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache * cache;
648*4dc78e53SAndroid Build Coastguard Worker 	int err;
649*4dc78e53SAndroid Build Coastguard Worker 
650*4dc78e53SAndroid Build Coastguard Worker 	cache = nl_cache_alloc(&rtnl_neigh_ops);
651*4dc78e53SAndroid Build Coastguard Worker 	if (!cache)
652*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
653*4dc78e53SAndroid Build Coastguard Worker 
654*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_set_flags(cache, flags);
655*4dc78e53SAndroid Build Coastguard Worker 
656*4dc78e53SAndroid Build Coastguard Worker 	if (sock && (err = nl_cache_refill(sock, cache)) < 0) {
657*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_free(cache);
658*4dc78e53SAndroid Build Coastguard Worker 		return err;
659*4dc78e53SAndroid Build Coastguard Worker 	}
660*4dc78e53SAndroid Build Coastguard Worker 
661*4dc78e53SAndroid Build Coastguard Worker 	*result = cache;
662*4dc78e53SAndroid Build Coastguard Worker 	return 0;
663*4dc78e53SAndroid Build Coastguard Worker }
664*4dc78e53SAndroid Build Coastguard Worker 
665*4dc78e53SAndroid Build Coastguard Worker /**
666*4dc78e53SAndroid Build Coastguard Worker  * Look up a neighbour by interface index and destination address
667*4dc78e53SAndroid Build Coastguard Worker  * @arg cache		neighbour cache
668*4dc78e53SAndroid Build Coastguard Worker  * @arg ifindex		interface index the neighbour is on
669*4dc78e53SAndroid Build Coastguard Worker  * @arg dst		destination address of the neighbour
670*4dc78e53SAndroid Build Coastguard Worker  *
671*4dc78e53SAndroid Build Coastguard Worker  * @return neighbour handle or NULL if no match was found.
672*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_neigh_get(struct nl_cache * cache,int ifindex,struct nl_addr * dst)673*4dc78e53SAndroid Build Coastguard Worker struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex,
674*4dc78e53SAndroid Build Coastguard Worker 				   struct nl_addr *dst)
675*4dc78e53SAndroid Build Coastguard Worker {
676*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_neigh *neigh;
677*4dc78e53SAndroid Build Coastguard Worker 
678*4dc78e53SAndroid Build Coastguard Worker 	nl_list_for_each_entry(neigh, &cache->c_items, ce_list) {
679*4dc78e53SAndroid Build Coastguard Worker 		if (neigh->n_ifindex == ((unsigned)ifindex) &&
680*4dc78e53SAndroid Build Coastguard Worker 		    neigh->n_family == ((unsigned)dst->a_family) &&
681*4dc78e53SAndroid Build Coastguard Worker 		    !nl_addr_cmp(neigh->n_dst, dst)) {
682*4dc78e53SAndroid Build Coastguard Worker 			nl_object_get((struct nl_object *) neigh);
683*4dc78e53SAndroid Build Coastguard Worker 			return neigh;
684*4dc78e53SAndroid Build Coastguard Worker 		}
685*4dc78e53SAndroid Build Coastguard Worker 	}
686*4dc78e53SAndroid Build Coastguard Worker 
687*4dc78e53SAndroid Build Coastguard Worker 	return NULL;
688*4dc78e53SAndroid Build Coastguard Worker }
689*4dc78e53SAndroid Build Coastguard Worker 
690*4dc78e53SAndroid Build Coastguard Worker /**
691*4dc78e53SAndroid Build Coastguard Worker  * Look up a neighbour by interface index, link layer address and vlan id
692*4dc78e53SAndroid Build Coastguard Worker  * @arg cache		neighbour cache
693*4dc78e53SAndroid Build Coastguard Worker  * @arg ifindex 	interface index the neighbour is on
694*4dc78e53SAndroid Build Coastguard Worker  * @arg lladdr		link layer address of the neighbour
695*4dc78e53SAndroid Build Coastguard Worker  * @arg vlan		vlan id of the neighbour
696*4dc78e53SAndroid Build Coastguard Worker  *
697*4dc78e53SAndroid Build Coastguard Worker  * @return neighbour handle or NULL if no match was found.
698*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_neigh_get_by_vlan(struct nl_cache * cache,int ifindex,struct nl_addr * lladdr,int vlan)699*4dc78e53SAndroid Build Coastguard Worker struct rtnl_neigh * rtnl_neigh_get_by_vlan(struct nl_cache *cache, int ifindex,
700*4dc78e53SAndroid Build Coastguard Worker 					   struct nl_addr *lladdr, int vlan)
701*4dc78e53SAndroid Build Coastguard Worker {
702*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_neigh *neigh;
703*4dc78e53SAndroid Build Coastguard Worker 
704*4dc78e53SAndroid Build Coastguard Worker 	nl_list_for_each_entry(neigh, &cache->c_items, ce_list) {
705*4dc78e53SAndroid Build Coastguard Worker 		if ((neigh->n_ifindex == (unsigned)ifindex) &&
706*4dc78e53SAndroid Build Coastguard Worker 		    neigh->n_vlan == vlan && neigh->n_lladdr &&
707*4dc78e53SAndroid Build Coastguard Worker 		    !nl_addr_cmp(neigh->n_lladdr, lladdr)) {
708*4dc78e53SAndroid Build Coastguard Worker 			nl_object_get((struct nl_object *) neigh);
709*4dc78e53SAndroid Build Coastguard Worker 			return neigh;
710*4dc78e53SAndroid Build Coastguard Worker 		}
711*4dc78e53SAndroid Build Coastguard Worker 	}
712*4dc78e53SAndroid Build Coastguard Worker 
713*4dc78e53SAndroid Build Coastguard Worker 	return NULL;
714*4dc78e53SAndroid Build Coastguard Worker }
715*4dc78e53SAndroid Build Coastguard Worker 
716*4dc78e53SAndroid Build Coastguard Worker /** @} */
717*4dc78e53SAndroid Build Coastguard Worker 
718*4dc78e53SAndroid Build Coastguard Worker /**
719*4dc78e53SAndroid Build Coastguard Worker  * @name Neighbour Addition
720*4dc78e53SAndroid Build Coastguard Worker  * @{
721*4dc78e53SAndroid Build Coastguard Worker  */
722*4dc78e53SAndroid Build Coastguard Worker 
build_neigh_msg(struct rtnl_neigh * tmpl,int cmd,int flags,struct nl_msg ** result)723*4dc78e53SAndroid Build Coastguard Worker static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags,
724*4dc78e53SAndroid Build Coastguard Worker 			   struct nl_msg **result)
725*4dc78e53SAndroid Build Coastguard Worker {
726*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
727*4dc78e53SAndroid Build Coastguard Worker 	struct ndmsg nhdr = {
728*4dc78e53SAndroid Build Coastguard Worker 		.ndm_ifindex = tmpl->n_ifindex,
729*4dc78e53SAndroid Build Coastguard Worker 		.ndm_state = NUD_PERMANENT,
730*4dc78e53SAndroid Build Coastguard Worker 	};
731*4dc78e53SAndroid Build Coastguard Worker 
732*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->n_family != AF_BRIDGE) {
733*4dc78e53SAndroid Build Coastguard Worker 		if (!(tmpl->ce_mask & NEIGH_ATTR_DST))
734*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_MISSING_ATTR;
735*4dc78e53SAndroid Build Coastguard Worker 		nhdr.ndm_family = nl_addr_get_family(tmpl->n_dst);
736*4dc78e53SAndroid Build Coastguard Worker 	}
737*4dc78e53SAndroid Build Coastguard Worker 	else
738*4dc78e53SAndroid Build Coastguard Worker 		nhdr.ndm_family = AF_BRIDGE;
739*4dc78e53SAndroid Build Coastguard Worker 
740*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & NEIGH_ATTR_FLAGS)
741*4dc78e53SAndroid Build Coastguard Worker 		nhdr.ndm_flags = tmpl->n_flags;
742*4dc78e53SAndroid Build Coastguard Worker 
743*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & NEIGH_ATTR_STATE)
744*4dc78e53SAndroid Build Coastguard Worker 		nhdr.ndm_state = tmpl->n_state;
745*4dc78e53SAndroid Build Coastguard Worker 
746*4dc78e53SAndroid Build Coastguard Worker 	msg = nlmsg_alloc_simple(cmd, flags);
747*4dc78e53SAndroid Build Coastguard Worker 	if (!msg)
748*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
749*4dc78e53SAndroid Build Coastguard Worker 
750*4dc78e53SAndroid Build Coastguard Worker 	if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0)
751*4dc78e53SAndroid Build Coastguard Worker 		goto nla_put_failure;
752*4dc78e53SAndroid Build Coastguard Worker 
753*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & NEIGH_ATTR_DST)
754*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst);
755*4dc78e53SAndroid Build Coastguard Worker 
756*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & NEIGH_ATTR_LLADDR)
757*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr);
758*4dc78e53SAndroid Build Coastguard Worker 
759*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & NEIGH_ATTR_VLAN)
760*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U16(msg, NDA_VLAN, tmpl->n_vlan);
761*4dc78e53SAndroid Build Coastguard Worker 
762*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & NEIGH_ATTR_NHID)
763*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, NDA_NH_ID, tmpl->n_nhid);
764*4dc78e53SAndroid Build Coastguard Worker 
765*4dc78e53SAndroid Build Coastguard Worker 	*result = msg;
766*4dc78e53SAndroid Build Coastguard Worker 	return 0;
767*4dc78e53SAndroid Build Coastguard Worker 
768*4dc78e53SAndroid Build Coastguard Worker nla_put_failure:
769*4dc78e53SAndroid Build Coastguard Worker 	nlmsg_free(msg);
770*4dc78e53SAndroid Build Coastguard Worker 	return -NLE_MSGSIZE;
771*4dc78e53SAndroid Build Coastguard Worker }
772*4dc78e53SAndroid Build Coastguard Worker 
773*4dc78e53SAndroid Build Coastguard Worker /**
774*4dc78e53SAndroid Build Coastguard Worker  * Build netlink request message to add a new neighbour
775*4dc78e53SAndroid Build Coastguard Worker  * @arg tmpl		template with data of new neighbour
776*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		additional netlink message flags
777*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting message.
778*4dc78e53SAndroid Build Coastguard Worker  *
779*4dc78e53SAndroid Build Coastguard Worker  * Builds a new netlink message requesting a addition of a new
780*4dc78e53SAndroid Build Coastguard Worker  * neighbour. The netlink message header isn't fully equipped with
781*4dc78e53SAndroid Build Coastguard Worker  * all relevant fields and must thus be sent out via nl_send_auto_complete()
782*4dc78e53SAndroid Build Coastguard Worker  * or supplemented as needed. \a tmpl must contain the attributes of the new
783*4dc78e53SAndroid Build Coastguard Worker  * neighbour set via \c rtnl_neigh_set_* functions.
784*4dc78e53SAndroid Build Coastguard Worker  *
785*4dc78e53SAndroid Build Coastguard Worker  * The following attributes must be set in the template:
786*4dc78e53SAndroid Build Coastguard Worker  *  - Interface index (rtnl_neigh_set_ifindex())
787*4dc78e53SAndroid Build Coastguard Worker  *  - State (rtnl_neigh_set_state())
788*4dc78e53SAndroid Build Coastguard Worker  *  - Destination address (rtnl_neigh_set_dst())
789*4dc78e53SAndroid Build Coastguard Worker  *  - Link layer address (rtnl_neigh_set_lladdr())
790*4dc78e53SAndroid Build Coastguard Worker  *
791*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
792*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_neigh_build_add_request(struct rtnl_neigh * tmpl,int flags,struct nl_msg ** result)793*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags,
794*4dc78e53SAndroid Build Coastguard Worker 				 struct nl_msg **result)
795*4dc78e53SAndroid Build Coastguard Worker {
796*4dc78e53SAndroid Build Coastguard Worker 	return build_neigh_msg(tmpl, RTM_NEWNEIGH, flags, result);
797*4dc78e53SAndroid Build Coastguard Worker }
798*4dc78e53SAndroid Build Coastguard Worker 
799*4dc78e53SAndroid Build Coastguard Worker /**
800*4dc78e53SAndroid Build Coastguard Worker  * Add a new neighbour
801*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
802*4dc78e53SAndroid Build Coastguard Worker  * @arg tmpl		template with requested changes
803*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		additional netlink message flags
804*4dc78e53SAndroid Build Coastguard Worker  *
805*4dc78e53SAndroid Build Coastguard Worker  * Builds a netlink message by calling rtnl_neigh_build_add_request(),
806*4dc78e53SAndroid Build Coastguard Worker  * sends the request to the kernel and waits for the next ACK to be
807*4dc78e53SAndroid Build Coastguard Worker  * received and thus blocks until the request has been fullfilled.
808*4dc78e53SAndroid Build Coastguard Worker  *
809*4dc78e53SAndroid Build Coastguard Worker  * The following attributes must be set in the template:
810*4dc78e53SAndroid Build Coastguard Worker  *  - Interface index (rtnl_neigh_set_ifindex())
811*4dc78e53SAndroid Build Coastguard Worker  *  - State (rtnl_neigh_set_state())
812*4dc78e53SAndroid Build Coastguard Worker  *  - Destination address (rtnl_neigh_set_dst())
813*4dc78e53SAndroid Build Coastguard Worker  *  - Link layer address (rtnl_neigh_set_lladdr())
814*4dc78e53SAndroid Build Coastguard Worker  *
815*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error if an error occured.
816*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_neigh_add(struct nl_sock * sk,struct rtnl_neigh * tmpl,int flags)817*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags)
818*4dc78e53SAndroid Build Coastguard Worker {
819*4dc78e53SAndroid Build Coastguard Worker 	int err;
820*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
821*4dc78e53SAndroid Build Coastguard Worker 
822*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_neigh_build_add_request(tmpl, flags, &msg)) < 0)
823*4dc78e53SAndroid Build Coastguard Worker 		return err;
824*4dc78e53SAndroid Build Coastguard Worker 
825*4dc78e53SAndroid Build Coastguard Worker 	err = nl_send_auto_complete(sk, msg);
826*4dc78e53SAndroid Build Coastguard Worker 	nlmsg_free(msg);
827*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
828*4dc78e53SAndroid Build Coastguard Worker 		return err;
829*4dc78e53SAndroid Build Coastguard Worker 
830*4dc78e53SAndroid Build Coastguard Worker 	return wait_for_ack(sk);
831*4dc78e53SAndroid Build Coastguard Worker }
832*4dc78e53SAndroid Build Coastguard Worker 
833*4dc78e53SAndroid Build Coastguard Worker /** @} */
834*4dc78e53SAndroid Build Coastguard Worker 
835*4dc78e53SAndroid Build Coastguard Worker /**
836*4dc78e53SAndroid Build Coastguard Worker  * @name Neighbour Deletion
837*4dc78e53SAndroid Build Coastguard Worker  * @{
838*4dc78e53SAndroid Build Coastguard Worker  */
839*4dc78e53SAndroid Build Coastguard Worker 
840*4dc78e53SAndroid Build Coastguard Worker /**
841*4dc78e53SAndroid Build Coastguard Worker  * Build a netlink request message to delete a neighbour
842*4dc78e53SAndroid Build Coastguard Worker  * @arg neigh		neighbour to delete
843*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		additional netlink message flags
844*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting message.
845*4dc78e53SAndroid Build Coastguard Worker  *
846*4dc78e53SAndroid Build Coastguard Worker  * Builds a new netlink message requesting a deletion of a neighbour.
847*4dc78e53SAndroid Build Coastguard Worker  * The netlink message header isn't fully equipped with all relevant
848*4dc78e53SAndroid Build Coastguard Worker  * fields and must thus be sent out via nl_send_auto_complete()
849*4dc78e53SAndroid Build Coastguard Worker  * or supplemented as needed. \a neigh must point to an existing
850*4dc78e53SAndroid Build Coastguard Worker  * neighbour.
851*4dc78e53SAndroid Build Coastguard Worker  *
852*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
853*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_neigh_build_delete_request(struct rtnl_neigh * neigh,int flags,struct nl_msg ** result)854*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, int flags,
855*4dc78e53SAndroid Build Coastguard Worker 				    struct nl_msg **result)
856*4dc78e53SAndroid Build Coastguard Worker {
857*4dc78e53SAndroid Build Coastguard Worker 	return build_neigh_msg(neigh, RTM_DELNEIGH, flags, result);
858*4dc78e53SAndroid Build Coastguard Worker }
859*4dc78e53SAndroid Build Coastguard Worker 
860*4dc78e53SAndroid Build Coastguard Worker /**
861*4dc78e53SAndroid Build Coastguard Worker  * Delete a neighbour
862*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
863*4dc78e53SAndroid Build Coastguard Worker  * @arg neigh		neighbour to delete
864*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		additional netlink message flags
865*4dc78e53SAndroid Build Coastguard Worker  *
866*4dc78e53SAndroid Build Coastguard Worker  * Builds a netlink message by calling rtnl_neigh_build_delete_request(),
867*4dc78e53SAndroid Build Coastguard Worker  * sends the request to the kernel and waits for the next ACK to be
868*4dc78e53SAndroid Build Coastguard Worker  * received and thus blocks until the request has been fullfilled.
869*4dc78e53SAndroid Build Coastguard Worker  *
870*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error if an error occured.
871*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_neigh_delete(struct nl_sock * sk,struct rtnl_neigh * neigh,int flags)872*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh,
873*4dc78e53SAndroid Build Coastguard Worker 		      int flags)
874*4dc78e53SAndroid Build Coastguard Worker {
875*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
876*4dc78e53SAndroid Build Coastguard Worker 	int err;
877*4dc78e53SAndroid Build Coastguard Worker 
878*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_neigh_build_delete_request(neigh, flags, &msg)) < 0)
879*4dc78e53SAndroid Build Coastguard Worker 		return err;
880*4dc78e53SAndroid Build Coastguard Worker 
881*4dc78e53SAndroid Build Coastguard Worker 	err = nl_send_auto_complete(sk, msg);
882*4dc78e53SAndroid Build Coastguard Worker 	nlmsg_free(msg);
883*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
884*4dc78e53SAndroid Build Coastguard Worker 		return err;
885*4dc78e53SAndroid Build Coastguard Worker 
886*4dc78e53SAndroid Build Coastguard Worker 	return wait_for_ack(sk);
887*4dc78e53SAndroid Build Coastguard Worker }
888*4dc78e53SAndroid Build Coastguard Worker 
889*4dc78e53SAndroid Build Coastguard Worker /** @} */
890*4dc78e53SAndroid Build Coastguard Worker 
891*4dc78e53SAndroid Build Coastguard Worker /**
892*4dc78e53SAndroid Build Coastguard Worker  * @name Neighbour States Translations
893*4dc78e53SAndroid Build Coastguard Worker  * @{
894*4dc78e53SAndroid Build Coastguard Worker  */
895*4dc78e53SAndroid Build Coastguard Worker 
896*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl neigh_states[] = {
897*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NUD_INCOMPLETE, incomplete),
898*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NUD_REACHABLE, reachable),
899*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NUD_STALE, stale),
900*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NUD_DELAY, delay),
901*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NUD_PROBE, probe),
902*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NUD_FAILED, failed),
903*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NUD_NOARP, noarp),
904*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NUD_PERMANENT, permanent),
905*4dc78e53SAndroid Build Coastguard Worker 
906*4dc78e53SAndroid Build Coastguard Worker 	/* Accept this value for backward compatibility. Originally
907*4dc78e53SAndroid Build Coastguard Worker 	 * there was a typo in the string value. This was fixed later,
908*4dc78e53SAndroid Build Coastguard Worker 	 * but we still want to successfully parse "norarp". */
909*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NUD_NOARP, norarp),
910*4dc78e53SAndroid Build Coastguard Worker };
911*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_state2str(int state,char * buf,size_t len)912*4dc78e53SAndroid Build Coastguard Worker char * rtnl_neigh_state2str(int state, char *buf, size_t len)
913*4dc78e53SAndroid Build Coastguard Worker {
914*4dc78e53SAndroid Build Coastguard Worker 	return __flags2str(state, buf, len, neigh_states,
915*4dc78e53SAndroid Build Coastguard Worker 	    ARRAY_SIZE(neigh_states) - 1);
916*4dc78e53SAndroid Build Coastguard Worker }
917*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_str2state(const char * name)918*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_str2state(const char *name)
919*4dc78e53SAndroid Build Coastguard Worker {
920*4dc78e53SAndroid Build Coastguard Worker 	return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states));
921*4dc78e53SAndroid Build Coastguard Worker }
922*4dc78e53SAndroid Build Coastguard Worker 
923*4dc78e53SAndroid Build Coastguard Worker /** @} */
924*4dc78e53SAndroid Build Coastguard Worker 
925*4dc78e53SAndroid Build Coastguard Worker /**
926*4dc78e53SAndroid Build Coastguard Worker  * @name Neighbour Flags Translations
927*4dc78e53SAndroid Build Coastguard Worker  * @{
928*4dc78e53SAndroid Build Coastguard Worker  */
929*4dc78e53SAndroid Build Coastguard Worker 
930*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl neigh_flags[] = {
931*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NTF_USE, use),
932*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NTF_PROXY, proxy),
933*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NTF_ROUTER, router),
934*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NTF_SELF, self),
935*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NTF_MASTER, master),
936*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NTF_EXT_LEARNED, ext_learned),
937*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NTF_OFFLOADED, offloaded),
938*4dc78e53SAndroid Build Coastguard Worker };
939*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_flags2str(int flags,char * buf,size_t len)940*4dc78e53SAndroid Build Coastguard Worker char * rtnl_neigh_flags2str(int flags, char *buf, size_t len)
941*4dc78e53SAndroid Build Coastguard Worker {
942*4dc78e53SAndroid Build Coastguard Worker 	return __flags2str(flags, buf, len, neigh_flags,
943*4dc78e53SAndroid Build Coastguard Worker 	    ARRAY_SIZE(neigh_flags));
944*4dc78e53SAndroid Build Coastguard Worker }
945*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_str2flag(const char * name)946*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_str2flag(const char *name)
947*4dc78e53SAndroid Build Coastguard Worker {
948*4dc78e53SAndroid Build Coastguard Worker 	return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags));
949*4dc78e53SAndroid Build Coastguard Worker }
950*4dc78e53SAndroid Build Coastguard Worker 
951*4dc78e53SAndroid Build Coastguard Worker /** @} */
952*4dc78e53SAndroid Build Coastguard Worker 
953*4dc78e53SAndroid Build Coastguard Worker /**
954*4dc78e53SAndroid Build Coastguard Worker  * @name Attributes
955*4dc78e53SAndroid Build Coastguard Worker  * @{
956*4dc78e53SAndroid Build Coastguard Worker  */
957*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_set_state(struct rtnl_neigh * neigh,int state)958*4dc78e53SAndroid Build Coastguard Worker void rtnl_neigh_set_state(struct rtnl_neigh *neigh, int state)
959*4dc78e53SAndroid Build Coastguard Worker {
960*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_state_mask |= state;
961*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_state |= state;
962*4dc78e53SAndroid Build Coastguard Worker 	neigh->ce_mask |= NEIGH_ATTR_STATE;
963*4dc78e53SAndroid Build Coastguard Worker }
964*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_get_state(struct rtnl_neigh * neigh)965*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_get_state(struct rtnl_neigh *neigh)
966*4dc78e53SAndroid Build Coastguard Worker {
967*4dc78e53SAndroid Build Coastguard Worker 	if (neigh->ce_mask & NEIGH_ATTR_STATE)
968*4dc78e53SAndroid Build Coastguard Worker 		return neigh->n_state;
969*4dc78e53SAndroid Build Coastguard Worker 	else
970*4dc78e53SAndroid Build Coastguard Worker 		return -1;
971*4dc78e53SAndroid Build Coastguard Worker }
972*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_unset_state(struct rtnl_neigh * neigh,int state)973*4dc78e53SAndroid Build Coastguard Worker void rtnl_neigh_unset_state(struct rtnl_neigh *neigh, int state)
974*4dc78e53SAndroid Build Coastguard Worker {
975*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_state_mask |= state;
976*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_state &= ~state;
977*4dc78e53SAndroid Build Coastguard Worker 	neigh->ce_mask |= NEIGH_ATTR_STATE;
978*4dc78e53SAndroid Build Coastguard Worker }
979*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_set_flags(struct rtnl_neigh * neigh,unsigned int flags)980*4dc78e53SAndroid Build Coastguard Worker void rtnl_neigh_set_flags(struct rtnl_neigh *neigh, unsigned int flags)
981*4dc78e53SAndroid Build Coastguard Worker {
982*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_flag_mask |= flags;
983*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_flags |= flags;
984*4dc78e53SAndroid Build Coastguard Worker 	neigh->ce_mask |= NEIGH_ATTR_FLAGS;
985*4dc78e53SAndroid Build Coastguard Worker }
986*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_get_flags(struct rtnl_neigh * neigh)987*4dc78e53SAndroid Build Coastguard Worker unsigned int rtnl_neigh_get_flags(struct rtnl_neigh *neigh)
988*4dc78e53SAndroid Build Coastguard Worker {
989*4dc78e53SAndroid Build Coastguard Worker 	return neigh->n_flags;
990*4dc78e53SAndroid Build Coastguard Worker }
991*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_unset_flags(struct rtnl_neigh * neigh,unsigned int flags)992*4dc78e53SAndroid Build Coastguard Worker void rtnl_neigh_unset_flags(struct rtnl_neigh *neigh, unsigned int flags)
993*4dc78e53SAndroid Build Coastguard Worker {
994*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_flag_mask |= flags;
995*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_flags &= ~flags;
996*4dc78e53SAndroid Build Coastguard Worker 	neigh->ce_mask |= NEIGH_ATTR_FLAGS;
997*4dc78e53SAndroid Build Coastguard Worker }
998*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_set_ifindex(struct rtnl_neigh * neigh,int ifindex)999*4dc78e53SAndroid Build Coastguard Worker void rtnl_neigh_set_ifindex(struct rtnl_neigh *neigh, int ifindex)
1000*4dc78e53SAndroid Build Coastguard Worker {
1001*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_ifindex = ifindex;
1002*4dc78e53SAndroid Build Coastguard Worker 	neigh->ce_mask |= NEIGH_ATTR_IFINDEX;
1003*4dc78e53SAndroid Build Coastguard Worker }
1004*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_get_ifindex(struct rtnl_neigh * neigh)1005*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_get_ifindex(struct rtnl_neigh *neigh)
1006*4dc78e53SAndroid Build Coastguard Worker {
1007*4dc78e53SAndroid Build Coastguard Worker 	return neigh->n_ifindex;
1008*4dc78e53SAndroid Build Coastguard Worker }
1009*4dc78e53SAndroid Build Coastguard Worker 
__assign_addr(struct rtnl_neigh * neigh,struct nl_addr ** pos,struct nl_addr * new,int flag,int nocheck)1010*4dc78e53SAndroid Build Coastguard Worker static inline int __assign_addr(struct rtnl_neigh *neigh, struct nl_addr **pos,
1011*4dc78e53SAndroid Build Coastguard Worker 			        struct nl_addr *new, int flag, int nocheck)
1012*4dc78e53SAndroid Build Coastguard Worker {
1013*4dc78e53SAndroid Build Coastguard Worker 	if (!nocheck) {
1014*4dc78e53SAndroid Build Coastguard Worker 		if (neigh->ce_mask & NEIGH_ATTR_FAMILY) {
1015*4dc78e53SAndroid Build Coastguard Worker 			if (neigh->n_family != ((unsigned)new->a_family))
1016*4dc78e53SAndroid Build Coastguard Worker 				return -NLE_AF_MISMATCH;
1017*4dc78e53SAndroid Build Coastguard Worker 		} else {
1018*4dc78e53SAndroid Build Coastguard Worker 			neigh->n_family = new->a_family;
1019*4dc78e53SAndroid Build Coastguard Worker 			neigh->ce_mask |= NEIGH_ATTR_FAMILY;
1020*4dc78e53SAndroid Build Coastguard Worker 		}
1021*4dc78e53SAndroid Build Coastguard Worker 	}
1022*4dc78e53SAndroid Build Coastguard Worker 
1023*4dc78e53SAndroid Build Coastguard Worker 	if (*pos)
1024*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_put(*pos);
1025*4dc78e53SAndroid Build Coastguard Worker 
1026*4dc78e53SAndroid Build Coastguard Worker 	nl_addr_get(new);
1027*4dc78e53SAndroid Build Coastguard Worker 	*pos = new;
1028*4dc78e53SAndroid Build Coastguard Worker 
1029*4dc78e53SAndroid Build Coastguard Worker 	neigh->ce_mask |= flag;
1030*4dc78e53SAndroid Build Coastguard Worker 
1031*4dc78e53SAndroid Build Coastguard Worker 	return 0;
1032*4dc78e53SAndroid Build Coastguard Worker }
1033*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_set_lladdr(struct rtnl_neigh * neigh,struct nl_addr * addr)1034*4dc78e53SAndroid Build Coastguard Worker void rtnl_neigh_set_lladdr(struct rtnl_neigh *neigh, struct nl_addr *addr)
1035*4dc78e53SAndroid Build Coastguard Worker {
1036*4dc78e53SAndroid Build Coastguard Worker 	__assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1);
1037*4dc78e53SAndroid Build Coastguard Worker }
1038*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_get_lladdr(struct rtnl_neigh * neigh)1039*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_neigh_get_lladdr(struct rtnl_neigh *neigh)
1040*4dc78e53SAndroid Build Coastguard Worker {
1041*4dc78e53SAndroid Build Coastguard Worker 	if (neigh->ce_mask & NEIGH_ATTR_LLADDR)
1042*4dc78e53SAndroid Build Coastguard Worker 		return neigh->n_lladdr;
1043*4dc78e53SAndroid Build Coastguard Worker 	else
1044*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
1045*4dc78e53SAndroid Build Coastguard Worker }
1046*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_set_dst(struct rtnl_neigh * neigh,struct nl_addr * addr)1047*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_set_dst(struct rtnl_neigh *neigh, struct nl_addr *addr)
1048*4dc78e53SAndroid Build Coastguard Worker {
1049*4dc78e53SAndroid Build Coastguard Worker 	return __assign_addr(neigh, &neigh->n_dst, addr,
1050*4dc78e53SAndroid Build Coastguard Worker 			     NEIGH_ATTR_DST, 0);
1051*4dc78e53SAndroid Build Coastguard Worker }
1052*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_get_dst(struct rtnl_neigh * neigh)1053*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_neigh_get_dst(struct rtnl_neigh *neigh)
1054*4dc78e53SAndroid Build Coastguard Worker {
1055*4dc78e53SAndroid Build Coastguard Worker 	if (neigh->ce_mask & NEIGH_ATTR_DST)
1056*4dc78e53SAndroid Build Coastguard Worker 		return neigh->n_dst;
1057*4dc78e53SAndroid Build Coastguard Worker 	else
1058*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
1059*4dc78e53SAndroid Build Coastguard Worker }
1060*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_set_family(struct rtnl_neigh * neigh,int family)1061*4dc78e53SAndroid Build Coastguard Worker void rtnl_neigh_set_family(struct rtnl_neigh *neigh, int family)
1062*4dc78e53SAndroid Build Coastguard Worker {
1063*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_family = family;
1064*4dc78e53SAndroid Build Coastguard Worker 	neigh->ce_mask |= NEIGH_ATTR_FAMILY;
1065*4dc78e53SAndroid Build Coastguard Worker }
1066*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_get_family(struct rtnl_neigh * neigh)1067*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_get_family(struct rtnl_neigh *neigh)
1068*4dc78e53SAndroid Build Coastguard Worker {
1069*4dc78e53SAndroid Build Coastguard Worker 	return neigh->n_family;
1070*4dc78e53SAndroid Build Coastguard Worker }
1071*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_set_type(struct rtnl_neigh * neigh,int type)1072*4dc78e53SAndroid Build Coastguard Worker void rtnl_neigh_set_type(struct rtnl_neigh *neigh, int type)
1073*4dc78e53SAndroid Build Coastguard Worker {
1074*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_type = type;
1075*4dc78e53SAndroid Build Coastguard Worker 	neigh->ce_mask = NEIGH_ATTR_TYPE;
1076*4dc78e53SAndroid Build Coastguard Worker }
1077*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_get_type(struct rtnl_neigh * neigh)1078*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_get_type(struct rtnl_neigh *neigh)
1079*4dc78e53SAndroid Build Coastguard Worker {
1080*4dc78e53SAndroid Build Coastguard Worker 	if (neigh->ce_mask & NEIGH_ATTR_TYPE)
1081*4dc78e53SAndroid Build Coastguard Worker 		return neigh->n_type;
1082*4dc78e53SAndroid Build Coastguard Worker 	else
1083*4dc78e53SAndroid Build Coastguard Worker 		return -1;
1084*4dc78e53SAndroid Build Coastguard Worker }
1085*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_set_vlan(struct rtnl_neigh * neigh,int vlan)1086*4dc78e53SAndroid Build Coastguard Worker void rtnl_neigh_set_vlan(struct rtnl_neigh *neigh, int vlan)
1087*4dc78e53SAndroid Build Coastguard Worker {
1088*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_vlan = vlan;
1089*4dc78e53SAndroid Build Coastguard Worker 	neigh->ce_mask |= NEIGH_ATTR_VLAN;
1090*4dc78e53SAndroid Build Coastguard Worker }
1091*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_get_vlan(struct rtnl_neigh * neigh)1092*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_get_vlan(struct rtnl_neigh *neigh)
1093*4dc78e53SAndroid Build Coastguard Worker {
1094*4dc78e53SAndroid Build Coastguard Worker 	if (neigh->ce_mask & NEIGH_ATTR_VLAN)
1095*4dc78e53SAndroid Build Coastguard Worker 		return neigh->n_vlan;
1096*4dc78e53SAndroid Build Coastguard Worker 	else
1097*4dc78e53SAndroid Build Coastguard Worker 		return -1;
1098*4dc78e53SAndroid Build Coastguard Worker }
1099*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_set_master(struct rtnl_neigh * neigh,int ifindex)1100*4dc78e53SAndroid Build Coastguard Worker void rtnl_neigh_set_master(struct rtnl_neigh *neigh, int ifindex)
1101*4dc78e53SAndroid Build Coastguard Worker {
1102*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_master = ifindex;
1103*4dc78e53SAndroid Build Coastguard Worker 	neigh->ce_mask |= NEIGH_ATTR_MASTER;
1104*4dc78e53SAndroid Build Coastguard Worker }
1105*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_get_master(struct rtnl_neigh * neigh)1106*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_get_master(struct rtnl_neigh *neigh) {
1107*4dc78e53SAndroid Build Coastguard Worker 	return neigh->n_master;
1108*4dc78e53SAndroid Build Coastguard Worker }
1109*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_set_nhid(struct rtnl_neigh * neigh,uint32_t nhid)1110*4dc78e53SAndroid Build Coastguard Worker void rtnl_neigh_set_nhid(struct rtnl_neigh *neigh, uint32_t nhid)
1111*4dc78e53SAndroid Build Coastguard Worker {
1112*4dc78e53SAndroid Build Coastguard Worker 	neigh->n_nhid = nhid;
1113*4dc78e53SAndroid Build Coastguard Worker 	neigh->ce_mask |= NEIGH_ATTR_NHID;
1114*4dc78e53SAndroid Build Coastguard Worker }
1115*4dc78e53SAndroid Build Coastguard Worker 
rtnl_neigh_get_nhid(struct rtnl_neigh * neigh,uint32_t * out_val)1116*4dc78e53SAndroid Build Coastguard Worker int rtnl_neigh_get_nhid(struct rtnl_neigh *neigh, uint32_t *out_val) {
1117*4dc78e53SAndroid Build Coastguard Worker 	if (!(neigh->ce_mask & NEIGH_ATTR_NHID))
1118*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOATTR;
1119*4dc78e53SAndroid Build Coastguard Worker 
1120*4dc78e53SAndroid Build Coastguard Worker 	*out_val = neigh->n_nhid;
1121*4dc78e53SAndroid Build Coastguard Worker 	return NLE_SUCCESS;
1122*4dc78e53SAndroid Build Coastguard Worker }
1123*4dc78e53SAndroid Build Coastguard Worker 
1124*4dc78e53SAndroid Build Coastguard Worker /** @} */
1125*4dc78e53SAndroid Build Coastguard Worker 
1126*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops neigh_obj_ops = {
1127*4dc78e53SAndroid Build Coastguard Worker 	.oo_name		= "route/neigh",
1128*4dc78e53SAndroid Build Coastguard Worker 	.oo_size		= sizeof(struct rtnl_neigh),
1129*4dc78e53SAndroid Build Coastguard Worker 	.oo_free_data		= neigh_free_data,
1130*4dc78e53SAndroid Build Coastguard Worker 	.oo_clone		= neigh_clone,
1131*4dc78e53SAndroid Build Coastguard Worker 	.oo_dump = {
1132*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_LINE]	= neigh_dump_line,
1133*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_DETAILS]	= neigh_dump_details,
1134*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_STATS]	= neigh_dump_stats,
1135*4dc78e53SAndroid Build Coastguard Worker 	},
1136*4dc78e53SAndroid Build Coastguard Worker 	.oo_compare		= neigh_compare,
1137*4dc78e53SAndroid Build Coastguard Worker 	.oo_keygen		= neigh_keygen,
1138*4dc78e53SAndroid Build Coastguard Worker 	.oo_attrs2str		= neigh_attrs2str,
1139*4dc78e53SAndroid Build Coastguard Worker 	.oo_id_attrs		= (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY),
1140*4dc78e53SAndroid Build Coastguard Worker 	.oo_id_attrs_get	= neigh_id_attrs_get
1141*4dc78e53SAndroid Build Coastguard Worker };
1142*4dc78e53SAndroid Build Coastguard Worker 
1143*4dc78e53SAndroid Build Coastguard Worker static struct nl_af_group neigh_groups[] = {
1144*4dc78e53SAndroid Build Coastguard Worker 	{ AF_UNSPEC, RTNLGRP_NEIGH },
1145*4dc78e53SAndroid Build Coastguard Worker 	{ AF_BRIDGE, RTNLGRP_NEIGH },
1146*4dc78e53SAndroid Build Coastguard Worker 	{ END_OF_GROUP_LIST },
1147*4dc78e53SAndroid Build Coastguard Worker };
1148*4dc78e53SAndroid Build Coastguard Worker 
1149*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_neigh_ops = {
1150*4dc78e53SAndroid Build Coastguard Worker 	.co_name		= "route/neigh",
1151*4dc78e53SAndroid Build Coastguard Worker 	.co_hdrsize		= sizeof(struct ndmsg),
1152*4dc78e53SAndroid Build Coastguard Worker 	.co_msgtypes		= {
1153*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_NEWNEIGH, NL_ACT_NEW, "new" },
1154*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_DELNEIGH, NL_ACT_DEL, "del" },
1155*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_GETNEIGH, NL_ACT_GET, "get" },
1156*4dc78e53SAndroid Build Coastguard Worker 					END_OF_MSGTYPES_LIST,
1157*4dc78e53SAndroid Build Coastguard Worker 				  },
1158*4dc78e53SAndroid Build Coastguard Worker 	.co_protocol		= NETLINK_ROUTE,
1159*4dc78e53SAndroid Build Coastguard Worker 	.co_groups		= neigh_groups,
1160*4dc78e53SAndroid Build Coastguard Worker 	.co_request_update	= neigh_request_update,
1161*4dc78e53SAndroid Build Coastguard Worker 	.co_msg_parser		= neigh_msg_parser,
1162*4dc78e53SAndroid Build Coastguard Worker 	.co_obj_ops		= &neigh_obj_ops,
1163*4dc78e53SAndroid Build Coastguard Worker };
1164*4dc78e53SAndroid Build Coastguard Worker 
neigh_init(void)1165*4dc78e53SAndroid Build Coastguard Worker static void _nl_init neigh_init(void)
1166*4dc78e53SAndroid Build Coastguard Worker {
1167*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_mngt_register(&rtnl_neigh_ops);
1168*4dc78e53SAndroid Build Coastguard Worker }
1169*4dc78e53SAndroid Build Coastguard Worker 
neigh_exit(void)1170*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit neigh_exit(void)
1171*4dc78e53SAndroid Build Coastguard Worker {
1172*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_mngt_unregister(&rtnl_neigh_ops);
1173*4dc78e53SAndroid Build Coastguard Worker }
1174*4dc78e53SAndroid Build Coastguard Worker 
1175*4dc78e53SAndroid Build Coastguard Worker /** @} */
1176