#include #include #include #include #include #include "macros.h" #include "network.h" const char *addr_to_str(struct sockaddr *sa, socklen_t len) { const int family = sa->sa_family; static char ip[INET6_ADDRSTRLEN]; char *str = ip; switch (family) { case AF_INET6 : inet_ntop(family, &((struct sockaddr_in6 *)sa)->sin6_addr, ip, len); break; case AF_INET : inet_ntop(family, &((struct sockaddr_in *)sa)->sin_addr, ip, len); break; case AF_UNIX : str = ((struct sockaddr_un *)sa)->sun_path; break; } return str; } struct sockaddr *get_sock_addr(int socket) { struct sockaddr *sa; socklen_t sock_len = sizeof(struct sockaddr); getsockname(socket, NULL, &sock_len); sa = calloc(1, sock_len); getsockname(socket, sa, &sock_len); return sa; } int create_socket(struct sockaddr *sa, size_t sock_len) { const int one = 1; /* Create a new listen socket. */ const int fd = socket(sa->sa_family, SOCK_SEQPACKET, IPPROTO_SCTP); const char *addr_str = addr_to_str(sa, sock_len); int ret = fd; /* Did we fail to create the listen socket? */ if (fd < 0) { log_reason(LOG_ERR, "Failed to create listen socket for addresss \"%s\".", addr_str, strerror(errno)); return -1; } /* Do we have an IPv6 socket? */ if (sa->sa_family == AF_INET6) { int set = 1; setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &set, sizeof(set)); } /* Did we fail to enable SO_REUSEADDR? */ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) { log_reason(LOG_ERR, "Failed to enable SO_REUSEADDR for socket %i.", fd, strerror(errno)); ret = -1; } /* Did we fail to bind the listen socket? */ if (ret >= 0 && bind(fd, sa, sock_len) < 0) { log_reason(LOG_ERR, "Failed to bind listen socket %i with address \"%s\".", fd, addr_str, strerror(errno)); ret = -1; } /* Did we fail to listen to the socket? */ if (ret >= 0 && listen(fd, 20) < 0) { log_reason(LOG_ERR, "Failed to listen to socket %i.", fd, strerror(errno)); ret = -1; } /* Did we get an error? */ if (ret < 0) { /* Close the socket. */ close(fd); /* Is this a unix domain socket? */ if (sa->sa_family == AF_UNIX) { struct sockaddr_un *sa_un = (struct sockaddr_un *)sa; /* Unlink the path. */ unlink(sa_un->sun_path); } log_reason(LOG_ERR, "Failed to create socket for address \"%s\".", addr_str, strerror(errno)); } else { log(LOG_INFO, "Successfully created socket descriptor %i for address \"%s\".", fd, addr_str); } return ret; }