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>
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
172 static struct nl_cache_ops rtnl_neigh_ops;
173 static struct nl_object_ops neigh_obj_ops;
176 static void neigh_free_data(
struct nl_object *c)
178 struct rtnl_neigh *neigh = nl_object_priv(c);
183 nl_addr_put(neigh->n_lladdr);
184 nl_addr_put(neigh->n_dst);
187 static int neigh_clone(
struct nl_object *_dst,
struct nl_object *_src)
189 struct rtnl_neigh *dst = nl_object_priv(_dst);
190 struct rtnl_neigh *src = nl_object_priv(_src);
203 static void neigh_keygen(
struct nl_object *obj, uint32_t *hashkey,
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 {
213 } __attribute__((packed)) *nkey;
214 char buf[INET6_ADDRSTRLEN+5];
216 if (neigh->n_family == AF_BRIDGE) {
218 addr = neigh->n_lladdr;
219 }
else if (neigh->n_dst) {
223 nkey_sz =
sizeof(*nkey);
227 nkey = calloc(1, nkey_sz);
232 nkey->n_family = neigh->n_family;
233 if (neigh->n_family == AF_BRIDGE)
234 nkey->n_ifindex = neigh->n_master;
236 nkey->n_ifindex = neigh->n_ifindex;
242 *hashkey = nl_hash(nkey, nkey_sz, 0) % table_sz;
244 NL_DBG(5,
"neigh %p key (fam %d dev %d addr %s) keysz %d hash 0x%x\n",
245 neigh, nkey->n_family, nkey->n_ifindex,
254 static int neigh_compare(
struct nl_object *_a,
struct nl_object *_b,
255 uint32_t attrs,
int flags)
257 struct rtnl_neigh *a = (
struct rtnl_neigh *) _a;
258 struct rtnl_neigh *b = (
struct rtnl_neigh *) _b;
261 #define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR)
263 diff |= NEIGH_DIFF(IFINDEX, a->n_ifindex != b->n_ifindex);
264 diff |= NEIGH_DIFF(FAMILY, a->n_family != b->n_family);
265 diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type);
266 diff |= NEIGH_DIFF(LLADDR,
nl_addr_cmp(a->n_lladdr, b->n_lladdr));
267 diff |= NEIGH_DIFF(DST,
nl_addr_cmp(a->n_dst, b->n_dst));
268 diff |= NEIGH_DIFF(MASTER, a->n_master != b->n_master);
270 if (flags & LOOSE_COMPARISON) {
271 diff |= NEIGH_DIFF(STATE,
272 (a->n_state ^ b->n_state) & b->n_state_mask);
273 diff |= NEIGH_DIFF(FLAGS,
274 (a->n_flags ^ b->n_flags) & b->n_flag_mask);
276 diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state);
277 diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags);
285 static const struct trans_tbl neigh_attrs[] = {
286 __ADD(NEIGH_ATTR_FLAGS, flags)
287 __ADD(NEIGH_ATTR_STATE, state)
288 __ADD(NEIGH_ATTR_LLADDR, lladdr)
289 __ADD(NEIGH_ATTR_DST, dst)
290 __ADD(NEIGH_ATTR_CACHEINFO, cacheinfo)
291 __ADD(NEIGH_ATTR_IFINDEX, ifindex)
292 __ADD(NEIGH_ATTR_FAMILY, family)
293 __ADD(NEIGH_ATTR_TYPE, type)
294 __ADD(NEIGH_ATTR_PROBES, probes)
297 static
char *neigh_attrs2str(
int attrs,
char *buf,
size_t len)
299 return __flags2str(attrs, buf, len, neigh_attrs,
300 ARRAY_SIZE(neigh_attrs));
303 static uint32_t neigh_id_attrs_get(
struct nl_object *obj)
305 struct rtnl_neigh *neigh = (
struct rtnl_neigh *)obj;
307 if (neigh->n_family == AF_BRIDGE)
308 return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_MASTER);
310 return (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY);
313 static struct nla_policy neigh_policy[NDA_MAX+1] = {
314 [NDA_CACHEINFO] = { .
minlen =
sizeof(
struct nda_cacheinfo) },
315 [NDA_PROBES] = { .type =
NLA_U32 },
318 static int neigh_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
319 struct nlmsghdr *n,
struct nl_parser_param *pp)
321 struct rtnl_neigh *neigh;
324 if ((err = rtnl_neigh_parse(n, &neigh)) < 0)
327 err = pp->pp_cb((
struct nl_object *) neigh, pp);
329 rtnl_neigh_put(neigh);
334 int rtnl_neigh_parse(
struct nlmsghdr *n,
struct rtnl_neigh **result)
336 struct rtnl_neigh *neigh;
337 struct nlattr *tb[NDA_MAX + 1];
341 neigh = rtnl_neigh_alloc();
347 neigh->ce_msgtype = n->nlmsg_type;
350 err =
nlmsg_parse(n,
sizeof(*nm), tb, NDA_MAX, neigh_policy);
354 neigh->n_family = nm->ndm_family;
355 neigh->n_ifindex = nm->ndm_ifindex;
356 neigh->n_state = nm->ndm_state;
357 neigh->n_flags = nm->ndm_flags;
358 neigh->n_type = nm->ndm_type;
360 neigh->ce_mask |= (NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX |
361 NEIGH_ATTR_STATE | NEIGH_ATTR_FLAGS |
364 if (tb[NDA_LLADDR]) {
366 if (!neigh->n_lladdr) {
370 nl_addr_set_family(neigh->n_lladdr,
372 neigh->ce_mask |= NEIGH_ATTR_LLADDR;
381 neigh->ce_mask |= NEIGH_ATTR_DST;
384 if (tb[NDA_CACHEINFO]) {
385 struct nda_cacheinfo *ci =
nla_data(tb[NDA_CACHEINFO]);
387 neigh->n_cacheinfo.nci_confirmed = ci->ndm_confirmed;
388 neigh->n_cacheinfo.nci_used = ci->ndm_used;
389 neigh->n_cacheinfo.nci_updated = ci->ndm_updated;
390 neigh->n_cacheinfo.nci_refcnt = ci->ndm_refcnt;
392 neigh->ce_mask |= NEIGH_ATTR_CACHEINFO;
395 if (tb[NDA_PROBES]) {
397 neigh->ce_mask |= NEIGH_ATTR_PROBES;
403 if (neigh->n_family == AF_BRIDGE) {
409 neigh->n_master = link->l_master;
411 neigh->ce_mask |= NEIGH_ATTR_MASTER;
414 nl_cache_put(lcache);
422 rtnl_neigh_put(neigh);
426 static int neigh_request_update(
struct nl_cache *c,
struct nl_sock *h)
428 int family = c->c_iarg1;
434 static void neigh_dump_line(
struct nl_object *a,
struct nl_dump_params *p)
436 char dst[INET6_ADDRSTRLEN+5], lladdr[INET6_ADDRSTRLEN+5];
437 struct rtnl_neigh *n = (
struct rtnl_neigh *) a;
438 struct nl_cache *link_cache;
439 char state[128], flags[64];
443 if (n->n_family != AF_BRIDGE)
444 nl_dump_line(p,
"%s ",
nl_addr2str(n->n_dst, dst,
sizeof(dst)));
449 state,
sizeof(state)));
451 nl_dump(p,
"dev %d ", n->n_ifindex);
453 if (n->ce_mask & NEIGH_ATTR_LLADDR)
457 rtnl_neigh_state2str(n->n_state, state,
sizeof(state));
458 rtnl_neigh_flags2str(n->n_flags, flags,
sizeof(flags));
463 nl_dump(p,
"%s%s", state[0] ?
"," :
"<", flags);
464 if (state[0] || flags[0])
469 nl_cache_put(link_cache);
472 static void neigh_dump_details(
struct nl_object *a,
struct nl_dump_params *p)
475 struct rtnl_neigh *n = (
struct rtnl_neigh *) a;
478 neigh_dump_line(a, p);
480 nl_dump_line(p,
" refcnt %u type %s confirmed %u used "
482 n->n_cacheinfo.nci_refcnt,
483 nl_rtntype2str(n->n_type, rtn_type,
sizeof(rtn_type)),
484 n->n_cacheinfo.nci_confirmed/hz,
485 n->n_cacheinfo.nci_used/hz, n->n_cacheinfo.nci_updated/hz);
488 static void neigh_dump_stats(
struct nl_object *a,
struct nl_dump_params *p)
490 neigh_dump_details(a, p);
498 struct rtnl_neigh *rtnl_neigh_alloc(
void)
503 void rtnl_neigh_put(
struct rtnl_neigh *neigh)
540 struct rtnl_neigh *neigh;
542 nl_list_for_each_entry(neigh, &cache->c_items, ce_list) {
543 if (neigh->n_family == AF_UNSPEC &&
544 neigh->n_ifindex == ifindex &&
561 static int build_neigh_msg(
struct rtnl_neigh *tmpl,
int cmd,
int flags,
562 struct nl_msg **result)
565 struct ndmsg nhdr = {
566 .ndm_ifindex = tmpl->n_ifindex,
567 .ndm_state = NUD_PERMANENT,
570 if (tmpl->n_family != AF_BRIDGE) {
571 if (!(tmpl->ce_mask & NEIGH_ATTR_DST))
572 return -NLE_MISSING_ATTR;
573 nhdr.ndm_family = nl_addr_get_family(tmpl->n_dst);
576 nhdr.ndm_family = AF_BRIDGE;
578 if (tmpl->ce_mask & NEIGH_ATTR_FLAGS)
579 nhdr.ndm_flags = tmpl->n_flags;
581 if (tmpl->ce_mask & NEIGH_ATTR_STATE)
582 nhdr.ndm_state = tmpl->n_state;
588 if (
nlmsg_append(msg, &nhdr,
sizeof(nhdr), NLMSG_ALIGNTO) < 0)
589 goto nla_put_failure;
591 if (tmpl->n_family != AF_BRIDGE)
594 if (tmpl->ce_mask & NEIGH_ATTR_LLADDR)
626 struct nl_msg **result)
628 return build_neigh_msg(tmpl, RTM_NEWNEIGH, flags, result);
662 return wait_for_ack(sk);
687 struct nl_msg **result)
689 return build_neigh_msg(neigh, RTM_DELNEIGH, flags, result);
718 return wait_for_ack(sk);
728 static const struct trans_tbl neigh_states[] = {
729 __ADD(NUD_INCOMPLETE, incomplete)
730 __ADD(NUD_REACHABLE, reachable)
731 __ADD(NUD_STALE, stale)
732 __ADD(NUD_DELAY, delay)
733 __ADD(NUD_PROBE, probe)
734 __ADD(NUD_FAILED, failed)
735 __ADD(NUD_NOARP, norarp)
736 __ADD(NUD_PERMANENT, permanent)
739 char * rtnl_neigh_state2str(
int state,
char *buf,
size_t len)
741 return __flags2str(state, buf, len, neigh_states,
742 ARRAY_SIZE(neigh_states));
745 int rtnl_neigh_str2state(
const char *name)
747 return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states));
757 static const struct trans_tbl neigh_flags[] = {
759 __ADD(NTF_PROXY, proxy)
760 __ADD(NTF_ROUTER, router)
763 char * rtnl_neigh_flags2str(
int flags,
char *buf,
size_t len)
765 return __flags2str(flags, buf, len, neigh_flags,
766 ARRAY_SIZE(neigh_flags));
769 int rtnl_neigh_str2flag(
const char *name)
771 return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags));
781 void rtnl_neigh_set_state(
struct rtnl_neigh *neigh,
int state)
783 neigh->n_state_mask |= state;
784 neigh->n_state |= state;
785 neigh->ce_mask |= NEIGH_ATTR_STATE;
788 int rtnl_neigh_get_state(
struct rtnl_neigh *neigh)
790 if (neigh->ce_mask & NEIGH_ATTR_STATE)
791 return neigh->n_state;
796 void rtnl_neigh_unset_state(
struct rtnl_neigh *neigh,
int state)
798 neigh->n_state_mask |= state;
799 neigh->n_state &= ~state;
800 neigh->ce_mask |= NEIGH_ATTR_STATE;
803 void rtnl_neigh_set_flags(
struct rtnl_neigh *neigh,
unsigned int flags)
805 neigh->n_flag_mask |= flags;
806 neigh->n_flags |= flags;
807 neigh->ce_mask |= NEIGH_ATTR_FLAGS;
810 unsigned int rtnl_neigh_get_flags(
struct rtnl_neigh *neigh)
812 return neigh->n_flags;
815 void rtnl_neigh_unset_flags(
struct rtnl_neigh *neigh,
unsigned int flags)
817 neigh->n_flag_mask |= flags;
818 neigh->n_flags &= ~flags;
819 neigh->ce_mask |= NEIGH_ATTR_FLAGS;
822 void rtnl_neigh_set_ifindex(
struct rtnl_neigh *neigh,
int ifindex)
824 neigh->n_ifindex = ifindex;
825 neigh->ce_mask |= NEIGH_ATTR_IFINDEX;
828 int rtnl_neigh_get_ifindex(
struct rtnl_neigh *neigh)
830 return neigh->n_ifindex;
833 static inline int __assign_addr(
struct rtnl_neigh *neigh,
struct nl_addr **pos,
834 struct nl_addr *
new,
int flag,
int nocheck)
837 if (neigh->ce_mask & NEIGH_ATTR_FAMILY) {
838 if (new->a_family != neigh->n_family)
839 return -NLE_AF_MISMATCH;
841 neigh->n_family =
new->a_family;
842 neigh->ce_mask |= NEIGH_ATTR_FAMILY;
852 neigh->ce_mask |= flag;
857 void rtnl_neigh_set_lladdr(
struct rtnl_neigh *neigh,
struct nl_addr *addr)
859 __assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1);
862 struct nl_addr *rtnl_neigh_get_lladdr(
struct rtnl_neigh *neigh)
864 if (neigh->ce_mask & NEIGH_ATTR_LLADDR)
865 return neigh->n_lladdr;
870 int rtnl_neigh_set_dst(
struct rtnl_neigh *neigh,
struct nl_addr *addr)
872 return __assign_addr(neigh, &neigh->n_dst, addr,
876 struct nl_addr *rtnl_neigh_get_dst(
struct rtnl_neigh *neigh)
878 if (neigh->ce_mask & NEIGH_ATTR_DST)
884 void rtnl_neigh_set_family(
struct rtnl_neigh *neigh,
int family)
886 neigh->n_family = family;
887 neigh->ce_mask |= NEIGH_ATTR_FAMILY;
890 int rtnl_neigh_get_family(
struct rtnl_neigh *neigh)
892 return neigh->n_family;
895 void rtnl_neigh_set_type(
struct rtnl_neigh *neigh,
int type)
897 neigh->n_type = type;
898 neigh->ce_mask = NEIGH_ATTR_TYPE;
901 int rtnl_neigh_get_type(
struct rtnl_neigh *neigh)
903 if (neigh->ce_mask & NEIGH_ATTR_TYPE)
904 return neigh->n_type;
911 static struct nl_object_ops neigh_obj_ops = {
912 .oo_name =
"route/neigh",
913 .oo_size =
sizeof(
struct rtnl_neigh),
914 .oo_free_data = neigh_free_data,
915 .oo_clone = neigh_clone,
921 .oo_compare = neigh_compare,
922 .oo_keygen = neigh_keygen,
923 .oo_attrs2str = neigh_attrs2str,
924 .oo_id_attrs = (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY),
925 .oo_id_attrs_get = neigh_id_attrs_get
928 static struct nl_af_group neigh_groups[] = {
929 { AF_UNSPEC, RTNLGRP_NEIGH },
930 { AF_BRIDGE, RTNLGRP_NEIGH },
931 { END_OF_GROUP_LIST },
934 static struct nl_cache_ops rtnl_neigh_ops = {
935 .co_name =
"route/neigh",
936 .co_hdrsize =
sizeof(
struct ndmsg),
938 { RTM_NEWNEIGH, NL_ACT_NEW,
"new" },
939 { RTM_DELNEIGH, NL_ACT_DEL,
"del" },
940 { RTM_GETNEIGH, NL_ACT_GET,
"get" },
941 END_OF_MSGTYPES_LIST,
943 .co_protocol = NETLINK_ROUTE,
944 .co_groups = neigh_groups,
945 .co_request_update = neigh_request_update,
946 .co_msg_parser = neigh_msg_parser,
947 .co_obj_ops = &neigh_obj_ops,
950 static void __init neigh_init(
void)
955 static void __exit neigh_exit(
void)