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