1 /* 2 * Tests for util/qemu-sockets.c 3 * 4 * Copyright 2018 Red Hat, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this library; if not, see <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21 #include "qemu/osdep.h" 22 #include "qemu-common.h" 23 #include "qemu/sockets.h" 24 #include "qapi/error.h" 25 #include "socket-helpers.h" 26 #include "monitor/monitor.h" 27 28 static void test_fd_is_socket_bad(void) 29 { 30 char *tmp = g_strdup("qemu-test-util-sockets-XXXXXX"); 31 int fd = mkstemp(tmp); 32 if (fd != 0) { 33 unlink(tmp); 34 } 35 g_free(tmp); 36 37 g_assert(fd >= 0); 38 39 g_assert(!fd_is_socket(fd)); 40 close(fd); 41 } 42 43 static void test_fd_is_socket_good(void) 44 { 45 int fd = qemu_socket(PF_INET, SOCK_STREAM, 0); 46 47 g_assert(fd >= 0); 48 49 g_assert(fd_is_socket(fd)); 50 close(fd); 51 } 52 53 static int mon_fd = -1; 54 static const char *mon_fdname; 55 56 int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp) 57 { 58 g_assert(cur_mon); 59 g_assert(mon == cur_mon); 60 if (mon_fd == -1 || !g_str_equal(mon_fdname, fdname)) { 61 error_setg(errp, "No fd named %s", fdname); 62 return -1; 63 } 64 return dup(mon_fd); 65 } 66 67 /* Syms in libqemustub.a are discarded at .o file granularity. 68 * To replace monitor_get_fd() we must ensure everything in 69 * stubs/monitor.c is defined, to make sure monitor.o is discarded 70 * otherwise we get duplicate syms at link time. 71 */ 72 __thread Monitor *cur_mon; 73 int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); } 74 void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp) {} 75 void monitor_init_hmp(Chardev *chr, bool use_readline) {} 76 77 78 static void test_socket_fd_pass_name_good(void) 79 { 80 SocketAddress addr; 81 int fd; 82 83 cur_mon = g_malloc(1); /* Fake a monitor */ 84 mon_fdname = "myfd"; 85 mon_fd = qemu_socket(AF_INET, SOCK_STREAM, 0); 86 g_assert_cmpint(mon_fd, >, STDERR_FILENO); 87 88 addr.type = SOCKET_ADDRESS_TYPE_FD; 89 addr.u.fd.str = g_strdup(mon_fdname); 90 91 fd = socket_connect(&addr, &error_abort); 92 g_assert_cmpint(fd, !=, -1); 93 g_assert_cmpint(fd, !=, mon_fd); 94 close(fd); 95 96 fd = socket_listen(&addr, 1, &error_abort); 97 g_assert_cmpint(fd, !=, -1); 98 g_assert_cmpint(fd, !=, mon_fd); 99 close(fd); 100 101 g_free(addr.u.fd.str); 102 mon_fdname = NULL; 103 close(mon_fd); 104 mon_fd = -1; 105 g_free(cur_mon); 106 cur_mon = NULL; 107 } 108 109 static void test_socket_fd_pass_name_bad(void) 110 { 111 SocketAddress addr; 112 Error *err = NULL; 113 int fd; 114 115 cur_mon = g_malloc(1); /* Fake a monitor */ 116 mon_fdname = "myfd"; 117 mon_fd = dup(STDOUT_FILENO); 118 g_assert_cmpint(mon_fd, >, STDERR_FILENO); 119 120 addr.type = SOCKET_ADDRESS_TYPE_FD; 121 addr.u.fd.str = g_strdup(mon_fdname); 122 123 fd = socket_connect(&addr, &err); 124 g_assert_cmpint(fd, ==, -1); 125 error_free_or_abort(&err); 126 127 fd = socket_listen(&addr, 1, &err); 128 g_assert_cmpint(fd, ==, -1); 129 error_free_or_abort(&err); 130 131 g_free(addr.u.fd.str); 132 mon_fdname = NULL; 133 close(mon_fd); 134 mon_fd = -1; 135 g_free(cur_mon); 136 cur_mon = NULL; 137 } 138 139 static void test_socket_fd_pass_name_nomon(void) 140 { 141 SocketAddress addr; 142 Error *err = NULL; 143 int fd; 144 145 g_assert(cur_mon == NULL); 146 147 addr.type = SOCKET_ADDRESS_TYPE_FD; 148 addr.u.fd.str = g_strdup("myfd"); 149 150 fd = socket_connect(&addr, &err); 151 g_assert_cmpint(fd, ==, -1); 152 error_free_or_abort(&err); 153 154 fd = socket_listen(&addr, 1, &err); 155 g_assert_cmpint(fd, ==, -1); 156 error_free_or_abort(&err); 157 158 g_free(addr.u.fd.str); 159 } 160 161 162 static void test_socket_fd_pass_num_good(void) 163 { 164 SocketAddress addr; 165 int fd, sfd; 166 167 g_assert(cur_mon == NULL); 168 sfd = qemu_socket(AF_INET, SOCK_STREAM, 0); 169 g_assert_cmpint(sfd, >, STDERR_FILENO); 170 171 addr.type = SOCKET_ADDRESS_TYPE_FD; 172 addr.u.fd.str = g_strdup_printf("%d", sfd); 173 174 fd = socket_connect(&addr, &error_abort); 175 g_assert_cmpint(fd, ==, sfd); 176 177 fd = socket_listen(&addr, 1, &error_abort); 178 g_assert_cmpint(fd, ==, sfd); 179 180 g_free(addr.u.fd.str); 181 close(sfd); 182 } 183 184 static void test_socket_fd_pass_num_bad(void) 185 { 186 SocketAddress addr; 187 Error *err = NULL; 188 int fd, sfd; 189 190 g_assert(cur_mon == NULL); 191 sfd = dup(STDOUT_FILENO); 192 193 addr.type = SOCKET_ADDRESS_TYPE_FD; 194 addr.u.fd.str = g_strdup_printf("%d", sfd); 195 196 fd = socket_connect(&addr, &err); 197 g_assert_cmpint(fd, ==, -1); 198 error_free_or_abort(&err); 199 200 fd = socket_listen(&addr, 1, &err); 201 g_assert_cmpint(fd, ==, -1); 202 error_free_or_abort(&err); 203 204 g_free(addr.u.fd.str); 205 close(sfd); 206 } 207 208 static void test_socket_fd_pass_num_nocli(void) 209 { 210 SocketAddress addr; 211 Error *err = NULL; 212 int fd; 213 214 cur_mon = g_malloc(1); /* Fake a monitor */ 215 216 addr.type = SOCKET_ADDRESS_TYPE_FD; 217 addr.u.fd.str = g_strdup_printf("%d", STDOUT_FILENO); 218 219 fd = socket_connect(&addr, &err); 220 g_assert_cmpint(fd, ==, -1); 221 error_free_or_abort(&err); 222 223 fd = socket_listen(&addr, 1, &err); 224 g_assert_cmpint(fd, ==, -1); 225 error_free_or_abort(&err); 226 227 g_free(addr.u.fd.str); 228 } 229 230 231 int main(int argc, char **argv) 232 { 233 bool has_ipv4, has_ipv6; 234 235 socket_init(); 236 237 g_test_init(&argc, &argv, NULL); 238 239 /* We're creating actual IPv4/6 sockets, so we should 240 * check if the host running tests actually supports 241 * each protocol to avoid breaking tests on machines 242 * with either IPv4 or IPv6 disabled. 243 */ 244 if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) { 245 g_printerr("socket_check_protocol_support() failed\n"); 246 goto end; 247 } 248 249 if (has_ipv4) { 250 g_test_add_func("/util/socket/is-socket/bad", 251 test_fd_is_socket_bad); 252 g_test_add_func("/util/socket/is-socket/good", 253 test_fd_is_socket_good); 254 g_test_add_func("/socket/fd-pass/name/good", 255 test_socket_fd_pass_name_good); 256 g_test_add_func("/socket/fd-pass/name/bad", 257 test_socket_fd_pass_name_bad); 258 g_test_add_func("/socket/fd-pass/name/nomon", 259 test_socket_fd_pass_name_nomon); 260 g_test_add_func("/socket/fd-pass/num/good", 261 test_socket_fd_pass_num_good); 262 g_test_add_func("/socket/fd-pass/num/bad", 263 test_socket_fd_pass_num_bad); 264 g_test_add_func("/socket/fd-pass/num/nocli", 265 test_socket_fd_pass_num_nocli); 266 } 267 268 end: 269 return g_test_run(); 270 } 271