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