* 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_ADDR_H_
/* Creation */
extern struct nl_addr * nl_addr_alloc(size_t);
-extern struct nl_addr * nl_addr_alloc_from_attr(struct nlattr *, int);
+extern struct nl_addr * nl_addr_alloc_attr(struct nlattr *, int);
extern struct nl_addr * nl_addr_build(int, void *, size_t);
extern int nl_addr_parse(const char *, int, struct nl_addr **);
extern struct nl_addr * nl_addr_clone(struct nl_addr *);
extern int nla_parse_nested(struct nlattr **, int, struct nlattr *,
struct nla_policy *);
-/* DEPRECATED! */
-extern struct nl_data * nla_get_data(struct nlattr *);
-extern struct nl_addr * nla_get_addr(struct nlattr *, int);
-
/**
* @name Attribute Construction (Exception Based)
* @{
* 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_DATA_H_
/* General */
extern struct nl_data * nl_data_alloc(void *, size_t);
-extern struct nl_data * nl_data_alloc_from_attr(struct nlattr *);
+extern struct nl_data * nl_data_alloc_attr(struct nlattr *);
extern struct nl_data * nl_data_clone(struct nl_data *);
extern int nl_data_append(struct nl_data *, void *, size_t);
extern void nl_data_free(struct nl_data *);
*
* @return Newly allocated address handle or NULL.
*/
-struct nl_addr *nl_addr_alloc_from_attr(struct nlattr *nla, int family)
+struct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family)
{
return nl_addr_build(family, nla_data(nla), nla_len(nla));
}
nl_data_get(data));
}
-/* FIXME: Remove in 1.2 */
-struct nl_data * nla_get_data(struct nlattr *nla)
-{
- return nl_data_alloc_from_attr(nla);
-}
-
/**
* Add abstract address as unspecific attribute to netlink message.
* @arg msg Netlink message.
nl_addr_get_binary_addr(addr));
}
-/* FIXME: Remove in 1.2 */
-struct nl_addr *nla_get_addr(struct nlattr *nla, int family)
-{
- return nl_addr_alloc_from_attr(nla, family);
-}
-
/** @} */
/**
* @see nla_data_alloc
* @return Newly allocated data handle or NULL
*/
-struct nl_data *nl_data_alloc_from_attr(struct nlattr *nla)
+struct nl_data *nl_data_alloc_attr(struct nlattr *nla)
{
return nl_data_alloc(nla_data(nla), nla_len(nla));
}
goto errout;
if (tb[CTA_IP_V4_SRC]) {
- addr = nla_get_addr(tb[CTA_IP_V4_SRC], AF_INET);
+ addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET);
if (addr == NULL)
- goto errout_errno;
+ goto errout_enomem;
err = nfnl_ct_set_src(ct, repl, addr);
nl_addr_put(addr);
if (err < 0)
goto errout;
}
if (tb[CTA_IP_V4_DST]) {
- addr = nla_get_addr(tb[CTA_IP_V4_DST], AF_INET);
+ addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET);
if (addr == NULL)
- goto errout_errno;
+ goto errout_enomem;
err = nfnl_ct_set_dst(ct, repl, addr);
nl_addr_put(addr);
if (err < 0)
goto errout;
}
if (tb[CTA_IP_V6_SRC]) {
- addr = nla_get_addr(tb[CTA_IP_V6_SRC], AF_INET6);
+ addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6);
if (addr == NULL)
- goto errout_errno;
+ goto errout_enomem;
err = nfnl_ct_set_src(ct, repl, addr);
nl_addr_put(addr);
if (err < 0)
goto errout;
}
if (tb[CTA_IP_V6_DST]) {
- addr = nla_get_addr(tb[CTA_IP_V6_DST], AF_INET6);
+ addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6);
if (addr == NULL)
- goto errout_errno;
+ goto errout_enomem;
err = nfnl_ct_set_dst(ct, repl, addr);
nl_addr_put(addr);
if (err < 0)
return 0;
-errout_errno:
+errout_enomem:
err = -NLE_NOMEM;
errout:
return err;
struct rtnl_addr *addr;
struct ifaddrmsg *ifa;
struct nlattr *tb[IFA_MAX+1];
- int err, peer_prefix = 0;
+ int err, peer_prefix = 0, family;
addr = rtnl_addr_alloc();
- if (!addr) {
- err = -NLE_NOMEM;
- goto errout;
- }
+ if (!addr)
+ return -NLE_NOMEM;
+
addr->ce_msgtype = nlh->nlmsg_type;
err = nlmsg_parse(nlh, sizeof(*ifa), tb, IFA_MAX, addr_policy);
if (err < 0)
- goto errout_free;
+ goto errout;
ifa = nlmsg_data(nlh);
- addr->a_family = ifa->ifa_family;
+ addr->a_family = family = ifa->ifa_family;
addr->a_prefixlen = ifa->ifa_prefixlen;
addr->a_flags = ifa->ifa_flags;
addr->a_scope = ifa->ifa_scope;
}
if (tb[IFA_LOCAL]) {
- addr->a_local = nla_get_addr(tb[IFA_LOCAL], addr->a_family);
+ addr->a_local = nl_addr_alloc_attr(tb[IFA_LOCAL], family);
if (!addr->a_local)
- goto errout_free;
+ goto errout_nomem;
addr->ce_mask |= ADDR_ATTR_LOCAL;
}
if (tb[IFA_ADDRESS]) {
struct nl_addr *a;
- a = nla_get_addr(tb[IFA_ADDRESS], addr->a_family);
+ a = nl_addr_alloc_attr(tb[IFA_ADDRESS], family);
if (!a)
- goto errout_free;
+ goto errout_nomem;
/* IPv6 sends the local address as IFA_ADDRESS with
* no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS
addr->a_prefixlen);
if (tb[IFA_BROADCAST]) {
- addr->a_bcast = nla_get_addr(tb[IFA_BROADCAST], addr->a_family);
+ addr->a_bcast = nl_addr_alloc_attr(tb[IFA_BROADCAST], family);
if (!addr->a_bcast)
- goto errout_free;
+ goto errout_nomem;
addr->ce_mask |= ADDR_ATTR_BROADCAST;
}
if (tb[IFA_ANYCAST]) {
- addr->a_anycast = nla_get_addr(tb[IFA_ANYCAST], addr->a_family);
+ addr->a_anycast = nl_addr_alloc_attr(tb[IFA_ANYCAST], family);
if (!addr->a_anycast)
- goto errout_free;
+ goto errout_nomem;
addr->ce_mask |= ADDR_ATTR_ANYCAST;
}
if (tb[IFA_MULTICAST]) {
- addr->a_multicast = nla_get_addr(tb[IFA_MULTICAST],
- addr->a_family);
+ addr->a_multicast = nl_addr_alloc_attr(tb[IFA_MULTICAST],
+ family);
if (!addr->a_multicast)
- goto errout_free;
+ goto errout_nomem;
addr->ce_mask |= ADDR_ATTR_MULTICAST;
}
err = pp->pp_cb((struct nl_object *) addr, pp);
if (err < 0)
- goto errout_free;
+ goto errout;
err = P_ACCEPT;
-errout_free:
- rtnl_addr_put(addr);
errout:
+ rtnl_addr_put(addr);
+
return err;
+
+errout_nomem:
+ err = -NLE_NOMEM;
+ goto errout;
}
static int addr_request_update(struct nl_cache *cache, struct nl_handle *handle)
}
if (tb[TCA_FW_ACT]) {
- f->cf_act = nla_get_data(tb[TCA_FW_ACT]);
+ f->cf_act = nl_data_alloc_attr(tb[TCA_FW_ACT]);
if (!f->cf_act)
return -NLE_NOMEM;
f->cf_mask |= FW_ATTR_ACTION;
}
if (tb[TCA_FW_POLICE]) {
- f->cf_police = nla_get_data(tb[TCA_FW_POLICE]);
+ f->cf_police = nl_data_alloc_attr(tb[TCA_FW_POLICE]);
if (!f->cf_police)
return -NLE_NOMEM;
f->cf_mask |= FW_ATTR_POLICE;
}
if (tb[TCA_U32_SEL]) {
- u->cu_selector = nla_get_data(tb[TCA_U32_SEL]);
+ u->cu_selector = nl_data_alloc_attr(tb[TCA_U32_SEL]);
if (!u->cu_selector)
goto errout_nomem;
u->cu_mask |= U32_ATTR_SELECTOR;
}
if (tb[TCA_U32_ACT]) {
- u->cu_act = nla_get_data(tb[TCA_U32_ACT]);
+ u->cu_act = nl_data_alloc_attr(tb[TCA_U32_ACT]);
if (!u->cu_act)
goto errout_nomem;
u->cu_mask |= U32_ATTR_ACTION;
}
if (tb[TCA_U32_POLICE]) {
- u->cu_police = nla_get_data(tb[TCA_U32_POLICE]);
+ u->cu_police = nl_data_alloc_attr(tb[TCA_U32_POLICE]);
if (!u->cu_police)
goto errout_nomem;
u->cu_mask |= U32_ATTR_POLICE;
goto errout;
}
- u->cu_pcnt = nla_get_data(tb[TCA_U32_PCNT]);
+ u->cu_pcnt = nl_data_alloc_attr(tb[TCA_U32_PCNT]);
if (!u->cu_pcnt)
goto errout_nomem;
u->cu_mask |= U32_ATTR_PCNT;
}
if (tb[IFLA_ADDRESS]) {
- link->l_addr = nla_get_addr(tb[IFLA_ADDRESS], AF_UNSPEC);
- if (link->l_addr == NULL)
+ link->l_addr = nl_addr_alloc_attr(tb[IFLA_ADDRESS], AF_UNSPEC);
+ if (link->l_addr == NULL) {
+ err = -NLE_NOMEM;
goto errout;
+ }
nl_addr_set_family(link->l_addr,
nl_addr_guess_family(link->l_addr));
link->ce_mask |= LINK_ATTR_ADDR;
}
if (tb[IFLA_BROADCAST]) {
- link->l_bcast = nla_get_addr(tb[IFLA_BROADCAST], AF_UNSPEC);
- if (link->l_bcast == NULL)
+ link->l_bcast = nl_addr_alloc_attr(tb[IFLA_BROADCAST],
+ AF_UNSPEC);
+ if (link->l_bcast == NULL) {
+ err = -NLE_NOMEM;
goto errout;
+ }
nl_addr_set_family(link->l_bcast,
nl_addr_guess_family(link->l_bcast));
link->ce_mask |= LINK_ATTR_BRD;
NEIGH_ATTR_TYPE);
if (tb[NDA_LLADDR]) {
- neigh->n_lladdr = nla_get_addr(tb[NDA_LLADDR], AF_UNSPEC);
- if (!neigh->n_lladdr)
+ neigh->n_lladdr = nl_addr_alloc_attr(tb[NDA_LLADDR], AF_UNSPEC);
+ if (!neigh->n_lladdr) {
+ err = -NLE_NOMEM;
goto errout;
+ }
nl_addr_set_family(neigh->n_lladdr,
nl_addr_guess_family(neigh->n_lladdr));
neigh->ce_mask |= NEIGH_ATTR_LLADDR;
}
if (tb[NDA_DST]) {
- neigh->n_dst = nla_get_addr(tb[NDA_DST], neigh->n_family);
- if (!neigh->n_dst)
+ neigh->n_dst = nl_addr_alloc_attr(tb[NDA_DST], neigh->n_family);
+ if (!neigh->n_dst) {
+ err = -NLE_NOMEM;
goto errout;
+ }
neigh->ce_mask |= NEIGH_ATTR_DST;
}
[RTA_MULTIPATH] = { .type = NLA_NESTED },
};
+static int parse_multipath(struct rtnl_route *route, struct nlattr *attr)
+{
+ struct rtnl_nexthop *nh = NULL;
+ struct rtnexthop *rtnh = nla_data(attr);
+ size_t tlen = nla_len(attr);
+ int err;
+
+ while (tlen >= sizeof(*rtnh) && tlen >= rtnh->rtnh_len) {
+ nh = rtnl_route_nh_alloc();
+ if (!nh)
+ return -NLE_NOMEM;
+
+ 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];
+
+ err = nla_parse(ntb, RTA_MAX, (struct nlattr *)
+ RTNH_DATA(rtnh),
+ rtnh->rtnh_len - sizeof(*rtnh),
+ route_policy);
+ if (err < 0)
+ goto errout;
+
+ if (ntb[RTA_GATEWAY]) {
+ struct nl_addr *addr;
+
+ addr = nl_addr_alloc_attr(ntb[RTA_GATEWAY],
+ route->rt_family);
+ if (!addr) {
+ err = -NLE_NOMEM;
+ goto errout;
+ }
+
+ rtnl_route_nh_set_gateway(nh, addr);
+ nl_addr_put(addr);
+ }
+
+ if (ntb[RTA_FLOW]) {
+ uint32_t realms;
+
+ realms = nla_get_u32(ntb[RTA_FLOW]);
+ rtnl_route_nh_set_realms(nh, realms);
+ }
+ }
+
+ rtnl_route_add_nexthop(route, nh);
+ tlen -= RTNH_ALIGN(rtnh->rtnh_len);
+ rtnh = RTNH_NEXT(rtnh);
+ }
+
+ err = 0;
+errout:
+ if (err && nh)
+ rtnl_route_nh_free(nh);
+
+ return err;
+}
+
int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result)
{
struct rtmsg *rtm;
struct nlattr *tb[RTA_MAX + 1];
struct nl_addr *src = NULL, *dst = NULL, *addr;
struct rtnl_nexthop *old_nh = NULL;
- int err;
+ int err, family;
route = rtnl_route_alloc();
if (!route) {
goto errout;
rtm = nlmsg_data(nlh);
- route->rt_family = rtm->rtm_family;
+ route->rt_family = family = rtm->rtm_family;
route->rt_tos = rtm->rtm_tos;
route->rt_table = rtm->rtm_table;
route->rt_type = rtm->rtm_type;
ROUTE_ATTR_FLAGS;
if (tb[RTA_DST]) {
- dst = nla_get_addr(tb[RTA_DST], rtm->rtm_family);
- if (dst == NULL)
- goto errout;
+ if (!(dst = nl_addr_alloc_attr(tb[RTA_DST], family)))
+ goto errout_nomem;
} else {
- dst = nl_addr_alloc(0);
+ if (!(dst = nl_addr_alloc(0)))
+ goto errout_nomem;
nl_addr_set_family(dst, rtm->rtm_family);
}
nl_addr_put(dst);
if (tb[RTA_SRC]) {
- src = nla_get_addr(tb[RTA_SRC], rtm->rtm_family);
- if (src == NULL)
- goto errout;
+ if (!(src = nl_addr_alloc_attr(tb[RTA_SRC], family)))
+ goto errout_nomem;
} else if (rtm->rtm_src_len)
- src = nl_addr_alloc(0);
+ if (!(src = nl_addr_alloc(0)))
+ goto errout_nomem;
if (src) {
nl_addr_set_prefixlen(src, rtm->rtm_src_len);
rtnl_route_set_priority(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;
+ if (!(addr = nl_addr_alloc_attr(tb[RTA_PREFSRC], family)))
+ goto errout_nomem;
rtnl_route_set_pref_src(route, addr);
nl_addr_put(addr);
}
}
}
- 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]) {
- struct nl_addr *addr;
-
- addr = nla_get_addr(ntb[RTA_GATEWAY],
- route->rt_family);
- rtnl_route_nh_set_gateway(nh, addr);
- nl_addr_put(addr);
- }
-
- if (ntb[RTA_FLOW]) {
- uint32_t realms;
-
- realms = nla_get_u32(ntb[RTA_FLOW]);
- rtnl_route_nh_set_realms(nh, realms);
- }
- }
-
- rtnl_route_add_nexthop(route, nh);
- tlen -= RTNH_ALIGN(rtnh->rtnh_len);
- rtnh = RTNH_NEXT(rtnh);
- }
- }
+ if (tb[RTA_MULTIPATH])
+ if ((err = parse_multipath(route, tb[RTA_MULTIPATH])) < 0)
+ goto errout;
if (tb[RTA_CACHEINFO]) {
nla_memcpy(&route->rt_cacheinfo, tb[RTA_CACHEINFO],
if (!old_nh && !(old_nh = rtnl_route_nh_alloc()))
goto errout;
- addr = nla_get_addr(tb[RTA_GATEWAY], route->rt_family);
- if (addr == NULL)
- goto errout;
+ if (!(addr = nl_addr_alloc_attr(tb[RTA_GATEWAY], family)))
+ goto errout_nomem;
rtnl_route_nh_set_gateway(old_nh, addr);
nl_addr_put(addr);
errout:
rtnl_route_put(route);
return err;
+
+errout_nomem:
+ err = -NLE_NOMEM;
+ goto errout;
}
int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route)
struct rtnl_rule *rule;
struct rtmsg *r;
struct nlattr *tb[RTA_MAX+1];
- int err = 1;
+ int err = 1, family;
rule = rtnl_rule_alloc();
if (!rule) {
if (err < 0)
goto errout;
- rule->r_family = r->rtm_family;
+ rule->r_family = family = r->rtm_family;
rule->r_type = r->rtm_type;
rule->r_dsfield = r->rtm_tos;
rule->r_src_len = r->rtm_src_len;
}
if (tb[RTA_SRC]) {
- rule->r_src = nla_get_addr(tb[RTA_SRC], r->rtm_family);
- if (!rule->r_src) {
- err = -NLE_NOMEM;
- goto errout;
- }
+ if (!(rule->r_src = nl_addr_alloc_attr(tb[RTA_SRC], family)))
+ goto errout_enomem;
nl_addr_set_prefixlen(rule->r_src, r->rtm_src_len);
rule->ce_mask |= RULE_ATTR_SRC;
}
if (tb[RTA_DST]) {
- rule->r_dst = nla_get_addr(tb[RTA_DST], r->rtm_family);
- if (!rule->r_dst) {
- err = -NLE_NOMEM;
- goto errout;
- }
+ if (!(rule->r_dst = nl_addr_alloc_attr(tb[RTA_DST], family)))
+ goto errout_enomem;
nl_addr_set_prefixlen(rule->r_dst, r->rtm_dst_len);
rule->ce_mask |= RULE_ATTR_DST;
}
}
if (tb[RTA_GATEWAY]) {
- rule->r_srcmap = nla_get_addr(tb[RTA_GATEWAY], r->rtm_family);
- if (!rule->r_srcmap) {
- err = -NLE_NOMEM;
- goto errout;
- }
+ rule->r_srcmap = nl_addr_alloc_attr(tb[RTA_GATEWAY], family);
+ if (!rule->r_srcmap)
+ goto errout_enomem;
rule->ce_mask |= RULE_ATTR_SRCMAP;
}
errout:
rtnl_rule_put(rule);
return err;
+
+errout_enomem:
+ err = -NLE_NOMEM;
+ goto errout;
}
static int rule_request_update(struct nl_cache *c, struct nl_handle *h)
TCA_ATTR_PARENT | TCA_ATTR_INFO | TCA_ATTR_KIND);
if (tb[TCA_OPTIONS]) {
- g->tc_opts = nla_get_data(tb[TCA_OPTIONS]);
+ g->tc_opts = nl_data_alloc_attr(tb[TCA_OPTIONS]);
if (!g->tc_opts)
return -NLE_NOMEM;
g->ce_mask |= TCA_ATTR_OPTS;
g->ce_mask |= TCA_ATTR_STATS;
if (tbs[TCA_STATS_APP]) {
- g->tc_xstats = nla_get_data(tbs[TCA_STATS_APP]);
+ g->tc_xstats = nl_data_alloc_attr(tbs[TCA_STATS_APP]);
if (g->tc_xstats == NULL)
return -NLE_NOMEM;
} else
compat_xstats:
if (tb[TCA_XSTATS]) {
- g->tc_xstats = nla_get_data(tb[TCA_XSTATS]);
+ g->tc_xstats = nl_data_alloc_attr(tb[TCA_XSTATS]);
if (g->tc_xstats == NULL)
return -NLE_NOMEM;
g->ce_mask |= TCA_ATTR_XSTATS;