s/qmail 4.3.20
Next generation secure email transport
Loading...
Searching...
No Matches
qmail-qmqpc.c
Go to the documentation of this file.
1#include <unistd.h>
2#include <sys/types.h>
3#include <sys/socket.h>
4#include <netinet/in.h>
5#include <arpa/inet.h>
6#include "buffer.h"
7#include "getln.h"
8#include "exit.h"
9#include "stralloc.h"
10#include "readclose.h"
11#include "timeoutconn.h"
12#include "logmsg.h"
13#include "str.h"
14#include "sig.h"
15#include "ip.h"
16#include "timeout.h"
17#include "auto_qmail.h"
18#include "qmail.h"
19#include "control.h"
20#include "fmt.h"
21#include "uint_t.h"
22#include "socket_if.h"
23
24#define PORT_QMQP 628
25#define TCP_TIMEOUT 60
26
27void die_success() { _exit(0); }
28void die_perm() { _exit(31); }
29void nomem() { _exit(51); }
30void die_read() { if (errno == ENOMEM) nomem(); _exit(54); }
31void die_control() { _exit(55); }
32void die_socket() { _exit(56); }
33void die_home() { _exit(61); }
34void die_temp() { _exit(71); }
35void die_conn() { _exit(74); }
36void die_format() { _exit(91); }
37
38int lasterror = 55;
40
41ssize_t saferead(int fd,char *buf,int len)
42{
43 int r;
44 r = timeoutread(TCP_TIMEOUT,qmqpfd,buf,len);
45 if (r <= 0) die_conn();
46 return r;
47}
48
49ssize_t safewrite(int fd,char *buf,int len)
50{
51 int r;
52 r = timeoutwrite(TCP_TIMEOUT,qmqpfd,buf,len);
53 if (r <= 0) die_conn();
54 return r;
55}
56
58buffer bo = BUFFER_INIT(safewrite,-1,buf,sizeof(buf));
59buffer bi = BUFFER_INIT(saferead,-1,buf,sizeof(buf));
60buffer be = BUFFER_INIT(read,1,buf,sizeof(buf)); // envelope
61/* WARNING: can use only one of these at a time! */
62
63stralloc beforemessage = {0};
64stralloc message = {0};
65stralloc aftermessage = {0};
66
67char strnum[FMT_ULONG];
68stralloc line = {0};
69
70void getmess()
71{
72 int match;
73
74 if (readclose_append(0,&message,BUFSIZE_LINE) == -1) die_read();
75
76 strnum[fmt_ulong(strnum,(unsigned long) message.len)] = 0;
78 if (!stralloc_cats(&beforemessage,":")) nomem();
79 if (!stralloc_copys(&aftermessage,",")) nomem();
80
81 if (getln(&be,&line,&match,'\0') == -1) die_read();
82 if (!match) die_format();
83 if (line.len < 2) die_format();
84 if (line.s[0] != 'F') die_format();
85
86 strnum[fmt_ulong(strnum,(unsigned long) line.len - 2)] = 0;
87 if (!stralloc_cats(&aftermessage,strnum)) nomem();
88 if (!stralloc_cats(&aftermessage,":")) nomem();
89 if (!stralloc_catb(&aftermessage,line.s + 1,line.len - 2)) nomem();
90 if (!stralloc_cats(&aftermessage,",")) nomem();
91
92 for (;;) {
93 if (getln(&be,&line,&match,'\0') == -1) die_read();
94 if (!match) die_format();
95 if (line.len < 2) break;
96 if (line.s[0] != 'T') die_format();
97
98 strnum[fmt_ulong(strnum,(unsigned long) line.len - 2)] = 0;
99 if (!stralloc_cats(&aftermessage,strnum)) nomem();
100 if (!stralloc_cats(&aftermessage,":")) nomem();
101 if (!stralloc_catb(&aftermessage,line.s + 1,line.len - 2)) nomem();
102 if (!stralloc_cats(&aftermessage,",")) nomem();
103 }
104}
105
106void doit(char *server)
107{
108 struct ip4_address ip4s;
109 struct ip6_address ip6s;
110 char *netif = 0;
111 uint32 ifidx = 0;
112 char ch;
113 int i, j, r;
114
115 i = str_chr(server,':');
116 if (server[i] == ':') {
117 j = str_chr(server,'%'); /* IF index */
118 if (server[j] == '%') {
119 server[j] = 0;
120 netif = &server[j + 1];
121 ifidx = socket_getifidx(netif);
122 }
123 if (!ip6_scan(server,(char *)&ip6s.d)) return;
124 qmqpfd = socket(AF_INET6,SOCK_STREAM,0);
125 if (qmqpfd == -1) die_socket();
126 r = timeoutconn6(qmqpfd,(char *)&ip6s.d,PORT_QMQP,10,ifidx);
127 } else {
128 if (!ip4_scan(server,(char *)&ip4s.d)) return;
129 qmqpfd = socket(AF_INET,SOCK_STREAM,0);
130 if (qmqpfd == -1) die_socket();
131 r = timeoutconn4(qmqpfd,(char *)&ip4s.d,PORT_QMQP,10);
132 }
133 if (r != 0) {
134 lasterror = 73;
135 if (errno == ETIMEDOUT) lasterror = 72;
136 close(qmqpfd);
137 return;
138 }
139
140 strnum[fmt_ulong(strnum,(unsigned long) (beforemessage.len + message.len + aftermessage.len))] = 0;
141 buffer_puts(&bo,strnum);
142 buffer_puts(&bo,":");
143 buffer_put(&bo,beforemessage.s,beforemessage.len);
144 buffer_put(&bo,message.s,message.len);
145 buffer_put(&bo,aftermessage.s,aftermessage.len);
146 buffer_puts(&bo,",");
147 buffer_flush(&bo);
148
149 for (;;) {
150 buffer_get(&bi,&ch,1);
151 if (ch == 'K') die_success();
152 if (ch == 'Z') die_temp();
153 if (ch == 'D') die_perm();
154 }
155}
156
157stralloc servers = {0};
158
159int main()
160{
161 int i;
162 int j;
163
164 sig_pipeignore();
165
166 if (chdir(auto_qmail) == -1) die_home();
167 if (control_init() == -1) die_control();
168 if (control_readfile(&servers,"control/qmqpservers",0) != 1) die_control();
169
170 getmess();
171
172 i = 0;
173 for (j = 0; j < servers.len; ++j)
174 if (!servers.s[j]) {
175 doit(servers.s + i);
176 i = j + 1;
177 }
178
180}
char auto_qmail[]
int control_readfile(stralloc *sa, char *fn, int flagme)
Definition: control.c:87
int control_init(void)
Definition: control.c:33
int stralloc_copys(stralloc *, char const *)
void _exit(int)
int match
Definition: matchup.c:196
int fd
void die_control()
Definition: qmail-qmqpc.c:31
ssize_t saferead(int fd, char *buf, int len)
Definition: qmail-qmqpc.c:41
void die_home()
Definition: qmail-qmqpc.c:33
void die_format()
Definition: qmail-qmqpc.c:36
void die_socket()
Definition: qmail-qmqpc.c:32
buffer be
Definition: qmail-qmqpc.c:60
char strnum[FMT_ULONG]
Definition: qmail-qmqpc.c:67
#define PORT_QMQP
Definition: qmail-qmqpc.c:24
void getmess()
Definition: qmail-qmqpc.c:70
stralloc aftermessage
Definition: qmail-qmqpc.c:65
char buf[BUFSIZE_LINE]
Definition: qmail-qmqpc.c:57
#define TCP_TIMEOUT
Definition: qmail-qmqpc.c:25
void nomem()
Definition: qmail-qmqpc.c:29
void die_temp()
Definition: qmail-qmqpc.c:34
void die_read()
Definition: qmail-qmqpc.c:30
void doit(char *server)
Definition: qmail-qmqpc.c:106
int lasterror
Definition: qmail-qmqpc.c:38
stralloc line
Definition: qmail-qmqpc.c:68
buffer bi
Definition: qmail-qmqpc.c:59
ssize_t safewrite(int fd, char *buf, int len)
Definition: qmail-qmqpc.c:49
stralloc servers
Definition: qmail-qmqpc.c:157
void die_conn()
Definition: qmail-qmqpc.c:35
void die_success()
Definition: qmail-qmqpc.c:27
buffer bo
Definition: qmail-qmqpc.c:58
int qmqpfd
Definition: qmail-qmqpc.c:39
int main()
Definition: qmail-qmqpc.c:159
void die_perm()
Definition: qmail-qmqpc.c:28
stralloc beforemessage
Definition: qmail-qmqpc.c:63
uint32 ifidx
Definition: qmail-remote.c:92
int j
Definition: qmail-send.c:926
#define BUFSIZE_LINE
Definition: qmail.h:8