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