1 /* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 5 * Copyright (c) 1996-2000 Wichert Akkerman <wichert (at) cistron.nl> 6 * Copyright (c) 2005-2016 Dmitry V. Levin <ldv (at) altlinux.org> 7 * Copyright (c) 2016-2017 The strace developers. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "defs.h" 34 #include "print_fields.h" 35 36 #include <sys/socket.h> 37 #include <sys/un.h> 38 #include <netinet/in.h> 39 #include <arpa/inet.h> 40 41 #include "netlink.h" 42 #include <linux/if_packet.h> 43 #include <linux/if_arp.h> 44 #include <linux/if_ether.h> 45 46 #ifdef HAVE_NETIPX_IPX_H 47 # include <netipx/ipx.h> 48 #else 49 # include <linux/ipx.h> 50 #endif 51 52 #include "xlat/addrfams.h" 53 #include "xlat/arp_hardware_types.h" 54 #include "xlat/ethernet_protocols.h" 55 #include "xlat/af_packet_types.h" 56 57 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H 58 # include <bluetooth/bluetooth.h> 59 # include <bluetooth/hci.h> 60 # include <bluetooth/l2cap.h> 61 # include <bluetooth/rfcomm.h> 62 # include <bluetooth/sco.h> 63 64 # include "xlat/hci_channels.h" 65 #endif 66 67 #define SIZEOF_SA_FAMILY sizeof(((struct sockaddr *) 0)->sa_family) 68 69 static void 70 print_sockaddr_data_un(const void *const buf, const int addrlen) 71 { 72 const struct sockaddr_un *const sa_un = buf; 73 const int un_len = addrlen > (int) sizeof(*sa_un) 74 ? (int) sizeof(*sa_un) : addrlen; 75 const int path_len = un_len - SIZEOF_SA_FAMILY; 76 77 tprints("sun_path="); 78 if (sa_un->sun_path[0]) { 79 print_quoted_string(sa_un->sun_path, path_len + 1, 80 QUOTE_0_TERMINATED); 81 } else { 82 tprints("@"); 83 print_quoted_string(sa_un->sun_path + 1, path_len - 1, 0); 84 } 85 } 86 87 bool 88 print_inet_addr(const int af, 89 const void *const addr, 90 const unsigned int len, 91 const char *const var_name) 92 { 93 char buf[INET6_ADDRSTRLEN]; 94 95 switch (af) { 96 case AF_INET: 97 if (inet_ntop(af, addr, buf, sizeof(buf))) { 98 if (var_name) 99 tprintf("%s=inet_addr(\"%s\")", var_name, buf); 100 else 101 tprints(buf); 102 return true; 103 } 104 break; 105 case AF_INET6: 106 if (inet_ntop(af, addr, buf, sizeof(buf))) { 107 if (var_name) 108 tprintf("inet_pton(%s, \"%s\", &%s)", 109 "AF_INET6", buf, var_name); 110 else 111 tprints(buf); 112 return true; 113 } 114 break; 115 } 116 117 if (var_name) 118 tprintf("%s=", var_name); 119 print_quoted_string(addr, len, QUOTE_FORCE_HEX); 120 return false; 121 } 122 123 bool 124 decode_inet_addr(struct tcb *const tcp, 125 const kernel_ulong_t addr, 126 const unsigned int len, 127 const int family, 128 const char *const var_name) 129 { 130 union { 131 struct in_addr a4; 132 struct in6_addr a6; 133 } addrbuf; 134 size_t size = 0; 135 136 switch (family) { 137 case AF_INET: 138 size = sizeof(addrbuf.a4); 139 break; 140 case AF_INET6: 141 size = sizeof(addrbuf.a6); 142 break; 143 } 144 145 if (!size || len < size) { 146 if (var_name) 147 tprintf("%s=", var_name); 148 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); 149 return false; 150 } 151 152 if (umoven(tcp, addr, size, &addrbuf) < 0) { 153 if (var_name) 154 tprintf("%s=", var_name); 155 printaddr(addr); 156 return false; 157 } 158 159 return print_inet_addr(family, &addrbuf, size, var_name); 160 } 161 162 static void 163 print_sockaddr_data_in(const void *const buf, const int addrlen) 164 { 165 const struct sockaddr_in *const sa_in = buf; 166 167 PRINT_FIELD_NET_PORT("", *sa_in, sin_port); 168 PRINT_FIELD_INET4_ADDR(", ", *sa_in, sin_addr); 169 } 170 171 #define SIN6_MIN_LEN offsetof(struct sockaddr_in6, sin6_scope_id) 172 173 static void 174 print_sockaddr_data_in6(const void *const buf, const int addrlen) 175 { 176 const struct sockaddr_in6 *const sa_in6 = buf; 177 178 PRINT_FIELD_NET_PORT("", *sa_in6, sin6_port); 179 PRINT_FIELD_INET_ADDR(", ", *sa_in6, sin6_addr, AF_INET6); 180 tprintf(", sin6_flowinfo=htonl(%u)", ntohl(sa_in6->sin6_flowinfo)); 181 182 if (addrlen <= (int) SIN6_MIN_LEN) 183 return; 184 185 #if defined IN6_IS_ADDR_LINKLOCAL && defined IN6_IS_ADDR_MC_LINKLOCAL 186 if (IN6_IS_ADDR_LINKLOCAL(&sa_in6->sin6_addr) 187 || IN6_IS_ADDR_MC_LINKLOCAL(&sa_in6->sin6_addr)) 188 PRINT_FIELD_IFINDEX(", ", *sa_in6, sin6_scope_id); 189 else 190 #endif 191 PRINT_FIELD_U(", ", *sa_in6, sin6_scope_id); 192 } 193 194 static void 195 print_sockaddr_data_ipx(const void *const buf, const int addrlen) 196 { 197 const struct sockaddr_ipx *const sa_ipx = buf; 198 unsigned int i; 199 200 PRINT_FIELD_NET_PORT("", *sa_ipx, sipx_port); 201 tprintf(", sipx_network=htonl(%#08x)" 202 ", sipx_node=[", 203 ntohl(sa_ipx->sipx_network)); 204 for (i = 0; i < IPX_NODE_LEN; ++i) { 205 tprintf("%s%#02x", i ? ", " : "", 206 sa_ipx->sipx_node[i]); 207 } 208 PRINT_FIELD_0X("], ", *sa_ipx, sipx_type); 209 } 210 211 static void 212 print_sockaddr_data_nl(const void *const buf, const int addrlen) 213 { 214 const struct sockaddr_nl *const sa_nl = buf; 215 216 PRINT_FIELD_D("", *sa_nl, nl_pid); 217 PRINT_FIELD_0X(", ", *sa_nl, nl_groups); 218 } 219 220 static void 221 print_sockaddr_data_ll(const void *const buf, const int addrlen) 222 { 223 const struct sockaddr_ll *const sa_ll = buf; 224 225 tprints("sll_protocol=htons("); 226 printxval(ethernet_protocols, ntohs(sa_ll->sll_protocol), "ETH_P_???"); 227 PRINT_FIELD_IFINDEX("), ", *sa_ll, sll_ifindex); 228 tprints(", sll_hatype="); 229 printxval(arp_hardware_types, sa_ll->sll_hatype, "ARPHRD_???"); 230 tprints(", sll_pkttype="); 231 printxval(af_packet_types, sa_ll->sll_pkttype, "PACKET_???"); 232 tprintf(", sll_halen=%u", sa_ll->sll_halen); 233 if (sa_ll->sll_halen) { 234 const unsigned int oob_halen = 235 addrlen - offsetof(struct sockaddr_ll, sll_addr); 236 unsigned int i; 237 238 tprints(", sll_addr=["); 239 for (i = 0; i < sa_ll->sll_halen; ++i) { 240 if (i) 241 tprints(", "); 242 if (i >= oob_halen) { 243 tprints("..."); 244 break; 245 } 246 tprintf("%#02x", sa_ll->sll_addr[i]); 247 } 248 tprints("]"); 249 } 250 } 251 252 static void 253 print_sockaddr_data_raw(const void *const buf, const int addrlen) 254 { 255 const char *const data = buf + SIZEOF_SA_FAMILY; 256 const int datalen = addrlen - SIZEOF_SA_FAMILY; 257 258 tprints("sa_data="); 259 print_quoted_string(data, datalen, 0); 260 } 261 262 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H 263 static void 264 print_sockaddr_data_bt(const void *const buf, const int addrlen) 265 { 266 switch (addrlen) { 267 case sizeof(struct sockaddr_hci): { 268 const struct sockaddr_hci *const hci = buf; 269 tprintf("hci_dev=htobs(%hu), hci_channel=", 270 btohs(hci->hci_dev)); 271 printxval(hci_channels, hci->hci_channel, 272 "HCI_CHANNEL_???"); 273 break; 274 } 275 case sizeof(struct sockaddr_sco): { 276 const struct sockaddr_sco *const sco = buf; 277 tprintf("sco_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x", 278 sco->sco_bdaddr.b[0], sco->sco_bdaddr.b[1], 279 sco->sco_bdaddr.b[2], sco->sco_bdaddr.b[3], 280 sco->sco_bdaddr.b[4], sco->sco_bdaddr.b[5]); 281 break; 282 } 283 case sizeof(struct sockaddr_rc): { 284 const struct sockaddr_rc *const rc = buf; 285 tprintf("rc_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" 286 ", rc_channel=%u", 287 rc->rc_bdaddr.b[0], rc->rc_bdaddr.b[1], 288 rc->rc_bdaddr.b[2], rc->rc_bdaddr.b[3], 289 rc->rc_bdaddr.b[4], rc->rc_bdaddr.b[5], 290 rc->rc_channel); 291 break; 292 } 293 case sizeof(struct sockaddr_l2): { 294 const struct sockaddr_l2 *const l2 = buf; 295 tprintf("l2_psm=htobs(%hu)" 296 ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" 297 ", l2_cid=htobs(%hu), l2_bdaddr_type=%u", 298 btohs(l2->l2_psm), 299 l2->l2_bdaddr.b[0], l2->l2_bdaddr.b[1], 300 l2->l2_bdaddr.b[2], l2->l2_bdaddr.b[3], 301 l2->l2_bdaddr.b[4], l2->l2_bdaddr.b[5], 302 btohs(l2->l2_cid), l2->l2_bdaddr_type); 303 break; 304 } 305 default: 306 print_sockaddr_data_raw(buf, addrlen); 307 break; 308 } 309 } 310 #endif /* HAVE_BLUETOOTH_BLUETOOTH_H */ 311 312 typedef void (* const sockaddr_printer)(const void *const, const int); 313 314 static const struct { 315 const sockaddr_printer printer; 316 const int min_len; 317 } sa_printers[] = { 318 [AF_UNIX] = { print_sockaddr_data_un, SIZEOF_SA_FAMILY + 1 }, 319 [AF_INET] = { print_sockaddr_data_in, sizeof(struct sockaddr_in) }, 320 [AF_IPX] = { print_sockaddr_data_ipx, sizeof(struct sockaddr_ipx) }, 321 [AF_INET6] = { print_sockaddr_data_in6, SIN6_MIN_LEN }, 322 [AF_NETLINK] = { print_sockaddr_data_nl, SIZEOF_SA_FAMILY + 1 }, 323 [AF_PACKET] = { print_sockaddr_data_ll, sizeof(struct sockaddr_ll) }, 324 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H 325 [AF_BLUETOOTH] = { print_sockaddr_data_bt, SIZEOF_SA_FAMILY + 1 }, 326 #endif 327 }; 328 329 void 330 print_sockaddr(const void *const buf, const int addrlen) 331 { 332 const struct sockaddr *const sa = buf; 333 334 tprints("{sa_family="); 335 printxval(addrfams, sa->sa_family, "AF_???"); 336 337 if (addrlen > (int) SIZEOF_SA_FAMILY) { 338 tprints(", "); 339 340 if (sa->sa_family < ARRAY_SIZE(sa_printers) 341 && sa_printers[sa->sa_family].printer 342 && addrlen >= sa_printers[sa->sa_family].min_len) { 343 sa_printers[sa->sa_family].printer(buf, addrlen); 344 } else { 345 print_sockaddr_data_raw(buf, addrlen); 346 } 347 } 348 349 tprints("}"); 350 } 351 352 int 353 decode_sockaddr(struct tcb *const tcp, const kernel_ulong_t addr, int addrlen) 354 { 355 if (addrlen < 2) { 356 printaddr(addr); 357 return -1; 358 } 359 360 union { 361 struct sockaddr sa; 362 struct sockaddr_storage storage; 363 char pad[sizeof(struct sockaddr_storage) + 1]; 364 } addrbuf; 365 366 if ((unsigned) addrlen > sizeof(addrbuf.storage)) 367 addrlen = sizeof(addrbuf.storage); 368 369 if (umoven_or_printaddr(tcp, addr, addrlen, addrbuf.pad)) 370 return -1; 371 372 memset(&addrbuf.pad[addrlen], 0, sizeof(addrbuf.pad) - addrlen); 373 374 print_sockaddr(&addrbuf, addrlen); 375 376 return addrbuf.sa.sa_family; 377 } 378