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