dect
/
libnl
Archived
13
0
Fork 0

Merge branch 'master' of /repos/git/libnl

This commit is contained in:
Patrick McHardy 2010-05-20 17:20:12 +02:00
commit 47a4c5a4c0
14 changed files with 299 additions and 56 deletions

View File

@ -66,8 +66,4 @@ nobase_include_HEADERS = \
netlink/socket.h \
netlink/types.h \
netlink/utils.h \
netlink/version.h \
netlink-generic.h \
netlink-local.h \
netlink-tc.h \
netlink-types.h
netlink/version.h

View File

@ -93,7 +93,9 @@ extern unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *);
extern struct nl_msg * nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *);
extern int nfnl_queue_msg_send_verdict(struct nl_sock *,
const struct nfnl_queue_msg *);
extern int nfnl_queue_msg_send_verdict_payload(struct nl_sock *,
const struct nfnl_queue_msg *,
const void *, unsigned );
#ifdef __cplusplus
}
#endif

View File

@ -51,6 +51,10 @@ extern int nl_sendto(struct nl_sock *, void *, size_t);
extern int nl_sendmsg(struct nl_sock *, struct nl_msg *,
struct msghdr *);
extern int nl_send(struct nl_sock *, struct nl_msg *);
extern int nl_send_iovec(struct nl_sock *, struct nl_msg *,
const struct iovec *, unsigned);
extern void nl_auto_complete(struct nl_sock *,
struct nl_msg *);
extern int nl_send_auto_complete(struct nl_sock *,
struct nl_msg *);
extern int nl_send_simple(struct nl_sock *, int, int,

View File

@ -198,7 +198,18 @@ extern "C" {
*
* @return True if the attribute is available, otherwise false is returned.
*/
#define AVAILABLE(A, B, ATTR) (((A)->ce_mask & (B)->ce_mask) & (ATTR))
#define AVAILABLE(A, B, ATTR) (((A)->ce_mask & (B)->ce_mask) & (ATTR))
/**
* Return true if attribute is available in only one of both objects
* @arg A an object
* @arg B another object
* @arg ATTR attribute bit
*
* @return True if the attribute is available in only one of both objects,
* otherwise false is returned.
*/
#define AVAILABLE_MISMATCH(A, B, ATTR) (((A)->ce_mask ^ (B)->ce_mask) & (ATTR))
/**
* Return true if attributes mismatch
@ -215,7 +226,8 @@ extern "C" {
*
* @return True if the attribute mismatch, or false if they match.
*/
#define ATTR_MISMATCH(A, B, ATTR, EXPR) (!AVAILABLE(A, B, ATTR) || (EXPR))
#define ATTR_MISMATCH(A, B, ATTR, EXPR) (AVAILABLE_MISMATCH(A, B, ATTR) || \
(AVAILABLE(A, B, ATTR) && (EXPR)))
/**
* Return attribute bit if attribute does not match

View File

@ -74,6 +74,9 @@ extern struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *);
extern int rtnl_addr_set_multicast(struct rtnl_addr *, struct nl_addr *);
extern struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *);
extern int rtnl_addr_set_anycast(struct rtnl_addr *, struct nl_addr *);
extern struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *);
extern uint32_t rtnl_addr_get_valid_lifetime(struct rtnl_addr *);
extern void rtnl_addr_set_valid_lifetime(struct rtnl_addr *, uint32_t);
extern uint32_t rtnl_addr_get_preferred_lifetime(struct rtnl_addr *);

View File

@ -605,9 +605,15 @@ int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache,
if (err < 0)
goto errout;
nl_list_for_each_entry_safe(obj, next, &cache->c_items, ce_list)
if (nl_object_is_marked(obj))
nl_list_for_each_entry_safe(obj, next, &cache->c_items, ce_list) {
if (nl_object_is_marked(obj)) {
nl_object_get(obj);
nl_cache_remove(obj);
if (change_cb)
change_cb(cache, obj, NL_ACT_DEL);
nl_object_put(obj);
}
}
NL_DBG(1, "Finished resyncing %p <%s>\n", cache, nl_cache_name(cache));

View File

@ -7,6 +7,7 @@
* of the License.
*
* Copyright (c) 2007, 2008 Patrick McHardy <kaber@trash.net>
* Copyright (c) 2010 Karl Hiramoto <karl@hiramoto.org>
*/
/**
@ -189,6 +190,12 @@ nla_put_failure:
return NULL;
}
/**
* Send a message verdict/mark
* @arg nlh netlink messsage header
* @arg msg queue msg
* @return 0 on OK or error code
*/
int nfnl_queue_msg_send_verdict(struct nl_sock *nlh,
const struct nfnl_queue_msg *msg)
{
@ -206,6 +213,51 @@ int nfnl_queue_msg_send_verdict(struct nl_sock *nlh,
return wait_for_ack(nlh);
}
/**
* Send a message verdict including the payload
* @arg nlh netlink messsage header
* @arg msg queue msg
* @arg payload_data packet payload data
* @arg payload_len payload length
* @return 0 on OK or error code
*/
int nfnl_queue_msg_send_verdict_payload(struct nl_sock *nlh,
const struct nfnl_queue_msg *msg,
const void *payload_data, unsigned payload_len)
{
struct nl_msg *nlmsg;
int err;
struct iovec iov[3];
struct nlattr nla;
nlmsg = nfnl_queue_msg_build_verdict(msg);
if (nlmsg == NULL)
return -NLE_NOMEM;
memset(iov, 0, sizeof(iov));
iov[0].iov_base = (void *) nlmsg_hdr(nlmsg);
iov[0].iov_len = nlmsg_hdr(nlmsg)->nlmsg_len;
nla.nla_type = NFQA_PAYLOAD;
nla.nla_len = payload_len + sizeof(nla);
nlmsg_hdr(nlmsg)->nlmsg_len += nla.nla_len;
iov[1].iov_base = (void *) &nla;
iov[1].iov_len = sizeof(nla);
iov[2].iov_base = (void *) payload_data;
iov[2].iov_len = NLA_ALIGN(payload_len);
nl_auto_complete(nlh, nlmsg);
err = nl_send_iovec(nlh, nlmsg, iov, 3);
nlmsg_free(nlmsg);
if (err < 0)
return err;
return wait_for_ack(nlh);
}
#define NFNLMSG_QUEUE_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_QUEUE, (type))
static struct nl_cache_ops nfnl_queue_msg_ops = {
.co_name = "netfilter/queue_msg",

View File

@ -197,6 +197,11 @@ uint16_t nfnl_queue_msg_get_group(const struct nfnl_queue_msg *msg)
return msg->queue_msg_group;
}
/**
* Set the protocol family
* @arg msg NF queue message
* @arg family AF_XXX address family example: AF_INET, AF_UNIX, etc
*/
void nfnl_queue_msg_set_family(struct nfnl_queue_msg *msg, uint8_t family)
{
msg->queue_msg_family = family;
@ -424,6 +429,11 @@ const void *nfnl_queue_msg_get_payload(const struct nfnl_queue_msg *msg, int *le
return msg->queue_msg_payload;
}
/**
* Return the number of items matching a filter in the cache
* @arg msg queue msg
* @arg verdict NF_DROP, NF_ACCEPT, NF_REPEAT, etc
*/
void nfnl_queue_msg_set_verdict(struct nfnl_queue_msg *msg,
unsigned int verdict)
{

View File

@ -207,14 +207,6 @@ int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr)
struct nl_cb *cb;
int ret;
struct iovec iov = {
.iov_base = (void *) nlmsg_hdr(msg),
.iov_len = nlmsg_hdr(msg)->nlmsg_len,
};
hdr->msg_iov = &iov;
hdr->msg_iovlen = 1;
nlmsg_set_src(msg, &sk->s_local);
cb = sk->s_cb;
@ -226,6 +218,7 @@ int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr)
if (ret < 0)
return -nl_syserr2nlerr(errno);
NL_DBG(4, "sent %d bytes\n", ret);
return ret;
}
@ -234,17 +227,20 @@ int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr)
* Send netlink message.
* @arg sk Netlink socket.
* @arg msg Netlink message to be sent.
* @arg iov iovec to be sent.
* @arg iovlen number of struct iovec to be sent.
* @see nl_sendmsg()
* @return Number of characters sent on success or a negative error code.
*/
int nl_send(struct nl_sock *sk, struct nl_msg *msg)
int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, const struct iovec *iov, unsigned iovlen)
{
struct sockaddr_nl *dst;
struct ucred *creds;
struct msghdr hdr = {
.msg_name = (void *) &sk->s_peer,
.msg_namelen = sizeof(struct sockaddr_nl),
.msg_iov = iov,
.msg_iovlen = iovlen,
};
/* Overwrite destination if specified in the message itself, defaults
@ -273,6 +269,45 @@ int nl_send(struct nl_sock *sk, struct nl_msg *msg)
return nl_sendmsg(sk, msg, &hdr);
}
/**
* Send netlink message.
* @arg sk Netlink socket.
* @arg msg Netlink message to be sent.
* @see nl_sendmsg()
* @return Number of characters sent on success or a negative error code.
*/
int nl_send(struct nl_sock *sk, struct nl_msg *msg)
{
struct iovec iov = {
.iov_base = (void *) nlmsg_hdr(msg),
.iov_len = nlmsg_hdr(msg)->nlmsg_len,
};
return nl_send_iovec(sk, msg, &iov, 1);
}
void nl_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
{
struct nlmsghdr *nlh;
nlh = nlmsg_hdr(msg);
if (nlh->nlmsg_pid == 0)
nlh->nlmsg_pid = sk->s_local.nl_pid;
if (nlh->nlmsg_seq == 0)
nlh->nlmsg_seq = sk->s_seq_next++;
if (msg->nm_protocol == -1)
msg->nm_protocol = sk->s_proto;
nlh->nlmsg_flags |= NLM_F_REQUEST;
if (!(sk->s_flags & NL_NO_AUTO_ACK))
nlh->nlmsg_flags |= NLM_F_ACK;
}
/**
* Send netlink message and check & extend header values as needed.
* @arg sk Netlink socket.
@ -287,23 +322,9 @@ int nl_send(struct nl_sock *sk, struct nl_msg *msg)
*/
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
{
struct nlmsghdr *nlh;
struct nl_cb *cb = sk->s_cb;
nlh = nlmsg_hdr(msg);
if (nlh->nlmsg_pid == 0)
nlh->nlmsg_pid = sk->s_local.nl_pid;
if (nlh->nlmsg_seq == 0)
nlh->nlmsg_seq = sk->s_seq_next++;
if (msg->nm_protocol == -1)
msg->nm_protocol = sk->s_proto;
nlh->nlmsg_flags |= NLM_F_REQUEST;
if (!(sk->s_flags & NL_NO_AUTO_ACK))
nlh->nlmsg_flags |= NLM_F_ACK;
nl_auto_complete(sk, msg);
if (cb->cb_send_ow)
return cb->cb_send_ow(sk, msg);

View File

@ -265,6 +265,8 @@ int nl_object_identical(struct nl_object *a, struct nl_object *b)
return 0;
req_attrs = ops->oo_id_attrs;
if (req_attrs == ~0)
req_attrs = a->ce_mask & b->ce_mask;
/* Both objects must provide all required attributes to uniquely
* identify an object */

View File

@ -126,6 +126,7 @@
#define ADDR_ATTR_LOCAL 0x0100
#define ADDR_ATTR_BROADCAST 0x0200
#define ADDR_ATTR_MULTICAST 0x0400
#define ADDR_ATTR_ANYCAST 0x0800
static struct nl_cache_ops rtnl_addr_ops;
static struct nl_object_ops addr_obj_ops;
@ -149,6 +150,7 @@ static void addr_free_data(struct nl_object *obj)
nl_addr_put(addr->a_local);
nl_addr_put(addr->a_bcast);
nl_addr_put(addr->a_multicast);
nl_addr_put(addr->a_anycast);
}
static int addr_clone(struct nl_object *_dst, struct nl_object *_src)
@ -172,6 +174,10 @@ static int addr_clone(struct nl_object *_dst, struct nl_object *_src)
if (!(dst->a_multicast = nl_addr_clone(src->a_multicast)))
return -NLE_NOMEM;
if (src->a_anycast)
if (!(dst->a_anycast = nl_addr_clone(src->a_anycast)))
return -NLE_NOMEM;
return 0;
}
@ -273,6 +279,15 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
addr->ce_mask |= ADDR_ATTR_MULTICAST;
}
if (tb[IFA_ANYCAST]) {
addr->a_anycast = nl_addr_alloc_attr(tb[IFA_ANYCAST],
family);
if (!addr->a_anycast)
goto errout_nomem;
addr->ce_mask |= ADDR_ATTR_ANYCAST;
}
err = pp->pp_cb((struct nl_object *) addr, pp);
errout:
rtnl_addr_put(addr);
@ -349,6 +364,11 @@ static void addr_dump_details(struct nl_object *obj, struct nl_dump_params *p)
nl_addr2str(addr->a_multicast, buf,
sizeof(buf)));
if (addr->ce_mask & ADDR_ATTR_ANYCAST)
nl_dump(p, " anycast %s",
nl_addr2str(addr->a_anycast, buf,
sizeof(buf)));
nl_dump(p, "\n");
}
@ -380,6 +400,81 @@ static void addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
addr_dump_details(obj, p);
}
static void addr_dump_env(struct nl_object *obj, struct nl_dump_params *p)
{
struct rtnl_addr *addr = (struct rtnl_addr *) obj;
struct nl_cache *link_cache;
char buf[128];
nl_dump_line(p, "ADDR_FAMILY=%s\n",
nl_af2str(addr->a_family, buf, sizeof(buf)));
if (addr->ce_mask & ADDR_ATTR_LOCAL)
nl_dump_line(p, "ADDR_LOCAL=%s\n",
nl_addr2str(addr->a_local, buf, sizeof(buf)));
if (addr->ce_mask & ADDR_ATTR_PEER)
nl_dump_line(p, "ADDR_PEER=%s\n",
nl_addr2str(addr->a_peer, buf, sizeof(buf)));
if (addr->ce_mask & ADDR_ATTR_BROADCAST)
nl_dump_line(p, "ADDR_BROADCAST=%s\n",
nl_addr2str(addr->a_bcast, buf, sizeof(buf)));
if (addr->ce_mask & ADDR_ATTR_ANYCAST)
nl_dump_line(p, "ADDR_ANYCAST=%s\n",
nl_addr2str(addr->a_anycast, buf, sizeof(buf)));
if (addr->ce_mask & ADDR_ATTR_MULTICAST)
nl_dump_line(p, "ADDR_MULTICAST=%s\n",
nl_addr2str(addr->a_multicast, buf,
sizeof(buf)));
if (addr->ce_mask & ADDR_ATTR_PREFIXLEN)
nl_dump_line(p, "ADDR_PREFIXLEN=%u\n",
addr->a_prefixlen);
link_cache = nl_cache_mngt_require("route/link");
nl_dump_line(p, "ADDR_IFINDEX=%u\n", addr->a_ifindex);
if (link_cache)
nl_dump_line(p, "ADDR_IFNAME=%s\n",
rtnl_link_i2name(link_cache, addr->a_ifindex,
buf, sizeof(buf)));
if (addr->ce_mask & ADDR_ATTR_SCOPE)
nl_dump_line(p, "ADDR_SCOPE=%s\n",
rtnl_scope2str(addr->a_scope, buf, sizeof(buf)));
if (addr->ce_mask & ADDR_ATTR_LABEL)
nl_dump_line(p, "ADDR_LABEL=%s\n", addr->a_label);
rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf));
if (buf[0])
nl_dump_line(p, "ADDR_FLAGS=%s\n", buf);
if (addr->ce_mask & ADDR_ATTR_CACHEINFO) {
struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo;
nl_dump_line(p, "ADDR_CACHEINFO_VALID=%s\n",
ci->aci_valid == 0xFFFFFFFFU ? "forever" :
nl_msec2str(ci->aci_valid * 1000,
buf, sizeof(buf)));
nl_dump_line(p, "ADDR_CACHEINFO_PREFERED=%s\n",
ci->aci_prefered == 0xFFFFFFFFU ? "forever" :
nl_msec2str(ci->aci_prefered * 1000,
buf, sizeof(buf)));
nl_dump_line(p, "ADDR_CACHEINFO_CREATED=%s\n",
nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10,
buf, sizeof(buf)));
nl_dump_line(p, "ADDR_CACHEINFO_LASTUPDATE=%s\n",
nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10,
buf, sizeof(buf)));
}
}
static int addr_compare(struct nl_object *_a, struct nl_object *_b,
uint32_t attrs, int flags)
{
@ -398,6 +493,7 @@ static int addr_compare(struct nl_object *_a, struct nl_object *_b,
diff |= ADDR_DIFF(MULTICAST, nl_addr_cmp(a->a_multicast,
b->a_multicast));
diff |= ADDR_DIFF(BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast));
diff |= ADDR_DIFF(ANYCAST, nl_addr_cmp(a->a_anycast, b->a_anycast));
if (flags & LOOSE_COMPARISON)
diff |= ADDR_DIFF(FLAGS,
@ -825,6 +921,17 @@ struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr)
return addr->a_multicast;
}
int rtnl_addr_set_anycast(struct rtnl_addr *addr, struct nl_addr *anycast)
{
return __assign_addr(addr, &addr->a_anycast, anycast,
ADDR_ATTR_ANYCAST);
}
struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *addr)
{
return addr->a_anycast;
}
uint32_t rtnl_addr_get_valid_lifetime(struct rtnl_addr *addr)
{
if (addr->ce_mask & ADDR_ATTR_CACHEINFO)
@ -903,6 +1010,7 @@ static struct nl_object_ops addr_obj_ops = {
[NL_DUMP_LINE] = addr_dump_line,
[NL_DUMP_DETAILS] = addr_dump_details,
[NL_DUMP_STATS] = addr_dump_stats,
[NL_DUMP_ENV] = addr_dump_env,
},
.oo_compare = addr_compare,
.oo_attrs2str = addr_attrs2str,

View File

@ -850,7 +850,7 @@ static struct nl_object_ops neigh_obj_ops = {
},
.oo_compare = neigh_compare,
.oo_attrs2str = neigh_attrs2str,
.oo_id_attrs = (NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY),
.oo_id_attrs = (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY),
};
static struct nl_af_group neigh_groups[] = {

View File

@ -285,7 +285,7 @@ static void __init get_psched_settings(void)
{
char name[FILENAME_MAX];
FILE *fd;
int got_hz = 0, got_tick = 0;
int got_hz = 0;
if (getenv("HZ")) {
long hz = strtol(getenv("HZ"), NULL, 0);
@ -301,28 +301,25 @@ static void __init get_psched_settings(void)
if (getenv("TICKS_PER_USEC")) {
double t = strtod(getenv("TICKS_PER_USEC"), NULL);
ticks_per_usec = t;
got_tick = 1;
}
else {
if (getenv("PROC_NET_PSCHED"))
snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED"));
else if (getenv("PROC_ROOT"))
snprintf(name, sizeof(name), "%s/net/psched",
getenv("PROC_ROOT"));
else
strncpy(name, "/proc/net/psched", sizeof(name) - 1);
if (getenv("PROC_NET_PSCHED"))
snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED"));
else if (getenv("PROC_ROOT"))
snprintf(name, sizeof(name), "%s/net/psched",
getenv("PROC_ROOT"));
else
strncpy(name, "/proc/net/psched", sizeof(name) - 1);
if ((fd = fopen(name, "r"))) {
uint32_t tick, us, nom;
int r = fscanf(fd, "%08x%08x%08x%*08x", &tick, &us, &nom);
if (4 == r && nom == 1000000 && !got_tick)
if ((fd = fopen(name, "r"))) {
uint32_t tick, us;
/* the file contains 4 hexadecimals, but we just use
the first two of them */
int r = fscanf(fd, "%08x %08x", &tick, &us);
ticks_per_usec = (double)tick/(double)us;
fclose(fd);
fclose(fd);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* src/nf-log.c Monitor netfilter queue events
* src/nf-queue.c Monitor netfilter queue events
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -7,6 +7,7 @@
* of the License.
*
* Copyright (c) 2007, 2008 Patrick McHardy <kaber@trash.net>
* Copyright (c) 2010 Karl Hiramoto <karl@hiramoto.org>
*/
@ -40,7 +41,31 @@ static void obj_input(struct nl_object *obj, void *arg)
.dp_fd = stdout,
.dp_dump_msgtype = 1,
};
uint32_t packet_id = nfnl_queue_msg_get_packetid(msg);
static uint32_t next_packet_id = 0;
struct nfnl_queue_msg *lost_msg = NULL;
uint8_t family;
uint16_t group;
if (packet_id > next_packet_id) {
printf("Warning: %d Out of order packets. Queue or socket overload \n", packet_id - next_packet_id);
group = nfnl_queue_msg_get_group(msg);
family = nfnl_queue_msg_get_family(msg);
lost_msg = nfnl_queue_msg_alloc();
do {
nfnl_queue_msg_set_group(lost_msg, group);
nfnl_queue_msg_set_family(lost_msg, family);
nfnl_queue_msg_set_packetid(lost_msg, next_packet_id);
nfnl_queue_msg_set_verdict(lost_msg, NF_ACCEPT);
nfnl_queue_msg_send_verdict(nf_sock, lost_msg);
next_packet_id++;
} while (packet_id > next_packet_id);
nfnl_queue_msg_put(lost_msg);
}
next_packet_id = packet_id + 1;
nfnl_queue_msg_set_verdict(msg, NF_ACCEPT);
nl_object_dump(obj, &dp);
nfnl_queue_msg_send_verdict(nf_sock, msg);
@ -75,6 +100,9 @@ int main(int argc, char *argv[])
if ((argc > 1 && !strcasecmp(argv[1], "-h")) || argc < 3) {
printf("Usage: nf-queue family group [ copy_mode ] "
"[ copy_range ]\n");
printf("family: [ inet | inet6 | ... ] \n");
printf("group: the --queue-num arg that you gave to iptables\n");
printf("copy_mode: [ none | meta | packet ] \n");
return 2;
}
@ -113,6 +141,8 @@ int main(int argc, char *argv[])
nl_cli_connect(rt_sock, NETLINK_ROUTE);
link_cache = nl_cli_link_alloc_cache(rt_sock);
nl_socket_set_buffer_size(nf_sock, 1024*127, 1024*127);
while (1) {
fd_set rfds;
int nffd, rtfd, maxfd, retval;