1 /* $NetBSD: unix_listen.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* unix_listen 3 6 /* SUMMARY 7 /* start UNIX-domain listener 8 /* SYNOPSIS 9 /* #include <listen.h> 10 /* 11 /* int unix_listen(addr, backlog, block_mode) 12 /* const char *addr; 13 /* int backlog; 14 /* int block_mode; 15 /* 16 /* int unix_accept(fd) 17 /* int fd; 18 /* DESCRIPTION 19 /* The \fBunix_listen\fR() routine starts a listener in the UNIX domain 20 /* on the specified address, with the specified backlog, and returns 21 /* the resulting file descriptor. 22 /* 23 /* unix_accept() accepts a connection and sanitizes error results. 24 /* 25 /* Arguments: 26 /* .IP addr 27 /* Null-terminated string with connection destination. 28 /* .IP backlog 29 /* This argument is passed on to the \fIlisten(2)\fR routine. 30 /* .IP block_mode 31 /* Either NON_BLOCKING for a non-blocking socket, or BLOCKING for 32 /* blocking mode. 33 /* .IP fd 34 /* File descriptor returned by unix_listen(). 35 /* DIAGNOSTICS 36 /* Fatal errors: unix_listen() aborts upon any system call failure. 37 /* unix_accept() leaves all error handling up to the caller. 38 /* LICENSE 39 /* .ad 40 /* .fi 41 /* The Secure Mailer license must be distributed with this software. 42 /* AUTHOR(S) 43 /* Wietse Venema 44 /* IBM T.J. Watson Research 45 /* P.O. Box 704 46 /* Yorktown Heights, NY 10598, USA 47 /*--*/ 48 49 /* System interfaces. */ 50 51 #include <sys_defs.h> 52 #include <sys/socket.h> 53 #include <sys/un.h> 54 #include <string.h> 55 #include <unistd.h> 56 #include <sys/stat.h> 57 #include <errno.h> 58 59 /* Utility library. */ 60 61 #include "msg.h" 62 #include "iostuff.h" 63 #include "listen.h" 64 #include "sane_accept.h" 65 66 /* unix_listen - create UNIX-domain listener */ 67 68 int unix_listen(const char *addr, int backlog, int block_mode) 69 { 70 #undef sun 71 struct sockaddr_un sun; 72 ssize_t len = strlen(addr); 73 int sock; 74 75 /* 76 * Translate address information to internal form. 77 */ 78 if (len >= sizeof(sun.sun_path)) 79 msg_fatal("unix-domain name too long: %s", addr); 80 memset((void *) &sun, 0, sizeof(sun)); 81 sun.sun_family = AF_UNIX; 82 #ifdef HAS_SUN_LEN 83 sun.sun_len = len + 1; 84 #endif 85 memcpy(sun.sun_path, addr, len + 1); 86 87 /* 88 * Create a listener socket. Do whatever we can so we don't run into 89 * trouble when this process is restarted after crash. 90 */ 91 if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 92 msg_fatal("socket: %m"); 93 if (unlink(addr) < 0 && errno != ENOENT) 94 msg_fatal("remove %s: %m", addr); 95 if (bind(sock, (struct sockaddr *) &sun, sizeof(sun)) < 0) 96 msg_fatal("bind: %s: %m", addr); 97 #ifdef FCHMOD_UNIX_SOCKETS 98 if (fchmod(sock, 0666) < 0) 99 msg_fatal("fchmod socket %s: %m", addr); 100 #else 101 if (chmod(addr, 0666) < 0) 102 msg_fatal("chmod socket %s: %m", addr); 103 #endif 104 non_blocking(sock, block_mode); 105 if (listen(sock, backlog) < 0) 106 msg_fatal("listen: %m"); 107 return (sock); 108 } 109 110 /* unix_accept - accept connection */ 111 112 int unix_accept(int fd) 113 { 114 return (sane_accept(fd, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0)); 115 } 116