blob: 2a7190d285e607cd523cbca4bce417fd12933dd5 [file] [log] [blame]
JP Abgrallbaf0db42011-06-20 12:41:46 -07001/*
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 * Most of the functions in this file just waste time if DEBUG is not defined.
13 * The matching xt_qtaguid_print.h will static inline empty funcs if the needed
14 * debug flags ore not defined.
15 * Those funcs that fail to allocate memory will panic as there is no need to
16 * hobble allong just pretending to do the requested work.
17 */
18
19#define DEBUG
20
21#include <linux/fs.h>
22#include <linux/gfp.h>
23#include <linux/net.h>
24#include <linux/rbtree.h>
25#include <linux/slab.h>
26#include <linux/spinlock_types.h>
Chenbo Feng875e5262017-04-19 14:22:47 -070027#include <net/sock.h>
JP Abgrallbaf0db42011-06-20 12:41:46 -070028
29#include "xt_qtaguid_internal.h"
30#include "xt_qtaguid_print.h"
31
32#ifdef DDEBUG
33
34static void _bug_on_err_or_null(void *ptr)
35{
36 if (IS_ERR_OR_NULL(ptr)) {
37 pr_err("qtaguid: kmalloc failed\n");
38 BUG();
39 }
40}
41
42char *pp_tag_t(tag_t *tag)
43{
44 char *res;
45
46 if (!tag)
47 res = kasprintf(GFP_ATOMIC, "tag_t@null{}");
48 else
49 res = kasprintf(GFP_ATOMIC,
50 "tag_t@%p{tag=0x%llx, uid=%u}",
51 tag, *tag, get_uid_from_tag(*tag));
52 _bug_on_err_or_null(res);
53 return res;
54}
55
56char *pp_data_counters(struct data_counters *dc, bool showValues)
57{
58 char *res;
59
60 if (!dc)
61 res = kasprintf(GFP_ATOMIC, "data_counters@null{}");
62 else if (showValues)
63 res = kasprintf(
64 GFP_ATOMIC, "data_counters@%p{"
65 "set0{"
66 "rx{"
67 "tcp{b=%llu, p=%llu}, "
68 "udp{b=%llu, p=%llu},"
69 "other{b=%llu, p=%llu}}, "
70 "tx{"
71 "tcp{b=%llu, p=%llu}, "
72 "udp{b=%llu, p=%llu},"
73 "other{b=%llu, p=%llu}}}, "
74 "set1{"
75 "rx{"
76 "tcp{b=%llu, p=%llu}, "
77 "udp{b=%llu, p=%llu},"
78 "other{b=%llu, p=%llu}}, "
79 "tx{"
80 "tcp{b=%llu, p=%llu}, "
81 "udp{b=%llu, p=%llu},"
82 "other{b=%llu, p=%llu}}}}",
83 dc,
84 dc->bpc[0][IFS_RX][IFS_TCP].bytes,
85 dc->bpc[0][IFS_RX][IFS_TCP].packets,
86 dc->bpc[0][IFS_RX][IFS_UDP].bytes,
87 dc->bpc[0][IFS_RX][IFS_UDP].packets,
88 dc->bpc[0][IFS_RX][IFS_PROTO_OTHER].bytes,
89 dc->bpc[0][IFS_RX][IFS_PROTO_OTHER].packets,
90 dc->bpc[0][IFS_TX][IFS_TCP].bytes,
91 dc->bpc[0][IFS_TX][IFS_TCP].packets,
92 dc->bpc[0][IFS_TX][IFS_UDP].bytes,
93 dc->bpc[0][IFS_TX][IFS_UDP].packets,
94 dc->bpc[0][IFS_TX][IFS_PROTO_OTHER].bytes,
95 dc->bpc[0][IFS_TX][IFS_PROTO_OTHER].packets,
96 dc->bpc[1][IFS_RX][IFS_TCP].bytes,
97 dc->bpc[1][IFS_RX][IFS_TCP].packets,
98 dc->bpc[1][IFS_RX][IFS_UDP].bytes,
99 dc->bpc[1][IFS_RX][IFS_UDP].packets,
100 dc->bpc[1][IFS_RX][IFS_PROTO_OTHER].bytes,
101 dc->bpc[1][IFS_RX][IFS_PROTO_OTHER].packets,
102 dc->bpc[1][IFS_TX][IFS_TCP].bytes,
103 dc->bpc[1][IFS_TX][IFS_TCP].packets,
104 dc->bpc[1][IFS_TX][IFS_UDP].bytes,
105 dc->bpc[1][IFS_TX][IFS_UDP].packets,
106 dc->bpc[1][IFS_TX][IFS_PROTO_OTHER].bytes,
107 dc->bpc[1][IFS_TX][IFS_PROTO_OTHER].packets);
108 else
109 res = kasprintf(GFP_ATOMIC, "data_counters@%p{...}", dc);
110 _bug_on_err_or_null(res);
111 return res;
112}
113
114char *pp_tag_node(struct tag_node *tn)
115{
116 char *tag_str;
117 char *res;
118
119 if (!tn) {
120 res = kasprintf(GFP_ATOMIC, "tag_node@null{}");
121 _bug_on_err_or_null(res);
122 return res;
123 }
124 tag_str = pp_tag_t(&tn->tag);
125 res = kasprintf(GFP_ATOMIC,
126 "tag_node@%p{tag=%s}",
127 tn, tag_str);
128 _bug_on_err_or_null(res);
129 kfree(tag_str);
130 return res;
131}
132
133char *pp_tag_ref(struct tag_ref *tr)
134{
135 char *tn_str;
136 char *res;
137
138 if (!tr) {
139 res = kasprintf(GFP_ATOMIC, "tag_ref@null{}");
140 _bug_on_err_or_null(res);
141 return res;
142 }
143 tn_str = pp_tag_node(&tr->tn);
144 res = kasprintf(GFP_ATOMIC,
145 "tag_ref@%p{%s, num_sock_tags=%d}",
146 tr, tn_str, tr->num_sock_tags);
147 _bug_on_err_or_null(res);
148 kfree(tn_str);
149 return res;
150}
151
152char *pp_tag_stat(struct tag_stat *ts)
153{
154 char *tn_str;
155 char *counters_str;
156 char *parent_counters_str;
157 char *res;
158
159 if (!ts) {
160 res = kasprintf(GFP_ATOMIC, "tag_stat@null{}");
161 _bug_on_err_or_null(res);
162 return res;
163 }
164 tn_str = pp_tag_node(&ts->tn);
165 counters_str = pp_data_counters(&ts->counters, true);
166 parent_counters_str = pp_data_counters(ts->parent_counters, false);
167 res = kasprintf(GFP_ATOMIC,
168 "tag_stat@%p{%s, counters=%s, parent_counters=%s}",
169 ts, tn_str, counters_str, parent_counters_str);
170 _bug_on_err_or_null(res);
171 kfree(tn_str);
172 kfree(counters_str);
173 kfree(parent_counters_str);
174 return res;
175}
176
177char *pp_iface_stat(struct iface_stat *is)
178{
179 char *res;
JP Abgrall87f93e82013-01-28 16:50:44 -0800180 if (!is) {
JP Abgrallbaf0db42011-06-20 12:41:46 -0700181 res = kasprintf(GFP_ATOMIC, "iface_stat@null{}");
JP Abgrall87f93e82013-01-28 16:50:44 -0800182 } else {
183 struct data_counters *cnts = &is->totals_via_skb;
JP Abgrallbaf0db42011-06-20 12:41:46 -0700184 res = kasprintf(GFP_ATOMIC, "iface_stat@%p{"
185 "list=list_head{...}, "
186 "ifname=%s, "
JP Abgrall9e0858c2012-04-27 12:57:39 -0700187 "total_dev={rx={bytes=%llu, "
188 "packets=%llu}, "
189 "tx={bytes=%llu, "
190 "packets=%llu}}, "
191 "total_skb={rx={bytes=%llu, "
JP Abgrallbaf0db42011-06-20 12:41:46 -0700192 "packets=%llu}, "
193 "tx={bytes=%llu, "
194 "packets=%llu}}, "
195 "last_known_valid=%d, "
196 "last_known={rx={bytes=%llu, "
197 "packets=%llu}, "
198 "tx={bytes=%llu, "
199 "packets=%llu}}, "
200 "active=%d, "
201 "net_dev=%p, "
202 "proc_ptr=%p, "
203 "tag_stat_tree=rb_root{...}}",
204 is,
205 is->ifname,
JP Abgrall9e0858c2012-04-27 12:57:39 -0700206 is->totals_via_dev[IFS_RX].bytes,
207 is->totals_via_dev[IFS_RX].packets,
208 is->totals_via_dev[IFS_TX].bytes,
209 is->totals_via_dev[IFS_TX].packets,
JP Abgrall87f93e82013-01-28 16:50:44 -0800210 dc_sum_bytes(cnts, 0, IFS_RX),
211 dc_sum_packets(cnts, 0, IFS_RX),
212 dc_sum_bytes(cnts, 0, IFS_TX),
213 dc_sum_packets(cnts, 0, IFS_TX),
JP Abgrallbaf0db42011-06-20 12:41:46 -0700214 is->last_known_valid,
215 is->last_known[IFS_RX].bytes,
216 is->last_known[IFS_RX].packets,
217 is->last_known[IFS_TX].bytes,
218 is->last_known[IFS_TX].packets,
219 is->active,
220 is->net_dev,
221 is->proc_ptr);
JP Abgrall87f93e82013-01-28 16:50:44 -0800222 }
JP Abgrallbaf0db42011-06-20 12:41:46 -0700223 _bug_on_err_or_null(res);
224 return res;
225}
226
227char *pp_sock_tag(struct sock_tag *st)
228{
229 char *tag_str;
230 char *res;
231
232 if (!st) {
233 res = kasprintf(GFP_ATOMIC, "sock_tag@null{}");
234 _bug_on_err_or_null(res);
235 return res;
236 }
237 tag_str = pp_tag_t(&st->tag);
238 res = kasprintf(GFP_ATOMIC, "sock_tag@%p{"
239 "sock_node=rb_node{...}, "
Chenbo Feng875e5262017-04-19 14:22:47 -0700240 "sk=%p (f_count=%d), list=list_head{...}, "
JP Abgrallbaf0db42011-06-20 12:41:46 -0700241 "pid=%u, tag=%s}",
Chenbo Feng875e5262017-04-19 14:22:47 -0700242 st, st->sk, atomic_read(
243 &st->sk->sk_refcnt),
JP Abgrallbaf0db42011-06-20 12:41:46 -0700244 st->pid, tag_str);
245 _bug_on_err_or_null(res);
246 kfree(tag_str);
247 return res;
248}
249
250char *pp_uid_tag_data(struct uid_tag_data *utd)
251{
252 char *res;
253
254 if (!utd)
255 res = kasprintf(GFP_ATOMIC, "uid_tag_data@null{}");
256 else
257 res = kasprintf(GFP_ATOMIC, "uid_tag_data@%p{"
258 "uid=%u, num_active_acct_tags=%d, "
259 "num_pqd=%d, "
260 "tag_node_tree=rb_root{...}, "
261 "proc_qtu_data_tree=rb_root{...}}",
262 utd, utd->uid,
263 utd->num_active_tags, utd->num_pqd);
264 _bug_on_err_or_null(res);
265 return res;
266}
267
268char *pp_proc_qtu_data(struct proc_qtu_data *pqd)
269{
270 char *parent_tag_data_str;
271 char *res;
272
273 if (!pqd) {
274 res = kasprintf(GFP_ATOMIC, "proc_qtu_data@null{}");
275 _bug_on_err_or_null(res);
276 return res;
277 }
278 parent_tag_data_str = pp_uid_tag_data(pqd->parent_tag_data);
279 res = kasprintf(GFP_ATOMIC, "proc_qtu_data@%p{"
280 "node=rb_node{...}, pid=%u, "
281 "parent_tag_data=%s, "
282 "sock_tag_list=list_head{...}}",
283 pqd, pqd->pid, parent_tag_data_str
284 );
285 _bug_on_err_or_null(res);
286 kfree(parent_tag_data_str);
287 return res;
288}
289
290/*------------------------------------------*/
291void prdebug_sock_tag_tree(int indent_level,
292 struct rb_root *sock_tag_tree)
293{
294 struct rb_node *node;
295 struct sock_tag *sock_tag_entry;
296 char *str;
297
298 if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
299 return;
300
301 if (RB_EMPTY_ROOT(sock_tag_tree)) {
302 str = "sock_tag_tree=rb_root{}";
303 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
304 return;
305 }
306
307 str = "sock_tag_tree=rb_root{";
308 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
309 indent_level++;
310 for (node = rb_first(sock_tag_tree);
311 node;
312 node = rb_next(node)) {
313 sock_tag_entry = rb_entry(node, struct sock_tag, sock_node);
314 str = pp_sock_tag(sock_tag_entry);
315 pr_debug("%*d: %s,\n", indent_level*2, indent_level, str);
316 kfree(str);
317 }
318 indent_level--;
319 str = "}";
320 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
321}
322
323void prdebug_sock_tag_list(int indent_level,
324 struct list_head *sock_tag_list)
325{
326 struct sock_tag *sock_tag_entry;
327 char *str;
328
329 if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
330 return;
331
332 if (list_empty(sock_tag_list)) {
333 str = "sock_tag_list=list_head{}";
334 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
335 return;
336 }
337
338 str = "sock_tag_list=list_head{";
339 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
340 indent_level++;
341 list_for_each_entry(sock_tag_entry, sock_tag_list, list) {
342 str = pp_sock_tag(sock_tag_entry);
343 pr_debug("%*d: %s,\n", indent_level*2, indent_level, str);
344 kfree(str);
345 }
346 indent_level--;
347 str = "}";
348 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
349}
350
351void prdebug_proc_qtu_data_tree(int indent_level,
352 struct rb_root *proc_qtu_data_tree)
353{
354 char *str;
355 struct rb_node *node;
356 struct proc_qtu_data *proc_qtu_data_entry;
357
358 if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
359 return;
360
361 if (RB_EMPTY_ROOT(proc_qtu_data_tree)) {
362 str = "proc_qtu_data_tree=rb_root{}";
363 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
364 return;
365 }
366
367 str = "proc_qtu_data_tree=rb_root{";
368 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
369 indent_level++;
370 for (node = rb_first(proc_qtu_data_tree);
371 node;
372 node = rb_next(node)) {
373 proc_qtu_data_entry = rb_entry(node,
374 struct proc_qtu_data,
375 node);
376 str = pp_proc_qtu_data(proc_qtu_data_entry);
377 pr_debug("%*d: %s,\n", indent_level*2, indent_level,
378 str);
379 kfree(str);
380 indent_level++;
381 prdebug_sock_tag_list(indent_level,
382 &proc_qtu_data_entry->sock_tag_list);
383 indent_level--;
384
385 }
386 indent_level--;
387 str = "}";
388 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
389}
390
391void prdebug_tag_ref_tree(int indent_level, struct rb_root *tag_ref_tree)
392{
393 char *str;
394 struct rb_node *node;
395 struct tag_ref *tag_ref_entry;
396
397 if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
398 return;
399
400 if (RB_EMPTY_ROOT(tag_ref_tree)) {
401 str = "tag_ref_tree{}";
402 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
403 return;
404 }
405
406 str = "tag_ref_tree{";
407 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
408 indent_level++;
409 for (node = rb_first(tag_ref_tree);
410 node;
411 node = rb_next(node)) {
412 tag_ref_entry = rb_entry(node,
413 struct tag_ref,
414 tn.node);
415 str = pp_tag_ref(tag_ref_entry);
416 pr_debug("%*d: %s,\n", indent_level*2, indent_level,
417 str);
418 kfree(str);
419 }
420 indent_level--;
421 str = "}";
422 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
423}
424
425void prdebug_uid_tag_data_tree(int indent_level,
426 struct rb_root *uid_tag_data_tree)
427{
428 char *str;
429 struct rb_node *node;
430 struct uid_tag_data *uid_tag_data_entry;
431
432 if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
433 return;
434
435 if (RB_EMPTY_ROOT(uid_tag_data_tree)) {
436 str = "uid_tag_data_tree=rb_root{}";
437 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
438 return;
439 }
440
441 str = "uid_tag_data_tree=rb_root{";
442 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
443 indent_level++;
444 for (node = rb_first(uid_tag_data_tree);
445 node;
446 node = rb_next(node)) {
447 uid_tag_data_entry = rb_entry(node, struct uid_tag_data,
448 node);
449 str = pp_uid_tag_data(uid_tag_data_entry);
450 pr_debug("%*d: %s,\n", indent_level*2, indent_level, str);
451 kfree(str);
452 if (!RB_EMPTY_ROOT(&uid_tag_data_entry->tag_ref_tree)) {
453 indent_level++;
454 prdebug_tag_ref_tree(indent_level,
455 &uid_tag_data_entry->tag_ref_tree);
456 indent_level--;
457 }
458 }
459 indent_level--;
460 str = "}";
461 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
462}
463
464void prdebug_tag_stat_tree(int indent_level,
465 struct rb_root *tag_stat_tree)
466{
467 char *str;
468 struct rb_node *node;
469 struct tag_stat *ts_entry;
470
471 if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
472 return;
473
474 if (RB_EMPTY_ROOT(tag_stat_tree)) {
475 str = "tag_stat_tree{}";
476 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
477 return;
478 }
479
480 str = "tag_stat_tree{";
481 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
482 indent_level++;
483 for (node = rb_first(tag_stat_tree);
484 node;
485 node = rb_next(node)) {
486 ts_entry = rb_entry(node, struct tag_stat, tn.node);
487 str = pp_tag_stat(ts_entry);
488 pr_debug("%*d: %s\n", indent_level*2, indent_level,
489 str);
490 kfree(str);
491 }
492 indent_level--;
493 str = "}";
494 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
495}
496
497void prdebug_iface_stat_list(int indent_level,
498 struct list_head *iface_stat_list)
499{
500 char *str;
501 struct iface_stat *iface_entry;
502
503 if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
504 return;
505
506 if (list_empty(iface_stat_list)) {
507 str = "iface_stat_list=list_head{}";
508 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
509 return;
510 }
511
512 str = "iface_stat_list=list_head{";
513 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
514 indent_level++;
515 list_for_each_entry(iface_entry, iface_stat_list, list) {
516 str = pp_iface_stat(iface_entry);
517 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
518 kfree(str);
519
520 spin_lock_bh(&iface_entry->tag_stat_list_lock);
521 if (!RB_EMPTY_ROOT(&iface_entry->tag_stat_tree)) {
522 indent_level++;
523 prdebug_tag_stat_tree(indent_level,
524 &iface_entry->tag_stat_tree);
525 indent_level--;
526 }
527 spin_unlock_bh(&iface_entry->tag_stat_list_lock);
528 }
529 indent_level--;
530 str = "}";
531 pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
532}
533
534#endif /* ifdef DDEBUG */
535/*------------------------------------------*/
536static const char * const netdev_event_strings[] = {
537 "netdev_unknown",
538 "NETDEV_UP",
539 "NETDEV_DOWN",
540 "NETDEV_REBOOT",
541 "NETDEV_CHANGE",
542 "NETDEV_REGISTER",
543 "NETDEV_UNREGISTER",
544 "NETDEV_CHANGEMTU",
545 "NETDEV_CHANGEADDR",
546 "NETDEV_GOING_DOWN",
547 "NETDEV_CHANGENAME",
548 "NETDEV_FEAT_CHANGE",
549 "NETDEV_BONDING_FAILOVER",
550 "NETDEV_PRE_UP",
551 "NETDEV_PRE_TYPE_CHANGE",
552 "NETDEV_POST_TYPE_CHANGE",
553 "NETDEV_POST_INIT",
554 "NETDEV_UNREGISTER_BATCH",
555 "NETDEV_RELEASE",
556 "NETDEV_NOTIFY_PEERS",
557 "NETDEV_JOIN",
558};
559
560const char *netdev_evt_str(int netdev_event)
561{
562 if (netdev_event < 0
563 || netdev_event >= ARRAY_SIZE(netdev_event_strings))
564 return "bad event num";
565 return netdev_event_strings[netdev_event];
566}