comparison src/mservdetect.c @ 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 5b621742b2e7
children bfa7a8b566da
comparison
equal deleted inserted replaced
186:3dff59a4e764 187:bd7c52a36b0c
1 /* MasqMail 1 /* MasqMail
2 Copyright (C) 1999-2001 Oliver Kurth 2 Copyright (C) 1999-2001 Oliver Kurth
3 Copyright (C) 2010 markus schnalke <meillo@marmaro.de>
3 4
4 This program is free software; you can redistribute it and/or modify 5 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or 7 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version. 8 (at your option) any later version.
20 #include "config.h" 21 #include "config.h"
21 #include "masqmail.h" 22 #include "masqmail.h"
22 #include "readsock.h" 23 #include "readsock.h"
23 24
24 25
26
27 gboolean
28 init_sockaddr(struct sockaddr_in * name, interface * iface)
29 {
30 struct hostent *he;
31 struct in_addr ia;
32
33 if (inet_aton(iface->address, &ia) != 0) {
34 /* IP address */
35 memcpy(&(name->sin_addr), &ia, sizeof(name->sin_addr));
36 } else {
37 if ((he = gethostbyname(iface->address)) == NULL) {
38 logwrite(LOG_ALERT, "local address '%s' unknown. (deleting)\n", iface->address);
39 return FALSE;
40 }
41 memcpy(&(name->sin_addr), he->h_addr, sizeof(name->sin_addr));
42 }
43 name->sin_family = AF_INET;
44 name->sin_port = htons(iface->port);
45
46 return TRUE;
47 }
48
49
50 int
51 make_server_socket(interface * iface)
52 {
53 int sock = -1;
54 struct sockaddr_in server;
55
56 memset(&server, 0, sizeof(struct sockaddr_in));
57
58 /* Create the socket. */
59 sock = socket(PF_INET, SOCK_STREAM, 0);
60 if (sock < 0) {
61 logwrite(LOG_ALERT, "socket: %s\n", strerror(errno));
62 return -1;
63 }
64
65 if (init_sockaddr(&server, iface)) {
66 /* bind the socket */
67 if (bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {
68 logwrite(LOG_ALERT, "bind: %s\n", strerror(errno));
69 return -1;
70 }
71 } else {
72 close(sock);
73 return -1;
74 }
75
76 return sock;
77 }
78
79
80
81
25 gchar* 82 gchar*
26 mserver_detect_online(interface * iface) 83 mserver_detect_online(interface * iface)
27 { 84 {
28 struct sockaddr_in saddr; 85 struct sockaddr_in saddr;
29 gchar *ret = NULL; 86 gchar *ret = NULL;
30 87
31 if (init_sockaddr(&saddr, iface)) { 88 if (!init_sockaddr(&saddr, iface)) {
32 int sock = socket(PF_INET, SOCK_STREAM, 0); 89 return NULL;
33 int dup_sock; 90 }
34 if (connect(sock, (struct sockaddr *) (&saddr), sizeof(saddr)) == 0) { 91
35 FILE *in, *out; 92 int sock = socket(PF_INET, SOCK_STREAM, 0);
36 char buf[256]; 93 int dup_sock;
37 94 if (connect(sock, (struct sockaddr *) (&saddr), sizeof(saddr)) != 0) {
38 dup_sock = dup(sock); 95 return NULL;
39 out = fdopen(sock, "w"); 96 }
40 in = fdopen(dup_sock, "r"); 97
41 98 FILE *in, *out;
42 if (read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) { 99 char buf[256];
43 if (strncmp(buf, "READY", 5) == 0) { 100
44 fprintf(out, "STAT\n"); 101 dup_sock = dup(sock);
45 fflush(out); 102 out = fdopen(sock, "w");
46 if (read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) { 103 in = fdopen(dup_sock, "r");
47 if (strncmp(buf, "DOWN", 4) == 0) { 104
48 ret = NULL; 105 if (!read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) {
49 } else if (strncmp(buf, "UP", 2) == 0) { 106 return NULL;
50 gchar *p = buf + 3; 107 }
51 while ((*p != ':') && *p) 108
52 p++; 109 /* this is the protocol (reverse engineered):
53 if (*p) { 110 S: READY
54 *p = 0; 111 C: STAT
55 p++; 112 S: DOWN
56 if ((atoi(p) >= 0) && *p) 113 C: QUIT
57 ret = g_strdup(buf + 3); 114 -> offline
58 } else 115
59 logwrite(LOG_ALERT, "unexpected response from mserver after STAT cmd: %s", buf); 116 S: READY
60 } else { 117 C: STAT
61 logwrite(LOG_ALERT, "unexpected response from mserver after STAT cmd: %s", buf); 118 S: UP foo:-1
62 } 119 C: QUIT
120 -> offline
121
122 S: READY
123 C: STAT
124 S: UP foo:1
125 C: QUIT
126 -> online, `foo' gets printed
127 */
128
129 if (strncmp(buf, "READY", 5) == 0) {
130 fprintf(out, "STAT\n");
131 fflush(out);
132 if (read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) {
133 if (strncmp(buf, "DOWN", 4) == 0) {
134 ret = NULL;
135 } else if (strncmp(buf, "UP", 2) == 0) {
136 gchar *p = buf + 3;
137 while ((*p != ':') && *p) {
138 p++;
139 }
140 if (*p) {
141 *p = '\0';
142 p++;
143 if ((atoi(p) >= 0) && *p) {
144 /* `UP foo:N', where `N' is a non-negative number */
145 ret = g_strdup(buf + 3);
63 } 146 }
147 } else {
148 fprintf(stderr, "unexpected response from mserver after STAT cmd: %s", buf);
64 } 149 }
65 fprintf(out, "QUIT"); 150 } else {
66 fflush(out); 151 fprintf(stderr, "unexpected response from mserver after STAT cmd: %s", buf);
67
68 close(sock);
69 close(dup_sock);
70 fclose(in);
71 fclose(out);
72 } 152 }
73 } 153 }
74 } 154 }
155 fprintf(out, "QUIT");
156 fflush(out);
157
158 close(sock);
159 close(dup_sock);
160 fclose(in);
161 fclose(out);
162
75 return ret; 163 return ret;
76 } 164 }
77 165
78 166
79 void 167 void
80 logwrite(int pri, const char *fmt, ...) 168 logwrite(int pri, const char *fmt, ...)
81 { 169 {
82 va_list args; 170 va_list args;
83 va_start(args, fmt); 171 va_start(args, fmt);
84 172
85 vfprintf(stdout, fmt, args); 173 vfprintf(stderr, fmt, args);
86 174
87 va_end(args); 175 va_end(args);
88 } 176 }
89 177
90 void
91 debugf(const char *fmt, ...)
92 {
93 va_list args;
94 va_start(args, fmt);
95
96 vfprintf(stdout, fmt, args);
97
98 va_end(args);
99 }
100 178
101 int 179 int
102 main(int argc, char *argv[]) 180 main(int argc, char *argv[])
103 { 181 {
104 if (argc == 3) { 182 interface iface;
105 interface iface; 183 gchar *name;
106 gchar *name; 184
107 185 if (argc != 3) {
108 iface.address = g_strdup(argv[1]); 186 fprintf(stderr, "usage: %s HOST PORT\n", argv[0]);
109 iface.port = atoi(argv[2]); 187 return 1;
110 188 }
111 name = mserver_detect_online(&iface); 189
112 190 iface.address = g_strdup(argv[1]);
191 iface.port = atoi(argv[2]);
192
193 name = mserver_detect_online(&iface);
194
195 if (name) {
113 printf("%s\n", name); 196 printf("%s\n", name);
114 197 return 0;
115 exit(EXIT_SUCCESS); 198 }
116 } else { 199 return 1;
117 fprintf(stderr, "usage %s <host> <port>\n", argv[0]); 200 }
118 exit(EXIT_FAILURE);
119 }
120 }