2
* lib/route/neigh.c Neighbours
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
9
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
14
* @defgroup neigh Neighbours
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.
21
* @par Neighbour States
33
* @par Neighbour Flags
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())
47
* @par Changeable Attributes
48
* \anchor neigh_changeable
49
* - state (rtnl_neigh_set_state())
50
* - link layer address (rtnl_neigh_set_lladdr())
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
58
* - Document proxy settings
59
* - Document states and their influence
61
* @par 1) Retrieving information about configured neighbours
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);
67
* // Neighbours can then be looked up by the interface and destination
69
* struct rtnl_neigh *neigh = rtnl_neigh_get(cache, ifindex, dst_addr);
71
* // After successful usage, the object must be given back to the cache
72
* rtnl_neigh_put(neigh);
75
* @par 2) Adding new neighbours
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();
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"));
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);
93
* rtnl_neigh_put(neigh);
96
* @par 3) Deleting an existing neighbour
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();
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);
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);
116
* rtnl_neigh_put(neigh);
119
* @par 4) Changing neighbour attributes
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();
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);
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);
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);
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);
146
* rtnl_neigh_put(neigh);
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>
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
169
static struct nl_cache_ops rtnl_neigh_ops;
170
static struct nl_object_ops neigh_obj_ops;
173
static void neigh_free_data(struct nl_object *c)
175
struct rtnl_neigh *neigh = nl_object_priv(c);
180
nl_addr_put(neigh->n_lladdr);
181
nl_addr_put(neigh->n_dst);
184
static int neigh_clone(struct nl_object *_dst, struct nl_object *_src)
186
struct rtnl_neigh *dst = nl_object_priv(_dst);
187
struct rtnl_neigh *src = nl_object_priv(_src);
190
if (!(dst->n_lladdr = nl_addr_clone(src->n_lladdr)))
194
if (!(dst->n_dst = nl_addr_clone(src->n_dst)))
200
static int neigh_compare(struct nl_object *_a, struct nl_object *_b,
201
uint32_t attrs, int flags)
203
struct rtnl_neigh *a = (struct rtnl_neigh *) _a;
204
struct rtnl_neigh *b = (struct rtnl_neigh *) _b;
207
#define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR)
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));
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);
221
diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state);
222
diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags);
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)
242
static char *neigh_attrs2str(int attrs, char *buf, size_t len)
244
return __flags2str(attrs, buf, len, neigh_attrs,
245
ARRAY_SIZE(neigh_attrs));
248
static struct nla_policy neigh_policy[NDA_MAX+1] = {
249
[NDA_CACHEINFO] = { .minlen = sizeof(struct nda_cacheinfo) },
250
[NDA_PROBES] = { .type = NLA_U32 },
253
static int neigh_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
254
struct nlmsghdr *n, struct nl_parser_param *pp)
256
struct rtnl_neigh *neigh;
257
struct nlattr *tb[NDA_MAX + 1];
261
neigh = rtnl_neigh_alloc();
267
neigh->ce_msgtype = n->nlmsg_type;
270
err = nlmsg_parse(n, sizeof(*nm), tb, NDA_MAX, neigh_policy);
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;
280
neigh->ce_mask |= (NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX |
281
NEIGH_ATTR_STATE | NEIGH_ATTR_FLAGS |
284
if (tb[NDA_LLADDR]) {
285
neigh->n_lladdr = nl_addr_alloc_attr(tb[NDA_LLADDR], AF_UNSPEC);
286
if (!neigh->n_lladdr) {
290
nl_addr_set_family(neigh->n_lladdr,
291
nl_addr_guess_family(neigh->n_lladdr));
292
neigh->ce_mask |= NEIGH_ATTR_LLADDR;
296
neigh->n_dst = nl_addr_alloc_attr(tb[NDA_DST], neigh->n_family);
301
neigh->ce_mask |= NEIGH_ATTR_DST;
304
if (tb[NDA_CACHEINFO]) {
305
struct nda_cacheinfo *ci = nla_data(tb[NDA_CACHEINFO]);
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;
312
neigh->ce_mask |= NEIGH_ATTR_CACHEINFO;
315
if (tb[NDA_PROBES]) {
316
neigh->n_probes = nla_get_u32(tb[NDA_PROBES]);
317
neigh->ce_mask |= NEIGH_ATTR_PROBES;
320
err = pp->pp_cb((struct nl_object *) neigh, pp);
322
rtnl_neigh_put(neigh);
326
static int neigh_request_update(struct nl_cache *c, struct nl_sock *h)
328
return nl_rtgen_request(h, RTM_GETNEIGH, AF_UNSPEC, NLM_F_DUMP);
332
static void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p)
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];
339
link_cache = nl_cache_mngt_require("route/link");
341
nl_dump_line(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst)));
344
nl_dump(p, "dev %s ",
345
rtnl_link_i2name(link_cache, n->n_ifindex,
346
state, sizeof(state)));
348
nl_dump(p, "dev %d ", n->n_ifindex);
350
if (n->ce_mask & NEIGH_ATTR_LLADDR)
351
nl_dump(p, "lladdr %s ",
352
nl_addr2str(n->n_lladdr, lladdr, sizeof(lladdr)));
354
rtnl_neigh_state2str(n->n_state, state, sizeof(state));
355
rtnl_neigh_flags2str(n->n_flags, flags, sizeof(flags));
358
nl_dump(p, "<%s", state);
360
nl_dump(p, "%s%s", state[0] ? "," : "<", flags);
361
if (state[0] || flags[0])
366
static void neigh_dump_details(struct nl_object *a, struct nl_dump_params *p)
369
struct rtnl_neigh *n = (struct rtnl_neigh *) a;
370
int hz = nl_get_user_hz();
372
neigh_dump_line(a, p);
374
nl_dump_line(p, " refcnt %u type %s confirmed %u used "
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);
382
static void neigh_dump_stats(struct nl_object *a, struct nl_dump_params *p)
384
neigh_dump_details(a, p);
388
* @name Neighbour Object Allocation/Freeage
392
struct rtnl_neigh *rtnl_neigh_alloc(void)
394
return (struct rtnl_neigh *) nl_object_alloc(&neigh_obj_ops);
397
void rtnl_neigh_put(struct rtnl_neigh *neigh)
399
nl_object_put((struct nl_object *) neigh);
405
* @name Neighbour Cache Managament
410
* Build a neighbour cache including all neighbours currently configured in the kernel.
411
* @arg sk Netlink socket.
412
* @arg result Pointer to store resulting cache.
414
* Allocates a new neighbour cache, initializes it properly and updates it
415
* to include all neighbours currently configured in the kernel.
417
* @return 0 on success or a negative error code.
419
int rtnl_neigh_alloc_cache(struct nl_sock *sock, struct nl_cache **result)
421
return nl_cache_alloc_and_fill(&rtnl_neigh_ops, sock, result);
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.
431
struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex,
434
struct rtnl_neigh *neigh;
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);
450
* @name Neighbour Addition
454
static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags,
455
struct nl_msg **result)
458
struct ndmsg nhdr = {
459
.ndm_ifindex = tmpl->n_ifindex,
460
.ndm_state = NUD_PERMANENT,
463
if (!(tmpl->ce_mask & NEIGH_ATTR_DST))
464
return -NLE_MISSING_ATTR;
466
nhdr.ndm_family = nl_addr_get_family(tmpl->n_dst);
468
if (tmpl->ce_mask & NEIGH_ATTR_STATE)
469
nhdr.ndm_state = tmpl->n_state;
471
msg = nlmsg_alloc_simple(cmd, flags);
475
if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0)
476
goto nla_put_failure;
478
NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst);
480
if (tmpl->ce_mask & NEIGH_ATTR_LLADDR)
481
NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr);
492
* Build netlink request message to add a new neighbour
493
* @arg tmpl template with data of new neighbour
494
* @arg flags additional netlink message flags
495
* @arg result Pointer to store resulting message.
497
* Builds a new netlink message requesting a addition of a new
498
* neighbour. The netlink message header isn't fully equipped with
499
* all relevant fields and must thus be sent out via nl_send_auto_complete()
500
* or supplemented as needed. \a tmpl must contain the attributes of the new
501
* neighbour set via \c rtnl_neigh_set_* functions.
503
* The following attributes must be set in the template:
504
* - Interface index (rtnl_neigh_set_ifindex())
505
* - State (rtnl_neigh_set_state())
506
* - Destination address (rtnl_neigh_set_dst())
507
* - Link layer address (rtnl_neigh_set_lladdr())
509
* @return 0 on success or a negative error code.
511
int rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags,
512
struct nl_msg **result)
514
return build_neigh_msg(tmpl, RTM_NEWNEIGH, flags, result);
518
* Add a new neighbour
519
* @arg sk Netlink socket.
520
* @arg tmpl template with requested changes
521
* @arg flags additional netlink message flags
523
* Builds a netlink message by calling rtnl_neigh_build_add_request(),
524
* sends the request to the kernel and waits for the next ACK to be
525
* received and thus blocks until the request has been fullfilled.
527
* The following attributes must be set in the template:
528
* - Interface index (rtnl_neigh_set_ifindex())
529
* - State (rtnl_neigh_set_state())
530
* - Destination address (rtnl_neigh_set_dst())
531
* - Link layer address (rtnl_neigh_set_lladdr())
533
* @return 0 on sucess or a negative error if an error occured.
535
int rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags)
540
if ((err = rtnl_neigh_build_add_request(tmpl, flags, &msg)) < 0)
543
err = nl_send_auto_complete(sk, msg);
548
return wait_for_ack(sk);
554
* @name Neighbour Deletion
559
* Build a netlink request message to delete a neighbour
560
* @arg neigh neighbour to delete
561
* @arg flags additional netlink message flags
562
* @arg result Pointer to store resulting message.
564
* Builds a new netlink message requesting a deletion of a neighbour.
565
* The netlink message header isn't fully equipped with all relevant
566
* fields and must thus be sent out via nl_send_auto_complete()
567
* or supplemented as needed. \a neigh must point to an existing
570
* @return 0 on success or a negative error code.
572
int rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, int flags,
573
struct nl_msg **result)
575
return build_neigh_msg(neigh, RTM_DELNEIGH, flags, result);
580
* @arg sk Netlink socket.
581
* @arg neigh neighbour to delete
582
* @arg flags additional netlink message flags
584
* Builds a netlink message by calling rtnl_neigh_build_delete_request(),
585
* sends the request to the kernel and waits for the next ACK to be
586
* received and thus blocks until the request has been fullfilled.
588
* @return 0 on sucess or a negative error if an error occured.
590
int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh,
596
if ((err = rtnl_neigh_build_delete_request(neigh, flags, &msg)) < 0)
599
err = nl_send_auto_complete(sk, msg);
604
return wait_for_ack(sk);
610
* @name Neighbour States Translations
614
static const struct trans_tbl neigh_states[] = {
615
__ADD(NUD_INCOMPLETE, incomplete)
616
__ADD(NUD_REACHABLE, reachable)
617
__ADD(NUD_STALE, stale)
618
__ADD(NUD_DELAY, delay)
619
__ADD(NUD_PROBE, probe)
620
__ADD(NUD_FAILED, failed)
621
__ADD(NUD_NOARP, norarp)
622
__ADD(NUD_PERMANENT, permanent)
625
char * rtnl_neigh_state2str(int state, char *buf, size_t len)
627
return __flags2str(state, buf, len, neigh_states,
628
ARRAY_SIZE(neigh_states));
631
int rtnl_neigh_str2state(const char *name)
633
return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states));
639
* @name Neighbour Flags Translations
643
static const struct trans_tbl neigh_flags[] = {
645
__ADD(NTF_PROXY, proxy)
646
__ADD(NTF_ROUTER, router)
649
char * rtnl_neigh_flags2str(int flags, char *buf, size_t len)
651
return __flags2str(flags, buf, len, neigh_flags,
652
ARRAY_SIZE(neigh_flags));
655
int rtnl_neigh_str2flag(const char *name)
657
return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags));
667
void rtnl_neigh_set_state(struct rtnl_neigh *neigh, int state)
669
neigh->n_state_mask |= state;
670
neigh->n_state |= state;
671
neigh->ce_mask |= NEIGH_ATTR_STATE;
674
int rtnl_neigh_get_state(struct rtnl_neigh *neigh)
676
if (neigh->ce_mask & NEIGH_ATTR_STATE)
677
return neigh->n_state;
682
void rtnl_neigh_unset_state(struct rtnl_neigh *neigh, int state)
684
neigh->n_state_mask |= state;
685
neigh->n_state &= ~state;
686
neigh->ce_mask |= NEIGH_ATTR_STATE;
689
void rtnl_neigh_set_flags(struct rtnl_neigh *neigh, unsigned int flags)
691
neigh->n_flag_mask |= flags;
692
neigh->n_flags |= flags;
693
neigh->ce_mask |= NEIGH_ATTR_FLAGS;
696
unsigned int rtnl_neigh_get_flags(struct rtnl_neigh *neigh)
698
return neigh->n_flags;
701
void rtnl_neigh_unset_flags(struct rtnl_neigh *neigh, unsigned int flags)
703
neigh->n_flag_mask |= flags;
704
neigh->n_flags &= ~flags;
705
neigh->ce_mask |= NEIGH_ATTR_FLAGS;
708
void rtnl_neigh_set_ifindex(struct rtnl_neigh *neigh, int ifindex)
710
neigh->n_ifindex = ifindex;
711
neigh->ce_mask |= NEIGH_ATTR_IFINDEX;
714
int rtnl_neigh_get_ifindex(struct rtnl_neigh *neigh)
716
return neigh->n_ifindex;
719
static inline int __assign_addr(struct rtnl_neigh *neigh, struct nl_addr **pos,
720
struct nl_addr *new, int flag, int nocheck)
723
if (neigh->ce_mask & NEIGH_ATTR_FAMILY) {
724
if (new->a_family != neigh->n_family)
725
return -NLE_AF_MISMATCH;
727
neigh->n_family = new->a_family;
728
neigh->ce_mask |= NEIGH_ATTR_FAMILY;
738
neigh->ce_mask |= flag;
743
void rtnl_neigh_set_lladdr(struct rtnl_neigh *neigh, struct nl_addr *addr)
745
__assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1);
748
struct nl_addr *rtnl_neigh_get_lladdr(struct rtnl_neigh *neigh)
750
if (neigh->ce_mask & NEIGH_ATTR_LLADDR)
751
return neigh->n_lladdr;
756
int rtnl_neigh_set_dst(struct rtnl_neigh *neigh, struct nl_addr *addr)
758
return __assign_addr(neigh, &neigh->n_dst, addr,
762
struct nl_addr *rtnl_neigh_get_dst(struct rtnl_neigh *neigh)
764
if (neigh->ce_mask & NEIGH_ATTR_DST)
770
void rtnl_neigh_set_family(struct rtnl_neigh *neigh, int family)
772
neigh->n_family = family;
773
neigh->ce_mask |= NEIGH_ATTR_FAMILY;
776
int rtnl_neigh_get_family(struct rtnl_neigh *neigh)
778
return neigh->n_family;
781
void rtnl_neigh_set_type(struct rtnl_neigh *neigh, int type)
783
neigh->n_type = type;
784
neigh->ce_mask = NEIGH_ATTR_TYPE;
787
int rtnl_neigh_get_type(struct rtnl_neigh *neigh)
789
if (neigh->ce_mask & NEIGH_ATTR_TYPE)
790
return neigh->n_type;
797
static struct nl_object_ops neigh_obj_ops = {
798
.oo_name = "route/neigh",
799
.oo_size = sizeof(struct rtnl_neigh),
800
.oo_free_data = neigh_free_data,
801
.oo_clone = neigh_clone,
803
[NL_DUMP_LINE] = neigh_dump_line,
804
[NL_DUMP_DETAILS] = neigh_dump_details,
805
[NL_DUMP_STATS] = neigh_dump_stats,
807
.oo_compare = neigh_compare,
808
.oo_attrs2str = neigh_attrs2str,
809
.oo_id_attrs = (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY),
812
static struct nl_af_group neigh_groups[] = {
813
{ AF_UNSPEC, RTNLGRP_NEIGH },
814
{ END_OF_GROUP_LIST },
817
static struct nl_cache_ops rtnl_neigh_ops = {
818
.co_name = "route/neigh",
819
.co_hdrsize = sizeof(struct ndmsg),
821
{ RTM_NEWNEIGH, NL_ACT_NEW, "new" },
822
{ RTM_DELNEIGH, NL_ACT_DEL, "del" },
823
{ RTM_GETNEIGH, NL_ACT_GET, "get" },
824
END_OF_MSGTYPES_LIST,
826
.co_protocol = NETLINK_ROUTE,
827
.co_groups = neigh_groups,
828
.co_request_update = neigh_request_update,
829
.co_msg_parser = neigh_msg_parser,
830
.co_obj_ops = &neigh_obj_ops,
833
static void __init neigh_init(void)
835
nl_cache_mngt_register(&rtnl_neigh_ops);
838
static void __exit neigh_exit(void)
840
nl_cache_mngt_unregister(&rtnl_neigh_ops);