masqmail

annotate src/mservdetect.c @ 222:8cddc65765bd

added support for STARTTLS wrappers added the route config option `instant_helo' which causes masqmail, as SMTP client, not to wait for the server's 220 greeting. Instead if says EHLO right at once. You'll need this for STARTTLS wrappers that usually eat the greeting line.
author meillo@marmaro.de
date Fri, 23 Jul 2010 10:57:53 +0200
parents bd7c52a36b0c
children 41958685480d
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@0 21 #include "masqmail.h"
meillo@0 22 #include "readsock.h"
meillo@0 23
meillo@0 24
meillo@187 25 gboolean
meillo@188 26 init_sockaddr2(struct sockaddr_in * name, gchar* addr, int port)
meillo@187 27 {
meillo@187 28 struct hostent *he;
meillo@187 29 struct in_addr ia;
meillo@187 30
meillo@188 31 if (inet_aton(addr, &ia) != 0) {
meillo@187 32 /* IP address */
meillo@187 33 memcpy(&(name->sin_addr), &ia, sizeof(name->sin_addr));
meillo@187 34 } else {
meillo@188 35 if ((he = gethostbyname(addr)) == NULL) {
meillo@188 36 fprintf(stderr, "local address '%s' unknown. (deleting)\n", addr);
meillo@187 37 return FALSE;
meillo@187 38 }
meillo@187 39 memcpy(&(name->sin_addr), he->h_addr, sizeof(name->sin_addr));
meillo@187 40 }
meillo@187 41 name->sin_family = AF_INET;
meillo@188 42 name->sin_port = htons(port);
meillo@187 43
meillo@187 44 return TRUE;
meillo@187 45 }
meillo@187 46
meillo@187 47
meillo@164 48 gchar*
meillo@188 49 mserver_detect_online(gchar* addr, int port)
meillo@164 50 {
meillo@164 51 struct sockaddr_in saddr;
meillo@164 52 gchar *ret = NULL;
meillo@164 53
meillo@188 54 if (!init_sockaddr2(&saddr, addr, port)) {
meillo@187 55 return NULL;
meillo@187 56 }
meillo@164 57
meillo@187 58 int sock = socket(PF_INET, SOCK_STREAM, 0);
meillo@187 59 int dup_sock;
meillo@187 60 if (connect(sock, (struct sockaddr *) (&saddr), sizeof(saddr)) != 0) {
meillo@187 61 return NULL;
meillo@187 62 }
meillo@164 63
meillo@187 64 FILE *in, *out;
meillo@187 65 char buf[256];
meillo@187 66
meillo@187 67 dup_sock = dup(sock);
meillo@187 68 out = fdopen(sock, "w");
meillo@187 69 in = fdopen(dup_sock, "r");
meillo@187 70
meillo@187 71 if (!read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) {
meillo@187 72 return NULL;
meillo@187 73 }
meillo@187 74
meillo@187 75 /* this is the protocol (reverse engineered):
meillo@188 76
meillo@188 77 S: READY
meillo@188 78 C: STAT
meillo@188 79 |
meillo@188 80 +----------------+-----------------+
meillo@188 81 | | |
meillo@188 82 S: DOWN S: UP foo:-1 S: UP foo:1
meillo@188 83 C: QUIT C: QUIT C: QUIT
meillo@188 84
meillo@188 85 -> offline -> offline -> online
meillo@188 86 `foo' gets printed
meillo@188 87
meillo@187 88 */
meillo@187 89
meillo@187 90 if (strncmp(buf, "READY", 5) == 0) {
meillo@187 91 fprintf(out, "STAT\n");
meillo@187 92 fflush(out);
meillo@187 93 if (read_sockline(in, buf, 256, 15, READSOCKL_CHUG)) {
meillo@187 94 if (strncmp(buf, "DOWN", 4) == 0) {
meillo@187 95 ret = NULL;
meillo@187 96 } else if (strncmp(buf, "UP", 2) == 0) {
meillo@187 97 gchar *p = buf + 3;
meillo@187 98 while ((*p != ':') && *p) {
meillo@187 99 p++;
meillo@187 100 }
meillo@187 101 if (*p) {
meillo@187 102 *p = '\0';
meillo@187 103 p++;
meillo@187 104 if ((atoi(p) >= 0) && *p) {
meillo@187 105 /* `UP foo:N', where `N' is a non-negative number */
meillo@187 106 ret = g_strdup(buf + 3);
meillo@164 107 }
meillo@187 108 } else {
meillo@187 109 fprintf(stderr, "unexpected response from mserver after STAT cmd: %s", buf);
meillo@164 110 }
meillo@187 111 } else {
meillo@187 112 fprintf(stderr, "unexpected response from mserver after STAT cmd: %s", buf);
meillo@164 113 }
meillo@164 114 }
meillo@164 115 }
meillo@187 116 fprintf(out, "QUIT");
meillo@187 117 fflush(out);
meillo@187 118
meillo@187 119 close(sock);
meillo@187 120 close(dup_sock);
meillo@187 121 fclose(in);
meillo@187 122 fclose(out);
meillo@187 123
meillo@164 124 return ret;
meillo@164 125 }
meillo@164 126
meillo@0 127
meillo@10 128 int
meillo@10 129 main(int argc, char *argv[])
meillo@0 130 {
meillo@188 131 gchar* addr;
meillo@188 132 int port;
meillo@187 133 gchar *name;
meillo@0 134
meillo@187 135 if (argc != 3) {
meillo@187 136 fprintf(stderr, "usage: %s HOST PORT\n", argv[0]);
meillo@187 137 return 1;
meillo@187 138 }
meillo@0 139
meillo@188 140 addr = argv[1];
meillo@188 141 port = atoi(argv[2]);
meillo@0 142
meillo@188 143 name = mserver_detect_online(addr, port);
meillo@187 144
meillo@187 145 if (name) {
meillo@10 146 printf("%s\n", name);
meillo@187 147 return 0;
meillo@10 148 }
meillo@187 149 return 1;
meillo@0 150 }