netfilter: xt_qtaguid: 1st pass at tracking tag based data resources
[linux-2.6.git] / net / netfilter / xt_qtaguid_print.c
1 /*
2  * Pretty printing Support for iptables xt_qtaguid module.
3  *
4  * (C) 2011 Google, Inc
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 /*
12  * There are run-time debug flags enabled via the debug_mask module param, or
13  * via the DEFAULT_DEBUG_MASK. See xt_qtaguid_internal.h.
14  */
15 #define DEBUG
16
17 #include <linux/fs.h>
18 #include <linux/gfp.h>
19 #include <linux/net.h>
20 #include <linux/rbtree.h>
21 #include <linux/slab.h>
22 #include <linux/spinlock_types.h>
23
24
25 #include "xt_qtaguid_internal.h"
26 #include "xt_qtaguid_print.h"
27
28 char *pp_tag_t(tag_t *tag)
29 {
30         if (!tag)
31                 return kasprintf(GFP_ATOMIC, "tag_t@null{}");
32         return kasprintf(GFP_ATOMIC,
33                          "tag_t@%p{tag=0x%llx, uid=%u}",
34                          tag, *tag, get_uid_from_tag(*tag));
35 }
36
37 char *pp_data_counters(struct data_counters *dc, bool showValues)
38 {
39         if (!dc)
40                 return kasprintf(GFP_ATOMIC, "data_counters@null{}");
41         if (showValues)
42                 return kasprintf(
43                         GFP_ATOMIC, "data_counters@%p{"
44                         "set0{"
45                         "rx{"
46                         "tcp{b=%llu, p=%llu}, "
47                         "udp{b=%llu, p=%llu},"
48                         "other{b=%llu, p=%llu}}, "
49                         "tx{"
50                         "tcp{b=%llu, p=%llu}, "
51                         "udp{b=%llu, p=%llu},"
52                         "other{b=%llu, p=%llu}}}, "
53                         "set1{"
54                         "rx{"
55                         "tcp{b=%llu, p=%llu}, "
56                         "udp{b=%llu, p=%llu},"
57                         "other{b=%llu, p=%llu}}, "
58                         "tx{"
59                         "tcp{b=%llu, p=%llu}, "
60                         "udp{b=%llu, p=%llu},"
61                         "other{b=%llu, p=%llu}}}}",
62                         dc,
63                         dc->bpc[0][IFS_RX][IFS_TCP].bytes,
64                         dc->bpc[0][IFS_RX][IFS_TCP].packets,
65                         dc->bpc[0][IFS_RX][IFS_UDP].bytes,
66                         dc->bpc[0][IFS_RX][IFS_UDP].packets,
67                         dc->bpc[0][IFS_RX][IFS_PROTO_OTHER].bytes,
68                         dc->bpc[0][IFS_RX][IFS_PROTO_OTHER].packets,
69                         dc->bpc[0][IFS_TX][IFS_TCP].bytes,
70                         dc->bpc[0][IFS_TX][IFS_TCP].packets,
71                         dc->bpc[0][IFS_TX][IFS_UDP].bytes,
72                         dc->bpc[0][IFS_TX][IFS_UDP].packets,
73                         dc->bpc[0][IFS_TX][IFS_PROTO_OTHER].bytes,
74                         dc->bpc[0][IFS_TX][IFS_PROTO_OTHER].packets,
75                         dc->bpc[1][IFS_RX][IFS_TCP].bytes,
76                         dc->bpc[1][IFS_RX][IFS_TCP].packets,
77                         dc->bpc[1][IFS_RX][IFS_UDP].bytes,
78                         dc->bpc[1][IFS_RX][IFS_UDP].packets,
79                         dc->bpc[1][IFS_RX][IFS_PROTO_OTHER].bytes,
80                         dc->bpc[1][IFS_RX][IFS_PROTO_OTHER].packets,
81                         dc->bpc[1][IFS_TX][IFS_TCP].bytes,
82                         dc->bpc[1][IFS_TX][IFS_TCP].packets,
83                         dc->bpc[1][IFS_TX][IFS_UDP].bytes,
84                         dc->bpc[1][IFS_TX][IFS_UDP].packets,
85                         dc->bpc[1][IFS_TX][IFS_PROTO_OTHER].bytes,
86                         dc->bpc[1][IFS_TX][IFS_PROTO_OTHER].packets);
87         else
88                 return kasprintf(GFP_ATOMIC, "data_counters@%p{...}", dc);
89 }
90
91 char *pp_tag_node(struct tag_node *tn)
92 {
93         char *tag_str;
94         char *res;
95
96         if (!tn)
97                 return kasprintf(GFP_ATOMIC, "tag_node@null{}");
98         tag_str = pp_tag_t(&tn->tag);
99         res = kasprintf(GFP_ATOMIC,
100                         "tag_node@%p{tag=%s}",
101                         tn, tag_str);
102         kfree(tag_str);
103         return res;
104 }
105
106 char *pp_tag_ref(struct tag_ref *tr)
107 {
108         char *tn_str;
109         char *res;
110
111         if (!tr)
112                 return kasprintf(GFP_ATOMIC, "tag_ref@null{}");
113         tn_str = pp_tag_node(&tr->tn);
114         res = kasprintf(GFP_ATOMIC,
115                         "tag_ref@%p{%s, num_sock_tags=%d}",
116                         tr, tn_str, tr->num_sock_tags);
117         kfree(tn_str);
118         return res;
119 }
120
121 char *pp_tag_stat(struct tag_stat *ts)
122 {
123         char *tn_str;
124         char *counters_str;
125         char *parent_counters_str;
126         char *res;
127
128         if (!ts)
129                 return kasprintf(GFP_ATOMIC, "tag_stat@null{}");
130         tn_str = pp_tag_node(&ts->tn);
131         counters_str = pp_data_counters(&ts->counters, true);
132         parent_counters_str = pp_data_counters(ts->parent_counters, false);
133         res = kasprintf(GFP_ATOMIC,
134                         "tag_stat@%p{%s, counters=%s, parent_counters=%s}",
135                         ts, tn_str, counters_str, parent_counters_str);
136         kfree(tn_str);
137         kfree(counters_str);
138         kfree(parent_counters_str);
139         return res;
140 }
141
142 char *pp_iface_stat(struct iface_stat *is)
143 {
144         if (!is)
145                 return kasprintf(GFP_ATOMIC, "iface_stat@null{}");
146         return kasprintf(GFP_ATOMIC, "iface_stat@%p{"
147                          "list=list_head{...}, "
148                          "ifname=%s, "
149                          "rx_bytes=%llu, "
150                          "rx_packets=%llu, "
151                          "tx_bytes=%llu, "
152                          "tx_packets=%llu, "
153                          "active=%d, "
154                          "proc_ptr=%p, "
155                          "tag_stat_tree=rb_root{...}}",
156                          is,
157                          is->ifname,
158                          is->rx_bytes,
159                          is->rx_packets,
160                          is->tx_bytes,
161                          is->tx_packets,
162                          is->active,
163                          is->proc_ptr);
164 }
165
166 char *pp_sock_tag(struct sock_tag *st)
167 {
168         char *tag_str;
169         char *res;
170
171         if (!st)
172                 return kasprintf(GFP_ATOMIC, "sock_tag@null{}");
173         tag_str = pp_tag_t(&st->tag);
174         res = kasprintf(GFP_ATOMIC, "sock_tag@%p{"
175                         "sock_node=rb_node{...}, "
176                         "sk=%p socket=%p (f_count=%lu), list=list_head{...}, "
177                         "pid=%u, tag=%s}",
178                         st, st->sk, st->socket, atomic_long_read(
179                                 &st->socket->file->f_count),
180                         st->pid, tag_str);
181         kfree(tag_str);
182         return res;
183 }
184
185 char *pp_uid_tag_data(struct uid_tag_data *utd)
186 {
187         char *res;
188
189         if (!utd)
190                 return kasprintf(GFP_ATOMIC, "uid_tag_data@null{}");
191         res = kasprintf(GFP_ATOMIC, "uid_tag_data@%p{"
192                         "uid=%u, num_active_acct_tags=%d, "
193                         "tag_node_tree=rb_root{...}, "
194                         "proc_qtu_data_tree=rb_root{...}}",
195                         utd, utd->uid,
196                         utd->num_active_tags);
197         return res;
198 }
199
200 char *pp_proc_qtu_data(struct proc_qtu_data *pqd)
201 {
202         char *parent_tag_data_str;
203         char *res;
204
205         if (!pqd)
206                 return kasprintf(GFP_ATOMIC, "proc_qtu_data@null{}");
207         parent_tag_data_str = pp_uid_tag_data(pqd->parent_tag_data);
208         res = kasprintf(GFP_ATOMIC, "proc_qtu_data@%p{"
209                         "node=rb_node{...}, pid=%u, "
210                         "parent_tag_data=%s, "
211                         "sock_tag_list=list_head{...}}",
212                         pqd, pqd->pid, parent_tag_data_str
213                 );
214         kfree(parent_tag_data_str);
215         return res;
216 }
217
218 /*------------------------------------------*/
219 void prdebug_sock_tag_tree(int indent_level,
220                            struct rb_root *sock_tag_tree)
221 {
222         struct rb_node *node;
223         struct sock_tag *sock_tag_entry;
224         char *str;
225
226         str = "sock_tag_tree=rb_root{";
227         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
228         indent_level++;
229         for (node = rb_first(sock_tag_tree);
230              node;
231              node = rb_next(node)) {
232                 sock_tag_entry = rb_entry(node, struct sock_tag, sock_node);
233                 str = pp_sock_tag(sock_tag_entry);
234                 CT_DEBUG("%*d: %s,\n", indent_level*2, indent_level, str);
235                 kfree(str);
236         }
237         indent_level--;
238         str = "}";
239         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
240 }
241
242 void prdebug_sock_tag_list(int indent_level,
243                            struct list_head *sock_tag_list)
244 {
245         struct sock_tag *sock_tag_entry;
246         char *str;
247
248         str = "sock_tag_list=list_head{";
249         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
250         indent_level++;
251         list_for_each_entry(sock_tag_entry, sock_tag_list, list) {
252                 str = pp_sock_tag(sock_tag_entry);
253                 CT_DEBUG("%*d: %s,\n", indent_level*2, indent_level, str);
254                 kfree(str);
255         }
256         indent_level--;
257         str = "}";
258         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
259 }
260
261 void prdebug_proc_qtu_data_tree(int indent_level,
262                                 struct rb_root *proc_qtu_data_tree)
263 {
264         char *str;
265         struct rb_node *node;
266         struct proc_qtu_data *proc_qtu_data_entry;
267
268         str = "proc_qtu_data_tree=rb_root{";
269         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
270         indent_level++;
271         for (node = rb_first(proc_qtu_data_tree);
272              node;
273              node = rb_next(node)) {
274                 proc_qtu_data_entry = rb_entry(node,
275                                                struct proc_qtu_data,
276                                                node);
277                 str = pp_proc_qtu_data(proc_qtu_data_entry);
278                 CT_DEBUG("%*d: %s,\n", indent_level*2, indent_level,
279                          str);
280                 kfree(str);
281                 indent_level++;
282                 prdebug_sock_tag_list(indent_level,
283                                       &proc_qtu_data_entry->sock_tag_list);
284                 indent_level--;
285
286         }
287         indent_level--;
288         str = "}";
289         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
290 }
291
292 void prdebug_tag_ref_tree(int indent_level, struct rb_root *tag_ref_tree)
293 {
294         char *str;
295         struct rb_node *node;
296         struct tag_ref *tag_ref_entry;
297
298         str = "tag_ref_tree{";
299         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
300         indent_level++;
301         for (node = rb_first(tag_ref_tree);
302              node;
303              node = rb_next(node)) {
304                 tag_ref_entry = rb_entry(node,
305                                          struct tag_ref,
306                                          tn.node);
307                 str = pp_tag_ref(tag_ref_entry);
308                 CT_DEBUG("%*d: %s,\n", indent_level*2, indent_level,
309                          str);
310                 kfree(str);
311         }
312         indent_level--;
313         str = "}";
314         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
315 }
316
317 void prdebug_uid_tag_data_tree(int indent_level,
318                                struct rb_root *uid_tag_data_tree)
319 {
320         char *str;
321         struct rb_node *node;
322         struct uid_tag_data *uid_tag_data_entry;
323
324         str = "uid_tag_data_tree=rb_root{";
325         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
326         indent_level++;
327         for (node = rb_first(uid_tag_data_tree);
328              node;
329              node = rb_next(node)) {
330                 uid_tag_data_entry = rb_entry(node, struct uid_tag_data,
331                                               node);
332                 str = pp_uid_tag_data(uid_tag_data_entry);
333                 CT_DEBUG("%*d: %s,\n", indent_level*2, indent_level, str);
334                 kfree(str);
335                 if (!RB_EMPTY_ROOT(&uid_tag_data_entry->tag_ref_tree)) {
336                         indent_level++;
337                         prdebug_tag_ref_tree(indent_level,
338                                              &uid_tag_data_entry->tag_ref_tree);
339                         indent_level--;
340                 }
341         }
342         indent_level--;
343         str = "}";
344         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
345 }
346
347 void prdebug_tag_stat_tree(int indent_level,
348                                   struct rb_root *tag_stat_tree)
349 {
350         char *str;
351         struct rb_node *node;
352         struct tag_stat *ts_entry;
353
354         str = "tag_stat_tree{";
355         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
356         indent_level++;
357         for (node = rb_first(tag_stat_tree);
358              node;
359              node = rb_next(node)) {
360                 ts_entry = rb_entry(node, struct tag_stat, tn.node);
361                 str = pp_tag_stat(ts_entry);
362                 CT_DEBUG("%*d: %s\n", indent_level*2, indent_level,
363                          str);
364                 kfree(str);
365         }
366         indent_level--;
367         str = "}";
368         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
369 }
370
371 void prdebug_iface_stat_list(int indent_level,
372                              struct list_head *iface_stat_list)
373 {
374         char *str;
375         struct iface_stat *iface_entry;
376
377         str = "iface_stat_list=list_head{";
378         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
379         indent_level++;
380         list_for_each_entry(iface_entry, iface_stat_list, list) {
381                 str = pp_iface_stat(iface_entry);
382                 CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
383                 kfree(str);
384
385                 spin_lock_bh(&iface_entry->tag_stat_list_lock);
386                 if (!RB_EMPTY_ROOT(&iface_entry->tag_stat_tree)) {
387                         indent_level++;
388                         prdebug_tag_stat_tree(indent_level,
389                                               &iface_entry->tag_stat_tree);
390                         indent_level--;
391                 }
392                 spin_unlock_bh(&iface_entry->tag_stat_list_lock);
393         }
394         indent_level--;
395         str = "}";
396         CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
397 }