Home | History | Annotate | Download | only in tests
      1 /*
      2  * Check decoding of sockaddr structures
      3  *
      4  * Copyright (c) 2016 Dmitry V. Levin <ldv (at) altlinux.org>
      5  * Copyright (c) 2016-2017 The strace developers.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "tests.h"
     32 #include <stddef.h>
     33 #include <stdio.h>
     34 #include <string.h>
     35 #include <unistd.h>
     36 #include <sys/socket.h>
     37 #include <sys/un.h>
     38 #include <arpa/inet.h>
     39 #include <netinet/in.h>
     40 #include "netlink.h"
     41 #include <linux/if_arp.h>
     42 #include <linux/if_ether.h>
     43 #include <linux/if_packet.h>
     44 #include <linux/ipx.h>
     45 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
     46 # include <bluetooth/bluetooth.h>
     47 # include <bluetooth/hci.h>
     48 # include <bluetooth/l2cap.h>
     49 # include <bluetooth/rfcomm.h>
     50 # include <bluetooth/sco.h>
     51 #endif
     52 
     53 static void
     54 check_un(void)
     55 {
     56 	TAIL_ALLOC_OBJECT_VAR_PTR(struct sockaddr_un, un);
     57 	un->sun_family = AF_UNIX;
     58 	memset(un->sun_path, '0', sizeof(un->sun_path));
     59 	unsigned int len = sizeof(*un);
     60 	int ret = connect(-1, (void *) un, len);
     61 	printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}"
     62 	       ", %u) = %d EBADF (%m)\n",
     63 	       (int) sizeof(un->sun_path), 0, len, ret);
     64 
     65 	un->sun_path[1] = 0;
     66 	ret = connect(-1, (void *) un, len);
     67 	printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%u\"}, %u)"
     68 	       " = %d EBADF (%m)\n", 0, len, ret);
     69 
     70 	un->sun_path[0] = 0;
     71 	un->sun_path[2] = 1;
     72 	ret = connect(-1, (void *) un, len);
     73 	printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"\\0\\001%.*u\"}"
     74 	       ", %u) = %d EBADF (%m)\n",
     75 	       (int) sizeof(un->sun_path) - 3, 0, len, ret);
     76 
     77 	un = ((void *) un) - 2;
     78 	un->sun_family = AF_UNIX;
     79 	memset(un->sun_path, '0', sizeof(un->sun_path));
     80 	len = sizeof(*un) + 2;
     81 	ret = connect(-1, (void *) un, len);
     82 	printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}"
     83 	       ", %u) = %d EBADF (%m)\n",
     84 	       (int) sizeof(un->sun_path), 0, len, ret);
     85 
     86 	un->sun_path[0] = 0;
     87 	ret = connect(-1, (void *) un, len);
     88 	printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}"
     89 	       ", %u) = %d EBADF (%m)\n",
     90 	       (int) sizeof(un->sun_path) - 1, 0, len, ret);
     91 
     92 	un = ((void *) un) + 4;
     93 	un->sun_family = AF_UNIX;
     94 	len = sizeof(*un) - 2;
     95 	ret = connect(-1, (void *) un, len);
     96 	printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}"
     97 	       ", %u) = %d EBADF (%m)\n",
     98 	       (int) sizeof(un->sun_path) - 2, 0, len, ret);
     99 
    100 	un->sun_path[0] = 0;
    101 	ret = connect(-1, (void *) un, len);
    102 	printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}"
    103 	       ", %u) = %d EBADF (%m)\n",
    104 	       (int) sizeof(un->sun_path) - 3, 0, len, ret);
    105 
    106 	len = sizeof(*un);
    107 	ret = connect(-1, (void *) un, len);
    108 	printf("connect(-1, %p, %u) = %d EBADF (%m)\n", un, len, ret);
    109 
    110 	un = tail_alloc(sizeof(struct sockaddr_storage));
    111 	un->sun_family = AF_UNIX;
    112 	memset(un->sun_path, '0', sizeof(un->sun_path));
    113 	len = sizeof(struct sockaddr_storage) + 1;
    114 	ret = connect(-1, (void *) un, len);
    115 	printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}"
    116 	       ", %u) = %d EBADF (%m)\n",
    117 	       (int) sizeof(un->sun_path), 0, len, ret);
    118 
    119 	un->sun_path[0] = 0;
    120 	ret = connect(-1, (void *) un, len);
    121 	printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}"
    122 	       ", %u) = %d EBADF (%m)\n",
    123 	       (int) sizeof(un->sun_path) - 1, 0, len, ret);
    124 }
    125 
    126 static void
    127 check_in(void)
    128 {
    129 	const unsigned short h_port = 12345;
    130 	static const char h_addr[] = "12.34.56.78";
    131 
    132 	TAIL_ALLOC_OBJECT_VAR_PTR(struct sockaddr_in, in);
    133 	in->sin_family = AF_INET;
    134 	in->sin_port = htons(h_port);
    135 	in->sin_addr.s_addr = inet_addr(h_addr);
    136 	unsigned int len = sizeof(*in);
    137 	int ret = connect(-1, (void *) in, len);
    138 	printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)"
    139 	       ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n",
    140 	       h_port, h_addr, len, ret);
    141 
    142 	in = ((void *) in) - 4;
    143 	in->sin_family = AF_INET;
    144 	in->sin_port = htons(h_port);
    145 	in->sin_addr.s_addr = inet_addr(h_addr);
    146 	len = sizeof(*in) + 4;
    147 	ret = connect(-1, (void *) in, len);
    148 	printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)"
    149 	       ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n",
    150 	       h_port, h_addr, len, ret);
    151 
    152 	in = ((void *) in) + 8;
    153 	in->sin_family = AF_INET;
    154 	in->sin_port = 0;
    155 	in->sin_addr.s_addr = 0;
    156 	len = sizeof(*in) - 4;
    157 	ret = connect(-1, (void *) in, len);
    158 	printf("connect(-1, {sa_family=AF_INET, sa_data=\"%s\"}, %u)"
    159 	       " = %d EBADF (%m)\n",
    160 	       "\\0\\0\\0\\0\\0\\0\\377\\377\\377\\377",
    161 	       len, ret);
    162 
    163 	len = sizeof(*in);
    164 	ret = connect(-1, (void *) in, len);
    165 	printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in, len, ret);
    166 }
    167 
    168 static void
    169 check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr)
    170 {
    171 	inet_pton(AF_INET6, h_addr, &in6->sin6_addr);
    172 
    173 	in6->sin6_scope_id = 0xfacefeed;
    174 	unsigned int len = sizeof(*in6);
    175 	int ret = connect(-1, (void *) in6, len);
    176 	printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)"
    177 	       ", inet_pton(AF_INET6, \"%s\", &sin6_addr)"
    178 	       ", sin6_flowinfo=htonl(%u)"
    179 	       ", sin6_scope_id=%u}, %u)"
    180 	       " = %d EBADF (%m)\n",
    181 	       ntohs(in6->sin6_port), h_addr,
    182 	       ntohl(in6->sin6_flowinfo), in6->sin6_scope_id, len, ret);
    183 
    184 	in6->sin6_scope_id = ifindex_lo();
    185 	if (in6->sin6_scope_id) {
    186 		ret = connect(-1, (void *) in6, len);
    187 		printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)"
    188 		       ", inet_pton(AF_INET6, \"%s\", &sin6_addr)"
    189 		       ", sin6_flowinfo=htonl(%u)"
    190 		       ", sin6_scope_id=%s}, %u)"
    191 		       " = %d EBADF (%m)\n",
    192 		       ntohs(in6->sin6_port), h_addr, ntohl(in6->sin6_flowinfo),
    193 		       IFINDEX_LO_STR, len, ret);
    194 	}
    195 }
    196 
    197 static void
    198 check_in6(void)
    199 {
    200 	const unsigned short h_port = 12345;
    201 	const unsigned int h_flowinfo = 1234567890;
    202 	static const char h_addr[] = "12:34:56:78:90:ab:cd:ef";
    203 
    204 	TAIL_ALLOC_OBJECT_VAR_PTR(struct sockaddr_in6, in6);
    205 	in6->sin6_family = AF_INET6;
    206 	in6->sin6_port = htons(h_port);
    207 	in6->sin6_flowinfo = htonl(h_flowinfo);
    208 	inet_pton(AF_INET6, h_addr, &in6->sin6_addr);
    209 	in6->sin6_scope_id = 0xfacefeed;
    210 	unsigned int len = sizeof(*in6);
    211 	int ret = connect(-1, (void *) in6, len);
    212 	printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)"
    213 	       ", inet_pton(AF_INET6, \"%s\", &sin6_addr)"
    214 	       ", sin6_flowinfo=htonl(%u), sin6_scope_id=%u}, %u)"
    215 	       " = %d EBADF (%m)\n",
    216 	       h_port, h_addr, h_flowinfo, in6->sin6_scope_id, len, ret);
    217 
    218 	check_in6_linklocal(in6, "fe80::");
    219 	check_in6_linklocal(in6, "ff42::");
    220 
    221 	in6 = ((void *) in6) - 4;
    222 	in6->sin6_family = AF_INET6;
    223 	in6->sin6_port = htons(h_port);
    224 	in6->sin6_flowinfo = htonl(h_flowinfo);
    225 	inet_pton(AF_INET6, h_addr, &in6->sin6_addr);
    226 	in6->sin6_scope_id = 0xfacefeed;
    227 	len = sizeof(*in6) + 4;
    228 	ret = connect(-1, (void *) in6, len);
    229 	printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)"
    230 	       ", inet_pton(AF_INET6, \"%s\", &sin6_addr)"
    231 	       ", sin6_flowinfo=htonl(%u), sin6_scope_id=%u}, %u)"
    232 	       " = %d EBADF (%m)\n",
    233 	       h_port, h_addr, h_flowinfo, in6->sin6_scope_id, len, ret);
    234 
    235 	in6 = ((void *) in6) + 4 + sizeof(in6->sin6_scope_id);
    236 	in6->sin6_family = AF_INET6;
    237 	in6->sin6_port = htons(h_port);
    238 	in6->sin6_flowinfo = htonl(h_flowinfo);
    239 	inet_pton(AF_INET6, h_addr, &in6->sin6_addr);
    240 	len = sizeof(*in6) - sizeof(in6->sin6_scope_id);
    241 	ret = connect(-1, (void *) in6, len);
    242 	printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)"
    243 	       ", inet_pton(AF_INET6, \"%s\", &sin6_addr)"
    244 	       ", sin6_flowinfo=htonl(%u)}, %u)"
    245 	       " = %d EBADF (%m)\n",
    246 	       h_port, h_addr, h_flowinfo, len, ret);
    247 
    248 	in6 = ((void *) in6) + 4;
    249 	in6->sin6_family = AF_INET6;
    250 	in6->sin6_port = 0;
    251 	in6->sin6_flowinfo = 0;
    252 	memset(&in6->sin6_addr, '0', sizeof(in6->sin6_addr) - 4);
    253 	len = sizeof(*in6) - sizeof(in6->sin6_scope_id) - 4;
    254 	ret = connect(-1, (void *) in6, len);
    255 	printf("connect(-1, {sa_family=AF_INET6"
    256 	       ", sa_data=\"\\0\\0\\0\\0\\0\\000%.*u\"}, %u)"
    257 	       " = %d EBADF (%m)\n",
    258 	       (int) (len - offsetof(struct sockaddr_in6, sin6_addr)), 0,
    259 	       len, ret);
    260 
    261 	len = sizeof(*in6) - sizeof(in6->sin6_scope_id);
    262 	ret = connect(-1, (void *) in6, len);
    263 	printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in6, len, ret);
    264 }
    265 
    266 static void
    267 check_ipx(void)
    268 {
    269 	const unsigned short h_port = 12345;
    270 	const unsigned int h_network = 0xfacefeed;
    271 	struct sockaddr_ipx c_ipx = {
    272 		.sipx_family = AF_IPX,
    273 		.sipx_port = htons(h_port),
    274 		.sipx_network = htonl(h_network),
    275 		.sipx_node = "ABCDEF",
    276 		.sipx_type = -1
    277 	};
    278 	void *ipx = tail_memdup(&c_ipx, sizeof(c_ipx));
    279 	unsigned int len = sizeof(c_ipx);
    280 	int ret = connect(-1, ipx, len);
    281 	printf("connect(-1, {sa_family=AF_IPX, sipx_port=htons(%u)"
    282 	       ", sipx_network=htonl(%#x)"
    283 	       ", sipx_node=[%#02x, %#02x, %#02x, %#02x, %#02x, %#02x]"
    284 	       ", sipx_type=%#02x}, %u) = %d EBADF (%m)\n",
    285 	       h_port, h_network,
    286 	       c_ipx.sipx_node[0], c_ipx.sipx_node[1],
    287 	       c_ipx.sipx_node[2], c_ipx.sipx_node[3],
    288 	       c_ipx.sipx_node[4], c_ipx.sipx_node[5],
    289 	       c_ipx.sipx_type, len, ret);
    290 }
    291 
    292 static void
    293 check_nl(void)
    294 {
    295 	TAIL_ALLOC_OBJECT_VAR_PTR(struct sockaddr_nl, nl);
    296 	nl->nl_family = AF_NETLINK;
    297 	nl->nl_pid = 1234567890;
    298 	nl->nl_groups = 0xfacefeed;
    299 	unsigned int len = sizeof(*nl);
    300 	int ret = connect(-1, (void *) nl, len);
    301 	printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d"
    302 	       ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n",
    303 	       nl->nl_pid, nl->nl_groups, len, ret);
    304 
    305 	nl = ((void *) nl) - 4;
    306 	nl->nl_family = AF_NETLINK;
    307 	nl->nl_pid = 1234567890;
    308 	nl->nl_groups = 0xfacefeed;
    309 	len = sizeof(*nl) + 4;
    310 	ret = connect(-1, (void *) nl, len);
    311 	printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d"
    312 	       ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n",
    313 	       nl->nl_pid, nl->nl_groups, len, ret);
    314 }
    315 
    316 static void
    317 check_ll(void)
    318 {
    319 	struct sockaddr_ll c_ll = {
    320 		.sll_family = AF_PACKET,
    321 		.sll_protocol = htons(ETH_P_ALL),
    322 		.sll_ifindex = 0xfacefeed,
    323 		.sll_hatype = ARPHRD_ETHER,
    324 		.sll_pkttype = PACKET_HOST,
    325 		.sll_halen = sizeof(c_ll.sll_addr),
    326 		.sll_addr = "abcdefgh"
    327 	};
    328 	void *ll = tail_memdup(&c_ll, sizeof(c_ll));
    329 	unsigned int len = sizeof(c_ll);
    330 	int ret = connect(-1, ll, len);
    331 	printf("connect(-1, {sa_family=AF_PACKET"
    332 	       ", sll_protocol=htons(ETH_P_ALL)"
    333 	       ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER"
    334 	       ", sll_pkttype=PACKET_HOST, sll_halen=%u, sll_addr="
    335 	       "[%#02x, %#02x, %#02x, %#02x, %#02x, %#02x, %#02x, %#02x]"
    336 	       "}, %u) = %d EBADF (%m)\n",
    337 	       c_ll.sll_ifindex, c_ll.sll_halen,
    338 	       c_ll.sll_addr[0], c_ll.sll_addr[1],
    339 	       c_ll.sll_addr[2], c_ll.sll_addr[3],
    340 	       c_ll.sll_addr[4], c_ll.sll_addr[5],
    341 	       c_ll.sll_addr[6], c_ll.sll_addr[7],
    342 	       len, ret);
    343 
    344 	((struct sockaddr_ll *) ll)->sll_halen++;
    345 	ret = connect(-1, ll, len);
    346 	printf("connect(-1, {sa_family=AF_PACKET"
    347 	       ", sll_protocol=htons(ETH_P_ALL)"
    348 	       ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER"
    349 	       ", sll_pkttype=PACKET_HOST, sll_halen=%u, sll_addr="
    350 	       "[%#02x, %#02x, %#02x, %#02x, %#02x, %#02x, %#02x, %#02x, ...]"
    351 	       "}, %u) = %d EBADF (%m)\n",
    352 	       c_ll.sll_ifindex, c_ll.sll_halen + 1,
    353 	       c_ll.sll_addr[0], c_ll.sll_addr[1],
    354 	       c_ll.sll_addr[2], c_ll.sll_addr[3],
    355 	       c_ll.sll_addr[4], c_ll.sll_addr[5],
    356 	       c_ll.sll_addr[6], c_ll.sll_addr[7],
    357 	       len, ret);
    358 
    359 	((struct sockaddr_ll *) ll)->sll_halen = 0;
    360 	ret = connect(-1, ll, len);
    361 	printf("connect(-1, {sa_family=AF_PACKET"
    362 	       ", sll_protocol=htons(ETH_P_ALL)"
    363 	       ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER"
    364 	       ", sll_pkttype=PACKET_HOST, sll_halen=0}, %u)"
    365 	       " = %d EBADF (%m)\n", c_ll.sll_ifindex, len, ret);
    366 
    367 	((struct sockaddr_ll *) ll)->sll_ifindex = ifindex_lo();
    368 	if (((struct sockaddr_ll *) ll)->sll_ifindex) {
    369 		ret = connect(-1, ll, len);
    370 		printf("connect(-1, {sa_family=AF_PACKET"
    371 		       ", sll_protocol=htons(ETH_P_ALL)"
    372 		       ", sll_ifindex=%s"
    373 		       ", sll_hatype=ARPHRD_ETHER"
    374 		       ", sll_pkttype=PACKET_HOST, sll_halen=0}, %u)"
    375 		       " = %d EBADF (%m)\n", IFINDEX_LO_STR, len, ret);
    376 	}
    377 }
    378 
    379 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
    380 static void
    381 check_hci(void)
    382 {
    383 	const unsigned short h_port = 12345;
    384 	TAIL_ALLOC_OBJECT_VAR_PTR(struct sockaddr_hci, hci);
    385 	hci->hci_family = AF_BLUETOOTH;
    386 	hci->hci_dev = htobs(h_port);
    387 	hci->hci_channel = HCI_CHANNEL_RAW;
    388 	unsigned int len = sizeof(*hci);
    389 	int ret = connect(-1, (void *) hci, len);
    390 	printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)"
    391 	       ", hci_channel=HCI_CHANNEL_RAW}, %u) = %d EBADF (%m)\n",
    392 	       h_port, len, ret);
    393 }
    394 
    395 static void
    396 check_sco(void)
    397 {
    398 	const struct sockaddr_sco c_sco = {
    399 		.sco_family = AF_BLUETOOTH,
    400 		.sco_bdaddr.b = "abcdef"
    401 	};
    402 	void *sco = tail_memdup(&c_sco, sizeof(c_sco));
    403 	unsigned int len = sizeof(c_sco);
    404 	int ret = connect(-1, sco, len);
    405 	printf("connect(-1, {sa_family=AF_BLUETOOTH"
    406 	       ", sco_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x"
    407 	       "}, %u) = %d EBADF (%m)\n",
    408 	       c_sco.sco_bdaddr.b[0], c_sco.sco_bdaddr.b[1],
    409 	       c_sco.sco_bdaddr.b[2], c_sco.sco_bdaddr.b[3],
    410 	       c_sco.sco_bdaddr.b[4], c_sco.sco_bdaddr.b[5],
    411 	       len, ret);
    412 }
    413 
    414 static void
    415 check_rc(void)
    416 {
    417 	const struct sockaddr_rc c_rc = {
    418 		.rc_family = AF_BLUETOOTH,
    419 		.rc_bdaddr.b = "abcdef",
    420 		.rc_channel = 42
    421 	};
    422 	void *rc = tail_memdup(&c_rc, sizeof(c_rc));
    423 	unsigned int len = sizeof(c_rc);
    424 	int ret = connect(-1, rc, len);
    425 	printf("connect(-1, {sa_family=AF_BLUETOOTH"
    426 	       ", rc_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x"
    427 	       ", rc_channel=%u}, %u) = %d EBADF (%m)\n",
    428 	       c_rc.rc_bdaddr.b[0], c_rc.rc_bdaddr.b[1],
    429 	       c_rc.rc_bdaddr.b[2], c_rc.rc_bdaddr.b[3],
    430 	       c_rc.rc_bdaddr.b[4], c_rc.rc_bdaddr.b[5],
    431 	       c_rc.rc_channel, len, ret);
    432 }
    433 
    434 static void
    435 check_l2(void)
    436 {
    437 	const unsigned short h_psm = 12345;
    438 	const unsigned short h_cid = 13579;
    439 	const struct sockaddr_l2 c_l2 = {
    440 		.l2_family = AF_BLUETOOTH,
    441 		.l2_psm = htobs(h_psm),
    442 		.l2_bdaddr.b = "abcdef",
    443 		.l2_cid = htobs(h_cid),
    444 		.l2_bdaddr_type = 42
    445 	};
    446 	void *l2 = tail_memdup(&c_l2, sizeof(c_l2));
    447 	unsigned int len = sizeof(c_l2);
    448 	int ret = connect(-1, l2, len);
    449 	printf("connect(-1, {sa_family=AF_BLUETOOTH"
    450 	       ", l2_psm=htobs(%hu)"
    451 	       ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x"
    452 	       ", l2_cid=htobs(%hu), l2_bdaddr_type=%u}"
    453 	       ", %u) = %d EBADF (%m)\n", h_psm,
    454 	       c_l2.l2_bdaddr.b[0], c_l2.l2_bdaddr.b[1],
    455 	       c_l2.l2_bdaddr.b[2], c_l2.l2_bdaddr.b[3],
    456 	       c_l2.l2_bdaddr.b[4], c_l2.l2_bdaddr.b[5],
    457 	       h_cid, c_l2.l2_bdaddr_type, len, ret);
    458 }
    459 #endif
    460 
    461 static void
    462 check_raw(void)
    463 {
    464 	union {
    465 		struct sockaddr *sa;
    466 		struct sockaddr_storage *st;
    467 	} u = { .st = tail_alloc(sizeof(*u.st)) };
    468 	memset(u.st, '0', sizeof(*u.st));
    469 	u.sa->sa_family = 0xff;
    470 	unsigned int len = sizeof(*u.st) + 8;
    471 	int ret = connect(-1, (void *) u.st, len);
    472 	printf("connect(-1, {sa_family=%#x /* AF_??? */, sa_data=\"%.*u\"}"
    473 	       ", %u) = %d EBADF (%m)\n", u.sa->sa_family,
    474 	       (int) (sizeof(*u.st) - sizeof(u.sa->sa_family)), 0, len, ret);
    475 
    476 	u.sa->sa_family = 0;
    477 	len = sizeof(u.sa->sa_family) + 1;
    478 	ret = connect(-1, (void *) u.st, len);
    479 	printf("connect(-1, {sa_family=AF_UNSPEC, sa_data=\"0\"}, %u)"
    480 	       " = %d EBADF (%m)\n", len, ret);
    481 
    482 	u.sa->sa_family = AF_BLUETOOTH;
    483 	++len;
    484 	ret = connect(-1, (void *) u.st, len);
    485 	printf("connect(-1, {sa_family=AF_BLUETOOTH, sa_data=\"00\"}, %u)"
    486 	       " = %d EBADF (%m)\n", len, ret);
    487 }
    488 
    489 int
    490 main(void)
    491 {
    492 	check_un();
    493 	check_in();
    494 	check_in6();
    495 	check_ipx();
    496 	check_nl();
    497 	check_ll();
    498 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
    499 	check_hci();
    500 	check_sco();
    501 	check_rc();
    502 	check_l2();
    503 #endif
    504 	check_raw();
    505 
    506 	puts("+++ exited with 0 +++");
    507 	return 0;
    508 }
    509