1/* 2 * Copyright (C) Joerg Lenneis 2003 3 * All Rights Reserved. See COPYING. 4 */ 5 6#ifdef HAVE_CONFIG_H 7#include "config.h" 8#endif /* HAVE_CONFIG_H */ 9 10 11#include <stdlib.h> 12#include <string.h> 13#include <errno.h> 14#ifdef HAVE_UNISTD_H 15#include <unistd.h> 16#endif /* HAVE_UNISTD_H */ 17#include <sys/un.h> 18#include <sys/socket.h> 19#include <netinet/in.h> 20#include <arpa/inet.h> 21#include <netdb.h> 22 23#ifdef HAVE_SYS_TYPES_H 24#include <sys/types.h> 25#endif /* HAVE_SYS_TYPES_H */ 26#ifdef HAVE_SYS_TIME_H 27#include <sys/time.h> 28#endif /* HAVE_SYS_TIME_H */ 29 30 31#include <atalk/logger.h> 32#include <atalk/compat.h> 33#include "usockfd.h" 34 35#include <sys/select.h> 36 37int usockfd_create(char *usock_fn, mode_t mode, int backlog) 38{ 39 int sockfd; 40 struct sockaddr_un addr; 41 42 43 if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { 44 LOG(log_error, logtype_cnid, "error in socket call: %s", 45 strerror(errno)); 46 return -1; 47 } 48 49 if (unlink(usock_fn) < 0 && errno != ENOENT) { 50 LOG(log_error, logtype_cnid, "error unlinking unix socket file %s: %s", 51 usock_fn, strerror(errno)); 52 return -1; 53 } 54 memset((char *) &addr, 0, sizeof(struct sockaddr_un)); 55 addr.sun_family = AF_UNIX; 56 strncpy(addr.sun_path, usock_fn, sizeof(addr.sun_path) - 1); 57 if (bind(sockfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) < 0) { 58 LOG(log_error, logtype_cnid, "error binding to socket for %s: %s", 59 usock_fn, strerror(errno)); 60 return -1; 61 } 62 63 if (listen(sockfd, backlog) < 0) { 64 LOG(log_error, logtype_cnid, "error in listen for %s: %s", 65 usock_fn, strerror(errno)); 66 return -1; 67 } 68 69#ifdef chmod 70#undef chmod 71#endif 72 if (chmod(usock_fn, mode) < 0) { 73 LOG(log_error, logtype_cnid, "error changing permissions for %s: %s", 74 usock_fn, strerror(errno)); 75 close(sockfd); 76 return -1; 77 } 78 79 return sockfd; 80} 81 82/* --------------- 83 * create a tcp socket 84 */ 85int tsockfd_create(char *host, char *port, int backlog) 86{ 87 int sockfd, flag, ret; 88 struct addrinfo hints, *servinfo, *p; 89 90 /* Prepare hint for getaddrinfo */ 91 memset(&hints, 0, sizeof hints); 92 hints.ai_family = AF_UNSPEC; 93 hints.ai_socktype = SOCK_STREAM; 94 95 if ((ret = getaddrinfo(host, port, &hints, &servinfo)) != 0) { 96 LOG(log_error, logtype_default, "tsockfd_create: getaddrinfo: %s\n", gai_strerror(ret)); 97 return 0; 98 } 99 100 /* create a socket */ 101 /* loop through all the results and bind to the first we can */ 102 for (p = servinfo; p != NULL; p = p->ai_next) { 103 if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { 104 LOG(log_info, logtype_default, "tsockfd_create: socket: %s", strerror(errno)); 105 continue; 106 } 107 108 /* 109 * Set some socket options: 110 * SO_REUSEADDR deals w/ quick close/opens 111 * TCP_NODELAY diables Nagle 112 */ 113#ifdef SO_REUSEADDR 114 flag = 1; 115 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); 116#endif 117 118#ifdef USE_TCP_NODELAY 119#ifndef SOL_TCP 120#define SOL_TCP IPPROTO_TCP 121#endif 122 flag = 1; 123 setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag)); 124#endif /* USE_TCP_NODELAY */ 125 126 if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { 127 close(sockfd); 128 LOG(log_info, logtype_default, "tsockfd_create: bind: %s\n", strerror(errno)); 129 continue; 130 } 131 132 if (listen(sockfd, backlog) < 0) { 133 close(sockfd); 134 LOG(log_info, logtype_default, "tsockfd_create: listen: %s\n", strerror(errno)); 135 continue; 136 } 137 138 /* We got a socket */ 139 break; 140 } 141 142 if (p == NULL) { 143 LOG(log_error, logtype_default, "tsockfd_create: no suitable network config %s:%s", host, port); 144 freeaddrinfo(servinfo); 145 return -1; 146 } 147 148 freeaddrinfo(servinfo); 149 return sockfd; 150} 151 152/* --------------------- */ 153int usockfd_check(int sockfd, const sigset_t *sigset) 154{ 155 int fd; 156 socklen_t size; 157 fd_set readfds; 158 int ret; 159 160 FD_ZERO(&readfds); 161 FD_SET(sockfd, &readfds); 162 163 if ((ret = pselect(sockfd + 1, &readfds, NULL, NULL, NULL, sigset)) < 0) { 164 if (errno == EINTR) 165 return 0; 166 LOG(log_error, logtype_cnid, "error in select: %s", 167 strerror(errno)); 168 return -1; 169 } 170 171 if (ret) { 172 size = 0; 173 if ((fd = accept(sockfd, NULL, &size)) < 0) { 174 if (errno == EINTR) 175 return 0; 176 LOG(log_error, logtype_cnid, "error in accept: %s", 177 strerror(errno)); 178 return -1; 179 } 180 return fd; 181 } else 182 return 0; 183} 184