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  }