masqmail

view 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
line source
1 /* MasqMail
2 Copyright (C) 1999-2001 Oliver Kurth
3 Copyright (C) 2010 markus schnalke <meillo@marmaro.de>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
21 #include "config.h"
22 #include "masqmail.h"
23 #include "readsock.h"
27 gboolean
28 init_sockaddr(struct sockaddr_in * name, interface * iface)
29 {
30 struct hostent *he;
31 struct in_addr ia;
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);
46 return TRUE;
47 }
50 int
51 make_server_socket(interface * iface)
52 {
53 int sock = -1;
54 struct sockaddr_in server;
56 memset(&server, 0, sizeof(struct sockaddr_in));
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 }
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 }
76 return sock;
77 }
82 gchar*
83 mserver_detect_online(interface * iface)
84 {
85 struct sockaddr_in saddr;
86 gchar *ret = NULL;
88 if (!init_sockaddr(&saddr, iface)) {
89 return NULL;
90 }
92 int sock = socket(PF_INET, SOCK_STREAM, 0);
93 int dup_sock;
94 if (connect(sock, (struct sockaddr *) (&saddr), sizeof(saddr)) != 0) {
95 return NULL;
96 }
98 FILE *in, *out;
99 char buf[256];
101 dup_sock = dup(sock);
102 out = fdopen(sock, "w");
103 in = fdopen(dup_sock, "r");
105 if (!read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) {
106 return NULL;
107 }
109 /* this is the protocol (reverse engineered):
110 S: READY
111 C: STAT
112 S: DOWN
113 C: QUIT
114 -> offline
116 S: READY
117 C: STAT
118 S: UP foo:-1
119 C: QUIT
120 -> offline
122 S: READY
123 C: STAT
124 S: UP foo:1
125 C: QUIT
126 -> online, `foo' gets printed
127 */
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);
146 }
147 } else {
148 fprintf(stderr, "unexpected response from mserver after STAT cmd: %s", buf);
149 }
150 } else {
151 fprintf(stderr, "unexpected response from mserver after STAT cmd: %s", buf);
152 }
153 }
154 }
155 fprintf(out, "QUIT");
156 fflush(out);
158 close(sock);
159 close(dup_sock);
160 fclose(in);
161 fclose(out);
163 return ret;
164 }
167 void
168 logwrite(int pri, const char *fmt, ...)
169 {
170 va_list args;
171 va_start(args, fmt);
173 vfprintf(stderr, fmt, args);
175 va_end(args);
176 }
179 int
180 main(int argc, char *argv[])
181 {
182 interface iface;
183 gchar *name;
185 if (argc != 3) {
186 fprintf(stderr, "usage: %s HOST PORT\n", argv[0]);
187 return 1;
188 }
190 iface.address = g_strdup(argv[1]);
191 iface.port = atoi(argv[2]);
193 name = mserver_detect_online(&iface);
195 if (name) {
196 printf("%s\n", name);
197 return 0;
198 }
199 return 1;
200 }