1 /* $OpenBSD: dup2_accept.c,v 1.3 2018/07/10 08:08:00 mpi Exp $ */ 2 /* 3 * Copyright (c) 2018 Martin Pieuchot 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/socket.h> 19 #include <netinet/in.h> 20 21 #include <assert.h> 22 #include <err.h> 23 #include <errno.h> 24 #include <pthread.h> 25 #include <string.h> 26 #include <unistd.h> 27 28 #include <stdlib.h> 29 30 /* 31 * Listen on localhost:TEST_PORT for a connection 32 */ 33 #define TEST_PORT 9876 34 35 static void * 36 dupper(void *arg) 37 { 38 struct sockaddr_in addr; 39 int s; 40 41 sleep(1); 42 43 s = socket(PF_INET, SOCK_STREAM, 0); 44 if (s == -1) 45 err(1, "socket"); 46 47 assert(s == 5); 48 49 /* 50 * Make sure that dup'ing a LARVAL file fails with EBUSY. 51 * 52 * Otherwise abort the program before calling connect(2), 53 * this was previously panic'ing the kernel. 54 */ 55 if ((dup2(0, 4) != 4) && (errno != EBUSY)) 56 err(1, "dup2"); 57 58 addr.sin_family = AF_INET; 59 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 60 addr.sin_port = htons(TEST_PORT); 61 62 if (connect(5, (struct sockaddr *)&addr, sizeof(addr)) == -1) 63 err(1, "connect"); 64 65 return NULL; 66 } 67 68 int 69 main(void) 70 { 71 struct sockaddr_in serv_addr; 72 struct sockaddr client_addr; 73 int error, s, len, fd; 74 pthread_t tr; 75 76 if ((error = pthread_create(&tr, NULL, dupper, NULL))) 77 errc(1, error, "pthread_create"); 78 79 s = socket(PF_INET, SOCK_STREAM, 0); 80 if (s == -1) 81 err(1, "socket"); 82 83 assert(s == 3); 84 85 memset(&serv_addr, 0, sizeof(serv_addr)); 86 serv_addr.sin_family = AF_INET; 87 serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 88 serv_addr.sin_port = htons(TEST_PORT); 89 90 if (bind(s, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) 91 err(1, "bind"); 92 93 if (listen(s, 3)) 94 err(1, "listen"); 95 96 len = sizeof(client_addr); 97 fd = accept(s, &client_addr, &len); 98 99 return 0; 100 } 101