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