144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/route/neigh.c Neighbours 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup rtnl 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup neigh Neighbours 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @brief 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf * The neighbour table establishes bindings between protocol addresses and 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf * link layer addresses for hosts sharing the same physical link. This 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf * module allows you to access and manipulate the content of these tables. 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par Neighbour States 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf * NUD_INCOMPLETE 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf * NUD_REACHABLE 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf * NUD_STALE 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf * NUD_DELAY 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf * NUD_PROBE 2844d362409d5469aed47d19e7908d19bd194493aThomas Graf * NUD_FAILED 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf * NUD_NOARP 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf * NUD_PERMANENT 3144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par Neighbour Flags 3444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf * NTF_PROXY 3644d362409d5469aed47d19e7908d19bd194493aThomas Graf * NTF_ROUTER 3744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 3844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 3944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par Neighbour Identification 4044d362409d5469aed47d19e7908d19bd194493aThomas Graf * A neighbour is uniquely identified by the attributes listed below, whenever 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf * you refer to an existing neighbour all of the attributes must be set. 4244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Neighbours from caches automatically have all required attributes set. 4344d362409d5469aed47d19e7908d19bd194493aThomas Graf * - interface index (rtnl_neigh_set_ifindex()) 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf * - destination address (rtnl_neigh_set_dst()) 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par Changeable Attributes 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf * \anchor neigh_changeable 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf * - state (rtnl_neigh_set_state()) 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf * - link layer address (rtnl_neigh_set_lladdr()) 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par Required Caches for Dumping 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf * In order to dump neighbour attributes you must provide the following 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf * caches via nl_cache_provide() 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf * - link cache holding all links 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par TODO 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf * - Document proxy settings 5844d362409d5469aed47d19e7908d19bd194493aThomas Graf * - Document states and their influence 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 1) Retrieving information about configured neighbours 6144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // The first step is to retrieve a list of all available neighbour within 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf * // the kernel and put them into a cache. 641155370f520cb64657e25153255cf7dc1424317fThomas Graf * struct nl_cache *cache = rtnl_neigh_alloc_cache(sk); 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 6644d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Neighbours can then be looked up by the interface and destination 6744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // address: 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct rtnl_neigh *neigh = rtnl_neigh_get(cache, ifindex, dst_addr); 6944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf * // After successful usage, the object must be given back to the cache 7144d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_neigh_put(neigh); 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 2) Adding new neighbours 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Allocate an empty neighbour handle to be filled out with the attributes 7744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // of the new neighbour. 7844d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct rtnl_neigh *neigh = rtnl_neigh_alloc(); 7944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Fill out the attributes of the new neighbour 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_neigh_set_ifindex(neigh, ifindex); 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_neigh_set_dst(neigh, dst_addr); 8344d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_neigh_set_state(neigh, rtnl_neigh_str2state("permanent")); 8444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 8544d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Build the netlink message and send it to the kernel, the operation will 8644d362409d5469aed47d19e7908d19bd194493aThomas Graf * // block until the operation has been completed. Alternatively the required 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // netlink message can be built using rtnl_neigh_build_add_request() 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // to be sent out using nl_send_auto_complete(). 89531029c130db95a82c9f2121e59698e86cd84e79Thomas Graf * rtnl_neigh_add(sk, neigh, NLM_F_CREATE); 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Free the memory 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_neigh_put(neigh); 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 3) Deleting an existing neighbour 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Allocate an empty neighbour object to be filled out with the attributes 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // matching the neighbour to be deleted. Alternatively a fully equipped 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf * // neighbour object out of a cache can be used instead. 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct rtnl_neigh *neigh = rtnl_neigh_alloc(); 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Neighbours are uniquely identified by their interface index and 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf * // destination address, you may fill out other attributes but they 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf * // will have no influence. 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_neigh_set_ifindex(neigh, ifindex); 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_neigh_set_dst(neigh, dst_addr); 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Build the netlink message and send it to the kernel, the operation will 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf * // block until the operation has been completed. Alternatively the required 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf * // netlink message can be built using rtnl_neigh_build_delete_request() 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf * // to be sent out using nl_send_auto_complete(). 1121155370f520cb64657e25153255cf7dc1424317fThomas Graf * rtnl_neigh_delete(sk, neigh, 0); 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 11444d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Free the memory 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_neigh_put(neigh); 11644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 4) Changing neighbour attributes 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Allocate an empty neighbour object to be filled out with the attributes 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf * // matching the neighbour to be changed and the new parameters. Alternatively 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // a fully equipped modified neighbour object out of a cache can be used. 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct rtnl_neigh *neigh = rtnl_neigh_alloc(); 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Identify the neighbour to be changed by its interface index and 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf * // destination address 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_neigh_set_ifindex(neigh, ifindex); 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_neigh_set_dst(neigh, dst_addr); 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf * // The link layer address may be modified, if so it is wise to change 13144d362409d5469aed47d19e7908d19bd194493aThomas Graf * // its state to "permanent" in order to avoid having it overwritten. 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_neigh_set_lladdr(neigh, lladdr); 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 13444d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Secondly the state can be modified allowing normal neighbours to be 13544d362409d5469aed47d19e7908d19bd194493aThomas Graf * // converted into permanent entries or to manually confirm a neighbour. 13644d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_neigh_set_state(neigh, state); 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 13844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Build the netlink message and send it to the kernel, the operation will 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf * // block until the operation has been completed. Alternatively the required 14044d362409d5469aed47d19e7908d19bd194493aThomas Graf * // netlink message can be built using rtnl_neigh_build_change_request() 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf * // to be sent out using nl_send_auto_complete(). 142531029c130db95a82c9f2121e59698e86cd84e79Thomas Graf * rtnl_neigh_add(sk, neigh, NLM_F_REPLACE); 14344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Free the memory 14544d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_neigh_put(neigh); 14644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 14744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 14844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 14944d362409d5469aed47d19e7908d19bd194493aThomas Graf 15044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h> 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 15344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/rtnl.h> 15444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/neighbour.h> 15544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/link.h> 15644d362409d5469aed47d19e7908d19bd194493aThomas Graf 15744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @cond SKIP */ 15844d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NEIGH_ATTR_FLAGS 0x01 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NEIGH_ATTR_STATE 0x02 16044d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NEIGH_ATTR_LLADDR 0x04 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NEIGH_ATTR_DST 0x08 16244d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NEIGH_ATTR_CACHEINFO 0x10 16344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NEIGH_ATTR_IFINDEX 0x20 16444d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NEIGH_ATTR_FAMILY 0x40 16544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NEIGH_ATTR_TYPE 0x80 16644d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NEIGH_ATTR_PROBES 0x100 16744d362409d5469aed47d19e7908d19bd194493aThomas Graf 16844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops rtnl_neigh_ops; 16944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_object_ops neigh_obj_ops; 17044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @endcond */ 17144d362409d5469aed47d19e7908d19bd194493aThomas Graf 17244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void neigh_free_data(struct nl_object *c) 17344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 17444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_neigh *neigh = nl_object_priv(c); 17544d362409d5469aed47d19e7908d19bd194493aThomas Graf 17644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!neigh) 17744d362409d5469aed47d19e7908d19bd194493aThomas Graf return; 17844d362409d5469aed47d19e7908d19bd194493aThomas Graf 17944d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(neigh->n_lladdr); 18044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(neigh->n_dst); 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf 18344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int neigh_clone(struct nl_object *_dst, struct nl_object *_src) 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 18544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_neigh *dst = nl_object_priv(_dst); 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_neigh *src = nl_object_priv(_src); 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (src->n_lladdr) 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!(dst->n_lladdr = nl_addr_clone(src->n_lladdr))) 1908a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (src->n_dst) 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!(dst->n_dst = nl_addr_clone(src->n_dst))) 1948a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 19744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf 19944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int neigh_compare(struct nl_object *_a, struct nl_object *_b, 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t attrs, int flags) 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_neigh *a = (struct rtnl_neigh *) _a; 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_neigh *b = (struct rtnl_neigh *) _b; 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf int diff = 0; 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf 20644d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR) 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf 20844d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= NEIGH_DIFF(IFINDEX, a->n_ifindex != b->n_ifindex); 20944d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= NEIGH_DIFF(FAMILY, a->n_family != b->n_family); 21044d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type); 21144d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= NEIGH_DIFF(LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr)); 21244d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= NEIGH_DIFF(DST, nl_addr_cmp(a->n_dst, b->n_dst)); 21344d362409d5469aed47d19e7908d19bd194493aThomas Graf 214535e83162249ed6274ba46bc72d8cc683ba20e17Thomas Graf if (flags & LOOSE_COMPARISON) { 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= NEIGH_DIFF(STATE, 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf (a->n_state ^ b->n_state) & b->n_state_mask); 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= NEIGH_DIFF(FLAGS, 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf (a->n_flags ^ b->n_flags) & b->n_flag_mask); 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf } else { 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state); 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags); 22244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf#undef NEIGH_DIFF 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf return diff; 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf 22944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct trans_tbl neigh_attrs[] = { 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NEIGH_ATTR_FLAGS, flags) 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NEIGH_ATTR_STATE, state) 23244d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NEIGH_ATTR_LLADDR, lladdr) 23344d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NEIGH_ATTR_DST, dst) 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NEIGH_ATTR_CACHEINFO, cacheinfo) 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NEIGH_ATTR_IFINDEX, ifindex) 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NEIGH_ATTR_FAMILY, family) 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NEIGH_ATTR_TYPE, type) 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NEIGH_ATTR_PROBES, probes) 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf 24144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic char *neigh_attrs2str(int attrs, char *buf, size_t len) 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf return __flags2str(attrs, buf, len, neigh_attrs, 24444d362409d5469aed47d19e7908d19bd194493aThomas Graf ARRAY_SIZE(neigh_attrs)); 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 24644d362409d5469aed47d19e7908d19bd194493aThomas Graf 24744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy neigh_policy[NDA_MAX+1] = { 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf [NDA_CACHEINFO] = { .minlen = sizeof(struct nda_cacheinfo) }, 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf [NDA_PROBES] = { .type = NLA_U32 }, 25044d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf 25244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int neigh_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 2533040a1d6254465bed9e44e4d1bf279c2c50cd16aThomas Graf struct nlmsghdr *n, struct nl_parser_param *pp) 25444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 25544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_neigh *neigh; 25644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tb[NDA_MAX + 1]; 25744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct ndmsg *nm; 25844d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 25944d362409d5469aed47d19e7908d19bd194493aThomas Graf 26044d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh = rtnl_neigh_alloc(); 26144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!neigh) { 2628a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_NOMEM; 26344d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 26444d362409d5469aed47d19e7908d19bd194493aThomas Graf } 26544d362409d5469aed47d19e7908d19bd194493aThomas Graf 26644d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_msgtype = n->nlmsg_type; 26744d362409d5469aed47d19e7908d19bd194493aThomas Graf nm = nlmsg_data(n); 26844d362409d5469aed47d19e7908d19bd194493aThomas Graf 26944d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nlmsg_parse(n, sizeof(*nm), tb, NDA_MAX, neigh_policy); 27044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 27144d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 27244d362409d5469aed47d19e7908d19bd194493aThomas Graf 27344d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_family = nm->ndm_family; 27444d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_ifindex = nm->ndm_ifindex; 27544d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_state = nm->ndm_state; 27644d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_flags = nm->ndm_flags; 27744d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_type = nm->ndm_type; 27844d362409d5469aed47d19e7908d19bd194493aThomas Graf 27944d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask |= (NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX | 28044d362409d5469aed47d19e7908d19bd194493aThomas Graf NEIGH_ATTR_STATE | NEIGH_ATTR_FLAGS | 28144d362409d5469aed47d19e7908d19bd194493aThomas Graf NEIGH_ATTR_TYPE); 28244d362409d5469aed47d19e7908d19bd194493aThomas Graf 28344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[NDA_LLADDR]) { 284eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf neigh->n_lladdr = nl_addr_alloc_attr(tb[NDA_LLADDR], AF_UNSPEC); 285eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf if (!neigh->n_lladdr) { 286eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf err = -NLE_NOMEM; 28744d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 288eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf } 28944d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_set_family(neigh->n_lladdr, 29044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_guess_family(neigh->n_lladdr)); 29144d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask |= NEIGH_ATTR_LLADDR; 29244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 29344d362409d5469aed47d19e7908d19bd194493aThomas Graf 29444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[NDA_DST]) { 295eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf neigh->n_dst = nl_addr_alloc_attr(tb[NDA_DST], neigh->n_family); 296eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf if (!neigh->n_dst) { 297eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf err = -NLE_NOMEM; 29844d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 299eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf } 30044d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask |= NEIGH_ATTR_DST; 30144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 30244d362409d5469aed47d19e7908d19bd194493aThomas Graf 30344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[NDA_CACHEINFO]) { 30444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nda_cacheinfo *ci = nla_data(tb[NDA_CACHEINFO]); 30544d362409d5469aed47d19e7908d19bd194493aThomas Graf 30644d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_cacheinfo.nci_confirmed = ci->ndm_confirmed; 30744d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_cacheinfo.nci_used = ci->ndm_used; 30844d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_cacheinfo.nci_updated = ci->ndm_updated; 30944d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_cacheinfo.nci_refcnt = ci->ndm_refcnt; 31044d362409d5469aed47d19e7908d19bd194493aThomas Graf 31144d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask |= NEIGH_ATTR_CACHEINFO; 31244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 31344d362409d5469aed47d19e7908d19bd194493aThomas Graf 31444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[NDA_PROBES]) { 31544d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_probes = nla_get_u32(tb[NDA_PROBES]); 31644d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask |= NEIGH_ATTR_PROBES; 31744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 31844d362409d5469aed47d19e7908d19bd194493aThomas Graf 31944d362409d5469aed47d19e7908d19bd194493aThomas Graf err = pp->pp_cb((struct nl_object *) neigh, pp); 32044d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 32144d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_neigh_put(neigh); 32244d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 32344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 32444d362409d5469aed47d19e7908d19bd194493aThomas Graf 3251155370f520cb64657e25153255cf7dc1424317fThomas Grafstatic int neigh_request_update(struct nl_cache *c, struct nl_sock *h) 32644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 32744d362409d5469aed47d19e7908d19bd194493aThomas Graf return nl_rtgen_request(h, RTM_GETNEIGH, AF_UNSPEC, NLM_F_DUMP); 32844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 32944d362409d5469aed47d19e7908d19bd194493aThomas Graf 33044d362409d5469aed47d19e7908d19bd194493aThomas Graf 331d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p) 33244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 33344d362409d5469aed47d19e7908d19bd194493aThomas Graf char dst[INET6_ADDRSTRLEN+5], lladdr[INET6_ADDRSTRLEN+5]; 33444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_neigh *n = (struct rtnl_neigh *) a; 33544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache *link_cache; 33644d362409d5469aed47d19e7908d19bd194493aThomas Graf char state[128], flags[64]; 33744d362409d5469aed47d19e7908d19bd194493aThomas Graf 33844d362409d5469aed47d19e7908d19bd194493aThomas Graf link_cache = nl_cache_mngt_require("route/link"); 33944d362409d5469aed47d19e7908d19bd194493aThomas Graf 340d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst))); 34144d362409d5469aed47d19e7908d19bd194493aThomas Graf 34244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (link_cache) 343d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "dev %s ", 34444d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_link_i2name(link_cache, n->n_ifindex, 34544d362409d5469aed47d19e7908d19bd194493aThomas Graf state, sizeof(state))); 34644d362409d5469aed47d19e7908d19bd194493aThomas Graf else 347d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "dev %d ", n->n_ifindex); 34844d362409d5469aed47d19e7908d19bd194493aThomas Graf 34944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (n->ce_mask & NEIGH_ATTR_LLADDR) 350d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "lladdr %s ", 35144d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr2str(n->n_lladdr, lladdr, sizeof(lladdr))); 35244d362409d5469aed47d19e7908d19bd194493aThomas Graf 35344d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_neigh_state2str(n->n_state, state, sizeof(state)); 35444d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_neigh_flags2str(n->n_flags, flags, sizeof(flags)); 35544d362409d5469aed47d19e7908d19bd194493aThomas Graf 35644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (state[0]) 357d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "<%s", state); 35844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (flags[0]) 359d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "%s%s", state[0] ? "," : "<", flags); 36044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (state[0] || flags[0]) 361d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, ">"); 362d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "\n"); 36344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 36444d362409d5469aed47d19e7908d19bd194493aThomas Graf 365d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void neigh_dump_details(struct nl_object *a, struct nl_dump_params *p) 36644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 36744d362409d5469aed47d19e7908d19bd194493aThomas Graf char rtn_type[32]; 36844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_neigh *n = (struct rtnl_neigh *) a; 36944d362409d5469aed47d19e7908d19bd194493aThomas Graf int hz = nl_get_hz(); 37044d362409d5469aed47d19e7908d19bd194493aThomas Graf 371d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf neigh_dump_line(a, p); 37244d362409d5469aed47d19e7908d19bd194493aThomas Graf 373d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, " refcnt %u type %s confirmed %u used " 37444d362409d5469aed47d19e7908d19bd194493aThomas Graf "%u updated %u\n", 37544d362409d5469aed47d19e7908d19bd194493aThomas Graf n->n_cacheinfo.nci_refcnt, 37644d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_rtntype2str(n->n_type, rtn_type, sizeof(rtn_type)), 37744d362409d5469aed47d19e7908d19bd194493aThomas Graf n->n_cacheinfo.nci_confirmed/hz, 37844d362409d5469aed47d19e7908d19bd194493aThomas Graf n->n_cacheinfo.nci_used/hz, n->n_cacheinfo.nci_updated/hz); 37944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 38044d362409d5469aed47d19e7908d19bd194493aThomas Graf 381d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void neigh_dump_stats(struct nl_object *a, struct nl_dump_params *p) 38244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 383d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf neigh_dump_details(a, p); 38444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 38544d362409d5469aed47d19e7908d19bd194493aThomas Graf 386d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void neigh_dump_env(struct nl_object *obj, struct nl_dump_params *p) 38744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 38844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_neigh *neigh = (struct rtnl_neigh *) obj; 38944d362409d5469aed47d19e7908d19bd194493aThomas Graf char buf[128]; 39044d362409d5469aed47d19e7908d19bd194493aThomas Graf 391d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, "NEIGH_FAMILY=%s\n", 39244d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_af2str(neigh->n_family, buf, sizeof(buf))); 39344d362409d5469aed47d19e7908d19bd194493aThomas Graf 39444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (neigh->ce_mask & NEIGH_ATTR_LLADDR) 395d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, "NEIGHT_LLADDR=%s\n", 39644d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr2str(neigh->n_lladdr, buf, sizeof(buf))); 39744d362409d5469aed47d19e7908d19bd194493aThomas Graf 39844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (neigh->ce_mask & NEIGH_ATTR_DST) 399d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, "NEIGH_DST=%s\n", 40044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr2str(neigh->n_dst, buf, sizeof(buf))); 40144d362409d5469aed47d19e7908d19bd194493aThomas Graf 40244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (neigh->ce_mask & NEIGH_ATTR_IFINDEX) { 40344d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache *link_cache; 40444d362409d5469aed47d19e7908d19bd194493aThomas Graf 405d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, "NEIGH_IFINDEX=%u\n", neigh->n_ifindex); 40644d362409d5469aed47d19e7908d19bd194493aThomas Graf 40744d362409d5469aed47d19e7908d19bd194493aThomas Graf link_cache = nl_cache_mngt_require("route/link"); 40844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (link_cache) 409d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, "NEIGH_IFNAME=%s\n", 41044d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_link_i2name(link_cache, 41144d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_ifindex, 41244d362409d5469aed47d19e7908d19bd194493aThomas Graf buf, sizeof(buf))); 41344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 41444d362409d5469aed47d19e7908d19bd194493aThomas Graf 41544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (neigh->ce_mask & NEIGH_ATTR_PROBES) 416d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, "NEIGH_PROBES=%u\n", neigh->n_probes); 41744d362409d5469aed47d19e7908d19bd194493aThomas Graf 41844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (neigh->ce_mask & NEIGH_ATTR_TYPE) 419d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, "NEIGH_TYPE=%s\n", 42044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_rtntype2str(neigh->n_type, buf, sizeof(buf))); 42144d362409d5469aed47d19e7908d19bd194493aThomas Graf 42244d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_neigh_flags2str(neigh->n_flags, buf, sizeof(buf)); 42344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (buf[0]) 424d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, "NEIGH_FLAGS=%s\n", buf); 42544d362409d5469aed47d19e7908d19bd194493aThomas Graf 42644d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_neigh_state2str(neigh->n_state, buf, sizeof(buf)); 42744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (buf[0]) 428d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, "NEIGH_STATE=%s\n", buf); 42944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 43044d362409d5469aed47d19e7908d19bd194493aThomas Graf 43144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 43244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Neighbour Object Allocation/Freeage 43344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 43444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 43544d362409d5469aed47d19e7908d19bd194493aThomas Graf 43644d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct rtnl_neigh *rtnl_neigh_alloc(void) 43744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 43844d362409d5469aed47d19e7908d19bd194493aThomas Graf return (struct rtnl_neigh *) nl_object_alloc(&neigh_obj_ops); 43944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 44044d362409d5469aed47d19e7908d19bd194493aThomas Graf 44144d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_neigh_put(struct rtnl_neigh *neigh) 44244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 44344d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_object_put((struct nl_object *) neigh); 44444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 44544d362409d5469aed47d19e7908d19bd194493aThomas Graf 44644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 44744d362409d5469aed47d19e7908d19bd194493aThomas Graf 44844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 44944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Neighbour Cache Managament 45044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 45144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 45244d362409d5469aed47d19e7908d19bd194493aThomas Graf 45344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 45444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Build a neighbour cache including all neighbours currently configured in the kernel. 4551155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 4568a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @arg result Pointer to store resulting cache. 45744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 45844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocates a new neighbour cache, initializes it properly and updates it 45944d362409d5469aed47d19e7908d19bd194493aThomas Graf * to include all neighbours currently configured in the kernel. 46044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 4618a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @return 0 on success or a negative error code. 46244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 4631155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_neigh_alloc_cache(struct nl_sock *sock, struct nl_cache **result) 46444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 4658a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return nl_cache_alloc_and_fill(&rtnl_neigh_ops, sock, result); 46644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 46744d362409d5469aed47d19e7908d19bd194493aThomas Graf 46844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 46944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Look up a neighbour by interface index and destination address 47044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cache neighbour cache 47144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg ifindex interface index the neighbour is on 47244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg dst destination address of the neighbour 47344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return neighbour handle or NULL if no match was found. 47444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 47544d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex, 47644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_addr *dst) 47744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 47844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_neigh *neigh; 47944d362409d5469aed47d19e7908d19bd194493aThomas Graf 48044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_list_for_each_entry(neigh, &cache->c_items, ce_list) { 48144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (neigh->n_ifindex == ifindex && 48244d362409d5469aed47d19e7908d19bd194493aThomas Graf !nl_addr_cmp(neigh->n_dst, dst)) { 48344d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_object_get((struct nl_object *) neigh); 48444d362409d5469aed47d19e7908d19bd194493aThomas Graf return neigh; 48544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 48644d362409d5469aed47d19e7908d19bd194493aThomas Graf } 48744d362409d5469aed47d19e7908d19bd194493aThomas Graf 48844d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 48944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 49044d362409d5469aed47d19e7908d19bd194493aThomas Graf 49144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 49244d362409d5469aed47d19e7908d19bd194493aThomas Graf 49344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 49444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Neighbour Addition 49544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 49644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 49744d362409d5469aed47d19e7908d19bd194493aThomas Graf 4988a3efffa5b3fde252675239914118664d36a2c24Thomas Grafstatic int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags, 4998a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 50044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 50144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *msg; 50244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct ndmsg nhdr = { 50344d362409d5469aed47d19e7908d19bd194493aThomas Graf .ndm_ifindex = tmpl->n_ifindex, 50444d362409d5469aed47d19e7908d19bd194493aThomas Graf .ndm_state = NUD_PERMANENT, 50544d362409d5469aed47d19e7908d19bd194493aThomas Graf }; 50644d362409d5469aed47d19e7908d19bd194493aThomas Graf 507531029c130db95a82c9f2121e59698e86cd84e79Thomas Graf if (!(tmpl->ce_mask & NEIGH_ATTR_DST)) 508531029c130db95a82c9f2121e59698e86cd84e79Thomas Graf return -NLE_MISSING_ATTR; 509531029c130db95a82c9f2121e59698e86cd84e79Thomas Graf 510531029c130db95a82c9f2121e59698e86cd84e79Thomas Graf nhdr.ndm_family = nl_addr_get_family(tmpl->n_dst); 511531029c130db95a82c9f2121e59698e86cd84e79Thomas Graf 51244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tmpl->ce_mask & NEIGH_ATTR_STATE) 51344d362409d5469aed47d19e7908d19bd194493aThomas Graf nhdr.ndm_state = tmpl->n_state; 51444d362409d5469aed47d19e7908d19bd194493aThomas Graf 51544d362409d5469aed47d19e7908d19bd194493aThomas Graf msg = nlmsg_alloc_simple(cmd, flags); 51644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!msg) 5178a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 51844d362409d5469aed47d19e7908d19bd194493aThomas Graf 51944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0) 52044d362409d5469aed47d19e7908d19bd194493aThomas Graf goto nla_put_failure; 52144d362409d5469aed47d19e7908d19bd194493aThomas Graf 52244d362409d5469aed47d19e7908d19bd194493aThomas Graf NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst); 52344d362409d5469aed47d19e7908d19bd194493aThomas Graf 52444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tmpl->ce_mask & NEIGH_ATTR_LLADDR) 52544d362409d5469aed47d19e7908d19bd194493aThomas Graf NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr); 52644d362409d5469aed47d19e7908d19bd194493aThomas Graf 5278a3efffa5b3fde252675239914118664d36a2c24Thomas Graf *result = msg; 5288a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return 0; 52944d362409d5469aed47d19e7908d19bd194493aThomas Graf 53044d362409d5469aed47d19e7908d19bd194493aThomas Grafnla_put_failure: 53144d362409d5469aed47d19e7908d19bd194493aThomas Graf nlmsg_free(msg); 5328a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MSGSIZE; 53344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 53444d362409d5469aed47d19e7908d19bd194493aThomas Graf 53544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 53644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Build netlink request message to add a new neighbour 53744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg tmpl template with data of new neighbour 53844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags additional netlink message flags 5398a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @arg result Pointer to store resulting message. 54044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 54144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a new netlink message requesting a addition of a new 54244d362409d5469aed47d19e7908d19bd194493aThomas Graf * neighbour. The netlink message header isn't fully equipped with 54344d362409d5469aed47d19e7908d19bd194493aThomas Graf * all relevant fields and must thus be sent out via nl_send_auto_complete() 54444d362409d5469aed47d19e7908d19bd194493aThomas Graf * or supplemented as needed. \a tmpl must contain the attributes of the new 54544d362409d5469aed47d19e7908d19bd194493aThomas Graf * neighbour set via \c rtnl_neigh_set_* functions. 54644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 54744d362409d5469aed47d19e7908d19bd194493aThomas Graf * The following attributes must be set in the template: 54844d362409d5469aed47d19e7908d19bd194493aThomas Graf * - Interface index (rtnl_neigh_set_ifindex()) 54944d362409d5469aed47d19e7908d19bd194493aThomas Graf * - State (rtnl_neigh_set_state()) 55044d362409d5469aed47d19e7908d19bd194493aThomas Graf * - Destination address (rtnl_neigh_set_dst()) 55144d362409d5469aed47d19e7908d19bd194493aThomas Graf * - Link layer address (rtnl_neigh_set_lladdr()) 55244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 5538a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @return 0 on success or a negative error code. 55444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 5558a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags, 5568a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 55744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 558531029c130db95a82c9f2121e59698e86cd84e79Thomas Graf return build_neigh_msg(tmpl, RTM_NEWNEIGH, flags, result); 55944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 56044d362409d5469aed47d19e7908d19bd194493aThomas Graf 56144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 56244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Add a new neighbour 5631155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 56444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg tmpl template with requested changes 56544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags additional netlink message flags 56644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 56744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a netlink message by calling rtnl_neigh_build_add_request(), 56844d362409d5469aed47d19e7908d19bd194493aThomas Graf * sends the request to the kernel and waits for the next ACK to be 56944d362409d5469aed47d19e7908d19bd194493aThomas Graf * received and thus blocks until the request has been fullfilled. 57044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 57144d362409d5469aed47d19e7908d19bd194493aThomas Graf * The following attributes must be set in the template: 57244d362409d5469aed47d19e7908d19bd194493aThomas Graf * - Interface index (rtnl_neigh_set_ifindex()) 57344d362409d5469aed47d19e7908d19bd194493aThomas Graf * - State (rtnl_neigh_set_state()) 57444d362409d5469aed47d19e7908d19bd194493aThomas Graf * - Destination address (rtnl_neigh_set_dst()) 57544d362409d5469aed47d19e7908d19bd194493aThomas Graf * - Link layer address (rtnl_neigh_set_lladdr()) 57644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 57744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on sucess or a negative error if an error occured. 57844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 5791155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags) 58044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 58144d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 58244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *msg; 58344d362409d5469aed47d19e7908d19bd194493aThomas Graf 5848a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((err = rtnl_neigh_build_add_request(tmpl, flags, &msg)) < 0) 5858a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 58644d362409d5469aed47d19e7908d19bd194493aThomas Graf 587ef50a38fbd8682a5c9efd559e7db68664977f080Thomas Graf err = nl_send_auto_complete(sk, msg); 588ef50a38fbd8682a5c9efd559e7db68664977f080Thomas Graf nlmsg_free(msg); 589ef50a38fbd8682a5c9efd559e7db68664977f080Thomas Graf if (err < 0) 59044d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 59144d362409d5469aed47d19e7908d19bd194493aThomas Graf 592cfcfca070355b246028df60da79813f09ed65755Thomas Graf return wait_for_ack(sk); 59344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 59444d362409d5469aed47d19e7908d19bd194493aThomas Graf 59544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 59644d362409d5469aed47d19e7908d19bd194493aThomas Graf 59744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 59844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Neighbour Deletion 59944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 60044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 60144d362409d5469aed47d19e7908d19bd194493aThomas Graf 60244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 60344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Build a netlink request message to delete a neighbour 60444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg neigh neighbour to delete 60544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags additional netlink message flags 6068a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @arg result Pointer to store resulting message. 60744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 60844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a new netlink message requesting a deletion of a neighbour. 60944d362409d5469aed47d19e7908d19bd194493aThomas Graf * The netlink message header isn't fully equipped with all relevant 61044d362409d5469aed47d19e7908d19bd194493aThomas Graf * fields and must thus be sent out via nl_send_auto_complete() 61144d362409d5469aed47d19e7908d19bd194493aThomas Graf * or supplemented as needed. \a neigh must point to an existing 61244d362409d5469aed47d19e7908d19bd194493aThomas Graf * neighbour. 61344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 6148a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @return 0 on success or a negative error code. 61544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 6168a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, int flags, 6178a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 61844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 6198a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return build_neigh_msg(neigh, RTM_DELNEIGH, flags, result); 62044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 62144d362409d5469aed47d19e7908d19bd194493aThomas Graf 62244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 62344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Delete a neighbour 6241155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 62544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg neigh neighbour to delete 62644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags additional netlink message flags 62744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 62844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a netlink message by calling rtnl_neigh_build_delete_request(), 62944d362409d5469aed47d19e7908d19bd194493aThomas Graf * sends the request to the kernel and waits for the next ACK to be 63044d362409d5469aed47d19e7908d19bd194493aThomas Graf * received and thus blocks until the request has been fullfilled. 63144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 63244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on sucess or a negative error if an error occured. 63344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 6341155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh, 63544d362409d5469aed47d19e7908d19bd194493aThomas Graf int flags) 63644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 63744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *msg; 6388a3efffa5b3fde252675239914118664d36a2c24Thomas Graf int err; 63944d362409d5469aed47d19e7908d19bd194493aThomas Graf 6408a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((err = rtnl_neigh_build_delete_request(neigh, flags, &msg)) < 0) 6418a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 64244d362409d5469aed47d19e7908d19bd194493aThomas Graf 643ef50a38fbd8682a5c9efd559e7db68664977f080Thomas Graf err = nl_send_auto_complete(sk, msg); 644ef50a38fbd8682a5c9efd559e7db68664977f080Thomas Graf nlmsg_free(msg); 645ef50a38fbd8682a5c9efd559e7db68664977f080Thomas Graf if (err < 0) 64644d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 64744d362409d5469aed47d19e7908d19bd194493aThomas Graf 648cfcfca070355b246028df60da79813f09ed65755Thomas Graf return wait_for_ack(sk); 64944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 65044d362409d5469aed47d19e7908d19bd194493aThomas Graf 65144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 65244d362409d5469aed47d19e7908d19bd194493aThomas Graf 65344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 65444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Neighbour States Translations 65544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 65644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 65744d362409d5469aed47d19e7908d19bd194493aThomas Graf 65844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct trans_tbl neigh_states[] = { 65944d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NUD_INCOMPLETE, incomplete) 66044d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NUD_REACHABLE, reachable) 66144d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NUD_STALE, stale) 66244d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NUD_DELAY, delay) 66344d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NUD_PROBE, probe) 66444d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NUD_FAILED, failed) 66544d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NUD_NOARP, norarp) 66644d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NUD_PERMANENT, permanent) 66744d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 66844d362409d5469aed47d19e7908d19bd194493aThomas Graf 66944d362409d5469aed47d19e7908d19bd194493aThomas Grafchar * rtnl_neigh_state2str(int state, char *buf, size_t len) 67044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 67144d362409d5469aed47d19e7908d19bd194493aThomas Graf return __flags2str(state, buf, len, neigh_states, 67244d362409d5469aed47d19e7908d19bd194493aThomas Graf ARRAY_SIZE(neigh_states)); 67344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 67444d362409d5469aed47d19e7908d19bd194493aThomas Graf 67544d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_neigh_str2state(const char *name) 67644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 67744d362409d5469aed47d19e7908d19bd194493aThomas Graf return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states)); 67844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 67944d362409d5469aed47d19e7908d19bd194493aThomas Graf 68044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 68144d362409d5469aed47d19e7908d19bd194493aThomas Graf 68244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 68344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Neighbour Flags Translations 68444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 68544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 68644d362409d5469aed47d19e7908d19bd194493aThomas Graf 68744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct trans_tbl neigh_flags[] = { 68844d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NTF_PROXY, proxy) 68944d362409d5469aed47d19e7908d19bd194493aThomas Graf __ADD(NTF_ROUTER, router) 69044d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 69144d362409d5469aed47d19e7908d19bd194493aThomas Graf 69244d362409d5469aed47d19e7908d19bd194493aThomas Grafchar * rtnl_neigh_flags2str(int flags, char *buf, size_t len) 69344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 69444d362409d5469aed47d19e7908d19bd194493aThomas Graf return __flags2str(flags, buf, len, neigh_flags, 69544d362409d5469aed47d19e7908d19bd194493aThomas Graf ARRAY_SIZE(neigh_flags)); 69644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 69744d362409d5469aed47d19e7908d19bd194493aThomas Graf 69844d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_neigh_str2flag(const char *name) 69944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 70044d362409d5469aed47d19e7908d19bd194493aThomas Graf return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags)); 70144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 70244d362409d5469aed47d19e7908d19bd194493aThomas Graf 70344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 70444d362409d5469aed47d19e7908d19bd194493aThomas Graf 70544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 70644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Attributes 70744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 70844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 70944d362409d5469aed47d19e7908d19bd194493aThomas Graf 71044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_neigh_set_state(struct rtnl_neigh *neigh, int state) 71144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 71244d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_state_mask |= state; 71344d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_state |= state; 71444d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask |= NEIGH_ATTR_STATE; 71544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 71644d362409d5469aed47d19e7908d19bd194493aThomas Graf 71744d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_neigh_get_state(struct rtnl_neigh *neigh) 71844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 71944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (neigh->ce_mask & NEIGH_ATTR_STATE) 72044d362409d5469aed47d19e7908d19bd194493aThomas Graf return neigh->n_state; 72144d362409d5469aed47d19e7908d19bd194493aThomas Graf else 72244d362409d5469aed47d19e7908d19bd194493aThomas Graf return -1; 72344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 72444d362409d5469aed47d19e7908d19bd194493aThomas Graf 72544d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_neigh_unset_state(struct rtnl_neigh *neigh, int state) 72644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 72744d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_state_mask |= state; 72844d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_state &= ~state; 72944d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask |= NEIGH_ATTR_STATE; 73044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 73144d362409d5469aed47d19e7908d19bd194493aThomas Graf 73244d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_neigh_set_flags(struct rtnl_neigh *neigh, unsigned int flags) 73344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 73444d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_flag_mask |= flags; 73544d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_flags |= flags; 73644d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask |= NEIGH_ATTR_FLAGS; 73744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 73844d362409d5469aed47d19e7908d19bd194493aThomas Graf 73944d362409d5469aed47d19e7908d19bd194493aThomas Grafunsigned int rtnl_neigh_get_flags(struct rtnl_neigh *neigh) 74044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 74144d362409d5469aed47d19e7908d19bd194493aThomas Graf return neigh->n_flags; 74244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 74344d362409d5469aed47d19e7908d19bd194493aThomas Graf 74444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_neigh_unset_flags(struct rtnl_neigh *neigh, unsigned int flags) 74544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 74644d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_flag_mask |= flags; 74744d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_flags &= ~flags; 74844d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask |= NEIGH_ATTR_FLAGS; 74944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 75044d362409d5469aed47d19e7908d19bd194493aThomas Graf 75144d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_neigh_set_ifindex(struct rtnl_neigh *neigh, int ifindex) 75244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 75344d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_ifindex = ifindex; 75444d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask |= NEIGH_ATTR_IFINDEX; 75544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 75644d362409d5469aed47d19e7908d19bd194493aThomas Graf 75744d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_neigh_get_ifindex(struct rtnl_neigh *neigh) 75844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 759b4fbe1d34d6f54045b5c6236d86aacd4340ec83dThomas Graf return neigh->n_ifindex; 76044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 76144d362409d5469aed47d19e7908d19bd194493aThomas Graf 76244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline int __assign_addr(struct rtnl_neigh *neigh, struct nl_addr **pos, 76344d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_addr *new, int flag, int nocheck) 76444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 76544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!nocheck) { 76644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (neigh->ce_mask & NEIGH_ATTR_FAMILY) { 76744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (new->a_family != neigh->n_family) 7688a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_AF_MISMATCH; 76944d362409d5469aed47d19e7908d19bd194493aThomas Graf } else { 77044d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_family = new->a_family; 77144d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask |= NEIGH_ATTR_FAMILY; 77244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 77344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 77444d362409d5469aed47d19e7908d19bd194493aThomas Graf 77544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (*pos) 77644d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(*pos); 77744d362409d5469aed47d19e7908d19bd194493aThomas Graf 77844d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_get(new); 77944d362409d5469aed47d19e7908d19bd194493aThomas Graf *pos = new; 78044d362409d5469aed47d19e7908d19bd194493aThomas Graf 78144d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask |= flag; 78244d362409d5469aed47d19e7908d19bd194493aThomas Graf 78344d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 78444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 78544d362409d5469aed47d19e7908d19bd194493aThomas Graf 78644d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_neigh_set_lladdr(struct rtnl_neigh *neigh, struct nl_addr *addr) 78744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 78844d362409d5469aed47d19e7908d19bd194493aThomas Graf __assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1); 78944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 79044d362409d5469aed47d19e7908d19bd194493aThomas Graf 79144d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *rtnl_neigh_get_lladdr(struct rtnl_neigh *neigh) 79244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 79344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (neigh->ce_mask & NEIGH_ATTR_LLADDR) 79444d362409d5469aed47d19e7908d19bd194493aThomas Graf return neigh->n_lladdr; 79544d362409d5469aed47d19e7908d19bd194493aThomas Graf else 79644d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 79744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 79844d362409d5469aed47d19e7908d19bd194493aThomas Graf 79944d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_neigh_set_dst(struct rtnl_neigh *neigh, struct nl_addr *addr) 80044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 80144d362409d5469aed47d19e7908d19bd194493aThomas Graf return __assign_addr(neigh, &neigh->n_dst, addr, 80244d362409d5469aed47d19e7908d19bd194493aThomas Graf NEIGH_ATTR_DST, 0); 80344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 80444d362409d5469aed47d19e7908d19bd194493aThomas Graf 80544d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *rtnl_neigh_get_dst(struct rtnl_neigh *neigh) 80644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 80744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (neigh->ce_mask & NEIGH_ATTR_DST) 80844d362409d5469aed47d19e7908d19bd194493aThomas Graf return neigh->n_dst; 80944d362409d5469aed47d19e7908d19bd194493aThomas Graf else 81044d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 81144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 81244d362409d5469aed47d19e7908d19bd194493aThomas Graf 81344d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_neigh_set_family(struct rtnl_neigh *neigh, int family) 81444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 81544d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_family = family; 81644d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask |= NEIGH_ATTR_FAMILY; 81744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 81844d362409d5469aed47d19e7908d19bd194493aThomas Graf 8195d82806b48959e4726ae3913ae0b3ce279c4c04aThomas Grafint rtnl_neigh_get_family(struct rtnl_neigh *neigh) 8205d82806b48959e4726ae3913ae0b3ce279c4c04aThomas Graf{ 8215d82806b48959e4726ae3913ae0b3ce279c4c04aThomas Graf return neigh->n_family; 8225d82806b48959e4726ae3913ae0b3ce279c4c04aThomas Graf} 8235d82806b48959e4726ae3913ae0b3ce279c4c04aThomas Graf 82444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_neigh_set_type(struct rtnl_neigh *neigh, int type) 82544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 82644d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->n_type = type; 82744d362409d5469aed47d19e7908d19bd194493aThomas Graf neigh->ce_mask = NEIGH_ATTR_TYPE; 82844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 82944d362409d5469aed47d19e7908d19bd194493aThomas Graf 83044d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_neigh_get_type(struct rtnl_neigh *neigh) 83144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 83244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (neigh->ce_mask & NEIGH_ATTR_TYPE) 83344d362409d5469aed47d19e7908d19bd194493aThomas Graf return neigh->n_type; 83444d362409d5469aed47d19e7908d19bd194493aThomas Graf else 83544d362409d5469aed47d19e7908d19bd194493aThomas Graf return -1; 83644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 83744d362409d5469aed47d19e7908d19bd194493aThomas Graf 83844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 83944d362409d5469aed47d19e7908d19bd194493aThomas Graf 84044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_object_ops neigh_obj_ops = { 84144d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_name = "route/neigh", 84244d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_size = sizeof(struct rtnl_neigh), 84344d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_free_data = neigh_free_data, 84444d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_clone = neigh_clone, 845d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf .oo_dump = { 846d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_LINE] = neigh_dump_line, 847d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_DETAILS] = neigh_dump_details, 848d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_STATS] = neigh_dump_stats, 849d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_ENV] = neigh_dump_env, 850d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf }, 85144d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_compare = neigh_compare, 85244d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_attrs2str = neigh_attrs2str, 85382907257184f647353a9a993caaa1ebadaee2842Patrick McHardy .oo_id_attrs = (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY), 85444d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 85544d362409d5469aed47d19e7908d19bd194493aThomas Graf 85644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_af_group neigh_groups[] = { 85744d362409d5469aed47d19e7908d19bd194493aThomas Graf { AF_UNSPEC, RTNLGRP_NEIGH }, 85844d362409d5469aed47d19e7908d19bd194493aThomas Graf { END_OF_GROUP_LIST }, 85944d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 86044d362409d5469aed47d19e7908d19bd194493aThomas Graf 86144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops rtnl_neigh_ops = { 86244d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_name = "route/neigh", 86344d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_hdrsize = sizeof(struct ndmsg), 86444d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_msgtypes = { 86544d362409d5469aed47d19e7908d19bd194493aThomas Graf { RTM_NEWNEIGH, NL_ACT_NEW, "new" }, 86644d362409d5469aed47d19e7908d19bd194493aThomas Graf { RTM_DELNEIGH, NL_ACT_DEL, "del" }, 86744d362409d5469aed47d19e7908d19bd194493aThomas Graf { RTM_GETNEIGH, NL_ACT_GET, "get" }, 86844d362409d5469aed47d19e7908d19bd194493aThomas Graf END_OF_MSGTYPES_LIST, 86944d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 87044d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_protocol = NETLINK_ROUTE, 87144d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_groups = neigh_groups, 87244d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_request_update = neigh_request_update, 87344d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_msg_parser = neigh_msg_parser, 87444d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_obj_ops = &neigh_obj_ops, 87544d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 87644d362409d5469aed47d19e7908d19bd194493aThomas Graf 87744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __init neigh_init(void) 87844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 87944d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cache_mngt_register(&rtnl_neigh_ops); 88044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 88144d362409d5469aed47d19e7908d19bd194493aThomas Graf 88244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __exit neigh_exit(void) 88344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 88444d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cache_mngt_unregister(&rtnl_neigh_ops); 88544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 88644d362409d5469aed47d19e7908d19bd194493aThomas Graf 88744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 888