59 #include <sys/socket.h>
60 #include <netinet/in.h>
61 #include <arpa/inet.h>
73 #ifdef STRCASECMP_IN_STRINGS_H
114 #define SMFIC_ABORT 'A'
115 #define SMFIC_BODY 'B'
116 #define SMFIC_CONNECT 'C'
117 #define SMFIC_MACRO 'D'
118 #define SMFIC_BODYEOB 'E'
119 #define SMFIC_HELO 'H'
120 #define SMFIC_HEADER 'L'
121 #define SMFIC_MAIL 'M'
122 #define SMFIC_EOH 'N'
123 #define SMFIC_OPTNEG 'O'
124 #define SMFIC_QUIT 'Q'
125 #define SMFIC_RCPT 'R'
126 #define SMFIC_DATA 'T'
127 #define SMFIC_UNKNOWN 'U'
129 #define SMFIC_QUIT_NC 'K'
154 #define SMFIR_ADDRCPT '+'
155 #define SMFIR_DELRCPT '-'
156 #define SMFIR_ACCEPT 'a'
157 #define SMFIR_REPLBODY 'b'
158 #define SMFIR_CONTINUE 'c'
159 #define SMFIR_DISCARD 'd'
160 #define SMFIR_CONN_FAIL 'f'
161 #define SMFIR_CHGHEADER 'm'
162 #define SMFIR_PROGRESS 'p'
163 #define SMFIR_REJECT 'r'
164 #define SMFIR_TEMPFAIL 't'
165 #define SMFIR_SHUTDOWN '4'
166 #define SMFIR_ADDHEADER 'h'
167 #define SMFIR_INSHEADER 'i'
168 #define SMFIR_REPLYCODE 'y'
169 #define SMFIR_QUARANTINE 'q'
171 #define SMFIR_SKIP 's'
172 #define SMFIR_CHGFROM 'e'
173 #define SMFIR_ADDRCPT_PAR '2'
174 #define SMFIR_SETSYMLIST 'l'
205 #define SMFIP_NOCONNECT (1L<<0)
206 #define SMFIP_NOHELO (1L<<1)
207 #define SMFIP_NOMAIL (1L<<2)
208 #define SMFIP_NORCPT (1L<<3)
209 #define SMFIP_NOBODY (1L<<4)
210 #define SMFIP_NOHDRS (1L<<5)
211 #define SMFIP_NOEOH (1L<<6)
212 #define SMFIP_NR_HDR (1L<<7)
213 #define SMFIP_NOHREPL SMFIP_NR_HDR
214 #define SMFIP_NOUNKNOWN (1L<<8)
215 #define SMFIP_NODATA (1L<<9)
217 #define SMFIP_SKIP (1L<<10)
218 #define SMFIP_RCPT_REJ (1L<<11)
219 #define SMFIP_NR_CONN (1L<<12)
220 #define SMFIP_NR_HELO (1L<<13)
221 #define SMFIP_NR_MAIL (1L<<14)
222 #define SMFIP_NR_RCPT (1L<<15)
223 #define SMFIP_NR_DATA (1L<<16)
224 #define SMFIP_NR_UNKN (1L<<17)
225 #define SMFIP_NR_EOH (1L<<18)
226 #define SMFIP_NR_BODY (1L<<19)
227 #define SMFIP_HDR_LEADSPC (1L<<20)
229 #define SMFIP_NOSEND_MASK \
230 (SMFIP_NOCONNECT | SMFIP_NOHELO | SMFIP_NOMAIL | SMFIP_NORCPT \
231 | SMFIP_NOBODY | SMFIP_NOHDRS | SMFIP_NOEOH | SMFIP_NOUNKNOWN \
234 #define SMFIP_NOREPLY_MASK \
235 (SMFIP_NR_CONN | SMFIP_NR_HELO | SMFIP_NR_MAIL | SMFIP_NR_RCPT \
236 | SMFIP_NR_DATA | SMFIP_NR_UNKN | SMFIP_NR_HDR | SMFIP_NR_EOH | \
269 #define SMFIF_ADDHDRS (1L<<0)
270 #define SMFIF_CHGBODY (1L<<1)
271 #define SMFIF_ADDRCPT (1L<<2)
272 #define SMFIF_DELRCPT (1L<<3)
273 #define SMFIF_CHGHDRS (1L<<4)
274 #define SMFIF_QUARANTINE (1L<<5)
276 #define SMFIF_CHGFROM (1L<<6)
277 #define SMFIF_ADDRCPT_PAR (1L<<7)
278 #define SMFIF_SETSYMLIST (1L<<8)
297 #define SMFIA_UNKNOWN 'U'
298 #define SMFIA_UNIX 'L'
299 #define SMFIA_INET '4'
300 #define SMFIA_INET6 '6'
306 #define SMFIM_CONNECT 0
308 #define SMFIM_ENVFROM 2
309 #define SMFIM_ENVRCPT 3
329 static const size_t milter8_macro_offsets[] = {
339 #define MILTER8_MACRO_PTR(__macros, __class) \
340 ((char **) (((char *) (__macros)) + milter8_macro_offsets[(__class)]))
345 #define MILTER_CHUNK_SIZE 65535
382 #define LIBMILTER_AUTO_DISCONNECT
389 #define MILTER8_STAT_ERROR 1
390 #define MILTER8_STAT_CLOSED 2
391 #define MILTER8_STAT_READY 3
392 #define MILTER8_STAT_ENVELOPE 4
393 #define MILTER8_STAT_MESSAGE 5
394 #define MILTER8_STAT_ACCEPT_CON 6
395 #define MILTER8_STAT_ACCEPT_MSG 7
396 #define MILTER8_STAT_REJECT_CON 8
403 #define MILTER8_DATA_END 0
404 #define MILTER8_DATA_HLONG 1
405 #define MILTER8_DATA_BUFFER 2
406 #define MILTER8_DATA_STRING 3
407 #define MILTER8_DATA_NSHORT 4
408 #define MILTER8_DATA_ARGV 5
409 #define MILTER8_DATA_OCTET 6
410 #define MILTER8_DATA_MORE 7
415 #define XXX_MAX_DATA (INT_MAX / 2)
416 #define XXX_TIMEOUT 10
428 #define MILTER8_V2_PROTO_MASK \
429 (SMFIP_NOCONNECT | SMFIP_NOHELO | SMFIP_NOMAIL | SMFIP_NORCPT | \
430 SMFIP_NOBODY | SMFIP_NOHDRS | SMFIP_NOEOH)
435 #define MILTER8_V3_PROTO_MASK (MILTER8_V2_PROTO_MASK | SMFIP_NOUNKNOWN)
436 #define MILTER8_V4_PROTO_MASK (MILTER8_V3_PROTO_MASK | SMFIP_NODATA)
437 #define MILTER8_V6_PROTO_MASK \
438 (MILTER8_V4_PROTO_MASK | SMFIP_SKIP | SMFIP_RCPT_REJ \
439 | SMFIP_NOREPLY_MASK | SMFIP_HDR_LEADSPC)
456 static const NAME_CODE milter8_event_masks[] = {
471 static const NAME_CODE milter8_versions[] = {
476 "no_header_reply", 0,
482 #define STR(x) vstring_str(x)
483 #define LEN(x) VSTRING_LEN(x)
487 static const char *milter8_def_reply(
MILTER8 *milter,
const char *reply)
497 static int milter8_conf_error(
MILTER8 *milter)
509 if (milter->
fp != 0) {
519 reply =
"451 4.3.5 Server configuration problem - try again later";
521 milter8_def_reply(milter, reply);
527 static int milter8_comm_error(
MILTER8 *milter)
539 if (milter->
fp != 0) {
547 reply =
"550 5.5.0 Service unavailable";
549 reply =
"451 4.7.1 Service unavailable - try again later";
553 msg_warn(
"milter %s: unrecognized default action: %s",
555 reply =
"451 4.3.5 Server configuration problem - try again later";
557 milter8_def_reply(milter, reply);
563 static void milter8_close_stream(
MILTER8 *milter)
565 if (milter->
fp != 0) {
574 static int milter8_read_resp(
MILTER8 *milter,
int event,
unsigned char *command,
579 const char *smfic_name;
588 msg_warn(
"milter %s: can't read %s reply packet header: %m",
589 milter->
m.
name, smfic_name != 0 ?
590 smfic_name :
"(unknown MTA event)");
591 return (milter8_comm_error(milter));
592 }
else if ((pkt_len = ntohl(len)) < 1) {
593 msg_warn(
"milter %s: bad packet length: %ld",
594 milter->
m.
name, (
long) pkt_len);
595 return (milter8_comm_error(milter));
597 msg_warn(
"milter %s: unreasonable packet length: %ld > %ld",
599 return (milter8_comm_error(milter));
606 msg_warn(
"milter %s: EOF while reading command code: %m",
608 return (milter8_comm_error(milter));
616 *data_len = pkt_len - 1;
621 static int milter8_read_data(
MILTER8 *milter, ssize_t *data_len,...);
625 static int vmilter8_read_data(
MILTER8 *milter, ssize_t *data_len, va_list ap)
627 const char *myname =
"milter8_read_data";
642 msg_warn(
"milter %s: input packet too short for network long",
644 return (milter8_comm_error(milter));
649 msg_warn(
"milter %s: EOF while reading network long: %m",
651 return (milter8_comm_error(milter));
654 *host_long_ptr = ntohl(net_long);
662 msg_warn(
"milter %s: no data in input packet", milter->
m.
name);
663 return (milter8_comm_error(milter));
670 msg_warn(
"milter %s: EOF while reading data: %m", milter->
m.
name);
671 return (milter8_comm_error(milter));
682 msg_warn(
"milter %s: packet too short for string",
684 return (milter8_comm_error(milter));
690 msg_warn(
"%s: milter %s: EOF while reading string: %m",
691 myname, milter->
m.
name);
692 return (milter8_comm_error(milter));
698 if (*data_len <= 0) {
699 msg_warn(
"%s: milter %s: missing string null termimator",
700 myname, milter->
m.
name);
701 return (milter8_comm_error(milter));
711 msg_panic(
"%s: unknown argument type: %d", myname, arg_type);
720 msg_warn(
"%s: left-over data %ld bytes", myname, (
long) *data_len);
721 return (milter8_comm_error(milter));
724 msg_panic(
"%s: bad left-over data count %ld",
725 myname, (
long) *data_len);
731 static int milter8_read_data(
MILTER8 *milter, ssize_t *data_len,...)
736 va_start(ap, data_len);
737 ret = vmilter8_read_data(milter, data_len, ap);
744 static ssize_t vmilter8_size_data(va_list ap)
746 const char *myname =
"vmilter8_size_data";
756 for (data_len = 0; (arg_type = va_arg(ap,
int)) > 0; ) {
772 data_len +=
LEN(buf);
779 str = va_arg(ap,
char *);
780 data_len += strlen(str) + 1;
787 for (cpp = va_arg(ap,
const char **); *cpp; cpp++)
788 data_len += strlen(*cpp) + 1;
795 (void) va_arg(ap,
unsigned);
803 (void) va_arg(ap,
unsigned);
811 msg_panic(
"%s: bad argument type: %d", myname, arg_type);
820 static int vmilter8_write_cmd(
MILTER8 *milter,
int command, ssize_t data_len,
823 const char *myname =
"vmilter8_write_cmd";
837 if ((pkt_len = 1 + data_len) < 1)
838 msg_panic(
"%s: bad packet length %d", myname, pkt_len);
839 pkt_len = htonl(pkt_len);
842 while ((arg_type = va_arg(ap,
int)) > 0) {
850 net_long = htonl(host_long);
866 str = va_arg(ap,
char *);
874 ch = va_arg(ap,
unsigned);
882 for (cpp = va_arg(ap,
const char **); *cpp; cpp++)
890 net_short = va_arg(ap,
unsigned);
898 msg_panic(
"%s: bad argument type: %d", myname, arg_type);
905 msg_warn(
"milter %s: error writing command: %m", milter->
m.
name);
906 milter8_comm_error(milter);
916 static int milter8_write_cmd(
MILTER8 *milter,
int command,...)
926 va_start(ap, command);
932 data_len = vmilter8_size_data(ap);
938 err = vmilter8_write_cmd(milter, command, data_len, ap2);
946 static const char *milter8_event(
MILTER8 *milter,
int event,
951 const char *myname =
"milter8_event";
958 const char *smfic_name;
959 const char *smfir_name;
962 const char *edit_resp = 0;
963 const char *retval = 0;
966 int body_edit_lockout = 0;
968 #define DONT_SKIP_REPLY 0
974 msg_warn(
"%s: attempt to send event %s to milter %s after error",
977 smfic_name :
"(unknown MTA event)", milter->
m.
name);
984 if ((skip_event_flag & milter->
np_mask) != 0) {
986 msg_info(
"skipping non-protocol event %s for milter %s",
988 smfic_name :
"(unknown MTA event)", milter->
m.
name);
998 msg_info(
"skipping event %s after SMFIR_SKIP from milter %s",
1000 smfic_name :
"(unknown MTA event)", milter->
m.
name);
1018 if (macros->
argc > 0) {
1021 for (cpp = macros->
argv; *cpp && cpp[1]; cpp += 2)
1027 smfic_name :
"(unknown MTA event)", *
STR(buf) ?
1028 STR(buf) :
" (none)");
1042 if ((skip_event_flag & milter->
ev_mask) != 0) {
1044 msg_info(
"skipping event %s for milter %s",
1046 smfic_name :
"(unknown MTA event)", milter->
m.
name);
1053 va_start(ap, macros);
1060 data_len = vmilter8_size_data(ap);
1066 err = vmilter8_write_cmd(milter, event, data_len, ap2);
1082 msg_info(
"skipping reply for event %s from milter %s",
1084 smfic_name :
"(unknown MTA event)", milter->
m.
name);
1107 #define IN_CONNECT_EVENT(e) ((e) == SMFIC_CONNECT || (e) == SMFIC_HELO)
1113 #define MILTER8_EVENT_BREAK(s) { \
1125 if (milter8_read_resp(milter, event, &cmd, &data_size) != 0)
1128 msg_info(
"reply: %s data %ld bytes",
1130 smfir_name :
"unknown", (
long) data_size);
1145 if (edit_resp == 0 &&
LEN(body_line_buf) > 0)
1153 body_edit_lockout = 1;
1184 #ifdef LIBMILTER_AUTO_DISCONNECT
1185 milter8_close_stream(milter);
1205 msg_warn(
"milter %s: DISCARD action is not allowed "
1206 "for connect or helo", milter->
m.
name);
1222 #ifdef LIBMILTER_AUTO_DISCONNECT
1223 milter8_close_stream(milter);
1239 #ifdef LIBMILTER_AUTO_DISCONNECT
1240 milter8_close_stream(milter);
1244 "451 4.7.1 Service unavailable - try again later"));
1256 #ifdef LIBMILTER_AUTO_DISCONNECT
1257 milter8_close_stream(milter);
1273 if (milter8_read_data(milter, &data_size,
1278 if ((
STR(milter->
buf)[0] !=
'4' &&
STR(milter->
buf)[0] !=
'5')
1281 || (
STR(milter->
buf)[3] !=
' ' &&
STR(milter->
buf)[3] !=
'-')
1284 msg_warn(
"milter %s: malformed reply: %s",
1286 milter8_conf_error(milter);
1289 if ((rp = cp = strchr(
STR(milter->
buf),
'%')) != 0) {
1291 if ((ch = *cp++) ==
'%')
1299 for (cp =
STR(milter->
buf); ; cp = next) {
1305 if ((next = strstr(cp,
"\r\n")) == 0)
1311 #ifdef LIBMILTER_AUTO_DISCONNECT
1312 milter8_close_stream(milter);
1328 if (milter8_read_data(milter, &data_size,
1332 milter8_def_reply(milter,
"H");
1351 #define MILTER8_HDR_SPACE(m) (((m)->ev_mask & SMFIP_HDR_LEADSPC) ? "" : " ")
1358 if (milter8_read_data(milter, &data_size,
1370 if ((ssize_t) index < 1) {
1371 msg_warn(
"milter %s: bad change header index: %ld",
1372 milter->
m.
name, (
long) index);
1373 milter8_conf_error(milter);
1376 if (
LEN(milter->
buf) == 0) {
1377 msg_warn(
"milter %s: null change header name",
1379 milter8_conf_error(milter);
1398 if (milter8_read_data(milter, &data_size,
1419 if (milter8_read_data(milter, &data_size,
1428 if ((ssize_t) index + 1 < 1) {
1429 msg_warn(
"milter %s: bad insert header index: %ld",
1430 milter->
m.
name, (
long) index);
1431 milter8_conf_error(milter);
1435 (ssize_t) index + 1,
1446 if (milter8_read_data(milter, &data_size,
1450 if (data_size > 0) {
1451 if (milter8_read_data(milter, &data_size,
1471 if (milter8_read_data(milter, &data_size,
1487 if (milter8_read_data(milter, &data_size,
1491 if (data_size > 0) {
1492 if (milter8_read_data(milter, &data_size,
1512 if (milter8_read_data(milter, &data_size,
1528 if (body_edit_lockout) {
1529 msg_warn(
"milter %s: body replacement requests can't "
1530 "currently be mixed with other requests",
1532 milter8_conf_error(milter);
1535 if (milter8_read_data(milter, &data_size,
1543 if (body_line_buf == 0) {
1550 for (cp =
STR(milter->
body); edit_resp == 0
1552 ch = *(
unsigned char *) cp;
1554 if (
LEN(body_line_buf) > 0
1557 LEN(body_line_buf) - 1);
1569 msg_warn(
"milter %s: unexpected filter response %s after event %s",
1572 smfir_name :
"(unknown filter reply)",
1574 smfic_name :
"(unknown MTA event)");
1575 milter8_comm_error(milter);
1583 msg_warn(
"milter %s: reply %s was followed by %ld data bytes",
1585 smfir_name :
"unknown", (
long) data_len);
1586 milter8_comm_error(milter);
1603 if (edit_resp && (retval == 0 || strchr(
"DS4", retval[0]) == 0))
1610 static void milter8_connect(
MILTER8 *milter)
1612 const char *myname =
"milter8_connect";
1617 int (*connect_fn) (
const char *,
int,
int);
1629 char *saved_version;
1636 if (milter->
fp != 0)
1637 msg_panic(
"%s: milter %s: socket is not closed",
1638 myname, milter->
m.
name);
1659 if ((mask =
name_code(milter8_event_masks,
1663 || (vers != 0 && my_version != 0)) {
1664 msg_warn(
"milter %s: bad protocol information: %s",
1665 milter->
m.
name, name);
1666 milter8_conf_error(milter);
1674 if (my_events == 0 || my_version == 0) {
1675 msg_warn(
"milter %s: no protocol version information", milter->
m.
name);
1676 milter8_conf_error(milter);
1685 msg_info(
"%s: non-protocol events for protocol version %d: %s",
1693 #define FREE_TRANSPORT_AND_BAIL_OUT(milter, milter_error) do { \
1694 myfree(transport); \
1695 milter_error(milter); \
1700 if ((endpoint =
split_at(transport,
':')) == 0
1701 || *endpoint == 0 || *transport == 0) {
1702 msg_warn(
"Milter service needs transport:endpoint instead of \"%s\"",
1707 msg_info(
"%s: transport=%s endpoint=%s", myname, transport, endpoint);
1708 if (strcmp(transport,
"inet") == 0) {
1710 }
else if (strcmp(transport,
"unix") == 0) {
1712 }
else if (strcmp(transport,
"local") == 0) {
1715 msg_warn(
"invalid transport name: %s in Milter service: %s",
1716 transport, milter->
m.
name);
1724 msg_warn(
"connect to Milter service %s: %m", milter->
m.
name);
1742 msg_info(
"%s: my_version=0x%lx", myname, (
long) my_version);
1743 msg_info(
"%s: my_actions=0x%lx %s", myname, (
long) my_actions,
1746 msg_info(
"%s: my_events=0x%lx %s", myname, (
long) my_events,
1756 msg_warn(
"milter %s: write error in initial handshake",
1765 if (milter8_read_resp(milter,
SMFIC_OPTNEG, &cmd, &data_len) != 0) {
1766 msg_warn(
"milter %s: read error in initial handshake", milter->
m.
name);
1771 msg_warn(
"milter %s: unexpected reply \"%c\" in initial handshake",
1772 milter->
m.
name, cmd);
1773 (void) milter8_comm_error(milter);
1776 if (milter8_read_data(milter, &data_len,
1781 msg_warn(
"milter %s: read error in initial handshake", milter->
m.
name);
1785 if (milter->
version > my_version) {
1786 msg_warn(
"milter %s: protocol version %d conflict"
1787 " with MTA protocol version %d",
1789 (void) milter8_comm_error(milter);
1793 msg_warn(
"milter %s: request mask 0x%x conflict"
1794 " with MTA request mask 0x%lx",
1796 (void) milter8_comm_error(milter);
1812 if (milter->
version < my_version) {
1816 for (np = milter8_event_masks; ; np++) {
1817 if (np->
name == 0) {
1818 msg_warn(
"milter %s: unexpected protocol version %d",
1822 if ((version = atoi(np->
name)) > 0 && version <= milter->version) {
1825 msg_info(
"%s: non-protocol events for milter %s"
1826 " protocol version %d: %s",
1829 "non-protocol event mask",
1842 msg_info(
"milter %s: event mask 0x%x includes features not"
1843 " offered in MTA event mask 0x%lx",
1845 msg_info(
"%s: milter %s version %d",
1850 msg_info(
"%s: requests %s", myname,
1855 milter8_def_reply(milter, 0);
1864 const char *smfim_name;
1865 char **mac_value_ptr;
1870 && milter8_read_data(milter, &data_len,
1875 if (smfim_name == 0) {
1876 msg_warn(
"milter %s: ignoring unknown macro type %u",
1877 milter->
m.
name, (
unsigned) mac_type);
1880 msg_info(
"override %s macro list with \"%s\"",
1881 smfim_name,
STR(buf));
1895 static const char *milter8_conn_event(
MILTER *m,
1896 const char *client_name,
1897 const char *client_addr,
1898 const char *client_port,
1899 unsigned addr_family,
1902 const char *myname =
"milter8_conn_event";
1906 const char *sm_name;
1914 #define XXX_UNKNOWN "unknown"
1915 #define STR_EQ(x,y) (strcmp((x), (y)) == 0)
1916 #define STR_NE(x,y) (strcmp((x), (y)) != 0)
1923 #ifdef LIBMILTER_AUTO_DISCONNECT
1924 milter8_connect(milter);
1930 switch (milter->
state) {
1937 msg_info(
"%s: milter %s: connect %s/%s",
1938 myname, milter->
m.
name, client_name, client_addr);
1939 if (client_port == 0) {
1941 }
else if (!
alldig(client_port) || (port = atoi(client_port)) < 0
1943 msg_warn(
"milter %s: bad client port number %s",
1944 milter->
m.
name, client_port);
1952 (ptr =
concatenate(
"[", client_addr,
"]", (
char *) 0)));
1953 switch (addr_family) {
1995 msg_panic(
"%s: milter %s: bad state %d",
2002 static const char *milter8_helo_event(
MILTER *m,
const char *helo_name,
2006 const char *myname =
"milter8_helo_event";
2013 switch (milter->
state) {
2025 myname, milter->
m.
name, helo_name);
2032 msg_panic(
"%s: milter %s: bad state %d",
2039 static const char *milter8_mail_event(
MILTER *m,
const char **argv,
2042 const char *myname =
"milter8_mail_event";
2050 switch (milter->
state) {
2061 for (cpp = argv; *cpp; cpp++)
2073 msg_panic(
"%s: milter %s: bad state %d",
2080 static const char *milter8_rcpt_event(
MILTER *m,
const char **argv,
2083 const char *myname =
"milter8_rcpt_event";
2091 switch (milter->
state) {
2103 for (cpp = argv; *cpp; cpp++)
2115 msg_panic(
"%s: milter %s: bad state %d",
2122 static const char *milter8_data_event(
MILTER *m,
ARGV *macros)
2124 const char *myname =
"milter8_data_event";
2131 switch (milter->
state) {
2141 msg_info(
"%s: milter %s: data command", myname, milter->
m.
name);
2147 msg_panic(
"%s: milter %s: bad state %d",
2154 static const char *milter8_unknown_event(
MILTER *m,
const char *command,
2157 const char *myname =
"milter8_unknown_event";
2164 switch (milter->
state) {
2174 msg_info(
"%s: milter %s: unknown command: %s",
2175 myname, milter->
m.
name, command);
2183 msg_panic(
"%s: milter %s: bad state %d",
2190 static const char *milter8_other_event(
MILTER *m)
2192 const char *myname =
"milter8_other_event";
2205 static void milter8_abort(
MILTER *m)
2207 const char *myname =
"milter8_abort";
2215 switch (milter->
state) {
2235 msg_panic(
"%s: milter %s: bad state %d",
2242 static void milter8_disc_event(
MILTER *m)
2244 const char *myname =
"milter8_disc_event";
2252 switch (milter->
state) {
2257 #ifdef LIBMILTER_AUTO_DISCONNECT
2262 msg_info(
"%s: skip quit milter %s", myname, milter->
m.
name);
2266 #ifndef LIBMILTER_AUTO_DISCONNECT
2276 #ifdef LIBMILTER_AUTO_DISCONNECT
2277 milter8_close_stream(milter);
2282 milter8_def_reply(milter, 0);
2301 static void milter8_header(
void *ptr,
int unused_header_class,
2303 VSTRING *buf, off_t unused_offset)
2305 const char *myname =
"milter8_header";
2317 #define MILTER8_MESSAGE_DONE(milter, msg_ctx) \
2318 ((milter)->state != MILTER8_STAT_MESSAGE || (msg_ctx)->resp != 0)
2340 for (cpp = msg_ctx->
auto_hdrs->
argv, done = 1; *cpp; cpp++, done <<= 1)
2341 if ((msg_ctx->
auto_done & done) == 0 && strcmp(*cpp,
STR(buf)) == 0) {
2353 msg_info(
"%s: header milter %s: %.100s",
2355 cp =
STR(buf) + (header_info ? strlen(header_info->
name) :
2358 while (*cp ==
' ' || *cp ==
'\t')
2361 msg_panic(
"%s: header label not followed by ':'", myname);
2377 static void milter8_eoh(
void *ptr)
2379 const char *myname =
"milter8_eoh";
2397 static void milter8_body(
void *ptr,
int rec_type,
2398 const char *buf, ssize_t len,
2401 const char *myname =
"milter8_body";
2405 const char *bp = buf;
2435 msg_info(
"%s: body milter %s: %.100s", myname, milter->
m.
name, buf);
2448 myname, (
long)
LEN(milter->
body));
2449 count = (todo > space ? space : todo);
2475 static void milter8_eob(
void *ptr)
2477 const char *myname =
"milter8_eob";
2516 static const char *milter8_message(
MILTER *m,
VSTREAM *qfile,
2522 const char *myname =
"milter8_message";
2532 switch (milter->
state) {
2538 msg_info(
"%s: skip message to milter %s", myname, milter->
m.
name);
2542 msg_info(
"%s: message to milter %s", myname, milter->
m.
name);
2544 saved_errno = errno;
2547 return (saved_errno == EFBIG ?
2548 "552 5.3.4 Message file too big" :
2549 "451 4.3.0 Queue file write error");
2584 if ((rec_type =
rec_get(qfile, buf, 0)) < 0) {
2585 msg_warn(
"%s: error reading %s: %m",
2587 msg_ctx.
resp =
"450 4.3.0 Queue file write error";
2595 msg_warn(
"%s: MIME problem %s in %s",
2597 msg_ctx.
resp =
"450 4.3.0 Queue file write error";
2615 return (msg_ctx.
resp);
2617 msg_panic(
"%s: milter %s: bad state %d",
2626 #define MAIL_ATTR_MILT_NAME "milter_name"
2627 #define MAIL_ATTR_MILT_VERS "milter_version"
2628 #define MAIL_ATTR_MILT_ACTS "milter_actions"
2629 #define MAIL_ATTR_MILT_EVTS "milter_events"
2630 #define MAIL_ATTR_MILT_NPTS "milter_non_events"
2631 #define MAIL_ATTR_MILT_STAT "milter_state"
2632 #define MAIL_ATTR_MILT_CONN "milter_conn_timeout"
2633 #define MAIL_ATTR_MILT_CMD "milter_cmd_timeout"
2634 #define MAIL_ATTR_MILT_MSG "milter_msg_timeout"
2635 #define MAIL_ATTR_MILT_ACT "milter_action"
2636 #define MAIL_ATTR_MILT_MAC "milter_macro_list"
2640 static int milter8_active(
MILTER *m)
2644 return (milter->
fp != 0
2653 const char *myname =
"milter8_send";
2689 #ifdef CANT_WRITE_BEFORE_SENDING_FD
2698 #ifdef MUST_READ_AFTER_SENDING_FD
2709 static MILTER8 *milter8_alloc(
const char *,
int,
int,
int,
const char *,
2716 const char *myname =
"milter8_receive";
2732 #define FREE_MACROS_AND_RETURN(x) do { \
2734 milter_macros_free(macros); \
2738 if (name_buf == 0) {
2765 #ifdef CANT_WRITE_BEFORE_SENDING_FD
2775 #ifdef MUST_READ_AFTER_SENDING_FD
2780 #define NO_PROTOCOL ((char *) 0)
2785 milter = milter8_alloc(
STR(name_buf), conn_timeout, cmd_timeout,
2796 milter->
state = state;
2797 return (&milter->
m);
2803 static void milter8_free(
MILTER *m)
2826 static MILTER8 *milter8_alloc(
const char *name,
int conn_timeout,
2827 int cmd_timeout,
int msg_timeout,
2828 const char *protocol,
2829 const char *def_action,
2848 milter->
m.
message = milter8_message;
2851 milter->
m.
abort = milter8_abort;
2853 milter->
m.
active = milter8_active;
2854 milter->
m.
send = milter8_send;
2855 milter->
m.
free = milter8_free;
2877 int msg_timeout,
const char *protocol,
2878 const char *def_action,
MILTERS *parent)
2885 milter = milter8_alloc(name, conn_timeout, cmd_timeout, msg_timeout,
2886 protocol, def_action, parent);
2893 #ifndef LIBMILTER_AUTO_DISCONNECT
2894 milter8_connect(milter);
2896 return (&milter->
m);
MILTER_EDIT_BODY_FN repl_body
#define MAIL_ATTR_MILT_MAC
#define MAIL_ATTR_MILT_ACT
MILTER_EDIT_RCPT_FN del_rcpt
struct MILTER_MACROS * macros
#define CA_VSTREAM_CTL_TIMEOUT(v)
const char *(* conn_event)(struct MILTER *, const char *, const char *, const char *, unsigned, ARGV *)
#define MAIL_ATTR_MILT_NPTS
char * mystrdup(const char *str)
#define FREE_MACROS_AND_RETURN(x)
#define MILTER8_DATA_OCTET
MIME_STATE * mime_state_alloc(int flags, MIME_STATE_HEAD_OUT head_out, MIME_STATE_ANY_END head_end, MIME_STATE_BODY_OUT body_out, MIME_STATE_ANY_END body_end, MIME_STATE_ERR_PRINT err_print, void *context)
#define MILTER_MACROS_ALLOC_EMPTY
MILTER_EDIT_HEADER_FN ins_header
#define MILTER8_V3_PROTO_MASK
#define MILTER8_DATA_ARGV
const char *(* helo_event)(struct MILTER *, const char *, int, ARGV *)
NORETURN msg_panic(const char *fmt,...)
MILTER_EDIT_RCPT_PAR_FN add_rcpt_par
#define MILTER8_DATA_MORE
#define MILTER8_MESSAGE_DONE(milter, msg_ctx)
#define MAIL_ATTR_MILT_MSG
#define MILTER8_STAT_ACCEPT_MSG
int milter_macros_print(ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *)
#define MILTER8_V6_PROTO_MASK
void milter_macros_free(MILTER_MACROS *)
#define FREE_TRANSPORT_AND_BAIL_OUT(milter, milter_error)
#define IN_CONNECT_EVENT(e)
#define CA_VSTREAM_CTL_DOUBLE
#define SMFIR_ADDRCPT_PAR
VSTRING * vstring_truncate(VSTRING *vp, ssize_t len)
#define RECV_ATTR_INT(name, val)
MILTER_EDIT_FROM_FN chg_from
#define MILTER8_STAT_REJECT_CON
#define MILTER8_HDR_SPACE(m)
#define MAIL_ATTR_MILT_CONN
int alldig(const char *string)
void(* free)(struct MILTER *)
char * mystrtok(char **src, const char *sep)
#define VA_COPY(dest, src)
#define MIME_OPT_DISABLE_MIME
#define VSTRING_TERMINATE(vp)
#define MAIL_ATTR_MILT_NAME
MILTER_ADD_HEADER_FN add_header
MILTER_EDIT_RCPT_FN add_rcpt
#define MILTER_FLAG_WANT_RCPT_REJ
const char *(* other_event)(struct MILTER *)
#define VSTRING_ADDCH(vp, ch)
#define MAIL_ATTR_MILT_ACTS
VSTRING * vstring_sprintf_append(VSTRING *vp, const char *format,...)
void(* MIME_STATE_BODY_OUT)(void *, int, const char *, ssize_t, off_t)
const char * str_name_mask_opt(VSTRING *buf, const char *context, const NAME_MASK *table, int mask, int flags)
int mime_state_update(MIME_STATE *state, int rec_type, const char *text, ssize_t len)
#define MAIL_ATTR_MILT_STAT
int inet_connect(const char *, int, int)
MIME_STATE * mime_state_free(MIME_STATE *state)
#define MAIL_ATTR_MILT_VERS
#define MILTER8_V2_PROTO_MASK
int(* active)(struct MILTER *)
int milter_macros_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *)
int vstream_fclose(VSTREAM *stream)
int unix_connect(const char *, int, int)
const char * str_name_code(const NAME_CODE *table, int code)
const char *(* mail_event)(struct MILTER *, const char **, ARGV *)
void(* MIME_STATE_ANY_END)(void *)
void(* MIME_STATE_HEAD_OUT)(void *, int, const HEADER_OPTS *, VSTRING *, off_t)
#define VSTRING_RESET(vp)
#define MILTER8_STAT_CLOSED
#define MILTER8_DATA_HLONG
#define MILTER8_STAT_ACCEPT_CON
void msg_warn(const char *fmt,...)
const char *(* message)(struct MILTER *, VSTREAM *, off_t, ARGV *, ARGV *, ARGV *)
#define MILTER8_V4_PROTO_MASK
VSTRING * vstring_alloc(ssize_t len)
#define NAME_CODE_FLAG_NONE
#define MILTER_CHUNK_SIZE
MILTER * milter8_create(const char *name, int conn_timeout, int cmd_timeout, int msg_timeout, const char *protocol, const char *def_action, MILTERS *parent)
const MIME_STATE_DETAIL * mime_state_detail(int error_code)
#define MILTER8_DATA_STRING
#define SEND_ATTR_INT(name, val)
MILTER * milter8_receive(VSTREAM *stream, MILTERS *parent)
int name_code(const NAME_CODE *table, int flags, const char *name)
#define MILTER_BODY_START
off_t vstream_fseek(VSTREAM *stream, off_t offset, int whence)
#define MILTER8_EVENT_BREAK(s)
#define vstream_fread(v, b, n)
#define MILTER8_STAT_ENVELOPE
int vstream_fflush(VSTREAM *stream)
#define MAIL_ATTR_MILT_EVTS
char * concatenate(const char *arg0,...)
#define SMFIP_NOSEND_MASK
VSTRING * vstring_memcat(VSTRING *vp, const char *src, ssize_t len)
#define vstream_fwrite(v, b, n)
#define MAIL_ATTR_MILT_CMD
int vstream_tweak_tcp(VSTREAM *)
#define SEND_ATTR_FUNC(func, val)
#define VSTRING_SPACE(vp, len)
int(* send)(struct MILTER *, VSTREAM *)
#define MILTER8_MACRO_PTR(__macros, __class)
int strcasecmp(const char *s1, const char *s2)
int vstream_tweak_sock(VSTREAM *)
#define MILTER8_DATA_BUFFER
void(* MIME_STATE_ERR_PRINT)(void *, int, const char *, ssize_t)
VSTRING * vstring_free(VSTRING *vp)
#define MILTER8_DATA_NSHORT
#define MILTER8_STAT_ERROR
#define MILTER8_STAT_READY
char * split_at(char *string, int delimiter)
#define vstream_fileno(vp)
#define VSTRING_AT_OFFSET(vp, offset)
#define CA_VSTREAM_CTL_END
#define RECV_ATTR_FUNC(func, val)
#define VSTREAM_PUTC(ch, vp)
MILTER_DEL_HEADER_FN del_header
MILTER_EDIT_HEADER_FN upd_header
void vstream_control(VSTREAM *stream, int name,...)
MILTER_MACROS * milter_macros_alloc(int)
const char *(* data_event)(struct MILTER *, ARGV *)
#define rec_get(fp, buf, limit)
#define vstream_ferror(vp)
const char *(* unknown_event)(struct MILTER *, const char *, ARGV *)
void(* disc_event)(struct MILTER *)
void(* abort)(struct MILTER *)
#define SEND_ATTR_STR(name, val)
#define MILTER8_STAT_MESSAGE
const char *(* rcpt_event)(struct MILTER *, const char **, ARGV *)
#define MILTER_MACROS_ALLOC_ZERO
VSTREAM * vstream_fdopen(int fd, int flags)
#define SMFIP_HDR_LEADSPC
#define RECV_ATTR_STR(name, val)
void * mymalloc(ssize_t len)
void msg_info(const char *fmt,...)
#define SMFIF_ADDRCPT_PAR