libnftnl 1.2.6
batch.c
1/*
2 * Copyright (c) 2013-2015 Pablo Neira Ayuso <pablo@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#include "internal.h"
11#include <errno.h>
12#include <libmnl/libmnl.h>
13#include <libnftnl/batch.h>
14
16 uint32_t num_pages;
17 struct nftnl_batch_page *current_page;
18 uint32_t page_size;
19 uint32_t page_overrun_size;
20 struct list_head page_list;
21};
22
24 struct list_head head;
25 struct mnl_nlmsg_batch *batch;
26};
27
28static struct nftnl_batch_page *nftnl_batch_page_alloc(struct nftnl_batch *batch)
29{
30 struct nftnl_batch_page *page;
31 char *buf;
32
33 page = malloc(sizeof(struct nftnl_batch_page));
34 if (page == NULL)
35 return NULL;
36
37 buf = malloc(batch->page_size + batch->page_overrun_size);
38 if (buf == NULL)
39 goto err1;
40
41 page->batch = mnl_nlmsg_batch_start(buf, batch->page_size);
42 if (page->batch == NULL)
43 goto err2;
44
45 return page;
46err2:
47 free(buf);
48err1:
49 free(page);
50 return NULL;
51}
52
53static void nftnl_batch_add_page(struct nftnl_batch_page *page,
54 struct nftnl_batch *batch)
55{
56 batch->current_page = page;
57 batch->num_pages++;
58 list_add_tail(&page->head, &batch->page_list);
59}
60
61EXPORT_SYMBOL(nftnl_batch_alloc);
62struct nftnl_batch *nftnl_batch_alloc(uint32_t pg_size, uint32_t pg_overrun_size)
63{
64 struct nftnl_batch *batch;
65 struct nftnl_batch_page *page;
66
67 batch = calloc(1, sizeof(struct nftnl_batch));
68 if (batch == NULL)
69 return NULL;
70
71 batch->page_size = pg_size;
72 batch->page_overrun_size = pg_overrun_size;
73 INIT_LIST_HEAD(&batch->page_list);
74
75 page = nftnl_batch_page_alloc(batch);
76 if (page == NULL)
77 goto err1;
78
79 nftnl_batch_add_page(page, batch);
80 return batch;
81err1:
82 free(batch);
83 return NULL;
84}
85
86EXPORT_SYMBOL(nftnl_batch_free);
87void nftnl_batch_free(struct nftnl_batch *batch)
88{
89 struct nftnl_batch_page *page, *next;
90
91 list_for_each_entry_safe(page, next, &batch->page_list, head) {
92 free(mnl_nlmsg_batch_head(page->batch));
93 mnl_nlmsg_batch_stop(page->batch);
94 free(page);
95 }
96
97 free(batch);
98}
99
100EXPORT_SYMBOL(nftnl_batch_update);
101int nftnl_batch_update(struct nftnl_batch *batch)
102{
103 struct nftnl_batch_page *page;
104 struct nlmsghdr *last_nlh;
105
106 if (mnl_nlmsg_batch_next(batch->current_page->batch))
107 return 0;
108
109 last_nlh = nftnl_batch_buffer(batch);
110
111 page = nftnl_batch_page_alloc(batch);
112 if (page == NULL)
113 goto err1;
114
115 nftnl_batch_add_page(page, batch);
116
117 memcpy(nftnl_batch_buffer(batch), last_nlh, last_nlh->nlmsg_len);
118 mnl_nlmsg_batch_next(batch->current_page->batch);
119
120 return 0;
121err1:
122 return -1;
123}
124
125EXPORT_SYMBOL(nftnl_batch_buffer);
126void *nftnl_batch_buffer(struct nftnl_batch *batch)
127{
128 return mnl_nlmsg_batch_current(batch->current_page->batch);
129}
130
131EXPORT_SYMBOL(nftnl_batch_buffer_len);
132uint32_t nftnl_batch_buffer_len(struct nftnl_batch *batch)
133{
134 return mnl_nlmsg_batch_size(batch->current_page->batch);
135}
136
137EXPORT_SYMBOL(nftnl_batch_iovec_len);
138int nftnl_batch_iovec_len(struct nftnl_batch *batch)
139{
140 int num_pages = batch->num_pages;
141
142 /* Skip last page if it's empty */
143 if (mnl_nlmsg_batch_is_empty(batch->current_page->batch))
144 num_pages--;
145
146 return num_pages;
147}
148
149EXPORT_SYMBOL(nftnl_batch_iovec);
150void nftnl_batch_iovec(struct nftnl_batch *batch, struct iovec *iov,
151 uint32_t iovlen)
152{
153 struct nftnl_batch_page *page;
154 int i = 0;
155
156 list_for_each_entry(page, &batch->page_list, head) {
157 if (i >= iovlen)
158 break;
159
160 iov[i].iov_base = mnl_nlmsg_batch_head(page->batch);
161 iov[i].iov_len = mnl_nlmsg_batch_size(page->batch);
162 i++;
163 }
164}