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