18 #include <libmnl/libmnl.h>
19 #include <linux/netfilter/nfnetlink.h>
20 #include <linux/netfilter/nfnetlink_acct.h>
22 #include <libnetfilter_acct/libnetfilter_acct.h>
60 char name[NFACCT_NAME_MAX];
81 return calloc(1,
sizeof(
struct nfacct));
106 case NFACCT_ATTR_NAME:
107 strncpy(nfacct->name, data, NFACCT_NAME_MAX);
108 nfacct->name[NFACCT_NAME_MAX-1] =
'\0';
109 nfacct->bitset |= (1 << NFACCT_ATTR_NAME);
111 case NFACCT_ATTR_PKTS:
112 nfacct->pkts = *((uint64_t *) data);
113 nfacct->bitset |= (1 << NFACCT_ATTR_PKTS);
115 case NFACCT_ATTR_BYTES:
116 nfacct->bytes = *((uint64_t *) data);
117 nfacct->bitset |= (1 << NFACCT_ATTR_BYTES);
119 case NFACCT_ATTR_FLAGS:
120 nfacct->flags = *((uint32_t *) data);
121 nfacct->bitset |= (1 << NFACCT_ATTR_FLAGS);
123 case NFACCT_ATTR_QUOTA:
124 nfacct->quota = *((uint64_t *) data);
125 nfacct->bitset |= (1 << NFACCT_ATTR_QUOTA);
168 case NFACCT_ATTR_NAME:
169 nfacct->bitset &= ~(1 << NFACCT_ATTR_NAME);
171 case NFACCT_ATTR_PKTS:
172 nfacct->bitset &= ~(1 << NFACCT_ATTR_PKTS);
174 case NFACCT_ATTR_BYTES:
175 nfacct->bitset &= ~(1 << NFACCT_ATTR_BYTES);
177 case NFACCT_ATTR_FLAGS:
178 nfacct->bitset &= ~(1 << NFACCT_ATTR_FLAGS);
180 case NFACCT_ATTR_QUOTA:
181 nfacct->bitset &= ~(1 << NFACCT_ATTR_QUOTA);
197 const void *ret = NULL;
200 case NFACCT_ATTR_NAME:
201 if (nfacct->bitset & (1 << NFACCT_ATTR_NAME))
204 case NFACCT_ATTR_PKTS:
205 if (nfacct->bitset & (1 << NFACCT_ATTR_PKTS))
208 case NFACCT_ATTR_BYTES:
209 if (nfacct->bitset & (1 << NFACCT_ATTR_BYTES))
210 ret = &nfacct->bytes;
212 case NFACCT_ATTR_FLAGS:
213 if (nfacct->bitset & (1 << NFACCT_ATTR_FLAGS))
214 ret = &nfacct->flags;
216 case NFACCT_ATTR_QUOTA:
217 if (nfacct->bitset & (1 << NFACCT_ATTR_QUOTA))
218 ret = &nfacct->quota;
251 return ret ? *((uint64_t *)ret) : 0;
256 nfacct_snprintf_plain(
char *buf,
size_t rem,
struct nfacct *nfacct,
259 int ret, offset = 0, len = 0;
261 if (flags & NFACCT_SNPRINTF_F_FULL) {
262 ret = snprintf(buf, rem,
263 "{ pkts = %.20"PRIu64
", bytes = %.20"PRIu64
"",
266 SNPRINTF_CHECK(ret, rem, offset, len);
273 if (mode & NFACCT_F_QUOTA_PKTS)
274 mode_name =
"packet";
275 else if (mode & NFACCT_F_QUOTA_BYTES)
278 mode_name =
"unknown";
280 ret = snprintf(buf + offset, rem,
281 ", quota = %.20"PRIu64
", mode = %s"\
285 mode & NFACCT_F_OVERQUOTA ?
"yes" :
"no");
286 SNPRINTF_CHECK(ret, rem, offset, len);
289 ret = snprintf(buf + offset, rem,
" } = %s;",
292 ret = snprintf(buf, rem,
"%s\n",
295 SNPRINTF_CHECK(ret, rem, offset, len);
301 nfacct_snprintf_json(
char *buf,
size_t rem,
struct nfacct *nfacct,
304 int ret = 0, offset = 0, len = 0;
306 if (flags & NFACCT_SNPRINTF_F_FULL) {
307 ret = snprintf(buf, rem,
308 " { \"pkts\" : %"PRIu64
", \"bytes\" : %"PRIu64
"",
311 SNPRINTF_CHECK(ret, rem, offset, len);
318 if (mode & NFACCT_F_QUOTA_PKTS)
319 mode_name =
"packet";
320 else if (mode & NFACCT_F_QUOTA_BYTES)
323 mode_name =
"unknown";
325 ret = snprintf(buf + offset, rem,
326 ", \"quota\" : %"PRIu64
", \"mode\" = \"%s\""\
327 ", \"overquota\" = %u",
330 mode & NFACCT_F_OVERQUOTA ? 1 : 0);
331 SNPRINTF_CHECK(ret, rem, offset, len);
334 ret = snprintf(buf + offset, rem,
", \"name\" : \"%s\" }",
338 SNPRINTF_CHECK(ret, rem, offset, len);
343 #define BUFFER_SIZE(ret, size, rem, offset) \
351 nfacct_snprintf_xml_localtime(
char *buf,
unsigned int rem,
const struct tm *tm)
354 unsigned int size = 0, offset = 0;
356 ret = snprintf(buf+offset, rem,
"<hour>%d</hour>", tm->tm_hour);
357 BUFFER_SIZE(ret, size, rem, offset);
359 ret = snprintf(buf+offset, rem,
"<min>%02d</min>", tm->tm_min);
360 BUFFER_SIZE(ret, size, rem, offset);
362 ret = snprintf(buf+offset, rem,
"<sec>%02d</sec>", tm->tm_sec);
363 BUFFER_SIZE(ret, size, rem, offset);
365 ret = snprintf(buf+offset, rem,
"<wday>%d</wday>", tm->tm_wday + 1);
366 BUFFER_SIZE(ret, size, rem, offset);
368 ret = snprintf(buf+offset, rem,
"<day>%d</day>", tm->tm_mday);
369 BUFFER_SIZE(ret, size, rem, offset);
371 ret = snprintf(buf+offset, rem,
"<month>%d</month>", tm->tm_mon + 1);
372 BUFFER_SIZE(ret, size, rem, offset);
374 ret = snprintf(buf+offset, rem,
"<year>%d</year>", 1900 + tm->tm_year);
375 BUFFER_SIZE(ret, size, rem, offset);
382 nfacct_snprintf_xml(
char *buf,
size_t rem,
struct nfacct *nfacct,
386 unsigned int size = 0, offset = 0;
388 ret = snprintf(buf, rem,
389 "<obj><name>%s</name>"
390 "<pkts>%.20"PRIu64
"</pkts>"
391 "<bytes>%.20"PRIu64
"</bytes>",
395 BUFFER_SIZE(ret, size, rem, offset);
397 if (flags & NFACCT_SNPRINTF_F_TIME) {
402 if (localtime_r(&t, &tm) == NULL)
405 ret = nfacct_snprintf_xml_localtime(buf+offset, rem, &tm);
406 BUFFER_SIZE(ret, size, rem, offset);
409 ret = snprintf(buf+offset, rem,
"</obj>");
410 BUFFER_SIZE(ret, size, rem, offset);
428 uint16_t type, uint16_t flags)
433 case NFACCT_SNPRINTF_T_PLAIN:
434 ret = nfacct_snprintf_plain(buf, size, nfacct, flags);
436 case NFACCT_SNPRINTF_T_XML:
437 ret = nfacct_snprintf_xml(buf, size, nfacct, flags);
439 case NFACCT_SNPRINTF_T_JSON:
440 ret = nfacct_snprintf_json(buf, size, nfacct, flags);
490 struct nlmsghdr *nlh;
491 struct nfgenmsg *nfh;
493 nlh = mnl_nlmsg_put_header(buf);
494 nlh->nlmsg_type = (NFNL_SUBSYS_ACCT << 8) | cmd;
495 nlh->nlmsg_flags = NLM_F_REQUEST | flags;
496 nlh->nlmsg_seq = seq;
498 nfh = mnl_nlmsg_put_extra_header(nlh,
sizeof(
struct nfgenmsg));
499 nfh->nfgen_family = AF_UNSPEC;
500 nfh->version = NFNETLINK_V0;
514 if (nfacct->bitset & (1 << NFACCT_ATTR_NAME))
515 mnl_attr_put_strz(nlh, NFACCT_NAME, nfacct->name);
517 if (nfacct->bitset & (1 << NFACCT_ATTR_PKTS))
518 mnl_attr_put_u64(nlh, NFACCT_PKTS, htobe64(nfacct->pkts));
520 if (nfacct->bitset & (1 << NFACCT_ATTR_BYTES))
521 mnl_attr_put_u64(nlh, NFACCT_BYTES, htobe64(nfacct->bytes));
523 if (nfacct->bitset & (1 << NFACCT_ATTR_FLAGS))
524 mnl_attr_put_u32(nlh, NFACCT_FLAGS, htobe32(nfacct->flags));
526 if (nfacct->bitset & (1 << NFACCT_ATTR_QUOTA))
527 mnl_attr_put_u64(nlh, NFACCT_QUOTA, htobe64(nfacct->quota));
531 static int nfacct_nlmsg_parse_attr_cb(
const struct nlattr *attr,
void *data)
533 const struct nlattr **tb = data;
534 int type = mnl_attr_get_type(attr);
536 if (mnl_attr_type_valid(attr, NFACCT_MAX) < 0)
541 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
542 perror(
"mnl_attr_validate");
548 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) {
549 perror(
"mnl_attr_validate");
569 struct nlattr *tb[NFACCT_MAX+1] = {};
570 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
572 mnl_attr_parse(nlh,
sizeof(*nfg), nfacct_nlmsg_parse_attr_cb, tb);
573 if (!tb[NFACCT_NAME] && !tb[NFACCT_PKTS] && !tb[NFACCT_BYTES])
577 mnl_attr_get_str(tb[NFACCT_NAME]));
579 be64toh(mnl_attr_get_u64(tb[NFACCT_PKTS])));
581 be64toh(mnl_attr_get_u64(tb[NFACCT_BYTES])));
583 if (tb[NFACCT_FLAGS] && tb[NFACCT_QUOTA]) {
584 uint32_t flags = be32toh(mnl_attr_get_u32(tb[NFACCT_FLAGS]));
587 be64toh(mnl_attr_get_u64(tb[NFACCT_QUOTA])));
const void * nfacct_attr_get(struct nfacct *nfacct, enum nfacct_attr_type type)
void nfacct_nlmsg_build_payload(struct nlmsghdr *nlh, struct nfacct *nfacct)
void nfacct_attr_set(struct nfacct *nfacct, enum nfacct_attr_type type, const void *data)
const char * nfacct_attr_get_str(struct nfacct *nfacct, enum nfacct_attr_type type)
void nfacct_attr_unset(struct nfacct *nfacct, enum nfacct_attr_type type)
void nfacct_free(struct nfacct *nfacct)
uint64_t nfacct_attr_get_u64(struct nfacct *nfacct, enum nfacct_attr_type type)
int nfacct_nlmsg_parse_payload(const struct nlmsghdr *nlh, struct nfacct *nfacct)
struct nlmsghdr * nfacct_nlmsg_build_hdr(char *buf, uint8_t cmd, uint16_t flags, uint32_t seq)
struct nfacct * nfacct_alloc(void)
int nfacct_snprintf(char *buf, size_t size, struct nfacct *nfacct, uint16_t type, uint16_t flags)
void nfacct_attr_set_str(struct nfacct *nfacct, enum nfacct_attr_type type, const char *name)
void nfacct_attr_set_u64(struct nfacct *nfacct, enum nfacct_attr_type type, uint64_t value)