libnl  3.2.7
neigh.c
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-local.h>
152 #include <netlink/netlink.h>
153 #include <netlink/utils.h>
154 #include <netlink/route/rtnl.h>
155 #include <netlink/route/neighbour.h>
156 #include <netlink/route/link.h>
157 
158 /** @cond SKIP */
159 #define NEIGH_ATTR_FLAGS 0x01
160 #define NEIGH_ATTR_STATE 0x02
161 #define NEIGH_ATTR_LLADDR 0x04
162 #define NEIGH_ATTR_DST 0x08
163 #define NEIGH_ATTR_CACHEINFO 0x10
164 #define NEIGH_ATTR_IFINDEX 0x20
165 #define NEIGH_ATTR_FAMILY 0x40
166 #define NEIGH_ATTR_TYPE 0x80
167 #define NEIGH_ATTR_PROBES 0x100
168 
169 static struct nl_cache_ops rtnl_neigh_ops;
170 static struct nl_object_ops neigh_obj_ops;
171 /** @endcond */
172 
173 static void neigh_free_data(struct nl_object *c)
174 {
175  struct rtnl_neigh *neigh = nl_object_priv(c);
176 
177  if (!neigh)
178  return;
179 
180  nl_addr_put(neigh->n_lladdr);
181  nl_addr_put(neigh->n_dst);
182 }
183 
184 static int neigh_clone(struct nl_object *_dst, struct nl_object *_src)
185 {
186  struct rtnl_neigh *dst = nl_object_priv(_dst);
187  struct rtnl_neigh *src = nl_object_priv(_src);
188 
189  if (src->n_lladdr)
190  if (!(dst->n_lladdr = nl_addr_clone(src->n_lladdr)))
191  return -NLE_NOMEM;
192 
193  if (src->n_dst)
194  if (!(dst->n_dst = nl_addr_clone(src->n_dst)))
195  return -NLE_NOMEM;
196 
197  return 0;
198 }
199 
200 static int neigh_compare(struct nl_object *_a, struct nl_object *_b,
201  uint32_t attrs, int flags)
202 {
203  struct rtnl_neigh *a = (struct rtnl_neigh *) _a;
204  struct rtnl_neigh *b = (struct rtnl_neigh *) _b;
205  int diff = 0;
206 
207 #define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR)
208 
209  diff |= NEIGH_DIFF(IFINDEX, a->n_ifindex != b->n_ifindex);
210  diff |= NEIGH_DIFF(FAMILY, a->n_family != b->n_family);
211  diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type);
212  diff |= NEIGH_DIFF(LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr));
213  diff |= NEIGH_DIFF(DST, nl_addr_cmp(a->n_dst, b->n_dst));
214 
215  if (flags & LOOSE_COMPARISON) {
216  diff |= NEIGH_DIFF(STATE,
217  (a->n_state ^ b->n_state) & b->n_state_mask);
218  diff |= NEIGH_DIFF(FLAGS,
219  (a->n_flags ^ b->n_flags) & b->n_flag_mask);
220  } else {
221  diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state);
222  diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags);
223  }
224 
225 #undef NEIGH_DIFF
226 
227  return diff;
228 }
229 
230 static const struct trans_tbl neigh_attrs[] = {
231  __ADD(NEIGH_ATTR_FLAGS, flags)
232  __ADD(NEIGH_ATTR_STATE, state)
233  __ADD(NEIGH_ATTR_LLADDR, lladdr)
234  __ADD(NEIGH_ATTR_DST, dst)
235  __ADD(NEIGH_ATTR_CACHEINFO, cacheinfo)
236  __ADD(NEIGH_ATTR_IFINDEX, ifindex)
237  __ADD(NEIGH_ATTR_FAMILY, family)
238  __ADD(NEIGH_ATTR_TYPE, type)
239  __ADD(NEIGH_ATTR_PROBES, probes)
240 };
241 
242 static char *neigh_attrs2str(int attrs, char *buf, size_t len)
243 {
244  return __flags2str(attrs, buf, len, neigh_attrs,
245  ARRAY_SIZE(neigh_attrs));
246 }
247 
248 static struct nla_policy neigh_policy[NDA_MAX+1] = {
249  [NDA_CACHEINFO] = { .minlen = sizeof(struct nda_cacheinfo) },
250  [NDA_PROBES] = { .type = NLA_U32 },
251 };
252 
253 static int neigh_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
254  struct nlmsghdr *n, struct nl_parser_param *pp)
255 {
256  struct rtnl_neigh *neigh;
257  struct nlattr *tb[NDA_MAX + 1];
258  struct ndmsg *nm;
259  int err;
260 
261  neigh = rtnl_neigh_alloc();
262  if (!neigh) {
263  err = -NLE_NOMEM;
264  goto errout;
265  }
266 
267  neigh->ce_msgtype = n->nlmsg_type;
268  nm = nlmsg_data(n);
269 
270  err = nlmsg_parse(n, sizeof(*nm), tb, NDA_MAX, neigh_policy);
271  if (err < 0)
272  goto errout;
273 
274  neigh->n_family = nm->ndm_family;
275  neigh->n_ifindex = nm->ndm_ifindex;
276  neigh->n_state = nm->ndm_state;
277  neigh->n_flags = nm->ndm_flags;
278  neigh->n_type = nm->ndm_type;
279 
280  neigh->ce_mask |= (NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX |
281  NEIGH_ATTR_STATE | NEIGH_ATTR_FLAGS |
282  NEIGH_ATTR_TYPE);
283 
284  if (tb[NDA_LLADDR]) {
285  neigh->n_lladdr = nl_addr_alloc_attr(tb[NDA_LLADDR], AF_UNSPEC);
286  if (!neigh->n_lladdr) {
287  err = -NLE_NOMEM;
288  goto errout;
289  }
290  nl_addr_set_family(neigh->n_lladdr,
291  nl_addr_guess_family(neigh->n_lladdr));
292  neigh->ce_mask |= NEIGH_ATTR_LLADDR;
293  }
294 
295  if (tb[NDA_DST]) {
296  neigh->n_dst = nl_addr_alloc_attr(tb[NDA_DST], neigh->n_family);
297  if (!neigh->n_dst) {
298  err = -NLE_NOMEM;
299  goto errout;
300  }
301  neigh->ce_mask |= NEIGH_ATTR_DST;
302  }
303 
304  if (tb[NDA_CACHEINFO]) {
305  struct nda_cacheinfo *ci = nla_data(tb[NDA_CACHEINFO]);
306 
307  neigh->n_cacheinfo.nci_confirmed = ci->ndm_confirmed;
308  neigh->n_cacheinfo.nci_used = ci->ndm_used;
309  neigh->n_cacheinfo.nci_updated = ci->ndm_updated;
310  neigh->n_cacheinfo.nci_refcnt = ci->ndm_refcnt;
311 
312  neigh->ce_mask |= NEIGH_ATTR_CACHEINFO;
313  }
314 
315  if (tb[NDA_PROBES]) {
316  neigh->n_probes = nla_get_u32(tb[NDA_PROBES]);
317  neigh->ce_mask |= NEIGH_ATTR_PROBES;
318  }
319 
320  err = pp->pp_cb((struct nl_object *) neigh, pp);
321 errout:
322  rtnl_neigh_put(neigh);
323  return err;
324 }
325 
326 static int neigh_request_update(struct nl_cache *c, struct nl_sock *h)
327 {
328  return nl_rtgen_request(h, RTM_GETNEIGH, AF_UNSPEC, NLM_F_DUMP);
329 }
330 
331 
332 static void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p)
333 {
334  char dst[INET6_ADDRSTRLEN+5], lladdr[INET6_ADDRSTRLEN+5];
335  struct rtnl_neigh *n = (struct rtnl_neigh *) a;
336  struct nl_cache *link_cache;
337  char state[128], flags[64];
338 
339  link_cache = nl_cache_mngt_require("route/link");
340 
341  nl_dump_line(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst)));
342 
343  if (link_cache)
344  nl_dump(p, "dev %s ",
345  rtnl_link_i2name(link_cache, n->n_ifindex,
346  state, sizeof(state)));
347  else
348  nl_dump(p, "dev %d ", n->n_ifindex);
349 
350  if (n->ce_mask & NEIGH_ATTR_LLADDR)
351  nl_dump(p, "lladdr %s ",
352  nl_addr2str(n->n_lladdr, lladdr, sizeof(lladdr)));
353 
354  rtnl_neigh_state2str(n->n_state, state, sizeof(state));
355  rtnl_neigh_flags2str(n->n_flags, flags, sizeof(flags));
356 
357  if (state[0])
358  nl_dump(p, "<%s", state);
359  if (flags[0])
360  nl_dump(p, "%s%s", state[0] ? "," : "<", flags);
361  if (state[0] || flags[0])
362  nl_dump(p, ">");
363  nl_dump(p, "\n");
364 }
365 
366 static void neigh_dump_details(struct nl_object *a, struct nl_dump_params *p)
367 {
368  char rtn_type[32];
369  struct rtnl_neigh *n = (struct rtnl_neigh *) a;
370  int hz = nl_get_user_hz();
371 
372  neigh_dump_line(a, p);
373 
374  nl_dump_line(p, " refcnt %u type %s confirmed %u used "
375  "%u updated %u\n",
376  n->n_cacheinfo.nci_refcnt,
377  nl_rtntype2str(n->n_type, rtn_type, sizeof(rtn_type)),
378  n->n_cacheinfo.nci_confirmed/hz,
379  n->n_cacheinfo.nci_used/hz, n->n_cacheinfo.nci_updated/hz);
380 }
381 
382 static void neigh_dump_stats(struct nl_object *a, struct nl_dump_params *p)
383 {
384  neigh_dump_details(a, p);
385 }
386 
387 /**
388  * @name Neighbour Object Allocation/Freeage
389  * @{
390  */
391 
392 struct rtnl_neigh *rtnl_neigh_alloc(void)
393 {
394  return (struct rtnl_neigh *) nl_object_alloc(&neigh_obj_ops);
395 }
396 
397 void rtnl_neigh_put(struct rtnl_neigh *neigh)
398 {
399  nl_object_put((struct nl_object *) neigh);
400 }
401 
402 /** @} */
403 
404 /**
405  * @name Neighbour Cache Managament
406  * @{
407  */
408 
409 /**
410  * Build a neighbour cache including all neighbours currently configured in the kernel.
411  * @arg sock Netlink socket.
412  * @arg result Pointer to store resulting cache.
413  *
414  * Allocates a new neighbour cache, initializes it properly and updates it
415  * to include all neighbours currently configured in the kernel.
416  *
417  * @return 0 on success or a negative error code.
418  */
419 int rtnl_neigh_alloc_cache(struct nl_sock *sock, struct nl_cache **result)
420 {
421  return nl_cache_alloc_and_fill(&rtnl_neigh_ops, sock, result);
422 }
423 
424 /**
425  * Look up a neighbour by interface index and destination address
426  * @arg cache neighbour cache
427  * @arg ifindex interface index the neighbour is on
428  * @arg dst destination address of the neighbour
429  * @return neighbour handle or NULL if no match was found.
430  */
431 struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex,
432  struct nl_addr *dst)
433 {
434  struct rtnl_neigh *neigh;
435 
436  nl_list_for_each_entry(neigh, &cache->c_items, ce_list) {
437  if (neigh->n_ifindex == ifindex &&
438  !nl_addr_cmp(neigh->n_dst, dst)) {
439  nl_object_get((struct nl_object *) neigh);
440  return neigh;
441  }
442  }
443 
444  return NULL;
445 }
446 
447 /** @} */
448 
449 /**
450  * @name Neighbour Addition
451  * @{
452  */
453 
454 static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags,
455  struct nl_msg **result)
456 {
457  struct nl_msg *msg;
458  struct ndmsg nhdr = {
459  .ndm_ifindex = tmpl->n_ifindex,
460  .ndm_state = NUD_PERMANENT,
461  };
462 
463  if (!(tmpl->ce_mask & NEIGH_ATTR_DST))
464  return -NLE_MISSING_ATTR;
465 
466  nhdr.ndm_family = nl_addr_get_family(tmpl->n_dst);
467 
468  if (tmpl->ce_mask & NEIGH_ATTR_FLAGS)
469  nhdr.ndm_flags = tmpl->n_flags;
470 
471  if (tmpl->ce_mask & NEIGH_ATTR_STATE)
472  nhdr.ndm_state = tmpl->n_state;
473 
474  msg = nlmsg_alloc_simple(cmd, flags);
475  if (!msg)
476  return -NLE_NOMEM;
477 
478  if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0)
479  goto nla_put_failure;
480 
481  NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst);
482 
483  if (tmpl->ce_mask & NEIGH_ATTR_LLADDR)
484  NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr);
485 
486  *result = msg;
487  return 0;
488 
489 nla_put_failure:
490  nlmsg_free(msg);
491  return -NLE_MSGSIZE;
492 }
493 
494 /**
495  * Build netlink request message to add a new neighbour
496  * @arg tmpl template with data of new neighbour
497  * @arg flags additional netlink message flags
498  * @arg result Pointer to store resulting message.
499  *
500  * Builds a new netlink message requesting a addition of a new
501  * neighbour. The netlink message header isn't fully equipped with
502  * all relevant fields and must thus be sent out via nl_send_auto_complete()
503  * or supplemented as needed. \a tmpl must contain the attributes of the new
504  * neighbour set via \c rtnl_neigh_set_* functions.
505  *
506  * The following attributes must be set in the template:
507  * - Interface index (rtnl_neigh_set_ifindex())
508  * - State (rtnl_neigh_set_state())
509  * - Destination address (rtnl_neigh_set_dst())
510  * - Link layer address (rtnl_neigh_set_lladdr())
511  *
512  * @return 0 on success or a negative error code.
513  */
514 int rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags,
515  struct nl_msg **result)
516 {
517  return build_neigh_msg(tmpl, RTM_NEWNEIGH, flags, result);
518 }
519 
520 /**
521  * Add a new neighbour
522  * @arg sk Netlink socket.
523  * @arg tmpl template with requested changes
524  * @arg flags additional netlink message flags
525  *
526  * Builds a netlink message by calling rtnl_neigh_build_add_request(),
527  * sends the request to the kernel and waits for the next ACK to be
528  * received and thus blocks until the request has been fullfilled.
529  *
530  * The following attributes must be set in the template:
531  * - Interface index (rtnl_neigh_set_ifindex())
532  * - State (rtnl_neigh_set_state())
533  * - Destination address (rtnl_neigh_set_dst())
534  * - Link layer address (rtnl_neigh_set_lladdr())
535  *
536  * @return 0 on sucess or a negative error if an error occured.
537  */
538 int rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags)
539 {
540  int err;
541  struct nl_msg *msg;
542 
543  if ((err = rtnl_neigh_build_add_request(tmpl, flags, &msg)) < 0)
544  return err;
545 
546  err = nl_send_auto_complete(sk, msg);
547  nlmsg_free(msg);
548  if (err < 0)
549  return err;
550 
551  return wait_for_ack(sk);
552 }
553 
554 /** @} */
555 
556 /**
557  * @name Neighbour Deletion
558  * @{
559  */
560 
561 /**
562  * Build a netlink request message to delete a neighbour
563  * @arg neigh neighbour to delete
564  * @arg flags additional netlink message flags
565  * @arg result Pointer to store resulting message.
566  *
567  * Builds a new netlink message requesting a deletion of a neighbour.
568  * The netlink message header isn't fully equipped with all relevant
569  * fields and must thus be sent out via nl_send_auto_complete()
570  * or supplemented as needed. \a neigh must point to an existing
571  * neighbour.
572  *
573  * @return 0 on success or a negative error code.
574  */
575 int rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, int flags,
576  struct nl_msg **result)
577 {
578  return build_neigh_msg(neigh, RTM_DELNEIGH, flags, result);
579 }
580 
581 /**
582  * Delete a neighbour
583  * @arg sk Netlink socket.
584  * @arg neigh neighbour to delete
585  * @arg flags additional netlink message flags
586  *
587  * Builds a netlink message by calling rtnl_neigh_build_delete_request(),
588  * sends the request to the kernel and waits for the next ACK to be
589  * received and thus blocks until the request has been fullfilled.
590  *
591  * @return 0 on sucess or a negative error if an error occured.
592  */
593 int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh,
594  int flags)
595 {
596  struct nl_msg *msg;
597  int err;
598 
599  if ((err = rtnl_neigh_build_delete_request(neigh, flags, &msg)) < 0)
600  return err;
601 
602  err = nl_send_auto_complete(sk, msg);
603  nlmsg_free(msg);
604  if (err < 0)
605  return err;
606 
607  return wait_for_ack(sk);
608 }
609 
610 /** @} */
611 
612 /**
613  * @name Neighbour States Translations
614  * @{
615  */
616 
617 static const struct trans_tbl neigh_states[] = {
618  __ADD(NUD_INCOMPLETE, incomplete)
619  __ADD(NUD_REACHABLE, reachable)
620  __ADD(NUD_STALE, stale)
621  __ADD(NUD_DELAY, delay)
622  __ADD(NUD_PROBE, probe)
623  __ADD(NUD_FAILED, failed)
624  __ADD(NUD_NOARP, norarp)
625  __ADD(NUD_PERMANENT, permanent)
626 };
627 
628 char * rtnl_neigh_state2str(int state, char *buf, size_t len)
629 {
630  return __flags2str(state, buf, len, neigh_states,
631  ARRAY_SIZE(neigh_states));
632 }
633 
634 int rtnl_neigh_str2state(const char *name)
635 {
636  return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states));
637 }
638 
639 /** @} */
640 
641 /**
642  * @name Neighbour Flags Translations
643  * @{
644  */
645 
646 static const struct trans_tbl neigh_flags[] = {
647  __ADD(NTF_USE, use)
648  __ADD(NTF_PROXY, proxy)
649  __ADD(NTF_ROUTER, router)
650 };
651 
652 char * rtnl_neigh_flags2str(int flags, char *buf, size_t len)
653 {
654  return __flags2str(flags, buf, len, neigh_flags,
655  ARRAY_SIZE(neigh_flags));
656 }
657 
658 int rtnl_neigh_str2flag(const char *name)
659 {
660  return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags));
661 }
662 
663 /** @} */
664 
665 /**
666  * @name Attributes
667  * @{
668  */
669 
670 void rtnl_neigh_set_state(struct rtnl_neigh *neigh, int state)
671 {
672  neigh->n_state_mask |= state;
673  neigh->n_state |= state;
674  neigh->ce_mask |= NEIGH_ATTR_STATE;
675 }
676 
677 int rtnl_neigh_get_state(struct rtnl_neigh *neigh)
678 {
679  if (neigh->ce_mask & NEIGH_ATTR_STATE)
680  return neigh->n_state;
681  else
682  return -1;
683 }
684 
685 void rtnl_neigh_unset_state(struct rtnl_neigh *neigh, int state)
686 {
687  neigh->n_state_mask |= state;
688  neigh->n_state &= ~state;
689  neigh->ce_mask |= NEIGH_ATTR_STATE;
690 }
691 
692 void rtnl_neigh_set_flags(struct rtnl_neigh *neigh, unsigned int flags)
693 {
694  neigh->n_flag_mask |= flags;
695  neigh->n_flags |= flags;
696  neigh->ce_mask |= NEIGH_ATTR_FLAGS;
697 }
698 
699 unsigned int rtnl_neigh_get_flags(struct rtnl_neigh *neigh)
700 {
701  return neigh->n_flags;
702 }
703 
704 void rtnl_neigh_unset_flags(struct rtnl_neigh *neigh, unsigned int flags)
705 {
706  neigh->n_flag_mask |= flags;
707  neigh->n_flags &= ~flags;
708  neigh->ce_mask |= NEIGH_ATTR_FLAGS;
709 }
710 
711 void rtnl_neigh_set_ifindex(struct rtnl_neigh *neigh, int ifindex)
712 {
713  neigh->n_ifindex = ifindex;
714  neigh->ce_mask |= NEIGH_ATTR_IFINDEX;
715 }
716 
717 int rtnl_neigh_get_ifindex(struct rtnl_neigh *neigh)
718 {
719  return neigh->n_ifindex;
720 }
721 
722 static inline int __assign_addr(struct rtnl_neigh *neigh, struct nl_addr **pos,
723  struct nl_addr *new, int flag, int nocheck)
724 {
725  if (!nocheck) {
726  if (neigh->ce_mask & NEIGH_ATTR_FAMILY) {
727  if (new->a_family != neigh->n_family)
728  return -NLE_AF_MISMATCH;
729  } else {
730  neigh->n_family = new->a_family;
731  neigh->ce_mask |= NEIGH_ATTR_FAMILY;
732  }
733  }
734 
735  if (*pos)
736  nl_addr_put(*pos);
737 
738  nl_addr_get(new);
739  *pos = new;
740 
741  neigh->ce_mask |= flag;
742 
743  return 0;
744 }
745 
746 void rtnl_neigh_set_lladdr(struct rtnl_neigh *neigh, struct nl_addr *addr)
747 {
748  __assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1);
749 }
750 
751 struct nl_addr *rtnl_neigh_get_lladdr(struct rtnl_neigh *neigh)
752 {
753  if (neigh->ce_mask & NEIGH_ATTR_LLADDR)
754  return neigh->n_lladdr;
755  else
756  return NULL;
757 }
758 
759 int rtnl_neigh_set_dst(struct rtnl_neigh *neigh, struct nl_addr *addr)
760 {
761  return __assign_addr(neigh, &neigh->n_dst, addr,
762  NEIGH_ATTR_DST, 0);
763 }
764 
765 struct nl_addr *rtnl_neigh_get_dst(struct rtnl_neigh *neigh)
766 {
767  if (neigh->ce_mask & NEIGH_ATTR_DST)
768  return neigh->n_dst;
769  else
770  return NULL;
771 }
772 
773 void rtnl_neigh_set_family(struct rtnl_neigh *neigh, int family)
774 {
775  neigh->n_family = family;
776  neigh->ce_mask |= NEIGH_ATTR_FAMILY;
777 }
778 
779 int rtnl_neigh_get_family(struct rtnl_neigh *neigh)
780 {
781  return neigh->n_family;
782 }
783 
784 void rtnl_neigh_set_type(struct rtnl_neigh *neigh, int type)
785 {
786  neigh->n_type = type;
787  neigh->ce_mask = NEIGH_ATTR_TYPE;
788 }
789 
790 int rtnl_neigh_get_type(struct rtnl_neigh *neigh)
791 {
792  if (neigh->ce_mask & NEIGH_ATTR_TYPE)
793  return neigh->n_type;
794  else
795  return -1;
796 }
797 
798 /** @} */
799 
800 static struct nl_object_ops neigh_obj_ops = {
801  .oo_name = "route/neigh",
802  .oo_size = sizeof(struct rtnl_neigh),
803  .oo_free_data = neigh_free_data,
804  .oo_clone = neigh_clone,
805  .oo_dump = {
806  [NL_DUMP_LINE] = neigh_dump_line,
807  [NL_DUMP_DETAILS] = neigh_dump_details,
808  [NL_DUMP_STATS] = neigh_dump_stats,
809  },
810  .oo_compare = neigh_compare,
811  .oo_attrs2str = neigh_attrs2str,
812  .oo_id_attrs = (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY),
813 };
814 
815 static struct nl_af_group neigh_groups[] = {
816  { AF_UNSPEC, RTNLGRP_NEIGH },
817  { END_OF_GROUP_LIST },
818 };
819 
820 static struct nl_cache_ops rtnl_neigh_ops = {
821  .co_name = "route/neigh",
822  .co_hdrsize = sizeof(struct ndmsg),
823  .co_msgtypes = {
824  { RTM_NEWNEIGH, NL_ACT_NEW, "new" },
825  { RTM_DELNEIGH, NL_ACT_DEL, "del" },
826  { RTM_GETNEIGH, NL_ACT_GET, "get" },
827  END_OF_MSGTYPES_LIST,
828  },
829  .co_protocol = NETLINK_ROUTE,
830  .co_groups = neigh_groups,
831  .co_request_update = neigh_request_update,
832  .co_msg_parser = neigh_msg_parser,
833  .co_obj_ops = &neigh_obj_ops,
834 };
835 
836 static void __init neigh_init(void)
837 {
838  nl_cache_mngt_register(&rtnl_neigh_ops);
839 }
840 
841 static void __exit neigh_exit(void)
842 {
843  nl_cache_mngt_unregister(&rtnl_neigh_ops);
844 }
845 
846 /** @} */