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