Big routing code rework (API/ABI BREAK!)
Adds all missing routing attributes and brings the routing related code to a working state. In the process the API was broken several times with the justification that nobody is using this code yet. The changes include new example code which is also a prototype for how plain CLI tools could look like to control routes.
This commit is contained in:
parent
8ac78f1552
commit
535e831622
28 changed files with 1555 additions and 1087 deletions
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_LOCAL_TYPES_H_
|
||||
|
@ -104,7 +104,7 @@ struct genl_info
|
|||
struct nlattr ** attrs;
|
||||
};
|
||||
|
||||
#define LOOSE_FLAG_COMPARISON 1
|
||||
#define LOOSE_COMPARISON 1
|
||||
|
||||
#define NL_OBJ_MARK 1
|
||||
|
||||
|
@ -244,11 +244,6 @@ struct rtnl_addr
|
|||
uint32_t a_flag_mask;
|
||||
};
|
||||
|
||||
#define NEXTHOP_HAS_FLAGS 0x000001
|
||||
#define NEXTHOP_HAS_WEIGHT 0x000002
|
||||
#define NEXTHOP_HAS_IFINDEX 0x000004
|
||||
#define NEXTHOP_HAS_GATEWAY 0x000008
|
||||
|
||||
struct rtnl_nexthop
|
||||
{
|
||||
uint8_t rtnh_flags;
|
||||
|
@ -257,9 +252,9 @@ struct rtnl_nexthop
|
|||
/* 1 byte spare */
|
||||
uint32_t rtnh_ifindex;
|
||||
struct nl_addr * rtnh_gateway;
|
||||
uint32_t rtnh_mask;
|
||||
|
||||
uint32_t ce_mask; /* HACK to support attr macros */
|
||||
struct nl_list_head rtnh_list;
|
||||
uint32_t rtnh_realms;
|
||||
};
|
||||
|
||||
struct rtnl_route
|
||||
|
@ -270,24 +265,22 @@ struct rtnl_route
|
|||
uint8_t rt_dst_len;
|
||||
uint8_t rt_src_len;
|
||||
uint8_t rt_tos;
|
||||
uint8_t rt_table;
|
||||
uint8_t rt_protocol;
|
||||
uint8_t rt_scope;
|
||||
uint8_t rt_type;
|
||||
uint8_t rt_nmetrics;
|
||||
uint32_t rt_flags;
|
||||
struct nl_addr * rt_dst;
|
||||
struct nl_addr * rt_src;
|
||||
char rt_iif[IFNAMSIZ];
|
||||
uint32_t rt_oif;
|
||||
struct nl_addr * rt_gateway;
|
||||
uint32_t rt_table;
|
||||
uint32_t rt_iif;
|
||||
uint32_t rt_prio;
|
||||
uint32_t rt_metrics[RTAX_MAX];
|
||||
uint32_t rt_metrics_mask;
|
||||
uint32_t rt_nr_nh;
|
||||
struct nl_addr * rt_pref_src;
|
||||
struct nl_list_head rt_nexthops;
|
||||
realm_t rt_realms;
|
||||
struct rtnl_rtcacheinfo rt_cacheinfo;
|
||||
uint32_t rt_mp_algo;
|
||||
uint32_t rt_flag_mask;
|
||||
};
|
||||
|
||||
|
|
|
@ -68,6 +68,9 @@ static inline int nl_list_empty(struct nl_list_head *head)
|
|||
#define NL_LIST_HEAD(name) \
|
||||
struct nl_list_head name = { &(name), &(name) }
|
||||
|
||||
#define nl_list_first_entry(head, type, member) \
|
||||
nl_list_entry((head)->next, type, member)
|
||||
|
||||
#define nl_list_for_each_entry(pos, head, member) \
|
||||
for (pos = nl_list_entry((head)->next, typeof(*pos), member); \
|
||||
&(pos)->member != (head); \
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_ROUTE_NEXTHOP_H_
|
||||
|
@ -21,18 +21,42 @@ extern "C" {
|
|||
|
||||
struct rtnl_nexthop;
|
||||
|
||||
extern struct rtnl_nexthop * rtnl_route_nh_alloc(void);
|
||||
extern struct rtnl_nexthop * rtnl_route_nh_clone(struct rtnl_nexthop *);
|
||||
enum {
|
||||
NH_DUMP_FROM_ONELINE = -2,
|
||||
NH_DUMP_FROM_DETAILS = -1,
|
||||
NH_DUMP_FROM_ENV = 0,
|
||||
/* > 0 reserved for nexthop index */
|
||||
};
|
||||
|
||||
extern struct rtnl_nexthop * rtnl_route_nh_alloc(void);
|
||||
extern struct rtnl_nexthop * rtnl_route_nh_clone(struct rtnl_nexthop *);
|
||||
extern void rtnl_route_nh_free(struct rtnl_nexthop *);
|
||||
extern void rtnl_route_nh_set_weight(struct rtnl_nexthop *, int);
|
||||
|
||||
extern int rtnl_route_nh_compare(struct rtnl_nexthop *,
|
||||
struct rtnl_nexthop *,
|
||||
uint32_t, int);
|
||||
|
||||
extern void rtnl_route_nh_dump(struct rtnl_nexthop *,
|
||||
struct nl_dump_params *);
|
||||
|
||||
extern void rtnl_route_nh_set_weight(struct rtnl_nexthop *, uint8_t);
|
||||
extern uint8_t rtnl_route_nh_get_weight(struct rtnl_nexthop *);
|
||||
extern void rtnl_route_nh_set_ifindex(struct rtnl_nexthop *, int);
|
||||
extern int rtnl_route_nh_get_ifindex(struct rtnl_nexthop *);
|
||||
extern void rtnl_route_nh_set_gateway(struct rtnl_nexthop *,
|
||||
struct nl_addr *);
|
||||
extern struct nl_addr * rtnl_route_nh_get_gateway(struct rtnl_nexthop *);
|
||||
extern void rtnl_route_nh_set_flags(struct rtnl_nexthop *,
|
||||
unsigned int);
|
||||
extern void rtnl_route_nh_unset_flags(struct rtnl_nexthop *,
|
||||
unsigned int);
|
||||
extern unsigned int rtnl_route_nh_get_flags(struct rtnl_nexthop *);
|
||||
extern void rtnl_route_nh_set_realms(struct rtnl_nexthop *,
|
||||
uint32_t);
|
||||
extern uint32_t rtnl_route_nh_get_realms(struct rtnl_nexthop *);
|
||||
|
||||
extern char * rtnl_route_nh_flags2str(int, char *, size_t);
|
||||
extern int rtnl_route_nh_str2flags(const char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_ROUTE_H_
|
||||
|
@ -17,6 +17,7 @@
|
|||
#include <netlink/addr.h>
|
||||
#include <netlink/data.h>
|
||||
#include <netlink/route/nexthop.h>
|
||||
#include <netlink/route/rtnl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -46,63 +47,58 @@ extern struct nl_cache * rtnl_route_alloc_cache(struct nl_handle *);
|
|||
extern void rtnl_route_get(struct rtnl_route *);
|
||||
extern void rtnl_route_put(struct rtnl_route *);
|
||||
|
||||
extern struct rtnl_route *rtnl_route_parse(struct nlmsghdr *);
|
||||
extern int rtnl_route_build_msg(struct nl_msg *,
|
||||
struct rtnl_route *);
|
||||
|
||||
extern struct nl_msg *rtnl_route_build_add_request(struct rtnl_route *, int);
|
||||
extern int rtnl_route_add(struct nl_handle *, struct rtnl_route *, int);
|
||||
extern struct nl_msg *rtnl_route_build_del_request(struct rtnl_route *, int);
|
||||
extern int rtnl_route_del(struct nl_handle *, struct rtnl_route *, int);
|
||||
extern int rtnl_route_delete(struct nl_handle *, struct rtnl_route *, int);
|
||||
|
||||
extern void rtnl_route_set_table(struct rtnl_route *, int);
|
||||
extern int rtnl_route_get_table(struct rtnl_route *);
|
||||
extern void rtnl_route_set_scope(struct rtnl_route *, int);
|
||||
extern int rtnl_route_get_scope(struct rtnl_route *);
|
||||
extern void rtnl_route_set_tos(struct rtnl_route *, int);
|
||||
extern int rtnl_route_get_tos(struct rtnl_route *);
|
||||
extern void rtnl_route_set_realms(struct rtnl_route *, realm_t);
|
||||
extern realm_t rtnl_route_get_realms(struct rtnl_route *);
|
||||
extern void rtnl_route_set_protocol(struct rtnl_route *, int);
|
||||
extern int rtnl_route_get_protocol(struct rtnl_route *);
|
||||
extern void rtnl_route_set_prio(struct rtnl_route *, int);
|
||||
extern int rtnl_route_get_prio(struct rtnl_route *);
|
||||
extern void rtnl_route_set_family(struct rtnl_route *, int);
|
||||
extern int rtnl_route_get_family(struct rtnl_route *);
|
||||
extern void rtnl_route_set_type(struct rtnl_route *, int);
|
||||
extern int rtnl_route_get_type(struct rtnl_route *);
|
||||
extern void rtnl_route_set_flags(struct rtnl_route *,
|
||||
unsigned int);
|
||||
extern void rtnl_route_unset_flags(struct rtnl_route *,
|
||||
unsigned int);
|
||||
extern unsigned int rtnl_route_get_flags(struct rtnl_route *);
|
||||
extern void rtnl_route_set_table(struct rtnl_route *, uint32_t);
|
||||
extern uint32_t rtnl_route_get_table(struct rtnl_route *);
|
||||
extern void rtnl_route_set_scope(struct rtnl_route *, uint8_t);
|
||||
extern uint8_t rtnl_route_get_scope(struct rtnl_route *);
|
||||
extern void rtnl_route_set_tos(struct rtnl_route *, uint8_t);
|
||||
extern uint8_t rtnl_route_get_tos(struct rtnl_route *);
|
||||
extern void rtnl_route_set_protocol(struct rtnl_route *, uint8_t);
|
||||
extern uint8_t rtnl_route_get_protocol(struct rtnl_route *);
|
||||
extern void rtnl_route_set_priority(struct rtnl_route *, uint32_t);
|
||||
extern uint32_t rtnl_route_get_priority(struct rtnl_route *);
|
||||
extern int rtnl_route_set_family(struct rtnl_route *, uint8_t);
|
||||
extern uint8_t rtnl_route_get_family(struct rtnl_route *);
|
||||
extern int rtnl_route_set_type(struct rtnl_route *, uint8_t);
|
||||
extern uint8_t rtnl_route_get_type(struct rtnl_route *);
|
||||
extern void rtnl_route_set_flags(struct rtnl_route *, uint32_t);
|
||||
extern void rtnl_route_unset_flags(struct rtnl_route *, uint32_t);
|
||||
extern uint32_t rtnl_route_get_flags(struct rtnl_route *);
|
||||
extern int rtnl_route_set_metric(struct rtnl_route *, int,
|
||||
unsigned int);
|
||||
extern int rtnl_route_unset_metric(struct rtnl_route *, int);
|
||||
extern unsigned int rtnl_route_get_metric(struct rtnl_route *, int);
|
||||
extern int rtnl_route_get_metric(struct rtnl_route *, int,
|
||||
uint32_t *);
|
||||
extern int rtnl_route_set_dst(struct rtnl_route *,
|
||||
struct nl_addr *);
|
||||
extern struct nl_addr * rtnl_route_get_dst(struct rtnl_route *);
|
||||
extern int rtnl_route_set_src(struct rtnl_route *,
|
||||
struct nl_addr *);
|
||||
extern struct nl_addr * rtnl_route_get_src(struct rtnl_route *);
|
||||
extern int rtnl_route_set_gateway(struct rtnl_route *,
|
||||
struct nl_addr *);
|
||||
extern struct nl_addr * rtnl_route_get_gateway(struct rtnl_route *);
|
||||
extern int rtnl_route_set_pref_src(struct rtnl_route *,
|
||||
struct nl_addr *);
|
||||
extern struct nl_addr * rtnl_route_get_pref_src(struct rtnl_route *);
|
||||
extern void rtnl_route_set_oif(struct rtnl_route *, int);
|
||||
extern int rtnl_route_get_oif(struct rtnl_route *);
|
||||
extern void rtnl_route_set_iif(struct rtnl_route *, const char *);
|
||||
extern char * rtnl_route_get_iif(struct rtnl_route *);
|
||||
extern int rtnl_route_get_dst_len(struct rtnl_route *);
|
||||
extern void rtnl_route_set_iif(struct rtnl_route *, int);
|
||||
extern int rtnl_route_get_iif(struct rtnl_route *);
|
||||
extern int rtnl_route_get_src_len(struct rtnl_route *);
|
||||
|
||||
extern void rtnl_route_add_nexthop(struct rtnl_route *,
|
||||
struct rtnl_nexthop *);
|
||||
extern void rtnl_route_remove_nexthop(struct rtnl_nexthop *);
|
||||
extern void rtnl_route_remove_nexthop(struct rtnl_route *,
|
||||
struct rtnl_nexthop *);
|
||||
extern struct nl_list_head * rtnl_route_get_nexthops(struct rtnl_route *);
|
||||
extern void rtnl_route_set_cacheinfo(struct rtnl_route *,
|
||||
struct rtnl_rtcacheinfo *);
|
||||
extern uint32_t rtnl_route_get_mp_algo(struct rtnl_route *);
|
||||
extern void rtnl_route_set_mp_algo(struct rtnl_route *, uint32_t);
|
||||
extern int rtnl_route_get_nnexthops(struct rtnl_route *);
|
||||
|
||||
extern int rtnl_route_guess_scope(struct rtnl_route *);
|
||||
|
||||
extern char * rtnl_route_table2str(int, char *, size_t);
|
||||
extern int rtnl_route_str2table(const char *);
|
||||
|
@ -115,9 +111,6 @@ extern int rtnl_route_read_protocol_names(const char *);
|
|||
extern char * rtnl_route_metric2str(int, char *, size_t);
|
||||
extern int rtnl_route_str2metric(const char *);
|
||||
|
||||
extern char * rtnl_route_nh_flags2str(int, char *, size_t);
|
||||
extern int rtnl_route_nh_str2flags(const char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -23,8 +23,6 @@ extern "C" {
|
|||
* @{
|
||||
*/
|
||||
|
||||
typedef uint32_t realm_t;
|
||||
|
||||
/**
|
||||
* Mask specying the size of each realm part
|
||||
* @ingroup rtnl
|
||||
|
|
|
@ -69,8 +69,8 @@ extern char * rtnl_rule_get_iif(struct rtnl_rule *);
|
|||
extern void rtnl_rule_set_classid(struct rtnl_rule *, uint32_t);
|
||||
extern uint32_t rtnl_rule_get_classid(struct rtnl_rule *);
|
||||
|
||||
extern void rtnl_rule_set_realms(struct rtnl_rule *, realm_t);
|
||||
extern realm_t rtnl_rule_get_realms(struct rtnl_rule *);
|
||||
extern void rtnl_rule_set_realms(struct rtnl_rule *, uint32_t);
|
||||
extern uint32_t rtnl_rule_get_realms(struct rtnl_rule *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -197,7 +197,7 @@ static int ct_compare(struct nl_object *_a, struct nl_object *_b,
|
|||
#define CT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, CT_ATTR_##ATTR, a, b, EXPR)
|
||||
#define CT_DIFF_VAL(ATTR, FIELD) CT_DIFF(ATTR, a->FIELD != b->FIELD)
|
||||
#define CT_DIFF_ADDR(ATTR, FIELD) \
|
||||
((flags & LOOSE_FLAG_COMPARISON) \
|
||||
((flags & LOOSE_COMPARISON) \
|
||||
? CT_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \
|
||||
: CT_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD)))
|
||||
|
||||
|
@ -227,7 +227,7 @@ static int ct_compare(struct nl_object *_a, struct nl_object *_b,
|
|||
diff |= CT_DIFF_VAL(REPL_PACKETS, ct_repl.packets);
|
||||
diff |= CT_DIFF_VAL(REPL_BYTES, ct_repl.bytes);
|
||||
|
||||
if (flags & LOOSE_FLAG_COMPARISON)
|
||||
if (flags & LOOSE_COMPARISON)
|
||||
diff |= CT_DIFF(STATUS, (a->ct_status ^ b->ct_status) &
|
||||
b->ct_status_mask);
|
||||
else
|
||||
|
|
|
@ -318,7 +318,7 @@ int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter)
|
|||
return 0;
|
||||
|
||||
return !(ops->oo_compare(obj, filter, filter->ce_mask,
|
||||
LOOSE_FLAG_COMPARISON));
|
||||
LOOSE_COMPARISON));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -585,7 +585,7 @@ static int addr_compare(struct nl_object *_a, struct nl_object *_b,
|
|||
b->a_multicast));
|
||||
diff |= ADDR_DIFF(BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast));
|
||||
|
||||
if (flags & LOOSE_FLAG_COMPARISON)
|
||||
if (flags & LOOSE_COMPARISON)
|
||||
diff |= ADDR_DIFF(FLAGS,
|
||||
(a->a_flags ^ b->a_flags) & b->a_flag_mask);
|
||||
else
|
||||
|
|
|
@ -795,7 +795,7 @@ static int link_compare(struct nl_object *_a, struct nl_object *_b,
|
|||
diff |= LINK_DIFF(ADDR, nl_addr_cmp(a->l_addr, b->l_addr));
|
||||
diff |= LINK_DIFF(BRD, nl_addr_cmp(a->l_bcast, b->l_bcast));
|
||||
|
||||
if (flags & LOOSE_FLAG_COMPARISON)
|
||||
if (flags & LOOSE_COMPARISON)
|
||||
diff |= LINK_DIFF(FLAGS,
|
||||
(a->l_flags ^ b->l_flags) & b->l_flag_mask);
|
||||
else
|
||||
|
|
|
@ -213,7 +213,7 @@ static int neigh_compare(struct nl_object *_a, struct nl_object *_b,
|
|||
diff |= NEIGH_DIFF(LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr));
|
||||
diff |= NEIGH_DIFF(DST, nl_addr_cmp(a->n_dst, b->n_dst));
|
||||
|
||||
if (flags & LOOSE_FLAG_COMPARISON) {
|
||||
if (flags & LOOSE_COMPARISON) {
|
||||
diff |= NEIGH_DIFF(STATE,
|
||||
(a->n_state ^ b->n_state) & b->n_state_mask);
|
||||
diff |= NEIGH_DIFF(FLAGS,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -21,6 +21,14 @@
|
|||
#include <netlink/route/rtnl.h>
|
||||
#include <netlink/route/route.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
#define NH_ATTR_FLAGS 0x000001
|
||||
#define NH_ATTR_WEIGHT 0x000002
|
||||
#define NH_ATTR_IFINDEX 0x000004
|
||||
#define NH_ATTR_GATEWAY 0x000008
|
||||
#define NH_ATTR_REALMS 0x000010
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @name Allocation/Freeing
|
||||
* @{
|
||||
|
@ -53,7 +61,7 @@ struct rtnl_nexthop *rtnl_route_nh_clone(struct rtnl_nexthop *src)
|
|||
nh->rtnh_flag_mask = src->rtnh_flag_mask;
|
||||
nh->rtnh_weight = src->rtnh_weight;
|
||||
nh->rtnh_ifindex = src->rtnh_ifindex;
|
||||
nh->rtnh_mask = src->rtnh_mask;
|
||||
nh->ce_mask = src->ce_mask;
|
||||
|
||||
if (src->rtnh_gateway) {
|
||||
nh->rtnh_gateway = nl_addr_clone(src->rtnh_gateway);
|
||||
|
@ -74,78 +82,251 @@ void rtnl_route_nh_free(struct rtnl_nexthop *nh)
|
|||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Attributes
|
||||
*/
|
||||
|
||||
void rtnl_route_nh_set_weight(struct rtnl_nexthop *nh, int weight)
|
||||
int rtnl_route_nh_compare(struct rtnl_nexthop *a, struct rtnl_nexthop *b,
|
||||
uint32_t attrs, int loose)
|
||||
{
|
||||
nh->rtnh_weight = weight;
|
||||
nh->rtnh_mask |= NEXTHOP_HAS_WEIGHT;
|
||||
int diff = 0;
|
||||
|
||||
#define NH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NH_ATTR_##ATTR, a, b, EXPR)
|
||||
|
||||
diff |= NH_DIFF(IFINDEX, a->rtnh_ifindex != b->rtnh_ifindex);
|
||||
diff |= NH_DIFF(WEIGHT, a->rtnh_weight != b->rtnh_weight);
|
||||
diff |= NH_DIFF(REALMS, a->rtnh_realms != b->rtnh_realms);
|
||||
diff |= NH_DIFF(GATEWAY, nl_addr_cmp(a->rtnh_gateway,
|
||||
b->rtnh_gateway));
|
||||
|
||||
if (loose)
|
||||
diff |= NH_DIFF(FLAGS,
|
||||
(a->rtnh_flags ^ b->rtnh_flags) & b->rtnh_flag_mask);
|
||||
else
|
||||
diff |= NH_DIFF(FLAGS, a->rtnh_flags != b->rtnh_flags);
|
||||
|
||||
#undef NH_DIFF
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
int rtnl_route_nh_get_weight(struct rtnl_nexthop *nh)
|
||||
static void nh_dump_oneline(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
|
||||
{
|
||||
if (nh->rtnh_mask & NEXTHOP_HAS_WEIGHT)
|
||||
return nh->rtnh_weight;
|
||||
else
|
||||
return 0;
|
||||
struct nl_cache *link_cache;
|
||||
char buf[128];
|
||||
|
||||
link_cache = nl_cache_mngt_require("route/link");
|
||||
|
||||
nl_dump(dp, "via");
|
||||
|
||||
if (nh->ce_mask & NH_ATTR_GATEWAY)
|
||||
nl_dump(dp, " %s", nl_addr2str(nh->rtnh_gateway,
|
||||
buf, sizeof(buf)));
|
||||
|
||||
if(nh->ce_mask & NH_ATTR_IFINDEX) {
|
||||
if (link_cache) {
|
||||
nl_dump(dp, " dev %s",
|
||||
rtnl_link_i2name(link_cache,
|
||||
nh->rtnh_ifindex,
|
||||
buf, sizeof(buf)));
|
||||
} else
|
||||
nl_dump(dp, " dev %d", nh->rtnh_ifindex);
|
||||
}
|
||||
|
||||
nl_dump(dp, " ");
|
||||
}
|
||||
|
||||
static void nh_dump_details(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
|
||||
{
|
||||
struct nl_cache *link_cache;
|
||||
char buf[128];
|
||||
|
||||
link_cache = nl_cache_mngt_require("route/link");
|
||||
|
||||
nl_dump(dp, "nexthop");
|
||||
|
||||
if (nh->ce_mask & NH_ATTR_GATEWAY)
|
||||
nl_dump(dp, " via %s", nl_addr2str(nh->rtnh_gateway,
|
||||
buf, sizeof(buf)));
|
||||
|
||||
if(nh->ce_mask & NH_ATTR_IFINDEX) {
|
||||
if (link_cache) {
|
||||
nl_dump(dp, " dev %s",
|
||||
rtnl_link_i2name(link_cache,
|
||||
nh->rtnh_ifindex,
|
||||
buf, sizeof(buf)));
|
||||
} else
|
||||
nl_dump(dp, " dev %d", nh->rtnh_ifindex);
|
||||
}
|
||||
|
||||
if (nh->ce_mask & NH_ATTR_WEIGHT)
|
||||
nl_dump(dp, " weight %u", nh->rtnh_weight);
|
||||
|
||||
if (nh->ce_mask & NH_ATTR_REALMS)
|
||||
nl_dump(dp, " realm %04x:%04x",
|
||||
RTNL_REALM_FROM(nh->rtnh_realms),
|
||||
RTNL_REALM_TO(nh->rtnh_realms));
|
||||
|
||||
if (nh->ce_mask & NH_ATTR_FLAGS)
|
||||
nl_dump(dp, " <%s>", rtnl_route_nh_flags2str(nh->rtnh_flags,
|
||||
buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
static void nh_dump_env(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
|
||||
{
|
||||
struct nl_cache *link_cache;
|
||||
char buf[128];
|
||||
|
||||
link_cache = nl_cache_mngt_require("route/link");
|
||||
|
||||
if (nh->ce_mask & NH_ATTR_GATEWAY)
|
||||
nl_dump_line(dp, "ROUTE_NH%d_VIA=%s\n", dp->dp_ivar,
|
||||
nl_addr2str(nh->rtnh_gateway, buf, sizeof(buf)));
|
||||
|
||||
if(nh->ce_mask & NH_ATTR_IFINDEX) {
|
||||
if (link_cache) {
|
||||
nl_dump_line(dp, "ROUTE_NH%d_DEV=%s\n", dp->dp_ivar,
|
||||
rtnl_link_i2name(link_cache,
|
||||
nh->rtnh_ifindex,
|
||||
buf, sizeof(buf)));
|
||||
} else
|
||||
nl_dump_line(dp, "ROUTE_NH%d_DEV=%d\n", dp->dp_ivar,
|
||||
nh->rtnh_ifindex);
|
||||
}
|
||||
|
||||
if (nh->ce_mask & NH_ATTR_WEIGHT)
|
||||
nl_dump_line(dp, "ROUTE_NH%d_WEIGHT=%u\n", dp->dp_ivar,
|
||||
nh->rtnh_weight);
|
||||
|
||||
if (nh->ce_mask & NH_ATTR_REALMS)
|
||||
nl_dump_line(dp, "ROUTE_NH%d_REALM=%04x:%04x\n", dp->dp_ivar,
|
||||
RTNL_REALM_FROM(nh->rtnh_realms),
|
||||
RTNL_REALM_TO(nh->rtnh_realms));
|
||||
|
||||
if (nh->ce_mask & NH_ATTR_FLAGS)
|
||||
nl_dump_line(dp, "ROUTE_NH%d_FLAGS=<%s>\n", dp->dp_ivar,
|
||||
rtnl_route_nh_flags2str(nh->rtnh_flags,
|
||||
buf, sizeof(buf)));
|
||||
}
|
||||
void rtnl_route_nh_dump(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
|
||||
{
|
||||
switch (dp->dp_type) {
|
||||
case NL_DUMP_ONELINE:
|
||||
nh_dump_oneline(nh, dp);
|
||||
break;
|
||||
|
||||
case NL_DUMP_DETAILS:
|
||||
case NL_DUMP_STATS:
|
||||
if (dp->dp_ivar == NH_DUMP_FROM_DETAILS)
|
||||
nh_dump_details(nh, dp);
|
||||
break;
|
||||
|
||||
case NL_DUMP_ENV:
|
||||
nh_dump_env(nh, dp);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Attributes
|
||||
* @{
|
||||
*/
|
||||
|
||||
void rtnl_route_nh_set_weight(struct rtnl_nexthop *nh, uint8_t weight)
|
||||
{
|
||||
nh->rtnh_weight = weight;
|
||||
nh->ce_mask |= NH_ATTR_WEIGHT;
|
||||
}
|
||||
|
||||
uint8_t rtnl_route_nh_get_weight(struct rtnl_nexthop *nh)
|
||||
{
|
||||
return nh->rtnh_weight;
|
||||
}
|
||||
|
||||
void rtnl_route_nh_set_ifindex(struct rtnl_nexthop *nh, int ifindex)
|
||||
{
|
||||
nh->rtnh_ifindex = ifindex;
|
||||
nh->rtnh_mask |= NEXTHOP_HAS_IFINDEX;
|
||||
nh->ce_mask |= NH_ATTR_IFINDEX;
|
||||
}
|
||||
|
||||
int rtnl_route_nh_get_ifindex(struct rtnl_nexthop *nh)
|
||||
{
|
||||
if (nh->rtnh_mask & NEXTHOP_HAS_IFINDEX)
|
||||
return nh->rtnh_ifindex;
|
||||
else
|
||||
return -1;
|
||||
return nh->rtnh_ifindex;
|
||||
}
|
||||
|
||||
void rtnl_route_nh_set_gateway(struct rtnl_nexthop *nh, struct nl_addr *addr)
|
||||
{
|
||||
struct nl_addr *old = nh->rtnh_gateway;
|
||||
|
||||
nh->rtnh_gateway = nl_addr_get(addr);
|
||||
if (addr) {
|
||||
nh->rtnh_gateway = nl_addr_get(addr);
|
||||
nh->ce_mask |= NH_ATTR_GATEWAY;
|
||||
} else {
|
||||
nh->ce_mask &= ~NH_ATTR_GATEWAY;
|
||||
nh->rtnh_gateway = NULL;
|
||||
}
|
||||
|
||||
if (old)
|
||||
nl_addr_put(old);
|
||||
|
||||
nh->rtnh_mask |= NEXTHOP_HAS_GATEWAY;
|
||||
}
|
||||
|
||||
struct nl_addr *rtnl_route_nh_get_gateway(struct rtnl_nexthop *nh)
|
||||
{
|
||||
if (nh->rtnh_mask & NEXTHOP_HAS_GATEWAY)
|
||||
return nh->rtnh_gateway;
|
||||
else
|
||||
return NULL;
|
||||
return nh->rtnh_gateway;
|
||||
}
|
||||
|
||||
void rtnl_route_nh_set_flags(struct rtnl_nexthop *nh, unsigned int flags)
|
||||
{
|
||||
nh->rtnh_flag_mask |= flags;
|
||||
nh->rtnh_flags |= flags;
|
||||
nh->rtnh_mask |= NEXTHOP_HAS_FLAGS;
|
||||
nh->ce_mask |= NH_ATTR_FLAGS;
|
||||
}
|
||||
|
||||
void rtnl_route_nh_unset_flags(struct rtnl_nexthop *nh, unsigned int flags)
|
||||
{
|
||||
nh->rtnh_flag_mask |= flags;
|
||||
nh->rtnh_flags &= ~flags;
|
||||
nh->rtnh_mask |= NEXTHOP_HAS_FLAGS;
|
||||
nh->ce_mask |= NH_ATTR_FLAGS;
|
||||
}
|
||||
|
||||
unsigned int rtnl_route_nh_get_flags(struct rtnl_nexthop *nh)
|
||||
{
|
||||
if (nh->rtnh_mask & NEXTHOP_HAS_FLAGS)
|
||||
return nh->rtnh_flags;
|
||||
else
|
||||
return 0;
|
||||
return nh->rtnh_flags;
|
||||
}
|
||||
|
||||
void rtnl_route_nh_set_realms(struct rtnl_nexthop *nh, uint32_t realms)
|
||||
{
|
||||
nh->rtnh_realms = realms;
|
||||
nh->ce_mask |= NH_ATTR_REALMS;
|
||||
}
|
||||
|
||||
uint32_t rtnl_route_nh_get_realms(struct rtnl_nexthop *nh)
|
||||
{
|
||||
return nh->rtnh_realms;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Nexthop Flags Translations
|
||||
* @{
|
||||
*/
|
||||
|
||||
static struct trans_tbl nh_flags[] = {
|
||||
__ADD(RTNH_F_DEAD, dead)
|
||||
__ADD(RTNH_F_PERVASIVE, pervasive)
|
||||
__ADD(RTNH_F_ONLINK, onlink)
|
||||
};
|
||||
|
||||
char *rtnl_route_nh_flags2str(int flags, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(flags, buf, len, nh_flags, ARRAY_SIZE(nh_flags));
|
||||
}
|
||||
|
||||
int rtnl_route_nh_str2flags(const char *name)
|
||||
{
|
||||
return __str2flags(name, nh_flags, ARRAY_SIZE(nh_flags));
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -27,183 +27,16 @@
|
|||
|
||||
static struct nl_cache_ops rtnl_route_ops;
|
||||
|
||||
static struct nla_policy route_policy[RTA_MAX+1] = {
|
||||
[RTA_IIF] = { .type = NLA_STRING,
|
||||
.maxlen = IFNAMSIZ, },
|
||||
[RTA_OIF] = { .type = NLA_U32 },
|
||||
[RTA_PRIORITY] = { .type = NLA_U32 },
|
||||
[RTA_FLOW] = { .type = NLA_U32 },
|
||||
[RTA_MP_ALGO] = { .type = NLA_U32 },
|
||||
[RTA_CACHEINFO] = { .minlen = sizeof(struct rta_cacheinfo) },
|
||||
[RTA_METRICS] = { .type = NLA_NESTED },
|
||||
[RTA_MULTIPATH] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static void copy_cacheinfo_into_route(struct rta_cacheinfo *ci,
|
||||
struct rtnl_route *route)
|
||||
{
|
||||
struct rtnl_rtcacheinfo nci = {
|
||||
.rtci_clntref = ci->rta_clntref,
|
||||
.rtci_last_use = ci->rta_lastuse,
|
||||
.rtci_expires = ci->rta_expires,
|
||||
.rtci_error = ci->rta_error,
|
||||
.rtci_used = ci->rta_used,
|
||||
.rtci_id = ci->rta_id,
|
||||
.rtci_ts = ci->rta_ts,
|
||||
.rtci_tsage = ci->rta_tsage,
|
||||
};
|
||||
|
||||
rtnl_route_set_cacheinfo(route, &nci);
|
||||
}
|
||||
|
||||
static int route_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
||||
struct nlmsghdr *nlh, struct nl_parser_param *pp)
|
||||
{
|
||||
struct rtmsg *rtm;
|
||||
struct rtnl_route *route;
|
||||
struct nlattr *tb[RTA_MAX + 1];
|
||||
struct nl_addr *src = NULL, *dst = NULL, *addr;
|
||||
int err;
|
||||
|
||||
route = rtnl_route_alloc();
|
||||
if (!route) {
|
||||
err = nl_errno(ENOMEM);
|
||||
goto errout;
|
||||
}
|
||||
if (!(route = rtnl_route_parse(nlh)))
|
||||
return -EINVAL;
|
||||
|
||||
route->ce_msgtype = nlh->nlmsg_type;
|
||||
|
||||
err = nlmsg_parse(nlh, sizeof(struct rtmsg), tb, RTA_MAX,
|
||||
route_policy);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
rtm = nlmsg_data(nlh);
|
||||
rtnl_route_set_family(route, rtm->rtm_family);
|
||||
rtnl_route_set_tos(route, rtm->rtm_tos);
|
||||
rtnl_route_set_table(route, rtm->rtm_table);
|
||||
rtnl_route_set_type(route, rtm->rtm_type);
|
||||
rtnl_route_set_scope(route, rtm->rtm_scope);
|
||||
rtnl_route_set_protocol(route, rtm->rtm_protocol);
|
||||
rtnl_route_set_flags(route, rtm->rtm_flags);
|
||||
|
||||
if (tb[RTA_DST]) {
|
||||
dst = nla_get_addr(tb[RTA_DST], rtm->rtm_family);
|
||||
if (dst == NULL)
|
||||
goto errout_errno;
|
||||
} else {
|
||||
dst = nl_addr_alloc(0);
|
||||
nl_addr_set_family(dst, rtm->rtm_family);
|
||||
}
|
||||
|
||||
nl_addr_set_prefixlen(dst, rtm->rtm_dst_len);
|
||||
err = rtnl_route_set_dst(route, dst);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
nl_addr_put(dst);
|
||||
|
||||
if (tb[RTA_SRC]) {
|
||||
src = nla_get_addr(tb[RTA_SRC], rtm->rtm_family);
|
||||
if (src == NULL)
|
||||
goto errout_errno;
|
||||
} else if (rtm->rtm_src_len)
|
||||
src = nl_addr_alloc(0);
|
||||
|
||||
if (src) {
|
||||
nl_addr_set_prefixlen(src, rtm->rtm_src_len);
|
||||
rtnl_route_set_src(route, src);
|
||||
nl_addr_put(src);
|
||||
}
|
||||
|
||||
if (tb[RTA_IIF])
|
||||
rtnl_route_set_iif(route, nla_get_string(tb[RTA_IIF]));
|
||||
|
||||
if (tb[RTA_OIF])
|
||||
rtnl_route_set_oif(route, nla_get_u32(tb[RTA_OIF]));
|
||||
|
||||
if (tb[RTA_GATEWAY]) {
|
||||
addr = nla_get_addr(tb[RTA_GATEWAY], route->rt_family);
|
||||
if (addr == NULL)
|
||||
goto errout_errno;
|
||||
rtnl_route_set_gateway(route, addr);
|
||||
nl_addr_put(addr);
|
||||
}
|
||||
|
||||
if (tb[RTA_PRIORITY])
|
||||
rtnl_route_set_prio(route, nla_get_u32(tb[RTA_PRIORITY]));
|
||||
|
||||
if (tb[RTA_PREFSRC]) {
|
||||
addr = nla_get_addr(tb[RTA_PREFSRC], route->rt_family);
|
||||
if (addr == NULL)
|
||||
goto errout_errno;
|
||||
rtnl_route_set_pref_src(route, addr);
|
||||
nl_addr_put(addr);
|
||||
}
|
||||
|
||||
if (tb[RTA_METRICS]) {
|
||||
struct nlattr *mtb[RTAX_MAX + 1];
|
||||
int i;
|
||||
|
||||
err = nla_parse_nested(mtb, RTAX_MAX, tb[RTA_METRICS], NULL);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
for (i = 1; i <= RTAX_MAX; i++) {
|
||||
if (mtb[i] && nla_len(mtb[i]) >= sizeof(uint32_t)) {
|
||||
uint32_t m = nla_get_u32(mtb[i]);
|
||||
if (rtnl_route_set_metric(route, i, m) < 0)
|
||||
goto errout_errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[RTA_MULTIPATH]) {
|
||||
struct rtnl_nexthop *nh;
|
||||
struct rtnexthop *rtnh = nla_data(tb[RTA_MULTIPATH]);
|
||||
size_t tlen = nla_len(tb[RTA_MULTIPATH]);
|
||||
|
||||
while (tlen >= sizeof(*rtnh) && tlen >= rtnh->rtnh_len) {
|
||||
nh = rtnl_route_nh_alloc();
|
||||
if (!nh)
|
||||
goto errout;
|
||||
|
||||
rtnl_route_nh_set_weight(nh, rtnh->rtnh_hops);
|
||||
rtnl_route_nh_set_ifindex(nh, rtnh->rtnh_ifindex);
|
||||
rtnl_route_nh_set_flags(nh, rtnh->rtnh_flags);
|
||||
|
||||
if (rtnh->rtnh_len > sizeof(*rtnh)) {
|
||||
struct nlattr *ntb[RTA_MAX + 1];
|
||||
nla_parse(ntb, RTA_MAX, (struct nlattr *)
|
||||
RTNH_DATA(rtnh),
|
||||
rtnh->rtnh_len - sizeof(*rtnh),
|
||||
route_policy);
|
||||
|
||||
if (ntb[RTA_GATEWAY]) {
|
||||
nh->rtnh_gateway = nla_get_addr(
|
||||
ntb[RTA_GATEWAY],
|
||||
route->rt_family);
|
||||
nh->rtnh_mask = NEXTHOP_HAS_GATEWAY;
|
||||
}
|
||||
}
|
||||
|
||||
rtnl_route_add_nexthop(route, nh);
|
||||
tlen -= RTNH_ALIGN(rtnh->rtnh_len);
|
||||
rtnh = RTNH_NEXT(rtnh);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[RTA_FLOW])
|
||||
rtnl_route_set_realms(route, nla_get_u32(tb[RTA_FLOW]));
|
||||
|
||||
if (tb[RTA_CACHEINFO])
|
||||
copy_cacheinfo_into_route(nla_data(tb[RTA_CACHEINFO]), route);
|
||||
|
||||
if (tb[RTA_MP_ALGO])
|
||||
rtnl_route_set_mp_algo(route, nla_get_u32(tb[RTA_MP_ALGO]));
|
||||
|
||||
err = pp->pp_cb((struct nl_object *) route, pp);
|
||||
if (err < 0)
|
||||
if ((err = pp->pp_cb((struct nl_object *) route, pp)) < 0)
|
||||
goto errout;
|
||||
|
||||
err = P_ACCEPT;
|
||||
|
@ -211,10 +44,6 @@ static int route_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
|||
errout:
|
||||
rtnl_route_put(route);
|
||||
return err;
|
||||
|
||||
errout_errno:
|
||||
err = nl_get_errno();
|
||||
goto errout;
|
||||
}
|
||||
|
||||
static int route_request_update(struct nl_cache *c, struct nl_handle *h)
|
||||
|
@ -265,102 +94,17 @@ static struct nl_msg *build_route_msg(struct rtnl_route *tmpl, int cmd,
|
|||
int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
struct nl_addr *addr;
|
||||
int scope, i, oif, nmetrics = 0;
|
||||
struct nlattr *metrics;
|
||||
struct rtmsg rtmsg = {
|
||||
.rtm_family = rtnl_route_get_family(tmpl),
|
||||
.rtm_dst_len = rtnl_route_get_dst_len(tmpl),
|
||||
.rtm_src_len = rtnl_route_get_src_len(tmpl),
|
||||
.rtm_tos = rtnl_route_get_tos(tmpl),
|
||||
.rtm_table = rtnl_route_get_table(tmpl),
|
||||
.rtm_type = rtnl_route_get_type(tmpl),
|
||||
.rtm_protocol = rtnl_route_get_protocol(tmpl),
|
||||
.rtm_flags = rtnl_route_get_flags(tmpl),
|
||||
};
|
||||
|
||||
if (rtmsg.rtm_family == AF_UNSPEC) {
|
||||
nl_error(EINVAL, "Cannot build route message, address " \
|
||||
"family is unknown.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scope = rtnl_route_get_scope(tmpl);
|
||||
if (scope == RT_SCOPE_NOWHERE) {
|
||||
if (rtmsg.rtm_type == RTN_LOCAL)
|
||||
scope = RT_SCOPE_HOST;
|
||||
else {
|
||||
/* XXX Change to UNIVERSE if gw || nexthops */
|
||||
scope = RT_SCOPE_LINK;
|
||||
}
|
||||
}
|
||||
|
||||
rtmsg.rtm_scope = scope;
|
||||
|
||||
msg = nlmsg_alloc_simple(cmd, flags);
|
||||
if (msg == NULL)
|
||||
return NULL;
|
||||
|
||||
if (nlmsg_append(msg, &rtmsg, sizeof(rtmsg), NLMSG_ALIGNTO) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
addr = rtnl_route_get_dst(tmpl);
|
||||
if (addr)
|
||||
NLA_PUT_ADDR(msg, RTA_DST, addr);
|
||||
|
||||
addr = rtnl_route_get_src(tmpl);
|
||||
if (addr)
|
||||
NLA_PUT_ADDR(msg, RTA_SRC, addr);
|
||||
|
||||
addr = rtnl_route_get_gateway(tmpl);
|
||||
if (addr)
|
||||
NLA_PUT_ADDR(msg, RTA_GATEWAY, addr);
|
||||
|
||||
addr = rtnl_route_get_pref_src(tmpl);
|
||||
if (addr)
|
||||
NLA_PUT_ADDR(msg, RTA_PREFSRC, addr);
|
||||
|
||||
NLA_PUT_U32(msg, RTA_PRIORITY, rtnl_route_get_prio(tmpl));
|
||||
|
||||
oif = rtnl_route_get_oif(tmpl);
|
||||
if (oif != RTNL_LINK_NOT_FOUND)
|
||||
NLA_PUT_U32(msg, RTA_OIF, oif);
|
||||
|
||||
for (i = 1; i <= RTAX_MAX; i++)
|
||||
if (rtnl_route_get_metric(tmpl, i) != UINT_MAX)
|
||||
nmetrics++;
|
||||
|
||||
if (nmetrics > 0) {
|
||||
unsigned int val;
|
||||
|
||||
metrics = nla_nest_start(msg, RTA_METRICS);
|
||||
if (metrics == NULL)
|
||||
goto nla_put_failure;
|
||||
|
||||
for (i = 1; i <= RTAX_MAX; i++) {
|
||||
val = rtnl_route_get_metric(tmpl, i);
|
||||
if (val != UINT_MAX)
|
||||
NLA_PUT_U32(msg, i, val);
|
||||
}
|
||||
|
||||
nla_nest_end(msg, metrics);
|
||||
if (rtnl_route_build_msg(msg, tmpl) < 0) {
|
||||
nlmsg_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
RTA_IIF,
|
||||
RTA_MULTIPATH,
|
||||
RTA_PROTOINFO,
|
||||
RTA_FLOW,
|
||||
RTA_CACHEINFO,
|
||||
RTA_SESSION,
|
||||
RTA_MP_ALGO,
|
||||
#endif
|
||||
|
||||
return msg;
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct nl_msg *rtnl_route_build_add_request(struct rtnl_route *tmpl, int flags)
|
||||
|
@ -391,8 +135,8 @@ struct nl_msg *rtnl_route_build_del_request(struct rtnl_route *tmpl, int flags)
|
|||
return build_route_msg(tmpl, RTM_DELROUTE, flags);
|
||||
}
|
||||
|
||||
int rtnl_route_del(struct nl_handle *handle, struct rtnl_route *route,
|
||||
int flags)
|
||||
int rtnl_route_delete(struct nl_handle *handle, struct rtnl_route *route,
|
||||
int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -167,27 +167,4 @@ int rtnl_route_str2metric(const char *name)
|
|||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Nexthop Flags Translations
|
||||
* @{
|
||||
*/
|
||||
|
||||
static struct trans_tbl nh_flags[] = {
|
||||
__ADD(RTNH_F_DEAD, dead)
|
||||
__ADD(RTNH_F_PERVASIVE, pervasive)
|
||||
__ADD(RTNH_F_ONLINK, onlink)
|
||||
};
|
||||
|
||||
char * rtnl_route_nh_flags2str(int flags, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(flags, buf, len, nh_flags, ARRAY_SIZE(nh_flags));
|
||||
}
|
||||
|
||||
int rtnl_route_nh_str2flags(const char *name)
|
||||
{
|
||||
return __str2flags(name, nh_flags, ARRAY_SIZE(nh_flags));
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -840,13 +840,13 @@ int rtnl_rule_get_action(struct rtnl_rule *rule)
|
|||
return nl_errno(ENOENT);
|
||||
}
|
||||
|
||||
void rtnl_rule_set_realms(struct rtnl_rule *rule, realm_t realms)
|
||||
void rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms)
|
||||
{
|
||||
rule->r_realms = realms;
|
||||
rule->ce_mask |= RULE_ATTR_REALMS;
|
||||
}
|
||||
|
||||
realm_t rtnl_rule_get_realms(struct rtnl_rule *rule)
|
||||
uint32_t rtnl_rule_get_realms(struct rtnl_rule *rule)
|
||||
{
|
||||
if (rule->ce_mask & RULE_ATTR_REALMS)
|
||||
return rule->r_realms;
|
||||
|
|
4
src/.gitignore
vendored
4
src/.gitignore
vendored
|
@ -23,8 +23,8 @@ nl-qdisc-add
|
|||
nl-qdisc-delete
|
||||
nl-qdisc-dump
|
||||
nl-route-add
|
||||
nl-route-del
|
||||
nl-route-dump
|
||||
nl-route-delete
|
||||
nl-route-list
|
||||
nl-route-get
|
||||
nl-rule-dump
|
||||
nl-tctree-dump
|
||||
|
|
13
src/Makefile
13
src/Makefile
|
@ -6,36 +6,37 @@
|
|||
# License as published by the Free Software Foundation version 2.1
|
||||
# of the License.
|
||||
#
|
||||
# Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
|
||||
# Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
|
||||
#
|
||||
|
||||
ifeq ($(shell [ ! -r ../Makefile.opts ] && echo 1),)
|
||||
include ../Makefile.opts
|
||||
endif
|
||||
|
||||
LDFLAGS += -L../lib -lnl utils.o
|
||||
LDFLAGS += -L../lib -lnl
|
||||
CIN := $(wildcard nl-*.c) $(wildcard genl-*.c) $(wildcard nf-*.c)
|
||||
TOOLS := $(CIN:%.c=%)
|
||||
|
||||
all: $(TOOLS)
|
||||
|
||||
$(TOOLS): utils.o
|
||||
nl-route-add nl-route-delete nl-route-list: route-utils.o
|
||||
|
||||
nl-%: nl-%.c
|
||||
@echo " LD $@"; \
|
||||
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
genl-%: genl-%.c
|
||||
@echo " LD $@"; \
|
||||
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
nf-%: nf-%.c
|
||||
@echo " LD $@"; \
|
||||
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
@echo " CLEAN src"; \
|
||||
rm -f $(TOOLS) utils.o
|
||||
rm -f $(TOOLS) *.o
|
||||
|
||||
distclean: clean
|
||||
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* src/f_route.c Routes Filter
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
static void get_filter(struct rtnl_route *r, int ac, char **av, int idx,
|
||||
struct nl_cache *cache, struct nl_cache *link_cache)
|
||||
{
|
||||
while (ac > idx) {
|
||||
if (!strcasecmp(av[idx], "src")) {
|
||||
if (ac > ++idx) {
|
||||
struct nl_addr *a = nl_addr_parse(av[idx++], AF_UNSPEC);
|
||||
if (!a)
|
||||
goto err;
|
||||
rtnl_route_set_pref_src(r, a);
|
||||
nl_addr_put(a);
|
||||
}
|
||||
} else if (!strcasecmp(av[idx], "dst")) {
|
||||
if (ac > ++idx) {
|
||||
struct nl_addr *a = nl_addr_parse(av[idx++], AF_UNSPEC);
|
||||
if (!a)
|
||||
goto err;
|
||||
rtnl_route_set_dst(r, a);
|
||||
nl_addr_put(a);
|
||||
}
|
||||
} else if (!strcasecmp(av[idx], "via")) {
|
||||
if (ac > ++idx) {
|
||||
struct nl_addr *a = nl_addr_parse(av[idx++], AF_UNSPEC);
|
||||
if (!a)
|
||||
goto err;
|
||||
rtnl_route_set_gateway(r, a);
|
||||
nl_addr_put(a);
|
||||
}
|
||||
} else if (!strcasecmp(av[idx], "from")) {
|
||||
if (ac > ++idx) {
|
||||
struct nl_addr *a = nl_addr_parse(av[idx++], AF_UNSPEC);
|
||||
if (!a)
|
||||
goto err;
|
||||
rtnl_route_set_src(r, a);
|
||||
nl_addr_put(a);
|
||||
}
|
||||
} else if (!strcasecmp(av[idx], "tos")) {
|
||||
if (ac > ++idx)
|
||||
rtnl_route_set_tos(r, strtoul(av[idx++], NULL, 0));
|
||||
} else if (!strcasecmp(av[idx], "prio")) {
|
||||
if (ac > ++idx)
|
||||
rtnl_route_set_prio(r, strtoul(av[idx++], NULL, 0));
|
||||
} else if (!strcasecmp(av[idx], "scope")) {
|
||||
if (ac > ++idx)
|
||||
rtnl_route_set_scope(r, rtnl_str2scope(av[idx++]));
|
||||
} else if (!strcasecmp(av[idx], "dev")) {
|
||||
if (ac > ++idx) {
|
||||
int ifindex = rtnl_link_name2i(link_cache, av[idx++]);
|
||||
if (ifindex == RTNL_LINK_NOT_FOUND)
|
||||
goto err_notfound;
|
||||
rtnl_route_set_oif(r, ifindex);
|
||||
}
|
||||
} else if (!strcasecmp(av[idx], "table")) {
|
||||
if (ac > ++idx)
|
||||
rtnl_route_set_table(r, strtoul(av[idx++], NULL, 0));
|
||||
} else {
|
||||
fprintf(stderr, "What is '%s'?\n", av[idx]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err_notfound:
|
||||
fprintf(stderr, "Unable to find device \"%s\"\n", av[idx-1]);
|
||||
exit(1);
|
||||
err:
|
||||
fprintf(stderr, "%s\n", nl_geterror());
|
||||
exit(1);
|
||||
}
|
|
@ -1,76 +1,124 @@
|
|||
/*
|
||||
* src/nl-route-dump.c Dump route attributes
|
||||
* src/nl-route-add.c Route addition utility
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#include "utils.h"
|
||||
#include "route-utils.h"
|
||||
|
||||
static struct nl_cache *link_cache, *route_cache;
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
printf(
|
||||
"Usage: nl-route-add [<filter>]\n");
|
||||
"Usage: nl-route-add [OPTION]... --dst=ADDR --nh=NEXTHOP [--nh=...]\n"
|
||||
" nl-route-add [OPTION]... ADDR NEXTHOP\n"
|
||||
"\n"
|
||||
"Required Options\n"
|
||||
" -d, --dst=ADDR destination prefix, e.g. 10.10.0.0/16\n"
|
||||
" -n, --nh=NEXTHOP nexthop configuration:\n"
|
||||
" dev=DEV route via device\n"
|
||||
" weight=WEIGHT weight of nexthop\n"
|
||||
" flags=FLAGS\n"
|
||||
" via=GATEWAY route via other node\n"
|
||||
" realms=REALMS\n"
|
||||
"\n"
|
||||
" e.g. dev=eth0,via=192.168.1.12\n"
|
||||
"\n"
|
||||
"Options\n"
|
||||
" -s, --src=ADDR source prefix\n"
|
||||
" -i, --iif=DEV incomming interface\n"
|
||||
" -P, --pref-src=ADDR preferred source address\n"
|
||||
" -t, --table=TABLE routing table\n"
|
||||
" -m, --metric=OPTS metrics\n"
|
||||
" -p, --prio=NUM priotity\n"
|
||||
" -S, --scope=SCOPE scope\n"
|
||||
" -x, --proto=PROTO protocol\n"
|
||||
" -T, --type=TYPE routing type\n"
|
||||
" -h, --help show this help\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#include "f_route.c"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_handle *nlh;
|
||||
struct nl_cache *link_cache, *route_cache;
|
||||
struct rtnl_route *route;
|
||||
int err = 1;
|
||||
|
||||
if (nltool_init(argc, argv) < 0)
|
||||
return -1;
|
||||
|
||||
if (argc < 2 || !strcmp(argv[1], "-h"))
|
||||
print_usage();
|
||||
|
||||
nlh = nltool_alloc_handle();
|
||||
if (!nlh)
|
||||
goto errout;
|
||||
nltool_connect(nlh, NETLINK_ROUTE);
|
||||
link_cache = nltool_alloc_link_cache(nlh);
|
||||
route_cache = nltool_alloc_route_cache(nlh);
|
||||
|
||||
route = rtnl_route_alloc();
|
||||
if (!route)
|
||||
goto errout;
|
||||
|
||||
if (nltool_connect(nlh, NETLINK_ROUTE) < 0)
|
||||
goto errout_free;
|
||||
for (;;) {
|
||||
int c, optidx = 0;
|
||||
static struct option long_opts[] = {
|
||||
{ "dst", 1, 0, 'd' },
|
||||
{ "src", 1, 0, 's' },
|
||||
{ "iif", 1, 0, 'i' },
|
||||
{ "nh", 1, 0, 'n' },
|
||||
{ "pref-src", 1, 0, 'P' },
|
||||
{ "table", 1, 0, 't' },
|
||||
{ "metric", 1, 0, 'm' },
|
||||
{ "prio", 1, 0, 'p' },
|
||||
{ "scope", 1, 0, 'S' },
|
||||
{ "proto", 1, 0, 'x' },
|
||||
{ "type", 1, 0, 'T' },
|
||||
{ "help", 0, 0, 'h' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
link_cache = nltool_alloc_link_cache(nlh);
|
||||
if (!link_cache)
|
||||
goto errout_close;
|
||||
c = getopt_long(argc, argv, "d:s:i:n:P:t:m:p:S:x:T:h", long_opts, &optidx);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
route_cache = nltool_alloc_route_cache(nlh);
|
||||
if (!route_cache)
|
||||
goto errout_link_cache;
|
||||
switch (c) {
|
||||
case 'd': parse_dst(route, optarg); break;
|
||||
case 's': parse_src(route, optarg); break;
|
||||
case 'i': parse_iif(route, optarg, link_cache); break;
|
||||
case 'n': parse_nexthop(route, optarg, link_cache); break;
|
||||
case 'P': parse_pref_src(route, optarg); break;
|
||||
case 't': parse_table(route, optarg); break;
|
||||
case 'm': parse_metric(route, optarg); break;
|
||||
case 'p': parse_prio(route, optarg); break;
|
||||
case 'S': parse_scope(route, optarg); break;
|
||||
case 'x': parse_protocol(route, optarg); break;
|
||||
case 'T': parse_type(route, optarg); break;
|
||||
case 'h': print_usage(); break;
|
||||
}
|
||||
}
|
||||
|
||||
get_filter(route, argc, argv, 1, route_cache, link_cache);
|
||||
while (optind < argc) {
|
||||
if (!rtnl_route_get_dst(route)) {
|
||||
parse_dst(route, argv[optind++]);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This must all be nexthop configuration */
|
||||
}
|
||||
|
||||
if (rtnl_route_add(nlh, route, 0) < 0) {
|
||||
fprintf(stderr, "rtnl_route_add failed: %s\n",
|
||||
nl_geterror());
|
||||
goto errout_route_cache;
|
||||
fprintf(stderr, "rtnl_route_add failed: %s\n", nl_geterror());
|
||||
goto errout_free;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
||||
errout_route_cache:
|
||||
nl_cache_free(route_cache);
|
||||
errout_link_cache:
|
||||
nl_cache_free(link_cache);
|
||||
errout_close:
|
||||
nl_close(nlh);
|
||||
errout_free:
|
||||
rtnl_route_put(route);
|
||||
errout:
|
||||
nl_cache_free(route_cache);
|
||||
nl_cache_free(link_cache);
|
||||
nl_close(nlh);
|
||||
nl_handle_destroy(nlh);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* src/nl-route-del.c Delete Routes
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
printf(
|
||||
"Usage: nl-route-del [<filter>]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#include "f_route.c"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_handle *nlh;
|
||||
struct nl_cache *link_cache, *route_cache;
|
||||
struct rtnl_route *route;
|
||||
int err = 1;
|
||||
|
||||
if (nltool_init(argc, argv) < 0)
|
||||
return -1;
|
||||
|
||||
if (argc < 2 || !strcmp(argv[1], "-h"))
|
||||
print_usage();
|
||||
|
||||
nlh = nltool_alloc_handle();
|
||||
if (!nlh)
|
||||
goto errout;
|
||||
|
||||
route = rtnl_route_alloc();
|
||||
if (!route)
|
||||
goto errout;
|
||||
|
||||
if (nltool_connect(nlh, NETLINK_ROUTE) < 0)
|
||||
goto errout_free;
|
||||
|
||||
link_cache = nltool_alloc_link_cache(nlh);
|
||||
if (!link_cache)
|
||||
goto errout_close;
|
||||
|
||||
route_cache = nltool_alloc_route_cache(nlh);
|
||||
if (!route_cache)
|
||||
goto errout_link_cache;
|
||||
|
||||
get_filter(route, argc, argv, 1, route_cache, link_cache);
|
||||
|
||||
if (rtnl_route_del(nlh, route, 0) < 0) {
|
||||
fprintf(stderr, "rtnl_route_del failed: %s\n",
|
||||
nl_geterror());
|
||||
goto errout_route_cache;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
||||
errout_route_cache:
|
||||
nl_cache_free(route_cache);
|
||||
errout_link_cache:
|
||||
nl_cache_free(link_cache);
|
||||
errout_close:
|
||||
nl_close(nlh);
|
||||
errout_free:
|
||||
rtnl_route_put(route);
|
||||
errout:
|
||||
nl_handle_destroy(nlh);
|
||||
return err;
|
||||
}
|
113
src/nl-route-delete.c
Normal file
113
src/nl-route-delete.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* src/nl-route-delete.c Delete Routes
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#include "route-utils.h"
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
printf(
|
||||
"Usage: nl-route-delete [OPTION]...\n"
|
||||
"\n"
|
||||
"Options\n"
|
||||
" -f, --family=FAMILY address family\n"
|
||||
" -d, --dst=ADDR destination prefix, e.g. 10.10.0.0/16\n"
|
||||
" -n, --nh=NEXTHOP nexthop configuration:\n"
|
||||
" dev=DEV route via device\n"
|
||||
" weight=WEIGHT weight of nexthop\n"
|
||||
" flags=FLAGS\n"
|
||||
" via=GATEWAY route via other node\n"
|
||||
" realms=REALMS\n"
|
||||
" e.g. dev=eth0,via=192.168.1.12\n"
|
||||
" -s, --src=ADDR source prefix\n"
|
||||
" -i, --iif=DEV incomming interface\n"
|
||||
" -P, --pref-src=ADDR preferred source address\n"
|
||||
" -t, --table=TABLE routing table\n"
|
||||
" -m, --metric=OPTS metrics\n"
|
||||
" -p, --prio=NUM priotity\n"
|
||||
" -S, --scope=SCOPE scope\n"
|
||||
" -x, --proto=PROTO protocol\n"
|
||||
" -T, --type=TYPE routing type\n"
|
||||
" -D, --dumptype=TYPE { brief | detailed | stats | env }\n"
|
||||
" -h, --help show this help\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_handle *nlh;
|
||||
struct nl_cache *link_cache, *route_cache;
|
||||
struct rtnl_route *route;
|
||||
int err = 1;
|
||||
|
||||
nlh = nltool_alloc_handle();
|
||||
nltool_connect(nlh, NETLINK_ROUTE);
|
||||
link_cache = nltool_alloc_link_cache(nlh);
|
||||
route_cache = nltool_alloc_route_cache(nlh);
|
||||
|
||||
route = rtnl_route_alloc();
|
||||
if (!route)
|
||||
goto errout;
|
||||
|
||||
for (;;) {
|
||||
int c, optidx = 0;
|
||||
static struct option long_opts[] = {
|
||||
{ "family", 1, 0, 'f' },
|
||||
{ "dst", 1, 0, 'd' },
|
||||
{ "src", 1, 0, 's' },
|
||||
{ "iif", 1, 0, 'i' },
|
||||
{ "nh", 1, 0, 'n' },
|
||||
{ "pref-src", 1, 0, 'P' },
|
||||
{ "table", 1, 0, 't' },
|
||||
{ "metric", 1, 0, 'm' },
|
||||
{ "prio", 1, 0, 'p' },
|
||||
{ "scope", 1, 0, 'S' },
|
||||
{ "proto", 1, 0, 'x' },
|
||||
{ "type", 1, 0, 'T' },
|
||||
{ "help", 0, 0, 'h' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "f:d:s:i:n:P:t:m:p:S:x:T:h",
|
||||
long_opts, &optidx);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'f': parse_family(route, optarg); break;
|
||||
case 'd': parse_dst(route, optarg); break;
|
||||
case 's': parse_src(route, optarg); break;
|
||||
case 'i': parse_iif(route, optarg, link_cache); break;
|
||||
case 'n': parse_nexthop(route, optarg, link_cache); break;
|
||||
case 'P': parse_pref_src(route, optarg); break;
|
||||
case 't': parse_table(route, optarg); break;
|
||||
case 'm': parse_metric(route, optarg); break;
|
||||
case 'p': parse_prio(route, optarg); break;
|
||||
case 'S': parse_scope(route, optarg); break;
|
||||
case 'x': parse_protocol(route, optarg); break;
|
||||
case 'T': parse_type(route, optarg); break;
|
||||
case 'h': print_usage(); break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((err = rtnl_route_delete(nlh, route, 0)) < 0)
|
||||
fatal(err, "rtnl_route_del failed: %s\n", nl_geterror());
|
||||
|
||||
err = 0;
|
||||
|
||||
rtnl_route_put(route);
|
||||
errout:
|
||||
nl_cache_free(route_cache);
|
||||
nl_cache_free(link_cache);
|
||||
nl_close(nlh);
|
||||
nl_handle_destroy(nlh);
|
||||
|
||||
return err;
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* src/nl-route-dump.c Dump route attributes
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
printf(
|
||||
"Usage: nl-route-dump <mode> [<filter>]\n"
|
||||
" mode := { brief | detailed | stats | xml }\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#include "f_route.c"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_handle *nlh;
|
||||
struct nl_cache *link_cache, *route_cache;
|
||||
struct rtnl_route *route;
|
||||
struct nl_dump_params params = {
|
||||
.dp_fd = stdout,
|
||||
.dp_type = NL_DUMP_BRIEF
|
||||
};
|
||||
int err = 1;
|
||||
|
||||
if (nltool_init(argc, argv) < 0)
|
||||
return -1;
|
||||
|
||||
if (argc < 2 || !strcmp(argv[1], "-h"))
|
||||
print_usage();
|
||||
|
||||
nlh = nltool_alloc_handle();
|
||||
if (!nlh)
|
||||
goto errout;
|
||||
|
||||
route = rtnl_route_alloc();
|
||||
if (!route)
|
||||
goto errout;
|
||||
|
||||
if (nltool_connect(nlh, NETLINK_ROUTE) < 0)
|
||||
goto errout_free;
|
||||
|
||||
link_cache = nltool_alloc_link_cache(nlh);
|
||||
if (!link_cache)
|
||||
goto errout_close;
|
||||
|
||||
route_cache = nltool_alloc_route_cache(nlh);
|
||||
if (!route_cache)
|
||||
goto errout_link_cache;
|
||||
|
||||
params.dp_type = nltool_parse_dumptype(argv[1]);
|
||||
if (params.dp_type < 0)
|
||||
goto errout_route_cache;
|
||||
|
||||
get_filter(route, argc, argv, 2, route_cache, link_cache);
|
||||
|
||||
nl_cache_dump_filter(route_cache, ¶ms, (struct nl_object *) route);
|
||||
|
||||
err = 0;
|
||||
|
||||
errout_route_cache:
|
||||
nl_cache_free(route_cache);
|
||||
errout_link_cache:
|
||||
nl_cache_free(link_cache);
|
||||
errout_close:
|
||||
nl_close(nlh);
|
||||
errout_free:
|
||||
rtnl_route_put(route);
|
||||
errout:
|
||||
nl_handle_destroy(nlh);
|
||||
return err;
|
||||
}
|
118
src/nl-route-list.c
Normal file
118
src/nl-route-list.c
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* src/nl-route-list.c List route attributes
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#include "route-utils.h"
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
printf(
|
||||
"Usage: nl-route-list [OPTION]...\n"
|
||||
"\n"
|
||||
"Options\n"
|
||||
" -f, --family=FAMILY address family\n"
|
||||
" -d, --dst=ADDR destination prefix, e.g. 10.10.0.0/16\n"
|
||||
" -n, --nh=NEXTHOP nexthop configuration:\n"
|
||||
" dev=DEV route via device\n"
|
||||
" weight=WEIGHT weight of nexthop\n"
|
||||
" flags=FLAGS\n"
|
||||
" via=GATEWAY route via other node\n"
|
||||
" realms=REALMS\n"
|
||||
" e.g. dev=eth0,via=192.168.1.12\n"
|
||||
" -s, --src=ADDR source prefix\n"
|
||||
" -i, --iif=DEV incomming interface\n"
|
||||
" -P, --pref-src=ADDR preferred source address\n"
|
||||
" -t, --table=TABLE routing table\n"
|
||||
" -m, --metric=OPTS metrics\n"
|
||||
" -p, --prio=NUM priotity\n"
|
||||
" -S, --scope=SCOPE scope\n"
|
||||
" -x, --proto=PROTO protocol\n"
|
||||
" -T, --type=TYPE routing type\n"
|
||||
" -D, --dumptype=TYPE { brief | detailed | stats | env }\n"
|
||||
" -h, --help show this help\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_handle *nlh;
|
||||
struct nl_cache *link_cache, *route_cache;
|
||||
struct rtnl_route *route;
|
||||
struct nl_dump_params params = {
|
||||
.dp_fd = stdout,
|
||||
.dp_type = NL_DUMP_BRIEF
|
||||
};
|
||||
int err = 1;
|
||||
|
||||
nlh = nltool_alloc_handle();
|
||||
nltool_connect(nlh, NETLINK_ROUTE);
|
||||
link_cache = nltool_alloc_link_cache(nlh);
|
||||
route_cache = nltool_alloc_route_cache(nlh);
|
||||
|
||||
route = rtnl_route_alloc();
|
||||
if (!route)
|
||||
goto errout;
|
||||
|
||||
for (;;) {
|
||||
int c, optidx = 0;
|
||||
static struct option long_opts[] = {
|
||||
{ "family", 1, 0, 'f' },
|
||||
{ "dst", 1, 0, 'd' },
|
||||
{ "src", 1, 0, 's' },
|
||||
{ "iif", 1, 0, 'i' },
|
||||
{ "nh", 1, 0, 'n' },
|
||||
{ "pref-src", 1, 0, 'P' },
|
||||
{ "table", 1, 0, 't' },
|
||||
{ "metric", 1, 0, 'm' },
|
||||
{ "prio", 1, 0, 'p' },
|
||||
{ "scope", 1, 0, 'S' },
|
||||
{ "proto", 1, 0, 'x' },
|
||||
{ "type", 1, 0, 'T' },
|
||||
{ "dumptype", 1, 0, 'D' },
|
||||
{ "help", 0, 0, 'h' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "f:d:s:i:n:P:t:m:p:S:x:T:D:h",
|
||||
long_opts, &optidx);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'f': parse_family(route, optarg); break;
|
||||
case 'd': parse_dst(route, optarg); break;
|
||||
case 's': parse_src(route, optarg); break;
|
||||
case 'i': parse_iif(route, optarg, link_cache); break;
|
||||
case 'n': parse_nexthop(route, optarg, link_cache); break;
|
||||
case 'P': parse_pref_src(route, optarg); break;
|
||||
case 't': parse_table(route, optarg); break;
|
||||
case 'm': parse_metric(route, optarg); break;
|
||||
case 'p': parse_prio(route, optarg); break;
|
||||
case 'S': parse_scope(route, optarg); break;
|
||||
case 'x': parse_protocol(route, optarg); break;
|
||||
case 'T': parse_type(route, optarg); break;
|
||||
case 'D': params.dp_type = nltool_parse_dumptype(optarg); break;
|
||||
case 'h': print_usage(); break;
|
||||
}
|
||||
}
|
||||
|
||||
nl_cache_dump_filter(route_cache, ¶ms, OBJ_CAST(route));
|
||||
|
||||
err = 0;
|
||||
|
||||
rtnl_route_put(route);
|
||||
errout:
|
||||
nl_cache_free(route_cache);
|
||||
nl_cache_free(link_cache);
|
||||
nl_close(nlh);
|
||||
nl_handle_destroy(nlh);
|
||||
|
||||
return err;
|
||||
}
|
237
src/route-utils.c
Normal file
237
src/route-utils.c
Normal file
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* src/route-utils.c Route Helpers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2008 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#include "route-utils.h"
|
||||
|
||||
void parse_family(struct rtnl_route *route, char *arg)
|
||||
{
|
||||
int family;
|
||||
|
||||
if ((family = nl_str2af(arg)) != AF_UNSPEC)
|
||||
rtnl_route_set_family(route, family);
|
||||
}
|
||||
|
||||
void parse_dst(struct rtnl_route *route, char *arg)
|
||||
{
|
||||
struct nl_addr *addr;
|
||||
int err;
|
||||
|
||||
addr = nl_addr_parse(arg, rtnl_route_get_family(route));
|
||||
if (addr == NULL)
|
||||
fatal(nl_get_errno(), nl_geterror());
|
||||
|
||||
if ((err = rtnl_route_set_dst(route, addr)) < 0)
|
||||
fatal(err, nl_geterror());
|
||||
|
||||
nl_addr_put(addr);
|
||||
}
|
||||
|
||||
void parse_src(struct rtnl_route *route, char *arg)
|
||||
{
|
||||
struct nl_addr *addr;
|
||||
int err;
|
||||
|
||||
addr = nl_addr_parse(arg, rtnl_route_get_family(route));
|
||||
if (addr == NULL)
|
||||
fatal(nl_get_errno(), nl_geterror());
|
||||
|
||||
if ((err = rtnl_route_set_src(route, addr)) < 0)
|
||||
fatal(err, nl_geterror());
|
||||
|
||||
nl_addr_put(addr);
|
||||
}
|
||||
|
||||
void parse_pref_src(struct rtnl_route *route, char *arg)
|
||||
{
|
||||
struct nl_addr *addr;
|
||||
int err;
|
||||
|
||||
addr = nl_addr_parse(arg, rtnl_route_get_family(route));
|
||||
if (addr == NULL)
|
||||
fatal(nl_get_errno(), nl_geterror());
|
||||
|
||||
if ((err = rtnl_route_set_pref_src(route, addr)) < 0)
|
||||
fatal(err, nl_geterror());
|
||||
|
||||
nl_addr_put(addr);
|
||||
}
|
||||
|
||||
void parse_metric(struct rtnl_route *route, char *subopts)
|
||||
{
|
||||
/* strict equal order to RTAX_* */
|
||||
static char *const tokens[] = {
|
||||
"unspec",
|
||||
"lock",
|
||||
"mtu",
|
||||
"window",
|
||||
"rtt",
|
||||
"rttvar",
|
||||
"sstresh",
|
||||
"cwnd",
|
||||
"advmss",
|
||||
"reordering",
|
||||
"hoplimit",
|
||||
"initcwnd",
|
||||
"features",
|
||||
NULL,
|
||||
};
|
||||
unsigned long lval;
|
||||
char *arg, *endptr;
|
||||
|
||||
while (*subopts != '\0') {
|
||||
int ret = getsubopt(&subopts, tokens, &arg);
|
||||
if (ret == -1)
|
||||
fatal(EINVAL, "Unknown metric token \"%s\"", arg);
|
||||
|
||||
if (ret == 0)
|
||||
fatal(EINVAL, "Invalid metric \"%s\"", tokens[ret]);
|
||||
|
||||
if (arg == NULL)
|
||||
fatal(EINVAL, "Metric \"%s\", no value given", tokens[ret]);
|
||||
|
||||
lval = strtoul(arg, &endptr, 0);
|
||||
if (endptr == arg)
|
||||
fatal(EINVAL, "Metric \"%s\", value not numeric", tokens[ret]);
|
||||
|
||||
if ((ret = rtnl_route_set_metric(route, ret, lval)) < 0)
|
||||
fatal(ret, nl_geterror());
|
||||
}
|
||||
}
|
||||
|
||||
void parse_nexthop(struct rtnl_route *route, char *subopts,
|
||||
struct nl_cache *link_cache)
|
||||
{
|
||||
enum {
|
||||
NH_DEV,
|
||||
NH_VIA,
|
||||
NH_WEIGHT,
|
||||
};
|
||||
static char *const tokens[] = {
|
||||
"dev",
|
||||
"via",
|
||||
"weight",
|
||||
NULL,
|
||||
};
|
||||
struct rtnl_nexthop *nh;
|
||||
unsigned long lval;
|
||||
struct nl_addr *addr;
|
||||
int ival;
|
||||
char *arg, *endptr;
|
||||
|
||||
if (!(nh = rtnl_route_nh_alloc()))
|
||||
fatal(ENOMEM, "Out of memory");
|
||||
|
||||
while (*subopts != '\0') {
|
||||
int ret = getsubopt(&subopts, tokens, &arg);
|
||||
if (ret == -1)
|
||||
fatal(EINVAL, "Unknown nexthop token \"%s\"", arg);
|
||||
|
||||
switch (ret) {
|
||||
case NH_DEV:
|
||||
ival = rtnl_link_name2i(link_cache, arg);
|
||||
if (ival == RTNL_LINK_NOT_FOUND)
|
||||
fatal(ENOENT, "Link \"%s\" does not exist", arg);
|
||||
|
||||
rtnl_route_nh_set_ifindex(nh, ival);
|
||||
break;
|
||||
|
||||
case NH_VIA:
|
||||
addr = nl_addr_parse(arg, rtnl_route_get_family(route));
|
||||
if (addr == NULL)
|
||||
fatal(nl_get_errno(), nl_geterror());
|
||||
|
||||
rtnl_route_nh_set_gateway(nh, addr);
|
||||
nl_addr_put(addr);
|
||||
break;
|
||||
|
||||
case NH_WEIGHT:
|
||||
lval = strtoul(arg, &endptr, 0);
|
||||
if (endptr == arg)
|
||||
fatal(EINVAL, "Invalid weight \"%s\", not numeric", arg);
|
||||
rtnl_route_nh_set_weight(nh, lval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rtnl_route_add_nexthop(route, nh);
|
||||
}
|
||||
|
||||
void parse_table(struct rtnl_route *route, char *arg)
|
||||
{
|
||||
unsigned long lval;
|
||||
char *endptr;
|
||||
|
||||
lval = strtoul(arg, &endptr, 0);
|
||||
if (endptr == arg) {
|
||||
if ((lval = rtnl_route_str2table(arg)) < 0)
|
||||
fatal(EINVAL, "Unknown table name \"%s\"", arg);
|
||||
}
|
||||
|
||||
rtnl_route_set_table(route, lval);
|
||||
}
|
||||
|
||||
void parse_prio(struct rtnl_route *route, char *arg)
|
||||
{
|
||||
unsigned long lval;
|
||||
char *endptr;
|
||||
|
||||
lval = strtoul(arg, &endptr, 0);
|
||||
if (endptr == arg)
|
||||
fatal(EINVAL, "Invalid priority value, not numeric");
|
||||
rtnl_route_set_priority(route, lval);
|
||||
}
|
||||
|
||||
void parse_scope(struct rtnl_route *route, char *arg)
|
||||
{
|
||||
int ival;
|
||||
|
||||
if ((ival = rtnl_str2scope(arg)) < 0)
|
||||
fatal(EINVAL, "Unknown routing scope \"%s\"", arg);
|
||||
|
||||
rtnl_route_set_scope(route, ival);
|
||||
}
|
||||
|
||||
void parse_protocol(struct rtnl_route *route, char *arg)
|
||||
{
|
||||
unsigned long lval;
|
||||
char *endptr;
|
||||
|
||||
lval = strtoul(arg, &endptr, 0);
|
||||
if (endptr == arg) {
|
||||
if ((lval = rtnl_route_str2proto(arg)) < 0)
|
||||
fatal(EINVAL, "Unknown routing protocol name \"%s\"",
|
||||
arg);
|
||||
}
|
||||
|
||||
rtnl_route_set_protocol(route, lval);
|
||||
}
|
||||
|
||||
void parse_type(struct rtnl_route *route, char *arg)
|
||||
{
|
||||
int ival;
|
||||
|
||||
if ((ival = nl_str2rtntype(arg)) < 0)
|
||||
fatal(EINVAL, "Unknown routing type \"%s\"", arg);
|
||||
|
||||
if ((ival = rtnl_route_set_type(route, ival)) < 0)
|
||||
fatal(ival, nl_geterror());
|
||||
}
|
||||
|
||||
void parse_iif(struct rtnl_route *route, char *arg, struct nl_cache *link_cache)
|
||||
{
|
||||
int ival;
|
||||
|
||||
ival = rtnl_link_name2i(link_cache, arg);
|
||||
if (ival == RTNL_LINK_NOT_FOUND)
|
||||
fatal(ENOENT, "Link \"%s\" does not exist", arg);
|
||||
|
||||
rtnl_route_set_iif(route, ival);
|
||||
}
|
30
src/route-utils.h
Normal file
30
src/route-utils.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* src/route-utils.h Route Helpers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2008 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef __ROUTE_UTILS_H_
|
||||
#define __ROUTE_UTILS_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
extern void parse_family(struct rtnl_route *, char *);
|
||||
extern void parse_dst(struct rtnl_route *, char *);
|
||||
extern void parse_src(struct rtnl_route *, char *);
|
||||
extern void parse_pref_src(struct rtnl_route *, char *);
|
||||
extern void parse_metric(struct rtnl_route *, char *);
|
||||
extern void parse_nexthop(struct rtnl_route *, char *, struct nl_cache *);
|
||||
extern void parse_table(struct rtnl_route *, char *);
|
||||
extern void parse_prio(struct rtnl_route *, char *);
|
||||
extern void parse_scope(struct rtnl_route *, char *);
|
||||
extern void parse_protocol(struct rtnl_route *, char *);
|
||||
extern void parse_type(struct rtnl_route *, char *);
|
||||
extern void parse_iif(struct rtnl_route *, char *, struct nl_cache *);
|
||||
|
||||
#endif
|
70
src/utils.c
70
src/utils.c
|
@ -13,6 +13,21 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
void fatal(int err, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf(stderr, "Error: ");
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
exit(err);
|
||||
}
|
||||
|
||||
int nltool_init(int argc, char *argv[])
|
||||
{
|
||||
return 0;
|
||||
|
@ -24,7 +39,7 @@ int nltool_connect(struct nl_handle *nlh, int protocol)
|
|||
|
||||
err = nl_connect(nlh, protocol);
|
||||
if (err < 0)
|
||||
fprintf(stderr, "Unable to connect netlink socket%s\n",
|
||||
fatal(err, "Unable to connect netlink socket: %s",
|
||||
nl_geterror());
|
||||
|
||||
return err;
|
||||
|
@ -32,7 +47,12 @@ int nltool_connect(struct nl_handle *nlh, int protocol)
|
|||
|
||||
struct nl_handle *nltool_alloc_handle(void)
|
||||
{
|
||||
return nl_handle_alloc();
|
||||
struct nl_handle *sock;
|
||||
|
||||
if (!(sock = nl_handle_alloc()))
|
||||
fatal(ENOBUFS, "Unable to allocate netlink socket");
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
struct nl_addr *nltool_addr_parse(const char *str)
|
||||
|
@ -71,10 +91,10 @@ struct nl_cache *nltool_alloc_link_cache(struct nl_handle *nlh)
|
|||
|
||||
cache = rtnl_link_alloc_cache(nlh);
|
||||
if (!cache)
|
||||
fprintf(stderr, "Unable to retrieve link cache: %s\n",
|
||||
fatal(nl_get_errno(), "Unable to retrieve link cache: %s",
|
||||
nl_geterror());
|
||||
else
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
@ -85,10 +105,10 @@ struct nl_cache *nltool_alloc_addr_cache(struct nl_handle *nlh)
|
|||
|
||||
cache = rtnl_addr_alloc_cache(nlh);
|
||||
if (!cache)
|
||||
fprintf(stderr, "Unable to retrieve address cache: %s\n",
|
||||
fatal(nl_get_errno(), "Unable to retrieve address cache: %s\n",
|
||||
nl_geterror());
|
||||
else
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
@ -99,10 +119,10 @@ struct nl_cache *nltool_alloc_neigh_cache(struct nl_handle *nlh)
|
|||
|
||||
cache = rtnl_neigh_alloc_cache(nlh);
|
||||
if (!cache)
|
||||
fprintf(stderr, "Unable to retrieve neighbour cache: %s\n",
|
||||
fatal(nl_get_errno(), "Unable to retrieve neighbour cache: %s\n",
|
||||
nl_geterror());
|
||||
else
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
@ -113,8 +133,8 @@ struct nl_cache *nltool_alloc_neightbl_cache(struct nl_handle *nlh)
|
|||
|
||||
cache = rtnl_neightbl_alloc_cache(nlh);
|
||||
if (!cache)
|
||||
fprintf(stderr, "Unable to retrieve neighbour table "
|
||||
"cache: %s\n", nl_geterror());
|
||||
fatal(nl_get_errno(), "Unable to retrieve neighbour table "
|
||||
"cache: %s", nl_geterror());
|
||||
else
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
|
@ -127,10 +147,10 @@ struct nl_cache *nltool_alloc_route_cache(struct nl_handle *nlh)
|
|||
|
||||
cache = rtnl_route_alloc_cache(nlh);
|
||||
if (!cache)
|
||||
fprintf(stderr, "Unable to retrieve route cache: %s\n",
|
||||
fatal(nl_get_errno(), "Unable to retrieve route cache: %s\n",
|
||||
nl_geterror());
|
||||
else
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
@ -141,10 +161,10 @@ struct nl_cache *nltool_alloc_rule_cache(struct nl_handle *nlh)
|
|||
|
||||
cache = rtnl_rule_alloc_cache(nlh);
|
||||
if (!cache)
|
||||
fprintf(stderr, "Unable to retrieve rule cache: %s\n",
|
||||
fatal(nl_get_errno(), "Unable to retrieve rule cache: %s\n",
|
||||
nl_geterror());
|
||||
else
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
@ -155,10 +175,10 @@ struct nl_cache *nltool_alloc_qdisc_cache(struct nl_handle *nlh)
|
|||
|
||||
cache = rtnl_qdisc_alloc_cache(nlh);
|
||||
if (!cache)
|
||||
fprintf(stderr, "Unable to retrieve qdisc cache: %s\n",
|
||||
fatal(nl_get_errno(), "Unable to retrieve qdisc cache: %s\n",
|
||||
nl_geterror());
|
||||
else
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
@ -169,10 +189,10 @@ struct nl_cache *nltool_alloc_genl_family_cache(struct nl_handle *nlh)
|
|||
|
||||
cache = genl_ctrl_alloc_cache(nlh);
|
||||
if (!cache)
|
||||
fprintf(stderr, "Unable to retrieve genl family cache: %s\n",
|
||||
fatal(nl_get_errno(), "Unable to retrieve genl family cache: %s\n",
|
||||
nl_geterror());
|
||||
else
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
nl_cache_mngt_provide(cache);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include <netlink/genl/mngt.h>
|
||||
#include <netlink/netfilter/ct.h>
|
||||
|
||||
extern void fatal(int err, const char *fmt, ...);
|
||||
|
||||
extern int nltool_init(int argc, char *argv[]);
|
||||
extern int nltool_connect(struct nl_handle *nlh, int protocol);
|
||||
extern struct nl_addr *nltool_addr_parse(const char *str);
|
||||
|
|
Loading…
Add table
Reference in a new issue