00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "internal.h"
00011
00012 #include <time.h>
00013 #include <endian.h>
00014 #include <stdlib.h>
00015 #include <string.h>
00016
00017 #include <libmnl/libmnl.h>
00018 #include <linux/netfilter/nfnetlink.h>
00019 #include <linux/netfilter/nfnetlink_acct.h>
00020
00021 #include <libnetfilter_acct/libnetfilter_acct.h>
00022
00058 struct nfacct {
00059 char name[NFACCT_NAME_MAX];
00060 uint64_t pkts;
00061 uint64_t bytes;
00062 uint32_t bitset;
00063 };
00064
00076 struct nfacct *nfacct_alloc(void)
00077 {
00078 return calloc(1, sizeof(struct nfacct));
00079 }
00080 EXPORT_SYMBOL(nfacct_alloc);
00081
00086 void nfacct_free(struct nfacct *nfacct)
00087 {
00088 free(nfacct);
00089 }
00090 EXPORT_SYMBOL(nfacct_free);
00091
00098 void
00099 nfacct_attr_set(struct nfacct *nfacct, enum nfacct_attr_type type,
00100 const void *data)
00101 {
00102 switch(type) {
00103 case NFACCT_ATTR_NAME:
00104 strncpy(nfacct->name, data, NFACCT_NAME_MAX);
00105 nfacct->name[NFACCT_NAME_MAX-1] = '\0';
00106 nfacct->bitset |= (1 << NFACCT_ATTR_NAME);
00107 break;
00108 case NFACCT_ATTR_PKTS:
00109 nfacct->bytes = *((uint64_t *) data);
00110 nfacct->bitset |= (1 << NFACCT_ATTR_PKTS);
00111 break;
00112 case NFACCT_ATTR_BYTES:
00113 nfacct->pkts = *((uint64_t *) data);
00114 nfacct->bitset |= (1 << NFACCT_ATTR_BYTES);
00115 break;
00116 }
00117 }
00118 EXPORT_SYMBOL(nfacct_attr_set);
00119
00126 void
00127 nfacct_attr_set_str(struct nfacct *nfacct, enum nfacct_attr_type type,
00128 const char *name)
00129 {
00130 nfacct_attr_set(nfacct, type, name);
00131 }
00132 EXPORT_SYMBOL(nfacct_attr_set_str);
00133
00140 void
00141 nfacct_attr_set_u64(struct nfacct *nfacct, enum nfacct_attr_type type,
00142 uint64_t value)
00143 {
00144 nfacct_attr_set(nfacct, type, &value);
00145 }
00146 EXPORT_SYMBOL(nfacct_attr_set_u64);
00147
00153 void
00154 nfacct_attr_unset(struct nfacct *nfacct, enum nfacct_attr_type type)
00155 {
00156 switch(type) {
00157 case NFACCT_ATTR_NAME:
00158 nfacct->bitset &= ~(1 << NFACCT_ATTR_NAME);
00159 break;
00160 case NFACCT_ATTR_PKTS:
00161 nfacct->bitset &= ~(1 << NFACCT_ATTR_PKTS);
00162 break;
00163 case NFACCT_ATTR_BYTES:
00164 nfacct->bitset &= ~(1 << NFACCT_ATTR_BYTES);
00165 break;
00166 }
00167 }
00168 EXPORT_SYMBOL(nfacct_attr_unset);
00169
00178 const void *nfacct_attr_get(struct nfacct *nfacct, enum nfacct_attr_type type)
00179 {
00180 const void *ret = NULL;
00181
00182 switch(type) {
00183 case NFACCT_ATTR_NAME:
00184 if (nfacct->bitset & (1 << NFACCT_ATTR_NAME))
00185 ret = nfacct->name;
00186 break;
00187 case NFACCT_ATTR_PKTS:
00188 if (nfacct->bitset & (1 << NFACCT_ATTR_PKTS))
00189 ret = &nfacct->pkts;
00190 break;
00191 case NFACCT_ATTR_BYTES:
00192 if (nfacct->bitset & (1 << NFACCT_ATTR_BYTES))
00193 ret = &nfacct->bytes;
00194 break;
00195 }
00196 return ret;
00197 }
00198 EXPORT_SYMBOL(nfacct_attr_get);
00199
00208 const char *
00209 nfacct_attr_get_str(struct nfacct *nfacct, enum nfacct_attr_type type)
00210 {
00211 return (char *)nfacct_attr_get(nfacct, type);
00212 }
00213 EXPORT_SYMBOL(nfacct_attr_get_str);
00214
00223 uint64_t nfacct_attr_get_u64(struct nfacct *nfacct, enum nfacct_attr_type type)
00224 {
00225 const void *ret = nfacct_attr_get(nfacct, type);
00226 return ret ? *((uint64_t *)ret) : 0;
00227 }
00228 EXPORT_SYMBOL(nfacct_attr_get_u64);
00229
00241 int nfacct_snprintf(char *buf, size_t size, struct nfacct *nfacct,
00242 uint16_t type, uint16_t flags)
00243 {
00244 int ret = 0;
00245
00246 switch(type) {
00247 case NFACCT_SNPRINTF_T_PLAIN:
00248 if (flags & NFACCT_SNPRINTF_F_FULL) {
00249 ret = snprintf(buf, size,
00250 "{ pkts = %.20llu, bytes = %.20llu } = %s;",
00251 (unsigned long long)
00252 nfacct_attr_get_u64(nfacct, NFACCT_ATTR_BYTES),
00253 (unsigned long long)
00254 nfacct_attr_get_u64(nfacct, NFACCT_ATTR_PKTS),
00255 nfacct_attr_get_str(nfacct, NFACCT_ATTR_NAME));
00256 } else {
00257 ret = snprintf(buf, size, "%s\n",
00258 nfacct_attr_get_str(nfacct, NFACCT_ATTR_NAME));
00259 }
00260 break;
00261 case NFACCT_SNPRINTF_T_XML:
00262 ret = snprintf(buf, size,
00263 "<obj><name>%s</name>"
00264 "<pkts>%.20llu</pkts>"
00265 "<bytes>%.20llu</bytes></obj>",
00266 nfacct_attr_get_str(nfacct, NFACCT_ATTR_NAME),
00267 (unsigned long long)
00268 nfacct_attr_get_u64(nfacct, NFACCT_ATTR_BYTES),
00269 (unsigned long long)
00270 nfacct_attr_get_u64(nfacct, NFACCT_ATTR_PKTS));
00271 break;
00272 default:
00273 ret = -1;
00274 break;
00275 }
00276 return ret;
00277 }
00278 EXPORT_SYMBOL(nfacct_snprintf);
00279
00317 struct nlmsghdr *
00318 nfacct_nlmsg_build_hdr(char *buf, uint8_t cmd, uint16_t flags, uint32_t seq)
00319 {
00320 struct nlmsghdr *nlh;
00321 struct nfgenmsg *nfh;
00322
00323 nlh = mnl_nlmsg_put_header(buf);
00324 nlh->nlmsg_type = (NFNL_SUBSYS_ACCT << 8) | cmd;
00325 nlh->nlmsg_flags = NLM_F_REQUEST | flags;
00326 nlh->nlmsg_seq = seq;
00327
00328 nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
00329 nfh->nfgen_family = AF_UNSPEC;
00330 nfh->version = NFNETLINK_V0;
00331 nfh->res_id = 0;
00332
00333 return nlh;
00334 }
00335 EXPORT_SYMBOL(nfacct_nlmsg_build_hdr);
00336
00342 void nfacct_nlmsg_build_payload(struct nlmsghdr *nlh, struct nfacct *nfacct)
00343 {
00344 if (nfacct->bitset & (1 << NFACCT_ATTR_NAME))
00345 mnl_attr_put_strz(nlh, NFACCT_NAME, nfacct->name);
00346
00347 if (nfacct->bitset & (1 << NFACCT_ATTR_PKTS))
00348 mnl_attr_put_u64(nlh, NFACCT_PKTS, htobe64(nfacct->pkts));
00349
00350 if (nfacct->bitset & (1 << NFACCT_ATTR_BYTES))
00351 mnl_attr_put_u64(nlh, NFACCT_PKTS, htobe64(nfacct->bytes));
00352 }
00353 EXPORT_SYMBOL(nfacct_nlmsg_build_payload);
00354
00355 static int nfacct_nlmsg_parse_attr_cb(const struct nlattr *attr, void *data)
00356 {
00357 const struct nlattr **tb = data;
00358 int type = mnl_attr_get_type(attr);
00359
00360 if (mnl_attr_type_valid(attr, NFACCT_MAX) < 0)
00361 return MNL_CB_OK;
00362
00363 switch(type) {
00364 case NFACCT_NAME:
00365 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
00366 perror("mnl_attr_validate");
00367 return MNL_CB_ERROR;
00368 }
00369 break;
00370 case NFACCT_PKTS:
00371 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) {
00372 perror("mnl_attr_validate");
00373 return MNL_CB_ERROR;
00374 }
00375 break;
00376 case NFACCT_BYTES:
00377 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) {
00378 perror("mnl_attr_validate");
00379 return MNL_CB_ERROR;
00380 }
00381 break;
00382 }
00383 tb[type] = attr;
00384 return MNL_CB_OK;
00385 }
00386
00395 int
00396 nfacct_nlmsg_parse_payload(const struct nlmsghdr *nlh, struct nfacct *nfacct)
00397 {
00398 struct nlattr *tb[NFACCT_MAX+1] = {};
00399 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
00400
00401 mnl_attr_parse(nlh, sizeof(*nfg), nfacct_nlmsg_parse_attr_cb, tb);
00402 if (!tb[NFACCT_NAME] && !tb[NFACCT_PKTS] && !tb[NFACCT_BYTES])
00403 return -1;
00404
00405 nfacct_attr_set_str(nfacct, NFACCT_ATTR_NAME,
00406 mnl_attr_get_str(tb[NFACCT_NAME]));
00407 nfacct_attr_set_u64(nfacct, NFACCT_ATTR_PKTS,
00408 be64toh(mnl_attr_get_u64(tb[NFACCT_PKTS])));
00409 nfacct_attr_set_u64(nfacct, NFACCT_ATTR_BYTES,
00410 be64toh(mnl_attr_get_u64(tb[NFACCT_BYTES])));
00411
00412 return 0;
00413 }
00414 EXPORT_SYMBOL(nfacct_nlmsg_parse_payload);
00415