libnetfilter_conntrack  1.0.8
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_OFFLOAD)
188  size = snprintf(buf, len, "[OFFLOAD] ");
189  else if (ct->status & IPS_ASSURED)
190  size = snprintf(buf, len, "[ASSURED] ");
191 
192  return size;
193 }
194 
195 static int __snprintf_status_not_seen_reply(char *buf,
196  unsigned int len,
197  const struct nf_conntrack *ct)
198 {
199  int size = 0;
200 
201  if (!(ct->status & IPS_SEEN_REPLY))
202  size = snprintf(buf, len, "[UNREPLIED] ");
203 
204  return size;
205 }
206 
207 static int __snprintf_counters(char *buf,
208  unsigned int len,
209  const struct nf_conntrack *ct,
210  int dir)
211 {
212  return (snprintf(buf, len, "packets=%llu bytes=%llu ",
213  (unsigned long long) ct->counters[dir].packets,
214  (unsigned long long) ct->counters[dir].bytes));
215 }
216 
217 static int
218 __snprintf_mark(char *buf, unsigned int len, const struct nf_conntrack *ct)
219 {
220  return (snprintf(buf, len, "mark=%u ", ct->mark));
221 }
222 
223 static int
224 __snprintf_secmark(char *buf, unsigned int len, const struct nf_conntrack *ct)
225 {
226  return (snprintf(buf, len, "secmark=%u ", ct->secmark));
227 }
228 
229 static int
230 __snprintf_use(char *buf, unsigned int len, const struct nf_conntrack *ct)
231 {
232  return (snprintf(buf, len, "use=%u ", ct->use));
233 }
234 
235 static int
236 __snprintf_id(char *buf, unsigned int len, const struct nf_conntrack *ct)
237 {
238  return (snprintf(buf, len, "id=%u ", ct->id));
239 }
240 
241 static int
242 __snprintf_zone(char *buf, unsigned int len, const struct nf_conntrack *ct)
243 {
244  return (snprintf(buf, len, "zone=%u ", ct->zone));
245 }
246 
247 static int
248 __snprintf_secctx(char *buf, unsigned int len, const struct nf_conntrack *ct)
249 {
250  return (snprintf(buf, len, "secctx=%s ", ct->secctx));
251 }
252 
253 static int
254 __snprintf_timestamp_start(char *buf, unsigned int len,
255  const struct nf_conntrack *ct)
256 {
257  time_t start = (time_t)(ct->timestamp.start / NSEC_PER_SEC);
258  char *tmp = ctime(&start);
259 
260  /* overwrite \n in the ctime() output. */
261  tmp[strlen(tmp)-1] = '\0';
262  return (snprintf(buf, len, "[start=%s] ", tmp));
263 }
264 
265 static int
266 __snprintf_timestamp_stop(char *buf, unsigned int len,
267  const struct nf_conntrack *ct)
268 {
269  time_t stop = (time_t)(ct->timestamp.stop / NSEC_PER_SEC);
270  char *tmp = ctime(&stop);
271 
272  /* overwrite \n in the ctime() output. */
273  tmp[strlen(tmp)-1] = '\0';
274  return (snprintf(buf, len, "[stop=%s] ", tmp));
275 }
276 
277 static int
278 __snprintf_timestamp_delta(char *buf, unsigned int len,
279  const struct nf_conntrack *ct)
280 {
281  time_t delta_time, stop;
282 
283  if (ct->timestamp.stop == 0)
284  time(&stop);
285  else
286  stop = (time_t)(ct->timestamp.stop / NSEC_PER_SEC);
287 
288  delta_time = stop - (time_t)(ct->timestamp.start / NSEC_PER_SEC);
289 
290  return (snprintf(buf, len, "delta-time=%llu ",
291  (unsigned long long)delta_time));
292 }
293 
294 static int
295 __snprintf_helper_name(char *buf, unsigned int len, const struct nf_conntrack *ct)
296 {
297  return (snprintf(buf, len, "helper=%s ", ct->helper_name));
298 }
299 
300 int
301 __snprintf_connlabels(char *buf, unsigned int len,
302  struct nfct_labelmap *map,
303  const struct nfct_bitmask *b, const char *fmt)
304 {
305  unsigned int i, max;
306  int ret, size = 0, offset = 0;
307 
308  max = nfct_bitmask_maxbit(b);
309  for (i = 0; i <= max && len; i++) {
310  const char *name;
311  if (!nfct_bitmask_test_bit(b, i))
312  continue;
313  name = nfct_labelmap_get_name(map, i);
314  if (!name || strcmp(name, "") == 0)
315  continue;
316 
317  ret = snprintf(buf + offset, len, fmt, name);
318  BUFFER_SIZE(ret, size, len, offset);
319  }
320  return size;
321 }
322 
323 static int
324 __snprintf_clabels(char *buf, unsigned int len,
325  const struct nf_conntrack *ct, struct nfct_labelmap *map)
326 {
327  const struct nfct_bitmask *b = nfct_get_attr(ct, ATTR_CONNLABELS);
328  int ret, size = 0, offset = 0;
329 
330  if (!b)
331  return 0;
332 
333  ret = snprintf(buf, len, "labels=");
334  BUFFER_SIZE(ret, size, len, offset);
335 
336  ret = __snprintf_connlabels(buf + offset, len, map, b, "%s,");
337 
338  BUFFER_SIZE(ret, size, len, offset);
339 
340  offset--; /* remove last , */
341  size--;
342  ret = snprintf(buf + offset, len, " ");
343  BUFFER_SIZE(ret, size, len, offset);
344 
345  return size;
346 }
347 
348 int __snprintf_conntrack_default(char *buf,
349  unsigned int len,
350  const struct nf_conntrack *ct,
351  unsigned int msg_type,
352  unsigned int flags,
353  struct nfct_labelmap *map)
354 {
355  int ret = 0, size = 0, offset = 0;
356 
357  switch(msg_type) {
358  case NFCT_T_NEW:
359  ret = snprintf(buf, len, "%9s ", "[NEW]");
360  break;
361  case NFCT_T_UPDATE:
362  ret = snprintf(buf, len, "%9s ", "[UPDATE]");
363  break;
364  case NFCT_T_DESTROY:
365  ret = snprintf(buf, len, "%9s ", "[DESTROY]");
366  break;
367  default:
368  break;
369  }
370 
371  BUFFER_SIZE(ret, size, len, offset);
372 
373  if (flags & NFCT_OF_SHOW_LAYER3) {
374  ret = __snprintf_l3protocol(buf+offset, len, ct);
375  BUFFER_SIZE(ret, size, len, offset);
376  }
377 
378  ret = __snprintf_protocol(buf+offset, len, ct);
379  BUFFER_SIZE(ret, size, len, offset);
380 
381  if (test_bit(ATTR_TIMEOUT, ct->head.set)) {
382  ret = __snprintf_timeout(buf+offset, len, ct);
383  BUFFER_SIZE(ret, size, len, offset);
384  }
385 
386  if (test_bit(ATTR_TCP_STATE, ct->head.set)) {
387  ret = __snprintf_protoinfo(buf+offset, len, ct);
388  BUFFER_SIZE(ret, size, len, offset);
389  }
390 
391  if (test_bit(ATTR_SCTP_STATE, ct->head.set)) {
392  ret = __snprintf_protoinfo_sctp(buf+offset, len, ct);
393  BUFFER_SIZE(ret, size, len, offset);
394  }
395 
396  if (test_bit(ATTR_DCCP_STATE, ct->head.set)) {
397  ret = __snprintf_protoinfo_dccp(buf+offset, len, ct);
398  BUFFER_SIZE(ret, size, len, offset);
399  }
400 
401  ret = __snprintf_address(buf+offset, len, &ct->head.orig,
402  "src", "dst");
403  BUFFER_SIZE(ret, size, len, offset);
404 
405  ret = __snprintf_proto(buf+offset, len, &ct->head.orig);
406  BUFFER_SIZE(ret, size, len, offset);
407 
408  if (test_bit(ATTR_ORIG_ZONE, ct->head.set)) {
409  ret = __snprintf_tuple_zone(buf+offset, len, "orig", &ct->head.orig);
410  BUFFER_SIZE(ret, size, len, offset);
411  }
412 
413  if (test_bit(ATTR_ORIG_COUNTER_PACKETS, ct->head.set) &&
414  test_bit(ATTR_ORIG_COUNTER_BYTES, ct->head.set)) {
415  ret = __snprintf_counters(buf+offset, len, ct, __DIR_ORIG);
416  BUFFER_SIZE(ret, size, len, offset);
417  }
418 
419  if (test_bit(ATTR_STATUS, ct->head.set)) {
420  ret = __snprintf_status_not_seen_reply(buf+offset, len, ct);
421  BUFFER_SIZE(ret, size, len, offset);
422  }
423 
424  ret = __snprintf_address(buf+offset, len, &ct->repl,
425  "src", "dst");
426  BUFFER_SIZE(ret, size, len, offset);
427 
428  ret = __snprintf_proto(buf+offset, len, &ct->repl);
429  BUFFER_SIZE(ret, size, len, offset);
430 
431  if (test_bit(ATTR_REPL_ZONE, ct->head.set)) {
432  ret = __snprintf_tuple_zone(buf+offset, len, "reply", &ct->repl);
433  BUFFER_SIZE(ret, size, len, offset);
434  }
435 
436  if (test_bit(ATTR_REPL_COUNTER_PACKETS, ct->head.set) &&
437  test_bit(ATTR_REPL_COUNTER_BYTES, ct->head.set)) {
438  ret = __snprintf_counters(buf+offset, len, ct, __DIR_REPL);
439  BUFFER_SIZE(ret, size, len, offset);
440  }
441 
442  if (test_bit(ATTR_STATUS, ct->head.set)) {
443  ret = __snprintf_status_assured(buf+offset, len, ct);
444  BUFFER_SIZE(ret, size, len, offset);
445  }
446 
447  if (test_bit(ATTR_MARK, ct->head.set)) {
448  ret = __snprintf_mark(buf+offset, len, ct);
449  BUFFER_SIZE(ret, size, len, offset);
450  }
451 
452  if (test_bit(ATTR_SECMARK, ct->head.set)) {
453  ret = __snprintf_secmark(buf+offset, len, ct);
454  BUFFER_SIZE(ret, size, len, offset);
455  }
456 
457  if (test_bit(ATTR_SECCTX, ct->head.set)) {
458  ret = __snprintf_secctx(buf+offset, len, ct);
459  BUFFER_SIZE(ret, size, len, offset);
460  }
461 
462  if (test_bit(ATTR_ZONE, ct->head.set)) {
463  ret = __snprintf_zone(buf+offset, len, ct);
464  BUFFER_SIZE(ret, size, len, offset);
465  }
466 
467  if (test_bit(ATTR_TIMESTAMP_START, ct->head.set)) {
468  ret = __snprintf_timestamp_delta(buf+offset, len, ct);
469  BUFFER_SIZE(ret, size, len, offset);
470  }
471  if (flags & NFCT_OF_TIMESTAMP) {
472  if (test_bit(ATTR_TIMESTAMP_START, ct->head.set)) {
473  ret = __snprintf_timestamp_start(buf+offset, len, ct);
474  BUFFER_SIZE(ret, size, len, offset);
475  }
476  if (test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
477  ret = __snprintf_timestamp_stop(buf+offset, len, ct);
478  BUFFER_SIZE(ret, size, len, offset);
479  }
480  }
481 
482  if (test_bit(ATTR_HELPER_NAME, ct->head.set)) {
483  ret = __snprintf_helper_name(buf+offset, len, ct);
484  BUFFER_SIZE(ret, size, len, offset);
485  }
486 
487  if (test_bit(ATTR_USE, ct->head.set)) {
488  ret = __snprintf_use(buf+offset, len, ct);
489  BUFFER_SIZE(ret, size, len, offset);
490  }
491 
492  if (flags & NFCT_OF_ID && test_bit(ATTR_ID, ct->head.set)) {
493  ret = __snprintf_id(buf+offset, len, ct);
494  BUFFER_SIZE(ret, size, len, offset);
495  }
496 
497  if (map && test_bit(ATTR_CONNLABELS, ct->head.set)) {
498  ret = __snprintf_clabels(buf+offset, len, ct, map);
499  BUFFER_SIZE(ret, size, len, offset);
500  }
501 
502  /* Delete the last blank space */
503  size--;
504 
505  return size;
506 }
const void * nfct_get_attr(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
const char * nfct_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)