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
171 #define NEIGH_ATTR_VLAN 0x400
173 static struct nl_cache_ops rtnl_neigh_ops;
174 static struct nl_object_ops neigh_obj_ops;
177 static void neigh_free_data(
struct nl_object *c)
179 struct rtnl_neigh *neigh = nl_object_priv(c);
188 static int neigh_clone(
struct nl_object *_dst,
struct nl_object *_src)
190 struct rtnl_neigh *dst = nl_object_priv(_dst);
191 struct rtnl_neigh *src = nl_object_priv(_src);
204 static void neigh_keygen(
struct nl_object *obj, uint32_t *hashkey,
207 struct rtnl_neigh *neigh = (
struct rtnl_neigh *) obj;
208 unsigned int nkey_sz;
209 struct nl_addr *addr = NULL;
210 struct neigh_hash_key {
214 } __attribute__((packed)) *nkey;
216 char buf[INET6_ADDRSTRLEN+5];
219 if (neigh->n_family == AF_BRIDGE) {
221 addr = neigh->n_lladdr;
222 }
else if (neigh->n_dst) {
226 nkey_sz =
sizeof(*nkey);
230 nkey = calloc(1, nkey_sz);
235 nkey->n_family = neigh->n_family;
236 if (neigh->n_family == AF_BRIDGE)
237 nkey->n_ifindex = neigh->n_master;
239 nkey->n_ifindex = neigh->n_ifindex;
245 *hashkey = nl_hash(nkey, nkey_sz, 0) % table_sz;
247 NL_DBG(5,
"neigh %p key (fam %d dev %d addr %s) keysz %d hash 0x%x\n",
248 neigh, nkey->n_family, nkey->n_ifindex,
257 static int neigh_compare(
struct nl_object *_a,
struct nl_object *_b,
258 uint32_t attrs,
int flags)
260 struct rtnl_neigh *a = (
struct rtnl_neigh *) _a;
261 struct rtnl_neigh *b = (
struct rtnl_neigh *) _b;
264 #define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR)
266 diff |= NEIGH_DIFF(IFINDEX, a->n_ifindex != b->n_ifindex);
267 diff |= NEIGH_DIFF(FAMILY, a->n_family != b->n_family);
268 diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type);
269 diff |= NEIGH_DIFF(LLADDR,
nl_addr_cmp(a->n_lladdr, b->n_lladdr));
270 diff |= NEIGH_DIFF(DST,
nl_addr_cmp(a->n_dst, b->n_dst));
271 diff |= NEIGH_DIFF(MASTER, a->n_master != b->n_master);
272 diff |= NEIGH_DIFF(VLAN, a->n_vlan != b->n_vlan);
274 if (flags & LOOSE_COMPARISON) {
275 diff |= NEIGH_DIFF(STATE,
276 (a->n_state ^ b->n_state) & b->n_state_mask);
277 diff |= NEIGH_DIFF(FLAGS,
278 (a->n_flags ^ b->n_flags) & b->n_flag_mask);
280 diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state);
281 diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags);
289 static const struct trans_tbl neigh_attrs[] = {
290 __ADD(NEIGH_ATTR_FLAGS, flags),
291 __ADD(NEIGH_ATTR_STATE, state),
292 __ADD(NEIGH_ATTR_LLADDR, lladdr),
293 __ADD(NEIGH_ATTR_DST, dst),
294 __ADD(NEIGH_ATTR_CACHEINFO, cacheinfo),
295 __ADD(NEIGH_ATTR_IFINDEX, ifindex),
296 __ADD(NEIGH_ATTR_FAMILY, family),
297 __ADD(NEIGH_ATTR_TYPE, type),
298 __ADD(NEIGH_ATTR_PROBES, probes),
299 __ADD(NEIGH_ATTR_MASTER, master),
300 __ADD(NEIGH_ATTR_VLAN, vlan),
303 static char *neigh_attrs2str(
int attrs,
char *buf,
size_t len)
305 return __flags2str(attrs, buf, len, neigh_attrs,
306 ARRAY_SIZE(neigh_attrs));
309 static uint32_t neigh_id_attrs_get(
struct nl_object *obj)
311 struct rtnl_neigh *neigh = (
struct rtnl_neigh *)obj;
313 if (neigh->n_family == AF_BRIDGE)
314 return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_MASTER);
316 return (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY);
319 static struct nla_policy neigh_policy[NDA_MAX+1] = {
320 [NDA_CACHEINFO] = { .
minlen =
sizeof(
struct nda_cacheinfo) },
321 [NDA_PROBES] = { .type =
NLA_U32 },
324 static int neigh_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
325 struct nlmsghdr *n,
struct nl_parser_param *pp)
327 struct rtnl_neigh *neigh;
330 if ((err = rtnl_neigh_parse(n, &neigh)) < 0)
333 err = pp->pp_cb((
struct nl_object *) neigh, pp);
335 rtnl_neigh_put(neigh);
340 int rtnl_neigh_parse(
struct nlmsghdr *n,
struct rtnl_neigh **result)
342 struct rtnl_neigh *neigh;
343 struct nlattr *tb[NDA_MAX + 1];
347 neigh = rtnl_neigh_alloc();
353 neigh->ce_msgtype = n->nlmsg_type;
356 err =
nlmsg_parse(n,
sizeof(*nm), tb, NDA_MAX, neigh_policy);
360 neigh->n_family = nm->ndm_family;
361 neigh->n_ifindex = nm->ndm_ifindex;
362 neigh->n_state = nm->ndm_state;
363 neigh->n_flags = nm->ndm_flags;
364 neigh->n_type = nm->ndm_type;
366 neigh->ce_mask |= (NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX |
367 NEIGH_ATTR_STATE | NEIGH_ATTR_FLAGS |
370 if (tb[NDA_LLADDR]) {
372 if (!neigh->n_lladdr) {
378 neigh->ce_mask |= NEIGH_ATTR_LLADDR;
387 neigh->ce_mask |= NEIGH_ATTR_DST;
390 if (tb[NDA_CACHEINFO]) {
391 struct nda_cacheinfo *ci =
nla_data(tb[NDA_CACHEINFO]);
393 neigh->n_cacheinfo.nci_confirmed = ci->ndm_confirmed;
394 neigh->n_cacheinfo.nci_used = ci->ndm_used;
395 neigh->n_cacheinfo.nci_updated = ci->ndm_updated;
396 neigh->n_cacheinfo.nci_refcnt = ci->ndm_refcnt;
398 neigh->ce_mask |= NEIGH_ATTR_CACHEINFO;
401 if (tb[NDA_PROBES]) {
403 neigh->ce_mask |= NEIGH_ATTR_PROBES;
408 neigh->ce_mask |= NEIGH_ATTR_VLAN;
414 if (neigh->n_family == AF_BRIDGE) {
420 neigh->n_master = link->l_master;
422 neigh->ce_mask |= NEIGH_ATTR_MASTER;
425 nl_cache_put(lcache);
433 rtnl_neigh_put(neigh);
437 static int neigh_request_update(
struct nl_cache *c,
struct nl_sock *h)
439 int family = c->c_iarg1;
445 static void neigh_dump_line(
struct nl_object *a,
struct nl_dump_params *p)
447 char dst[INET6_ADDRSTRLEN+5], lladdr[INET6_ADDRSTRLEN+5];
448 struct rtnl_neigh *n = (
struct rtnl_neigh *) a;
449 struct nl_cache *link_cache;
450 char state[128], flags[64];
454 if (n->n_family != AF_BRIDGE)
455 nl_dump_line(p,
"%s ",
nl_addr2str(n->n_dst, dst,
sizeof(dst)));
460 state,
sizeof(state)));
462 nl_dump(p,
"dev %d ", n->n_ifindex);
464 if (n->ce_mask & NEIGH_ATTR_LLADDR)
468 rtnl_neigh_state2str(n->n_state, state,
sizeof(state));
469 rtnl_neigh_flags2str(n->n_flags, flags,
sizeof(flags));
474 nl_dump(p,
"%s%s", state[0] ?
"," :
"<", flags);
475 if (state[0] || flags[0])
480 nl_cache_put(link_cache);
483 static void neigh_dump_details(
struct nl_object *a,
struct nl_dump_params *p)
486 struct rtnl_neigh *n = (
struct rtnl_neigh *) a;
489 neigh_dump_line(a, p);
491 nl_dump_line(p,
" refcnt %u type %s confirmed %u used "
493 n->n_cacheinfo.nci_refcnt,
494 nl_rtntype2str(n->n_type, rtn_type,
sizeof(rtn_type)),
495 n->n_cacheinfo.nci_confirmed/hz,
496 n->n_cacheinfo.nci_used/hz, n->n_cacheinfo.nci_updated/hz);
499 static void neigh_dump_stats(
struct nl_object *a,
struct nl_dump_params *p)
501 neigh_dump_details(a, p);
509 struct rtnl_neigh *rtnl_neigh_alloc(
void)
514 void rtnl_neigh_put(
struct rtnl_neigh *neigh)
552 struct rtnl_neigh *neigh;
554 nl_list_for_each_entry(neigh, &cache->c_items, ce_list) {
555 if (neigh->n_ifindex == ifindex &&
572 static int build_neigh_msg(
struct rtnl_neigh *tmpl,
int cmd,
int flags,
573 struct nl_msg **result)
576 struct ndmsg nhdr = {
577 .ndm_ifindex = tmpl->n_ifindex,
578 .ndm_state = NUD_PERMANENT,
581 if (tmpl->n_family != AF_BRIDGE) {
582 if (!(tmpl->ce_mask & NEIGH_ATTR_DST))
583 return -NLE_MISSING_ATTR;
587 nhdr.ndm_family = AF_BRIDGE;
589 if (tmpl->ce_mask & NEIGH_ATTR_FLAGS)
590 nhdr.ndm_flags = tmpl->n_flags;
592 if (tmpl->ce_mask & NEIGH_ATTR_STATE)
593 nhdr.ndm_state = tmpl->n_state;
599 if (
nlmsg_append(msg, &nhdr,
sizeof(nhdr), NLMSG_ALIGNTO) < 0)
600 goto nla_put_failure;
602 if (tmpl->n_family != AF_BRIDGE)
605 if (tmpl->ce_mask & NEIGH_ATTR_LLADDR)
608 if (tmpl->ce_mask & NEIGH_ATTR_VLAN)
640 struct nl_msg **result)
642 return build_neigh_msg(tmpl, RTM_NEWNEIGH, flags, result);
676 return wait_for_ack(sk);
701 struct nl_msg **result)
703 return build_neigh_msg(neigh, RTM_DELNEIGH, flags, result);
732 return wait_for_ack(sk);
742 static const struct trans_tbl neigh_states[] = {
743 __ADD(NUD_INCOMPLETE, incomplete),
744 __ADD(NUD_REACHABLE, reachable),
745 __ADD(NUD_STALE, stale),
746 __ADD(NUD_DELAY, delay),
747 __ADD(NUD_PROBE, probe),
748 __ADD(NUD_FAILED, failed),
749 __ADD(NUD_NOARP, noarp),
750 __ADD(NUD_PERMANENT, permanent),
755 __ADD(NUD_NOARP, norarp),
758 char * rtnl_neigh_state2str(
int state,
char *buf,
size_t len)
760 return __flags2str(state, buf, len, neigh_states,
761 ARRAY_SIZE(neigh_states) - 1);
764 int rtnl_neigh_str2state(
const char *name)
766 return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states));
776 static const struct trans_tbl neigh_flags[] = {
778 __ADD(NTF_PROXY, proxy),
779 __ADD(NTF_ROUTER, router),
782 char * rtnl_neigh_flags2str(
int flags,
char *buf,
size_t len)
784 return __flags2str(flags, buf, len, neigh_flags,
785 ARRAY_SIZE(neigh_flags));
788 int rtnl_neigh_str2flag(
const char *name)
790 return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags));
800 void rtnl_neigh_set_state(
struct rtnl_neigh *neigh,
int state)
802 neigh->n_state_mask |= state;
803 neigh->n_state |= state;
804 neigh->ce_mask |= NEIGH_ATTR_STATE;
807 int rtnl_neigh_get_state(
struct rtnl_neigh *neigh)
809 if (neigh->ce_mask & NEIGH_ATTR_STATE)
810 return neigh->n_state;
815 void rtnl_neigh_unset_state(
struct rtnl_neigh *neigh,
int state)
817 neigh->n_state_mask |= state;
818 neigh->n_state &= ~state;
819 neigh->ce_mask |= NEIGH_ATTR_STATE;
822 void rtnl_neigh_set_flags(
struct rtnl_neigh *neigh,
unsigned int flags)
824 neigh->n_flag_mask |= flags;
825 neigh->n_flags |= flags;
826 neigh->ce_mask |= NEIGH_ATTR_FLAGS;
829 unsigned int rtnl_neigh_get_flags(
struct rtnl_neigh *neigh)
831 return neigh->n_flags;
834 void rtnl_neigh_unset_flags(
struct rtnl_neigh *neigh,
unsigned int flags)
836 neigh->n_flag_mask |= flags;
837 neigh->n_flags &= ~flags;
838 neigh->ce_mask |= NEIGH_ATTR_FLAGS;
841 void rtnl_neigh_set_ifindex(
struct rtnl_neigh *neigh,
int ifindex)
843 neigh->n_ifindex = ifindex;
844 neigh->ce_mask |= NEIGH_ATTR_IFINDEX;
847 int rtnl_neigh_get_ifindex(
struct rtnl_neigh *neigh)
849 return neigh->n_ifindex;
852 static inline int __assign_addr(
struct rtnl_neigh *neigh,
struct nl_addr **pos,
853 struct nl_addr *
new,
int flag,
int nocheck)
856 if (neigh->ce_mask & NEIGH_ATTR_FAMILY) {
857 if (new->a_family != neigh->n_family)
858 return -NLE_AF_MISMATCH;
860 neigh->n_family =
new->a_family;
861 neigh->ce_mask |= NEIGH_ATTR_FAMILY;
871 neigh->ce_mask |= flag;
876 void rtnl_neigh_set_lladdr(
struct rtnl_neigh *neigh,
struct nl_addr *addr)
878 __assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1);
881 struct nl_addr *rtnl_neigh_get_lladdr(
struct rtnl_neigh *neigh)
883 if (neigh->ce_mask & NEIGH_ATTR_LLADDR)
884 return neigh->n_lladdr;
889 int rtnl_neigh_set_dst(
struct rtnl_neigh *neigh,
struct nl_addr *addr)
891 return __assign_addr(neigh, &neigh->n_dst, addr,
895 struct nl_addr *rtnl_neigh_get_dst(
struct rtnl_neigh *neigh)
897 if (neigh->ce_mask & NEIGH_ATTR_DST)
903 void rtnl_neigh_set_family(
struct rtnl_neigh *neigh,
int family)
905 neigh->n_family = family;
906 neigh->ce_mask |= NEIGH_ATTR_FAMILY;
909 int rtnl_neigh_get_family(
struct rtnl_neigh *neigh)
911 return neigh->n_family;
914 void rtnl_neigh_set_type(
struct rtnl_neigh *neigh,
int type)
916 neigh->n_type = type;
917 neigh->ce_mask = NEIGH_ATTR_TYPE;
920 int rtnl_neigh_get_type(
struct rtnl_neigh *neigh)
922 if (neigh->ce_mask & NEIGH_ATTR_TYPE)
923 return neigh->n_type;
928 void rtnl_neigh_set_vlan(
struct rtnl_neigh *neigh,
int vlan)
930 neigh->n_vlan = vlan;
931 neigh->ce_mask |= NEIGH_ATTR_VLAN;
934 int rtnl_neigh_get_vlan(
struct rtnl_neigh *neigh)
936 if (neigh->ce_mask & NEIGH_ATTR_VLAN)
937 return neigh->n_vlan;
944 static struct nl_object_ops neigh_obj_ops = {
945 .oo_name =
"route/neigh",
946 .oo_size =
sizeof(
struct rtnl_neigh),
947 .oo_free_data = neigh_free_data,
948 .oo_clone = neigh_clone,
954 .oo_compare = neigh_compare,
955 .oo_keygen = neigh_keygen,
956 .oo_attrs2str = neigh_attrs2str,
957 .oo_id_attrs = (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY),
958 .oo_id_attrs_get = neigh_id_attrs_get
961 static struct nl_af_group neigh_groups[] = {
962 { AF_UNSPEC, RTNLGRP_NEIGH },
963 { AF_BRIDGE, RTNLGRP_NEIGH },
964 { END_OF_GROUP_LIST },
967 static struct nl_cache_ops rtnl_neigh_ops = {
968 .co_name =
"route/neigh",
969 .co_hdrsize =
sizeof(
struct ndmsg),
971 { RTM_NEWNEIGH, NL_ACT_NEW,
"new" },
972 { RTM_DELNEIGH, NL_ACT_DEL,
"del" },
973 { RTM_GETNEIGH, NL_ACT_GET,
"get" },
974 END_OF_MSGTYPES_LIST,
976 .co_protocol = NETLINK_ROUTE,
977 .co_groups = neigh_groups,
978 .co_request_update = neigh_request_update,
979 .co_msg_parser = neigh_msg_parser,
980 .co_obj_ops = &neigh_obj_ops,
983 static void __init neigh_init(
void)
988 static void __exit neigh_exit(
void)
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
Dump object briefly on one line.
int nl_get_user_hz(void)
Return the value of HZ.
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
int nl_addr_guess_family(const struct nl_addr *addr)
Guess address family of abstract address based on address size.
int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh, int flags)
Delete a neighbour.
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
struct rtnl_link * rtnl_link_get(struct nl_cache *cache, int ifindex)
Lookup link in cache by interface index.
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Attribute validation policy.
struct nl_cache * nl_cache_mngt_require_safe(const char *name)
Return cache previously provided via nl_cache_mngt_provide()
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, struct nla_policy *policy)
parse attributes of a netlink message
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
void nl_addr_set_family(struct nl_addr *addr, int family)
Set address family.
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
int rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags)
Add a new neighbour.
Dump all attributes but no statistics.
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
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.
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.
int nl_rtgen_request(struct nl_sock *sk, int type, int family, int flags)
Send routing netlink request message.
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
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.
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.
uint16_t minlen
Minimal length of payload required.
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, size_t len)
Translate interface index to corresponding link name.
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
void rtnl_link_put(struct rtnl_link *link)
Return a link object reference.
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
Dump all attributes including statistics.
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
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.
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
int nl_addr_get_family(const struct nl_addr *addr)
Return address family.