#define __KAVSOCKETS_C #include #include #include #include #include #include #include #include #include #include #include #include "kaverrors.h" #include "kavsockets.h" int kavSocketConnect(const char *sock, int * const sockFamily) { int ret = -1; char *address = 0; int port = 0; // parse destination stirng if ((port = parseDestination(sock, &address)) == -1) { kavSetError("Wrong destination parameter"); return (-1); } // connect to kavmd if (port == 0) { *sockFamily = KAV_SOCK_UNIX; ret = kavSocketConnectUnix(address); } else { *sockFamily = KAV_SOCK_INET; ret = kavSocketConnectInet(address, port); } return (ret); } void kavSocketClose(int fd) { close(fd); } int kavSocketWrite(int fd, const void *buf, unsigned int size) { int ret, total = 0; do { ret = write(fd, buf + total, size - total); if (ret > 0) total += ret; } while ((ret == -1 && errno == EINTR) || (total < size)); if (ret == -1) kavSetError(strerror(errno)); return (ret == -1 ? -1 : total); } int kavSocketRead(int fd, void *buf, unsigned int size) { int ret, total = 0; do { ret = read(fd, buf + total, size - total); if (ret > 0) total += ret; } while ((ret == -1 && errno == EINTR) || (total < size)); if (ret == -1) kavSetError(strerror(errno)); return (ret == -1 ? -1 : total); } static int kavSocketConnectInet(const char *dest, unsigned short port) { struct sockaddr_in sa; int s = socket(AF_INET, SOCK_STREAM, 0); if (s == -1) { kavSetError(strerror(errno)); return (-1); } memset(&sa, 0, sizeof(struct sockaddr_in)); sa.sin_addr.s_addr = inet_addr(dest); if (sa.sin_addr.s_addr == INADDR_NONE) { kavSetError(strerror(errno)); return (-1); } sa.sin_port = htons(port); sa.sin_family = AF_INET; if (connect(s, (const struct sockaddr *) &sa, sizeof(struct sockaddr_in)) == -1) { kavSetError(strerror(errno)); close(s); return (-1); } return (s); } static int kavSocketConnectUnix(const char *dest) { struct sockaddr_un sa; int s; // buffer overflow is bad, mmk ? if (strlen(dest) >= sizeof(sa.sun_path)) { char tmp[512]; snprintf((char *) &tmp, sizeof(tmp), "Path too long (must be less or equal to %lu)", sizeof(sa.sun_path)); kavSetError(tmp); return (-1); } if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { kavSetError(strerror(errno)); return (-1); } memset(&sa, 0, sizeof(struct sockaddr_un)); sa.sun_family = AF_UNIX; strcpy(sa.sun_path, dest); if (connect(s, (const struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) { kavSetError(strerror(errno)); close(s); return (-1); } return (s); } static int parseDestination(const char *dest, char **address) { if (strstr(dest, "local:") == dest) { *address = strchr(dest, ':') + 1; if (**address == '\0') return (-1); return (0); // 0 means that the socket is of type UNIX/LOCAL } else if (strstr(dest, "inet:") == dest) { int port = 0; char *pos1, *pos2 = (char *) dest + 4; // 4 = strlen("inet") char *endptr; if ((pos1 = strchr(dest, '@')) == 0) return (-1); // don't modify the received string, work on a copy if ((*address = malloc(pos1 - pos2)) == 0) return (-1); strncpy(*address, pos2 + 1, pos1 - pos2 - 1); address[pos1 - pos2 - 1] = 0; port = strtol(*address, &endptr, 10); free(*address); if (*endptr != '\0' || port < 0 || port > USHRT_MAX) return (-1); *address = pos1 + 1; if (strlen(*address) == 0) return (-1); return (port); } return (-1); }