libnftnl  1.0.8
buffer.c
1 /*
2  * (C) 2012-2014 by 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 <stdio.h>
11 #include <stdint.h>
12 #include <stdarg.h>
13 #include <inttypes.h>
14 #include <string.h>
15 #include <buffer.h>
16 #include <libnftnl/common.h>
17 #include <libnftnl/expr.h>
18 #include "internal.h"
19 
20 int nftnl_buf_update(struct nftnl_buf *b, int ret)
21 {
22  if (ret < 0) {
23  b->fail = true;
24  } else {
25  b->off += ret;
26  if (ret > b->len)
27  ret = b->len;
28  b->size += ret;
29  b->len -= ret;
30  }
31 
32  return ret;
33 }
34 
35 int nftnl_buf_done(struct nftnl_buf *b)
36 {
37  if (b->fail)
38  return -1;
39 
40  /* Remove trailing comma in json */
41  if (b->size > 0 && b->buf[b->size - 1] == ',') {
42  b->off--;
43  b->size--;
44  b->len++;
45  }
46 
47  return b->off;
48 }
49 
50 static int nftnl_buf_put(struct nftnl_buf *b, const char *fmt, ...)
51 {
52  int ret;
53  va_list ap;
54 
55  va_start(ap, fmt);
56  ret = vsnprintf(b->buf + b->off, b->len, fmt, ap);
57  ret = nftnl_buf_update(b, ret);
58  va_end(ap);
59 
60  return ret;
61 }
62 
63 int nftnl_buf_open(struct nftnl_buf *b, int type, const char *tag)
64 {
65  switch (type) {
66  case NFTNL_OUTPUT_JSON:
67  return nftnl_buf_put(b, "{\"%s\":{", tag);
68  case NFTNL_OUTPUT_XML:
69  default:
70  return 0;
71  }
72 }
73 
74 int nftnl_buf_close(struct nftnl_buf *b, int type, const char *tag)
75 {
76  switch (type) {
77  case NFTNL_OUTPUT_JSON:
78  /* Remove trailing comma in json */
79  if (b->size > 0 && b->buf[b->size - 1] == ',') {
80  b->off--;
81  b->size--;
82  b->len++;
83  }
84 
85  return nftnl_buf_put(b, "}}");
86  case NFTNL_OUTPUT_XML:
87  default:
88  return 0;
89  }
90 }
91 
92 int nftnl_buf_open_array(struct nftnl_buf *b, int type, const char *tag)
93 {
94  switch (type) {
95  case NFTNL_OUTPUT_JSON:
96  return nftnl_buf_put(b, "{\"%s\":[", tag);
97  case NFTNL_OUTPUT_XML:
98  default:
99  return 0;
100  }
101 }
102 
103 int nftnl_buf_close_array(struct nftnl_buf *b, int type, const char *tag)
104 {
105  switch (type) {
106  case NFTNL_OUTPUT_JSON:
107  return nftnl_buf_put(b, "]}");
108  case NFTNL_OUTPUT_XML:
109  default:
110  return 0;
111  }
112 }
113 
114 int nftnl_buf_u32(struct nftnl_buf *b, int type, uint32_t value, const char *tag)
115 {
116  switch (type) {
117  case NFTNL_OUTPUT_JSON:
118  return nftnl_buf_put(b, "\"%s\":%u,", tag, value);
119  case NFTNL_OUTPUT_XML:
120  default:
121  return 0;
122  }
123 }
124 
125 int nftnl_buf_s32(struct nftnl_buf *b, int type, uint32_t value, const char *tag)
126 {
127  switch (type) {
128  case NFTNL_OUTPUT_JSON:
129  return nftnl_buf_put(b, "\"%s\":%d,", tag, value);
130  case NFTNL_OUTPUT_XML:
131  default:
132  return 0;
133  }
134 }
135 
136 int nftnl_buf_u64(struct nftnl_buf *b, int type, uint64_t value, const char *tag)
137 {
138  switch (type) {
139  case NFTNL_OUTPUT_JSON:
140  return nftnl_buf_put(b, "\"%s\":%"PRIu64",", tag, value);
141  case NFTNL_OUTPUT_XML:
142  default:
143  return 0;
144  }
145 }
146 
147 int nftnl_buf_str(struct nftnl_buf *b, int type, const char *str, const char *tag)
148 {
149  switch (type) {
150  case NFTNL_OUTPUT_JSON:
151  return nftnl_buf_put(b, "\"%s\":\"%s\",", tag, str);
152  case NFTNL_OUTPUT_XML:
153  default:
154  return 0;
155  }
156 }
157 
158 int nftnl_buf_reg(struct nftnl_buf *b, int type, union nftnl_data_reg *reg,
159  int reg_type, const char *tag)
160 {
161  int ret;
162 
163  switch (type) {
164  case NFTNL_OUTPUT_XML:
165  return 0;
166  case NFTNL_OUTPUT_JSON:
167  nftnl_buf_put(b, "\"%s\":{", tag);
168  ret = nftnl_data_reg_snprintf(b->buf + b->off, b->len, reg,
169  NFTNL_OUTPUT_JSON, 0, reg_type);
170  nftnl_buf_update(b, ret);
171  return nftnl_buf_put(b, "},");
172  }
173  return 0;
174 }
175 
176 int nftnl_buf_expr_open(struct nftnl_buf *b, int type)
177 {
178  switch (type) {
179  case NFTNL_OUTPUT_XML:
180  return 0;
181  case NFTNL_OUTPUT_JSON:
182  return nftnl_buf_put(b, "\"expr\":[");
183  }
184  return 0;
185 }
186 
187 int nftnl_buf_expr_close(struct nftnl_buf *b, int type)
188 {
189  switch (type) {
190  case NFTNL_OUTPUT_XML:
191  return 0;
192  case NFTNL_OUTPUT_JSON:
193  nftnl_buf_done(b);
194  return nftnl_buf_put(b, "]");
195  }
196  return 0;
197 }
198 
199 int nftnl_buf_expr(struct nftnl_buf *b, int type, uint32_t flags,
200  struct nftnl_expr *expr)
201 {
202  int ret;
203 
204  switch (type) {
205  case NFTNL_OUTPUT_XML:
206  return 0;
207  case NFTNL_OUTPUT_JSON:
208  nftnl_buf_put(b, "{");
209  nftnl_buf_str(b, type, expr->ops->name, TYPE);
210  ret = nftnl_expr_snprintf(b->buf + b->off, b->len, expr, type,
211  flags);
212  if (ret > 0)
213  nftnl_buf_update(b, ret);
214  else
215  nftnl_buf_done(b);
216 
217  return nftnl_buf_put(b, "},");
218  }
219  return 0;
220 }