• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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