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