1 /*
2 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
3 * Copyright (c) 2017-2021 The strace developers.
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "tests.h"
10
11 #include <stdio.h>
12 #include <inttypes.h>
13 #include "test_nlattr.h"
14 #include <linux/fib_rules.h>
15 #include <linux/in.h>
16 #include <linux/ip.h>
17
18 static void
19 init_rtmsg(struct nlmsghdr *const nlh, const unsigned int msg_len)
20 {
21 SET_STRUCT(struct nlmsghdr, nlh,
22 .nlmsg_len = msg_len,
23 .nlmsg_type = RTM_GETRULE,
24 .nlmsg_flags = NLM_F_DUMP
25 );
26
27 struct rtmsg *const msg = NLMSG_DATA(nlh);
28 SET_STRUCT(struct rtmsg, msg,
29 .rtm_family = AF_UNIX,
30 .rtm_tos = IPTOS_LOWDELAY,
31 .rtm_table = RT_TABLE_UNSPEC,
32 .rtm_type = FR_ACT_TO_TBL,
33 .rtm_flags = FIB_RULE_INVERT
34 );
35 }
36
37 static void
38 print_rtmsg(const unsigned int msg_len)
39 {
40 printf("{nlmsg_len=%u, nlmsg_type=RTM_GETRULE, nlmsg_flags=NLM_F_DUMP"
41 ", nlmsg_seq=0, nlmsg_pid=0}, {family=AF_UNIX"
42 ", dst_len=0, src_len=0"
43 ", tos=IPTOS_LOWDELAY"
44 ", table=RT_TABLE_UNSPEC"
45 ", action=FR_ACT_TO_TBL"
46 ", flags=FIB_RULE_INVERT}",
47 msg_len);
48 }
49
50 int
51 main(void)
52 {
53 skip_if_unavailable("/proc/self/fd/");
54
55 const int fd = create_nl_socket(NETLINK_ROUTE);
56 const unsigned int hdrlen = sizeof(struct rtmsg);
57 void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), NLA_HDRLEN + 8);
58
59 static char pattern[4096];
60 fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
61
62 const unsigned int nla_type = 0xffff & NLA_TYPE_MASK;
63 char nla_type_str[256];
64 sprintf(nla_type_str, "%#x /* FRA_??? */", nla_type);
65 TEST_NLATTR_(fd, nlh0, hdrlen,
66 init_rtmsg, print_rtmsg,
67 nla_type, nla_type_str,
68 4, pattern, 4,
69 print_quoted_hex(pattern, 4));
70
71 TEST_NLATTR(fd, nlh0, hdrlen,
72 init_rtmsg, print_rtmsg,
73 FRA_DST, 4, pattern, 4,
74 print_quoted_hex(pattern, 4));
75
76 const uint32_t table_id = RT_TABLE_DEFAULT;
77 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
78 init_rtmsg, print_rtmsg,
79 FRA_TABLE, pattern, table_id,
80 printf("RT_TABLE_DEFAULT"));
81
82 static const struct fib_rule_uid_range range = {
83 .start = 0xabcdedad,
84 .end = 0xbcdeadba
85 };
86 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
87 init_rtmsg, print_rtmsg,
88 FRA_UID_RANGE, pattern, range,
89 printf("{");
90 PRINT_FIELD_U(range, start);
91 printf(", ");
92 PRINT_FIELD_U(range, end);
93 printf("}"));
94 #if defined HAVE_BE64TOH || defined be64toh
95 const uint64_t tun_id = 0xabcdcdbeedabadef;
96 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
97 init_rtmsg, print_rtmsg,
98 FRA_TUN_ID, pattern, tun_id,
99 printf("htobe64(%" PRIu64 ")", be64toh(tun_id)));
100 #endif
101
102 uint8_t proto;
103
104 static const struct {
105 uint8_t arg;
106 const char *str;
107 } proto_args[] = {
108 { ARG_STR(RTPROT_UNSPEC) },
109 { 5, "0x5 /* RTPROT_??? */" },
110 { 17, "RTPROT_MROUTED" },
111 { 42, "RTPROT_BABEL" },
112 { 43, "0x2b /* RTPROT_??? */" },
113 { ARG_STR(0xde) " /* RTPROT_??? */" },
114 };
115
116 for (unsigned i = 0; i < ARRAY_SIZE(proto_args); i++) {
117 proto = proto_args[i].arg;
118 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
119 init_rtmsg, print_rtmsg,
120 FRA_PROTOCOL, pattern, proto,
121 printf("%s", proto_args[i].str));
122 }
123
124 static const struct {
125 uint8_t arg;
126 const char *str;
127 } ipproto_args[] = {
128 { ARG_STR(IPPROTO_TCP) },
129 { 254, "0xfe /* IPPROTO_??? */" },
130 { ARG_STR(IPPROTO_RAW) },
131 };
132
133 for (unsigned i = 0; i < ARRAY_SIZE(ipproto_args); i++) {
134 proto = ipproto_args[i].arg;
135 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
136 init_rtmsg, print_rtmsg,
137 FRA_IP_PROTO, pattern, proto,
138 printf("%s", ipproto_args[i].str));
139 }
140
141 static const struct fib_rule_port_range prange = {
142 .start = 0xabcd,
143 .end = 0xfeed,
144 };
145 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
146 init_rtmsg, print_rtmsg,
147 FRA_SPORT_RANGE, pattern, prange,
148 printf("{");
149 PRINT_FIELD_U(prange, start);
150 printf(", ");
151 PRINT_FIELD_U(prange, end);
152 printf("}"));
153 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
154 init_rtmsg, print_rtmsg,
155 FRA_DPORT_RANGE, pattern, prange,
156 printf("{");
157 PRINT_FIELD_U(prange, start);
158 printf(", ");
159 PRINT_FIELD_U(prange, end);
160 printf("}"));
161
162 puts("+++ exited with 0 +++");
163 return 0;
164 }