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