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