├── .hgsigs ├── .hgtags ├── CMakeLists.txt ├── ChangeLog ├── README.md ├── centos ├── 80-rmilter.preset ├── rmilter.conf ├── rmilter.conf.common ├── rmilter.conf.sysvinit ├── rmilter.sh └── rmilter.spec ├── compat ├── blake2-impl.h ├── blake2.h └── blake2b-ref.c ├── config.h.in ├── contrib ├── http-parser │ ├── CMakeLists.txt │ ├── LICENSE-MIT │ ├── http_parser.c │ └── http_parser.h ├── lc-btrie │ ├── CMakeLists.txt │ ├── btrie.c │ ├── btrie.h │ ├── mempool.c │ └── mempool.h ├── libucl │ ├── CMakeLists.txt │ ├── khash.h │ ├── kvec.h │ ├── lua_ucl.c │ ├── lua_ucl.h │ ├── tree.h │ ├── ucl.h │ ├── ucl_chartable.h │ ├── ucl_emitter.c │ ├── ucl_emitter_streamline.c │ ├── ucl_emitter_utils.c │ ├── ucl_hash.c │ ├── ucl_hash.h │ ├── ucl_internal.h │ ├── ucl_msgpack.c │ ├── ucl_parser.c │ ├── ucl_schema.c │ ├── ucl_sexp.c │ └── ucl_util.c ├── xxhash │ ├── CMakeLists.txt │ ├── LICENSE │ ├── xxhash.c │ └── xxhash.h └── zstd │ ├── CMakeLists.txt │ ├── LICENSE │ ├── PATENTS │ ├── README.md │ ├── bitstream.h │ ├── divsufsort.c │ ├── divsufsort.h │ ├── entropy_common.c │ ├── error_private.h │ ├── error_public.h │ ├── fse.h │ ├── fse_compress.c │ ├── fse_decompress.c │ ├── huf.h │ ├── huf_compress.c │ ├── huf_decompress.c │ ├── mem.h │ ├── zbuff.h │ ├── zbuff_compress.c │ ├── zbuff_decompress.c │ ├── zdict.c │ ├── zdict.h │ ├── zstd.h │ ├── zstd_common.c │ ├── zstd_compress.c │ ├── zstd_decompress.c │ ├── zstd_internal.h │ └── zstd_opt.h ├── debian ├── changelog ├── compat ├── control ├── copyright ├── dirs ├── install ├── postinst ├── postrm ├── prerm ├── rmilter-tmpfiles.conf ├── rmilter.conf ├── rmilter.conf.common ├── rmilter.conf.sysvinit ├── rmilter.init ├── rmilter.install ├── rmilter.manpages ├── rmilter.service ├── rules └── source │ └── format ├── dist.sh ├── doc ├── Makefile ├── rmilter.8 └── rmilter.8.md ├── freebsd └── rmilter ├── hiredis ├── CMakeLists.txt ├── COPYING ├── README.md ├── adapters │ └── libevent.h ├── async.c ├── async.h ├── dict.c ├── dict.h ├── fmacros.h ├── hiredis.c ├── hiredis.h ├── net.c ├── net.h ├── read.c ├── read.h ├── sds.c └── sds.h ├── rmilter-grey.conf ├── rmilter.conf.sample ├── rmilter.service ├── src ├── cache.c ├── cache.h ├── cfg_file.c ├── cfg_file.h ├── cfg_file.l ├── cfg_file.y ├── greylist.c ├── greylist.h ├── libclamc.c ├── libclamc.h ├── libspamd.c ├── libspamd.h ├── main.c ├── radix.c ├── radix.h ├── ratelimit.c ├── ratelimit.h ├── rmilter.c ├── rmilter.h ├── upstream.c ├── upstream.h ├── util.c └── util.h └── uthash ├── utarray.h ├── uthash.h ├── utlist.h └── utstring.h /.hgsigs: -------------------------------------------------------------------------------- 1 | 522da15a00772d0a7ecb0bbc03025e689048ab04 0 iD8DBQBHKej/AtDGLf76lVYRAtyrAKCCoIqOoVx69lr9m1Inw5N4qjbNRQCdHWgGsXgyNgsy5iuR3vY8xdm8BPo= 2 | ddfabe58f2111f40428d0421192e657b018f71a9 0 iD8DBQBHKepAAtDGLf76lVYRArn2AJ9YVFLANIuVZTO/I9qTg5UloI8e0ACghhWLZ/CsB5dcUG7GuvCd0R655vE= 3 | -------------------------------------------------------------------------------- /.hgtags: -------------------------------------------------------------------------------- 1 | 40cb2deb45eafed5a11b3cbb6099ba584fc0aca3 1.5.26 2 | 38ba721dbea0f9c6c01a82fe6e00f4b71b4507c7 1.5.29 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About Rmilter 2 | 3 | ## Introduction 4 | 5 | [Rmilter](https://rspamd.com/rmilter/) is used to integrate Rspamd with `milter` compatible MTA, for example [Postfix](http://postfix.org) or [Sendmail](http://sendmail.org). 6 | 7 | This project is now not under active development, however, bug fixes and Rspamd integration features are still considered. 8 | 9 | Historically, Rmilter supported many other features besides Rspamd integration. So far, all these features are implemented in Rspamd which allows to simplify integration with different MTA (e.g. Exim, Haraka or other non-milter compatible servers). Therefore, if you use this functionality you should consider switching it to Rspamd where all equal features are usually better implemented and have active and actual support. 10 | 11 | The list of features includes the following ones: 12 | 13 | - Greylisting - provided by [greylisting module](https://rspamd.com/doc/modules/greylisting.html) 14 | - Ratelimit - is done by [ratelimit module](https://rspamd.com/doc/modules/ratelimit.html) 15 | - Replies whitelisting - is implemented in [replies module](https://rspamd.com/doc/modules/replies.html) 16 | - Antivirus filtering - provided now by [antivirus module](https://rspamd.com/doc/modules/antivirus.html) 17 | - DCC checks - are now done in [dcc module](https://rspamd.com/doc/modules/dcc.html) 18 | - Dkim signing - can be done now by using of [dkim module](https://rspamd.com/doc/modules/dkim.html#dkim-signatures) and also by a more simple [dkim signing module](https://rspamd.com/doc/modules/dkim_signing.html) 19 | 20 | All duplicating features are still kept in Rmilter for compatibility reasons. However, no further development or bug fixes will likely be done for them. 21 | 22 | Rmilter project page can be found on GitHub: . 23 | 24 | ## Rmilter configuration 25 | 26 | Rmilter configuration format is described in the **[following page](https://rspamd.com/rmilter/configuration.html)**. 27 | 28 | ## Postfix settings 29 | 30 | Here is a scheme that demonstrates Rspamd and Rmilter integration using Postfix MTA: 31 | 32 | 33 | 34 | There are several useful settings for postfix to work with this milter: 35 | 36 | smtpd_milters = unix:/var/run/rmilter/rmilter.sock 37 | milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen} 38 | milter_protocol = 6 -------------------------------------------------------------------------------- /centos/80-rmilter.preset: -------------------------------------------------------------------------------- 1 | enable rmilter.service 2 | -------------------------------------------------------------------------------- /centos/rmilter.conf: -------------------------------------------------------------------------------- 1 | # systemd-specific settings for rmilter 2 | 3 | .include /etc/rmilter/rmilter.conf.common 4 | 5 | bind_socket = unix:/var/run/rmilter/rmilter.sock; 6 | -------------------------------------------------------------------------------- /centos/rmilter.conf.common: -------------------------------------------------------------------------------- 1 | # Sample config file for rmilter 2 | # $Id$ 3 | # 4 | 5 | # .include - directive to include other config file 6 | #.include /etc/rmilter/rmilter-grey.conf 7 | 8 | # pidfile - path to pid file 9 | # Default: pidfile = /var/run/rmilter.pid 10 | 11 | pidfile = /var/run/rmilter/rmilter.pid; 12 | 13 | 14 | clamav { 15 | # servers - clamav socket definitions in format: 16 | # /path/to/file 17 | # host[:port] 18 | # sockets are separated by ',' 19 | # Default: empty 20 | #servers = localhost; 21 | # connect_timeout - timeout in miliseconds for connecting to clamav 22 | # Default: 1s 23 | connect_timeout = 1s; 24 | 25 | # port_timeout - timeout in miliseconds for waiting for clamav port response 26 | # Default: 4s 27 | port_timeout = 4s; 28 | 29 | # results_timeout - timeout in miliseconds for waiting for clamav response 30 | # Default: 20s 31 | results_timeout = 20s; 32 | 33 | # error_time - time in seconds during which we are counting errors 34 | # Default: 10 35 | error_time = 10; 36 | 37 | # dead_time - time in seconds during which we are thinking that server is down 38 | # Default: 300 39 | dead_time = 300; 40 | 41 | # maxerrors - maximum number of errors that can occur during error_time to make us thinking that 42 | # this upstream is dead 43 | # Default: 10 44 | maxerrors = 10; 45 | }; 46 | 47 | spamd { 48 | # servers - spamd socket definitions in format: 49 | # /path/to/file 50 | # host[:port] 51 | # sockets are separated by ',' 52 | # is server name is prefixed with r: it is rspamd server 53 | # Default: empty 54 | servers = localhost:11333; 55 | 56 | # also_check - extra spamd servers to check 57 | #also_check = r:spam.example.com; 58 | 59 | # diff_dir - path where to write messages that have different results from main and extra checks 60 | #diff_dir = /var/run/rmilter/diffmsg; 61 | 62 | # connect_timeout - timeout in milliseconds for connecting to spamd 63 | # Default: 1s 64 | connect_timeout = 1s; 65 | 66 | # results_timeout - timeout in milliseconds for waiting for spamd response 67 | # Default: 20s 68 | results_timeout = 20s; 69 | 70 | # error_time - time in seconds during which we are counting errors 71 | # Default: 10 72 | error_time = 10; 73 | 74 | # dead_time - time in seconds during which we are thinking that server is down 75 | # Default: 300 76 | dead_time = 300; 77 | 78 | # maxerrors - maximum number of errors that can occur during error_time to make us thinking that 79 | # this upstream is dead 80 | # Default: 10 81 | maxerrors = 10; 82 | 83 | # reject_message - reject message for spam 84 | # Default: "Spam message rejected; If this is not spam contact abuse" 85 | reject_message = "Spam message rejected; If this is not spam contact abuse"; 86 | 87 | # whitelist - list of ips or nets that should be not checked with spamd 88 | # Default: empty 89 | whitelist = 127.0.0.1/32, 192.168.0.0/16, [::1]/128; 90 | 91 | # rspamd_metric - metric for using with rspamd 92 | # Default: "default" 93 | rspamd_metric = "default"; 94 | }; 95 | 96 | redis { 97 | # servers_grey - memcached servers for greylisting in format: 98 | # host[:port][, host[:port]] 99 | # It is possible to make memcached mirroring, its syntax is {server1, server2} 100 | servers_grey = localhost; 101 | 102 | # servers_white - memcached servers for whitelisting in format similar to that is used 103 | # in servers_grey 104 | # servers_white = {localhost, mcgi12.example.com}, mcgi18.example.com:11211; 105 | 106 | # servers_limits - memcached servers used for limits storing, can not be mirrored 107 | servers_limits = localhost; 108 | 109 | # servers_id - memcached servers used for message id storing, can not be mirrored 110 | servers_id = localhost; 111 | 112 | # id_prefix - prefix for extracting message ids from memcached 113 | # Default: empty (no prefix is prepended to key) 114 | id_prefix = "message_id."; 115 | 116 | # grey_prefix - prefix for extracting greylisted records from memcached 117 | # Default: empty (no prefix is prepended to key) 118 | grey_prefix = "grey."; 119 | 120 | # id_prefix - prefix for extracting whitelisted records from memcached 121 | # Default: empty (no prefix is prepended to key) 122 | white_prefix = "white."; 123 | 124 | # connect_timeout - timeout in miliseconds for waiting for memcached 125 | # Default: 1s 126 | connect_timeout = 1s; 127 | 128 | # error_time - time in seconds during which we are counting errors 129 | # Default: 10 130 | error_time = 10; 131 | 132 | # dead_time - time in seconds during which we are thinking that server is down 133 | # Default: 300 134 | dead_time = 300; 135 | 136 | # maxerrors - maximum number of errors that can occur during error_time to make us thinking that 137 | # this upstream is dead 138 | # Default: 10 139 | maxerrors = 10; 140 | 141 | # protocol - protocol that is using for connecting to memcached (tcp or udp) 142 | # Default: udp 143 | protocol = tcp; 144 | }; 145 | 146 | # bind_socket - socket credits for local bind: 147 | # unix:/path/to/file - bind to local socket 148 | # inet:port@host - bind to inet socket 149 | # Default: bind_socket = unix:/var/tmp/rmilter.sock; 150 | 151 | bind_socket = unix:/run/rmilter/rmilter.sock; 152 | 153 | # tempdir - path to directory that contains temporary files 154 | # Default: $TMPDIR 155 | 156 | tempdir = /tmp; 157 | 158 | # max_size - maximum size of scanned mail with clamav and dcc 159 | # Default: 0 (no limit) 160 | 161 | max_size = 10M; 162 | 163 | # strict_auth - strict checks for mails from authenticated senders 164 | # Default: no 165 | 166 | strict_auth = no; 167 | 168 | # spf_domains - path to file that contains hash of spf domains 169 | # Default: empty 170 | 171 | #spf_domains = example.com; 172 | 173 | # use_dcc - whether use or not dcc system 174 | # Default: no 175 | 176 | use_dcc = no; 177 | 178 | # rule definition: 179 | # rule { 180 | # accept|discard|reject|tempfail|quarantine "[message]"; <- action definition 181 | # [not] connect ; <- conditions 182 | # helo ; 183 | # envfrom ; 184 | # envrcpt ; 185 | # header ; 186 | # body ; 187 | # }; 188 | 189 | # limits section 190 | limits { 191 | # Whitelisted ip or networks 192 | limit_whitelist = 194.67.45.4/32; 193 | # Whitelisted recipients 194 | limit_whitelist_rcpt = postmaster, mailer-daemon; 195 | # Addrs for bounce checks 196 | limit_bounce_addrs = postmaster, mailer-daemon, symantec_antivirus_for_smtp_gateways, <>, null, fetchmail-daemon; 197 | # Limit for bounce mail 198 | limit_bounce_to = 5:0.000277778; 199 | # Limit for bounce mail per one source ip 200 | limit_bounce_to_ip = 5:0.000277778; 201 | # Limit for all mail per recipient 202 | limit_to = 20:0.016666667; 203 | # Limit for all mail per one source ip 204 | limit_to_ip = 30:0.025; 205 | # Limit for all mail per one source ip and from address 206 | limit_to_ip_from = 100:0.033333333; 207 | }; 208 | 209 | greylisting { 210 | timeout = 300s; 211 | expire = 3d; 212 | whitelist = 127.0.0.1, 213 | 192.168.1.1, 214 | 192.168.2.0/24, 215 | [::1]/128; 216 | }; 217 | 218 | dkim { 219 | # Sample for dkim specific keys 220 | # domain { 221 | # key = /etc/dkim/dkim_example.key; 222 | # domain = "example.com"; 223 | # selector = "dkim"; 224 | # }; 225 | # domain { 226 | # key = /etc/dkim/dkim_test.key; 227 | # domain = "test.com"; 228 | # selector = "dkim"; 229 | # }; 230 | # Universal selector, keys will be checked for pattern /etc/dkim/..key 231 | domain { 232 | key = /etc/dkim; 233 | domain = "*"; 234 | selector = "dkim"; 235 | }; 236 | header_canon = relaxed; 237 | body_canon = relaxed; 238 | sign_alg = sha256; 239 | }; 240 | 241 | 242 | # Order of checks at EOM: 243 | # 244 | # SPF -> DCC -> CLAMAV 245 | -------------------------------------------------------------------------------- /centos/rmilter.conf.sysvinit: -------------------------------------------------------------------------------- 1 | # sysvinit-specific settings for rmilter 2 | 3 | .include /etc/rmilter/rmilter.conf.common 4 | 5 | bind_socket = unix:/var/run/rmilter/rmilter.sock; 6 | -------------------------------------------------------------------------------- /centos/rmilter.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # rmilter - this script starts and stops the rmilter daemon 4 | # 5 | # chkconfig: - 85 15 6 | # description: rmilter is a spam filtering system 7 | # processname: rmilter 8 | # config: /etc/rmilter/rmilter.sysvinit.conf 9 | # config: /etc/sysconfig/rmilter 10 | # pidfile: /var/run/rmilter/rmilter.pid 11 | 12 | # Source function library. 13 | . /etc/rc.d/init.d/functions 14 | 15 | # Source networking configuration. 16 | . /etc/sysconfig/network 17 | 18 | # Check that networking is up. 19 | [ "$NETWORKING" = "no" ] && exit 0 20 | 21 | rmilter="/usr/sbin/rmilter" 22 | prog=$(basename $rmilter) 23 | 24 | rmilter_CONF_FILE="/etc/rmilter/rmilter.conf.sysvinit" 25 | rmilter_USER="_rmilter" 26 | rmilter_GROUP="adm" 27 | 28 | [ -f /etc/sysconfig/rmilter ] && . /etc/sysconfig/rmilter 29 | 30 | lockfile=/var/lock/subsys/rs 31 | 32 | start() { 33 | [ -x $rmilter ] || exit 5 34 | [ -f $rmilter_CONF_FILE ] || exit 6 35 | echo -n $"Starting $prog: " 36 | daemon --user=$rmilter_USER $rmilter -c $rmilter_CONF_FILE 37 | retval=$? 38 | echo 39 | [ $retval -eq 0 ] && touch $lockfile 40 | return $retval 41 | } 42 | 43 | stop() { 44 | echo -n $"Stopping $prog: " 45 | killproc $prog -QUIT 46 | retval=$? 47 | if [ $retval -eq 0 ]; then 48 | if [ "$CONSOLETYPE" != "serial" ]; then 49 | echo -en "\\033[16G" 50 | fi 51 | while rh_status_q 52 | do 53 | sleep 1 54 | echo -n $"." 55 | done 56 | rm -f $lockfile 57 | fi 58 | echo 59 | return $retval 60 | } 61 | 62 | restart() { 63 | stop 64 | start 65 | } 66 | 67 | reload() { 68 | echo -n $"Reloading $prog: " 69 | killproc $rmilter -HUP 70 | RETVAL=$? 71 | echo 72 | } 73 | 74 | force_reload() { 75 | restart 76 | } 77 | 78 | rh_status() { 79 | status $prog 80 | } 81 | 82 | rh_status_q() { 83 | rh_status >/dev/null 2>&1 84 | } 85 | 86 | case "$1" in 87 | start) 88 | rh_status_q && exit 0 89 | $1 90 | ;; 91 | stop) 92 | rh_status_q || exit 0 93 | $1 94 | ;; 95 | restart) 96 | $1 97 | ;; 98 | reload) 99 | rh_status_q || exit 7 100 | $1 101 | ;; 102 | force-reload) 103 | force_reload 104 | ;; 105 | status) 106 | rh_status 107 | ;; 108 | condrestart|try-restart) 109 | rh_status_q || exit 0 110 | ;; 111 | *) 112 | echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" 113 | exit 2 114 | esac 115 | 116 | -------------------------------------------------------------------------------- /centos/rmilter.spec: -------------------------------------------------------------------------------- 1 | %define rmilter_user _rmilter 2 | %define rmilter_group adm 3 | %define rmilter_home %{_localstatedir}/run/rmilter 4 | 5 | %define has_systemd 1 6 | %{?el6:%undefine has_systemd} 7 | %{?!suse_version:%define not_suse 1} 8 | 9 | Name: rmilter 10 | Version: 1.7.0 11 | Release: 1 12 | Summary: Multi-purpose milter 13 | Group: System Environment/Daemons 14 | 15 | # BSD License (two clause) 16 | # http://www.freebsd.org/copyright/freebsd-license.html 17 | %if 0%{?suse_version} 18 | License: BSD-2-Clause 19 | %else 20 | License: BSD2c 21 | %endif 22 | URL: https://github.com/vstakhov/rmilter 23 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release} 24 | %if 0%{?not_suse} 25 | BuildRequires: sendmail-milter 26 | %endif 27 | BuildRequires: sendmail-devel,openssl-devel,pcre-devel,glib2-devel 28 | BuildRequires: cmake,bison,flex,libopendkim-devel 29 | %if 0%{?has_systemd} 30 | BuildRequires: systemd 31 | Requires(pre): systemd 32 | Requires(post): systemd 33 | Requires(preun): systemd 34 | Requires(postun): systemd 35 | %endif 36 | %if 0%{?suse_version} 37 | Requires(pre): shadow 38 | %else 39 | BuildRequires: sqlite-devel 40 | Requires(pre): shadow-utils 41 | %endif 42 | 43 | %if 0%{?el6} 44 | Requires: logrotate 45 | Requires(post): chkconfig 46 | Requires(preun): chkconfig, initscripts 47 | Requires(postun): initscripts 48 | Source4: %{name}.sh 49 | %endif 50 | 51 | Source0: https://rspamd.com/downloads/%{name}-%{version}.tar.xz 52 | Source1: %{name}.conf 53 | Source2: %{name}.conf.common 54 | Source3: %{name}.conf.sysvinit 55 | Source5: 80-rmilter.preset 56 | 57 | %description 58 | The rmilter utility is designed to act as milter for sendmail and postfix MTA. 59 | It provides several filter and mail scan features. 60 | 61 | %prep 62 | %setup -q 63 | rm -rf %{buildroot} || true 64 | 65 | %build 66 | 67 | %{__cmake} \ 68 | -DCMAKE_C_OPT_FLAGS="%{optflags}" \ 69 | -DCMAKE_INSTALL_PREFIX=%{_prefix} \ 70 | -DCONFDIR=%{_sysconfdir}/rmilter \ 71 | -DMANDIR=%{_mandir} \ 72 | %if 0%{?has_systemd} 73 | -DWANT_SYSTEMD_UNITS=ON \ 74 | -DSYSTEMDDIR=%{_unitdir} \ 75 | %else 76 | -DWANT_SYSTEMD_UNITS=OFF \ 77 | %endif 78 | %if 0%{?suse_version} 79 | -DCMAKE_SKIP_INSTALL_RPATH=ON \ 80 | %endif 81 | -DNO_SHARED=ON \ 82 | -DRMILTER_GROUP=%{rmilter_group} \ 83 | -DRMILTER_USER=%{rmilter_user} 84 | 85 | %{__make} %{?jobs:-j%jobs} 86 | 87 | %install 88 | %{__make} install DESTDIR=%{buildroot} INSTALLDIRS=vendor 89 | 90 | %{__install} -p -d -D -m 0755 %{buildroot}%{_sysconfdir}/%{name} 91 | %{__install} -p -D -m 0644 %{SOURCE1} %{buildroot}%{_sysconfdir}/%{name}/ 92 | %{__install} -p -D -m 0644 %{SOURCE2} %{buildroot}%{_sysconfdir}/%{name}/ 93 | %{__install} -p -D -m 0644 %{SOURCE3} %{buildroot}%{_sysconfdir}/%{name}/ 94 | %if 0%{?el6} 95 | %{__install} -p -D -m 0755 %{SOURCE4} %{buildroot}%{_initrddir}/%{name} 96 | %{__install} -p -D -d -m 0755 %{buildroot}%{rmilter_home} 97 | %else 98 | %{__install} -p -D -m 0644 %{SOURCE5} %{buildroot}%{_presetdir}/80-rmilter.preset 99 | %endif 100 | %{__install} -p -D -d -m 0755 %{buildroot}%{_sysconfdir}/%{name}/rmilter.conf.d/ 101 | 102 | 103 | %clean 104 | rm -rf %{buildroot} 105 | 106 | %pre 107 | %{_sbindir}/groupadd -r %{rmilter_group} 2>/dev/null || : 108 | %{_sbindir}/useradd -g %{rmilter_group} -c "Rmilter user" -s /bin/false -r %{rmilter_user} 2>/dev/null || : 109 | 110 | %if 0%{?suse_version} 111 | %service_add_pre %{name}.service 112 | %endif 113 | 114 | %post 115 | %{__chown} -R %{rmilter_user}:%{rmilter_group} %{rmilter_home} 116 | %if 0%{?suse_version} 117 | %service_add_post %{name}.service 118 | %endif 119 | %if 0%{?not_suse} && 0%{?has_systemd} 120 | #Macro is not used as we want to do this on upgrade 121 | #%systemd_post %{name}.service 122 | systemctl --no-reload preset %{name}.service >/dev/null 2>&1 || : 123 | %endif 124 | %if 0%{?el6} 125 | /sbin/chkconfig --add %{name} 126 | %endif 127 | 128 | %preun 129 | %if 0%{?suse_version} 130 | %service_del_preun %{name}.service 131 | %endif 132 | %if 0%{?not_suse} && 0%{?has_systemd} 133 | %systemd_preun %{name}.service 134 | %endif 135 | %if 0%{?el6} 136 | if [ $1 = 0 ]; then 137 | /sbin/service %{name} stop >/dev/null 2>&1 138 | /sbin/chkconfig --del %{name} 139 | fi 140 | %endif 141 | 142 | %postun 143 | %if 0%{?suse_version} 144 | %service_del_postun %{name}.service 145 | %endif 146 | %if 0%{?not_suse} && 0%{?has_systemd} 147 | %systemd_postun_with_restart %{name}.service 148 | %endif 149 | %if 0%{?el6} 150 | if [ $1 -ge 1 ]; then 151 | /sbin/service %{name} condrestart > /dev/null 2>&1 || : 152 | fi 153 | 154 | %endif 155 | 156 | %files 157 | %defattr(-,root,root,-) 158 | %if 0%{?has_systemd} 159 | %{_unitdir}/%{name}.service 160 | %{_presetdir}/80-rmilter.preset 161 | %endif 162 | %if 0%{?el6} 163 | %{_initrddir}/%{name} 164 | %attr(-, _rmilter, adm) %dir %{rmilter_home} 165 | %endif 166 | %{_sbindir}/rmilter 167 | %dir %{_sysconfdir}/rmilter 168 | %dir %{_sysconfdir}/rmilter/rmilter.conf.d 169 | %config(noreplace) %{_sysconfdir}/rmilter/%{name}.conf 170 | %config(noreplace) %{_sysconfdir}/rmilter/%{name}.conf.common 171 | %config(noreplace) %{_sysconfdir}/rmilter/%{name}.conf.sysvinit 172 | 173 | %changelog 174 | * Mon Jul 06 2015 Vsevolod Stakhov 1.6.3-1 175 | - Update to 1.6.3 176 | -------------------------------------------------------------------------------- /compat/blake2-impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - reference C implementations 3 | 4 | Written in 2012 by Samuel Neves 5 | 6 | To the extent possible under law, the author(s) have dedicated all copyright 7 | and related and neighboring rights to this software to the public domain 8 | worldwide. This software is distributed without any warranty. 9 | 10 | You should have received a copy of the CC0 Public Domain Dedication along with 11 | this software. If not, see . 12 | */ 13 | #pragma once 14 | #ifndef __BLAKE2_IMPL_H__ 15 | #define __BLAKE2_IMPL_H__ 16 | 17 | #include 18 | 19 | static inline uint32_t load32( const void *src ) 20 | { 21 | #if defined(NATIVE_LITTLE_ENDIAN) 22 | return *( uint32_t * )( src ); 23 | #else 24 | const uint8_t *p = ( uint8_t * )src; 25 | uint32_t w = *p++; 26 | w |= ( uint32_t )( *p++ ) << 8; 27 | w |= ( uint32_t )( *p++ ) << 16; 28 | w |= ( uint32_t )( *p++ ) << 24; 29 | return w; 30 | #endif 31 | } 32 | 33 | static inline uint64_t load64( const void *src ) 34 | { 35 | #if defined(NATIVE_LITTLE_ENDIAN) 36 | return *( uint64_t * )( src ); 37 | #else 38 | const uint8_t *p = ( uint8_t * )src; 39 | uint64_t w = *p++; 40 | w |= ( uint64_t )( *p++ ) << 8; 41 | w |= ( uint64_t )( *p++ ) << 16; 42 | w |= ( uint64_t )( *p++ ) << 24; 43 | w |= ( uint64_t )( *p++ ) << 32; 44 | w |= ( uint64_t )( *p++ ) << 40; 45 | w |= ( uint64_t )( *p++ ) << 48; 46 | w |= ( uint64_t )( *p++ ) << 56; 47 | return w; 48 | #endif 49 | } 50 | 51 | static inline void store32( void *dst, uint32_t w ) 52 | { 53 | #if defined(NATIVE_LITTLE_ENDIAN) 54 | *( uint32_t * )( dst ) = w; 55 | #else 56 | uint8_t *p = ( uint8_t * )dst; 57 | *p++ = ( uint8_t )w; w >>= 8; 58 | *p++ = ( uint8_t )w; w >>= 8; 59 | *p++ = ( uint8_t )w; w >>= 8; 60 | *p++ = ( uint8_t )w; 61 | #endif 62 | } 63 | 64 | static inline void store64( void *dst, uint64_t w ) 65 | { 66 | #if defined(NATIVE_LITTLE_ENDIAN) 67 | *( uint64_t * )( dst ) = w; 68 | #else 69 | uint8_t *p = ( uint8_t * )dst; 70 | *p++ = ( uint8_t )w; w >>= 8; 71 | *p++ = ( uint8_t )w; w >>= 8; 72 | *p++ = ( uint8_t )w; w >>= 8; 73 | *p++ = ( uint8_t )w; w >>= 8; 74 | *p++ = ( uint8_t )w; w >>= 8; 75 | *p++ = ( uint8_t )w; w >>= 8; 76 | *p++ = ( uint8_t )w; w >>= 8; 77 | *p++ = ( uint8_t )w; 78 | #endif 79 | } 80 | 81 | static inline uint64_t load48( const void *src ) 82 | { 83 | const uint8_t *p = ( const uint8_t * )src; 84 | uint64_t w = *p++; 85 | w |= ( uint64_t )( *p++ ) << 8; 86 | w |= ( uint64_t )( *p++ ) << 16; 87 | w |= ( uint64_t )( *p++ ) << 24; 88 | w |= ( uint64_t )( *p++ ) << 32; 89 | w |= ( uint64_t )( *p++ ) << 40; 90 | return w; 91 | } 92 | 93 | static inline void store48( void *dst, uint64_t w ) 94 | { 95 | uint8_t *p = ( uint8_t * )dst; 96 | *p++ = ( uint8_t )w; w >>= 8; 97 | *p++ = ( uint8_t )w; w >>= 8; 98 | *p++ = ( uint8_t )w; w >>= 8; 99 | *p++ = ( uint8_t )w; w >>= 8; 100 | *p++ = ( uint8_t )w; w >>= 8; 101 | *p++ = ( uint8_t )w; 102 | } 103 | 104 | static inline uint32_t rotl32( const uint32_t w, const unsigned c ) 105 | { 106 | return ( w << c ) | ( w >> ( 32 - c ) ); 107 | } 108 | 109 | static inline uint64_t rotl64( const uint64_t w, const unsigned c ) 110 | { 111 | return ( w << c ) | ( w >> ( 64 - c ) ); 112 | } 113 | 114 | static inline uint32_t rotr32( const uint32_t w, const unsigned c ) 115 | { 116 | return ( w >> c ) | ( w << ( 32 - c ) ); 117 | } 118 | 119 | static inline uint64_t rotr64( const uint64_t w, const unsigned c ) 120 | { 121 | return ( w >> c ) | ( w << ( 64 - c ) ); 122 | } 123 | 124 | /* prevents compiler optimizing out memset() */ 125 | static inline void secure_zero_memory( void *v, size_t n ) 126 | { 127 | volatile uint8_t *p = ( volatile uint8_t * )v; 128 | 129 | while( n-- ) *p++ = 0; 130 | } 131 | 132 | #endif 133 | 134 | -------------------------------------------------------------------------------- /compat/blake2.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - reference C implementations 3 | 4 | Written in 2012 by Samuel Neves 5 | 6 | To the extent possible under law, the author(s) have dedicated all copyright 7 | and related and neighboring rights to this software to the public domain 8 | worldwide. This software is distributed without any warranty. 9 | 10 | You should have received a copy of the CC0 Public Domain Dedication along with 11 | this software. If not, see . 12 | */ 13 | #pragma once 14 | #ifndef __BLAKE2_H__ 15 | #define __BLAKE2_H__ 16 | 17 | #include 18 | #include 19 | 20 | #if defined(_MSC_VER) 21 | #define BLAKE2_ALIGN(x) __declspec(align(x)) 22 | #else 23 | #define BLAKE2_ALIGN(x) __attribute__((aligned(x))) 24 | #endif 25 | 26 | #if defined(__cplusplus) 27 | extern "C" { 28 | #endif 29 | 30 | enum blake2s_constant 31 | { 32 | BLAKE2S_BLOCKBYTES = 64, 33 | BLAKE2S_OUTBYTES = 32, 34 | BLAKE2S_KEYBYTES = 32, 35 | BLAKE2S_SALTBYTES = 8, 36 | BLAKE2S_PERSONALBYTES = 8 37 | }; 38 | 39 | enum blake2b_constant 40 | { 41 | BLAKE2B_BLOCKBYTES = 128, 42 | BLAKE2B_OUTBYTES = 64, 43 | BLAKE2B_KEYBYTES = 64, 44 | BLAKE2B_SALTBYTES = 16, 45 | BLAKE2B_PERSONALBYTES = 16 46 | }; 47 | 48 | #pragma pack(push, 1) 49 | typedef struct __blake2s_param 50 | { 51 | uint8_t digest_length; // 1 52 | uint8_t key_length; // 2 53 | uint8_t fanout; // 3 54 | uint8_t depth; // 4 55 | uint32_t leaf_length; // 8 56 | uint8_t node_offset[6];// 14 57 | uint8_t node_depth; // 15 58 | uint8_t inner_length; // 16 59 | // uint8_t reserved[0]; 60 | uint8_t salt[BLAKE2S_SALTBYTES]; // 24 61 | uint8_t personal[BLAKE2S_PERSONALBYTES]; // 32 62 | } blake2s_param; 63 | 64 | BLAKE2_ALIGN( 64 ) typedef struct __blake2s_state 65 | { 66 | uint32_t h[8]; 67 | uint32_t t[2]; 68 | uint32_t f[2]; 69 | uint8_t buf[2 * BLAKE2S_BLOCKBYTES]; 70 | size_t buflen; 71 | uint8_t last_node; 72 | } blake2s_state ; 73 | 74 | typedef struct __blake2b_param 75 | { 76 | uint8_t digest_length; // 1 77 | uint8_t key_length; // 2 78 | uint8_t fanout; // 3 79 | uint8_t depth; // 4 80 | uint32_t leaf_length; // 8 81 | uint64_t node_offset; // 16 82 | uint8_t node_depth; // 17 83 | uint8_t inner_length; // 18 84 | uint8_t reserved[14]; // 32 85 | uint8_t salt[BLAKE2B_SALTBYTES]; // 48 86 | uint8_t personal[BLAKE2B_PERSONALBYTES]; // 64 87 | } blake2b_param; 88 | 89 | BLAKE2_ALIGN( 64 ) typedef struct __blake2b_state 90 | { 91 | uint64_t h[8]; 92 | uint64_t t[2]; 93 | uint64_t f[2]; 94 | uint8_t buf[2 * BLAKE2B_BLOCKBYTES]; 95 | size_t buflen; 96 | uint8_t last_node; 97 | } blake2b_state; 98 | 99 | typedef struct __blake2sp_state 100 | { 101 | blake2s_state S[8][1]; 102 | blake2s_state R[1]; 103 | uint8_t buf[8 * BLAKE2S_BLOCKBYTES]; 104 | size_t buflen; 105 | } blake2sp_state; 106 | 107 | typedef struct __blake2bp_state 108 | { 109 | blake2b_state S[4][1]; 110 | blake2b_state R[1]; 111 | uint8_t buf[4 * BLAKE2B_BLOCKBYTES]; 112 | size_t buflen; 113 | } blake2bp_state; 114 | #pragma pack(pop) 115 | 116 | // Streaming API 117 | 118 | int blake2b_init( blake2b_state *S, const uint8_t outlen ); 119 | int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ); 120 | int blake2b_init_param( blake2b_state *S, const blake2b_param *P ); 121 | int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen ); 122 | int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen ); 123 | 124 | // Simple API 125 | int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ); 126 | 127 | static inline int blake2( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ) 128 | { 129 | return blake2b( out, in, key, outlen, inlen, keylen ); 130 | } 131 | 132 | #if defined(__cplusplus) 133 | } 134 | #endif 135 | 136 | #endif 137 | 138 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | #ifndef RMILTER_CONFIG_H_IN 2 | #define RMILTER_CONFIG_H_IN 3 | 4 | #cmakedefine HAVE_SYS_TYPES_H 1 5 | 6 | #cmakedefine HAVE_SYS_TIME_H 1 7 | 8 | #cmakedefine HAVE_SYS_UIO_H 1 9 | 10 | #cmakedefine HAVE_FCNTL_H 1 11 | 12 | #cmakedefine HAVE_MATH_H 1 13 | 14 | #cmakedefine HAVE_STDIO_H 1 15 | 16 | #cmakedefine HAVE_STDLIB_H 1 17 | 18 | #cmakedefine HAVE_STRING_H 1 19 | 20 | #cmakedefine HAVE_STRINGS_H 1 21 | 22 | #cmakedefine HAVE_TIME_H 1 23 | 24 | #cmakedefine HAVE_UNISTD_H 1 25 | 26 | #cmakedefine HAVE_SYSEXITS_H 1 27 | 28 | #cmakedefine HAVE_STDINT_H 1 29 | 30 | #cmakedefine HAVE_INTTYPES_H 1 31 | 32 | #cmakedefine HAVE_STDBOOL_H 1 33 | 34 | #cmakedefine HAVE_ARPA_INET_H 1 35 | #cmakedefine HAVE_NETINET_IN_H 1 36 | 37 | #cmakedefine HAVE_NETDB_H 1 38 | 39 | #cmakedefine HAVE_POLL_H 1 40 | 41 | #cmakedefine HAVE_SYSLOG_H 1 42 | 43 | #cmakedefine HAVE_SIGINFO_H 1 44 | 45 | #cmakedefine HAVE_LIBUTIL_H 1 46 | 47 | #cmakedefine HAVE_LIBGEN_H 1 48 | 49 | #cmakedefine HAVE_SEARCH_H 1 50 | 51 | #cmakedefine HAVE_LOCALE_H 1 52 | 53 | #cmakedefine HAVE_GRP_H 1 54 | #cmakedefine HAVE_PWD_H 1 55 | 56 | #cmakedefine HAVE_GLOB_H 1 57 | 58 | #cmakedefine HAVE_ENDIAN_H 1 59 | #cmakedefine HAVE_SYS_ENDIAN_H 1 60 | #cmakedefine HAVE_MACHINE_ENDIAN_H 1 61 | #cmakedefine HAVE_SYS_CDEFS_H 1 62 | 63 | #ifdef HAVE_ENDIAN_H 64 | #include 65 | #else 66 | #ifdef HAVE_SYS_ENDIAN_H 67 | #include 68 | #else 69 | #ifdef HAVE_MACHINE_ENDIAN_H 70 | #include 71 | #else 72 | #define LITTLE_ENDIAN 1234 73 | #define BIG_ENDIAN 4321 74 | #if defined(i386) || defined(__i386) || defined(__amd64) || \ 75 | defined(BIT_ZERO_ON_RIGHT) || defined(__x86__) 76 | #define BYTE_ORDER LITTLE_ENDIAN 77 | #endif 78 | 79 | #if defined(__sparc) || defined(__sparc__) || defined(__powerpc__) 80 | #define BYTE_ORDER BIG_ENDIAN 81 | #endif 82 | 83 | #endif /* HAVE_MACHINE_ENDIAN_H */ 84 | #endif /* HAVE_SYS_ENDIAN_H */ 85 | #endif /* HAVE_ENDIAN_H */ 86 | 87 | #if !defined(BYTE_ORDER) || (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN) 88 | # error "Undefined or unknown BYTE_ORDER" 89 | #endif 90 | 91 | 92 | 93 | #cmakedefine HAVE_SYS_QUEUE_H 1 94 | #cmakedefine HAVE_SYS_MMAN_H 1 95 | #cmakedefine HAVE_SYS_SOCKET_H 1 96 | #cmakedefine HAVE_SYS_UN_H 1 97 | #cmakedefine HAVE_SYS_STAT_H 1 98 | #cmakedefine HAVE_SYS_WAIT_H 1 99 | #cmakedefine HAVE_SYS_PARAM_H 1 100 | #cmakedefine HAVE_SYS_FILE_H 1 101 | #cmakedefine HAVE_SYS_RESOURCE_H 1 102 | #cmakedefine HAVE_SYS_TIMEB_H 1 103 | #cmakedefine HAVE_SYS_UTSNAME_H 1 104 | 105 | #cmakedefine HAVE_PIDFILE 1 106 | 107 | #cmakedefine HAVE_PIDFILE_FILENO 1 108 | 109 | #cmakedefine HAVE_SETPROCTITLE 1 110 | 111 | #cmakedefine HAVE_GETPAGESIZE 1 112 | 113 | #cmakedefine HAVE_NANOSLEEP 1 114 | 115 | #cmakedefine HAVE_PATH_MAX 1 116 | 117 | #cmakedefine HAVE_MAXPATHLEN 1 118 | 119 | #cmakedefine HAVE_MMAP_SHARED 1 120 | 121 | #cmakedefine HAVE_MMAP_ANON 1 122 | 123 | #cmakedefine HAVE_MMAP_NOCORE 1 124 | 125 | #cmakedefine HAVE_O_DIRECT 1 126 | 127 | #cmakedefine HAVE_FADVISE 1 128 | 129 | #cmakedefine HAVE_FALLOCATE 1 130 | #cmakedefine HAVE_POSIX_FALLOCATE 1 131 | 132 | #cmakedefine HAVE_FDATASYNC 1 133 | #cmakedefine HAVE_COMPATIBLE_QUEUE_H 1 134 | 135 | #cmakedefine HAVE_SC_NPROCESSORS_ONLN 1 136 | 137 | #cmakedefine HAVE_VFORK 1 138 | 139 | #cmakedefine HAVE_WAIT4 1 140 | 141 | #cmakedefine HAVE_WAITPID 1 142 | 143 | #cmakedefine HAVE_FLOCK 1 144 | 145 | #cmakedefine HAVE_SA_SIGINFO 1 146 | 147 | #cmakedefine WITH_DEBUG 1 148 | 149 | #cmakedefine HAVE_CLOCK_VIRTUAL 1 150 | #cmakedefine HAVE_CLOCK_PROCESS_CPUTIME_ID 1 151 | 152 | #cmakedefine HAVE_SETITIMER 1 153 | 154 | #cmakedefine HAVE_INET_PTON 1 155 | 156 | #define WITHOUT_PERL 1 157 | 158 | #cmakedefine WITH_DKIM 1 159 | 160 | #cmakedefine WITH_SPF 1 161 | 162 | #cmakedefine WITH_MEMCACHED 1 163 | 164 | #cmakedefine HAVE_SENDFILE 1 165 | #cmakedefine HAVE_SYS_SENDFILE_H 1 166 | 167 | #cmakedefine HAVE_MKSTEMP 1 168 | 169 | #cmakedefine HAVE_CLOCK_GETTIME 1 170 | 171 | #cmakedefine HAVE_OPENSSL 1 172 | 173 | 174 | #define MVERSION "${RMILTER_VERSION}" 175 | #define RMILTER_MASTER_SITE_URL "${RMILTER_MASTER_SITE_URL}" 176 | 177 | /* sys/types */ 178 | #ifdef HAVE_SYS_TYPES_H 179 | #include 180 | #endif 181 | 182 | /* cdefs */ 183 | #ifdef HAVE_SYS_CDEFS_H 184 | #include 185 | #endif 186 | 187 | /* sys/param */ 188 | #ifdef HAVE_SYS_PARAM_H 189 | #include 190 | #endif 191 | 192 | /* stdint */ 193 | #ifdef HAVE_STDINT_H 194 | #include 195 | #elif defined(HAVE_INTTYPES_H) 196 | #include 197 | #endif 198 | 199 | /* stdbool */ 200 | #ifdef HAVE_STDBOOL_H 201 | #include 202 | #endif 203 | #ifndef HAVE_STDBOOL_H 204 | # ifndef bool 205 | # ifndef __bool_true_false_are_defined 206 | typedef int bool; 207 | # define __bool_true_false_are_defined 1 208 | # endif /* ! __bool_true_false_are_defined */ 209 | # endif /* bool */ 210 | # ifndef true 211 | #define false 0 212 | #define true 1 213 | # endif /* ! true */ 214 | #endif 215 | 216 | /* sys/socket */ 217 | #ifdef HAVE_SYS_SOCKET_H 218 | #include 219 | #endif 220 | 221 | /* sys/file.h */ 222 | #ifdef HAVE_SYS_FILE_H 223 | #include 224 | #endif 225 | 226 | /* sys/uio.h */ 227 | #ifdef HAVE_SYS_UIO_H 228 | #include 229 | #endif 230 | 231 | /* sys/mman */ 232 | #ifdef HAVE_SYS_MMAN_H 233 | #include 234 | #endif 235 | 236 | /* netinet issues */ 237 | #ifdef HAVE_NETINET_IN_H 238 | #include 239 | #endif 240 | #ifdef HAVE_ARPA_INET_H 241 | #include 242 | #endif 243 | 244 | /* unix sockets */ 245 | #ifdef HAVE_SYS_UN_H 246 | #include 247 | #endif 248 | 249 | /* netdb */ 250 | #ifdef HAVE_NETDB_H 251 | #include 252 | #endif 253 | 254 | /* stdlib */ 255 | #ifdef HAVE_STDLIB_H 256 | #include 257 | #endif 258 | 259 | /* stdio */ 260 | #ifdef HAVE_STDIO_H 261 | #include 262 | #endif 263 | 264 | /* time */ 265 | #ifdef HAVE_TIME_H 266 | #include 267 | #endif 268 | 269 | #ifdef HAVE_SYS_TIME_H 270 | #include 271 | #endif 272 | 273 | /* sysexits */ 274 | #ifdef HAVE_SYSEXITS_H 275 | #include 276 | #endif 277 | 278 | /* unistd */ 279 | #ifdef HAVE_UNISTD_H 280 | #include 281 | #endif 282 | 283 | 284 | /* string */ 285 | #ifdef HAVE_STRING_H 286 | #include 287 | #endif 288 | 289 | /* strings */ 290 | #ifdef HAVE_STRINGS_H 291 | #include 292 | #endif 293 | 294 | /* fcntl */ 295 | #ifdef HAVE_FCNTL_H 296 | #include 297 | #endif 298 | 299 | /* poll */ 300 | #ifdef HAVE_POLL_H 301 | #include 302 | #endif 303 | 304 | /* sys/stat */ 305 | #ifdef HAVE_SYS_STAT_H 306 | #include 307 | #endif 308 | 309 | /* sys/wait */ 310 | #ifdef HAVE_SYS_WAIT_H 311 | #include 312 | #endif 313 | 314 | /* sys/resource.h */ 315 | #ifdef HAVE_SYS_RESOURCE_H 316 | #include 317 | #endif 318 | 319 | /* math */ 320 | #ifdef HAVE_MATH_H 321 | #include 322 | #endif 323 | 324 | 325 | /* syslog */ 326 | #ifdef HAVE_SYSLOG_H 327 | #include 328 | #endif 329 | 330 | #ifdef HAVE_LIBGEN_H 331 | #include 332 | #define HAVE_DIRNAME 1 333 | #endif 334 | 335 | #ifdef HAVE_SYS_SENDFILE_H 336 | #include 337 | #endif 338 | 339 | #include 340 | #include 341 | #include 342 | #ifdef HAVE_SIGINFO_H 343 | # include 344 | #endif 345 | 346 | #include 347 | #include 348 | #include 349 | 350 | #endif 351 | -------------------------------------------------------------------------------- /contrib/http-parser/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | SET(HTTPSRC http_parser.c) 2 | 3 | if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") 4 | set(HTTP_COMPILE_FLAGS "${HTTP_COMPILE_FLAGS} -O3") 5 | endif () 6 | 7 | ADD_LIBRARY(rmilter-http-parser STATIC ${HTTPSRC}) 8 | SET_TARGET_PROPERTIES(rmilter-http-parser PROPERTIES COMPILE_FLAGS "${HTTP_COMPILE_FLAGS}") -------------------------------------------------------------------------------- /contrib/http-parser/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright 2 | Igor Sysoev. 3 | 4 | Additional changes are licensed under the same terms as NGINX and 5 | copyright Joyent, Inc. and other Node contributors. All rights reserved. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to 9 | deal in the Software without restriction, including without limitation the 10 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | sell copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /contrib/lc-btrie/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | SET(LCTRIESRC btrie.c 2 | mempool.c) 3 | ADD_LIBRARY(lcbtrie STATIC ${LCTRIESRC}) 4 | 5 | SET(LCTRIE_CFLAGS "-DBUILD_RSPAMD") 6 | if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") 7 | SET(LCTRIE_CFLAGS "${LCTRIE_CFLAGS} -O3") 8 | endif () 9 | set_target_properties(lcbtrie PROPERTIES COMPILE_FLAGS "${LCTRIE_CFLAGS}") -------------------------------------------------------------------------------- /contrib/lc-btrie/btrie.h: -------------------------------------------------------------------------------- 1 | /* Level-Compressed Tree Bitmap (LC-TBM) Trie implementation 2 | * 3 | * Contributed by Geoffrey T. Dairiki 4 | * 5 | * This file is released under a "Three-clause BSD License". 6 | * 7 | * Copyright (c) 2013, Geoffrey T. Dairiki 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * 17 | * * Redistributions in binary form must reproduce the above 18 | * copyright notice, this list of conditions and the following 19 | * disclaimer in the documentation and/or other materials provided 20 | * with the distribution. 21 | * 22 | * * Neither the name of Geoffrey T. Dairiki nor the names of other 23 | * contributors may be used to endorse or promote products derived 24 | * from this software without specific prior written permission. 25 | * 26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 29 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GEOFFREY 30 | * T. DAIRIKI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 31 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 32 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 33 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 34 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 36 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 37 | * DAMAGE. 38 | */ 39 | #ifndef _BTRIE_H_INCLUDED 40 | #define _BTRIE_H_INCLUDED 41 | 42 | #include "config.h" 43 | 44 | #ifndef NO_STDINT_H 45 | # include 46 | typedef uint8_t btrie_oct_t; 47 | #else 48 | typedef unsigned char btrie_oct_t; 49 | #endif 50 | 51 | /* maximum length of bit string btrie_walk() can handle 52 | * 53 | * note: this limit is necessitated by the use of fixed length buffers 54 | * in btrie_walk() --- btrie_add_prefix() and btrie_lookup() impose no 55 | * limit on the length of bitstrings 56 | */ 57 | #define BTRIE_MAX_PREFIX 128 58 | 59 | struct btrie; 60 | struct mempool; 61 | 62 | struct btrie * btrie_init(struct mempool *mp); 63 | 64 | enum btrie_result { 65 | BTRIE_OKAY = 0, 66 | BTRIE_ALLOC_FAILED = -1, 67 | BTRIE_DUPLICATE_PREFIX = 1 68 | }; 69 | 70 | enum btrie_result btrie_add_prefix(struct btrie *btrie, 71 | const btrie_oct_t *prefix, unsigned len, 72 | const void *data); 73 | 74 | const void *btrie_lookup(const struct btrie *btrie, 75 | const btrie_oct_t *pfx, unsigned len); 76 | 77 | const char *btrie_stats(const struct btrie *btrie); 78 | 79 | #ifndef NO_MASTER_DUMP 80 | typedef void btrie_walk_cb_t(const btrie_oct_t *prefix, unsigned len, 81 | const void *data, int post, void *user_data); 82 | 83 | void btrie_walk(const struct btrie *btrie, 84 | btrie_walk_cb_t *callback, void *user_data); 85 | #endif /* not NO_MASTER_DUMP */ 86 | 87 | #endif /* _BTRIE_H_INCLUDED */ 88 | -------------------------------------------------------------------------------- /contrib/lc-btrie/mempool.c: -------------------------------------------------------------------------------- 1 | /* memory pool implementation 2 | */ 3 | 4 | #include 5 | #include 6 | #include "mempool.h" 7 | 8 | #define MEM_ALIGNMENT 16 /* Better for SSE */ 9 | #define alignmask (MEM_ALIGNMENT-1) 10 | 11 | #define MEMPOOL_CHUNKSIZE (65536-sizeof(unsigned)*4) 12 | 13 | struct mempool_chunk { 14 | char buf[MEMPOOL_CHUNKSIZE+MEM_ALIGNMENT]; 15 | struct mempool_chunk *next; 16 | unsigned size; 17 | }; 18 | 19 | struct mempool_cfull { /* pseudo-chunk: one entry into full list */ 20 | struct mempool_chunk *next; 21 | char buf[1]; 22 | }; 23 | 24 | void mp_init(struct mempool *mp) { 25 | memset (mp, 0, sizeof (*mp)); 26 | } 27 | 28 | void *mp_alloc(struct mempool *mp, unsigned size, int align) { 29 | if (size >= MEMPOOL_CHUNKSIZE / 2) { 30 | /* for large blocks, allocate separate "full" chunk */ 31 | struct mempool_cfull *c = malloc (sizeof(*c)+size-1); 32 | if (!c) { 33 | return NULL; 34 | } 35 | c->next = mp->mp_fullc; 36 | mp->mp_fullc = (struct mempool_chunk*)c; 37 | return c->buf; 38 | } 39 | else { 40 | struct mempool_chunk *c; 41 | struct mempool_chunk *best; /* "best fit" chunk */ 42 | unsigned avg; /* average data size: total size / numallocs */ 43 | 44 | ++mp->mp_nallocs; mp->mp_datasz += size; 45 | avg = mp->mp_datasz / mp->mp_nallocs; 46 | 47 | /* round size up to a multiple of alignto */ 48 | if (align) { 49 | size = (size + alignmask) & ~alignmask; 50 | } 51 | 52 | for(c = mp->mp_chunk, best = NULL; c; c = c->next) 53 | if (c->size >= size && (!best || best->size > c->size)) { 54 | best = c; 55 | if (c->size - size < avg) { 56 | break; 57 | } 58 | } 59 | 60 | if (best != NULL) { /* found a free chunk */ 61 | char *b; 62 | if (align) { 63 | best->size &= ~alignmask; 64 | } 65 | 66 | b = best->buf + MEMPOOL_CHUNKSIZE - best->size; 67 | best->size -= size; 68 | 69 | if (best->size < avg) { 70 | struct mempool_chunk **cp = &mp->mp_chunk; 71 | while(*cp != best) { 72 | cp = &(*cp)->next; 73 | } 74 | *cp = best->next; 75 | best->next = mp->mp_fullc; 76 | mp->mp_fullc = best; 77 | } 78 | return b; 79 | } 80 | 81 | else { /* no sutable chunks -> allocate new one */ 82 | c = (struct mempool_chunk *)malloc(sizeof(*c)); 83 | if (!c) { 84 | return NULL; 85 | } 86 | 87 | c->next = mp->mp_chunk; 88 | mp->mp_chunk = c; 89 | c->size = MEMPOOL_CHUNKSIZE - size; 90 | 91 | return c->buf; 92 | } 93 | } 94 | } 95 | 96 | void mp_free(struct mempool *mp) { 97 | struct mempool_chunk *c; 98 | 99 | while((c = mp->mp_chunk) != NULL) { 100 | mp->mp_chunk = c->next; 101 | free(c); 102 | } 103 | 104 | while((c = mp->mp_fullc) != NULL) { 105 | mp->mp_fullc = c->next; 106 | free(c); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /contrib/lc-btrie/mempool.h: -------------------------------------------------------------------------------- 1 | /* memory pool #include file 2 | */ 3 | 4 | #ifndef _MEMPOOL_H_INCLUDED 5 | #define _MEMPOOL_H_INCLUDED 6 | 7 | struct mempool_chunk; 8 | 9 | struct mempool { /* free-once memory pool. All members are private */ 10 | struct mempool_chunk *mp_chunk; /* list of chunks with free space */ 11 | struct mempool_chunk *mp_fullc; /* list of full chunks */ 12 | unsigned mp_nallocs; /* number of allocs so far */ 13 | unsigned mp_datasz; /* size of allocated data */ 14 | const char *mp_lastbuf; /* last allocated string */ 15 | unsigned mp_lastlen; /* length of lastbuf */ 16 | }; 17 | 18 | void mp_init(struct mempool *mp); 19 | void *mp_alloc(struct mempool *mp, unsigned size, int align); 20 | void mp_free(struct mempool *mp); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /contrib/libucl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | SET(UCLSRC ucl_util.c 2 | ucl_parser.c 3 | ucl_emitter.c 4 | ucl_emitter_streamline.c 5 | ucl_emitter_utils.c 6 | ucl_hash.c 7 | ucl_schema.c 8 | ucl_msgpack.c 9 | ucl_sexp.c) 10 | 11 | 12 | SET (LIB_TYPE STATIC) 13 | ADD_LIBRARY(ucl ${LIB_TYPE} ${UCLSRC}) 14 | 15 | IF(ENABLE_URL_SIGN MATCHES "ON") 16 | IF(OPENSSL_FOUND) 17 | TARGET_LINK_LIBRARIES(ucl ${OPENSSL_LIBRARIES}) 18 | ENDIF(OPENSSL_FOUND) 19 | ENDIF(ENABLE_URL_SIGN MATCHES "ON") 20 | -------------------------------------------------------------------------------- /contrib/libucl/kvec.h: -------------------------------------------------------------------------------- 1 | /* The MIT License 2 | 3 | Copyright (c) 2008, by Attractive Chaos 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | */ 25 | 26 | /* 27 | An example: 28 | 29 | #include "kvec.h" 30 | int main() { 31 | kvec_t(int) array; 32 | kv_init(array); 33 | kv_push(int, array, 10); // append 34 | kv_a(int, array, 20) = 5; // dynamic 35 | kv_A(array, 20) = 4; // static 36 | kv_destroy(array); 37 | return 0; 38 | } 39 | */ 40 | 41 | /* 42 | 2008-09-22 (0.1.0): 43 | 44 | * The initial version. 45 | 46 | */ 47 | 48 | #ifndef AC_KVEC_H 49 | #define AC_KVEC_H 50 | 51 | #include 52 | 53 | #define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) 54 | 55 | #define kvec_t(type) struct { size_t n, m; type *a; } 56 | #define kv_init(v) ((v).n = (v).m = 0, (v).a = 0) 57 | #define kv_destroy(v) free((v).a) 58 | #define kv_A(v, i) ((v).a[(i)]) 59 | #define kv_pop(v) ((v).a[--(v).n]) 60 | #define kv_size(v) ((v).n) 61 | #define kv_max(v) ((v).m) 62 | 63 | #define kv_resize(type, v, s) ((v).m = (s), (v).a = (type*)realloc((v).a, sizeof(type) * (v).m)) 64 | #define kv_grow_factor 1.5 65 | #define kv_grow(type, v) ((v).m = ((v).m > 1 ? (v).m * kv_grow_factor : 2), \ 66 | (v).a = (type*)realloc((v).a, sizeof(type) * (v).m)) 67 | 68 | #define kv_copy(type, v1, v0) do { \ 69 | if ((v1).m < (v0).n) kv_resize(type, v1, (v0).n); \ 70 | (v1).n = (v0).n; \ 71 | memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \ 72 | } while (0) \ 73 | 74 | #define kv_push(type, v, x) do { \ 75 | if ((v).n == (v).m) { \ 76 | kv_grow(type, v); \ 77 | } \ 78 | (v).a[(v).n++] = (x); \ 79 | } while (0) 80 | 81 | #define kv_prepend(type, v, x) do { \ 82 | if ((v).n == (v).m) { \ 83 | kv_grow(type, v); \ 84 | } \ 85 | memmove((v).a + 1, (v).a, sizeof(type) * (v).n); \ 86 | (v).a[0] = (x); \ 87 | (v).n ++; \ 88 | } while (0) 89 | 90 | #define kv_concat(type, v1, v0) do { \ 91 | if ((v1).m < (v0).n + (v1).n) kv_resize(type, v1, (v0).n + (v1).n); \ 92 | memcpy((v1).a + (v1).n, (v0).a, sizeof(type) * ((v0).n + (v1).n)); \ 93 | (v1).n = (v0).n + (v1).n; \ 94 | } while (0) 95 | 96 | #define kv_del(type, v, i) do { \ 97 | if ((i) < (v).n) { \ 98 | memmove((v).a + (i), (v).a + ((i) + 1), sizeof(type) * ((v).n - (i) - 1)); \ 99 | (v).n --; \ 100 | } \ 101 | } while (0) 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /contrib/libucl/lua_ucl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014, Vsevolod Stakhov 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * 12 | * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | */ 23 | #ifndef LUA_UCL_H_ 24 | #define LUA_UCL_H_ 25 | 26 | #ifdef HAVE_CONFIG_H 27 | #include "config.h" 28 | #endif 29 | 30 | #include 31 | #include 32 | #include 33 | #include "ucl.h" 34 | 35 | /** 36 | * Closure structure for lua function storing inside UCL 37 | */ 38 | struct ucl_lua_funcdata { 39 | lua_State *L; 40 | int idx; 41 | char *ret; 42 | }; 43 | 44 | /** 45 | * Initialize lua UCL API 46 | */ 47 | UCL_EXTERN int luaopen_ucl (lua_State *L); 48 | 49 | /** 50 | * Import UCL object from lua state 51 | * @param L lua state 52 | * @param idx index of object at the lua stack to convert to UCL 53 | * @return new UCL object or NULL, the caller should unref object after using 54 | */ 55 | UCL_EXTERN ucl_object_t* ucl_object_lua_import (lua_State *L, int idx); 56 | 57 | /** 58 | * Push an object to lua 59 | * @param L lua state 60 | * @param obj object to push 61 | * @param allow_array traverse over implicit arrays 62 | */ 63 | UCL_EXTERN int ucl_object_push_lua (lua_State *L, 64 | const ucl_object_t *obj, bool allow_array); 65 | 66 | UCL_EXTERN struct ucl_lua_funcdata* ucl_object_toclosure ( 67 | const ucl_object_t *obj); 68 | 69 | #endif /* LUA_UCL_H_ */ 70 | -------------------------------------------------------------------------------- /contrib/libucl/ucl_emitter_streamline.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014, Vsevolod Stakhov 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * 12 | * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | */ 23 | 24 | #ifdef HAVE_CONFIG_H 25 | #include "config.h" 26 | #endif 27 | 28 | #include "ucl.h" 29 | #include "ucl_internal.h" 30 | #include "ucl_chartable.h" 31 | 32 | struct ucl_emitter_streamline_stack { 33 | bool is_array; 34 | bool empty; 35 | const ucl_object_t *obj; 36 | struct ucl_emitter_streamline_stack *next; 37 | }; 38 | 39 | struct ucl_emitter_context_streamline { 40 | /* Inherited from the main context */ 41 | /** Name of emitter (e.g. json, compact_json) */ 42 | const char *name; 43 | /** Unique id (e.g. UCL_EMIT_JSON for standard emitters */ 44 | int id; 45 | /** A set of output functions */ 46 | const struct ucl_emitter_functions *func; 47 | /** A set of output operations */ 48 | const struct ucl_emitter_operations *ops; 49 | /** Current amount of indent tabs */ 50 | unsigned int indent; 51 | /** Top level object */ 52 | const ucl_object_t *top; 53 | /** Optional comments */ 54 | const ucl_object_t *comments; 55 | 56 | /* Streamline specific fields */ 57 | struct ucl_emitter_streamline_stack *containers; 58 | }; 59 | 60 | #define TO_STREAMLINE(ctx) (struct ucl_emitter_context_streamline *)(ctx) 61 | 62 | struct ucl_emitter_context* 63 | ucl_object_emit_streamline_new (const ucl_object_t *obj, 64 | enum ucl_emitter emit_type, 65 | struct ucl_emitter_functions *emitter) 66 | { 67 | const struct ucl_emitter_context *ctx; 68 | struct ucl_emitter_context_streamline *sctx; 69 | 70 | ctx = ucl_emit_get_standard_context (emit_type); 71 | if (ctx == NULL) { 72 | return NULL; 73 | } 74 | 75 | sctx = calloc (1, sizeof (*sctx)); 76 | if (sctx == NULL) { 77 | return NULL; 78 | } 79 | 80 | memcpy (sctx, ctx, sizeof (*ctx)); 81 | sctx->func = emitter; 82 | sctx->top = obj; 83 | 84 | ucl_object_emit_streamline_start_container ((struct ucl_emitter_context *)sctx, 85 | obj); 86 | 87 | return (struct ucl_emitter_context *)sctx; 88 | } 89 | 90 | void 91 | ucl_object_emit_streamline_start_container (struct ucl_emitter_context *ctx, 92 | const ucl_object_t *obj) 93 | { 94 | struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx); 95 | struct ucl_emitter_streamline_stack *st, *top; 96 | bool print_key = false; 97 | 98 | /* Check top object presence */ 99 | if (sctx->top == NULL) { 100 | sctx->top = obj; 101 | } 102 | 103 | top = sctx->containers; 104 | st = malloc (sizeof (*st)); 105 | if (st != NULL) { 106 | if (top != NULL && !top->is_array) { 107 | print_key = true; 108 | } 109 | st->empty = true; 110 | st->obj = obj; 111 | if (obj != NULL && obj->type == UCL_ARRAY) { 112 | st->is_array = true; 113 | sctx->ops->ucl_emitter_start_array (ctx, obj, print_key); 114 | } 115 | else { 116 | st->is_array = false; 117 | sctx->ops->ucl_emitter_start_object (ctx, obj, print_key); 118 | } 119 | LL_PREPEND (sctx->containers, st); 120 | } 121 | } 122 | 123 | void 124 | ucl_object_emit_streamline_add_object ( 125 | struct ucl_emitter_context *ctx, const ucl_object_t *obj) 126 | { 127 | struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx); 128 | bool is_array = false, is_first = false; 129 | 130 | if (sctx->containers != NULL) { 131 | if (sctx->containers->is_array) { 132 | is_array = true; 133 | } 134 | if (sctx->containers->empty) { 135 | is_first = true; 136 | sctx->containers->empty = false; 137 | } 138 | } 139 | 140 | sctx->ops->ucl_emitter_write_elt (ctx, obj, is_first, !is_array); 141 | } 142 | 143 | void 144 | ucl_object_emit_streamline_end_container (struct ucl_emitter_context *ctx) 145 | { 146 | struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx); 147 | struct ucl_emitter_streamline_stack *st; 148 | 149 | if (sctx->containers != NULL) { 150 | st = sctx->containers; 151 | 152 | if (st->is_array) { 153 | sctx->ops->ucl_emitter_end_array (ctx, st->obj); 154 | } 155 | else { 156 | sctx->ops->ucl_emitter_end_object (ctx, st->obj); 157 | } 158 | sctx->containers = st->next; 159 | free (st); 160 | } 161 | } 162 | 163 | void 164 | ucl_object_emit_streamline_finish (struct ucl_emitter_context *ctx) 165 | { 166 | struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx); 167 | 168 | while (sctx->containers != NULL) { 169 | ucl_object_emit_streamline_end_container (ctx); 170 | } 171 | 172 | free (sctx); 173 | } 174 | -------------------------------------------------------------------------------- /contrib/libucl/ucl_hash.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Vsevolod Stakhov 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * 12 | * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | */ 23 | 24 | #ifndef __UCL_HASH_H 25 | #define __UCL_HASH_H 26 | 27 | #include "ucl.h" 28 | 29 | /******************************************************************************/ 30 | 31 | struct ucl_hash_node_s; 32 | typedef struct ucl_hash_node_s ucl_hash_node_t; 33 | 34 | typedef int (*ucl_hash_cmp_func) (const void* void_a, const void* void_b); 35 | typedef void (*ucl_hash_free_func) (void *ptr); 36 | typedef void* ucl_hash_iter_t; 37 | 38 | 39 | /** 40 | * Linear chained hashtable. 41 | */ 42 | struct ucl_hash_struct; 43 | typedef struct ucl_hash_struct ucl_hash_t; 44 | 45 | 46 | /** 47 | * Initializes the hashtable. 48 | */ 49 | ucl_hash_t* ucl_hash_create (bool ignore_case); 50 | 51 | /** 52 | * Deinitializes the hashtable. 53 | */ 54 | void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func); 55 | 56 | /** 57 | * Inserts an element in the the hashtable. 58 | */ 59 | void ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, const char *key, 60 | unsigned keylen); 61 | 62 | /** 63 | * Replace element in the hash 64 | */ 65 | void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old, 66 | const ucl_object_t *new); 67 | 68 | /** 69 | * Delete an element from the the hashtable. 70 | */ 71 | void ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj); 72 | 73 | /** 74 | * Searches an element in the hashtable. 75 | */ 76 | const ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key, 77 | unsigned keylen); 78 | 79 | 80 | /** 81 | * Iterate over hash table 82 | * @param hashlin hash 83 | * @param iter iterator (must be NULL on first iteration) 84 | * @return the next object 85 | */ 86 | const void* ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter); 87 | 88 | /** 89 | * Check whether an iterator has next element 90 | */ 91 | bool ucl_hash_iter_has_next (ucl_hash_t *hashlin, ucl_hash_iter_t iter); 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /contrib/libucl/ucl_sexp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Vsevolod Stakhov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY 14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 17 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | #include "config.h" 27 | #endif 28 | 29 | #include 30 | #include "ucl.h" 31 | #include "ucl_internal.h" 32 | #include "utlist.h" 33 | 34 | #define NEXT_STATE do { \ 35 | if (p >= end) { \ 36 | if (state != read_ebrace) { \ 37 | ucl_create_err (&parser->err,\ 38 | "extra data");\ 39 | state = parse_err; \ 40 | } \ 41 | } \ 42 | else { \ 43 | switch (*p) { \ 44 | case '(': \ 45 | state = read_obrace; \ 46 | break; \ 47 | case ')': \ 48 | state = read_ebrace; \ 49 | break; \ 50 | default: \ 51 | len = 0; \ 52 | mult = 1; \ 53 | state = read_length; \ 54 | break; \ 55 | } \ 56 | } \ 57 | } while(0) 58 | 59 | bool 60 | ucl_parse_csexp (struct ucl_parser *parser) 61 | { 62 | const unsigned char *p, *end; 63 | ucl_object_t *obj; 64 | struct ucl_stack *st; 65 | uint64_t len = 0, mult = 1; 66 | enum { 67 | start_parse, 68 | read_obrace, 69 | read_length, 70 | read_value, 71 | read_ebrace, 72 | parse_err 73 | } state = start_parse; 74 | 75 | assert (parser != NULL); 76 | assert (parser->chunks != NULL); 77 | assert (parser->chunks->begin != NULL); 78 | assert (parser->chunks->remain != 0); 79 | 80 | p = parser->chunks->begin; 81 | end = p + parser->chunks->remain; 82 | 83 | while (p < end) { 84 | switch (state) { 85 | case start_parse: 86 | /* At this point we expect open brace */ 87 | if (*p == '(') { 88 | state = read_obrace; 89 | } 90 | else { 91 | ucl_create_err (&parser->err, "bad starting character for " 92 | "sexp block: %x", (int)*p); 93 | state = parse_err; 94 | } 95 | break; 96 | 97 | case read_obrace: 98 | st = calloc (1, sizeof (*st)); 99 | 100 | if (st == NULL) { 101 | ucl_create_err (&parser->err, "no memory"); 102 | state = parse_err; 103 | continue; 104 | } 105 | 106 | st->obj = ucl_object_typed_new (UCL_ARRAY); 107 | 108 | if (st->obj == NULL) { 109 | ucl_create_err (&parser->err, "no memory"); 110 | state = parse_err; 111 | free (st); 112 | continue; 113 | } 114 | 115 | if (parser->stack == NULL) { 116 | /* We have no stack */ 117 | parser->stack = st; 118 | 119 | if (parser->top_obj == NULL) { 120 | parser->top_obj = st->obj; 121 | } 122 | } 123 | else { 124 | /* Prepend new element to the stack */ 125 | LL_PREPEND (parser->stack, st); 126 | } 127 | 128 | p ++; 129 | NEXT_STATE; 130 | 131 | break; 132 | 133 | case read_length: 134 | if (*p == ':') { 135 | if (len == 0) { 136 | ucl_create_err (&parser->err, "zero length element"); 137 | state = parse_err; 138 | continue; 139 | } 140 | 141 | state = read_value; 142 | } 143 | else if (*p >= '0' && *p <= '9') { 144 | len += (*p - '0') * mult; 145 | mult *= 10; 146 | 147 | if (len > UINT32_MAX) { 148 | ucl_create_err (&parser->err, "too big length of an " 149 | "element"); 150 | state = parse_err; 151 | continue; 152 | } 153 | } 154 | else { 155 | ucl_create_err (&parser->err, "bad length character: %x", 156 | (int)*p); 157 | state = parse_err; 158 | continue; 159 | } 160 | 161 | p ++; 162 | break; 163 | 164 | case read_value: 165 | if ((uint64_t)(end - p) > len || len == 0) { 166 | ucl_create_err (&parser->err, "invalid length: %llu, %ld " 167 | "remain", (long long unsigned)len, (long)(end - p)); 168 | state = parse_err; 169 | continue; 170 | } 171 | obj = ucl_object_typed_new (UCL_STRING); 172 | 173 | obj->value.sv = (const char*)p; 174 | obj->len = len; 175 | obj->flags |= UCL_OBJECT_BINARY; 176 | 177 | if (!(parser->flags & UCL_PARSER_ZEROCOPY)) { 178 | ucl_copy_value_trash (obj); 179 | } 180 | 181 | ucl_array_append (parser->stack->obj, obj); 182 | p += len; 183 | NEXT_STATE; 184 | break; 185 | 186 | case read_ebrace: 187 | if (parser->stack == NULL) { 188 | /* We have an extra end brace */ 189 | ucl_create_err (&parser->err, "invalid length: %llu, %ld " 190 | "remain", (long long unsigned)len, (long)(end - p)); 191 | state = parse_err; 192 | continue; 193 | } 194 | /* Pop the container */ 195 | st = parser->stack; 196 | parser->stack = st->next; 197 | 198 | if (parser->stack->obj->type == UCL_ARRAY) { 199 | ucl_array_append (parser->stack->obj, st->obj); 200 | } 201 | else { 202 | ucl_create_err (&parser->err, "bad container object, array " 203 | "expected"); 204 | state = parse_err; 205 | continue; 206 | } 207 | 208 | free (st); 209 | st = NULL; 210 | p++; 211 | NEXT_STATE; 212 | break; 213 | 214 | case parse_err: 215 | default: 216 | return false; 217 | } 218 | } 219 | 220 | if (state != read_ebrace) { 221 | ucl_create_err (&parser->err, "invalid finishing state: %d", state); 222 | return false; 223 | } 224 | 225 | return true; 226 | } 227 | -------------------------------------------------------------------------------- /contrib/xxhash/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | SET(XXHASHSRC xxhash.c) 2 | 3 | if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") 4 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") 5 | endif () 6 | ADD_LIBRARY(xxhash STATIC ${XXHASHSRC}) -------------------------------------------------------------------------------- /contrib/xxhash/LICENSE: -------------------------------------------------------------------------------- 1 | xxHash Library 2 | Copyright (c) 2012-2014, Yann Collet 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, this 12 | list of conditions and the following disclaimer in the documentation and/or 13 | other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /contrib/xxhash/xxhash.h: -------------------------------------------------------------------------------- 1 | /* 2 | xxHash - Extremely Fast Hash algorithm 3 | Header File 4 | Copyright (C) 2012-2014, Yann Collet. 5 | BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are 9 | met: 10 | 11 | * Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above 14 | copyright notice, this list of conditions and the following disclaimer 15 | in the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | You can contact the author at : 31 | - xxHash source repository : http://code.google.com/p/xxhash/ 32 | */ 33 | 34 | /* Notice extracted from xxHash homepage : 35 | 36 | xxHash is an extremely fast Hash algorithm, running at RAM speed limits. 37 | It also successfully passes all tests from the SMHasher suite. 38 | 39 | Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) 40 | 41 | Name Speed Q.Score Author 42 | xxHash 5.4 GB/s 10 43 | CrapWow 3.2 GB/s 2 Andrew 44 | MumurHash 3a 2.7 GB/s 10 Austin Appleby 45 | SpookyHash 2.0 GB/s 10 Bob Jenkins 46 | SBox 1.4 GB/s 9 Bret Mulvey 47 | Lookup3 1.2 GB/s 9 Bob Jenkins 48 | SuperFastHash 1.2 GB/s 1 Paul Hsieh 49 | CityHash64 1.05 GB/s 10 Pike & Alakuijala 50 | FNV 0.55 GB/s 5 Fowler, Noll, Vo 51 | CRC32 0.43 GB/s 9 52 | MD5-32 0.33 GB/s 10 Ronald L. Rivest 53 | SHA1-32 0.28 GB/s 10 54 | 55 | Q.Score is a measure of quality of the hash function. 56 | It depends on successfully passing SMHasher test set. 57 | 10 is a perfect score. 58 | */ 59 | 60 | #pragma once 61 | 62 | #if defined (__cplusplus) 63 | extern "C" { 64 | #endif 65 | 66 | 67 | /***************************** 68 | Includes 69 | *****************************/ 70 | #include /* size_t */ 71 | 72 | 73 | /***************************** 74 | Type 75 | *****************************/ 76 | typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; 77 | 78 | 79 | 80 | /***************************** 81 | Simple Hash Functions 82 | *****************************/ 83 | 84 | unsigned int XXH32 (const void* input, size_t length, unsigned seed); 85 | unsigned long long XXH64 (const void* input, size_t length, unsigned long long seed); 86 | 87 | /* 88 | XXH32() : 89 | Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input". 90 | The memory between input & input+length must be valid (allocated and read-accessible). 91 | "seed" can be used to alter the result predictably. 92 | This function successfully passes all SMHasher tests. 93 | Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s 94 | XXH64() : 95 | Calculate the 64-bits hash of sequence of length "len" stored at memory address "input". 96 | */ 97 | 98 | 99 | 100 | /***************************** 101 | Advanced Hash Functions 102 | *****************************/ 103 | typedef struct { long long ll[ 6]; } XXH32_state_t; 104 | typedef struct { long long ll[11]; } XXH64_state_t; 105 | 106 | /* 107 | These structures allow static allocation of XXH states. 108 | States must then be initialized using XXHnn_reset() before first use. 109 | 110 | If you prefer dynamic allocation, please refer to functions below. 111 | */ 112 | 113 | /* 114 | * !!! 115 | * Rspamd specific: we use the legacy method to free state when digest is obtained 116 | * !!! 117 | */ 118 | void * XXH32_init (unsigned seed); 119 | XXH32_state_t* XXH32_createState(void); 120 | XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); 121 | 122 | XXH64_state_t* XXH64_createState(void); 123 | XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); 124 | 125 | /* 126 | These functions create and release memory for XXH state. 127 | States must then be initialized using XXHnn_reset() before first use. 128 | */ 129 | 130 | 131 | XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned seed); 132 | XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); 133 | unsigned int XXH32_digest (const XXH32_state_t* statePtr); 134 | 135 | XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed); 136 | XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); 137 | unsigned long long XXH64_digest (const XXH64_state_t* statePtr); 138 | 139 | /* 140 | These functions calculate the xxHash of an input provided in multiple smaller packets, 141 | as opposed to an input provided as a single block. 142 | 143 | XXH state space must first be allocated, using either static or dynamic method provided above. 144 | 145 | Start a new hash by initializing state with a seed, using XXHnn_reset(). 146 | 147 | Then, feed the hash state by calling XXHnn_update() as many times as necessary. 148 | Obviously, input must be valid, meaning allocated and read accessible. 149 | The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. 150 | 151 | Finally, you can produce a hash anytime, by using XXHnn_digest(). 152 | This function returns the final nn-bits hash. 153 | You can nonetheless continue feeding the hash state with more input, 154 | and therefore get some new hashes, by calling again XXHnn_digest(). 155 | 156 | When you are done, don't forget to free XXH state space, using typically XXHnn_freeState(). 157 | */ 158 | 159 | 160 | #if defined (__cplusplus) 161 | } 162 | #endif 163 | -------------------------------------------------------------------------------- /contrib/zstd/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | SET(ZSTDSRC divsufsort.c 2 | entropy_common.c 3 | fse_compress.c 4 | fse_decompress.c 5 | huf_compress.c 6 | huf_decompress.c 7 | zbuff_compress.c 8 | zbuff_decompress.c 9 | zdict.c 10 | zstd_common.c 11 | zstd_compress.c 12 | zstd_decompress.c) 13 | 14 | ADD_LIBRARY(rmilter-zstd STATIC ${ZSTDSRC}) 15 | if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") 16 | SET_TARGET_PROPERTIES(rmilter-zstd PROPERTIES COMPILE_FLAGS "-O3") 17 | endif () 18 | -------------------------------------------------------------------------------- /contrib/zstd/LICENSE: -------------------------------------------------------------------------------- 1 | BSD License 2 | 3 | For Zstandard software 4 | 5 | Copyright (c) 2016-present, Facebook, Inc. All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, 8 | are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name Facebook nor the names of its contributors may be used to 18 | endorse or promote products derived from this software without specific 19 | prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 25 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /contrib/zstd/PATENTS: -------------------------------------------------------------------------------- 1 | Additional Grant of Patent Rights Version 2 2 | 3 | "Software" means the Zstandard software distributed by Facebook, Inc. 4 | 5 | Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software 6 | ("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable 7 | (subject to the termination provision below) license under any Necessary 8 | Claims, to make, have made, use, sell, offer to sell, import, and otherwise 9 | transfer the Software. For avoidance of doubt, no license is granted under 10 | Facebook’s rights in any patent claims that are infringed by (i) modifications 11 | to the Software made by you or any third party or (ii) the Software in 12 | combination with any software or other technology. 13 | 14 | The license granted hereunder will terminate, automatically and without notice, 15 | if you (or any of your subsidiaries, corporate affiliates or agents) initiate 16 | directly or indirectly, or take a direct financial interest in, any Patent 17 | Assertion: (i) against Facebook or any of its subsidiaries or corporate 18 | affiliates, (ii) against any party if such Patent Assertion arises in whole or 19 | in part from any software, technology, product or service of Facebook or any of 20 | its subsidiaries or corporate affiliates, or (iii) against any party relating 21 | to the Software. Notwithstanding the foregoing, if Facebook or any of its 22 | subsidiaries or corporate affiliates files a lawsuit alleging patent 23 | infringement against you in the first instance, and you respond by filing a 24 | patent infringement counterclaim in that lawsuit against that party that is 25 | unrelated to the Software, the license granted hereunder will not terminate 26 | under section (i) of this paragraph due to such counterclaim. 27 | 28 | A "Necessary Claim" is a claim of a patent owned by Facebook that is 29 | necessarily infringed by the Software standing alone. 30 | 31 | A "Patent Assertion" is any lawsuit or other action alleging direct, indirect, 32 | or contributory infringement or inducement to infringe any patent, including a 33 | cross-claim or counterclaim. 34 | -------------------------------------------------------------------------------- /contrib/zstd/README.md: -------------------------------------------------------------------------------- 1 | **Zstd**, short for Zstandard, is a fast lossless compression algorithm, 2 | targeting real-time compression scenarios at zlib-level and better compression ratios. 3 | 4 | It is provided as an open-source BSD-licensed **C** library. 5 | For other programming languages, 6 | you can consult a list of known ports on [Zstandard homepage](http://www.zstd.net/#other-languages). 7 | 8 | |Branch |Status | 9 | |------------|---------| 10 | |master | [![Build Status](https://travis-ci.org/facebook/zstd.svg?branch=master)](https://travis-ci.org/facebook/zstd) | 11 | |dev | [![Build Status](https://travis-ci.org/facebook/zstd.svg?branch=dev)](https://travis-ci.org/facebook/zstd) | 12 | 13 | As a reference, several fast compression algorithms were tested and compared on a Core i7-3930K CPU @ 4.5GHz, using [lzbench], an open-source in-memory benchmark by @inikep compiled with gcc 5.4.0, with the [Silesia compression corpus]. 14 | 15 | [lzbench]: https://github.com/inikep/lzbench 16 | [Silesia compression corpus]: http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia 17 | 18 | 19 | |Name | Ratio | C.speed | D.speed | 20 | |-----------------|-------|--------:|--------:| 21 | | | | MB/s | MB/s | 22 | |**zstd 0.8.2 -1**|**2.877**|**330**| **940** | 23 | | [zlib] 1.2.8 -1 | 2.730 | 95 | 360 | 24 | | brotli 0.4 -0 | 2.708 | 320 | 375 | 25 | | QuickLZ 1.5 | 2.237 | 510 | 605 | 26 | | LZO 2.09 | 2.106 | 610 | 870 | 27 | | [LZ4] r131 | 2.101 | 620 | 3100 | 28 | | Snappy 1.1.3 | 2.091 | 480 | 1600 | 29 | | LZF 3.6 | 2.077 | 375 | 790 | 30 | 31 | [zlib]:http://www.zlib.net/ 32 | [LZ4]: http://www.lz4.org/ 33 | 34 | Zstd can also offer stronger compression ratios at the cost of compression speed. 35 | Speed vs Compression trade-off is configurable by small increment. Decompression speed is preserved and remain roughly the same at all settings, a property shared by most LZ compression algorithms, such as [zlib] or lzma. 36 | 37 | The following tests were run on a Core i7-3930K CPU @ 4.5GHz, using [lzbench], an open-source in-memory benchmark by @inikep compiled with gcc 5.2.1, on the [Silesia compression corpus]. 38 | 39 | Compression Speed vs Ratio | Decompression Speed 40 | ---------------------------|-------------------- 41 | ![Compression Speed vs Ratio](images/Cspeed4.png "Compression Speed vs Ratio") | ![Decompression Speed](images/Dspeed4.png "Decompression Speed") 42 | 43 | Several algorithms can produce higher compression ratio but at slower speed, falling outside of the graph. 44 | For a larger picture including very slow modes, [click on this link](images/DCspeed5.png) . 45 | 46 | 47 | ### The case for Small Data compression 48 | 49 | Previous charts provide results applicable to typical files and streams scenarios (several MB). Small data come with different perspectives. The smaller the amount of data to compress, the more difficult it is to achieve any significant compression. 50 | 51 | This problem is common to any compression algorithm. The reason is, compression algorithms learn from past data how to compress future data. But at the beginning of a new file, there is no "past" to build upon. 52 | 53 | To solve this situation, Zstd offers a __training mode__, which can be used to tune the algorithm for a selected type of data, by providing it with a few samples. The result of the training is stored in a file called "dictionary", which can be loaded before compression and decompression. Using this dictionary, the compression ratio achievable on small data improves dramatically : 54 | 55 | ![Compressing Small Data](images/smallData.png "Compressing Small Data") 56 | 57 | These compression gains are achieved while simultaneously providing faster compression and decompression speeds. 58 | 59 | Dictionary work if there is some correlation in a family of small data (there is no _universal dictionary_). 60 | Hence, deploying one dictionary per type of data will provide the greater benefits. Dictionary gains are mostly effective in the first few KB. Then, the compression algorithm will rely more and more on previously decoded content to compress the rest of the file. 61 | 62 | #### Dictionary compression How To : 63 | 64 | 1) Create the dictionary 65 | 66 | `zstd --train FullPathToTrainingSet/* -o dictionaryName` 67 | 68 | 2) Compress with dictionary 69 | 70 | `zstd FILE -D dictionaryName` 71 | 72 | 3) Decompress with dictionary 73 | 74 | `zstd --decompress FILE.zst -D dictionaryName` 75 | 76 | ### Status 77 | 78 | Zstandard is currently deployed within Facebook. It is used daily to compress and decompress very large amount of data in multiple formats and use cases. 79 | Zstandard is considered safe for production environments. 80 | 81 | ### License 82 | 83 | Zstandard is [BSD-licensed](LICENSE). We also provide an [additional patent grant](PATENTS). 84 | 85 | ### Contributing 86 | 87 | The "dev" branch is the one where all contributions will be merged before reaching "master". 88 | If you plan to propose a patch, please commit into the "dev" branch or its own feature branch. 89 | Direct commit to "master" are not permitted. 90 | For more information, please read [CONTRIBUTING](CONTRIBUTING.md). 91 | 92 | ### Miscellaneous 93 | 94 | Zstd entropy stage is provided by [Huff0 and FSE, from Finite State Entropy library](https://github.com/Cyan4973/FiniteStateEntropy). 95 | -------------------------------------------------------------------------------- /contrib/zstd/divsufsort.h: -------------------------------------------------------------------------------- 1 | /* 2 | * divsufsort.h for libdivsufsort-lite 3 | * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, 9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following 12 | * conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | * OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | #ifndef _DIVSUFSORT_H 28 | #define _DIVSUFSORT_H 1 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif /* __cplusplus */ 33 | 34 | 35 | /*- Prototypes -*/ 36 | 37 | /** 38 | * Constructs the suffix array of a given string. 39 | * @param T [0..n-1] The input string. 40 | * @param SA [0..n-1] The output array of suffixes. 41 | * @param n The length of the given string. 42 | * @param openMP enables OpenMP optimization. 43 | * @return 0 if no error occurred, -1 or -2 otherwise. 44 | */ 45 | int 46 | divsufsort(const unsigned char *T, int *SA, int n, int openMP); 47 | 48 | /** 49 | * Constructs the burrows-wheeler transformed string of a given string. 50 | * @param T [0..n-1] The input string. 51 | * @param U [0..n-1] The output string. (can be T) 52 | * @param A [0..n-1] The temporary array. (can be NULL) 53 | * @param n The length of the given string. 54 | * @param num_indexes The length of secondary indexes array. (can be NULL) 55 | * @param indexes The secondary indexes array. (can be NULL) 56 | * @param openMP enables OpenMP optimization. 57 | * @return The primary index if no error occurred, -1 or -2 otherwise. 58 | */ 59 | int 60 | divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP); 61 | 62 | 63 | #ifdef __cplusplus 64 | } /* extern "C" */ 65 | #endif /* __cplusplus */ 66 | 67 | #endif /* _DIVSUFSORT_H */ 68 | -------------------------------------------------------------------------------- /contrib/zstd/entropy_common.c: -------------------------------------------------------------------------------- 1 | /* 2 | Common functions of New Generation Entropy library 3 | Copyright (C) 2016, Yann Collet. 4 | 5 | BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are 9 | met: 10 | 11 | * Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above 14 | copyright notice, this list of conditions and the following disclaimer 15 | in the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | You can contact the author at : 31 | - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy 32 | - Public forum : https://groups.google.com/forum/#!forum/lz4c 33 | *************************************************************************** */ 34 | 35 | /* ************************************* 36 | * Dependencies 37 | ***************************************/ 38 | #include "mem.h" 39 | #include "error_private.h" /* ERR_*, ERROR */ 40 | #define FSE_STATIC_LINKING_ONLY /* FSE_MIN_TABLELOG */ 41 | #include "fse.h" 42 | #define HUF_STATIC_LINKING_ONLY /* HUF_TABLELOG_ABSOLUTEMAX */ 43 | #include "huf.h" 44 | 45 | 46 | /*-**************************************** 47 | * FSE Error Management 48 | ******************************************/ 49 | unsigned FSE_isError(size_t code) { return ERR_isError(code); } 50 | 51 | const char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); } 52 | 53 | 54 | /* ************************************************************** 55 | * HUF Error Management 56 | ****************************************************************/ 57 | unsigned HUF_isError(size_t code) { return ERR_isError(code); } 58 | 59 | const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); } 60 | 61 | 62 | /*-************************************************************** 63 | * FSE NCount encoding-decoding 64 | ****************************************************************/ 65 | static short FSE_abs(short a) { return (short)(a<0 ? -a : a); } 66 | 67 | size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, 68 | const void* headerBuffer, size_t hbSize) 69 | { 70 | const BYTE* const istart = (const BYTE*) headerBuffer; 71 | const BYTE* const iend = istart + hbSize; 72 | const BYTE* ip = istart; 73 | int nbBits; 74 | int remaining; 75 | int threshold; 76 | U32 bitStream; 77 | int bitCount; 78 | unsigned charnum = 0; 79 | int previous0 = 0; 80 | 81 | if (hbSize < 4) return ERROR(srcSize_wrong); 82 | bitStream = MEM_readLE32(ip); 83 | nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */ 84 | if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge); 85 | bitStream >>= 4; 86 | bitCount = 4; 87 | *tableLogPtr = nbBits; 88 | remaining = (1<1) & (charnum<=*maxSVPtr)) { 93 | if (previous0) { 94 | unsigned n0 = charnum; 95 | while ((bitStream & 0xFFFF) == 0xFFFF) { 96 | n0 += 24; 97 | if (ip < iend-5) { 98 | ip += 2; 99 | bitStream = MEM_readLE32(ip) >> bitCount; 100 | } else { 101 | bitStream >>= 16; 102 | bitCount += 16; 103 | } } 104 | while ((bitStream & 3) == 3) { 105 | n0 += 3; 106 | bitStream >>= 2; 107 | bitCount += 2; 108 | } 109 | n0 += bitStream & 3; 110 | bitCount += 2; 111 | if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall); 112 | while (charnum < n0) normalizedCounter[charnum++] = 0; 113 | if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { 114 | ip += bitCount>>3; 115 | bitCount &= 7; 116 | bitStream = MEM_readLE32(ip) >> bitCount; 117 | } else { 118 | bitStream >>= 2; 119 | } } 120 | { short const max = (short)((2*threshold-1)-remaining); 121 | short count; 122 | 123 | if ((bitStream & (threshold-1)) < (U32)max) { 124 | count = (short)(bitStream & (threshold-1)); 125 | bitCount += nbBits-1; 126 | } else { 127 | count = (short)(bitStream & (2*threshold-1)); 128 | if (count >= threshold) count -= max; 129 | bitCount += nbBits; 130 | } 131 | 132 | count--; /* extra accuracy */ 133 | remaining -= FSE_abs(count); 134 | normalizedCounter[charnum++] = count; 135 | previous0 = !count; 136 | while (remaining < threshold) { 137 | nbBits--; 138 | threshold >>= 1; 139 | } 140 | 141 | if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { 142 | ip += bitCount>>3; 143 | bitCount &= 7; 144 | } else { 145 | bitCount -= (int)(8 * (iend - 4 - ip)); 146 | ip = iend - 4; 147 | } 148 | bitStream = MEM_readLE32(ip) >> (bitCount & 31); 149 | } } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */ 150 | if (remaining != 1) return ERROR(corruption_detected); 151 | if (bitCount > 32) return ERROR(corruption_detected); 152 | *maxSVPtr = charnum-1; 153 | 154 | ip += (bitCount+7)>>3; 155 | return ip-istart; 156 | } 157 | 158 | 159 | /*! HUF_readStats() : 160 | Read compact Huffman tree, saved by HUF_writeCTable(). 161 | `huffWeight` is destination buffer. 162 | @return : size read from `src` , or an error Code . 163 | Note : Needed by HUF_readCTable() and HUF_readDTableX?() . 164 | */ 165 | size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, 166 | U32* nbSymbolsPtr, U32* tableLogPtr, 167 | const void* src, size_t srcSize) 168 | { 169 | U32 weightTotal; 170 | const BYTE* ip = (const BYTE*) src; 171 | size_t iSize = ip[0]; 172 | size_t oSize; 173 | 174 | /* memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */ 175 | 176 | if (iSize >= 128) { /* special header */ 177 | oSize = iSize - 127; 178 | iSize = ((oSize+1)/2); 179 | if (iSize+1 > srcSize) return ERROR(srcSize_wrong); 180 | if (oSize >= hwSize) return ERROR(corruption_detected); 181 | ip += 1; 182 | { U32 n; 183 | for (n=0; n> 4; 185 | huffWeight[n+1] = ip[n/2] & 15; 186 | } } } 187 | else { /* header compressed with FSE (normal case) */ 188 | if (iSize+1 > srcSize) return ERROR(srcSize_wrong); 189 | oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize); /* max (hwSize-1) values decoded, as last one is implied */ 190 | if (FSE_isError(oSize)) return oSize; 191 | } 192 | 193 | /* collect weight stats */ 194 | memset(rankStats, 0, (HUF_TABLELOG_ABSOLUTEMAX + 1) * sizeof(U32)); 195 | weightTotal = 0; 196 | { U32 n; for (n=0; n= HUF_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected); 198 | rankStats[huffWeight[n]]++; 199 | weightTotal += (1 << huffWeight[n]) >> 1; 200 | } } 201 | 202 | /* get last non-null symbol weight (implied, total must be 2^n) */ 203 | { U32 const tableLog = BIT_highbit32(weightTotal) + 1; 204 | if (tableLog > HUF_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected); 205 | *tableLogPtr = tableLog; 206 | /* determine last weight */ 207 | { U32 const total = 1 << tableLog; 208 | U32 const rest = total - weightTotal; 209 | U32 const verif = 1 << BIT_highbit32(rest); 210 | U32 const lastWeight = BIT_highbit32(rest) + 1; 211 | if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */ 212 | huffWeight[oSize] = (BYTE)lastWeight; 213 | rankStats[lastWeight]++; 214 | } } 215 | 216 | /* check tree construction validity */ 217 | if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */ 218 | 219 | /* results */ 220 | *nbSymbolsPtr = (U32)(oSize+1); 221 | return iSize+1; 222 | } 223 | -------------------------------------------------------------------------------- /contrib/zstd/error_private.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | /* Note : this module is expected to remain private, do not expose it */ 11 | 12 | #ifndef ERROR_H_MODULE 13 | #define ERROR_H_MODULE 14 | 15 | #if defined (__cplusplus) 16 | extern "C" { 17 | #endif 18 | 19 | 20 | /* **************************************** 21 | * Dependencies 22 | ******************************************/ 23 | #include /* size_t */ 24 | #include "error_public.h" /* enum list */ 25 | 26 | 27 | /* **************************************** 28 | * Compiler-specific 29 | ******************************************/ 30 | #if defined(__GNUC__) 31 | # define ERR_STATIC static __attribute__((unused)) 32 | #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) 33 | # define ERR_STATIC static inline 34 | #elif defined(_MSC_VER) 35 | # define ERR_STATIC static __inline 36 | #else 37 | # define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ 38 | #endif 39 | 40 | 41 | /*-**************************************** 42 | * Customization (error_public.h) 43 | ******************************************/ 44 | typedef ZSTD_ErrorCode ERR_enum; 45 | #define PREFIX(name) ZSTD_error_##name 46 | 47 | 48 | /*-**************************************** 49 | * Error codes handling 50 | ******************************************/ 51 | #ifdef ERROR 52 | # undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */ 53 | #endif 54 | #define ERROR(name) ((size_t)-PREFIX(name)) 55 | 56 | ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); } 57 | 58 | ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); } 59 | 60 | 61 | /*-**************************************** 62 | * Error Strings 63 | ******************************************/ 64 | 65 | ERR_STATIC const char* ERR_getErrorString(ERR_enum code) 66 | { 67 | static const char* notErrorCode = "Unspecified error code"; 68 | switch( code ) 69 | { 70 | case PREFIX(no_error): return "No error detected"; 71 | case PREFIX(GENERIC): return "Error (generic)"; 72 | case PREFIX(prefix_unknown): return "Unknown frame descriptor"; 73 | case PREFIX(version_unsupported): return "Version not supported"; 74 | case PREFIX(parameter_unknown): return "Unknown parameter type"; 75 | case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter"; 76 | case PREFIX(frameParameter_unsupportedBy32bits): return "Frame parameter unsupported in 32-bits mode"; 77 | case PREFIX(compressionParameter_unsupported): return "Compression parameter is out of bound"; 78 | case PREFIX(init_missing): return "Context should be init first"; 79 | case PREFIX(memory_allocation): return "Allocation error : not enough memory"; 80 | case PREFIX(stage_wrong): return "Operation not authorized at current processing stage"; 81 | case PREFIX(dstSize_tooSmall): return "Destination buffer is too small"; 82 | case PREFIX(srcSize_wrong): return "Src size incorrect"; 83 | case PREFIX(corruption_detected): return "Corrupted block detected"; 84 | case PREFIX(checksum_wrong): return "Restored data doesn't match checksum"; 85 | case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported"; 86 | case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large"; 87 | case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small"; 88 | case PREFIX(dictionary_corrupted): return "Dictionary is corrupted"; 89 | case PREFIX(dictionary_wrong): return "Dictionary mismatch"; 90 | case PREFIX(maxCode): 91 | default: return notErrorCode; 92 | } 93 | } 94 | 95 | ERR_STATIC const char* ERR_getErrorName(size_t code) 96 | { 97 | return ERR_getErrorString(ERR_getErrorCode(code)); 98 | } 99 | 100 | #if defined (__cplusplus) 101 | } 102 | #endif 103 | 104 | #endif /* ERROR_H_MODULE */ 105 | -------------------------------------------------------------------------------- /contrib/zstd/error_public.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #ifndef ERROR_PUBLIC_H_MODULE 11 | #define ERROR_PUBLIC_H_MODULE 12 | 13 | #if defined (__cplusplus) 14 | extern "C" { 15 | #endif 16 | 17 | /*===== dependency =====*/ 18 | #include /* size_t */ 19 | 20 | 21 | /*-**************************************** 22 | * error codes list 23 | ******************************************/ 24 | typedef enum { 25 | ZSTD_error_no_error, 26 | ZSTD_error_GENERIC, 27 | ZSTD_error_prefix_unknown, 28 | ZSTD_error_version_unsupported, 29 | ZSTD_error_parameter_unknown, 30 | ZSTD_error_frameParameter_unsupported, 31 | ZSTD_error_frameParameter_unsupportedBy32bits, 32 | ZSTD_error_compressionParameter_unsupported, 33 | ZSTD_error_init_missing, 34 | ZSTD_error_memory_allocation, 35 | ZSTD_error_stage_wrong, 36 | ZSTD_error_dstSize_tooSmall, 37 | ZSTD_error_srcSize_wrong, 38 | ZSTD_error_corruption_detected, 39 | ZSTD_error_checksum_wrong, 40 | ZSTD_error_tableLog_tooLarge, 41 | ZSTD_error_maxSymbolValue_tooLarge, 42 | ZSTD_error_maxSymbolValue_tooSmall, 43 | ZSTD_error_dictionary_corrupted, 44 | ZSTD_error_dictionary_wrong, 45 | ZSTD_error_maxCode 46 | } ZSTD_ErrorCode; 47 | 48 | /*! ZSTD_getErrorCode() : 49 | convert a `size_t` function result into a `ZSTD_ErrorCode` enum type, 50 | which can be used to compare directly with enum list published into "error_public.h" */ 51 | ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult); 52 | const char* ZSTD_getErrorString(ZSTD_ErrorCode code); 53 | 54 | 55 | #if defined (__cplusplus) 56 | } 57 | #endif 58 | 59 | #endif /* ERROR_PUBLIC_H_MODULE */ 60 | -------------------------------------------------------------------------------- /contrib/zstd/zdict.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #ifndef DICTBUILDER_H_001 11 | #define DICTBUILDER_H_001 12 | 13 | #if defined (__cplusplus) 14 | extern "C" { 15 | #endif 16 | 17 | 18 | /*====== Dependencies ======*/ 19 | #include /* size_t */ 20 | 21 | 22 | /*====== Export for Windows ======*/ 23 | /*! 24 | * ZSTD_DLL_EXPORT : 25 | * Enable exporting of functions when building a Windows DLL 26 | */ 27 | #if defined(_WIN32) && defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) 28 | # define ZDICTLIB_API __declspec(dllexport) 29 | #else 30 | # define ZDICTLIB_API 31 | #endif 32 | 33 | 34 | /*! ZDICT_trainFromBuffer() : 35 | Train a dictionary from an array of samples. 36 | Samples must be stored concatenated in a single flat buffer `samplesBuffer`, 37 | supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order. 38 | The resulting dictionary will be saved into `dictBuffer`. 39 | @return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) 40 | or an error code, which can be tested with ZDICT_isError(). 41 | Tips : In general, a reasonable dictionary has a size of ~ 100 KB. 42 | It's obviously possible to target smaller or larger ones, just by specifying different `dictBufferCapacity`. 43 | In general, it's recommended to provide a few thousands samples, but this can vary a lot. 44 | It's recommended that total size of all samples be about ~x100 times the target size of dictionary. 45 | */ 46 | ZDICTLIB_API size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCapacity, 47 | const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples); 48 | 49 | 50 | /*====== Helper functions ======*/ 51 | ZDICTLIB_API unsigned ZDICT_getDictID(const void* dictBuffer, size_t dictSize); /**< extracts dictID; @return zero if error (not a valid dictionary) */ 52 | ZDICTLIB_API unsigned ZDICT_isError(size_t errorCode); 53 | ZDICTLIB_API const char* ZDICT_getErrorName(size_t errorCode); 54 | 55 | 56 | 57 | #ifdef ZDICT_STATIC_LINKING_ONLY 58 | 59 | /* ==================================================================================== 60 | * The definitions in this section are considered experimental. 61 | * They should never be used with a dynamic library, as they may change in the future. 62 | * They are provided for advanced usages. 63 | * Use them only in association with static linking. 64 | * ==================================================================================== */ 65 | 66 | typedef struct { 67 | unsigned selectivityLevel; /* 0 means default; larger => select more => larger dictionary */ 68 | int compressionLevel; /* 0 means default; target a specific zstd compression level */ 69 | unsigned notificationLevel; /* Write to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */ 70 | unsigned dictID; /* 0 means auto mode (32-bits random value); other : force dictID value */ 71 | unsigned reserved[2]; /* space for future parameters */ 72 | } ZDICT_params_t; 73 | 74 | 75 | /*! ZDICT_trainFromBuffer_advanced() : 76 | Same as ZDICT_trainFromBuffer() with control over more parameters. 77 | `parameters` is optional and can be provided with values set to 0 to mean "default". 78 | @return : size of dictionary stored into `dictBuffer` (<= `dictBufferSize`), 79 | or an error code, which can be tested by ZDICT_isError(). 80 | note : ZDICT_trainFromBuffer_advanced() will send notifications into stderr if instructed to, using notificationLevel>0. 81 | */ 82 | size_t ZDICT_trainFromBuffer_advanced(void* dictBuffer, size_t dictBufferCapacity, 83 | const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples, 84 | ZDICT_params_t parameters); 85 | 86 | 87 | /*! ZDICT_addEntropyTablesFromBuffer() : 88 | 89 | Given a content-only dictionary (built using any 3rd party algorithm), 90 | add entropy tables computed from an array of samples. 91 | Samples must be stored concatenated in a flat buffer `samplesBuffer`, 92 | supplied with an array of sizes `samplesSizes`, providing the size of each sample in order. 93 | 94 | The input dictionary content must be stored *at the end* of `dictBuffer`. 95 | Its size is `dictContentSize`. 96 | The resulting dictionary with added entropy tables will be *written back to `dictBuffer`*, 97 | starting from its beginning. 98 | @return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`). 99 | */ 100 | size_t ZDICT_addEntropyTablesFromBuffer(void* dictBuffer, size_t dictContentSize, size_t dictBufferCapacity, 101 | const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples); 102 | 103 | 104 | 105 | #endif /* ZDICT_STATIC_LINKING_ONLY */ 106 | 107 | #if defined (__cplusplus) 108 | } 109 | #endif 110 | 111 | #endif /* DICTBUILDER_H_001 */ 112 | -------------------------------------------------------------------------------- /contrib/zstd/zstd_common.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | 11 | 12 | /*-************************************* 13 | * Dependencies 14 | ***************************************/ 15 | #include /* malloc */ 16 | #include "error_private.h" 17 | #define ZSTD_STATIC_LINKING_ONLY 18 | #include "zstd.h" /* declaration of ZSTD_isError, ZSTD_getErrorName, ZSTD_getErrorCode, ZSTD_getErrorString, ZSTD_versionNumber */ 19 | #include "zbuff.h" /* declaration of ZBUFF_isError, ZBUFF_getErrorName */ 20 | 21 | 22 | /*-**************************************** 23 | * Version 24 | ******************************************/ 25 | unsigned ZSTD_versionNumber (void) { return ZSTD_VERSION_NUMBER; } 26 | 27 | 28 | /*-**************************************** 29 | * ZSTD Error Management 30 | ******************************************/ 31 | /*! ZSTD_isError() : 32 | * tells if a return value is an error code */ 33 | unsigned ZSTD_isError(size_t code) { return ERR_isError(code); } 34 | 35 | /*! ZSTD_getErrorName() : 36 | * provides error code string from function result (useful for debugging) */ 37 | const char* ZSTD_getErrorName(size_t code) { return ERR_getErrorName(code); } 38 | 39 | /*! ZSTD_getError() : 40 | * convert a `size_t` function result into a proper ZSTD_errorCode enum */ 41 | ZSTD_ErrorCode ZSTD_getErrorCode(size_t code) { return ERR_getErrorCode(code); } 42 | 43 | /*! ZSTD_getErrorString() : 44 | * provides error code string from enum */ 45 | const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorName(code); } 46 | 47 | 48 | /* ************************************************************** 49 | * ZBUFF Error Management 50 | ****************************************************************/ 51 | unsigned ZBUFF_isError(size_t errorCode) { return ERR_isError(errorCode); } 52 | 53 | const char* ZBUFF_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); } 54 | 55 | 56 | 57 | /*=************************************************************** 58 | * Custom allocator 59 | ****************************************************************/ 60 | /* default uses stdlib */ 61 | void* ZSTD_defaultAllocFunction(void* opaque, size_t size) 62 | { 63 | void* address = malloc(size); 64 | (void)opaque; 65 | return address; 66 | } 67 | 68 | void ZSTD_defaultFreeFunction(void* opaque, void* address) 69 | { 70 | (void)opaque; 71 | free(address); 72 | } 73 | 74 | void* ZSTD_malloc(size_t size, ZSTD_customMem customMem) 75 | { 76 | return customMem.customAlloc(customMem.opaque, size); 77 | } 78 | 79 | void ZSTD_free(void* ptr, ZSTD_customMem customMem) 80 | { 81 | if (ptr!=NULL) 82 | customMem.customFree(customMem.opaque, ptr); 83 | } 84 | -------------------------------------------------------------------------------- /contrib/zstd/zstd_internal.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #ifndef ZSTD_CCOMMON_H_MODULE 11 | #define ZSTD_CCOMMON_H_MODULE 12 | 13 | /*-************************************* 14 | * Dependencies 15 | ***************************************/ 16 | #include "mem.h" 17 | #include "error_private.h" 18 | #define ZSTD_STATIC_LINKING_ONLY 19 | #include "zstd.h" 20 | 21 | 22 | /*-************************************* 23 | * Common macros 24 | ***************************************/ 25 | #define MIN(a,b) ((a)<(b) ? (a) : (b)) 26 | #define MAX(a,b) ((a)>(b) ? (a) : (b)) 27 | 28 | 29 | /*-************************************* 30 | * Common constants 31 | ***************************************/ 32 | #define ZSTD_OPT_NUM (1<<12) 33 | #define ZSTD_DICT_MAGIC 0xEC30A437 /* v0.7+ */ 34 | 35 | #define ZSTD_REP_NUM 3 /* number of repcodes */ 36 | #define ZSTD_REP_CHECK (ZSTD_REP_NUM) /* number of repcodes to check by the optimal parser */ 37 | #define ZSTD_REP_MOVE (ZSTD_REP_NUM-1) 38 | #define ZSTD_REP_MOVE_OPT (ZSTD_REP_NUM) 39 | static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 }; 40 | 41 | #define KB *(1 <<10) 42 | #define MB *(1 <<20) 43 | #define GB *(1U<<30) 44 | 45 | #define BIT7 128 46 | #define BIT6 64 47 | #define BIT5 32 48 | #define BIT4 16 49 | #define BIT1 2 50 | #define BIT0 1 51 | 52 | #define ZSTD_WINDOWLOG_ABSOLUTEMIN 10 53 | static const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 }; 54 | static const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 }; 55 | 56 | #define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */ 57 | static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE; 58 | typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e; 59 | 60 | #define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */ 61 | #define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */ 62 | 63 | #define HufLog 12 64 | typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingType_e; 65 | 66 | #define LONGNBSEQ 0x7F00 67 | 68 | #define MINMATCH 3 69 | #define EQUAL_READ32 4 70 | 71 | #define Litbits 8 72 | #define MaxLit ((1<= 3) /* GCC Intrinsic */ 214 | return 31 - __builtin_clz(val); 215 | # else /* Software version */ 216 | static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; 217 | U32 v = val; 218 | int r; 219 | v |= v >> 1; 220 | v |= v >> 2; 221 | v |= v >> 4; 222 | v |= v >> 8; 223 | v |= v >> 16; 224 | r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27]; 225 | return r; 226 | # endif 227 | } 228 | 229 | 230 | #endif /* ZSTD_CCOMMON_H_MODULE */ 231 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | rmilter (1.6.7) unstable; urgency=low 2 | 3 | * New release. 4 | 5 | -- Vsevolod Stakhov Wed, 18 Nov 2015 22:11:32 +0000 6 | 7 | rmilter (1.6.5) unstable; urgency=low 8 | 9 | * File 'debian/rmilter.install' was added in order to fix empty-binary-package error. 10 | * Dbg package was included. 11 | 12 | -- Vitaly Isaev Thu, 12 Nov 2015 18:00:00 +0200 13 | 14 | rmilter (1.6.3) unstable; urgency=low 15 | 16 | * New release. 17 | 18 | -- Mikhail Gusarov Sat, 18 Jul 2015 22:11:32 +0200 19 | 20 | rmilter (1.6.2) unstable; urgency=low 21 | 22 | * Use systemd socket activation. 23 | * Bump Standards-Version to 3.9.6, no changes required 24 | 25 | -- Mikhail Gusarov Sat, 21 Feb 2015 18:40:13 +0100 26 | 27 | rmilter (1.6.1) unstable; urgency=medium 28 | 29 | * Initial upload (Closes: #741161) 30 | 31 | -- Mikhail Gusarov Mon, 10 Mar 2014 00:55:10 +0100 32 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: rmilter 2 | Section: mail 3 | Priority: extra 4 | Maintainer: Mikhail Gusarov 5 | Build-Depends: bison, cmake, debhelper (>= 9), dh-systemd, dpkg-dev (>= 1.16.1~), flex, libglib2.0-dev, libmilter-dev, libopendkim-dev, libpcre3-dev, libssl-dev (>= 1.0) 6 | Standards-Version: 3.9.6 7 | Homepage: https://github.com/vstakhov/rmilter 8 | Vcs-Git: https://github.com/vstakhov/rmilter.git 9 | Vcs-Browser: https://github.com/vstakhov/rmilter 10 | 11 | Package: rmilter 12 | Architecture: any 13 | Depends: adduser, libmilter1.0.1, lsb-base, ${misc:Depends}, ${shlibs:Depends} 14 | Recommends: sendmail | postfix 15 | Description: Another sendmail milter for different mail checks 16 | rmilter is a standalone application that provides the following features: 17 | SPF checks; 18 | greylisting using memcached storage; 19 | ratelimits using memcached storage; 20 | checking mail via rspamd/spamassassin; 21 | checking mail via clamav antivirus; 22 | regexp filters; 23 | DKIM signing; 24 | beanstalk operations for specific messages. 25 | . 26 | Rmilter uses sendmail milter interface and is compatible with Sendmail 27 | and Postfix MTA as well as with other MTA that supports milter interface. 28 | 29 | Package: rmilter-dbg 30 | Architecture: any 31 | Section: debug 32 | Depends: rmilter (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} 33 | Description: Debuginfo for another sendmail milter for different mail checks 34 | rmilter is a standalone application that provides the following features: 35 | SPF checks; 36 | greylisting using memcached storage; 37 | ratelimits using memcached storage; 38 | checking mail via rspamd/spamassassin; 39 | checking mail via clamav antivirus; 40 | regexp filters; 41 | DKIM signing; 42 | beanstalk operations for specific messages. 43 | . 44 | Rmilter uses sendmail milter interface and is compatible with Sendmail 45 | and Postfix MTA as well as with other MTA that supports milter interface. 46 | . 47 | This package contains the debugging information for rmilter package. 48 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: rmilter 3 | Upstream-Contact: Vsevolod Stakhov 4 | Source: https://bitbucket.org/vstakhov/rmilter 5 | 6 | Files: * 7 | Copyright: 2007-2012 Vsevolod Stakhov 8 | License: BSD-2-clause 9 | 10 | Files: uthash/* 11 | Copyright: 2008-2012, Troy D. Hanson 12 | License: BSD-1-clause 13 | 14 | Files: compat/blake2* 15 | Copyright: 2012 Samuel Neves 16 | License: CC0 17 | 18 | Files: debian/* 19 | Copyright: 2014-2015 Mikhail Gusarov 20 | License: BSD-2-clause 21 | 22 | License: BSD-1-clause 23 | Redistribution and use in source and binary forms, with or without 24 | modification, are permitted provided that the following conditions are met: 25 | . 26 | Redistributions of source code must retain the above copyright 27 | notice, this list of conditions and the following disclaimer. 28 | . 29 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 30 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 31 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 32 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 33 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 34 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 35 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 36 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 37 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 38 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 39 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 | 41 | License: BSD-2-clause 42 | Redistribution and use in source and binary forms, with or without 43 | modification, are permitted provided that the following conditions are met: 44 | . 45 | Redistributions of source code must retain the above copyright notice, this 46 | list of conditions and the following disclaimer. 47 | . 48 | Redistributions in binary form must reproduce the above copyright notice, this 49 | list of conditions and the following disclaimer in the documentation and/or 50 | other materials provided with the distribution. Neither the name of the author 51 | nor the names of its contributors may be used to endorse or promote products 52 | derived from this software without specific prior written permission. 53 | . 54 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 55 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 56 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 57 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 58 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 60 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 61 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 62 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 63 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 64 | 65 | License: CC0 66 | To the extent possible under law, the author(s) have dedicated all copyright 67 | and related and neighboring rights to this software to the public domain 68 | worldwide. This software is distributed without any warranty. 69 | . 70 | You should have received a copy of the CC0 Public Domain Dedication along with 71 | this software. If not, see . 72 | -------------------------------------------------------------------------------- /debian/dirs: -------------------------------------------------------------------------------- 1 | etc/rmilter.conf.d -------------------------------------------------------------------------------- /debian/install: -------------------------------------------------------------------------------- 1 | debian/rmilter.conf.common /etc 2 | debian/rmilter.conf /etc 3 | debian/rmilter.conf.sysvinit /etc 4 | debian/rmilter-tmpfiles.conf /usr/lib/tmpfiles.d 5 | -------------------------------------------------------------------------------- /debian/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | case "$1" in 5 | configure) 6 | adduser --quiet \ 7 | --system \ 8 | --group \ 9 | --home /run/rmilter \ 10 | --no-create-home \ 11 | --disabled-login \ 12 | --gecos "rmilter" \ 13 | --force-badname \ 14 | _rmilter 15 | ;; 16 | 17 | abort-*) 18 | ;; 19 | 20 | *) 21 | echo "postinst called with unknown argument \`$1'" >&2 22 | exit 1 23 | ;; 24 | esac 25 | 26 | #DEBHELPER# 27 | 28 | exit 0 29 | -------------------------------------------------------------------------------- /debian/postrm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | if [ -d /run/systemd/system ]; then 5 | systemctl --system daemon-reload >/dev/null || true 6 | fi 7 | 8 | #DEBHELPER# 9 | -------------------------------------------------------------------------------- /debian/prerm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | if [ -x /etc/init.d/rmilter ] && ! [ -d /run/systemd/system ]; then 5 | invoke-rc.d rmilter stop || exit $? 6 | fi 7 | 8 | #DEBHELPER# 9 | -------------------------------------------------------------------------------- /debian/rmilter-tmpfiles.conf: -------------------------------------------------------------------------------- 1 | d /run/rmilter 0755 _rmilter adm - 2 | -------------------------------------------------------------------------------- /debian/rmilter.conf: -------------------------------------------------------------------------------- 1 | # systemd-specific settings for rmilter 2 | 3 | .include /etc/rmilter.conf.common 4 | 5 | bind_socket = unix:/run/rmilter/rmilter.sock; 6 | 7 | # include user's configuration 8 | .try_include /etc/rmilter.conf.local 9 | .try_include /etc/rmilter.conf.d/*.conf 10 | -------------------------------------------------------------------------------- /debian/rmilter.conf.common: -------------------------------------------------------------------------------- 1 | # Sample config file for rmilter 2 | # $Id$ 3 | # 4 | 5 | # .include - directive to include other config file 6 | #.include ./rmilter-grey.conf 7 | 8 | 9 | clamav { 10 | # servers - clamav socket definitions in format: 11 | # /path/to/file 12 | # host[:port] 13 | # sockets are separated by ',' 14 | # Default: empty 15 | #servers = localhost; 16 | # connect_timeout - timeout in miliseconds for connecting to clamav 17 | # Default: 1s 18 | connect_timeout = 1s; 19 | 20 | # port_timeout - timeout in miliseconds for waiting for clamav port response 21 | # Default: 4s 22 | port_timeout = 4s; 23 | 24 | # results_timeout - timeout in miliseconds for waiting for clamav response 25 | # Default: 20s 26 | results_timeout = 20s; 27 | 28 | # error_time - time in seconds during which we are counting errors 29 | # Default: 10 30 | error_time = 10; 31 | 32 | # dead_time - time in seconds during which we are thinking that server is down 33 | # Default: 300 34 | dead_time = 300; 35 | 36 | # maxerrors - maximum number of errors that can occur during error_time to make us thinking that 37 | # this upstream is dead 38 | # Default: 10 39 | maxerrors = 10; 40 | }; 41 | 42 | spamd { 43 | # servers - spamd socket definitions in format: 44 | # /path/to/file 45 | # host[:port] 46 | # sockets are separated by ',' 47 | # is server name is prefixed with r: it is rspamd server 48 | # Default: empty 49 | servers = r:localhost:11333; 50 | 51 | # also_check - extra spamd servers to check 52 | #also_check = r:spam.example.com; 53 | 54 | # diff_dir - path where to write messages that have different results from main and extra checks 55 | #diff_dir = /var/run/rmilter/diffmsg; 56 | 57 | # connect_timeout - timeout in milliseconds for connecting to spamd 58 | # Default: 1s 59 | connect_timeout = 1s; 60 | 61 | # results_timeout - timeout in milliseconds for waiting for spamd response 62 | # Default: 20s 63 | results_timeout = 20s; 64 | 65 | # error_time - time in seconds during which we are counting errors 66 | # Default: 10 67 | error_time = 10; 68 | 69 | # dead_time - time in seconds during which we are thinking that server is down 70 | # Default: 300 71 | dead_time = 300; 72 | 73 | # maxerrors - maximum number of errors that can occur during error_time to make us thinking that 74 | # this upstream is dead 75 | # Default: 10 76 | maxerrors = 10; 77 | 78 | # reject_message - reject message for spam 79 | # Default: "Spam message rejected; If this is not spam contact abuse" 80 | reject_message = "Spam message rejected; If this is not spam contact abuse"; 81 | 82 | # whitelist - list of ips or nets that should be not checked with spamd 83 | # Default: empty 84 | whitelist = 127.0.0.1/32, 192.168.0.0/16, [::1]/128; 85 | 86 | # rspamd_metric - metric for using with rspamd 87 | # Default: "default" 88 | rspamd_metric = "default"; 89 | }; 90 | 91 | redis { 92 | # servers_grey - redis servers for greylisting in format: 93 | # host[:port][, host[:port]] 94 | servers_grey = localhost; 95 | 96 | # servers_white - redis servers for whitelisting in format similar to that is used 97 | # in servers_grey 98 | # servers_white = redis.example.com:6379; 99 | 100 | # servers_limits - redis servers used for limits storing, can not be mirrored 101 | servers_limits = localhost; 102 | 103 | # servers_id - redis servers used for message id storing, can not be mirrored 104 | servers_id = localhost; 105 | 106 | # id_prefix - prefix for extracting message ids from redis 107 | # Default: empty (no prefix is prepended to key) 108 | id_prefix = "message_id."; 109 | 110 | # grey_prefix - prefix for extracting greylisted records from redis 111 | # Default: empty (no prefix is prepended to key) 112 | grey_prefix = "grey."; 113 | 114 | # id_prefix - prefix for extracting whitelisted records from redis 115 | # Default: empty (no prefix is prepended to key) 116 | white_prefix = "white."; 117 | 118 | # connect_timeout - timeout in miliseconds for waiting for redis 119 | # Default: 1s 120 | connect_timeout = 1s; 121 | 122 | # error_time - time in seconds during which we are counting errors 123 | # Default: 10 124 | error_time = 10; 125 | 126 | # dead_time - time in seconds during which we are thinking that server is down 127 | # Default: 300 128 | dead_time = 300; 129 | 130 | # maxerrors - maximum number of errors that can occur during error_time to make us thinking that 131 | # this upstream is dead 132 | # Default: 10 133 | maxerrors = 10; 134 | }; 135 | 136 | # bind_socket - socket credits for local bind: 137 | # unix:/path/to/file - bind to local socket 138 | # inet:port@host - bind to inet socket 139 | # Default: bind_socket = unix:/var/tmp/rmilter.sock; 140 | 141 | #bind_socket = unix:/run/rmilter/rmilter.sock; 142 | 143 | # tempdir - path to directory that contains temporary files 144 | # Default: $TMPDIR 145 | 146 | tempdir = /tmp; 147 | 148 | # tempfiles_mode - set permission for temp files 149 | # Default: 00600 150 | 151 | tempfiles_mode = 00600; 152 | 153 | # max_size - maximum size of scanned mail with clamav and dcc 154 | # Default: 0 (no limit) 155 | 156 | max_size = 10M; 157 | 158 | # strict_auth - strict checks for mails from authenticated senders 159 | # Default: no 160 | 161 | strict_auth = no; 162 | 163 | # spf_domains - path to file that contains hash of spf domains 164 | # Default: empty 165 | 166 | #spf_domains = example.com; 167 | 168 | # use_dcc - whether use or not dcc system 169 | # Default: no 170 | 171 | use_dcc = no; 172 | 173 | # rule definition: 174 | # rule { 175 | # accept|discard|reject|tempfail|quarantine "[message]"; <- action definition 176 | # [not] connect ; <- conditions 177 | # helo ; 178 | # envfrom ; 179 | # envrcpt ; 180 | # header ; 181 | # body ; 182 | # }; 183 | 184 | # limits section 185 | limits { 186 | # Whitelisted ip or networks 187 | #limit_whitelist = 194.67.45.4/32; 188 | # Whitelisted recipients 189 | limit_whitelist_rcpt = postmaster, mailer-daemon; 190 | # Addrs for bounce checks 191 | limit_bounce_addrs = postmaster, mailer-daemon, symantec_antivirus_for_smtp_gateways, <>, null, fetchmail-daemon; 192 | # Limit for bounce mail 193 | limit_bounce_to = 5:0.000277778; 194 | # Limit for bounce mail per one source ip 195 | limit_bounce_to_ip = 5:0.000277778; 196 | # Limit for all mail per recipient 197 | limit_to = 20:0.016666667; 198 | # Limit for all mail per one source ip 199 | limit_to_ip = 30:0.025; 200 | # Limit for all mail per one source ip and from address 201 | limit_to_ip_from = 100:0.033333333; 202 | }; 203 | 204 | greylisting { 205 | timeout = 300s; 206 | expire = 3d; 207 | whitelist = 127.0.0.1, 208 | 192.168.1.1, 209 | 192.168.2.0/24; 210 | }; 211 | 212 | dkim { 213 | # Sample for dkim specific keys 214 | # domain { 215 | # key = /etc/dkim/dkim_example.key; 216 | # domain = "example.com"; 217 | # selector = "dkim"; 218 | # }; 219 | # domain { 220 | # key = /etc/dkim/dkim_test.key; 221 | # domain = "test.com"; 222 | # selector = "dkim"; 223 | # }; 224 | # Universal selector, keys will be checked for pattern /etc/dkim/..key 225 | domain { 226 | key = /etc/dkim; 227 | domain = "*"; 228 | selector = "dkim"; 229 | }; 230 | header_canon = relaxed; 231 | body_canon = relaxed; 232 | sign_alg = sha256; 233 | }; 234 | 235 | # Order of checks at EOM: 236 | # 237 | # SPF -> DCC -> CLAMAV 238 | -------------------------------------------------------------------------------- /debian/rmilter.conf.sysvinit: -------------------------------------------------------------------------------- 1 | # sysvinit-specific settings for rmilter 2 | 3 | .include /etc/rmilter.conf.common 4 | 5 | bind_socket = unix:/run/rmilter/rmilter.sock; 6 | 7 | # pidfile - path to pid file 8 | # Default: pidfile = /var/run/rmilter.pid 9 | 10 | pidfile = /run/rmilter/rmilter.pid; 11 | 12 | # include user's configuration 13 | .try_include /etc/rmilter.conf.local 14 | .try_include /etc/rmilter.conf.d/*.conf 15 | -------------------------------------------------------------------------------- /debian/rmilter.init: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Rmilter init script 4 | ### BEGIN INIT INFO 5 | # Provides: rmilter 6 | # Required-Start: $local_fs $named $remote_fs $syslog 7 | # Required-Stop: $local_fs $remote_fs 8 | # Should-Start: sendmail 9 | # Should-Stop: 10 | # Default-Start: 2 3 4 5 11 | # Default-Stop: 0 1 6 12 | # Short-Description: Script to start/stop the rmilter 13 | # Description: another spam-defense service 14 | ### END INIT INFO 15 | 16 | # Based on skeleton by Miquel van Smoorenburg and Ian Murdock 17 | 18 | PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin 19 | DAEMON=/usr/sbin/rmilter 20 | NAME=rmilter 21 | DESC="Rmilter Mail Filter Daemon" 22 | USER=_rmilter 23 | RUNDIR=/run/$NAME 24 | SOCKET=$RUNDIR/$NAME.sock 25 | SCRIPTNAME=/etc/init.d/$NAME 26 | 27 | [ -x $DAEMON ] || exit 0 28 | 29 | . /lib/init/vars.sh 30 | . /lib/lsb/init-functions 31 | 32 | export TMPDIR=/tmp 33 | # Apparently people have trouble if this isn't explicitly set... 34 | 35 | # Include rmilter defaults if available 36 | if [ -f /etc/default/$NAME ]; then 37 | . /etc/default/$NAME 38 | fi 39 | 40 | set -e 41 | 42 | SSD="start-stop-daemon --pidfile $RUNDIR/$NAME.pid --name rmilter" 43 | 44 | do_start() 45 | { 46 | mkdir -m750 -p $RUNDIR 47 | chown $USER:adm $RUNDIR 48 | chmod g+s $RUNDIR 49 | rm -f $SOCKET 50 | $SSD --start --background --chuid $USER --oknodo \ 51 | --startas $DAEMON -- -c /etc/rmilter.conf.sysvinit 52 | } 53 | 54 | do_stop() 55 | { 56 | $SSD --stop --oknodo "$@" 57 | } 58 | 59 | case "$1" in 60 | start) 61 | [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" 62 | do_start;; 63 | stop) 64 | [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" 65 | do_stop;; 66 | restart|force-reload) 67 | [ "$VERBOSE" != no ] && log_daemon_msg "Restarting $DESC" "$NAME" 68 | do_stop --retry 5 && do_start;; 69 | status) 70 | PID=`pidof $DAEMON` 71 | if [ x$PID = x ]; then 72 | echo "$DAEMON is not running" 73 | else 74 | echo "$DESC is running with pid[$PID]" 75 | fi 76 | exit 0;; 77 | *) 78 | echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2 79 | exit 1;; 80 | esac 81 | 82 | RET=$? 83 | [ "$VERBOSE" != no ] && log_end_msg $RET 84 | exit $RET 85 | -------------------------------------------------------------------------------- /debian/rmilter.install: -------------------------------------------------------------------------------- 1 | debian/rmilter.conf.common debian/rmilter.conf debian/rmilter.conf.sysvinit /etc 2 | usr/sbin 3 | -------------------------------------------------------------------------------- /debian/rmilter.manpages: -------------------------------------------------------------------------------- 1 | doc/rmilter.8 2 | -------------------------------------------------------------------------------- /debian/rmilter.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Another sendmail milter for different mail checks 3 | Documentation=https://rspamd.com/rmilter/ 4 | 5 | [Service] 6 | User=_rmilter 7 | ExecStart=/usr/sbin/rmilter -n -c /etc/rmilter.conf 8 | ExecReload=/bin/kill -USR1 $MAINPID 9 | Restart=always 10 | RuntimeDirectory=rmilter 11 | RuntimeDirectoryMode=0755 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | %: 3 | dh $@ --with systemd 4 | 5 | export DEB_LDFLAGS_MAINT_APPEND=-Wl,--as-needed 6 | 7 | override_dh_auto_configure: 8 | dh_auto_configure -- \ 9 | -DENABLE_DKIM=ON \ 10 | -DMANDIR=/usr/share/man \ 11 | -DCMAKE_INSTALL_PREFIX:PATH=/usr \ 12 | -DCMAKE_BUILD_TYPE=ReleaseWithDebInfo \ 13 | -DDEBIAN_BUILD=1 \ 14 | -DWANT_SYSTEMD_UNITS=ON 15 | 16 | override_dh_strip: 17 | dh_strip --dbg-package=rmilter-dbg 18 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /dist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | TAR=${2:-"tar"} 4 | 5 | if [ $# -lt 1 ] ; then 6 | echo "Usage: dist.sh [tar_command]" 7 | exit 1 8 | fi 9 | 10 | FNAME=$1 11 | PREFIX=`basename $FNAME | sed -e 's/\.tar.*$//'` 12 | 13 | OUT="" 14 | while true ; do 15 | OUT="/tmp/files-`strings -7 /dev/urandom | head -1 | sed -e 's/[^[:alnum:]]//g'`" 16 | if [ ! -f "$OUT" ] ; then break ; fi 17 | done 18 | 19 | git ls-files > $OUT 20 | SUBMODULES=`git submodule | cut -d ' ' -f 3` 21 | 22 | for sub in $SUBMODULES ; do 23 | (cd $sub && git ls-files | sed -e "s|^|$sub/|" >> $OUT) 24 | done 25 | 26 | ${TAR} -c --exclude='.[^/]*' --exclude='*.xz' --exclude='*.gz' --no-recursion --transform "s|^|$PREFIX/|" -a -T $OUT -v -f $FNAME 27 | rm -f $OUT 28 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # A simple makefile to generate documentation from .md using pandoc 2 | 3 | PANDOC ?= pandoc 4 | 5 | all: man 6 | 7 | man: rmilter.8 8 | 9 | rmilter.8: rmilter.8.md 10 | $(PANDOC) -s -f markdown -t man -o rmilter.8 rmilter.8.md 11 | -------------------------------------------------------------------------------- /doc/rmilter.8: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pandoc 1.17.2 2 | .\" 3 | .TH "RMILTER" "8" "" "Rmilter User Manual" "" 4 | .hy 5 | .SH NAME 6 | .PP 7 | rmilter \- Another milter for different mail checks. 8 | .SH SYNOPSIS 9 | .PP 10 | rmilter [\f[I]options\f[]]... 11 | .PP 12 | rmilter \-h 13 | .SH DESCRIPTION 14 | .PP 15 | Rmilter is used to integrate Rspamd with milter compatible MTA, for 16 | example Postfix or Sendmail. 17 | .SH OPTIONS 18 | .TP 19 | .B \-c \f[I]path\f[] 20 | Specify config file(s) 21 | .RS 22 | .RE 23 | .SH EXAMPLES 24 | .PP 25 | Run rmilter in foreground with custom configuration: 26 | .IP 27 | .nf 28 | \f[C] 29 | rmilter\ \-c\ ~/rmilter.conf 30 | \f[] 31 | .fi 32 | .SH SEE ALSO 33 | .PP 34 | Rmilter documentation and source codes may be downloaded from 35 | . 36 | -------------------------------------------------------------------------------- /doc/rmilter.8.md: -------------------------------------------------------------------------------- 1 | % RMILTER(8) Rmilter User Manual 2 | 3 | # NAME 4 | 5 | rmilter - Another milter for different mail checks. 6 | 7 | # SYNOPSIS 8 | 9 | rmilter [*options*]... 10 | 11 | rmilter -h 12 | 13 | # DESCRIPTION 14 | 15 | Rmilter is used to integrate Rspamd with milter compatible MTA, for example Postfix or Sendmail. 16 | 17 | # OPTIONS 18 | 19 | -c *path* 20 | : Specify config file(s) 21 | 22 | # EXAMPLES 23 | 24 | Run rmilter in foreground with custom configuration: 25 | 26 | rmilter -c ~/rmilter.conf 27 | 28 | # SEE ALSO 29 | 30 | Rmilter documentation and source codes may be downloaded from 31 | . 32 | -------------------------------------------------------------------------------- /freebsd/rmilter: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # PROVIDE: rmilter 3 | # REQUIRE: LOGIN 4 | # BEFORE: mail 5 | # KEYWORD: shutdown 6 | # 7 | # Add the following line to /etc/rc.conf to enable rmilter: 8 | # rmilter_enable="YES" 9 | # 10 | 11 | . /etc/rc.subr 12 | 13 | name="rmilter" 14 | rcvar=rmilter_enable 15 | command="%%PREFIX%%/sbin/rmilter" 16 | 17 | load_rc_config $name 18 | 19 | : ${rmilter_enable="NO"} 20 | : ${rmilter_pidfile="/var/run/rmilter/rmilter.pid"} 21 | : ${rmilter_socket="/var/run/rmilter/rmilter.sock"} 22 | : ${rmilter_user="_rmilter"} 23 | : ${rmilter_group="mail"} 24 | 25 | rmilter_cleanup() { 26 | rm -f $rmilter_pidfile || true 27 | if [ -n $rmilter_socket ] && [ -S $rmilter_socket ] ; then 28 | rm -f $rmilter_socket || true 29 | fi 30 | } 31 | 32 | rmilter_fixupbloodylibmilter() { 33 | if [ -n $rmilter_socket ] && [ -S $rmilter_socket ] ; then 34 | chown ${rmilter_user}:${rmilter_group} $rmilter_socket 35 | chmod 774 $rmilter_socket 36 | fi 37 | } 38 | 39 | start_precmd=rmilter_cleanup 40 | start_postcmd=rmilter_fixupbloodylibmilter 41 | stop_postcmd=rmilter_cleanup 42 | 43 | extra_commands="reload" 44 | sig_reload="USR1" 45 | 46 | command_args="$procname -c %%PREFIX%%/etc/rmilter.conf" 47 | 48 | run_rc_command "$1" 49 | -------------------------------------------------------------------------------- /hiredis/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | SET(HIREDISSRC async.c 2 | dict.c 3 | hiredis.c 4 | net.c 5 | read.c 6 | sds.c) 7 | 8 | SET(HIREDIS_CFLAGS "") 9 | IF("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") 10 | SET(HIREDIS_CFLAGS "${HIREDIS_CFLAGS} -O3") 11 | ENDIF() 12 | 13 | ADD_LIBRARY(rmilter-hiredis STATIC ${HIREDISSRC}) 14 | 15 | SET_TARGET_PROPERTIES(rmilter-hiredis PROPERTIES COMPILE_FLAGS "${HIREDIS_CFLAGS}") -------------------------------------------------------------------------------- /hiredis/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2011, Salvatore Sanfilippo 2 | Copyright (c) 2010-2011, Pieter Noordhuis 3 | 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of Redis nor the names of its contributors may be used 17 | to endorse or promote products derived from this software without specific 18 | prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 24 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /hiredis/adapters/libevent.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2011, Pieter Noordhuis 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef __HIREDIS_LIBEVENT_H__ 32 | #define __HIREDIS_LIBEVENT_H__ 33 | #include 34 | #include "../hiredis.h" 35 | #include "../async.h" 36 | 37 | typedef struct redisLibeventEvents { 38 | redisAsyncContext *context; 39 | struct event rev, wev; 40 | } redisLibeventEvents; 41 | 42 | static void redisLibeventReadEvent(int fd, short event, void *arg) { 43 | ((void)fd); ((void)event); 44 | redisLibeventEvents *e = (redisLibeventEvents*)arg; 45 | redisAsyncHandleRead(e->context); 46 | } 47 | 48 | static void redisLibeventWriteEvent(int fd, short event, void *arg) { 49 | ((void)fd); ((void)event); 50 | redisLibeventEvents *e = (redisLibeventEvents*)arg; 51 | redisAsyncHandleWrite(e->context); 52 | } 53 | 54 | static void redisLibeventAddRead(void *privdata) { 55 | redisLibeventEvents *e = (redisLibeventEvents*)privdata; 56 | event_add(&e->rev,NULL); 57 | } 58 | 59 | static void redisLibeventDelRead(void *privdata) { 60 | redisLibeventEvents *e = (redisLibeventEvents*)privdata; 61 | event_del(&e->rev); 62 | } 63 | 64 | static void redisLibeventAddWrite(void *privdata) { 65 | redisLibeventEvents *e = (redisLibeventEvents*)privdata; 66 | event_add(&e->wev,NULL); 67 | } 68 | 69 | static void redisLibeventDelWrite(void *privdata) { 70 | redisLibeventEvents *e = (redisLibeventEvents*)privdata; 71 | event_del(&e->wev); 72 | } 73 | 74 | static void redisLibeventCleanup(void *privdata) { 75 | redisLibeventEvents *e = (redisLibeventEvents*)privdata; 76 | event_del(&e->rev); 77 | event_del(&e->wev); 78 | free(e); 79 | } 80 | 81 | static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) { 82 | redisContext *c = &(ac->c); 83 | redisLibeventEvents *e; 84 | 85 | /* Nothing should be attached when something is already attached */ 86 | if (ac->ev.data != NULL) 87 | return REDIS_ERR; 88 | 89 | /* Create container for context and r/w events */ 90 | e = (redisLibeventEvents*)malloc(sizeof(*e)); 91 | e->context = ac; 92 | 93 | /* Register functions to start/stop listening for events */ 94 | ac->ev.addRead = redisLibeventAddRead; 95 | ac->ev.delRead = redisLibeventDelRead; 96 | ac->ev.addWrite = redisLibeventAddWrite; 97 | ac->ev.delWrite = redisLibeventDelWrite; 98 | ac->ev.cleanup = redisLibeventCleanup; 99 | ac->ev.data = e; 100 | 101 | /* Initialize and install read/write events */ 102 | event_set(&e->rev,c->fd,EV_READ,redisLibeventReadEvent,e); 103 | event_set(&e->wev,c->fd,EV_WRITE,redisLibeventWriteEvent,e); 104 | event_base_set(base,&e->rev); 105 | event_base_set(base,&e->wev); 106 | return REDIS_OK; 107 | } 108 | #endif 109 | -------------------------------------------------------------------------------- /hiredis/async.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009-2011, Salvatore Sanfilippo 3 | * Copyright (c) 2010-2011, Pieter Noordhuis 4 | * 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of Redis nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef __HIREDIS_ASYNC_H 33 | #define __HIREDIS_ASYNC_H 34 | #include "hiredis.h" 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | struct redisAsyncContext; /* need forward declaration of redisAsyncContext */ 41 | struct dict; /* dictionary header is included in async.c */ 42 | 43 | /* Reply callback prototype and container */ 44 | typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*); 45 | typedef struct redisCallback { 46 | struct redisCallback *next; /* simple singly linked list */ 47 | redisCallbackFn *fn; 48 | void *privdata; 49 | } redisCallback; 50 | 51 | /* List of callbacks for either regular replies or pub/sub */ 52 | typedef struct redisCallbackList { 53 | redisCallback *head, *tail; 54 | } redisCallbackList; 55 | 56 | /* Connection callback prototypes */ 57 | typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status); 58 | typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status); 59 | 60 | /* Context for an async connection to Redis */ 61 | typedef struct redisAsyncContext { 62 | /* Hold the regular context, so it can be realloc'ed. */ 63 | redisContext c; 64 | 65 | /* Setup error flags so they can be used directly. */ 66 | int err; 67 | char *errstr; 68 | 69 | /* Not used by hiredis */ 70 | void *data; 71 | 72 | /* Event library data and hooks */ 73 | struct { 74 | void *data; 75 | 76 | /* Hooks that are called when the library expects to start 77 | * reading/writing. These functions should be idempotent. */ 78 | void (*addRead)(void *privdata); 79 | void (*delRead)(void *privdata); 80 | void (*addWrite)(void *privdata); 81 | void (*delWrite)(void *privdata); 82 | void (*cleanup)(void *privdata); 83 | } ev; 84 | 85 | /* Called when either the connection is terminated due to an error or per 86 | * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */ 87 | redisDisconnectCallback *onDisconnect; 88 | 89 | /* Called when the first write event was received. */ 90 | redisConnectCallback *onConnect; 91 | 92 | /* Regular command callbacks */ 93 | redisCallbackList replies; 94 | 95 | /* Subscription callbacks */ 96 | struct { 97 | redisCallbackList invalid; 98 | struct dict *channels; 99 | struct dict *patterns; 100 | } sub; 101 | } redisAsyncContext; 102 | 103 | /* Functions that proxy to hiredis */ 104 | redisAsyncContext *redisAsyncConnect(const char *ip, int port); 105 | redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr); 106 | redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port, 107 | const char *source_addr); 108 | redisAsyncContext *redisAsyncConnectUnix(const char *path); 109 | int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn); 110 | int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); 111 | void redisAsyncDisconnect(redisAsyncContext *ac); 112 | void redisAsyncFree(redisAsyncContext *ac); 113 | 114 | /* Handle read/write events */ 115 | void redisAsyncHandleRead(redisAsyncContext *ac); 116 | void redisAsyncHandleWrite(redisAsyncContext *ac); 117 | 118 | /* Command functions for an async context. Write the command to the 119 | * output buffer and register the provided callback. */ 120 | int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap); 121 | int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...); 122 | int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen); 123 | int redisAsyncFormattedCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len); 124 | 125 | #ifdef __cplusplus 126 | } 127 | #endif 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /hiredis/dict.h: -------------------------------------------------------------------------------- 1 | /* Hash table implementation. 2 | * 3 | * This file implements in memory hash tables with insert/del/replace/find/ 4 | * get-random-element operations. Hash tables will auto resize if needed 5 | * tables of power of two in size are used, collisions are handled by 6 | * chaining. See the source code for more information... :) 7 | * 8 | * Copyright (c) 2006-2010, Salvatore Sanfilippo 9 | * All rights reserved. 10 | * 11 | * Redistribution and use in source and binary forms, with or without 12 | * modification, are permitted provided that the following conditions are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright notice, 15 | * this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * * Neither the name of Redis nor the names of its contributors may be used 20 | * to endorse or promote products derived from this software without 21 | * specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 | * POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | 36 | #ifndef __DICT_H 37 | #define __DICT_H 38 | 39 | #define DICT_OK 0 40 | #define DICT_ERR 1 41 | 42 | /* Unused arguments generate annoying warnings... */ 43 | #define DICT_NOTUSED(V) ((void) V) 44 | 45 | typedef struct dictEntry { 46 | void *key; 47 | void *val; 48 | struct dictEntry *next; 49 | } dictEntry; 50 | 51 | typedef struct dictType { 52 | unsigned int (*hashFunction)(const void *key); 53 | void *(*keyDup)(void *privdata, const void *key); 54 | void *(*valDup)(void *privdata, const void *obj); 55 | int (*keyCompare)(void *privdata, const void *key1, const void *key2); 56 | void (*keyDestructor)(void *privdata, void *key); 57 | void (*valDestructor)(void *privdata, void *obj); 58 | } dictType; 59 | 60 | typedef struct dict { 61 | dictEntry **table; 62 | dictType *type; 63 | unsigned long size; 64 | unsigned long sizemask; 65 | unsigned long used; 66 | void *privdata; 67 | } dict; 68 | 69 | typedef struct dictIterator { 70 | dict *ht; 71 | int index; 72 | dictEntry *entry, *nextEntry; 73 | } dictIterator; 74 | 75 | /* This is the initial size of every hash table */ 76 | #define DICT_HT_INITIAL_SIZE 4 77 | 78 | /* ------------------------------- Macros ------------------------------------*/ 79 | #define dictFreeEntryVal(ht, entry) \ 80 | if ((ht)->type->valDestructor) \ 81 | (ht)->type->valDestructor((ht)->privdata, (entry)->val) 82 | 83 | #define dictSetHashVal(ht, entry, _val_) do { \ 84 | if ((ht)->type->valDup) \ 85 | entry->val = (ht)->type->valDup((ht)->privdata, _val_); \ 86 | else \ 87 | entry->val = (_val_); \ 88 | } while(0) 89 | 90 | #define dictFreeEntryKey(ht, entry) \ 91 | if ((ht)->type->keyDestructor) \ 92 | (ht)->type->keyDestructor((ht)->privdata, (entry)->key) 93 | 94 | #define dictSetHashKey(ht, entry, _key_) do { \ 95 | if ((ht)->type->keyDup) \ 96 | entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \ 97 | else \ 98 | entry->key = (_key_); \ 99 | } while(0) 100 | 101 | #define dictCompareHashKeys(ht, key1, key2) \ 102 | (((ht)->type->keyCompare) ? \ 103 | (ht)->type->keyCompare((ht)->privdata, key1, key2) : \ 104 | (key1) == (key2)) 105 | 106 | #define dictHashKey(ht, key) (ht)->type->hashFunction(key) 107 | 108 | #define dictGetEntryKey(he) ((he)->key) 109 | #define dictGetEntryVal(he) ((he)->val) 110 | #define dictSlots(ht) ((ht)->size) 111 | #define dictSize(ht) ((ht)->used) 112 | 113 | /* API */ 114 | static unsigned int dictGenHashFunction(const unsigned char *buf, int len); 115 | static dict *dictCreate(dictType *type, void *privDataPtr); 116 | static int dictExpand(dict *ht, unsigned long size); 117 | static int dictAdd(dict *ht, void *key, void *val); 118 | static int dictReplace(dict *ht, void *key, void *val); 119 | static int dictDelete(dict *ht, const void *key); 120 | static void dictRelease(dict *ht); 121 | static dictEntry * dictFind(dict *ht, const void *key); 122 | static dictIterator *dictGetIterator(dict *ht); 123 | static dictEntry *dictNext(dictIterator *iter); 124 | static void dictReleaseIterator(dictIterator *iter); 125 | 126 | #endif /* __DICT_H */ 127 | -------------------------------------------------------------------------------- /hiredis/fmacros.h: -------------------------------------------------------------------------------- 1 | #ifndef __HIREDIS_FMACRO_H 2 | #define __HIREDIS_FMACRO_H 3 | 4 | #if defined(__linux__) 5 | #define _BSD_SOURCE 6 | #define _DEFAULT_SOURCE 7 | #endif 8 | 9 | #if defined(__sun__) 10 | #define _POSIX_C_SOURCE 200112L 11 | #elif defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__) 12 | #define _XOPEN_SOURCE 600 13 | #else 14 | #define _XOPEN_SOURCE 15 | #endif 16 | 17 | #if __APPLE__ && __MACH__ 18 | #define _OSX 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /hiredis/net.h: -------------------------------------------------------------------------------- 1 | /* Extracted from anet.c to work properly with Hiredis error reporting. 2 | * 3 | * Copyright (c) 2009-2011, Salvatore Sanfilippo 4 | * Copyright (c) 2010-2014, Pieter Noordhuis 5 | * Copyright (c) 2015, Matt Stancliff , 6 | * Jan-Erik Rediger 7 | * 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions are met: 12 | * 13 | * * Redistributions of source code must retain the above copyright notice, 14 | * this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * * Neither the name of Redis nor the names of its contributors may be used 19 | * to endorse or promote products derived from this software without 20 | * specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #ifndef __NET_H 36 | #define __NET_H 37 | 38 | #include "hiredis.h" 39 | 40 | #if defined(__sun) 41 | #define AF_LOCAL AF_UNIX 42 | #endif 43 | 44 | int redisCheckSocketError(redisContext *c); 45 | int redisContextSetTimeout(redisContext *c, const struct timeval tv); 46 | int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout); 47 | int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, 48 | const struct timeval *timeout, 49 | const char *source_addr); 50 | int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout); 51 | int redisKeepAlive(redisContext *c, int interval); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /hiredis/read.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009-2011, Salvatore Sanfilippo 3 | * Copyright (c) 2010-2011, Pieter Noordhuis 4 | * 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of Redis nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | 33 | #ifndef __HIREDIS_READ_H 34 | #define __HIREDIS_READ_H 35 | #include /* for size_t */ 36 | 37 | #define REDIS_ERR -1 38 | #define REDIS_OK 0 39 | 40 | /* When an error occurs, the err flag in a context is set to hold the type of 41 | * error that occurred. REDIS_ERR_IO means there was an I/O error and you 42 | * should use the "errno" variable to find out what is wrong. 43 | * For other values, the "errstr" field will hold a description. */ 44 | #define REDIS_ERR_IO 1 /* Error in read or write */ 45 | #define REDIS_ERR_EOF 3 /* End of file */ 46 | #define REDIS_ERR_PROTOCOL 4 /* Protocol error */ 47 | #define REDIS_ERR_OOM 5 /* Out of memory */ 48 | #define REDIS_ERR_OTHER 2 /* Everything else... */ 49 | 50 | #define REDIS_REPLY_STRING 1 51 | #define REDIS_REPLY_ARRAY 2 52 | #define REDIS_REPLY_INTEGER 3 53 | #define REDIS_REPLY_NIL 4 54 | #define REDIS_REPLY_STATUS 5 55 | #define REDIS_REPLY_ERROR 6 56 | 57 | #define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */ 58 | 59 | #ifdef __cplusplus 60 | extern "C" { 61 | #endif 62 | 63 | typedef struct redisReadTask { 64 | int type; 65 | int elements; /* number of elements in multibulk container */ 66 | int idx; /* index in parent (array) object */ 67 | void *obj; /* holds user-generated value for a read task */ 68 | struct redisReadTask *parent; /* parent task */ 69 | void *privdata; /* user-settable arbitrary field */ 70 | } redisReadTask; 71 | 72 | typedef struct redisReplyObjectFunctions { 73 | void *(*createString)(const redisReadTask*, char*, size_t); 74 | void *(*createArray)(const redisReadTask*, int); 75 | void *(*createInteger)(const redisReadTask*, long long); 76 | void *(*createNil)(const redisReadTask*); 77 | void (*freeObject)(void*); 78 | } redisReplyObjectFunctions; 79 | 80 | typedef struct redisReader { 81 | int err; /* Error flags, 0 when there is no error */ 82 | char errstr[128]; /* String representation of error when applicable */ 83 | 84 | char *buf; /* Read buffer */ 85 | size_t pos; /* Buffer cursor */ 86 | size_t len; /* Buffer length */ 87 | size_t maxbuf; /* Max length of unused buffer */ 88 | 89 | redisReadTask rstack[9]; 90 | int ridx; /* Index of current read task */ 91 | void *reply; /* Temporary reply pointer */ 92 | 93 | redisReplyObjectFunctions *fn; 94 | void *privdata; 95 | } redisReader; 96 | 97 | /* Public API for the protocol parser. */ 98 | redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn); 99 | void redisReaderFree(redisReader *r); 100 | int redisReaderFeed(redisReader *r, const char *buf, size_t len); 101 | int redisReaderGetReply(redisReader *r, void **reply); 102 | 103 | /* Backwards compatibility, can be removed on big version bump. */ 104 | #define redisReplyReaderCreate redisReaderCreate 105 | #define redisReplyReaderFree redisReaderFree 106 | #define redisReplyReaderFeed redisReaderFeed 107 | #define redisReplyReaderGetReply redisReaderGetReply 108 | #define redisReplyReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p)) 109 | #define redisReplyReaderGetObject(_r) (((redisReader*)(_r))->reply) 110 | #define redisReplyReaderGetError(_r) (((redisReader*)(_r))->errstr) 111 | 112 | #ifdef __cplusplus 113 | } 114 | #endif 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /hiredis/sds.h: -------------------------------------------------------------------------------- 1 | /* SDS (Simple Dynamic Strings), A C dynamic strings library. 2 | * 3 | * Copyright (c) 2006-2014, Salvatore Sanfilippo 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef __SDS_H 32 | #define __SDS_H 33 | 34 | #define SDS_MAX_PREALLOC (1024*1024) 35 | 36 | #include 37 | #include 38 | #ifdef _MSC_VER 39 | #include "win32.h" 40 | #endif 41 | 42 | typedef char *sds; 43 | 44 | struct sdshdr { 45 | int len; 46 | int free; 47 | char buf[]; 48 | }; 49 | 50 | static inline size_t sdslen(const sds s) { 51 | struct sdshdr *sh = (struct sdshdr *)(s-sizeof *sh); 52 | return sh->len; 53 | } 54 | 55 | static inline size_t sdsavail(const sds s) { 56 | struct sdshdr *sh = (struct sdshdr *)(s-sizeof *sh); 57 | return sh->free; 58 | } 59 | 60 | sds sdsnewlen(const void *init, size_t initlen); 61 | sds sdsnew(const char *init); 62 | sds sdsempty(void); 63 | size_t sdslen(const sds s); 64 | sds sdsdup(const sds s); 65 | void sdsfree(sds s); 66 | size_t sdsavail(const sds s); 67 | sds sdsgrowzero(sds s, size_t len); 68 | sds sdscatlen(sds s, const void *t, size_t len); 69 | sds sdscat(sds s, const char *t); 70 | sds sdscatsds(sds s, const sds t); 71 | sds sdscpylen(sds s, const char *t, size_t len); 72 | sds sdscpy(sds s, const char *t); 73 | 74 | sds sdscatvprintf(sds s, const char *fmt, va_list ap); 75 | #ifdef __GNUC__ 76 | sds sdscatprintf(sds s, const char *fmt, ...) 77 | __attribute__((format(printf, 2, 3))); 78 | #else 79 | sds sdscatprintf(sds s, const char *fmt, ...); 80 | #endif 81 | 82 | sds sdscatfmt(sds s, char const *fmt, ...); 83 | void sdstrim(sds s, const char *cset); 84 | void sdsrange(sds s, int start, int end); 85 | void sdsupdatelen(sds s); 86 | void sdsclear(sds s); 87 | int sdscmp(const sds s1, const sds s2); 88 | sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count); 89 | void sdsfreesplitres(sds *tokens, int count); 90 | void sdstolower(sds s); 91 | void sdstoupper(sds s); 92 | sds sdsfromlonglong(long long value); 93 | sds sdscatrepr(sds s, const char *p, size_t len); 94 | sds *sdssplitargs(const char *line, int *argc); 95 | sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen); 96 | sds sdsjoin(char **argv, int argc, char *sep, size_t seplen); 97 | sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen); 98 | 99 | /* Low level functions exposed to the user API */ 100 | sds sdsMakeRoomFor(sds s, size_t addlen); 101 | void sdsIncrLen(sds s, int incr); 102 | sds sdsRemoveFreeSpace(sds s); 103 | size_t sdsAllocSize(sds s); 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /rmilter-grey.conf: -------------------------------------------------------------------------------- 1 | greylisting { 2 | timeout = 300s; 3 | whitelist = 127.0.0.1, 4 | 192.168.1.1, 5 | 192.168.2.0/24; 6 | }; 7 | -------------------------------------------------------------------------------- /rmilter.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Another sendmail milter for different mail checks 3 | Documentation=https://rspamd.com/rmilter/ 4 | 5 | [Service] 6 | User=_rmilter 7 | ExecStart=/usr/sbin/rmilter -n -c /etc/rmilter/rmilter.conf 8 | ExecReload=/bin/kill -USR1 $MAINPID 9 | Restart=always 10 | RuntimeDirectory=rmilter 11 | RuntimeDirectoryMode=0755 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | -------------------------------------------------------------------------------- /src/cache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Vsevolod Stakhov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY 14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 17 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 26 | #ifndef INCLUDE_CACHE_H_ 27 | #define INCLUDE_CACHE_H_ 28 | 29 | #include "config.h" 30 | #include 31 | 32 | #ifndef MAXKEYLEN 33 | #define MAXKEYLEN 250 34 | #endif 35 | 36 | struct config_file; 37 | struct mlfi_priv; 38 | 39 | enum rmilter_query_type { 40 | RMILTER_QUERY_GREYLIST = 0, 41 | RMILTER_QUERY_WHITELIST, 42 | RMILTER_QUERY_RATELIMIT, 43 | RMILTER_QUERY_ID, 44 | }; 45 | 46 | enum rmilter_publish_type { 47 | RMILTER_PUBLISH_COPY = 0, 48 | RMILTER_PUBLISH_SPAM, 49 | }; 50 | 51 | /** 52 | * Query cache (preferring redis) for the specified key 53 | * @param cfg 54 | * @param type type of query 55 | * @param key key to check 56 | * @param keylen length of the key 57 | * @param data data returned by a server (must be freed by a caller) 58 | * @param datalen pointer to length of data (out) 59 | * @param priv pointer to useful information from milter protocol 60 | * @return 61 | */ 62 | bool rmilter_query_cache (struct config_file *cfg, enum rmilter_query_type type, 63 | const unsigned char *key, size_t keylen, 64 | unsigned char **data, size_t *datalen, struct mlfi_priv *priv); 65 | 66 | bool rmilter_set_cache (struct config_file *cfg, enum rmilter_query_type type , 67 | const unsigned char *key, size_t keylen, 68 | const unsigned char *data, size_t datalen, unsigned expire, struct mlfi_priv *priv); 69 | 70 | bool rmilter_delete_cache (struct config_file *cfg, enum rmilter_query_type type , 71 | const unsigned char *key, size_t keylen, struct mlfi_priv *priv); 72 | 73 | int rmilter_publish_cache (struct config_file *cfg, enum rmilter_publish_type type, 74 | const unsigned char *channel, size_t channel_len, 75 | const unsigned char *data, size_t datalen, struct mlfi_priv *priv); 76 | 77 | #endif /* INCLUDE_CACHE_H_ */ 78 | -------------------------------------------------------------------------------- /src/greylist.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Vsevolod Stakhov 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * 12 | * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | */ 23 | 24 | #ifndef GREYLIST_H_ 25 | #define GREYLIST_H_ 26 | 27 | #include "cfg_file.h" 28 | 29 | 30 | #define GREY_GREYLISTED 1 31 | #define GREY_WHITELISTED 2 32 | #define GREY_ERROR -1 33 | 34 | struct rcpt; 35 | struct mlfi_priv; 36 | 37 | int 38 | check_greylisting (void *_ctx, struct config_file *cfg, struct mlfi_priv *priv); 39 | 40 | #endif /* GREYLIST_H_ */ 41 | -------------------------------------------------------------------------------- /src/libclamc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2012, Vsevolod Stakhov 3 | * All rights reserved. 4 | 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. Redistributions in binary form 9 | * must reproduce the above copyright notice, this list of conditions and the 10 | * following disclaimer in the documentation and/or other materials provided with 11 | * the distribution. Neither the name of the author nor the names of its 12 | * contributors may be used to endorse or promote products derived from this 13 | * software without specific prior written permission. 14 | 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef LIBCLAMC_H 28 | #define LIBCLAMC_H 1 29 | 30 | struct config_file; 31 | struct mlfi_priv; 32 | 33 | int clamscan (void *ctx, struct mlfi_priv *priv, struct config_file *cfg, 34 | char *strres, size_t strres_len); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/libspamd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2012, Vsevolod Stakhov 3 | * All rights reserved. 4 | 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. Redistributions in binary form 9 | * must reproduce the above copyright notice, this list of conditions and the 10 | * following disclaimer in the documentation and/or other materials provided with 11 | * the distribution. Neither the name of the author nor the names of its 12 | * contributors may be used to endorse or promote products derived from this 13 | * software without specific prior written permission. 14 | 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef LIBSPAMD_H 28 | #define LIBSPAMD_H 29 | 30 | #include "config.h" 31 | #include "ucl.h" 32 | 33 | struct config_file; 34 | struct mlfi_priv; 35 | 36 | struct rspamd_metric_result* spamdscan (void *ctx, struct mlfi_priv *priv, 37 | struct config_file *cfg, int is_extra, int dkim_only); 38 | void spamd_free_result (struct rspamd_metric_result *mres); 39 | 40 | 41 | /* Structure for rspamd results */ 42 | enum rspamd_metric_action { 43 | METRIC_ACTION_NOACTION = 0, 44 | METRIC_ACTION_GREYLIST, 45 | METRIC_ACTION_ADD_HEADER, 46 | METRIC_ACTION_REWRITE_SUBJECT, 47 | METRIC_ACTION_SOFT_REJECT, 48 | METRIC_ACTION_REJECT 49 | }; 50 | 51 | #define SPAM_IS_SPAM(res) ((res)->action >= METRIC_ACTION_ADD_HEADER) 52 | #define SPAM_IS_GREYLIST(res) ((res)->action >= METRIC_ACTION_GREYLIST && (res)->action < METRIC_ACTION_SOFT_REJECT) 53 | 54 | struct rspamd_symbol { 55 | const char *symbol; 56 | const ucl_object_t *options; 57 | double score; 58 | struct rspamd_symbol *prev, *next; 59 | }; 60 | 61 | struct rspamd_metric_result { 62 | ucl_object_t *obj; 63 | const char *dkim_signature; 64 | const char *metric_name; 65 | const char *subject; 66 | const char *message; 67 | const char *message_id; 68 | double score; 69 | double required_score; 70 | double reject_score; 71 | enum rspamd_metric_action action; 72 | struct rspamd_symbol *symbols; 73 | struct mlfi_priv *priv; 74 | bool parsed; 75 | bool compressed; 76 | }; 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/radix.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2016 Vsevolod Stakhov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "config.h" 17 | #include "radix.h" 18 | #include "btrie.h" 19 | #include "mempool.h" 20 | 21 | struct radix_tree_compressed { 22 | struct mempool pool; 23 | size_t size; 24 | struct btrie *tree; 25 | }; 26 | 27 | uintptr_t 28 | radix_find_compressed (radix_compressed_t * tree, const guint8 *key, gsize keylen) 29 | { 30 | gconstpointer ret; 31 | 32 | if (tree == NULL) { 33 | return RADIX_NO_VALUE; 34 | } 35 | 36 | ret = btrie_lookup (tree->tree, key, keylen * NBBY); 37 | 38 | if (ret == NULL) { 39 | return RADIX_NO_VALUE; 40 | } 41 | 42 | return (uintptr_t)ret; 43 | } 44 | 45 | 46 | uintptr_t 47 | radix_insert_compressed (radix_compressed_t * tree, 48 | guint8 *key, gsize keylen, 49 | gsize masklen, 50 | uintptr_t value) 51 | { 52 | guint keybits = keylen * NBBY; 53 | uintptr_t old; 54 | gchar ip_str[INET6_ADDRSTRLEN + 1]; 55 | int ret; 56 | 57 | if (tree == NULL) { 58 | return NULL; 59 | } 60 | 61 | g_assert (keybits >= masklen); 62 | 63 | old = radix_find_compressed (tree, key, keylen); 64 | 65 | ret = btrie_add_prefix (tree->tree, key, keybits - masklen, 66 | (gconstpointer)value); 67 | 68 | if (ret != BTRIE_OKAY) { 69 | memset (ip_str, 0, sizeof (ip_str)); 70 | 71 | if (keybits == 32) { 72 | msg_err ("cannot insert %p, key: %s/%d, duplicate value", 73 | (gpointer)value, 74 | inet_ntop (AF_INET, key, ip_str, sizeof (ip_str) - 1), 75 | (int)(keybits - masklen)); 76 | } 77 | else if (keybits == 128) { 78 | msg_err ("cannot insert %p, key: [%s]/%d, duplicate value", 79 | (gpointer)value, 80 | inet_ntop (AF_INET6, key, ip_str, sizeof (ip_str) - 1), 81 | (int)(keybits - masklen)); 82 | } 83 | else { 84 | msg_err ("cannot insert %p with mask %d, key: unknown, duplicate value", 85 | (gpointer)value, (int)(keybits - masklen)); 86 | } 87 | } 88 | else { 89 | tree->size ++; 90 | } 91 | 92 | return old; 93 | } 94 | 95 | 96 | radix_compressed_t * 97 | radix_create_compressed (void) 98 | { 99 | radix_compressed_t *tree; 100 | 101 | tree = calloc (1, sizeof (*tree)); 102 | if (tree == NULL) { 103 | return NULL; 104 | } 105 | 106 | mp_init (&tree->pool); 107 | tree->size = 0; 108 | tree->tree = btrie_init (&tree->pool); 109 | 110 | return tree; 111 | } 112 | 113 | void 114 | radix_destroy_compressed (radix_compressed_t *tree) 115 | { 116 | if (tree) { 117 | mp_free (&tree->pool); 118 | free (tree); 119 | } 120 | } 121 | 122 | gint 123 | rspamd_radix_add_iplist (const gchar *list, const gchar *separators, 124 | radix_compressed_t *tree, gconstpointer value, gboolean resolve) 125 | { 126 | gchar *token, *ipnet, *err_str, **strv, **cur, *brace; 127 | struct in_addr ina; 128 | struct in6_addr ina6; 129 | guint k = G_MAXINT; 130 | gint af; 131 | gint res = 0, r; 132 | struct addrinfo hints, *ai_res, *cur_ai; 133 | 134 | /* Split string if there are multiple items inside a single string */ 135 | strv = g_strsplit_set (list, separators, 0); 136 | cur = strv; 137 | while (*cur) { 138 | af = AF_UNSPEC; 139 | if (**cur == '\0') { 140 | cur++; 141 | continue; 142 | } 143 | /* Extract ipnet */ 144 | ipnet = *cur; 145 | token = strsep (&ipnet, "/"); 146 | 147 | if (ipnet != NULL) { 148 | errno = 0; 149 | /* Get mask */ 150 | k = strtoul (ipnet, &err_str, 10); 151 | if (errno != 0) { 152 | msg_warn ( 153 | "invalid netmask, error detected on symbol: %s, error: %s", 154 | err_str, 155 | strerror (errno)); 156 | k = G_MAXINT; 157 | } 158 | } 159 | 160 | /* Check IP */ 161 | if (token[0] == '[') { 162 | /* Braced IPv6 */ 163 | brace = strrchr (token, ']'); 164 | 165 | if (brace != NULL) { 166 | token ++; 167 | *brace = '\0'; 168 | 169 | if (inet_pton (AF_INET6, token, &ina6) == 1) { 170 | af = AF_INET6; 171 | } 172 | else { 173 | msg_warn ("invalid IP address: %s", token); 174 | 175 | cur ++; 176 | continue; 177 | } 178 | } 179 | else { 180 | msg_warn ("invalid IP address: %s", token); 181 | 182 | cur ++; 183 | continue; 184 | } 185 | } 186 | else { 187 | if (inet_pton (AF_INET, token, &ina) == 1) { 188 | af = AF_INET; 189 | } 190 | else if (inet_pton (AF_INET6, token, &ina6) == 1) { 191 | af = AF_INET6; 192 | } 193 | else { 194 | 195 | if (resolve) { 196 | memset (&hints, 0, sizeof (hints)); 197 | hints.ai_socktype = SOCK_STREAM; /* Type of the socket */ 198 | hints.ai_flags = AI_NUMERICSERV; 199 | hints.ai_family = AF_UNSPEC; 200 | 201 | if ((r = getaddrinfo (token, NULL, &hints, &ai_res)) == 0) { 202 | for (cur_ai = ai_res; cur_ai != NULL; 203 | cur_ai = cur_ai->ai_next) { 204 | 205 | if (cur_ai->ai_family == AF_INET) { 206 | struct sockaddr_in *sin; 207 | 208 | sin = (struct sockaddr_in *)cur_ai->ai_addr; 209 | if (k > 32) { 210 | k = 32; 211 | } 212 | 213 | radix_insert_compressed (tree, 214 | (guint8 *)&sin->sin_addr, 215 | sizeof (sin->sin_addr), 216 | 32 - k, (uintptr_t)value); 217 | res ++; 218 | } 219 | else if (cur_ai->ai_family == AF_INET6) { 220 | struct sockaddr_in6 *sin6; 221 | 222 | sin6 = (struct sockaddr_in6 *)cur_ai->ai_addr; 223 | if (k > 128) { 224 | k = 128; 225 | } 226 | 227 | radix_insert_compressed (tree, 228 | (guint8 *)&sin6->sin6_addr, 229 | sizeof (sin6->sin6_addr), 230 | 128 - k, (uintptr_t)value); 231 | res ++; 232 | } 233 | } 234 | 235 | freeaddrinfo (ai_res); 236 | } 237 | else { 238 | msg_warn ("getaddrinfo failed for %s: %s", token, 239 | gai_strerror (r)); 240 | } 241 | 242 | cur ++; 243 | continue; 244 | } 245 | else { 246 | msg_warn ("invalid IP address: %s", token); 247 | 248 | cur ++; 249 | continue; 250 | } 251 | } 252 | } 253 | 254 | if (af == AF_INET) { 255 | if (k > 32) { 256 | k = 32; 257 | } 258 | radix_insert_compressed (tree, (guint8 *)&ina, sizeof (ina), 259 | 32 - k, (uintptr_t)value); 260 | res ++; 261 | } 262 | else if (af == AF_INET6){ 263 | if (k > 128) { 264 | k = 128; 265 | } 266 | radix_insert_compressed (tree, (guint8 *)&ina6, sizeof (ina6), 267 | 128 - k, (uintptr_t)value); 268 | res ++; 269 | } 270 | cur++; 271 | } 272 | 273 | g_strfreev (strv); 274 | 275 | return res; 276 | } 277 | 278 | gboolean 279 | radix_add_generic_iplist (const gchar *ip_list, radix_compressed_t **tree, 280 | gboolean resolve) 281 | { 282 | if (*tree == NULL) { 283 | *tree = radix_create_compressed (); 284 | } 285 | 286 | return (rspamd_radix_add_iplist (ip_list, ",; ", *tree, 287 | GINT_TO_POINTER (1), resolve) > 0); 288 | } 289 | 290 | 291 | gsize 292 | radix_get_size (radix_compressed_t *tree) 293 | { 294 | if (tree != NULL) { 295 | return tree->size; 296 | } 297 | 298 | return 0; 299 | } 300 | 301 | 302 | 303 | const gchar * 304 | radix_get_info (radix_compressed_t *tree) 305 | { 306 | if (tree == NULL) { 307 | return NULL; 308 | } 309 | 310 | return btrie_stats (tree->tree); 311 | } 312 | 313 | uintptr_t 314 | radix_find_rmilter_addr (radix_compressed_t * tree, 315 | const struct rmilter_inet_address *addr) 316 | { 317 | const uint8_t *key; 318 | size_t keylen; 319 | 320 | switch (addr->family) { 321 | case AF_INET: 322 | key = (const uint8_t *)&addr->addr.sa4.sin_addr; 323 | keylen = sizeof (addr->addr.sa4.sin_addr); 324 | break; 325 | case AF_INET6: 326 | key = (const uint8_t *)&addr->addr.sa6.sin6_addr; 327 | keylen = sizeof (addr->addr.sa6.sin6_addr); 328 | break; 329 | default: 330 | return RADIX_NO_VALUE; 331 | } 332 | 333 | return radix_find_compressed (tree, key, keylen); 334 | } 335 | -------------------------------------------------------------------------------- /src/radix.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2016 Vsevolod Stakhov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef RADIX_H 17 | #define RADIX_H 18 | 19 | #include "config.h" 20 | #include "util.h" 21 | 22 | #define RADIX_NO_VALUE (uintptr_t)-1 23 | 24 | 25 | typedef struct radix_tree_compressed radix_compressed_t; 26 | 27 | /** 28 | * Insert new key to the radix trie 29 | * @param tree radix trie 30 | * @param key key to insert (bitstring) 31 | * @param keylen length of the key (in bytes) 32 | * @param masklen lenght of mask that should be applied to the key (in bits) 33 | * @param value opaque value pointer 34 | * @return previous value of the key or `RADIX_NO_VALUE` 35 | */ 36 | uintptr_t 37 | radix_insert_compressed (radix_compressed_t * tree, 38 | guint8 *key, gsize keylen, 39 | gsize masklen, 40 | uintptr_t value); 41 | 42 | /** 43 | * Find a key in a radix trie 44 | * @param tree radix trie 45 | * @param key key to find (bitstring) 46 | * @param keylen length of a key 47 | * @return opaque pointer or `RADIX_NO_VALUE` if no value has been found 48 | */ 49 | uintptr_t radix_find_compressed (radix_compressed_t * tree, const guint8 *key, 50 | gsize keylen); 51 | 52 | /** 53 | * Destroy the complete radix trie 54 | * @param tree 55 | */ 56 | void radix_destroy_compressed (radix_compressed_t *tree); 57 | 58 | /** 59 | * Create new radix trie 60 | * @return 61 | */ 62 | radix_compressed_t *radix_create_compressed (void); 63 | 64 | /** 65 | * Insert list of ip addresses and masks to the radix tree 66 | * @param list string line of addresses 67 | * @param separators string of characters used as separators 68 | * @param tree target tree 69 | * @return number of elements inserted 70 | */ 71 | gint rspamd_radix_add_iplist (const gchar *list, const gchar *separators, 72 | radix_compressed_t *tree, gconstpointer value, gboolean resolve); 73 | 74 | /** 75 | * Generic version of @see rspamd_radix_add_iplist. This function creates tree 76 | * if `tree` is NULL. 77 | */ 78 | gboolean radix_add_generic_iplist (const gchar *ip_list, 79 | radix_compressed_t **tree, gboolean resolve); 80 | 81 | /** 82 | * Returns number of elements in the tree 83 | * @param tree 84 | * @return 85 | */ 86 | gsize radix_get_size (radix_compressed_t *tree); 87 | 88 | /** 89 | * Return string that describes this radix tree (memory, nodes, compression etc) 90 | * @param tree 91 | * @return constant string 92 | */ 93 | const gchar * radix_get_info (radix_compressed_t *tree); 94 | 95 | uintptr_t radix_find_rmilter_addr (radix_compressed_t * tree, 96 | const struct rmilter_inet_address *addr); 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /src/ratelimit.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2012, Vsevolod Stakhov 3 | * All rights reserved. 4 | 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. Redistributions in binary form 9 | * must reproduce the above copyright notice, this list of conditions and the 10 | * following disclaimer in the documentation and/or other materials provided with 11 | * the distribution. Neither the name of the author nor the names of its 12 | * contributors may be used to endorse or promote products derived from this 13 | * software without specific prior written permission. 14 | 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include "config.h" 28 | 29 | #include "radix.h" 30 | #include "cfg_file.h" 31 | #include "rmilter.h" 32 | #include "cache.h" 33 | #include "upstream.h" 34 | #include "ratelimit.h" 35 | 36 | #define EXPIRE_TIME 86400 37 | 38 | struct ratelimit_bucket_s 39 | { 40 | double tm; 41 | double count; 42 | }; 43 | 44 | enum keytype 45 | { 46 | TO = 0, TO_IP, TO_IP_FROM, BOUNCE_TO, BOUNCE_TO_IP 47 | }; 48 | 49 | /* Convert string to lowercase */ 50 | static void convert_to_lowercase(char *str, unsigned int size) 51 | { 52 | while (size--) { 53 | *str = tolower (*str); 54 | str++; 55 | } 56 | } 57 | 58 | /* Return lenth of user part */ 59 | static size_t extract_user_part(const char *str) 60 | { 61 | size_t user_part_len; 62 | const char *p; 63 | 64 | /* Extract user part from rcpt */ 65 | p = str; 66 | user_part_len = 0; 67 | while (*p++) { 68 | if (*p == '@') { 69 | break; 70 | } 71 | user_part_len++; 72 | } 73 | 74 | return user_part_len; 75 | } 76 | 77 | static int 78 | is_whitelisted (struct rmilter_inet_address *addr, const char *rcpt, 79 | struct config_file *cfg) 80 | { 81 | if (is_whitelisted_rcpt (&cfg->wlist_rcpt_limit, rcpt) 82 | || is_whitelisted_rcpt (&cfg->wlist_rcpt_global, rcpt)) { 83 | return 1; 84 | } 85 | 86 | if (radix_find_rmilter_addr (cfg->limit_whitelist_tree, addr) 87 | != RADIX_NO_VALUE) { 88 | return 2; 89 | } 90 | 91 | return 0; 92 | } 93 | 94 | static int is_bounce(char *from, struct config_file *cfg) 95 | { 96 | size_t user_part_len; 97 | struct addr_list_entry *cur_addr = NULL; 98 | 99 | user_part_len = extract_user_part (from); 100 | HASH_FIND (hh, cfg->bounce_addrs, from, user_part_len, cur_addr); 101 | 102 | if (cur_addr) { 103 | return 1; 104 | } 105 | 106 | return 0; 107 | } 108 | 109 | static int make_key(char *buf, size_t buflen, enum keytype type, 110 | struct mlfi_priv *priv, const char *rcpt) 111 | { 112 | int r = 0; 113 | switch (type) { 114 | case TO: 115 | r = snprintf(buf, buflen, "%s", rcpt); 116 | break; 117 | case TO_IP: 118 | r = snprintf(buf, buflen, "%s:%s", rcpt, priv->priv_ip); 119 | break; 120 | case TO_IP_FROM: 121 | r = snprintf(buf, buflen, "%s:%s:%s", rcpt, priv->priv_ip, 122 | priv->priv_from); 123 | break; 124 | case BOUNCE_TO: 125 | r = snprintf(buf, buflen, "%s:<>", rcpt); 126 | break; 127 | case BOUNCE_TO_IP: 128 | r = snprintf(buf, buflen, "%s:%s:<>", rcpt, priv->priv_ip); 129 | break; 130 | } 131 | 132 | if (r >= buflen) { 133 | return 0; 134 | } 135 | 136 | convert_to_lowercase (buf, r); 137 | 138 | return r; 139 | } 140 | 141 | static int check_specific_limit(struct mlfi_priv *priv, struct config_file *cfg, 142 | enum keytype type, bucket_t *bucket, double tm, const char *rcpt, 143 | int is_update) 144 | { 145 | struct memcached_server *selected; 146 | struct ratelimit_bucket_s *b; 147 | char key[MAXKEYLEN]; 148 | size_t klen, dlen; 149 | 150 | if (bucket->burst == 0 || bucket->rate == 0) { 151 | return 1; 152 | } 153 | 154 | klen = make_key (key, sizeof(key), type, priv, rcpt); 155 | 156 | if (klen == 0) { 157 | msg_err("<%s>; check_specific_limit: got error bad too long key", priv->mlfi_id); 158 | return -1; 159 | } 160 | 161 | dlen = sizeof (*b); 162 | 163 | if (!rmilter_query_cache (cfg, RMILTER_QUERY_RATELIMIT, key, klen, 164 | (unsigned char **) &b, &dlen, priv)) { 165 | b = calloc (1, sizeof (*b)); 166 | dlen = sizeof (*b); 167 | 168 | if (b == NULL) { 169 | msg_err("<%s>; check_specific_limit: calloc failed: %s", 170 | priv->mlfi_id, strerror (errno)); 171 | return -1; 172 | } 173 | } 174 | 175 | msg_debug("<%s>; check_specific_limit: got limit for key: '%s', " 176 | "count: %.1f, time: %.1f", priv->mlfi_id, key, b->count, b->tm); 177 | /* Leak from bucket at specified rate */ 178 | if (b->count > 0) { 179 | b->count -= (tm - b->tm) * bucket->rate; 180 | } 181 | 182 | b->count += is_update; 183 | b->tm = tm; 184 | if (b->count < 0) { 185 | b->count = 0; 186 | } 187 | 188 | if (is_update && b->count == 0) { 189 | /* Delete key if bucket is empty */ 190 | rmilter_delete_cache (cfg, RMILTER_QUERY_RATELIMIT, key, klen, priv); 191 | } 192 | else { 193 | /* Update rate limit */ 194 | rmilter_set_cache (cfg, RMILTER_QUERY_RATELIMIT, key, klen, 195 | (unsigned char *) b, dlen, EXPIRE_TIME, priv); 196 | } 197 | 198 | if (b->count > bucket->burst && !is_update) { 199 | /* Rate limit exceeded */ 200 | msg_info( 201 | "<%s>; rate_check: ratelimit exceeded for key: %s, count: %.2f, burst: %u", 202 | priv->mlfi_id, key, b->count, bucket->burst); 203 | free (b); 204 | 205 | return 0; 206 | } 207 | 208 | free (b); 209 | /* Rate limit not exceeded */ 210 | return 1; 211 | } 212 | 213 | int 214 | rate_check (struct mlfi_priv *priv, struct config_file *cfg, 215 | const char *rcpt, int is_update) 216 | { 217 | double t; 218 | struct timeval tm; 219 | int r; 220 | 221 | if (!cfg->ratelimit_enable) { 222 | return 1; 223 | } 224 | 225 | if (priv->priv_addr.family == AF_INET 226 | && is_whitelisted (&priv->priv_addr, rcpt, cfg) 227 | != 0) { 228 | msg_info("<%s>; rate_check: address is whitelisted, skipping checks", priv->mlfi_id); 229 | return 1; 230 | } 231 | 232 | tm.tv_sec = priv->conn_tm.tv_sec; 233 | tm.tv_usec = priv->conn_tm.tv_usec; 234 | 235 | t = tm.tv_sec + tm.tv_usec / 1000000.; 236 | 237 | if (is_bounce (priv->priv_from, cfg) != 0) { 238 | msg_debug( 239 | "<%s>; rate_check: bounce address detected, doing special checks: %s", 240 | priv->mlfi_id, priv->priv_from); 241 | r = check_specific_limit (priv, cfg, BOUNCE_TO, &cfg->limit_bounce_to, 242 | t, rcpt, is_update); 243 | if (r != 1) { 244 | return r; 245 | } 246 | r = check_specific_limit (priv, cfg, BOUNCE_TO_IP, 247 | &cfg->limit_bounce_to_ip, t, rcpt, is_update); 248 | if (r != 1) { 249 | return r; 250 | } 251 | } 252 | /* Check other limits */ 253 | r = check_specific_limit (priv, cfg, TO_IP_FROM, &cfg->limit_to_ip_from, t, 254 | rcpt, is_update); 255 | if (r != 1) { 256 | return r; 257 | } 258 | r = check_specific_limit (priv, cfg, TO_IP, &cfg->limit_to_ip, t, rcpt, 259 | is_update); 260 | if (r != 1) { 261 | return r; 262 | } 263 | r = check_specific_limit (priv, cfg, TO, &cfg->limit_to, t, rcpt, 264 | is_update); 265 | if (r != 1) { 266 | return r; 267 | } 268 | 269 | return 1; 270 | } 271 | 272 | /* 273 | * vi:ts=4 274 | */ 275 | -------------------------------------------------------------------------------- /src/ratelimit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2012, Vsevolod Stakhov 3 | * All rights reserved. 4 | 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. Redistributions in binary form 9 | * must reproduce the above copyright notice, this list of conditions and the 10 | * following disclaimer in the documentation and/or other materials provided with 11 | * the distribution. Neither the name of the author nor the names of its 12 | * contributors may be used to endorse or promote products derived from this 13 | * software without specific prior written permission. 14 | 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef RATELIMIT_H 28 | #define RATELIMIT_H 29 | #include 30 | 31 | /* Forward declarations */ 32 | struct mlfi_priv; 33 | struct config_file; 34 | 35 | int rate_check (struct mlfi_priv *priv, struct config_file *cfg, const char *rcpt, int is_update); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/rmilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2012, Vsevolod Stakhov 3 | * All rights reserved. 4 | 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. Redistributions in binary form 9 | * must reproduce the above copyright notice, this list of conditions and the 10 | * following disclaimer in the documentation and/or other materials provided with 11 | * the distribution. Neither the name of the author nor the names of its 12 | * contributors may be used to endorse or promote products derived from this 13 | * software without specific prior written permission. 14 | 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef RMILTER_H 28 | #define RMILTER_H 29 | 30 | #include "config.h" 31 | #include "util.h" 32 | #include "cfg_file.h" 33 | 34 | #ifdef WITH_DKIM 35 | #include 36 | #endif 37 | 38 | #ifndef ADDRLEN 39 | #define ADDRLEN 324 40 | #endif 41 | 42 | #ifndef NS_MAXDNAME 43 | #define NS_MAXDNAME 1025 44 | #endif 45 | 46 | #define STAGE_MAX 7 47 | 48 | #define RCODE_REJECT "554" 49 | #define RCODE_TEMPFAIL "451" 50 | #define RCODE_LATER "452" 51 | #define XCODE_REJECT "5.7.1" 52 | #define XCODE_TEMPFAIL "4.7.1" 53 | 54 | 55 | struct rmilter_rng_state { 56 | pthread_mutex_t mtx; 57 | uint64_t s[16]; 58 | int p; 59 | }; 60 | 61 | /* Structures and macros used */ 62 | struct rcpt { 63 | char r_addr[ADDRLEN + 1]; 64 | int is_whitelisted; 65 | struct rcpt *prev, *next; 66 | }; 67 | 68 | struct mlfi_priv { 69 | struct rmilter_inet_address priv_addr; 70 | char priv_ip[INET6_ADDRSTRLEN + 1]; 71 | char priv_hostname[ADDRLEN + 1]; 72 | char priv_helo[ADDRLEN + 1]; 73 | char priv_from[ADDRLEN + 1]; 74 | char priv_user[ADDRLEN + 1]; 75 | char message_id[ADDRLEN + 1]; 76 | struct rcpt *rcpts; 77 | char *priv_subject; 78 | int priv_rcptcount; 79 | struct { 80 | char *header_name; 81 | char *header_value; 82 | } priv_cur_header; 83 | struct { 84 | char *value; 85 | size_t len; 86 | } priv_cur_body; 87 | char mlfi_id[14]; 88 | char queue_id[32]; 89 | char mta_tag[ADDRLEN + 1]; 90 | char reply_id[ADDRLEN + 33]; 91 | 92 | #ifdef HAVE_PATH_MAX 93 | char file[PATH_MAX]; 94 | #elif defined(HAVE_MAXPATHLEN) 95 | char file[MAXPATHLEN]; 96 | #else 97 | #error "neither PATH_MAX nor MAXPATHLEN defined" 98 | #endif 99 | FILE *fileh; 100 | int filed; 101 | struct timeval conn_tm; 102 | struct rule* matched_rules[STAGE_MAX]; 103 | long eoh_pos; 104 | short int strict; 105 | /* Config serial */ 106 | short int serial; 107 | short int has_return_path; 108 | short int complete_to_beanstalk; 109 | short int has_whitelisted; 110 | short int authenticated; 111 | #ifdef WITH_DKIM 112 | DKIM *dkim; 113 | struct dkim_domain_entry *dkim_domain; 114 | #endif 115 | }; 116 | 117 | #define MLFIPRIV ((struct mlfi_priv *) smfi_getpriv(ctx)) 118 | 119 | #endif /* RMILTER_H */ 120 | /* 121 | * vi:ts=4 122 | */ 123 | -------------------------------------------------------------------------------- /src/upstream.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2012, Vsevolod Stakhov 3 | * All rights reserved. 4 | 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. Redistributions in binary form 9 | * must reproduce the above copyright notice, this list of conditions and the 10 | * following disclaimer in the documentation and/or other materials provided with 11 | * the distribution. Neither the name of the author nor the names of its 12 | * contributors may be used to endorse or promote products derived from this 13 | * software without specific prior written permission. 14 | 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef UPSTREAM_H 28 | #define UPSTREAM_H 29 | 30 | #include "config.h" 31 | 32 | struct upstream { 33 | unsigned int errors; 34 | time_t time; 35 | unsigned char dead; 36 | unsigned char priority; 37 | int16_t weight; 38 | }; 39 | 40 | struct mlfi_priv; 41 | 42 | void upstream_fail (struct upstream *up, time_t now); 43 | void upstream_ok (struct upstream *up, time_t now); 44 | void revive_all_upstreams (void *ups, unsigned int members, unsigned int msize, 45 | const struct mlfi_priv *priv); 46 | 47 | struct upstream* get_random_upstream (void *ups, unsigned int members, unsigned int msize, 48 | time_t now, time_t error_timeout, 49 | time_t revive_timeout, unsigned int max_errors, const struct mlfi_priv *priv); 50 | 51 | struct upstream* get_upstream_by_hash (void *ups, unsigned int members, unsigned int msize, 52 | time_t now, time_t error_timeout, 53 | time_t revive_timeout, unsigned int max_errors, 54 | const unsigned char *key, unsigned int keylen, 55 | const struct mlfi_priv *priv); 56 | 57 | struct upstream* get_upstream_round_robin (void *ups, unsigned int members, unsigned int msize, 58 | time_t now, time_t error_timeout, 59 | time_t revive_timeout, unsigned int max_errors, 60 | const struct mlfi_priv *priv); 61 | 62 | struct upstream* get_upstream_master_slave (void *ups, unsigned int members, unsigned int msize, 63 | time_t now, time_t error_timeout, 64 | time_t revive_timeout, unsigned int max_errors, 65 | const struct mlfi_priv *priv); 66 | 67 | #endif /* UPSTREAM_H */ 68 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Vsevolod Stakhov 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * 12 | * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | */ 23 | 24 | #ifndef UTIL_H_ 25 | #define UTIL_H_ 26 | 27 | #include "config.h" 28 | 29 | struct rmilter_inet_address { 30 | int family; 31 | union { 32 | struct sockaddr_in sa4; 33 | struct sockaddr_in6 sa6; 34 | struct sockaddr sa; 35 | } addr; 36 | }; 37 | 38 | /** 39 | * Copy src to dest limited to len, in compare with standard strlcpy(3) rmilter_strlcpy does not 40 | * traverse the whole string and it is possible to use it for non NULL terminated strings. This is 41 | * more like memccpy(dst, src, size, '\0') 42 | * 43 | * @param dst destination string 44 | * @param src source string 45 | * @param siz length of destination buffer 46 | * @return bytes copied 47 | */ 48 | size_t rmilter_strlcpy (char *dst, const char *src, size_t siz); 49 | 50 | typedef struct rmilter_pidfh_s { 51 | int pf_fd; 52 | #ifdef HAVE_PATH_MAX 53 | char pf_path[PATH_MAX + 1]; 54 | #elif defined(HAVE_MAXPATHLEN) 55 | char pf_path[MAXPATHLEN + 1]; 56 | #else 57 | char pf_path[1024 + 1]; 58 | #endif 59 | dev_t pf_dev; 60 | ino_t pf_ino; 61 | } rmilter_pidfh_t; 62 | rmilter_pidfh_t * rmilter_pidfile_open (const char *path, 63 | mode_t mode, 64 | pid_t *pidptr); 65 | int rmilter_pidfile_write (rmilter_pidfh_t *pfh); 66 | int rmilter_pidfile_close (rmilter_pidfh_t *pfh); 67 | int rmilter_pidfile_remove (rmilter_pidfh_t *pfh); 68 | 69 | #define msg_err(args...) syslog(LOG_ERR, ##args) 70 | #define msg_warn(args...) syslog(LOG_WARNING, ##args) 71 | #define msg_info(args...) syslog(LOG_INFO, ##args) 72 | #ifdef WITH_DEBUG 73 | #define msg_debug(args...) syslog(LOG_DEBUG, ##args) 74 | #else 75 | #define msg_debug(args...) do {} while(0) 76 | #endif 77 | 78 | struct mlfi_priv; 79 | 80 | char* rmilter_encode_base64 (const u_char *in, size_t inlen, int str_len, 81 | size_t *outlen); 82 | 83 | int rmilter_connect_addr (const char *addr, int port, int msec, 84 | const struct mlfi_priv *priv); 85 | int rmilter_poll_fd (int fd, int timeout, short events); 86 | 87 | #define msec_to_tv(msec, tv) do { (tv)->tv_sec = (msec) / 1000; (tv)->tv_usec = \ 88 | ((msec) - (tv)->tv_sec * 1000) * 1000; \ 89 | } while (0) 90 | 91 | void rmilter_str_lc (char *str, unsigned int size); 92 | 93 | ssize_t rmilter_atomic_write (int fd, const void *buf, size_t len); 94 | 95 | int rmilter_file_xopen (const char *fname, int oflags, unsigned int mode); 96 | void* rmilter_file_xmap (const char *fname, unsigned int mode, size_t *size); 97 | 98 | /** 99 | * Fold header using rfc822 rules, return new GString from the previous one 100 | * @param name name of header (used just for folding) 101 | * @param value value of header 102 | * @return new GString with the folded value 103 | */ 104 | GString *rmilter_header_value_fold (const gchar *name, 105 | const gchar *value, 106 | guint fold_max); 107 | 108 | #endif /* UTIL_H_ */ 109 | --------------------------------------------------------------------------------