/*
- * $Id: usockfd.c,v 1.5 2009-10-18 20:21:09 didg Exp $
- *
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
#include <sys/un.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
-
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif /* HAVE_SYS_TYPES_H */
-#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
-#endif /* HAVE_SYS_TIME_H */
-
#include <atalk/logger.h>
+#include <atalk/compat.h>
#include "usockfd.h"
#include <sys/select.h>
return -1;
}
+#ifdef chmod
+#undef chmod
+#endif
if (chmod(usock_fn, mode) < 0) {
LOG(log_error, logtype_cnid, "error changing permissions for %s: %s",
usock_fn, strerror(errno));
}
/* ---------------
- create a tcp socket (should share dsi stuff)
-*/
-int tsockfd_create(char *host, u_int16_t ipport, int backlog)
+ * create a tcp socket
+ */
+int tsockfd_create(char *host, char *port, int backlog)
{
- int sockfd;
- struct sockaddr_in server;
- struct hostent *hp;
- int port;
-
- hp=gethostbyname(host);
- if (!hp) {
- unsigned long int addr=inet_addr(host);
- if (addr!= (unsigned)-1)
- hp=gethostbyaddr((char*)addr,sizeof(addr),AF_INET);
-
- if (!hp) {
- LOG(log_error, logtype_cnid, "gethostbyaddr %s: %s", host, strerror(errno));
- return -1;
- }
- }
- memcpy((char*)&server.sin_addr,(char*)hp->h_addr,sizeof(server.sin_addr));
+ int sockfd, flag, ret;
+ struct addrinfo hints, *servinfo, *p;
- if ((sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
- LOG(log_error, logtype_cnid, "error in socket call: %s", strerror(errno));
- return -1;
+ /* Prepare hint for getaddrinfo */
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if ((ret = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
+ LOG(log_error, logtype_cnid, "tsockfd_create: getaddrinfo: %s\n", gai_strerror(ret));
+ return 0;
}
-
- port = htons(ipport);
-
- server.sin_family = AF_INET;
- server.sin_port = port;
+ /* create a socket */
+ /* loop through all the results and bind to the first we can */
+ for (p = servinfo; p != NULL; p = p->ai_next) {
+ if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
+ LOG(log_info, logtype_cnid, "tsockfd_create: socket: %s", strerror(errno));
+ continue;
+ }
+
+ /*
+ * Set some socket options:
+ * SO_REUSEADDR deals w/ quick close/opens
+ * TCP_NODELAY diables Nagle
+ */
#ifdef SO_REUSEADDR
- port = 1;
- setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &port, sizeof(port));
-#endif /* SO_REUSEADDR */
+ flag = 1;
+ setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
+#endif
-#ifdef USE_TCP_NODELAY
+#ifdef USE_TCP_NODELAY
#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
-#endif /* ! SOL_TCP */
- port = 1;
- setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &port, sizeof(port));
+#endif
+ flag = 1;
+ setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag));
#endif /* USE_TCP_NODELAY */
+
+ if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
+ close(sockfd);
+ LOG(log_info, logtype_cnid, "tsockfd_create: bind: %s\n", strerror(errno));
+ continue;
+ }
- if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) {
- LOG(log_error, logtype_cnid, "error binding to socket for %s: %s",
- host, strerror(errno));
- return -1;
+ if (listen(sockfd, backlog) < 0) {
+ close(sockfd);
+ LOG(log_info, logtype_cnid, "tsockfd_create: listen: %s\n", strerror(errno));
+ continue;
+ }
+
+ /* We got a socket */
+ break;
}
- if (listen(sockfd, backlog) < 0) {
- LOG(log_error, logtype_cnid, "error in listen for %s: %s",
- host, strerror(errno));
+ if (p == NULL) {
+ LOG(log_error, logtype_cnid, "tsockfd_create: no suitable network config %s:%s", host, port);
+ freeaddrinfo(servinfo);
return -1;
}
+ freeaddrinfo(servinfo);
return sockfd;
}
socklen_t size;
fd_set readfds;
int ret;
- struct timeval tv;
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
strerror(errno));
return -1;
}
- tv.tv_sec = 5;
- tv.tv_usec = 0;
- if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
- LOG(log_error, logtype_cnid, "set SO_RCVTIMEO: %s", strerror(errno));
- close(fd);
- return -1;
- }
return fd;
} else
return 0;