masqmail
changeset 187:bd7c52a36b0c
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
author | meillo@marmaro.de |
---|---|
date | Thu, 15 Jul 2010 00:14:26 +0200 |
parents | 3dff59a4e764 |
children | bfa7a8b566da |
files | src/Makefile.am src/Makefile.in src/mservdetect.c |
diffstat | 3 files changed, 141 insertions(+), 63 deletions(-) [+] |
line diff
1.1 --- a/src/Makefile.am Wed Jul 14 23:26:20 2010 +0200 1.2 +++ b/src/Makefile.am Thu Jul 15 00:14:26 2010 +0200 1.3 @@ -71,7 +71,6 @@ 1.4 masqmail.h\ 1.5 readsock.h\ 1.6 mservdetect.c\ 1.7 - interface.c\ 1.8 readsock.c\ 1.9 peopen.c 1.10
2.1 --- a/src/Makefile.in Wed Jul 14 23:26:20 2010 +0200 2.2 +++ b/src/Makefile.in Thu Jul 15 00:14:26 2010 +0200 2.3 @@ -61,8 +61,8 @@ 2.4 timeival.$(OBJEXT) 2.5 masqmail_OBJECTS = $(am_masqmail_OBJECTS) 2.6 masqmail_DEPENDENCIES = 2.7 -am_mservdetect_OBJECTS = mservdetect.$(OBJEXT) interface.$(OBJEXT) \ 2.8 - readsock.$(OBJEXT) peopen.$(OBJEXT) 2.9 +am_mservdetect_OBJECTS = mservdetect.$(OBJEXT) readsock.$(OBJEXT) \ 2.10 + peopen.$(OBJEXT) 2.11 mservdetect_OBJECTS = $(am_mservdetect_OBJECTS) 2.12 mservdetect_DEPENDENCIES = 2.13 am_readtest_OBJECTS = readsock.$(OBJEXT) readtest.$(OBJEXT) 2.14 @@ -299,7 +299,6 @@ 2.15 masqmail.h\ 2.16 readsock.h\ 2.17 mservdetect.c\ 2.18 - interface.c\ 2.19 readsock.c\ 2.20 peopen.c 2.21
3.1 --- a/src/mservdetect.c Wed Jul 14 23:26:20 2010 +0200 3.2 +++ b/src/mservdetect.c Thu Jul 15 00:14:26 2010 +0200 3.3 @@ -1,5 +1,6 @@ 3.4 /* MasqMail 3.5 Copyright (C) 1999-2001 Oliver Kurth 3.6 + Copyright (C) 2010 markus schnalke <meillo@marmaro.de> 3.7 3.8 This program is free software; you can redistribute it and/or modify 3.9 it under the terms of the GNU General Public License as published by 3.10 @@ -22,56 +23,143 @@ 3.11 #include "readsock.h" 3.12 3.13 3.14 + 3.15 +gboolean 3.16 +init_sockaddr(struct sockaddr_in * name, interface * iface) 3.17 +{ 3.18 + struct hostent *he; 3.19 + struct in_addr ia; 3.20 + 3.21 + if (inet_aton(iface->address, &ia) != 0) { 3.22 + /* IP address */ 3.23 + memcpy(&(name->sin_addr), &ia, sizeof(name->sin_addr)); 3.24 + } else { 3.25 + if ((he = gethostbyname(iface->address)) == NULL) { 3.26 + logwrite(LOG_ALERT, "local address '%s' unknown. (deleting)\n", iface->address); 3.27 + return FALSE; 3.28 + } 3.29 + memcpy(&(name->sin_addr), he->h_addr, sizeof(name->sin_addr)); 3.30 + } 3.31 + name->sin_family = AF_INET; 3.32 + name->sin_port = htons(iface->port); 3.33 + 3.34 + return TRUE; 3.35 +} 3.36 + 3.37 + 3.38 +int 3.39 +make_server_socket(interface * iface) 3.40 +{ 3.41 + int sock = -1; 3.42 + struct sockaddr_in server; 3.43 + 3.44 + memset(&server, 0, sizeof(struct sockaddr_in)); 3.45 + 3.46 + /* Create the socket. */ 3.47 + sock = socket(PF_INET, SOCK_STREAM, 0); 3.48 + if (sock < 0) { 3.49 + logwrite(LOG_ALERT, "socket: %s\n", strerror(errno)); 3.50 + return -1; 3.51 + } 3.52 + 3.53 + if (init_sockaddr(&server, iface)) { 3.54 + /* bind the socket */ 3.55 + if (bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0) { 3.56 + logwrite(LOG_ALERT, "bind: %s\n", strerror(errno)); 3.57 + return -1; 3.58 + } 3.59 + } else { 3.60 + close(sock); 3.61 + return -1; 3.62 + } 3.63 + 3.64 + return sock; 3.65 +} 3.66 + 3.67 + 3.68 + 3.69 + 3.70 gchar* 3.71 mserver_detect_online(interface * iface) 3.72 { 3.73 struct sockaddr_in saddr; 3.74 gchar *ret = NULL; 3.75 3.76 - if (init_sockaddr(&saddr, iface)) { 3.77 - int sock = socket(PF_INET, SOCK_STREAM, 0); 3.78 - int dup_sock; 3.79 - if (connect(sock, (struct sockaddr *) (&saddr), sizeof(saddr)) == 0) { 3.80 - FILE *in, *out; 3.81 - char buf[256]; 3.82 + if (!init_sockaddr(&saddr, iface)) { 3.83 + return NULL; 3.84 + } 3.85 3.86 - dup_sock = dup(sock); 3.87 - out = fdopen(sock, "w"); 3.88 - in = fdopen(dup_sock, "r"); 3.89 + int sock = socket(PF_INET, SOCK_STREAM, 0); 3.90 + int dup_sock; 3.91 + if (connect(sock, (struct sockaddr *) (&saddr), sizeof(saddr)) != 0) { 3.92 + return NULL; 3.93 + } 3.94 3.95 - if (read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) { 3.96 - if (strncmp(buf, "READY", 5) == 0) { 3.97 - fprintf(out, "STAT\n"); 3.98 - fflush(out); 3.99 - if (read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) { 3.100 - if (strncmp(buf, "DOWN", 4) == 0) { 3.101 - ret = NULL; 3.102 - } else if (strncmp(buf, "UP", 2) == 0) { 3.103 - gchar *p = buf + 3; 3.104 - while ((*p != ':') && *p) 3.105 - p++; 3.106 - if (*p) { 3.107 - *p = 0; 3.108 - p++; 3.109 - if ((atoi(p) >= 0) && *p) 3.110 - ret = g_strdup(buf + 3); 3.111 - } else 3.112 - logwrite(LOG_ALERT, "unexpected response from mserver after STAT cmd: %s", buf); 3.113 - } else { 3.114 - logwrite(LOG_ALERT, "unexpected response from mserver after STAT cmd: %s", buf); 3.115 - } 3.116 + FILE *in, *out; 3.117 + char buf[256]; 3.118 + 3.119 + dup_sock = dup(sock); 3.120 + out = fdopen(sock, "w"); 3.121 + in = fdopen(dup_sock, "r"); 3.122 + 3.123 + if (!read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) { 3.124 + return NULL; 3.125 + } 3.126 + 3.127 + /* this is the protocol (reverse engineered): 3.128 + S: READY 3.129 + C: STAT 3.130 + S: DOWN 3.131 + C: QUIT 3.132 + -> offline 3.133 + 3.134 + S: READY 3.135 + C: STAT 3.136 + S: UP foo:-1 3.137 + C: QUIT 3.138 + -> offline 3.139 + 3.140 + S: READY 3.141 + C: STAT 3.142 + S: UP foo:1 3.143 + C: QUIT 3.144 + -> online, `foo' gets printed 3.145 + */ 3.146 + 3.147 + if (strncmp(buf, "READY", 5) == 0) { 3.148 + fprintf(out, "STAT\n"); 3.149 + fflush(out); 3.150 + if (read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) { 3.151 + if (strncmp(buf, "DOWN", 4) == 0) { 3.152 + ret = NULL; 3.153 + } else if (strncmp(buf, "UP", 2) == 0) { 3.154 + gchar *p = buf + 3; 3.155 + while ((*p != ':') && *p) { 3.156 + p++; 3.157 + } 3.158 + if (*p) { 3.159 + *p = '\0'; 3.160 + p++; 3.161 + if ((atoi(p) >= 0) && *p) { 3.162 + /* `UP foo:N', where `N' is a non-negative number */ 3.163 + ret = g_strdup(buf + 3); 3.164 } 3.165 + } else { 3.166 + fprintf(stderr, "unexpected response from mserver after STAT cmd: %s", buf); 3.167 } 3.168 - fprintf(out, "QUIT"); 3.169 - fflush(out); 3.170 - 3.171 - close(sock); 3.172 - close(dup_sock); 3.173 - fclose(in); 3.174 - fclose(out); 3.175 + } else { 3.176 + fprintf(stderr, "unexpected response from mserver after STAT cmd: %s", buf); 3.177 } 3.178 } 3.179 } 3.180 + fprintf(out, "QUIT"); 3.181 + fflush(out); 3.182 + 3.183 + close(sock); 3.184 + close(dup_sock); 3.185 + fclose(in); 3.186 + fclose(out); 3.187 + 3.188 return ret; 3.189 } 3.190 3.191 @@ -82,39 +170,31 @@ 3.192 va_list args; 3.193 va_start(args, fmt); 3.194 3.195 - vfprintf(stdout, fmt, args); 3.196 + vfprintf(stderr, fmt, args); 3.197 3.198 va_end(args); 3.199 } 3.200 3.201 -void 3.202 -debugf(const char *fmt, ...) 3.203 -{ 3.204 - va_list args; 3.205 - va_start(args, fmt); 3.206 - 3.207 - vfprintf(stdout, fmt, args); 3.208 - 3.209 - va_end(args); 3.210 -} 3.211 3.212 int 3.213 main(int argc, char *argv[]) 3.214 { 3.215 - if (argc == 3) { 3.216 - interface iface; 3.217 - gchar *name; 3.218 + interface iface; 3.219 + gchar *name; 3.220 3.221 - iface.address = g_strdup(argv[1]); 3.222 - iface.port = atoi(argv[2]); 3.223 + if (argc != 3) { 3.224 + fprintf(stderr, "usage: %s HOST PORT\n", argv[0]); 3.225 + return 1; 3.226 + } 3.227 3.228 - name = mserver_detect_online(&iface); 3.229 + iface.address = g_strdup(argv[1]); 3.230 + iface.port = atoi(argv[2]); 3.231 3.232 + name = mserver_detect_online(&iface); 3.233 + 3.234 + if (name) { 3.235 printf("%s\n", name); 3.236 - 3.237 - exit(EXIT_SUCCESS); 3.238 - } else { 3.239 - fprintf(stderr, "usage %s <host> <port>\n", argv[0]); 3.240 - exit(EXIT_FAILURE); 3.241 + return 0; 3.242 } 3.243 + return 1; 3.244 }