Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sockaddr.c 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  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. * SPDX-License-Identifier: LGPL-2.1-or-later
  11. */
  12. #include "defs.h"
  13. #include "print_fields.h"
  14. #include <sys/socket.h>
  15. #include <sys/un.h>
  16. #include <netinet/in.h>
  17. #include <arpa/inet.h>
  18. #include "netlink.h"
  19. #include <linux/ax25.h>
  20. #include <linux/if_packet.h>
  21. #include <linux/if_arp.h>
  22. #include <linux/if_ether.h>
  23. #include <linux/x25.h>
  24. #ifdef HAVE_NETIPX_IPX_H
  25. # include <netipx/ipx.h>
  26. #else
  27. # include <linux/ipx.h>
  28. #endif
  29. #include "xlat/addrfams.h"
  30. #include "xlat/arp_hardware_types.h"
  31. #include "xlat/ethernet_protocols.h"
  32. #include "xlat/af_packet_types.h"
  33. #include "xlat/bdaddr_types.h"
  34. #include "xlat/bluetooth_l2_cid.h"
  35. #include "xlat/bluetooth_l2_psm.h"
  36. #include "xlat/hci_channels.h"
  37. #define SIZEOF_SA_FAMILY sizeof(((struct sockaddr *) 0)->sa_family)
  38. const size_t arp_hardware_types_size = ARRAY_SIZE(arp_hardware_types) - 1;
  39. const size_t ethernet_protocols_size = ARRAY_SIZE(ethernet_protocols) - 1;
  40. static void
  41. print_sockaddr_data_un(const void *const buf, const int addrlen)
  42. {
  43. const struct sockaddr_un *const sa_un = buf;
  44. const int un_len = addrlen > (int) sizeof(*sa_un)
  45. ? (int) sizeof(*sa_un) : addrlen;
  46. const int path_len = un_len - SIZEOF_SA_FAMILY;
  47. tprints("sun_path=");
  48. if (sa_un->sun_path[0]) {
  49. print_quoted_string(sa_un->sun_path, path_len + 1,
  50. QUOTE_0_TERMINATED);
  51. } else {
  52. tprints("@");
  53. print_quoted_string(sa_un->sun_path + 1, path_len - 1, 0);
  54. }
  55. }
  56. bool
  57. print_inet_addr(const int af,
  58. const void *const addr,
  59. const unsigned int len,
  60. const char *const var_name)
  61. {
  62. char buf[INET6_ADDRSTRLEN];
  63. switch (af) {
  64. case AF_INET:
  65. if (inet_ntop(af, addr, buf, sizeof(buf))) {
  66. if (var_name)
  67. tprintf("%s=", var_name);
  68. if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV)
  69. print_quoted_string((const char*) addr,
  70. len, QUOTE_FORCE_HEX);
  71. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
  72. return true;
  73. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
  74. tprints(" /* ");
  75. tprintf("inet_addr(\"%s\")", buf);
  76. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
  77. tprints(" */");
  78. return true;
  79. }
  80. break;
  81. case AF_INET6:
  82. if (inet_ntop(af, addr, buf, sizeof(buf))) {
  83. if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV) {
  84. if (var_name)
  85. tprintf("%s=", var_name);
  86. print_quoted_string(addr, len, QUOTE_FORCE_HEX);
  87. }
  88. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
  89. return true;
  90. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
  91. tprints(" /* ");
  92. if (var_name &&
  93. (xlat_verbose(xlat_verbosity) == XLAT_STYLE_ABBREV))
  94. tprintf("inet_pton(%s, \"%s\", &%s)",
  95. "AF_INET6", buf, var_name);
  96. else
  97. tprintf("inet_pton(%s, \"%s\")",
  98. "AF_INET6", buf);
  99. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
  100. tprints(" */");
  101. return true;
  102. }
  103. break;
  104. }
  105. if (var_name)
  106. tprintf("%s=", var_name);
  107. print_quoted_string(addr, len, QUOTE_FORCE_HEX);
  108. return false;
  109. }
  110. bool
  111. decode_inet_addr(struct tcb *const tcp,
  112. const kernel_ulong_t addr,
  113. const unsigned int len,
  114. const int family,
  115. const char *const var_name)
  116. {
  117. union {
  118. struct in_addr a4;
  119. struct in6_addr a6;
  120. } addrbuf;
  121. size_t size = 0;
  122. switch (family) {
  123. case AF_INET:
  124. size = sizeof(addrbuf.a4);
  125. break;
  126. case AF_INET6:
  127. size = sizeof(addrbuf.a6);
  128. break;
  129. }
  130. if (!size || len < size) {
  131. if (var_name)
  132. tprintf("%s=", var_name);
  133. printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
  134. return false;
  135. }
  136. if (umoven(tcp, addr, size, &addrbuf) < 0) {
  137. if (var_name)
  138. tprintf("%s=", var_name);
  139. printaddr(addr);
  140. return false;
  141. }
  142. return print_inet_addr(family, &addrbuf, size, var_name);
  143. }
  144. static void
  145. print_sockaddr_data_in(const void *const buf, const int addrlen)
  146. {
  147. const struct sockaddr_in *const sa_in = buf;
  148. PRINT_FIELD_NET_PORT("", *sa_in, sin_port);
  149. PRINT_FIELD_INET_ADDR(", ", *sa_in, sin_addr, AF_INET);
  150. }
  151. #define SIN6_MIN_LEN offsetof(struct sockaddr_in6, sin6_scope_id)
  152. static void
  153. print_sockaddr_data_in6(const void *const buf, const int addrlen)
  154. {
  155. const struct sockaddr_in6 *const sa_in6 = buf;
  156. PRINT_FIELD_NET_PORT("", *sa_in6, sin6_port);
  157. tprints(", sin6_flowinfo=");
  158. if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV)
  159. print_quoted_string((const char*) &sa_in6->sin6_flowinfo,
  160. sizeof(sa_in6->sin6_flowinfo),
  161. QUOTE_FORCE_HEX);
  162. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
  163. tprintf(" /* htonl(%u) */", ntohl(sa_in6->sin6_flowinfo));
  164. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_ABBREV)
  165. tprintf("htonl(%u)", ntohl(sa_in6->sin6_flowinfo));
  166. PRINT_FIELD_INET_ADDR(", ", *sa_in6, sin6_addr, AF_INET6);
  167. if (addrlen <= (int) SIN6_MIN_LEN)
  168. return;
  169. #if defined IN6_IS_ADDR_LINKLOCAL && defined IN6_IS_ADDR_MC_LINKLOCAL
  170. if (IN6_IS_ADDR_LINKLOCAL(&sa_in6->sin6_addr)
  171. || IN6_IS_ADDR_MC_LINKLOCAL(&sa_in6->sin6_addr))
  172. PRINT_FIELD_IFINDEX(", ", *sa_in6, sin6_scope_id);
  173. else
  174. #endif
  175. PRINT_FIELD_U(", ", *sa_in6, sin6_scope_id);
  176. }
  177. /**
  178. * Check that we can print an AX.25 address in its native form, otherwise it
  179. * makes sense to print it in raw also (or in raw only).
  180. */
  181. enum xlat_style
  182. check_ax25_address(const ax25_address *addr)
  183. {
  184. enum xlat_style ret = XLAT_STYLE_DEFAULT;
  185. bool space_seen = false;
  186. bool char_seen = false;
  187. for (size_t i = 0; i < ARRAY_SIZE(addr->ax25_call) - 1; i++) {
  188. unsigned char c = addr->ax25_call[i];
  189. /* The lowest bit should be zero */
  190. if (c & 1)
  191. ret = XLAT_STYLE_VERBOSE;
  192. c >>= 1;
  193. if (c == ' ')
  194. space_seen = true;
  195. else
  196. char_seen = true;
  197. /* Sane address contains only numbers and uppercase letters */
  198. if ((c < '0' || c > '9') && (c < 'A' || c > 'Z') && c != ' ')
  199. ret = XLAT_STYLE_VERBOSE;
  200. if (c != ' ' && space_seen)
  201. ret = XLAT_STYLE_VERBOSE;
  202. /* non-printable chars */
  203. if (c < ' ' || c > 0x7e
  204. /* characters used for printing comments */
  205. || c == '*' || c == '/')
  206. return XLAT_STYLE_RAW;
  207. }
  208. if (addr->ax25_call[ARRAY_SIZE(addr->ax25_call) - 1] & ~0x1e)
  209. ret = XLAT_STYLE_VERBOSE;
  210. if (!char_seen && addr->ax25_call[ARRAY_SIZE(addr->ax25_call) - 1])
  211. ret = XLAT_STYLE_VERBOSE;
  212. return ret;
  213. }
  214. /** Convert a (presumably) valid AX.25 to a string */
  215. static const char *
  216. ax25_addr2str(const ax25_address *addr)
  217. {
  218. static char buf[ARRAY_SIZE(addr->ax25_call) + sizeof("-15")];
  219. char *p = buf;
  220. size_t end;
  221. for (end = ARRAY_SIZE(addr->ax25_call) - 1; end; end--)
  222. if ((addr->ax25_call[end - 1] >> 1) != ' ')
  223. break;
  224. for (size_t i = 0; i < end; i++)
  225. *p++ = ((unsigned char) addr->ax25_call[i]) >> 1;
  226. *p++ = '-';
  227. unsigned char ssid = (addr->ax25_call[ARRAY_SIZE(addr->ax25_call) - 1]
  228. >> 1) & 0xf;
  229. if (ssid > 9) {
  230. *p++ = '1';
  231. ssid -= 10;
  232. }
  233. *p++ = ssid + '0';
  234. *p = '\0';
  235. if (buf[0] == '-' && buf[1] == '0')
  236. return "*";
  237. return buf;
  238. }
  239. static void
  240. print_ax25_addr_raw(const ax25_address *addr)
  241. {
  242. PRINT_FIELD_HEX_ARRAY("{", *addr, ax25_call);
  243. tprints("}");
  244. }
  245. void
  246. print_ax25_addr(const void /* ax25_address */ *addr_void)
  247. {
  248. const ax25_address *addr = addr_void;
  249. enum xlat_style xs = check_ax25_address(addr);
  250. if (xs == XLAT_STYLE_DEFAULT)
  251. xs = xlat_verbose(xlat_verbosity);
  252. if (xs != XLAT_STYLE_ABBREV)
  253. print_ax25_addr_raw(addr);
  254. if (xs == XLAT_STYLE_RAW)
  255. return;
  256. const char *addr_str = ax25_addr2str(addr);
  257. (xs == XLAT_STYLE_VERBOSE ? tprints_comment : tprints)(addr_str);
  258. }
  259. static void
  260. print_sockaddr_data_ax25(const void *const buf, const int addrlen)
  261. {
  262. const struct full_sockaddr_ax25 *const sax25 = buf;
  263. size_t addrlen_us = MAX(addrlen, 0);
  264. bool full = sax25->fsa_ax25.sax25_ndigis ||
  265. (addrlen_us > sizeof(struct sockaddr_ax25));
  266. if (full)
  267. tprints("fsa_ax25={");
  268. tprints("sax25_call=");
  269. print_ax25_addr(&sax25->fsa_ax25.sax25_call);
  270. PRINT_FIELD_D(", ", sax25->fsa_ax25, sax25_ndigis);
  271. if (!full)
  272. return;
  273. tprints("}");
  274. size_t has_digis = MIN((addrlen_us - sizeof(sax25->fsa_ax25))
  275. / sizeof(sax25->fsa_digipeater[0]),
  276. ARRAY_SIZE(sax25->fsa_digipeater));
  277. size_t want_digis = MIN(
  278. (unsigned int) MAX(sax25->fsa_ax25.sax25_ndigis, 0),
  279. ARRAY_SIZE(sax25->fsa_digipeater));
  280. size_t digis = MIN(has_digis, want_digis);
  281. if (want_digis == 0)
  282. goto digis_end;
  283. tprints(", fsa_digipeater=[");
  284. for (size_t i = 0; i < digis; i++) {
  285. if (i)
  286. tprints(", ");
  287. print_ax25_addr(sax25->fsa_digipeater + i);
  288. }
  289. if (want_digis > has_digis)
  290. tprintf("%s/* ??? */", digis ? ", " : "");
  291. tprints("]");
  292. digis_end:
  293. if (addrlen_us > (has_digis * sizeof(sax25->fsa_digipeater[0])
  294. + sizeof(sax25->fsa_ax25)))
  295. tprints(", ...");
  296. }
  297. static void
  298. print_sockaddr_data_ipx(const void *const buf, const int addrlen)
  299. {
  300. const struct sockaddr_ipx *const sa_ipx = buf;
  301. unsigned int i;
  302. PRINT_FIELD_NET_PORT("", *sa_ipx, sipx_port);
  303. tprintf(", sipx_network=htonl(%#08x)"
  304. ", sipx_node=[",
  305. ntohl(sa_ipx->sipx_network));
  306. for (i = 0; i < IPX_NODE_LEN; ++i) {
  307. tprintf("%s%#02x", i ? ", " : "",
  308. sa_ipx->sipx_node[i]);
  309. }
  310. PRINT_FIELD_0X("], ", *sa_ipx, sipx_type);
  311. }
  312. void
  313. print_x25_addr(const void /* struct x25_address */ *addr_void)
  314. {
  315. const struct x25_address *addr = addr_void;
  316. tprints("{x25_addr=");
  317. print_quoted_cstring(addr->x25_addr, sizeof(addr->x25_addr));
  318. tprints("}");
  319. }
  320. static void
  321. print_sockaddr_data_x25(const void *const buf, const int addrlen)
  322. {
  323. const struct sockaddr_x25 *const sa_x25 = buf;
  324. PRINT_FIELD_X25_ADDR("", *sa_x25, sx25_addr);
  325. }
  326. static void
  327. print_sockaddr_data_nl(const void *const buf, const int addrlen)
  328. {
  329. const struct sockaddr_nl *const sa_nl = buf;
  330. PRINT_FIELD_D("", *sa_nl, nl_pid);
  331. PRINT_FIELD_0X(", ", *sa_nl, nl_groups);
  332. }
  333. static void
  334. print_sll_protocol(const struct sockaddr_ll *const sa_ll)
  335. {
  336. int x_style = xlat_verbose(xlat_verbosity);
  337. tprints("sll_protocol=");
  338. if (x_style != XLAT_STYLE_ABBREV)
  339. print_quoted_string((const char *) &sa_ll->sll_protocol,
  340. sizeof(sa_ll->sll_protocol),
  341. QUOTE_FORCE_HEX);
  342. if (x_style == XLAT_STYLE_RAW)
  343. return;
  344. if (x_style == XLAT_STYLE_VERBOSE)
  345. tprints(" /* ");
  346. tprints("htons(");
  347. printxval_search_ex(ethernet_protocols, ntohs(sa_ll->sll_protocol),
  348. "ETH_P_???", XLAT_STYLE_ABBREV);
  349. tprints(")");
  350. if (x_style == XLAT_STYLE_VERBOSE)
  351. tprints(" */");
  352. }
  353. static void
  354. print_sockaddr_data_ll(const void *const buf, const int addrlen)
  355. {
  356. const struct sockaddr_ll *const sa_ll = buf;
  357. print_sll_protocol(sa_ll);
  358. PRINT_FIELD_IFINDEX(", ", *sa_ll, sll_ifindex);
  359. tprints(", sll_hatype=");
  360. printxval_search(arp_hardware_types, sa_ll->sll_hatype, "ARPHRD_???");
  361. tprints(", sll_pkttype=");
  362. printxval_index(af_packet_types, sa_ll->sll_pkttype, "PACKET_???");
  363. tprintf(", sll_halen=%u", sa_ll->sll_halen);
  364. if (sa_ll->sll_halen) {
  365. const unsigned int oob_halen =
  366. addrlen - offsetof(struct sockaddr_ll, sll_addr);
  367. unsigned int i;
  368. tprints(", sll_addr=[");
  369. for (i = 0; i < sa_ll->sll_halen; ++i) {
  370. if (i)
  371. tprints(", ");
  372. if (i >= oob_halen) {
  373. tprints("...");
  374. break;
  375. }
  376. tprintf("%#02x", sa_ll->sll_addr[i]);
  377. }
  378. tprints("]");
  379. }
  380. }
  381. static void
  382. print_sockaddr_data_raw(const void *const buf, const int addrlen)
  383. {
  384. const char *const data = buf + SIZEOF_SA_FAMILY;
  385. const int datalen = addrlen - SIZEOF_SA_FAMILY;
  386. tprints("sa_data=");
  387. print_quoted_string(data, datalen, 0);
  388. }
  389. static uint16_t
  390. btohs(uint16_t val)
  391. {
  392. #ifdef WORDS_BIGENDIAN
  393. return (val << 8) | (val >> 8);
  394. #else
  395. return val;
  396. #endif
  397. }
  398. static void
  399. print_bluetooth_l2_psm(const char *prefix, uint16_t psm)
  400. {
  401. const uint16_t psm_he = btohs(psm);
  402. const char *psm_name = xlookup(bluetooth_l2_psm, psm_he);
  403. const bool psm_str = psm_name || (psm_he >= L2CAP_PSM_LE_DYN_START
  404. && psm_he <= L2CAP_PSM_LE_DYN_END)
  405. || (psm_he >= L2CAP_PSM_DYN_START);
  406. tprintf("%shtobs(", prefix);
  407. if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV || !psm_str)
  408. tprintf("%#x", psm_he);
  409. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
  410. goto print_bluetooth_l2_psm_end;
  411. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE || !psm_str)
  412. tprints(" /* ");
  413. if (psm_name) {
  414. tprints(psm_name);
  415. } else if (psm_he >= L2CAP_PSM_LE_DYN_START
  416. && psm_he <= L2CAP_PSM_LE_DYN_END) {
  417. print_xlat(L2CAP_PSM_LE_DYN_START);
  418. tprintf(" + %u", psm_he - L2CAP_PSM_LE_DYN_START);
  419. } else if (psm_he >= L2CAP_PSM_DYN_START) {
  420. print_xlat(L2CAP_PSM_DYN_START);
  421. tprintf(" + %u", psm_he - L2CAP_PSM_DYN_START);
  422. } else {
  423. tprints("L2CAP_PSM_???");
  424. }
  425. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE || !psm_str)
  426. tprints(" */");
  427. print_bluetooth_l2_psm_end:
  428. tprints(")");
  429. }
  430. static void
  431. print_bluetooth_l2_cid(const char *prefix, uint16_t cid)
  432. {
  433. const uint16_t cid_he = btohs(cid);
  434. const char *cid_name = xlookup(bluetooth_l2_cid, cid_he);
  435. const bool cid_str = cid_name || (cid_he >= L2CAP_CID_DYN_START);
  436. tprintf("%shtobs(", prefix);
  437. if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV || !cid_str)
  438. tprintf("%#x", cid_he);
  439. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
  440. goto print_bluetooth_l2_cid_end;
  441. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE || !cid_str)
  442. tprints(" /* ");
  443. if (cid_name) {
  444. tprints(cid_name);
  445. } else if (cid_he >= L2CAP_CID_DYN_START) {
  446. print_xlat(L2CAP_CID_DYN_START);
  447. tprintf(" + %u", cid_he - L2CAP_CID_DYN_START);
  448. } else {
  449. tprints("L2CAP_CID_???");
  450. }
  451. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE || !cid_str)
  452. tprints(" */");
  453. print_bluetooth_l2_cid_end:
  454. tprints(")");
  455. }
  456. static void
  457. print_sockaddr_data_bt(const void *const buf, const int addrlen)
  458. {
  459. struct sockaddr_hci {
  460. /* sa_family_t */ uint16_t hci_family;
  461. uint16_t hci_dev;
  462. uint16_t hci_channel;
  463. };
  464. struct bdaddr {
  465. uint8_t b[6];
  466. } ATTRIBUTE_PACKED;
  467. struct sockaddr_sco {
  468. /* sa_family_t */ uint16_t sco_family;
  469. struct bdaddr sco_bdaddr;
  470. };
  471. struct sockaddr_rc {
  472. /* sa_family_t */ uint16_t rc_family;
  473. struct bdaddr rc_bdaddr;
  474. uint8_t rc_channel;
  475. };
  476. struct sockaddr_l2 {
  477. /* sa_family_t */ uint16_t l2_family;
  478. /* little endian */ uint16_t l2_psm;
  479. struct bdaddr l2_bdaddr;
  480. /* little endian */ uint16_t l2_cid;
  481. uint8_t l2_bdaddr_type;
  482. };
  483. switch (addrlen) {
  484. case sizeof(struct sockaddr_hci): {
  485. const struct sockaddr_hci *const hci = buf;
  486. tprintf("hci_dev=htobs(%hu), hci_channel=",
  487. btohs(hci->hci_dev));
  488. printxval_index(hci_channels, hci->hci_channel,
  489. "HCI_CHANNEL_???");
  490. break;
  491. }
  492. case sizeof(struct sockaddr_sco): {
  493. const struct sockaddr_sco *const sco = buf;
  494. print_mac_addr("sco_bdaddr=", sco->sco_bdaddr.b,
  495. sizeof(sco->sco_bdaddr.b));
  496. break;
  497. }
  498. case sizeof(struct sockaddr_rc): {
  499. const struct sockaddr_rc *const rc = buf;
  500. print_mac_addr("rc_bdaddr=", rc->rc_bdaddr.b,
  501. sizeof(rc->rc_bdaddr.b));
  502. tprintf(", rc_channel=%u", rc->rc_channel);
  503. break;
  504. }
  505. case offsetof(struct sockaddr_l2, l2_bdaddr_type):
  506. case sizeof(struct sockaddr_l2): {
  507. const struct sockaddr_l2 *const l2 = buf;
  508. print_bluetooth_l2_psm("l2_psm=", l2->l2_psm);
  509. print_mac_addr(", l2_bdaddr=", l2->l2_bdaddr.b,
  510. sizeof(l2->l2_bdaddr.b));
  511. print_bluetooth_l2_cid(", l2_cid=", l2->l2_cid);
  512. if (addrlen == sizeof(struct sockaddr_l2)) {
  513. tprints(", l2_bdaddr_type=");
  514. printxval_index(bdaddr_types, l2->l2_bdaddr_type,
  515. "BDADDR_???");
  516. }
  517. break;
  518. }
  519. default:
  520. print_sockaddr_data_raw(buf, addrlen);
  521. break;
  522. }
  523. }
  524. typedef void (* const sockaddr_printer)(const void *const, const int);
  525. static const struct {
  526. const sockaddr_printer printer;
  527. const int min_len;
  528. } sa_printers[] = {
  529. [AF_UNIX] = { print_sockaddr_data_un, SIZEOF_SA_FAMILY + 1 },
  530. [AF_INET] = { print_sockaddr_data_in, sizeof(struct sockaddr_in) },
  531. [AF_AX25] = { print_sockaddr_data_ax25, sizeof(struct sockaddr_ax25) },
  532. [AF_IPX] = { print_sockaddr_data_ipx, sizeof(struct sockaddr_ipx) },
  533. [AF_X25] = { print_sockaddr_data_x25, sizeof(struct sockaddr_x25) },
  534. [AF_INET6] = { print_sockaddr_data_in6, SIN6_MIN_LEN },
  535. [AF_NETLINK] = { print_sockaddr_data_nl, SIZEOF_SA_FAMILY + 1 },
  536. [AF_PACKET] = { print_sockaddr_data_ll, sizeof(struct sockaddr_ll) },
  537. [AF_BLUETOOTH] = { print_sockaddr_data_bt, SIZEOF_SA_FAMILY + 1 },
  538. };
  539. void
  540. print_sockaddr(const void *const buf, const int addrlen)
  541. {
  542. const struct sockaddr *const sa = buf;
  543. tprints("{sa_family=");
  544. printxval_index(addrfams, sa->sa_family, "AF_???");
  545. if (addrlen > (int) SIZEOF_SA_FAMILY) {
  546. tprints(", ");
  547. if (sa->sa_family < ARRAY_SIZE(sa_printers)
  548. && sa_printers[sa->sa_family].printer
  549. && addrlen >= sa_printers[sa->sa_family].min_len) {
  550. sa_printers[sa->sa_family].printer(buf, addrlen);
  551. } else {
  552. print_sockaddr_data_raw(buf, addrlen);
  553. }
  554. }
  555. tprints("}");
  556. }
  557. int
  558. decode_sockaddr(struct tcb *const tcp, const kernel_ulong_t addr, int addrlen)
  559. {
  560. if (addrlen < 2) {
  561. printaddr(addr);
  562. return -1;
  563. }
  564. union {
  565. struct sockaddr sa;
  566. struct sockaddr_storage storage;
  567. char pad[sizeof(struct sockaddr_storage) + 1];
  568. } addrbuf;
  569. if ((unsigned) addrlen > sizeof(addrbuf.storage))
  570. addrlen = sizeof(addrbuf.storage);
  571. if (umoven_or_printaddr(tcp, addr, addrlen, addrbuf.pad))
  572. return -1;
  573. memset(&addrbuf.pad[addrlen], 0, sizeof(addrbuf.pad) - addrlen);
  574. print_sockaddr(&addrbuf, addrlen);
  575. return addrbuf.sa.sa_family;
  576. }