150 #include <netlink-local.h> 151 #include <netlink/netlink.h> 152 #include <netlink/utils.h> 153 #include <netlink/route/rtnl.h> 154 #include <netlink/route/neighbour.h> 155 #include <netlink/route/link.h> 158 #define NEIGH_ATTR_FLAGS 0x01 159 #define NEIGH_ATTR_STATE 0x02 160 #define NEIGH_ATTR_LLADDR 0x04 161 #define NEIGH_ATTR_DST 0x08 162 #define NEIGH_ATTR_CACHEINFO 0x10 163 #define NEIGH_ATTR_IFINDEX 0x20 164 #define NEIGH_ATTR_FAMILY 0x40 165 #define NEIGH_ATTR_TYPE 0x80 166 #define NEIGH_ATTR_PROBES 0x100 172 static void neigh_free_data(
struct nl_object *c)
174 struct rtnl_neigh *neigh = nl_object_priv(c);
179 nl_addr_put(neigh->n_lladdr);
180 nl_addr_put(neigh->n_dst);
183 static int neigh_clone(
struct nl_object *_dst,
struct nl_object *_src)
185 struct rtnl_neigh *dst = nl_object_priv(_dst);
186 struct rtnl_neigh *src = nl_object_priv(_src);
198 return nl_get_errno();
201 static int neigh_compare(
struct nl_object *_a,
struct nl_object *_b,
202 uint32_t attrs,
int flags)
204 struct rtnl_neigh *a = (
struct rtnl_neigh *) _a;
205 struct rtnl_neigh *b = (
struct rtnl_neigh *) _b;
208 #define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR) 210 diff |= NEIGH_DIFF(IFINDEX, a->n_ifindex != b->n_ifindex);
211 diff |= NEIGH_DIFF(FAMILY, a->n_family != b->n_family);
212 diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type);
213 diff |= NEIGH_DIFF(LLADDR,
nl_addr_cmp(a->n_lladdr, b->n_lladdr));
214 diff |= NEIGH_DIFF(DST,
nl_addr_cmp(a->n_dst, b->n_dst));
216 if (flags & LOOSE_FLAG_COMPARISON) {
217 diff |= NEIGH_DIFF(STATE,
218 (a->n_state ^ b->n_state) & b->n_state_mask);
219 diff |= NEIGH_DIFF(FLAGS,
220 (a->n_flags ^ b->n_flags) & b->n_flag_mask);
222 diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state);
223 diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags);
231 static struct trans_tbl neigh_attrs[] = {
232 __ADD(NEIGH_ATTR_FLAGS, flags)
233 __ADD(NEIGH_ATTR_STATE, state)
234 __ADD(NEIGH_ATTR_LLADDR, lladdr)
235 __ADD(NEIGH_ATTR_DST, dst)
236 __ADD(NEIGH_ATTR_CACHEINFO, cacheinfo)
237 __ADD(NEIGH_ATTR_IFINDEX, ifindex)
238 __ADD(NEIGH_ATTR_FAMILY, family)
239 __ADD(NEIGH_ATTR_TYPE, type)
240 __ADD(NEIGH_ATTR_PROBES, probes)
243 static char *neigh_attrs2str(
int attrs,
char *buf,
size_t len)
245 return __flags2str(attrs, buf, len, neigh_attrs,
246 ARRAY_SIZE(neigh_attrs));
249 static struct nla_policy neigh_policy[NDA_MAX+1] = {
250 [NDA_CACHEINFO] = { .
minlen =
sizeof(
struct nda_cacheinfo) },
251 [NDA_PROBES] = { .type =
NLA_U32 },
257 struct rtnl_neigh *neigh;
258 struct nlattr *tb[NDA_MAX + 1];
262 neigh = rtnl_neigh_alloc();
264 err = nl_errno(ENOMEM);
271 err =
nlmsg_parse(n,
sizeof(*nm), tb, NDA_MAX, neigh_policy);
275 neigh->n_family = nm->ndm_family;
276 neigh->n_ifindex = nm->ndm_ifindex;
277 neigh->n_state = nm->ndm_state;
278 neigh->n_flags = nm->ndm_flags;
279 neigh->n_type = nm->ndm_type;
281 neigh->ce_mask |= (NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX |
282 NEIGH_ATTR_STATE | NEIGH_ATTR_FLAGS |
285 if (tb[NDA_LLADDR]) {
286 neigh->n_lladdr =
nla_get_addr(tb[NDA_LLADDR], AF_UNSPEC);
287 if (!neigh->n_lladdr)
289 nl_addr_set_family(neigh->n_lladdr,
291 neigh->ce_mask |= NEIGH_ATTR_LLADDR;
295 neigh->n_dst =
nla_get_addr(tb[NDA_DST], neigh->n_family);
298 neigh->ce_mask |= NEIGH_ATTR_DST;
301 if (tb[NDA_CACHEINFO]) {
302 struct nda_cacheinfo *ci =
nla_data(tb[NDA_CACHEINFO]);
304 neigh->n_cacheinfo.nci_confirmed = ci->ndm_confirmed;
305 neigh->n_cacheinfo.nci_used = ci->ndm_used;
306 neigh->n_cacheinfo.nci_updated = ci->ndm_updated;
307 neigh->n_cacheinfo.nci_refcnt = ci->ndm_refcnt;
309 neigh->ce_mask |= NEIGH_ATTR_CACHEINFO;
312 if (tb[NDA_PROBES]) {
314 neigh->ce_mask |= NEIGH_ATTR_PROBES;
317 err = pp->pp_cb((
struct nl_object *) neigh, pp);
324 rtnl_neigh_put(neigh);
328 static int neigh_request_update(
struct nl_cache *c,
struct nl_handle *h)
334 static int neigh_dump_brief(
struct nl_object *a,
struct nl_dump_params *p)
336 char dst[INET6_ADDRSTRLEN+5], lladdr[INET6_ADDRSTRLEN+5];
337 struct rtnl_neigh *n = (
struct rtnl_neigh *) a;
338 struct nl_cache *link_cache;
339 char state[128], flags[64];
343 dp_dump(p,
"%s ",
nl_addr2str(n->n_dst, dst,
sizeof(dst)));
346 dp_dump(p,
"dev %s ",
348 state,
sizeof(state)));
350 dp_dump(p,
"dev %d ", n->n_ifindex);
352 if (n->ce_mask & NEIGH_ATTR_LLADDR)
353 dp_dump(p,
"lladdr %s ",
356 rtnl_neigh_state2str(n->n_state, state,
sizeof(state));
357 rtnl_neigh_flags2str(n->n_flags, flags,
sizeof(flags));
360 dp_dump(p,
"<%s", state);
362 dp_dump(p,
"%s%s", state[0] ?
"," :
"<", flags);
363 if (state[0] || flags[0])
370 static int neigh_dump_full(
struct nl_object *a,
struct nl_dump_params *p)
373 struct rtnl_neigh *n = (
struct rtnl_neigh *) a;
376 int line = neigh_dump_brief(a, p);
378 dp_dump_line(p, line++,
" refcnt %u type %s confirmed %u used " 380 n->n_cacheinfo.nci_refcnt,
381 nl_rtntype2str(n->n_type, rtn_type,
sizeof(rtn_type)),
382 n->n_cacheinfo.nci_confirmed/hz,
383 n->n_cacheinfo.nci_used/hz, n->n_cacheinfo.nci_updated/hz);
388 static int neigh_dump_stats(
struct nl_object *a,
struct nl_dump_params *p)
390 return neigh_dump_full(a, p);
393 static int neigh_dump_xml(
struct nl_object *obj,
struct nl_dump_params *p)
395 struct rtnl_neigh *neigh = (
struct rtnl_neigh *) obj;
399 dp_dump_line(p, line++,
"<neighbour>\n");
400 dp_dump_line(p, line++,
" <family>%s</family>\n",
401 nl_af2str(neigh->n_family, buf,
sizeof(buf)));
403 if (neigh->ce_mask & NEIGH_ATTR_LLADDR)
404 dp_dump_line(p, line++,
" <lladdr>%s</lladdr>\n",
407 if (neigh->ce_mask & NEIGH_ATTR_DST)
408 dp_dump_line(p, line++,
" <dst>%s</dst>\n",
411 if (neigh->ce_mask & NEIGH_ATTR_IFINDEX) {
412 struct nl_cache *link_cache;
417 dp_dump_line(p, line++,
" <device>%s</device>\n",
422 dp_dump_line(p, line++,
" <device>%u</device>\n",
426 if (neigh->ce_mask & NEIGH_ATTR_PROBES)
427 dp_dump_line(p, line++,
" <probes>%u</probes>\n",
430 if (neigh->ce_mask & NEIGH_ATTR_TYPE)
431 dp_dump_line(p, line++,
" <type>%s</type>\n",
432 nl_rtntype2str(neigh->n_type, buf,
sizeof(buf)));
434 rtnl_neigh_flags2str(neigh->n_flags, buf,
sizeof(buf));
436 dp_dump_line(p, line++,
" <flags>%s</flags>\n", buf);
438 rtnl_neigh_state2str(neigh->n_state, buf,
sizeof(buf));
440 dp_dump_line(p, line++,
" <state>%s</state>\n", buf);
442 dp_dump_line(p, line++,
"</neighbour>\n");
445 struct rtnl_ncacheinfo n_cacheinfo;
451 static int neigh_dump_env(
struct nl_object *obj,
struct nl_dump_params *p)
453 struct rtnl_neigh *neigh = (
struct rtnl_neigh *) obj;
457 dp_dump_line(p, line++,
"NEIGH_FAMILY=%s\n",
458 nl_af2str(neigh->n_family, buf,
sizeof(buf)));
460 if (neigh->ce_mask & NEIGH_ATTR_LLADDR)
461 dp_dump_line(p, line++,
"NEIGHT_LLADDR=%s\n",
464 if (neigh->ce_mask & NEIGH_ATTR_DST)
465 dp_dump_line(p, line++,
"NEIGH_DST=%s\n",
468 if (neigh->ce_mask & NEIGH_ATTR_IFINDEX) {
469 struct nl_cache *link_cache;
471 dp_dump_line(p, line++,
"NEIGH_IFINDEX=%u\n",
476 dp_dump_line(p, line++,
"NEIGH_IFNAME=%s\n",
482 if (neigh->ce_mask & NEIGH_ATTR_PROBES)
483 dp_dump_line(p, line++,
"NEIGH_PROBES=%u\n",
486 if (neigh->ce_mask & NEIGH_ATTR_TYPE)
487 dp_dump_line(p, line++,
"NEIGH_TYPE=%s\n",
488 nl_rtntype2str(neigh->n_type, buf,
sizeof(buf)));
490 rtnl_neigh_flags2str(neigh->n_flags, buf,
sizeof(buf));
492 dp_dump_line(p, line++,
"NEIGH_FLAGS=%s\n", buf);
494 rtnl_neigh_state2str(neigh->n_state, buf,
sizeof(buf));
496 dp_dump_line(p, line++,
"NEIGH_STATE=%s\n", buf);
506 struct rtnl_neigh *rtnl_neigh_alloc(
void)
511 void rtnl_neigh_put(
struct rtnl_neigh *neigh)
536 struct nl_cache *cache;
547 NL_DBG(2,
"Returning new cache %p\n", cache);
562 struct rtnl_neigh *neigh;
564 nl_list_for_each_entry(neigh, &cache->c_items, ce_list) {
565 if (neigh->n_ifindex == ifindex &&
582 static struct nl_msg * build_neigh_msg(
struct rtnl_neigh *tmpl,
int cmd,
586 struct ndmsg nhdr = {
587 .ndm_ifindex = tmpl->n_ifindex,
588 .ndm_family = nl_addr_get_family(tmpl->n_dst),
589 .ndm_state = NUD_PERMANENT,
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;
604 if (tmpl->ce_mask & NEIGH_ATTR_LLADDR)
635 return build_neigh_msg(tmpl, RTM_NEWNEIGH,
NLM_F_CREATE | flags);
663 return nl_errno(ENOMEM);
696 return build_neigh_msg(neigh, RTM_DELNEIGH, flags);
719 return nl_errno(ENOMEM);
753 return build_neigh_msg(neigh, RTM_NEWNEIGH,
NLM_F_REPLACE | flags);
778 return nl_errno(ENOMEM);
795 static struct trans_tbl neigh_states[] = {
796 __ADD(NUD_INCOMPLETE, incomplete)
797 __ADD(NUD_REACHABLE, reachable)
798 __ADD(NUD_STALE, stale)
799 __ADD(NUD_DELAY, delay)
800 __ADD(NUD_PROBE, probe)
801 __ADD(NUD_FAILED, failed)
802 __ADD(NUD_NOARP, norarp)
803 __ADD(NUD_PERMANENT, permanent)
806 char * rtnl_neigh_state2str(
int state,
char *buf,
size_t len)
808 return __flags2str(state, buf, len, neigh_states,
809 ARRAY_SIZE(neigh_states));
812 int rtnl_neigh_str2state(
const char *name)
814 return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states));
824 static struct trans_tbl neigh_flags[] = {
825 __ADD(NTF_PROXY, proxy)
826 __ADD(NTF_ROUTER, router)
829 char * rtnl_neigh_flags2str(
int flags,
char *buf,
size_t len)
831 return __flags2str(flags, buf, len, neigh_flags,
832 ARRAY_SIZE(neigh_flags));
835 int rtnl_neigh_str2flag(
const char *name)
837 return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags));
847 void rtnl_neigh_set_state(
struct rtnl_neigh *neigh,
int state)
849 neigh->n_state_mask |= state;
850 neigh->n_state |= state;
851 neigh->ce_mask |= NEIGH_ATTR_STATE;
854 int rtnl_neigh_get_state(
struct rtnl_neigh *neigh)
856 if (neigh->ce_mask & NEIGH_ATTR_STATE)
857 return neigh->n_state;
862 void rtnl_neigh_unset_state(
struct rtnl_neigh *neigh,
int state)
864 neigh->n_state_mask |= state;
865 neigh->n_state &= ~state;
866 neigh->ce_mask |= NEIGH_ATTR_STATE;
869 void rtnl_neigh_set_flags(
struct rtnl_neigh *neigh,
unsigned int flags)
871 neigh->n_flag_mask |= flags;
872 neigh->n_flags |= flags;
873 neigh->ce_mask |= NEIGH_ATTR_FLAGS;
876 unsigned int rtnl_neigh_get_flags(
struct rtnl_neigh *neigh)
878 return neigh->n_flags;
881 void rtnl_neigh_unset_flags(
struct rtnl_neigh *neigh,
unsigned int flags)
883 neigh->n_flag_mask |= flags;
884 neigh->n_flags &= ~flags;
885 neigh->ce_mask |= NEIGH_ATTR_FLAGS;
888 void rtnl_neigh_set_ifindex(
struct rtnl_neigh *neigh,
int ifindex)
890 neigh->n_ifindex = ifindex;
891 neigh->ce_mask |= NEIGH_ATTR_IFINDEX;
894 int rtnl_neigh_get_ifindex(
struct rtnl_neigh *neigh)
896 if (neigh->ce_mask & NEIGH_ATTR_IFINDEX)
897 return neigh->n_ifindex;
902 static inline int __assign_addr(
struct rtnl_neigh *neigh,
struct nl_addr **pos,
903 struct nl_addr *
new,
int flag,
int nocheck)
906 if (neigh->ce_mask & NEIGH_ATTR_FAMILY) {
907 if (new->a_family != neigh->n_family)
908 return nl_error(EINVAL,
909 "Address family mismatch");
911 neigh->n_family =
new->a_family;
912 neigh->ce_mask |= NEIGH_ATTR_FAMILY;
922 neigh->ce_mask |= flag;
927 void rtnl_neigh_set_lladdr(
struct rtnl_neigh *neigh,
struct nl_addr *addr)
929 __assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1);
932 struct nl_addr *rtnl_neigh_get_lladdr(
struct rtnl_neigh *neigh)
934 if (neigh->ce_mask & NEIGH_ATTR_LLADDR)
935 return neigh->n_lladdr;
940 int rtnl_neigh_set_dst(
struct rtnl_neigh *neigh,
struct nl_addr *addr)
942 return __assign_addr(neigh, &neigh->n_dst, addr,
946 struct nl_addr *rtnl_neigh_get_dst(
struct rtnl_neigh *neigh)
948 if (neigh->ce_mask & NEIGH_ATTR_DST)
954 void rtnl_neigh_set_family(
struct rtnl_neigh *neigh,
int family)
956 neigh->n_family = family;
957 neigh->ce_mask |= NEIGH_ATTR_FAMILY;
960 void rtnl_neigh_set_type(
struct rtnl_neigh *neigh,
int type)
962 neigh->n_type = type;
963 neigh->ce_mask = NEIGH_ATTR_TYPE;
966 int rtnl_neigh_get_type(
struct rtnl_neigh *neigh)
968 if (neigh->ce_mask & NEIGH_ATTR_TYPE)
969 return neigh->n_type;
978 .oo_size =
sizeof(
struct rtnl_neigh),
979 .oo_free_data = neigh_free_data,
980 .oo_clone = neigh_clone,
986 .oo_compare = neigh_compare,
987 .oo_attrs2str = neigh_attrs2str,
988 .oo_id_attrs = (NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY),
992 { AF_UNSPEC, RTNLGRP_NEIGH },
993 { END_OF_GROUP_LIST },
997 .co_name =
"route/neigh",
998 .co_hdrsize =
sizeof(
struct ndmsg),
1000 { RTM_NEWNEIGH, NL_ACT_NEW,
"new" },
1001 { RTM_DELNEIGH, NL_ACT_DEL,
"del" },
1002 { RTM_GETNEIGH, NL_ACT_GET,
"get" },
1003 END_OF_MSGTYPES_LIST,
1005 .co_protocol = NETLINK_ROUTE,
1006 .co_groups = neigh_groups,
1007 .co_request_update = neigh_request_update,
1008 .co_msg_parser = neigh_msg_parser,
1009 .co_obj_ops = &neigh_obj_ops,
1012 static void __init neigh_init(
void)
1017 static void __exit neigh_exit(
void)
#define NLM_F_REPLACE
Replace existing matching config object with this request.
Dump object in a brief one-liner.
#define RTNL_LINK_NOT_FOUND
Special interface index stating the link was not found.
char * nl_addr2str(struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
void * nlmsg_data(const struct nlmsghdr *nlh)
head of message payload
uint16_t nlmsg_type
Message type (content type)
int rtnl_neigh_add(struct nl_handle *handle, struct rtnl_neigh *tmpl, int flags)
Add a new neighbour.
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
struct nl_cache * rtnl_neigh_alloc_cache(struct nl_handle *handle)
Build a neighbour cache including all neighbours currently configured in the kernel.
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
attribute validation policy
struct nl_addr * nl_addr_clone(struct nl_addr *addr)
Clone existing abstract address object.
int nl_wait_for_ack(struct nl_handle *handle)
Wait for ACK.
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
int rtnl_neigh_delete(struct nl_handle *handle, struct rtnl_neigh *neigh, int flags)
Delete a neighbour.
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_msg * rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags)
Build netlink request message to add a new neighbour.
int nl_send_auto_complete(struct nl_handle *handle, struct nl_msg *msg)
Send netlink message and check & extend header values as needed.
struct nl_msg * rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, int flags)
Build a netlink request message to delete a neighbour.
void nl_cache_free(struct nl_cache *cache)
Free a cache.
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
int nl_cache_refill(struct nl_handle *handle, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
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.
Dump all attribtes in XML format.
#define NLM_F_CREATE
Create config object if it doesn't already exist.
#define NLM_F_DUMP
Dump all entries.
struct nl_cache * nl_cache_mngt_require(const char *name)
Demand the use of a global cache.
void * nla_data(const struct nlattr *nla)
head of payload
int nl_rtgen_request(struct nl_handle *handle, int type, int family, int flags)
Send routing netlink request message.
struct nl_addr * nla_get_addr(struct nlattr *nla, int family)
Return payload of address attribute.
#define NLA_PUT_ADDR(n, attrtype, addr)
Add a address attribute to a netlink message.
uint16_t minlen
Minimal length of payload required to be available.
int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b)
Compares two abstract address objects.
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.
int nl_addr_guess_family(struct nl_addr *addr)
Guess address family of an abstract address object based on address size.
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, size_t len)
Translate an interface index to the corresponding link name.
int rtnl_neigh_change(struct nl_handle *handle, struct rtnl_neigh *neigh, int flags)
Change neighbour attributes.
uint32_t nla_get_u32(struct nlattr *nla)
Return payload of u32 attribute.
Address family to netlink group association.
struct nl_msg * rtnl_neigh_build_change_request(struct rtnl_neigh *neigh, int flags)
Build a netlink request message to change neighbour attributes.
int nl_get_hz(void)
Return the value of HZ.
char * oo_name
Unique name of object type.
Dump all attributes but no statistics.
Dump all attributes including statistics.
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate an empty cache.
Dump all attribtues as env variables.