Mercurial > masqmail
annotate 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 |
rev | line source |
---|---|
0 | 1 /* MasqMail |
2 Copyright (C) 1999-2001 Oliver Kurth | |
187 | 3 Copyright (C) 2010 markus schnalke <meillo@marmaro.de> |
0 | 4 |
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. | |
9 | |
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. | |
14 | |
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 */ | |
19 | |
20 | |
21 #include "config.h" | |
22 #include "masqmail.h" | |
23 #include "readsock.h" | |
164 | 24 |
25 | |
187 | 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 | |
164 | 82 gchar* |
83 mserver_detect_online(interface * iface) | |
84 { | |
85 struct sockaddr_in saddr; | |
86 gchar *ret = NULL; | |
87 | |
187 | 88 if (!init_sockaddr(&saddr, iface)) { |
89 return NULL; | |
90 } | |
91 | |
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 } | |
164 | 97 |
187 | 98 FILE *in, *out; |
99 char buf[256]; | |
100 | |
101 dup_sock = dup(sock); | |
102 out = fdopen(sock, "w"); | |
103 in = fdopen(dup_sock, "r"); | |
104 | |
105 if (!read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) { | |
106 return NULL; | |
107 } | |
164 | 108 |
187 | 109 /* this is the protocol (reverse engineered): |
110 S: READY | |
111 C: STAT | |
112 S: DOWN | |
113 C: QUIT | |
114 -> offline | |
115 | |
116 S: READY | |
117 C: STAT | |
118 S: UP foo:-1 | |
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); | |
164 | 146 } |
187 | 147 } else { |
148 fprintf(stderr, "unexpected response from mserver after STAT cmd: %s", buf); | |
164 | 149 } |
187 | 150 } else { |
151 fprintf(stderr, "unexpected response from mserver after STAT cmd: %s", buf); | |
164 | 152 } |
153 } | |
154 } | |
187 | 155 fprintf(out, "QUIT"); |
156 fflush(out); | |
157 | |
158 close(sock); | |
159 close(dup_sock); | |
160 fclose(in); | |
161 fclose(out); | |
162 | |
164 | 163 return ret; |
164 } | |
165 | |
0 | 166 |
10
26e34ae9a3e3
changed indention and line wrapping to a more consistent style
meillo@marmaro.de
parents:
0
diff
changeset
|
167 void |
26e34ae9a3e3
changed indention and line wrapping to a more consistent style
meillo@marmaro.de
parents:
0
diff
changeset
|
168 logwrite(int pri, const char *fmt, ...) |
0 | 169 { |
10
26e34ae9a3e3
changed indention and line wrapping to a more consistent style
meillo@marmaro.de
parents:
0
diff
changeset
|
170 va_list args; |
26e34ae9a3e3
changed indention and line wrapping to a more consistent style
meillo@marmaro.de
parents:
0
diff
changeset
|
171 va_start(args, fmt); |
0 | 172 |
187 | 173 vfprintf(stderr, fmt, args); |
0 | 174 |
10
26e34ae9a3e3
changed indention and line wrapping to a more consistent style
meillo@marmaro.de
parents:
0
diff
changeset
|
175 va_end(args); |
0 | 176 } |
177 | |
187 | 178 |
10
26e34ae9a3e3
changed indention and line wrapping to a more consistent style
meillo@marmaro.de
parents:
0
diff
changeset
|
179 int |
26e34ae9a3e3
changed indention and line wrapping to a more consistent style
meillo@marmaro.de
parents:
0
diff
changeset
|
180 main(int argc, char *argv[]) |
0 | 181 { |
187 | 182 interface iface; |
183 gchar *name; | |
0 | 184 |
187 | 185 if (argc != 3) { |
186 fprintf(stderr, "usage: %s HOST PORT\n", argv[0]); | |
187 return 1; | |
188 } | |
0 | 189 |
187 | 190 iface.address = g_strdup(argv[1]); |
191 iface.port = atoi(argv[2]); | |
192 | |
193 name = mserver_detect_online(&iface); | |
0 | 194 |
187 | 195 if (name) { |
196 printf("%s\n", name); | |
197 return 0; | |
10
26e34ae9a3e3
changed indention and line wrapping to a more consistent style
meillo@marmaro.de
parents:
0
diff
changeset
|
198 } |
187 | 199 return 1; |
0 | 200 } |