dect
/
libnl
Archived
13
0
Fork 0

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:
Thomas Graf 2008-04-29 23:31:30 +02:00
parent 8ac78f1552
commit 535e831622
28 changed files with 1555 additions and 1087 deletions

View File

@ -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;
};

View File

@ -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); \

View File

@ -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
}

View File

@ -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

View File

@ -23,8 +23,6 @@ extern "C" {
* @{
*/
typedef uint32_t realm_t;
/**
* Mask specying the size of each realm part
* @ingroup rtnl

View File

@ -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
}

View File

@ -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

View File

@ -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));
}
/**

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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));
}
/** @} */
/** @} */

View File

@ -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

View File

@ -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));
}
/** @} */
/** @} */

View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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
View 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;
}

View File

@ -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, &params, (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
View 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, &params, 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
View 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
View 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

View File

@ -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;
}

View File

@ -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);