# HG changeset patch # User meillo@marmaro.de # Date 1279145666 -7200 # Node ID bd7c52a36b0c7d059a83b07f9b895aaa497c37ef # Parent 3dff59a4e7645359f4f094a76ffd64e0652bf09b improved mservdetect in various ways errors are handled better (no segfaults anymore) copied the relevant part of interface.c into mservdetect.c described how I think the mserver protocol works diff -r 3dff59a4e764 -r bd7c52a36b0c src/Makefile.am --- a/src/Makefile.am Wed Jul 14 23:26:20 2010 +0200 +++ b/src/Makefile.am Thu Jul 15 00:14:26 2010 +0200 @@ -71,7 +71,6 @@ masqmail.h\ readsock.h\ mservdetect.c\ - interface.c\ readsock.c\ peopen.c diff -r 3dff59a4e764 -r bd7c52a36b0c src/Makefile.in --- a/src/Makefile.in Wed Jul 14 23:26:20 2010 +0200 +++ b/src/Makefile.in Thu Jul 15 00:14:26 2010 +0200 @@ -61,8 +61,8 @@ timeival.$(OBJEXT) masqmail_OBJECTS = $(am_masqmail_OBJECTS) masqmail_DEPENDENCIES = -am_mservdetect_OBJECTS = mservdetect.$(OBJEXT) interface.$(OBJEXT) \ - readsock.$(OBJEXT) peopen.$(OBJEXT) +am_mservdetect_OBJECTS = mservdetect.$(OBJEXT) readsock.$(OBJEXT) \ + peopen.$(OBJEXT) mservdetect_OBJECTS = $(am_mservdetect_OBJECTS) mservdetect_DEPENDENCIES = am_readtest_OBJECTS = readsock.$(OBJEXT) readtest.$(OBJEXT) @@ -299,7 +299,6 @@ masqmail.h\ readsock.h\ mservdetect.c\ - interface.c\ readsock.c\ peopen.c diff -r 3dff59a4e764 -r bd7c52a36b0c src/mservdetect.c --- a/src/mservdetect.c Wed Jul 14 23:26:20 2010 +0200 +++ b/src/mservdetect.c Thu Jul 15 00:14:26 2010 +0200 @@ -1,5 +1,6 @@ /* MasqMail Copyright (C) 1999-2001 Oliver Kurth + Copyright (C) 2010 markus schnalke This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,56 +23,143 @@ #include "readsock.h" + +gboolean +init_sockaddr(struct sockaddr_in * name, interface * iface) +{ + struct hostent *he; + struct in_addr ia; + + if (inet_aton(iface->address, &ia) != 0) { + /* IP address */ + memcpy(&(name->sin_addr), &ia, sizeof(name->sin_addr)); + } else { + if ((he = gethostbyname(iface->address)) == NULL) { + logwrite(LOG_ALERT, "local address '%s' unknown. (deleting)\n", iface->address); + return FALSE; + } + memcpy(&(name->sin_addr), he->h_addr, sizeof(name->sin_addr)); + } + name->sin_family = AF_INET; + name->sin_port = htons(iface->port); + + return TRUE; +} + + +int +make_server_socket(interface * iface) +{ + int sock = -1; + struct sockaddr_in server; + + memset(&server, 0, sizeof(struct sockaddr_in)); + + /* Create the socket. */ + sock = socket(PF_INET, SOCK_STREAM, 0); + if (sock < 0) { + logwrite(LOG_ALERT, "socket: %s\n", strerror(errno)); + return -1; + } + + if (init_sockaddr(&server, iface)) { + /* bind the socket */ + if (bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0) { + logwrite(LOG_ALERT, "bind: %s\n", strerror(errno)); + return -1; + } + } else { + close(sock); + return -1; + } + + return sock; +} + + + + gchar* mserver_detect_online(interface * iface) { struct sockaddr_in saddr; gchar *ret = NULL; - if (init_sockaddr(&saddr, iface)) { - int sock = socket(PF_INET, SOCK_STREAM, 0); - int dup_sock; - if (connect(sock, (struct sockaddr *) (&saddr), sizeof(saddr)) == 0) { - FILE *in, *out; - char buf[256]; + if (!init_sockaddr(&saddr, iface)) { + return NULL; + } - dup_sock = dup(sock); - out = fdopen(sock, "w"); - in = fdopen(dup_sock, "r"); + int sock = socket(PF_INET, SOCK_STREAM, 0); + int dup_sock; + if (connect(sock, (struct sockaddr *) (&saddr), sizeof(saddr)) != 0) { + return NULL; + } - if (read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) { - if (strncmp(buf, "READY", 5) == 0) { - fprintf(out, "STAT\n"); - fflush(out); - if (read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) { - if (strncmp(buf, "DOWN", 4) == 0) { - ret = NULL; - } else if (strncmp(buf, "UP", 2) == 0) { - gchar *p = buf + 3; - while ((*p != ':') && *p) - p++; - if (*p) { - *p = 0; - p++; - if ((atoi(p) >= 0) && *p) - ret = g_strdup(buf + 3); - } else - logwrite(LOG_ALERT, "unexpected response from mserver after STAT cmd: %s", buf); - } else { - logwrite(LOG_ALERT, "unexpected response from mserver after STAT cmd: %s", buf); - } + FILE *in, *out; + char buf[256]; + + dup_sock = dup(sock); + out = fdopen(sock, "w"); + in = fdopen(dup_sock, "r"); + + if (!read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) { + return NULL; + } + + /* this is the protocol (reverse engineered): + S: READY + C: STAT + S: DOWN + C: QUIT + -> offline + + S: READY + C: STAT + S: UP foo:-1 + C: QUIT + -> offline + + S: READY + C: STAT + S: UP foo:1 + C: QUIT + -> online, `foo' gets printed + */ + + if (strncmp(buf, "READY", 5) == 0) { + fprintf(out, "STAT\n"); + fflush(out); + if (read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) { + if (strncmp(buf, "DOWN", 4) == 0) { + ret = NULL; + } else if (strncmp(buf, "UP", 2) == 0) { + gchar *p = buf + 3; + while ((*p != ':') && *p) { + p++; + } + if (*p) { + *p = '\0'; + p++; + if ((atoi(p) >= 0) && *p) { + /* `UP foo:N', where `N' is a non-negative number */ + ret = g_strdup(buf + 3); } + } else { + fprintf(stderr, "unexpected response from mserver after STAT cmd: %s", buf); } - fprintf(out, "QUIT"); - fflush(out); - - close(sock); - close(dup_sock); - fclose(in); - fclose(out); + } else { + fprintf(stderr, "unexpected response from mserver after STAT cmd: %s", buf); } } } + fprintf(out, "QUIT"); + fflush(out); + + close(sock); + close(dup_sock); + fclose(in); + fclose(out); + return ret; } @@ -82,39 +170,31 @@ va_list args; va_start(args, fmt); - vfprintf(stdout, fmt, args); + vfprintf(stderr, fmt, args); va_end(args); } -void -debugf(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - - vfprintf(stdout, fmt, args); - - va_end(args); -} int main(int argc, char *argv[]) { - if (argc == 3) { - interface iface; - gchar *name; + interface iface; + gchar *name; - iface.address = g_strdup(argv[1]); - iface.port = atoi(argv[2]); + if (argc != 3) { + fprintf(stderr, "usage: %s HOST PORT\n", argv[0]); + return 1; + } - name = mserver_detect_online(&iface); + iface.address = g_strdup(argv[1]); + iface.port = atoi(argv[2]); + name = mserver_detect_online(&iface); + + if (name) { printf("%s\n", name); - - exit(EXIT_SUCCESS); - } else { - fprintf(stderr, "usage %s \n", argv[0]); - exit(EXIT_FAILURE); + return 0; } + return 1; }