1 | /* Tests for socket address type definitions. |
2 | Copyright (C) 2016-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public License as |
7 | published by the Free Software Foundation; either version 2.1 of the |
8 | License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; see the file COPYING.LIB. If |
17 | not, see <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <netinet/in.h> |
20 | #include <stdbool.h> |
21 | #include <stddef.h> |
22 | #include <stdio.h> |
23 | #include <stdlib.h> |
24 | #include <string.h> |
25 | #include <sys/socket.h> |
26 | #include <sys/un.h> |
27 | |
28 | /* This is a copy of the previous definition of struct |
29 | sockaddr_storage. It is not equal to the old value of _SS_SIZE |
30 | (128) on all architectures. We must stay compatible with the old |
31 | definition. */ |
32 | |
33 | #define OLD_REFERENCE_SIZE 128 |
34 | #define OLD_PADSIZE (OLD_REFERENCE_SIZE - (2 * sizeof (__ss_aligntype))) |
35 | struct sockaddr_storage_old |
36 | { |
37 | __SOCKADDR_COMMON (old_); |
38 | __ss_aligntype old_align; |
39 | char old_padding[OLD_PADSIZE]; |
40 | }; |
41 | |
42 | static bool errors; |
43 | |
44 | static void |
45 | check (bool ok, const char *message) |
46 | { |
47 | if (!ok) |
48 | { |
49 | printf (format: "error: failed check: %s\n" , message); |
50 | errors = true; |
51 | } |
52 | } |
53 | |
54 | static int |
55 | do_test (void) |
56 | { |
57 | check (OLD_REFERENCE_SIZE >= _SS_SIZE, |
58 | message: "old target size is not smaller than actual size" ); |
59 | check (ok: sizeof (struct sockaddr_storage_old) |
60 | == sizeof (struct sockaddr_storage), |
61 | message: "old and new sizes match" ); |
62 | check (ok: __alignof (struct sockaddr_storage_old) |
63 | == __alignof (struct sockaddr_storage), |
64 | message: "old and new alignment matches" ); |
65 | check (offsetof (struct sockaddr_storage_old, old_family) |
66 | == offsetof (struct sockaddr_storage, ss_family), |
67 | message: "old and new family offsets match" ); |
68 | check (ok: sizeof (struct sockaddr_storage) == _SS_SIZE, |
69 | message: "struct sockaddr_storage size" ); |
70 | |
71 | /* Check for lack of holes in the struct definition. */ |
72 | check (offsetof (struct sockaddr_storage, __ss_padding) |
73 | == __SOCKADDR_COMMON_SIZE, |
74 | message: "implicit padding before explicit padding" ); |
75 | check (offsetof (struct sockaddr_storage, __ss_align) |
76 | == __SOCKADDR_COMMON_SIZE |
77 | + sizeof (((struct sockaddr_storage) {}).__ss_padding), |
78 | message: "implicit padding before explicit padding" ); |
79 | |
80 | /* Check for POSIX compatibility requirements between struct |
81 | sockaddr_storage and struct sockaddr_un. */ |
82 | check (ok: sizeof (struct sockaddr_storage) >= sizeof (struct sockaddr_un), |
83 | message: "sockaddr_storage is at least as large as sockaddr_un" ); |
84 | check (ok: __alignof (struct sockaddr_storage) |
85 | >= __alignof (struct sockaddr_un), |
86 | message: "sockaddr_storage is at least as aligned as sockaddr_un" ); |
87 | check (offsetof (struct sockaddr_storage, ss_family) |
88 | == offsetof (struct sockaddr_un, sun_family), |
89 | message: "family offsets match" ); |
90 | |
91 | /* Check that the compiler preserves bit patterns in aggregate |
92 | copies. Based on <https://gcc.gnu.org/PR71120>. */ |
93 | check (ok: sizeof (struct sockaddr_storage) >= sizeof (struct sockaddr_in), |
94 | message: "sockaddr_storage is at least as large as sockaddr_in" ); |
95 | { |
96 | struct sockaddr_storage addr; |
97 | memset (&addr, 0, sizeof (addr)); |
98 | { |
99 | struct sockaddr_in *sinp = (struct sockaddr_in *)&addr; |
100 | sinp->sin_family = AF_INET; |
101 | sinp->sin_addr.s_addr = htonl (INADDR_LOOPBACK); |
102 | sinp->sin_port = htons (80); |
103 | } |
104 | struct sockaddr_storage copy; |
105 | copy = addr; |
106 | |
107 | struct sockaddr_storage *p = malloc (size: sizeof (*p)); |
108 | if (p == NULL) |
109 | { |
110 | printf (format: "error: malloc: %m\n" ); |
111 | return 1; |
112 | } |
113 | *p = copy; |
114 | const struct sockaddr_in *sinp = (const struct sockaddr_in *)p; |
115 | check (ok: sinp->sin_family == AF_INET, message: "sin_family" ); |
116 | check (ok: sinp->sin_addr.s_addr == htonl (INADDR_LOOPBACK), message: "sin_addr" ); |
117 | check (ok: sinp->sin_port == htons (80), message: "sin_port" ); |
118 | free (ptr: p); |
119 | } |
120 | |
121 | return errors; |
122 | } |
123 | |
124 | #define TEST_FUNCTION do_test () |
125 | #include "../test-skeleton.c" |
126 | |