#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ip-utils.h" #ifndef INADDR_NONE #define INADDR_NONE 0xffffffff #endif int accept_tcp(int ms) { struct sockaddr_in sa; socklen_t alen = sizeof(sockaddr_in); int ss; while (true) { ss = accept(ms, (struct sockaddr *) &sa, &alen); if (ss > -1) return ss; if (errno == EINTR) continue; errexit("accept() failed:"); } } void errexit(const char * format, ...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); if ((strlen(format) > 0) && (format[strlen(format) - 1] == ':')) fprintf(stderr, " %s", strerror(errno)); fprintf(stderr, ".\n"); exit(EXIT_FAILURE); } static int get_socket(const std::string & protocol) { struct protoent * ppe; if ((ppe = getprotobyname(protocol.c_str())) == 0) errexit("Can't get \"%s\" protocol entry", protocol.c_str()); int s = socket(PF_INET, protocol == "udp" ? SOCK_DGRAM : SOCK_STREAM, ppe->p_proto); if (s < 0) errexit("Can't create socket:"); return s; } static short get_port(const char * service, const char * protocol) { short p; struct servent * pse = getservbyname(service, protocol); if (pse) p = pse->s_port; else if ((p = htons((unsigned short) atoi(service))) == 0) errexit("Can't get \"%s\" service entry", service); return p; } static int passive_socket( const char * service, const char * protocol, unsigned qlen) { struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = get_port(service, protocol); int s = get_socket(protocol); if (protocol == "tcp") { const int on = 1; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) errexit("setsockopt(SO_REUSEADDR) failed:"); } if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) errexit("Can't bind to %s port:", service); if ((protocol == "tcp") && (listen(s , qlen) < 0)) errexit("Can't listen on %s port:", service); return s; } int passive_tcp(const char * service, unsigned qlen) { return passive_socket(service, "tcp", qlen); } int passive_udp(const char * service) { return passive_socket(service, "udp", 0); } static int socket_connect( const char * host, const char * service, const char * protocol) { struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = get_port(service, protocol); struct hostent * phe = gethostbyname(host); if (phe) memcpy(&sin.sin_addr, phe->h_addr, phe->h_length); else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) errexit("Can't get \"%s\" host entry", host); int s = get_socket(protocol); if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) errexit("Can't connect to %s.%s:", host, service); return s; } int tcp_connect(const char * host, const char * service) { return socket_connect(host, service, "tcp"); } unsigned tcp_read(int s, char * buffer, unsigned bsize) { char * bp = buffer; while (bsize) { int n = read(s, buffer, bsize); if (n < 0) errexit("Error during tcp read:"); if (n == 0) break; bsize -= n; buffer += n; } return buffer - bp; } int udp_connect(const char * host, const char * service) { return socket_connect(host, service, "udp"); }