1 /* 2 * Copyright (c) 2017 JingPiao Chen <chenjingpiao (at) gmail.com> 3 * Copyright (c) 2017 The strace developers. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "tests.h" 30 31 #include <stdio.h> 32 #include <netinet/in.h> 33 #include <arpa/inet.h> 34 #include "test_nlattr.h" 35 #include <linux/ip.h> 36 #include <linux/rtnetlink.h> 37 38 #define RTA_ENCAP_TYPE 21 39 #define LWTUNNEL_ENCAP_NONE 0 40 41 static void 42 init_rtmsg(struct nlmsghdr *const nlh, const unsigned int msg_len) 43 { 44 SET_STRUCT(struct nlmsghdr, nlh, 45 .nlmsg_len = msg_len, 46 .nlmsg_type = RTM_GETROUTE, 47 .nlmsg_flags = NLM_F_DUMP 48 ); 49 50 struct rtmsg *const msg = NLMSG_DATA(nlh); 51 SET_STRUCT(struct rtmsg, msg, 52 .rtm_family = AF_UNIX, 53 .rtm_tos = IPTOS_LOWDELAY, 54 .rtm_table = RT_TABLE_DEFAULT, 55 .rtm_protocol = RTPROT_KERNEL, 56 .rtm_scope = RT_SCOPE_UNIVERSE, 57 .rtm_type = RTN_LOCAL, 58 .rtm_flags = RTM_F_NOTIFY 59 ); 60 } 61 62 static void 63 print_rtmsg(const unsigned int msg_len) 64 { 65 printf("{len=%u, type=RTM_GETROUTE, flags=NLM_F_DUMP" 66 ", seq=0, pid=0}, {rtm_family=AF_UNIX" 67 ", rtm_dst_len=0, rtm_src_len=0" 68 ", rtm_tos=IPTOS_LOWDELAY" 69 ", rtm_table=RT_TABLE_DEFAULT" 70 ", rtm_protocol=RTPROT_KERNEL" 71 ", rtm_scope=RT_SCOPE_UNIVERSE" 72 ", rtm_type=RTN_LOCAL" 73 ", rtm_flags=RTM_F_NOTIFY}", 74 msg_len); 75 } 76 77 int 78 main(void) 79 { 80 skip_if_unavailable("/proc/self/fd/"); 81 82 const int fd = create_nl_socket(NETLINK_ROUTE); 83 const unsigned int hdrlen = sizeof(struct rtmsg); 84 void *nlh0 = tail_alloc(NLMSG_SPACE(hdrlen)); 85 86 static char pattern[4096]; 87 fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1); 88 89 const unsigned int nla_type = 0xffff & NLA_TYPE_MASK; 90 char nla_type_str[256]; 91 sprintf(nla_type_str, "%#x /* RTA_??? */", nla_type); 92 TEST_NLATTR_(fd, nlh0, hdrlen, 93 init_rtmsg, print_rtmsg, 94 nla_type, nla_type_str, 95 4, pattern, 4, 96 print_quoted_hex(pattern, 4)); 97 98 TEST_NLATTR(fd, nlh0, hdrlen, 99 init_rtmsg, print_rtmsg, 100 RTA_DST, 4, pattern, 4, 101 print_quoted_hex(pattern, 4)); 102 103 const uint32_t ifindex = ifindex_lo(); 104 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 105 init_rtmsg, print_rtmsg, 106 RTA_OIF, pattern, ifindex, 107 printf(IFINDEX_LO_STR)); 108 109 const uint32_t rt_class_id = RT_TABLE_DEFAULT; 110 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 111 init_rtmsg, print_rtmsg, 112 RTA_TABLE, pattern, rt_class_id, 113 printf("RT_TABLE_DEFAULT")); 114 115 struct nlattr nla = { 116 .nla_type = RTAX_LOCK, 117 .nla_len = sizeof(nla) 118 }; 119 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 120 init_rtmsg, print_rtmsg, 121 RTA_METRICS, pattern, nla, 122 printf("{nla_len=%u, nla_type=RTAX_LOCK}", 123 nla.nla_len)); 124 struct rtnexthop nh = { 125 .rtnh_len = sizeof(nh) - 1, 126 .rtnh_flags = RTNH_F_DEAD, 127 .rtnh_hops = 0xab, 128 .rtnh_ifindex = ifindex_lo() 129 }; 130 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 131 init_rtmsg, print_rtmsg, 132 RTA_MULTIPATH, pattern, nh, 133 printf("{rtnh_len=%u, rtnh_flags=RTNH_F_DEAD" 134 ", rtnh_hops=%u" 135 ", rtnh_ifindex=" IFINDEX_LO_STR "}", 136 nh.rtnh_len, nh.rtnh_hops)); 137 138 char buf[RTNH_ALIGN(sizeof(nh)) + sizeof(nla)]; 139 nh.rtnh_len = sizeof(buf); 140 nla.nla_type = RTA_DST; 141 memcpy(buf, &nh, sizeof(nh)); 142 memcpy(buf + RTNH_ALIGN(sizeof(nh)), &nla, sizeof(nla)); 143 TEST_NLATTR(fd, nlh0, hdrlen, 144 init_rtmsg, print_rtmsg, 145 RTA_MULTIPATH, sizeof(buf), buf, sizeof(buf), 146 printf("{rtnh_len=%u, rtnh_flags=RTNH_F_DEAD" 147 ", rtnh_hops=%u, rtnh_ifindex=" IFINDEX_LO_STR "}" 148 ", {nla_len=%u, nla_type=RTA_DST}", 149 nh.rtnh_len, nh.rtnh_hops, nla.nla_len)); 150 151 static const struct rta_cacheinfo ci = { 152 .rta_clntref = 0xabcdefab, 153 .rta_lastuse = 0xbdadaedc, 154 .rta_expires = 0xcdadebad, 155 .rta_error = 0xdaedadeb, 156 .rta_used = 0xedfabdad, 157 .rta_id = 0xfeadbcda, 158 .rta_ts = 0xacdbaded, 159 .rta_tsage = 0xbadeadef 160 }; 161 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 162 init_rtmsg, print_rtmsg, 163 RTA_CACHEINFO, pattern, ci, 164 PRINT_FIELD_U("{", ci, rta_clntref); 165 PRINT_FIELD_U(", ", ci, rta_lastuse); 166 PRINT_FIELD_U(", ", ci, rta_expires); 167 PRINT_FIELD_U(", ", ci, rta_error); 168 PRINT_FIELD_U(", ", ci, rta_used); 169 PRINT_FIELD_X(", ", ci, rta_id); 170 PRINT_FIELD_U(", ", ci, rta_ts); 171 PRINT_FIELD_U(", ", ci, rta_tsage); 172 printf("}")); 173 174 #ifdef HAVE_STRUCT_RTA_MFC_STATS 175 static const struct rta_mfc_stats mfcs = { 176 .mfcs_packets = 0xadcdedfdadefadcd, 177 .mfcs_bytes = 0xbaedadedcdedadbd, 178 .mfcs_wrong_if = 0xcddeabeedaedabfa 179 }; 180 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 181 init_rtmsg, print_rtmsg, 182 RTA_MFC_STATS, pattern, mfcs, 183 PRINT_FIELD_U("{", mfcs, mfcs_packets); 184 PRINT_FIELD_U(", ", mfcs, mfcs_bytes); 185 PRINT_FIELD_U(", ", mfcs, mfcs_wrong_if); 186 printf("}")); 187 #endif 188 189 #ifdef HAVE_STRUCT_RTVIA 190 static const struct rtvia via = { 191 .rtvia_family = AF_INET 192 }; 193 194 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 195 init_rtmsg, print_rtmsg, 196 RTA_VIA, pattern, via, 197 printf("{rtvia_family=AF_INET}")); 198 199 static const char address4[] = "12.34.56.78"; 200 struct in_addr a4 = { 201 .s_addr = inet_addr(address4) 202 }; 203 char rtviabuf[sizeof(via) + sizeof(a4)]; 204 memcpy(rtviabuf, &via, sizeof(via)); 205 memcpy(rtviabuf + sizeof(via), &a4, sizeof(a4)); 206 207 TEST_NLATTR(fd, nlh0, hdrlen, 208 init_rtmsg, print_rtmsg, 209 RTA_VIA, sizeof(rtviabuf), rtviabuf, sizeof(rtviabuf), 210 printf("{rtvia_family=AF_INET" 211 ", rtvia_addr=inet_addr(\"%s\")}", address4)); 212 #endif 213 214 const uint16_t encap_type = LWTUNNEL_ENCAP_NONE; 215 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 216 init_rtmsg, print_rtmsg, 217 RTA_ENCAP_TYPE, pattern, encap_type, 218 printf("LWTUNNEL_ENCAP_NONE")); 219 220 puts("+++ exited with 0 +++"); 221 return 0; 222 } 223