1 /*
2 * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
4 * Copyright (c) 2016-2021 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: LGPL-2.1-or-later
8 */
9
10 #include "defs.h"
11
12 #include "netlink_route.h"
13 #include "nlattr.h"
14 #include "netlink.h"
15 #include <linux/fib_rules.h>
16
17 #include "xlat/fib_rule_actions.h"
18 #include "xlat/fib_rule_flags.h"
19 #include "xlat/rtnl_rule_attrs.h"
20
21 static bool
22 decode_rule_addr(struct tcb *const tcp,
23 const kernel_ulong_t addr,
24 const unsigned int len,
25 const void *const opaque_data)
26 {
27 const struct fib_rule_hdr *const msg = opaque_data;
28
29 decode_inet_addr(tcp, addr, len, msg->family, NULL);
30
31 return true;
32 }
33
34 static bool
35 decode_fib_rule_uid_range(struct tcb *const tcp,
36 const kernel_ulong_t addr,
37 const unsigned int len,
38 const void *const opaque_data)
39 {
40 struct fib_rule_uid_range range;
41
42 if (len < sizeof(range))
43 return false;
44 else if (!umove_or_printaddr(tcp, addr, &range)) {
45 tprint_struct_begin();
46 PRINT_FIELD_U(range, start);
47 tprint_struct_next();
48 PRINT_FIELD_U(range, end);
49 tprint_struct_end();
50 }
51
52 return true;
53 }
54
55 static bool
56 decode_rule_port_range(struct tcb *const tcp,
57 const kernel_ulong_t addr,
58 const unsigned int len,
59 const void *const opaque_data)
60 {
61 struct fib_rule_port_range range;
62
63 if (len < sizeof(range))
64 return false;
65 else if (!umove_or_printaddr(tcp, addr, &range)) {
66 tprint_struct_begin();
67 PRINT_FIELD_U(range, start);
68 tprint_struct_next();
69 PRINT_FIELD_U(range, end);
70 tprint_struct_end();
71 }
72
73 return true;
74 }
75
76 static const nla_decoder_t fib_rule_hdr_nla_decoders[] = {
77 [FRA_DST] = decode_rule_addr,
78 [FRA_SRC] = decode_rule_addr,
79 [FRA_IIFNAME] = decode_nla_str,
80 [FRA_GOTO] = decode_nla_u32,
81 [FRA_PRIORITY] = decode_nla_u32,
82 [FRA_FWMARK] = decode_nla_u32,
83 [FRA_FLOW] = decode_nla_u32,
84 [FRA_TUN_ID] = decode_nla_be64,
85 [FRA_SUPPRESS_IFGROUP] = decode_nla_u32,
86 [FRA_SUPPRESS_PREFIXLEN] = decode_nla_u32,
87 [FRA_TABLE] = decode_nla_rt_class,
88 [FRA_FWMASK] = decode_nla_u32,
89 [FRA_OIFNAME] = decode_nla_str,
90 [FRA_PAD] = NULL,
91 [FRA_L3MDEV] = decode_nla_u8,
92 [FRA_UID_RANGE] = decode_fib_rule_uid_range,
93 [FRA_PROTOCOL] = decode_nla_rt_proto,
94 [FRA_IP_PROTO] = decode_nla_ip_proto,
95 [FRA_SPORT_RANGE] = decode_rule_port_range,
96 [FRA_DPORT_RANGE] = decode_rule_port_range,
97 };
98
99 DECL_NETLINK_ROUTE_DECODER(decode_fib_rule_hdr)
100 {
101 struct fib_rule_hdr msg = { .family = family };
102 size_t offset = sizeof(msg.family);
103 bool decode_nla = false;
104
105 tprint_struct_begin();
106 PRINT_FIELD_XVAL(msg, family, addrfams, "AF_???");
107 tprint_struct_next();
108
109 if (len >= sizeof(msg)) {
110 if (!umoven_or_printaddr(tcp, addr + offset,
111 sizeof(msg) - offset,
112 (char *) &msg + offset)) {
113 PRINT_FIELD_U(msg, dst_len);
114 tprint_struct_next();
115 PRINT_FIELD_U(msg, src_len);
116 tprint_struct_next();
117 PRINT_FIELD_FLAGS(msg, tos,
118 ip_type_of_services, "IPTOS_TOS_???");
119 tprint_struct_next();
120 PRINT_FIELD_XVAL(msg, table,
121 routing_table_ids, "RT_TABLE_???");
122 tprint_struct_next();
123 PRINT_FIELD_XVAL(msg, action,
124 fib_rule_actions, "FR_ACT_???");
125 tprint_struct_next();
126 PRINT_FIELD_FLAGS(msg, flags,
127 fib_rule_flags, "FIB_RULE_???");
128 decode_nla = true;
129 }
130 } else
131 tprint_more_data_follows();
132 tprint_struct_end();
133
134 offset = NLMSG_ALIGN(sizeof(msg));
135 if (decode_nla && len > offset) {
136 tprint_array_next();
137 decode_nlattr(tcp, addr + offset, len - offset,
138 rtnl_rule_attrs, "FRA_???",
139 fib_rule_hdr_nla_decoders,
140 ARRAY_SIZE(fib_rule_hdr_nla_decoders), &msg);
141 }
142 }