1 /* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 5 * Copyright (c) 1996-2000 Wichert Akkerman <wichert@cistron.nl> 6 * Copyright (c) 2005-2016 Dmitry V. Levin <ldv@altlinux.org> 7 * Copyright (c) 2016-2018 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/ax25.h> 43 #include <linux/if_packet.h> 44 #include <linux/if_arp.h> 45 #include <linux/if_ether.h> 46 #include <linux/x25.h> 47 48 #ifdef HAVE_NETIPX_IPX_H 49 # include <netipx/ipx.h> 50 #else 51 # include <linux/ipx.h> 52 #endif 53 54 #include "xlat/addrfams.h" 55 #include "xlat/arp_hardware_types.h" 56 #include "xlat/ethernet_protocols.h" 57 #include "xlat/af_packet_types.h" 58 59 #include "xlat/bdaddr_types.h" 60 #include "xlat/bluetooth_l2_cid.h" 61 #include "xlat/bluetooth_l2_psm.h" 62 #include "xlat/hci_channels.h" 63 64 #define SIZEOF_SA_FAMILY sizeof(((struct sockaddr *) 0)->sa_family) 65 66 const size_t arp_hardware_types_size = ARRAY_SIZE(arp_hardware_types) - 1; 67 const size_t ethernet_protocols_size = ARRAY_SIZE(ethernet_protocols) - 1; 68 69 static void print_sockaddr_data_un(const void * const buf,const int addrlen)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 print_inet_addr(const int af,const void * const addr,const unsigned int len,const char * const var_name)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 decode_inet_addr(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const int family,const char * const var_name)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 print_sockaddr_data_in(const void * const buf,const int addrlen)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 print_sockaddr_data_in6(const void * const buf,const int addrlen)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 /** 195 * Check that we can print an AX.25 address in its native form, otherwise it 196 * makes sense to print it in raw also (or in raw only). 197 */ 198 enum xlat_style check_ax25_address(const ax25_address * addr)199 check_ax25_address(const ax25_address *addr) 200 { 201 enum xlat_style ret = XLAT_STYLE_DEFAULT; 202 bool space_seen = false; 203 bool char_seen = false; 204 205 for (size_t i = 0; i < ARRAY_SIZE(addr->ax25_call) - 1; i++) { 206 unsigned char c = addr->ax25_call[i]; 207 208 /* The lowest bit should be zero */ 209 if (c & 1) 210 ret = XLAT_STYLE_VERBOSE; 211 212 c >>= 1; 213 214 if (c == ' ') 215 space_seen = true; 216 else 217 char_seen = true; 218 219 /* Sane address contains only numbers and uppercase letters */ 220 if ((c < '0' || c > '9') && (c < 'A' || c > 'Z') && c != ' ') 221 ret = XLAT_STYLE_VERBOSE; 222 if (c != ' ' && space_seen) 223 ret = XLAT_STYLE_VERBOSE; 224 225 /* non-printable chars */ 226 if (c < ' ' || c > 0x7e 227 /* characters used for printing comments */ 228 || c == '*' || c == '/') 229 return XLAT_STYLE_RAW; 230 } 231 232 if (addr->ax25_call[ARRAY_SIZE(addr->ax25_call) - 1] & ~0x1e) 233 ret = XLAT_STYLE_VERBOSE; 234 235 if (!char_seen && addr->ax25_call[ARRAY_SIZE(addr->ax25_call) - 1]) 236 ret = XLAT_STYLE_VERBOSE; 237 238 return ret; 239 } 240 241 /** Convert a (presumably) valid AX.25 to a string */ 242 static const char * ax25_addr2str(const ax25_address * addr)243 ax25_addr2str(const ax25_address *addr) 244 { 245 static char buf[ARRAY_SIZE(addr->ax25_call) + sizeof("-15")]; 246 char *p = buf; 247 size_t end; 248 249 for (end = ARRAY_SIZE(addr->ax25_call) - 1; end; end--) 250 if ((addr->ax25_call[end - 1] >> 1) != ' ') 251 break; 252 253 for (size_t i = 0; i < end; i++) 254 *p++ = ((unsigned char) addr->ax25_call[i]) >> 1; 255 256 *p++ = '-'; 257 258 unsigned char ssid = (addr->ax25_call[ARRAY_SIZE(addr->ax25_call) - 1] 259 >> 1) & 0xf; 260 261 if (ssid > 9) { 262 *p++ = '1'; 263 ssid -= 10; 264 } 265 266 *p++ = ssid + '0'; 267 *p = '\0'; 268 269 if (buf[0] == '-' && buf[1] == '0') 270 return "*"; 271 272 return buf; 273 } 274 275 static void print_ax25_addr_raw(const ax25_address * addr)276 print_ax25_addr_raw(const ax25_address *addr) 277 { 278 PRINT_FIELD_HEX_ARRAY("{", *addr, ax25_call); 279 tprints("}"); 280 } 281 282 void print_ax25_addr(const void * addr_void)283 print_ax25_addr(const void /* ax25_address */ *addr_void) 284 { 285 const ax25_address *addr = addr_void; 286 enum xlat_style xs = check_ax25_address(addr); 287 288 if (xs == XLAT_STYLE_DEFAULT) 289 xs = xlat_verbose(xlat_verbosity); 290 291 if (xs != XLAT_STYLE_ABBREV) 292 print_ax25_addr_raw(addr); 293 294 if (xs == XLAT_STYLE_RAW) 295 return; 296 297 const char *addr_str = ax25_addr2str(addr); 298 299 (xs == XLAT_STYLE_VERBOSE ? tprints_comment : tprints)(addr_str); 300 } 301 302 static void print_sockaddr_data_ax25(const void * const buf,const int addrlen)303 print_sockaddr_data_ax25(const void *const buf, const int addrlen) 304 { 305 const struct full_sockaddr_ax25 *const sax25 = buf; 306 size_t addrlen_us = MAX(addrlen, 0); 307 bool full = sax25->fsa_ax25.sax25_ndigis || 308 (addrlen_us > sizeof(struct sockaddr_ax25)); 309 310 if (full) 311 tprints("fsa_ax25={"); 312 313 tprints("sax25_call="); 314 print_ax25_addr(&sax25->fsa_ax25.sax25_call); 315 PRINT_FIELD_D(", ", sax25->fsa_ax25, sax25_ndigis); 316 317 if (!full) 318 return; 319 320 tprints("}"); 321 322 size_t has_digis = MIN((addrlen_us - sizeof(sax25->fsa_ax25)) 323 / sizeof(sax25->fsa_digipeater[0]), 324 ARRAY_SIZE(sax25->fsa_digipeater)); 325 size_t want_digis = MIN( 326 (unsigned int) MAX(sax25->fsa_ax25.sax25_ndigis, 0), 327 ARRAY_SIZE(sax25->fsa_digipeater)); 328 size_t digis = MIN(has_digis, want_digis); 329 330 if (want_digis == 0) 331 goto digis_end; 332 333 tprints(", fsa_digipeater=["); 334 for (size_t i = 0; i < digis; i++) { 335 if (i) 336 tprints(", "); 337 338 print_ax25_addr(sax25->fsa_digipeater + i); 339 } 340 341 if (want_digis > has_digis) 342 tprintf("%s/* ??? */", digis ? ", " : ""); 343 344 tprints("]"); 345 346 digis_end: 347 if (addrlen_us > (has_digis * sizeof(sax25->fsa_digipeater[0]) 348 + sizeof(sax25->fsa_ax25))) 349 tprints(", ..."); 350 } 351 352 static void print_sockaddr_data_ipx(const void * const buf,const int addrlen)353 print_sockaddr_data_ipx(const void *const buf, const int addrlen) 354 { 355 const struct sockaddr_ipx *const sa_ipx = buf; 356 unsigned int i; 357 358 PRINT_FIELD_NET_PORT("", *sa_ipx, sipx_port); 359 tprintf(", sipx_network=htonl(%#08x)" 360 ", sipx_node=[", 361 ntohl(sa_ipx->sipx_network)); 362 for (i = 0; i < IPX_NODE_LEN; ++i) { 363 tprintf("%s%#02x", i ? ", " : "", 364 sa_ipx->sipx_node[i]); 365 } 366 PRINT_FIELD_0X("], ", *sa_ipx, sipx_type); 367 } 368 369 void print_x25_addr(const void * addr_void)370 print_x25_addr(const void /* struct x25_address */ *addr_void) 371 { 372 const struct x25_address *addr = addr_void; 373 374 tprints("{x25_addr="); 375 print_quoted_cstring(addr->x25_addr, sizeof(addr->x25_addr)); 376 tprints("}"); 377 } 378 379 static void print_sockaddr_data_x25(const void * const buf,const int addrlen)380 print_sockaddr_data_x25(const void *const buf, const int addrlen) 381 { 382 const struct sockaddr_x25 *const sa_x25 = buf; 383 384 PRINT_FIELD_X25_ADDR("", *sa_x25, sx25_addr); 385 } 386 387 static void print_sockaddr_data_nl(const void * const buf,const int addrlen)388 print_sockaddr_data_nl(const void *const buf, const int addrlen) 389 { 390 const struct sockaddr_nl *const sa_nl = buf; 391 392 PRINT_FIELD_D("", *sa_nl, nl_pid); 393 PRINT_FIELD_0X(", ", *sa_nl, nl_groups); 394 } 395 396 static void print_sockaddr_data_ll(const void * const buf,const int addrlen)397 print_sockaddr_data_ll(const void *const buf, const int addrlen) 398 { 399 const struct sockaddr_ll *const sa_ll = buf; 400 401 tprints("sll_protocol=htons("); 402 printxval_search(ethernet_protocols, ntohs(sa_ll->sll_protocol), 403 "ETH_P_???"); 404 PRINT_FIELD_IFINDEX("), ", *sa_ll, sll_ifindex); 405 tprints(", sll_hatype="); 406 printxval_search(arp_hardware_types, sa_ll->sll_hatype, "ARPHRD_???"); 407 tprints(", sll_pkttype="); 408 printxval_index(af_packet_types, sa_ll->sll_pkttype, "PACKET_???"); 409 tprintf(", sll_halen=%u", sa_ll->sll_halen); 410 if (sa_ll->sll_halen) { 411 const unsigned int oob_halen = 412 addrlen - offsetof(struct sockaddr_ll, sll_addr); 413 unsigned int i; 414 415 tprints(", sll_addr=["); 416 for (i = 0; i < sa_ll->sll_halen; ++i) { 417 if (i) 418 tprints(", "); 419 if (i >= oob_halen) { 420 tprints("..."); 421 break; 422 } 423 tprintf("%#02x", sa_ll->sll_addr[i]); 424 } 425 tprints("]"); 426 } 427 } 428 429 static void print_sockaddr_data_raw(const void * const buf,const int addrlen)430 print_sockaddr_data_raw(const void *const buf, const int addrlen) 431 { 432 const char *const data = buf + SIZEOF_SA_FAMILY; 433 const int datalen = addrlen - SIZEOF_SA_FAMILY; 434 435 tprints("sa_data="); 436 print_quoted_string(data, datalen, 0); 437 } 438 439 static uint16_t btohs(uint16_t val)440 btohs(uint16_t val) 441 { 442 #ifdef WORDS_BIGENDIAN 443 return (val << 8) | (val >> 8); 444 #else 445 return val; 446 #endif 447 } 448 449 static void print_bluetooth_l2_psm(const char * prefix,uint16_t psm)450 print_bluetooth_l2_psm(const char *prefix, uint16_t psm) 451 { 452 const uint16_t psm_he = btohs(psm); 453 const char *psm_name = xlookup(bluetooth_l2_psm, psm_he); 454 const bool psm_str = psm_name || (psm_he >= L2CAP_PSM_LE_DYN_START 455 && psm_he <= L2CAP_PSM_LE_DYN_END) 456 || (psm_he >= L2CAP_PSM_DYN_START); 457 458 tprintf("%shtobs(", prefix); 459 460 if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV || !psm_str) 461 tprintf("%#x", psm_he); 462 463 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW) 464 goto print_bluetooth_l2_psm_end; 465 466 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE || !psm_str) 467 tprints(" /* "); 468 469 if (psm_name) { 470 tprints(psm_name); 471 } else if (psm_he >= L2CAP_PSM_LE_DYN_START 472 && psm_he <= L2CAP_PSM_LE_DYN_END) { 473 print_xlat(L2CAP_PSM_LE_DYN_START); 474 tprintf(" + %u", psm_he - L2CAP_PSM_LE_DYN_START); 475 } else if (psm_he >= L2CAP_PSM_DYN_START) { 476 print_xlat(L2CAP_PSM_DYN_START); 477 tprintf(" + %u", psm_he - L2CAP_PSM_DYN_START); 478 } else { 479 tprints("L2CAP_PSM_???"); 480 } 481 482 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE || !psm_str) 483 tprints(" */"); 484 485 print_bluetooth_l2_psm_end: 486 tprints(")"); 487 } 488 489 static void print_bluetooth_l2_cid(const char * prefix,uint16_t cid)490 print_bluetooth_l2_cid(const char *prefix, uint16_t cid) 491 { 492 const uint16_t cid_he = btohs(cid); 493 const char *cid_name = xlookup(bluetooth_l2_cid, cid_he); 494 const bool cid_str = cid_name || (cid_he >= L2CAP_CID_DYN_START); 495 496 tprintf("%shtobs(", prefix); 497 498 if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV || !cid_str) 499 tprintf("%#x", cid_he); 500 501 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW) 502 goto print_bluetooth_l2_cid_end; 503 504 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE || !cid_str) 505 tprints(" /* "); 506 507 if (cid_name) { 508 tprints(cid_name); 509 } else if (cid_he >= L2CAP_CID_DYN_START) { 510 print_xlat(L2CAP_CID_DYN_START); 511 tprintf(" + %u", cid_he - L2CAP_CID_DYN_START); 512 } else { 513 tprints("L2CAP_CID_???"); 514 } 515 516 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE || !cid_str) 517 tprints(" */"); 518 519 print_bluetooth_l2_cid_end: 520 tprints(")"); 521 } 522 523 static void print_sockaddr_data_bt(const void * const buf,const int addrlen)524 print_sockaddr_data_bt(const void *const buf, const int addrlen) 525 { 526 struct sockaddr_hci { 527 /* sa_family_t */ uint16_t hci_family; 528 uint16_t hci_dev; 529 uint16_t hci_channel; 530 }; 531 532 struct bdaddr { 533 uint8_t b[6]; 534 } ATTRIBUTE_PACKED; 535 536 struct sockaddr_sco { 537 /* sa_family_t */ uint16_t sco_family; 538 struct bdaddr sco_bdaddr; 539 }; 540 541 struct sockaddr_rc { 542 /* sa_family_t */ uint16_t rc_family; 543 struct bdaddr rc_bdaddr; 544 uint8_t rc_channel; 545 }; 546 547 struct sockaddr_l2 { 548 /* sa_family_t */ uint16_t l2_family; 549 /* little endian */ uint16_t l2_psm; 550 struct bdaddr l2_bdaddr; 551 /* little endian */ uint16_t l2_cid; 552 uint8_t l2_bdaddr_type; 553 }; 554 555 switch (addrlen) { 556 case sizeof(struct sockaddr_hci): { 557 const struct sockaddr_hci *const hci = buf; 558 tprintf("hci_dev=htobs(%hu), hci_channel=", 559 btohs(hci->hci_dev)); 560 printxval_index(hci_channels, hci->hci_channel, 561 "HCI_CHANNEL_???"); 562 break; 563 } 564 case sizeof(struct sockaddr_sco): { 565 const struct sockaddr_sco *const sco = buf; 566 print_mac_addr("sco_bdaddr=", sco->sco_bdaddr.b, 567 sizeof(sco->sco_bdaddr.b)); 568 break; 569 } 570 case sizeof(struct sockaddr_rc): { 571 const struct sockaddr_rc *const rc = buf; 572 print_mac_addr("rc_bdaddr=", rc->rc_bdaddr.b, 573 sizeof(rc->rc_bdaddr.b)); 574 tprintf(", rc_channel=%u", rc->rc_channel); 575 break; 576 } 577 case offsetof(struct sockaddr_l2, l2_bdaddr_type): 578 case sizeof(struct sockaddr_l2): { 579 const struct sockaddr_l2 *const l2 = buf; 580 print_bluetooth_l2_psm("l2_psm=", l2->l2_psm); 581 print_mac_addr(", l2_bdaddr=", l2->l2_bdaddr.b, 582 sizeof(l2->l2_bdaddr.b)); 583 print_bluetooth_l2_cid(", l2_cid=", l2->l2_cid); 584 585 if (addrlen == sizeof(struct sockaddr_l2)) { 586 tprints(", l2_bdaddr_type="); 587 printxval_index(bdaddr_types, l2->l2_bdaddr_type, 588 "BDADDR_???"); 589 } 590 591 break; 592 } 593 default: 594 print_sockaddr_data_raw(buf, addrlen); 595 break; 596 } 597 } 598 599 typedef void (* const sockaddr_printer)(const void *const, const int); 600 601 static const struct { 602 const sockaddr_printer printer; 603 const int min_len; 604 } sa_printers[] = { 605 [AF_UNIX] = { print_sockaddr_data_un, SIZEOF_SA_FAMILY + 1 }, 606 [AF_INET] = { print_sockaddr_data_in, sizeof(struct sockaddr_in) }, 607 [AF_AX25] = { print_sockaddr_data_ax25, sizeof(struct sockaddr_ax25) }, 608 [AF_IPX] = { print_sockaddr_data_ipx, sizeof(struct sockaddr_ipx) }, 609 [AF_X25] = { print_sockaddr_data_x25, sizeof(struct sockaddr_x25) }, 610 [AF_INET6] = { print_sockaddr_data_in6, SIN6_MIN_LEN }, 611 [AF_NETLINK] = { print_sockaddr_data_nl, SIZEOF_SA_FAMILY + 1 }, 612 [AF_PACKET] = { print_sockaddr_data_ll, sizeof(struct sockaddr_ll) }, 613 [AF_BLUETOOTH] = { print_sockaddr_data_bt, SIZEOF_SA_FAMILY + 1 }, 614 }; 615 616 void print_sockaddr(const void * const buf,const int addrlen)617 print_sockaddr(const void *const buf, const int addrlen) 618 { 619 const struct sockaddr *const sa = buf; 620 621 tprints("{sa_family="); 622 printxval_index(addrfams, sa->sa_family, "AF_???"); 623 624 if (addrlen > (int) SIZEOF_SA_FAMILY) { 625 tprints(", "); 626 627 if (sa->sa_family < ARRAY_SIZE(sa_printers) 628 && sa_printers[sa->sa_family].printer 629 && addrlen >= sa_printers[sa->sa_family].min_len) { 630 sa_printers[sa->sa_family].printer(buf, addrlen); 631 } else { 632 print_sockaddr_data_raw(buf, addrlen); 633 } 634 } 635 636 tprints("}"); 637 } 638 639 int decode_sockaddr(struct tcb * const tcp,const kernel_ulong_t addr,int addrlen)640 decode_sockaddr(struct tcb *const tcp, const kernel_ulong_t addr, int addrlen) 641 { 642 if (addrlen < 2) { 643 printaddr(addr); 644 return -1; 645 } 646 647 union { 648 struct sockaddr sa; 649 struct sockaddr_storage storage; 650 char pad[sizeof(struct sockaddr_storage) + 1]; 651 } addrbuf; 652 653 if ((unsigned) addrlen > sizeof(addrbuf.storage)) 654 addrlen = sizeof(addrbuf.storage); 655 656 if (umoven_or_printaddr(tcp, addr, addrlen, addrbuf.pad)) 657 return -1; 658 659 memset(&addrbuf.pad[addrlen], 0, sizeof(addrbuf.pad) - addrlen); 660 661 print_sockaddr(&addrbuf, addrlen); 662 663 return addrbuf.sa.sa_family; 664 } 665