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