libnetfilter_conntrack  1.0.6
conntrack/snprintf_default.c
1 /*
2  * (C) 2005-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  */
9 
10 #include "internal/internal.h"
11 
12 static int __snprintf_l3protocol(char *buf,
13  unsigned int len,
14  const struct nf_conntrack *ct)
15 {
16  return (snprintf(buf, len, "%-8s %u ",
17  l3proto2str[ct->head.orig.l3protonum] == NULL ?
18  "unknown" : l3proto2str[ct->head.orig.l3protonum],
19  ct->head.orig.l3protonum));
20 }
21 
22 int __snprintf_protocol(char *buf,
23  unsigned int len,
24  const struct nf_conntrack *ct)
25 {
26  return (snprintf(buf, len, "%-8s %u ",
27  proto2str[ct->head.orig.protonum] == NULL ?
28  "unknown" : proto2str[ct->head.orig.protonum],
29  ct->head.orig.protonum));
30 }
31 
32 static int __snprintf_timeout(char *buf,
33  unsigned int len,
34  const struct nf_conntrack *ct)
35 {
36  return snprintf(buf, len, "%u ", ct->timeout);
37 }
38 
39 static int __snprintf_protoinfo(char *buf,
40  unsigned int len,
41  const struct nf_conntrack *ct)
42 {
43  return snprintf(buf, len, "%s ",
44  ct->protoinfo.tcp.state < TCP_CONNTRACK_MAX ?
45  states[ct->protoinfo.tcp.state] :
46  states[TCP_CONNTRACK_NONE]);
47 }
48 
49 static int __snprintf_protoinfo_sctp(char *buf,
50  unsigned int len,
51  const struct nf_conntrack *ct)
52 {
53  return snprintf(buf, len, "%s ",
54  ct->protoinfo.sctp.state < SCTP_CONNTRACK_MAX ?
55  sctp_states[ct->protoinfo.sctp.state] :
56  sctp_states[SCTP_CONNTRACK_NONE]);
57 }
58 
59 static int __snprintf_protoinfo_dccp(char *buf,
60  unsigned int len,
61  const struct nf_conntrack *ct)
62 {
63  return snprintf(buf, len, "%s ",
64  ct->protoinfo.dccp.state < DCCP_CONNTRACK_MAX ?
65  sctp_states[ct->protoinfo.dccp.state] :
66  sctp_states[DCCP_CONNTRACK_NONE]);
67 }
68 
69 static int __snprintf_address_ipv4(char *buf,
70  unsigned int len,
71  const struct __nfct_tuple *tuple,
72  const char *src_tag,
73  const char *dst_tag)
74 {
75  int ret, size = 0, offset = 0;
76  struct in_addr src = { .s_addr = tuple->src.v4 };
77  struct in_addr dst = { .s_addr = tuple->dst.v4 };
78 
79  ret = snprintf(buf, len, "%s=%s ", src_tag, inet_ntoa(src));
80  BUFFER_SIZE(ret, size, len, offset);
81 
82  ret = snprintf(buf+offset, len, "%s=%s ", dst_tag, inet_ntoa(dst));
83  BUFFER_SIZE(ret, size, len, offset);
84 
85  return size;
86 }
87 
88 static int __snprintf_address_ipv6(char *buf,
89  unsigned int len,
90  const struct __nfct_tuple *tuple,
91  const char *src_tag,
92  const char *dst_tag)
93 {
94  int ret, size = 0, offset = 0;
95  struct in6_addr src;
96  struct in6_addr dst;
97  char tmp[INET6_ADDRSTRLEN];
98 
99  memcpy(&src, &tuple->src.v6, sizeof(struct in6_addr));
100  memcpy(&dst, &tuple->dst.v6, sizeof(struct in6_addr));
101 
102  if (!inet_ntop(AF_INET6, &src, tmp, sizeof(tmp)))
103  return -1;
104 
105  ret = snprintf(buf, len, "%s=%s ", src_tag, tmp);
106  BUFFER_SIZE(ret, size, len, offset);
107 
108  if (!inet_ntop(AF_INET6, &dst, tmp, sizeof(tmp)))
109  return -1;
110 
111  ret = snprintf(buf+offset, len-size, "%s=%s ", dst_tag, tmp);
112  BUFFER_SIZE(ret, size, len, offset);
113 
114  return size;
115 }
116 
117 int __snprintf_address(char *buf,
118  unsigned int len,
119  const struct __nfct_tuple *tuple,
120  const char *src_tag,
121  const char *dst_tag)
122 {
123  int size = 0;
124 
125  switch (tuple->l3protonum) {
126  case AF_INET:
127  size = __snprintf_address_ipv4(buf, len, tuple,
128  src_tag, dst_tag);
129  break;
130  case AF_INET6:
131  size = __snprintf_address_ipv6(buf, len, tuple,
132  src_tag, dst_tag);
133  break;
134  }
135 
136  return size;
137 }
138 
139 int __snprintf_proto(char *buf,
140  unsigned int len,
141  const struct __nfct_tuple *tuple)
142 {
143  int size = 0;
144 
145  switch(tuple->protonum) {
146  case IPPROTO_TCP:
147  case IPPROTO_UDP:
148  case IPPROTO_UDPLITE:
149  case IPPROTO_SCTP:
150  case IPPROTO_DCCP:
151  return snprintf(buf, len, "sport=%u dport=%u ",
152  ntohs(tuple->l4src.tcp.port),
153  ntohs(tuple->l4dst.tcp.port));
154  break;
155  case IPPROTO_GRE:
156  return snprintf(buf, len, "srckey=0x%x dstkey=0x%x ",
157  ntohs(tuple->l4src.all),
158  ntohs(tuple->l4dst.all));
159  break;
160  case IPPROTO_ICMP:
161  case IPPROTO_ICMPV6:
162  /* The ID only makes sense some ICMP messages but we want to
163  * display the same output that /proc/net/ip_conntrack does */
164  return (snprintf(buf, len, "type=%d code=%d id=%d ",
165  tuple->l4dst.icmp.type,
166  tuple->l4dst.icmp.code,
167  ntohs(tuple->l4src.icmp.id)));
168  break;
169  }
170 
171  return size;
172 }
173 
174 static int
175 __snprintf_tuple_zone(char *buf, unsigned int len, const char *pfx,
176  const struct __nfct_tuple *tuple)
177 {
178  return (snprintf(buf, len, "zone-%s=%u ", pfx, tuple->zone));
179 }
180 
181 static int __snprintf_status_assured(char *buf,
182  unsigned int len,
183  const struct nf_conntrack *ct)
184 {
185  int size = 0;
186 
187  if (ct->status & IPS_ASSURED)
188  size = snprintf(buf, len, "[ASSURED] ");
189 
190  return size;
191 }
192 
193 static int __snprintf_status_not_seen_reply(char *buf,
194  unsigned int len,
195  const struct nf_conntrack *ct)
196 {
197  int size = 0;
198 
199  if (!(ct->status & IPS_SEEN_REPLY))
200  size = snprintf(buf, len, "[UNREPLIED] ");
201 
202  return size;
203 }
204 
205 static int __snprintf_counters(char *buf,
206  unsigned int len,
207  const struct nf_conntrack *ct,
208  int dir)
209 {
210  return (snprintf(buf, len, "packets=%llu bytes=%llu ",
211  (unsigned long long) ct->counters[dir].packets,
212  (unsigned long long) ct->counters[dir].bytes));
213 }
214 
215 static int
216 __snprintf_mark(char *buf, unsigned int len, const struct nf_conntrack *ct)
217 {
218  return (snprintf(buf, len, "mark=%u ", ct->mark));
219 }
220 
221 static int
222 __snprintf_secmark(char *buf, unsigned int len, const struct nf_conntrack *ct)
223 {
224  return (snprintf(buf, len, "secmark=%u ", ct->secmark));
225 }
226 
227 static int
228 __snprintf_use(char *buf, unsigned int len, const struct nf_conntrack *ct)
229 {
230  return (snprintf(buf, len, "use=%u ", ct->use));
231 }
232 
233 static int
234 __snprintf_id(char *buf, unsigned int len, const struct nf_conntrack *ct)
235 {
236  return (snprintf(buf, len, "id=%u ", ct->id));
237 }
238 
239 static int
240 __snprintf_zone(char *buf, unsigned int len, const struct nf_conntrack *ct)
241 {
242  return (snprintf(buf, len, "zone=%u ", ct->zone));
243 }
244 
245 static int
246 __snprintf_secctx(char *buf, unsigned int len, const struct nf_conntrack *ct)
247 {
248  return (snprintf(buf, len, "secctx=%s ", ct->secctx));
249 }
250 
251 static int
252 __snprintf_timestamp_start(char *buf, unsigned int len,
253  const struct nf_conntrack *ct)
254 {
255  time_t start = (time_t)(ct->timestamp.start / NSEC_PER_SEC);
256  char *tmp = ctime(&start);
257 
258  /* overwrite \n in the ctime() output. */
259  tmp[strlen(tmp)-1] = '\0';
260  return (snprintf(buf, len, "[start=%s] ", tmp));
261 }
262 
263 static int
264 __snprintf_timestamp_stop(char *buf, unsigned int len,
265  const struct nf_conntrack *ct)
266 {
267  time_t stop = (time_t)(ct->timestamp.stop / NSEC_PER_SEC);
268  char *tmp = ctime(&stop);
269 
270  /* overwrite \n in the ctime() output. */
271  tmp[strlen(tmp)-1] = '\0';
272  return (snprintf(buf, len, "[stop=%s] ", tmp));
273 }
274 
275 static int
276 __snprintf_timestamp_delta(char *buf, unsigned int len,
277  const struct nf_conntrack *ct)
278 {
279  time_t delta_time, stop;
280 
281  if (ct->timestamp.stop == 0)
282  time(&stop);
283  else
284  stop = (time_t)(ct->timestamp.stop / NSEC_PER_SEC);
285 
286  delta_time = stop - (time_t)(ct->timestamp.start / NSEC_PER_SEC);
287 
288  return (snprintf(buf, len, "delta-time=%llu ",
289  (unsigned long long)delta_time));
290 }
291 
292 static int
293 __snprintf_helper_name(char *buf, unsigned int len, const struct nf_conntrack *ct)
294 {
295  return (snprintf(buf, len, "helper=%s ", ct->helper_name));
296 }
297 
298 int
299 __snprintf_connlabels(char *buf, unsigned int len,
300  struct nfct_labelmap *map,
301  const struct nfct_bitmask *b, const char *fmt)
302 {
303  unsigned int i, max;
304  int ret, size = 0, offset = 0;
305 
306  max = nfct_bitmask_maxbit(b);
307  for (i = 0; i <= max && len; i++) {
308  const char *name;
309  if (!nfct_bitmask_test_bit(b, i))
310  continue;
311  name = nfct_labelmap_get_name(map, i);
312  if (!name || strcmp(name, "") == 0)
313  continue;
314 
315  ret = snprintf(buf + offset, len, fmt, name);
316  BUFFER_SIZE(ret, size, len, offset);
317  }
318  return size;
319 }
320 
321 static int
322 __snprintf_clabels(char *buf, unsigned int len,
323  const struct nf_conntrack *ct, struct nfct_labelmap *map)
324 {
325  const struct nfct_bitmask *b = nfct_get_attr(ct, ATTR_CONNLABELS);
326  int ret, size = 0, offset = 0;
327 
328  if (!b)
329  return 0;
330 
331  ret = snprintf(buf, len, "labels=");
332  BUFFER_SIZE(ret, size, len, offset);
333 
334  ret = __snprintf_connlabels(buf + offset, len, map, b, "%s,");
335 
336  BUFFER_SIZE(ret, size, len, offset);
337 
338  offset--; /* remove last , */
339  size--;
340  ret = snprintf(buf + offset, len, " ");
341  BUFFER_SIZE(ret, size, len, offset);
342 
343  return size;
344 }
345 
346 int __snprintf_conntrack_default(char *buf,
347  unsigned int len,
348  const struct nf_conntrack *ct,
349  unsigned int msg_type,
350  unsigned int flags,
351  struct nfct_labelmap *map)
352 {
353  int ret = 0, size = 0, offset = 0;
354 
355  switch(msg_type) {
356  case NFCT_T_NEW:
357  ret = snprintf(buf, len, "%9s ", "[NEW]");
358  break;
359  case NFCT_T_UPDATE:
360  ret = snprintf(buf, len, "%9s ", "[UPDATE]");
361  break;
362  case NFCT_T_DESTROY:
363  ret = snprintf(buf, len, "%9s ", "[DESTROY]");
364  break;
365  default:
366  break;
367  }
368 
369  BUFFER_SIZE(ret, size, len, offset);
370 
371  if (flags & NFCT_OF_SHOW_LAYER3) {
372  ret = __snprintf_l3protocol(buf+offset, len, ct);
373  BUFFER_SIZE(ret, size, len, offset);
374  }
375 
376  ret = __snprintf_protocol(buf+offset, len, ct);
377  BUFFER_SIZE(ret, size, len, offset);
378 
379  if (test_bit(ATTR_TIMEOUT, ct->head.set)) {
380  ret = __snprintf_timeout(buf+offset, len, ct);
381  BUFFER_SIZE(ret, size, len, offset);
382  }
383 
384  if (test_bit(ATTR_TCP_STATE, ct->head.set)) {
385  ret = __snprintf_protoinfo(buf+offset, len, ct);
386  BUFFER_SIZE(ret, size, len, offset);
387  }
388 
389  if (test_bit(ATTR_SCTP_STATE, ct->head.set)) {
390  ret = __snprintf_protoinfo_sctp(buf+offset, len, ct);
391  BUFFER_SIZE(ret, size, len, offset);
392  }
393 
394  if (test_bit(ATTR_DCCP_STATE, ct->head.set)) {
395  ret = __snprintf_protoinfo_dccp(buf+offset, len, ct);
396  BUFFER_SIZE(ret, size, len, offset);
397  }
398 
399  ret = __snprintf_address(buf+offset, len, &ct->head.orig,
400  "src", "dst");
401  BUFFER_SIZE(ret, size, len, offset);
402 
403  ret = __snprintf_proto(buf+offset, len, &ct->head.orig);
404  BUFFER_SIZE(ret, size, len, offset);
405 
406  if (test_bit(ATTR_ORIG_ZONE, ct->head.set)) {
407  ret = __snprintf_tuple_zone(buf+offset, len, "orig", &ct->head.orig);
408  BUFFER_SIZE(ret, size, len, offset);
409  }
410 
411  if (test_bit(ATTR_ORIG_COUNTER_PACKETS, ct->head.set) &&
412  test_bit(ATTR_ORIG_COUNTER_BYTES, ct->head.set)) {
413  ret = __snprintf_counters(buf+offset, len, ct, __DIR_ORIG);
414  BUFFER_SIZE(ret, size, len, offset);
415  }
416 
417  if (test_bit(ATTR_STATUS, ct->head.set)) {
418  ret = __snprintf_status_not_seen_reply(buf+offset, len, ct);
419  BUFFER_SIZE(ret, size, len, offset);
420  }
421 
422  ret = __snprintf_address(buf+offset, len, &ct->repl,
423  "src", "dst");
424  BUFFER_SIZE(ret, size, len, offset);
425 
426  ret = __snprintf_proto(buf+offset, len, &ct->repl);
427  BUFFER_SIZE(ret, size, len, offset);
428 
429  if (test_bit(ATTR_REPL_ZONE, ct->head.set)) {
430  ret = __snprintf_tuple_zone(buf+offset, len, "reply", &ct->repl);
431  BUFFER_SIZE(ret, size, len, offset);
432  }
433 
434  if (test_bit(ATTR_REPL_COUNTER_PACKETS, ct->head.set) &&
435  test_bit(ATTR_REPL_COUNTER_BYTES, ct->head.set)) {
436  ret = __snprintf_counters(buf+offset, len, ct, __DIR_REPL);
437  BUFFER_SIZE(ret, size, len, offset);
438  }
439 
440  if (test_bit(ATTR_STATUS, ct->head.set)) {
441  ret = __snprintf_status_assured(buf+offset, len, ct);
442  BUFFER_SIZE(ret, size, len, offset);
443  }
444 
445  if (test_bit(ATTR_MARK, ct->head.set)) {
446  ret = __snprintf_mark(buf+offset, len, ct);
447  BUFFER_SIZE(ret, size, len, offset);
448  }
449 
450  if (test_bit(ATTR_SECMARK, ct->head.set)) {
451  ret = __snprintf_secmark(buf+offset, len, ct);
452  BUFFER_SIZE(ret, size, len, offset);
453  }
454 
455  if (test_bit(ATTR_SECCTX, ct->head.set)) {
456  ret = __snprintf_secctx(buf+offset, len, ct);
457  BUFFER_SIZE(ret, size, len, offset);
458  }
459 
460  if (test_bit(ATTR_ZONE, ct->head.set)) {
461  ret = __snprintf_zone(buf+offset, len, ct);
462  BUFFER_SIZE(ret, size, len, offset);
463  }
464 
465  if (test_bit(ATTR_TIMESTAMP_START, ct->head.set)) {
466  ret = __snprintf_timestamp_delta(buf+offset, len, ct);
467  BUFFER_SIZE(ret, size, len, offset);
468  }
469  if (flags & NFCT_OF_TIMESTAMP) {
470  if (test_bit(ATTR_TIMESTAMP_START, ct->head.set)) {
471  ret = __snprintf_timestamp_start(buf+offset, len, ct);
472  BUFFER_SIZE(ret, size, len, offset);
473  }
474  if (test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
475  ret = __snprintf_timestamp_stop(buf+offset, len, ct);
476  BUFFER_SIZE(ret, size, len, offset);
477  }
478  }
479 
480  if (test_bit(ATTR_HELPER_NAME, ct->head.set)) {
481  ret = __snprintf_helper_name(buf+offset, len, ct);
482  BUFFER_SIZE(ret, size, len, offset);
483  }
484 
485  if (test_bit(ATTR_USE, ct->head.set)) {
486  ret = __snprintf_use(buf+offset, len, ct);
487  BUFFER_SIZE(ret, size, len, offset);
488  }
489 
490  if (flags & NFCT_OF_ID && test_bit(ATTR_ID, ct->head.set)) {
491  ret = __snprintf_id(buf+offset, len, ct);
492  BUFFER_SIZE(ret, size, len, offset);
493  }
494 
495  if (map && test_bit(ATTR_CONNLABELS, ct->head.set)) {
496  ret = __snprintf_clabels(buf+offset, len, ct, map);
497  BUFFER_SIZE(ret, size, len, offset);
498  }
499 
500  /* Delete the last blank space */
501  size--;
502 
503  return size;
504 }
const char * nfct_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)
const void * nfct_get_attr(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)