Compare commits
315 commits
solanum
...
merging-so
Author | SHA1 | Date | |
---|---|---|---|
c7da812303 | |||
|
6b8d4cb307 | ||
|
66225eb7ef | ||
|
f5f2190b40 | ||
|
529e8705c2 | ||
|
fca7f870c8 | ||
|
5572f43834 | ||
|
905508885b | ||
|
88fbca25d0 | ||
|
a74ee5d2c7 | ||
|
24b8fd0063 | ||
|
a589946b42 | ||
|
f44a0d7ea2 | ||
|
358a73c8d5 | ||
|
3c36726f83 | ||
|
9a10251fd5 | ||
|
d7aec4702a | ||
|
908f1c30c4 | ||
|
cee332ab83 | ||
|
0ca3cf0d91 | ||
|
590a46b165 | ||
|
23e6d4ed73 | ||
|
6d01464fc5 | ||
|
a4e5c2fa61 | ||
|
074e23e4e2 | ||
|
0b79494ec9 | ||
|
d89ff1897d | ||
|
bec08a8364 | ||
|
ef70f680c5 | ||
|
a034b14fbf | ||
|
cc34e7543a | ||
|
3ea954da3a | ||
|
28caceba33 | ||
|
4f8ad92ab4 | ||
|
151c4614a0 | ||
|
03f04cd80e | ||
|
f515fa9382 | ||
|
8e02234970 | ||
|
ccaf2012bd | ||
|
6e93b3b153 | ||
|
bfffef7436 | ||
|
11d111c3fa | ||
|
6c00795284 | ||
|
412263854f | ||
|
9d80b087cd | ||
|
cf5b56b06b | ||
|
5ce1252007 | ||
|
e1d4ebda4d | ||
|
c380c2336a | ||
|
b018538406 | ||
|
55735d9d7e | ||
|
754c1edf2e | ||
|
a6485efda0 | ||
|
c41d0c0f5f | ||
|
75399a9334 | ||
|
18823bcfca | ||
|
1c2012f03b | ||
|
6420b39ad0 | ||
|
55ae03aee1 | ||
|
ae6ce6100a | ||
|
a21843a0a0 | ||
|
8fc0cea653 | ||
|
ed78e97a96 | ||
|
ea3ca814f5 | ||
|
e09aeac9ed | ||
|
85f46bb59e | ||
|
e55c29ef11 | ||
|
3109b8a636 | ||
|
c67c9451a1 | ||
|
daf1b4b9af | ||
|
8952f21843 | ||
|
ec5f6dc23b | ||
|
f21bac62f4 | ||
|
f54e6c3558 | ||
|
82e920102f | ||
|
6f1e0a6f47 | ||
|
9ca4bd7e0c | ||
|
7406d7acad | ||
|
8c8a219e71 | ||
|
bd62a802f9 | ||
|
efc60d52a3 | ||
|
81e245be5b | ||
|
ee0a3970c8 | ||
|
72fd7c04ac | ||
|
eef58149c7 | ||
|
e52356b21e | ||
|
9c7e29bf66 | ||
|
ef14b780b4 | ||
|
fa2b7ab282 | ||
|
b253a53c51 | ||
|
28541a0d96 | ||
|
3f7ccca917 | ||
|
9519919ff5 | ||
|
846629b388 | ||
|
9b7cc82b90 | ||
|
a8517ee77c | ||
|
81ae0a7d1b | ||
|
9d7c65294f | ||
|
ce15ac6c0b | ||
|
705ca33e17 | ||
|
167ca46a04 | ||
|
51d65d191a | ||
|
62c0ac4124 | ||
|
789bb31c92 | ||
|
1b7c6aff1a | ||
|
e0f1c3b5bc | ||
|
68ba8e8125 | ||
|
8b96afb67b | ||
|
7e7107a6b7 | ||
|
5bc633fd77 | ||
|
c14e0b9523 | ||
|
f41c25c0c1 | ||
|
ea56df54f7 | ||
|
194a960192 | ||
|
79a69a8e43 | ||
|
8bb743a695 | ||
|
689137420b | ||
|
2838bd22d6 | ||
|
932350e189 | ||
|
bdfadfcb99 | ||
|
bc9cb138a4 | ||
|
c74b47583e | ||
|
0da7307521 | ||
|
2874f74c81 | ||
|
6fa52d140c | ||
|
d8df3c90de | ||
|
5d8a480305 | ||
|
b012874243 | ||
|
9f21f1b353 | ||
|
9bd8c1c0dc | ||
|
b04acc54ac | ||
|
5633e89376 | ||
|
e140ba71d6 | ||
|
6bcfd29624 | ||
|
4574e77f43 | ||
|
db05a36210 | ||
|
9cdd7270f9 | ||
|
a91a4515c9 | ||
|
5fd7e2bb8c | ||
|
598a7d3b7e | ||
|
8d0153ff55 | ||
|
0264fe161f | ||
|
9c98c1f866 | ||
|
d4b074a771 | ||
|
e386d7f362 | ||
|
2815967598 | ||
|
256e6fd251 | ||
|
65b9b1d06d | ||
|
aaf6039eea | ||
|
785df805d7 | ||
|
2afd965b21 | ||
|
0a9598655c | ||
|
95bdc091b2 | ||
|
ccd9e858f3 | ||
|
2b439b88fc | ||
|
6f3d3cb6f5 | ||
|
0508eea2ed | ||
|
a3868e7141 | ||
|
866026ab70 | ||
|
5de892828f | ||
|
ecfdcb08e8 | ||
|
fe9fba46cf | ||
|
70bb2e24e0 | ||
|
1a75461594 | ||
|
0071c423d5 | ||
|
d4e71871c0 | ||
|
939d7ec7fe | ||
|
9c7dda22e8 | ||
|
dd59642de1 | ||
|
67d31a2755 | ||
|
9986455edc | ||
|
2b5bf0bada | ||
|
f4726edf7a | ||
|
4369f1fa55 | ||
|
8ebebff4b4 | ||
|
8099d352c9 | ||
|
c6600fe290 | ||
|
d70129a0d6 | ||
|
2d01971d05 | ||
|
4fc76590b9 | ||
|
25ecd3cc86 | ||
|
5797027e9f | ||
|
3f32d48dab | ||
|
4618ec248e | ||
|
77119a5031 | ||
|
a41a1d20db | ||
|
5103d939d0 | ||
|
992aa93b80 | ||
|
6cc08ecf90 | ||
|
fde101b9b2 | ||
|
75d7d47a7e | ||
|
d9e6ff7349 | ||
|
4d89c83c32 | ||
|
a3a25a4c8a | ||
|
159d901e71 | ||
|
de78e5906a | ||
|
92c04c6b9d | ||
|
5feb292aa9 | ||
|
5bb5226edc | ||
|
15e2cab1e5 | ||
|
01ce1c508d | ||
|
b4a0b60dff | ||
|
d9c825c4de | ||
|
06c588e535 | ||
|
767fad345f | ||
|
a8db009575 | ||
|
45d05d8882 | ||
|
bd8097c459 | ||
|
485b5b8084 | ||
|
9114e3a2dc | ||
|
47d51fe3ac | ||
|
cc04fbe3f9 | ||
|
62fc0eab03 | ||
|
4e9441a1cb | ||
|
e569720fe1 | ||
|
a61e06e1d1 | ||
|
1c39c519fe | ||
|
1c7d295320 | ||
|
8a40573369 | ||
|
2aec9b6d68 | ||
|
1f30c8943b | ||
|
265dc4e53c | ||
|
f66a6390b0 | ||
|
101c659117 | ||
|
1083d8557b | ||
|
f0ad82013c | ||
|
ac62792970 | ||
|
988fedf212 | ||
|
bef81a5d45 | ||
|
8cd8b24ffb | ||
|
db12df5c16 | ||
|
8668cb9b9d | ||
|
46c61dd478 | ||
|
978c8ae828 | ||
|
163a4a9d06 | ||
|
5b900411bf | ||
|
295c8f7d37 | ||
|
354e61b4c2 | ||
|
566f46785f | ||
|
2a8ec58c15 | ||
|
ee10f6cdcc | ||
|
50851b0b55 | ||
|
1bc097d1ec | ||
|
89d4c468b6 | ||
|
818a3fda94 | ||
|
be31ac33d5 | ||
|
0db0805ed5 | ||
|
df51e80717 | ||
|
f92b4d81d4 | ||
|
6df12e8169 | ||
|
ede25e0a8a | ||
|
6f3651f8ec | ||
|
b21ed5c0aa | ||
|
42b029d0d6 | ||
|
6008896554 | ||
|
865e70f529 | ||
|
c2af499d4d | ||
|
c9c2d6ea12 | ||
|
531e6323d8 | ||
|
036419c344 | ||
|
cfcd4615ed | ||
|
19d9c417af | ||
|
f2fbec4510 | ||
|
f89406ac72 | ||
|
c1007a93d5 | ||
|
3ba0923c0e | ||
|
4c9ab80f6b | ||
|
07b6e728b5 | ||
|
545668de33 | ||
|
856ecd0011 | ||
|
24ba10b6b1 | ||
|
f70b6f55f9 | ||
|
1554951205 | ||
|
36335ea3f2 | ||
|
3288fc4648 | ||
|
f15a30a16f | ||
|
b24cfd7c50 | ||
|
06feeb244d | ||
|
897c10749d | ||
|
e5afd80775 | ||
|
0bd2f0b710 | ||
|
419f0c6af7 | ||
|
e719e46d27 | ||
|
82ce2ab4da | ||
|
cc3e763e26 | ||
|
03e6030ed2 | ||
|
bc2eeb0992 | ||
|
82d827469c | ||
|
828fe03888 | ||
|
f55078bdc7 | ||
|
96129f7d4d | ||
|
01fdef77e6 | ||
|
57d3cd1159 | ||
|
fd5af836b7 | ||
|
d35caf56cb | ||
|
2a1e5de8cb | ||
|
ddc6c9a922 | ||
|
b8cf4b3bf2 | ||
|
1ea72c8f86 | ||
|
5c8da48264 | ||
|
1d2ba176ea | ||
|
bf9e0a6ed5 | ||
|
558bca8608 | ||
|
db1b744e41 | ||
|
18244e32f3 | ||
|
987fa43982 | ||
|
f76b0cee90 | ||
|
d5ff7a9c3c | ||
|
1533b40304 | ||
|
b7cca0143d | ||
|
b1f028e5d4 | ||
|
56f1d769bd | ||
|
604ab13778 | ||
|
e3af723d23 | ||
|
e253d010ed |
98 changed files with 93265 additions and 35 deletions
58
.travis.yml
Normal file
58
.travis.yml
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
# Travis-CI Build for charybdis-3.5
|
||||||
|
# see travis-ci.org for details
|
||||||
|
|
||||||
|
language: c
|
||||||
|
|
||||||
|
# Use the faster container-based infrastructure.
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['gcc-4.8', 'automake', 'autoconf', 'libtool', 'shtool', 'libsqlite3-dev', 'python-sphinx', 'texinfo']
|
||||||
|
env: COMPILER=gcc-4.8
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['gcc-4.9', 'automake', 'autoconf', 'libtool', 'shtool', 'libsqlite3-dev', 'python-sphinx', 'texinfo']
|
||||||
|
env: COMPILER=gcc-4.9
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['gcc-5', 'automake', 'autoconf', 'libtool', 'shtool', 'libsqlite3-dev', 'python-sphinx', 'texinfo']
|
||||||
|
env: COMPILER=gcc-5
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7']
|
||||||
|
packages: ['clang-3.7', 'automake', 'autoconf', 'libtool', 'shtool', 'libsqlite3-dev', 'python-sphinx', 'texinfo']
|
||||||
|
env: COMPILER=clang-3.7
|
||||||
|
|
||||||
|
- os: osx
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER=clang LIBTOOLIZE=glibtoolize
|
||||||
|
|
||||||
|
|
||||||
|
osx_image: xcode7.3
|
||||||
|
|
||||||
|
cache:
|
||||||
|
apt:
|
||||||
|
ccache:
|
||||||
|
|
||||||
|
script:
|
||||||
|
- CC=$COMPILER ./configure --with-shared-sqlite
|
||||||
|
- make -j4
|
||||||
|
- make install
|
||||||
|
- "if [ ${TRAVIS_OS_NAME} != 'osx' ]; then make -C doc/oper-guide html man info; fi"
|
43
CREDITS
43
CREDITS
|
@ -1,3 +1,45 @@
|
||||||
|
<<<<<<< .merge_file_qEvahK
|
||||||
|
Charybdis started as an evolution from ircd-ratbox. Its development
|
||||||
|
is led by a team of dedicated developers who have put a lot of time
|
||||||
|
into the project, and it has seen use on a variety of different
|
||||||
|
network configurations.
|
||||||
|
|
||||||
|
The Charybdis core team, listed in nick-alphabetical order:
|
||||||
|
|
||||||
|
amdj, Aaron Jones <aaronmdjones -at- gmail.com>
|
||||||
|
Elizafox, Elizabeth Myers <elizabeth -at- interlinked.me>
|
||||||
|
jilles, Jilles Tjoelker <jilles -at- stack.nl>
|
||||||
|
kaniini, William Pitcock <nenolod -at- dereferenced.org>
|
||||||
|
mr_flea, Keith Buck <mr_flea -at- esper.net>
|
||||||
|
Simon, Simon Arlott <charybdis -at- uuid.uk>
|
||||||
|
|
||||||
|
The following people are also project members, listed in nick-alphabetical
|
||||||
|
order:
|
||||||
|
|
||||||
|
grawity, Mantas Mikulėnas <grawity -at- gmail.com>
|
||||||
|
jdhore, JD Horelick <jdhore1 -at- gmail.com>
|
||||||
|
viatsko, Valerii Iatsko <dwr -at- codingbox.io>
|
||||||
|
|
||||||
|
The following people have made contributions to the Charybdis releases,
|
||||||
|
in nick-alphabetical order:
|
||||||
|
|
||||||
|
AndroSyn, Aaron Sethman <androsyn -at- ratbox.org>
|
||||||
|
anfl, Lee Hardy <lee -at- leeh.co.uk>
|
||||||
|
beu, Elfyn McBratney <elfyn.mcbratney -at- gmail.com>
|
||||||
|
dwr, Valery Yatsko <dwr -at- shadowircd.net>
|
||||||
|
Elizacat, Elizabeth Myers <elizabeth -at- interlinked.me>
|
||||||
|
Entrope, Michael Poole <mdpoole -at- trolius.org>
|
||||||
|
gxti, Michael Tharp <gxti -at- partiallystapled.com>
|
||||||
|
mniip <mniip -at- mniip.com>
|
||||||
|
spb, Stephen Bennett <spb -at- attenuate.org>
|
||||||
|
Taros, Brett Greenham <taros -at- shadowircd.net>
|
||||||
|
ThaPrince, Jon Christopherson <jon -at- vile.com>
|
||||||
|
twincest, River Tarnell <river -at- attenuate.org>
|
||||||
|
w00t, Robin Burchell <surreal.w00t -at- gmail.com>
|
||||||
|
|
||||||
|
Visit the Charybdis website at: http://www.charybdis.io/
|
||||||
|
Visit us on IRC at: irc.charybdis.io #charybdis
|
||||||
|
=======
|
||||||
Solanum is based on Charybdis, which was based on ircd-ratbox.
|
Solanum is based on Charybdis, which was based on ircd-ratbox.
|
||||||
|
|
||||||
Development is led by a group of representatives from Libera Chat
|
Development is led by a group of representatives from Libera Chat
|
||||||
|
@ -26,3 +68,4 @@ is in doc/credits-past.txt.
|
||||||
|
|
||||||
Visit the Solanum website at: https://solanum.chat/
|
Visit the Solanum website at: https://solanum.chat/
|
||||||
Visit us on IRC at: irc.libera.chat #solanum
|
Visit us on IRC at: irc.libera.chat #solanum
|
||||||
|
>>>>>>> .merge_file_gXRYUC
|
||||||
|
|
110
NEWS.md
110
NEWS.md
|
@ -1,5 +1,114 @@
|
||||||
# News
|
# News
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_h36DbE
|
||||||
|
This is charybdis 3.5.7, Copyright (c) 2005-2019 Charybdis team.
|
||||||
|
See LICENSE for licensing details (GPL v2).
|
||||||
|
|
||||||
|
## charybdis-3.5.7
|
||||||
|
|
||||||
|
This is primarily a bugfix release.
|
||||||
|
|
||||||
|
### user
|
||||||
|
- modules/m_sasl.c: don't process messages if SASL has been aborted
|
||||||
|
- src/s_user.c: don't corrupt usermodes on module unload/reload
|
||||||
|
|
||||||
|
### misc
|
||||||
|
- modules/m_list.c: add fake /LIST reply output to help fight spambots
|
||||||
|
|
||||||
|
## charybdis-3.5.6
|
||||||
|
|
||||||
|
This is primarily a bugfix release.
|
||||||
|
|
||||||
|
### security
|
||||||
|
- doc/reference.conf: clarify: TLS server fingerprints are not optional
|
||||||
|
- extensions/extb_ssl.c: add support for matching fingerprints
|
||||||
|
- libratbox/src/mbedtls.c: check public/private keys match
|
||||||
|
- libratbox/src/mbedtls.c: support ChaCha20-Poly1305 by default
|
||||||
|
|
||||||
|
### user
|
||||||
|
- libratbox/src/commio.c: fix accept() for IPv6 after dropping IPv4
|
||||||
|
- src/client.c: don't delete servers from the client hash table
|
||||||
|
- src/s_user.c: don't send fake MODE for clients with CHGHOST support
|
||||||
|
- modules/m_sasl.c: abort session if we receive '*' as data
|
||||||
|
- modules/m_sasl.c: check agent is present after every client exit
|
||||||
|
|
||||||
|
### misc
|
||||||
|
- configure: adjust dlopen/dlsym checks to work under libasan
|
||||||
|
- configure: allow exact PID file prefix to be specified
|
||||||
|
- doc/: convert SGML oper guide to RST
|
||||||
|
- doc/: point users to HELP EXTBAN for inline help
|
||||||
|
- extensions/m_webirc.c: set sockhost before using it to set host
|
||||||
|
|
||||||
|
## charybdis-3.5.5
|
||||||
|
|
||||||
|
This is a minor bugfix release only
|
||||||
|
|
||||||
|
### misc
|
||||||
|
- GNUTLS: Initialise a variable before trying to load server certificates
|
||||||
|
- GNUTLS: Log why certificate fingerprint generation fails
|
||||||
|
- GNUTLS: Avoid using new tokens in the default priority string
|
||||||
|
|
||||||
|
## charybdis-3.5.4
|
||||||
|
|
||||||
|
### security
|
||||||
|
- Disable TLSv1.0 in all backends
|
||||||
|
- Fix possible NULL dereference in mkpasswd
|
||||||
|
- Backport SubjectPublicKeyInfo certificate digest methods from version 4
|
||||||
|
- Backport REHASH SSLD functionality from version 4
|
||||||
|
- This allows new ssld processes to be started (to inherit a new or upgraded TLS backend
|
||||||
|
library) without dropping any existing clients or active server links
|
||||||
|
|
||||||
|
### misc
|
||||||
|
- Various memory leak fixes in newconf, sslproc, zlib
|
||||||
|
- Fix crash bug when performing /whois on someone half-way through a CHALLENGE
|
||||||
|
- Fix crash bug when performing remote MODRESTART command
|
||||||
|
- Allow extban matching presence in secret (+s) channels
|
||||||
|
|
||||||
|
## charybdis-3.5.3
|
||||||
|
|
||||||
|
### security
|
||||||
|
- incorporate all relevant security patches for charybdis through 6th September 2016:
|
||||||
|
- fix issue allowing EXTERNAL authentications to be spoofed using a certificate not actually
|
||||||
|
held by the authenticating user
|
||||||
|
|
||||||
|
### misc
|
||||||
|
- mbedtls TLS backend improvements from charybdis 4 and 5:
|
||||||
|
- add support for configurable ciphersuites
|
||||||
|
- disable legacy (SSLv2) renegotiation support if possible
|
||||||
|
- disable session tickets if possible
|
||||||
|
- general robustness improvements
|
||||||
|
- gnutls TLS backend improvements from charybdis 4:
|
||||||
|
- make certfp support more reliable on newer gnutls versions
|
||||||
|
- avoid possible null dereference when constructing ciphersuites
|
||||||
|
- openssl TLS backend improvements from charybdis 4:
|
||||||
|
- avoid a possible use-after-free issue when newer openssl versions cannot load keypairs in a rehash
|
||||||
|
- improve compatibility with libressl
|
||||||
|
- more robustly load DH parameters files
|
||||||
|
- daemonization improvements from charybdis 4
|
||||||
|
|
||||||
|
## charybdis-3.5.2
|
||||||
|
|
||||||
|
### user
|
||||||
|
- Allow IRCv3.1 STARTTLS to work with other SSL backends besides OpenSSL.
|
||||||
|
- Fix an edge case regression involving channel ban cache that was introduced in 3.5.0.
|
||||||
|
|
||||||
|
### misc
|
||||||
|
- Ensure ssld does not crash when DH parameters are not provided.
|
||||||
|
- mbedtls TLS backend improvements from charybdis 4:
|
||||||
|
- add support for CertFP
|
||||||
|
- provide personalization data for the PRNG
|
||||||
|
- fix library linking order
|
||||||
|
- openssl TLS backend improvements from charybdis 4:
|
||||||
|
- do not manually initialise openssl when running with OpenSSL 1.1.0 or later
|
||||||
|
- support ECDHE on more than one curve on OpenSSL 1.0.2 and above
|
||||||
|
- fix DH parameters memory leak
|
||||||
|
- free the old TLS context before constructing a new one (#186)
|
||||||
|
|
||||||
|
## charybdis-3.5.1
|
||||||
|
|
||||||
|
### misc
|
||||||
|
- Backport various ssld IPC improvements from master.
|
||||||
|
=======
|
||||||
This is solanum 1.0-dev.
|
This is solanum 1.0-dev.
|
||||||
See LICENSE for licensing details (GPL v2).
|
See LICENSE for licensing details (GPL v2).
|
||||||
|
|
||||||
|
@ -197,6 +306,7 @@ bolded warnings in the full release notes below.
|
||||||
- Support for ratbox-style 'iodebug' hooks has been removed.
|
- Support for ratbox-style 'iodebug' hooks has been removed.
|
||||||
- New channel types may be added by modules, see `extensions/chantype_dummy.c`
|
- New channel types may be added by modules, see `extensions/chantype_dummy.c`
|
||||||
for a very simple example.
|
for a very simple example.
|
||||||
|
>>>>>>> .merge_file_4c8glm
|
||||||
|
|
||||||
## charybdis-3.5.0
|
## charybdis-3.5.0
|
||||||
|
|
||||||
|
|
17
README.md
17
README.md
|
@ -60,21 +60,38 @@ See `./configure --help` for build options.
|
||||||
|
|
||||||
* For SSL/TLS client and server connections, one of:
|
* For SSL/TLS client and server connections, one of:
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_7Huc5m
|
||||||
|
* OpenSSL 1.0.0 or newer (--enable-openssl)
|
||||||
|
* LibreSSL (--enable-openssl)
|
||||||
|
* MbedTLS (--enable-mbedtls)
|
||||||
|
* GnuTLS (--enable-gnutls)
|
||||||
|
=======
|
||||||
* OpenSSL 1.0.0 or newer (`--enable-openssl`)
|
* OpenSSL 1.0.0 or newer (`--enable-openssl`)
|
||||||
* LibreSSL (`--enable-openssl`)
|
* LibreSSL (`--enable-openssl`)
|
||||||
* mbedTLS (`--enable-mbedtls`)
|
* mbedTLS (`--enable-mbedtls`)
|
||||||
* GnuTLS (`--enable-gnutls`)
|
* GnuTLS (`--enable-gnutls`)
|
||||||
|
>>>>>>> .merge_file_dqpn0B
|
||||||
|
|
||||||
* For certificate-based oper CHALLENGE, OpenSSL 1.0.0 or newer.
|
* For certificate-based oper CHALLENGE, OpenSSL 1.0.0 or newer.
|
||||||
(Using CHALLENGE is not recommended for new deployments, so if you want to use a different TLS library,
|
(Using CHALLENGE is not recommended for new deployments, so if you want to use a different TLS library,
|
||||||
feel free.)
|
feel free.)
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_7Huc5m
|
||||||
|
* For ECDHE under OpenSSL, on Solaris and RHEL/Fedora (and its derivatives such as CentOS) you will
|
||||||
|
need to compile your own OpenSSL on these systems, as they have removed support for ECC/ECDHE.
|
||||||
|
Alternatively, consider using another library (see above).
|
||||||
|
|
||||||
|
# tips
|
||||||
|
|
||||||
|
* To report bugs in charybdis, visit us on IRC at chat.freenode.net #charybdis
|
||||||
|
=======
|
||||||
* For ECDHE under OpenSSL, on Solaris you will need to compile your own OpenSSL on these systems, as they
|
* For ECDHE under OpenSSL, on Solaris you will need to compile your own OpenSSL on these systems, as they
|
||||||
have removed support for ECC/ECDHE. Alternatively, consider using another library (see above).
|
have removed support for ECC/ECDHE. Alternatively, consider using another library (see above).
|
||||||
|
|
||||||
# tips
|
# tips
|
||||||
|
|
||||||
* To report bugs in Solanum, visit us at `#solanum` on [Libera Chat](https://libera.chat)
|
* To report bugs in Solanum, visit us at `#solanum` on [Libera Chat](https://libera.chat)
|
||||||
|
>>>>>>> .merge_file_dqpn0B
|
||||||
|
|
||||||
* Please read [doc/readme.txt](doc/readme.txt) to get an overview of the current documentation.
|
* Please read [doc/readme.txt](doc/readme.txt) to get an overview of the current documentation.
|
||||||
|
|
||||||
|
|
16
aclocal.m4
vendored
Normal file
16
aclocal.m4
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
|
||||||
|
|
||||||
|
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This file is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
|
||||||
|
m4_include([m4/charybdis.m4])
|
||||||
|
m4_include([m4/pkg.m4])
|
2
appveyor.yml
Normal file
2
appveyor.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
except:
|
||||||
|
- release/3.5
|
|
@ -236,10 +236,14 @@ parse_request(rb_helper *helper)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_OcfD4C
|
||||||
|
static void __attribute__((noreturn))
|
||||||
|
=======
|
||||||
static void
|
static void
|
||||||
error_cb(rb_helper *helper) __attribute__((noreturn));
|
error_cb(rb_helper *helper) __attribute__((noreturn));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
>>>>>>> .merge_file_OF4zx2
|
||||||
error_cb(rb_helper *helper)
|
error_cb(rb_helper *helper)
|
||||||
{
|
{
|
||||||
if(in_transaction)
|
if(in_transaction)
|
||||||
|
@ -281,10 +285,14 @@ setup_signals(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_OcfD4C
|
||||||
|
static void __attribute__((noreturn))
|
||||||
|
=======
|
||||||
static void
|
static void
|
||||||
db_error_cb(const char *errstr) __attribute__((noreturn));
|
db_error_cb(const char *errstr) __attribute__((noreturn));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
>>>>>>> .merge_file_OF4zx2
|
||||||
db_error_cb(const char *errstr)
|
db_error_cb(const char *errstr)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
@ -310,8 +318,7 @@ main(int argc, char *argv[])
|
||||||
rsdb_init(db_error_cb);
|
rsdb_init(db_error_cb);
|
||||||
check_schema();
|
check_schema();
|
||||||
rb_helper_loop(bandb_helper, 0);
|
rb_helper_loop(bandb_helper, 0);
|
||||||
|
/* UNREACHABLE */
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -141,7 +141,7 @@ main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
case 'h':
|
case 'h':
|
||||||
print_help(EXIT_SUCCESS);
|
print_help(EXIT_SUCCESS);
|
||||||
break;
|
/* noreturn call above, this is unreachable */
|
||||||
case 'i':
|
case 'i':
|
||||||
flag.none = false;
|
flag.none = false;
|
||||||
flag.import = true;
|
flag.import = true;
|
||||||
|
@ -861,8 +861,8 @@ bt_smalldate(const char *string)
|
||||||
/**
|
/**
|
||||||
* you are here ->.
|
* you are here ->.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
print_help(int i_exit)
|
print_help(const int i_exit)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "bantool v.%s - the solanum database tool.\n", BT_VERSION);
|
fprintf(stderr, "bantool v.%s - the solanum database tool.\n", BT_VERSION);
|
||||||
fprintf(stderr, "Copyright (C) 2008 Daniel J Reidy <dubkat@gmail.com>\n");
|
fprintf(stderr, "Copyright (C) 2008 Daniel J Reidy <dubkat@gmail.com>\n");
|
||||||
|
@ -892,5 +892,6 @@ print_help(int i_exit)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
" path : An optional directory containing old ratbox configs for import, or export.\n");
|
" path : An optional directory containing old ratbox configs for import, or export.\n");
|
||||||
fprintf(stderr, " If not specified, it looks in PREFIX/etc.\n");
|
fprintf(stderr, " If not specified, it looks in PREFIX/etc.\n");
|
||||||
|
|
||||||
exit(i_exit);
|
exit(i_exit);
|
||||||
}
|
}
|
||||||
|
|
163
configure.ac
163
configure.ac
|
@ -12,9 +12,13 @@ AC_GNU_SOURCE
|
||||||
|
|
||||||
AC_PROG_CC_C99
|
AC_PROG_CC_C99
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_E9kQwr
|
||||||
|
AC_INIT([charybdis], [3.5.7])
|
||||||
|
=======
|
||||||
if test x"$ac_cv_prog_cc_c99" = "xno"; then
|
if test x"$ac_cv_prog_cc_c99" = "xno"; then
|
||||||
AC_ERROR([solanum requires a C99 capable compiler])
|
AC_ERROR([solanum requires a C99 capable compiler])
|
||||||
fi
|
fi
|
||||||
|
>>>>>>> .merge_file_knjbyY
|
||||||
|
|
||||||
AC_PREFIX_DEFAULT($HOME/ircd)
|
AC_PREFIX_DEFAULT($HOME/ircd)
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
@ -114,7 +118,6 @@ AS_IF([test "x$enable_fhs_paths" = "xyes"],
|
||||||
pkglibdir='${libdir}/${PACKAGE_TARNAME}'
|
pkglibdir='${libdir}/${PACKAGE_TARNAME}'
|
||||||
AC_SUBST([pkglibdir])
|
AC_SUBST([pkglibdir])
|
||||||
AC_SUBST([rundir])
|
AC_SUBST([rundir])
|
||||||
AC_SUBST([pkgrundir])
|
|
||||||
AC_SUBST([pkglocalstatedir])
|
AC_SUBST([pkglocalstatedir])
|
||||||
AC_DEFINE_DIR([PKGLOCALSTATEDIR], [pkglocalstatedir], [[Directory in which to store state, such as ban database]])
|
AC_DEFINE_DIR([PKGLOCALSTATEDIR], [pkglocalstatedir], [[Directory in which to store state, such as ban database]])
|
||||||
AC_SUBST([pkglibexecdir])
|
AC_SUBST([pkglibexecdir])
|
||||||
|
@ -392,21 +395,40 @@ AC_ARG_WITH(moduledir,
|
||||||
AC_DEFINE_DIR(MODULE_DIR, moduledir, [Prefix where modules are installed.])
|
AC_DEFINE_DIR(MODULE_DIR, moduledir, [Prefix where modules are installed.])
|
||||||
AC_SUBST_DIR([moduledir])
|
AC_SUBST_DIR([moduledir])
|
||||||
|
|
||||||
|
dnl **********************************************************************
|
||||||
dnl Check for --with-rundir
|
dnl Check for --with-rundir
|
||||||
|
dnl **********************************************************************
|
||||||
|
|
||||||
AC_MSG_CHECKING([whether or modify rundir])
|
AC_MSG_CHECKING([whether to modify rundir])
|
||||||
AC_ARG_WITH([rundir],
|
AC_ARG_WITH([rundir],
|
||||||
[AC_HELP_STRING([--with-rundir=DIR],
|
[AC_HELP_STRING([--with-rundir=DIR],
|
||||||
[Directory in which to store pidfile.])],
|
[Directory to use as prefix for pidfile.])],
|
||||||
[AC_MSG_RESULT([yes])
|
[AC_MSG_RESULT([yes])
|
||||||
rundir=`echo $withval | sed 's/\/$//'`],
|
rundir=`echo $withval | sed 's/\/$//'`],
|
||||||
[AC_MSG_RESULT([no])
|
[AC_MSG_RESULT([no])
|
||||||
AS_IF([test "x$enable_fhs_paths" = "xyes"],
|
AS_IF([test "x$enable_fhs_paths" = "xyes"],
|
||||||
[rundir='${prefix}/run'],
|
[rundir='${prefix}/run'],
|
||||||
[rundir='${sysconfdir}'])])
|
[rundir='${sysconfdir}'])])
|
||||||
AC_SUBST([rundir])
|
|
||||||
|
dnl **********************************************************************
|
||||||
|
dnl Check for --with-pkgrundir
|
||||||
|
dnl **********************************************************************
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to modify pkgrundir])
|
||||||
|
AC_ARG_WITH([pkgrundir],
|
||||||
|
[AC_HELP_STRING([--with-pkgrundir=DIR],
|
||||||
|
[Directory in which to store pidfile.])],
|
||||||
|
[AC_MSG_RESULT([yes])
|
||||||
|
pkgrundir=`echo $withval | sed 's/\/$//'`],
|
||||||
|
[AC_MSG_RESULT([no])])
|
||||||
|
|
||||||
|
AC_SUBST([pkgrundir])
|
||||||
AC_DEFINE_DIR([PKGRUNDIR], [pkgrundir], [Directory to store pidfile in.])
|
AC_DEFINE_DIR([PKGRUNDIR], [pkgrundir], [Directory to store pidfile in.])
|
||||||
|
|
||||||
|
dnl **********************************************************************
|
||||||
|
dnl Check for --with-program-prefix
|
||||||
|
dnl **********************************************************************
|
||||||
|
|
||||||
dnl Installed utility program prefixes (does not affect binaries
|
dnl Installed utility program prefixes (does not affect binaries
|
||||||
dnl installed into pkglibexecdir)
|
dnl installed into pkglibexecdir)
|
||||||
AC_MSG_CHECKING([for program prefix])
|
AC_MSG_CHECKING([for program prefix])
|
||||||
|
@ -443,8 +465,16 @@ AC_HELP_STRING([--with-custom-version=NAME],
|
||||||
AC_MSG_RESULT([no])]
|
AC_MSG_RESULT([no])]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if git rev-parse --git-dir > /dev/null 2>&1; then
|
||||||
|
GITSHA=$(git rev-parse --short HEAD)
|
||||||
|
else
|
||||||
|
GITSHA="unknown"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
AC_DEFINE_UNQUOTED(BRANDING_NAME, ["$BRANDING_NAME"], [Custom branding name.])
|
AC_DEFINE_UNQUOTED(BRANDING_NAME, ["$BRANDING_NAME"], [Custom branding name.])
|
||||||
AC_DEFINE_UNQUOTED(BRANDING_VERSION, ["$BRANDING_VERSION"], [Custom branding name.])
|
AC_DEFINE_UNQUOTED(BRANDING_VERSION, ["${BRANDING_VERSION}-${GITSHA}"], [Custom branding name.])
|
||||||
|
|
||||||
|
|
||||||
if test "x$BRANDING_NAME" != "x$PACKAGE_NAME"; then
|
if test "x$BRANDING_NAME" != "x$PACKAGE_NAME"; then
|
||||||
AC_DEFINE(CUSTOM_BRANDING, 1, [Define if custom branding is enabled.])
|
AC_DEFINE(CUSTOM_BRANDING, 1, [Define if custom branding is enabled.])
|
||||||
|
@ -544,12 +574,135 @@ AC_DEFINE_UNQUOTED(TOPICLEN, ${TOPICLEN}, [Maximum topic length (<=390)])
|
||||||
AC_DEFINE_UNQUOTED(NICKLEN, (${NICKLEN}+1), [Nickname length])
|
AC_DEFINE_UNQUOTED(NICKLEN, (${NICKLEN}+1), [Nickname length])
|
||||||
|
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_E9kQwr
|
||||||
|
dnl Second stage: check for functions and headers.
|
||||||
|
if test "$shared_modules" = yes; then
|
||||||
|
DYNLINK_C=dynlink.c
|
||||||
|
AC_CHECK_HEADERS(dlfcn.h)
|
||||||
|
AC_SEARCH_LIBS(shl_load, dld,
|
||||||
|
[
|
||||||
|
AC_DEFINE(HAVE_SHL_LOAD, 1, [Define if the shl_load function is available.])
|
||||||
|
SUFFIX=".sl"
|
||||||
|
MOD_TARGET=hpux_shared
|
||||||
|
SEDOBJ="s/\.o/.sl/g"
|
||||||
|
],
|
||||||
|
dnl !shl_load:
|
||||||
|
[
|
||||||
|
dnl standard dlopen
|
||||||
|
AC_SEARCH_LIBS(dlopen, [dl c_r],
|
||||||
|
[
|
||||||
|
AC_SEARCH_LIBS(dlsym, [dl c_r],
|
||||||
|
[
|
||||||
|
if
|
||||||
|
test "$ac_cv_search_dlopen" != "none required" &&
|
||||||
|
test "$ac_cv_search_dlsym" != "none required" &&
|
||||||
|
test "$ac_cv_search_dlopen" != "$ac_cv_search_dlsym"; then
|
||||||
|
AC_MSG_WARN([dlopen and dlsym from different sources])
|
||||||
|
fi
|
||||||
|
AC_DEFINE(HAVE_DLOPEN, 1, [Define if the dlopen function is available.])
|
||||||
|
SUFFIX=".so"
|
||||||
|
MOD_TARGET=shared_modules
|
||||||
|
SEDOBJ="s/\.o/.so/g"
|
||||||
|
if test "$AppleGCC" = yes; then
|
||||||
|
AC_CHECK_HEADERS([mach-o/dyld.h])
|
||||||
|
fi
|
||||||
|
AC_CHECK_FUNCS(dlfunc)
|
||||||
|
],
|
||||||
|
[
|
||||||
|
shared_modules=no
|
||||||
|
])
|
||||||
|
],
|
||||||
|
[
|
||||||
|
shared_modules=no
|
||||||
|
])
|
||||||
|
])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_DEFINE_UNQUOTED(SHARED_SUFFIX, "$SUFFIX", [Suffix for shared libraries on this platform.])
|
||||||
|
|
||||||
|
dnl Third stage - wrangling the linker.
|
||||||
|
if test "$shared_modules" = yes; then
|
||||||
|
# The GNU linker requires the -export-dynamic option to make
|
||||||
|
# all symbols visible in the dynamic symbol table.
|
||||||
|
hold_ldflags=$LDFLAGS
|
||||||
|
AC_MSG_CHECKING(for the ld -export-dynamic flag)
|
||||||
|
LDFLAGS="${LDFLAGS} -Wl,-export-dynamic -Werror"
|
||||||
|
AC_LINK_IFELSE(AC_LANG_PROGRAM([],[int i;]), found=yes, found=no)
|
||||||
|
LDFLAGS=$hold_ldflags
|
||||||
|
|
||||||
|
if expr "`uname -s`" : ^IRIX >/dev/null 2>&1; then
|
||||||
|
found="no, IRIX ld uses -B,dynamic"
|
||||||
|
LDFLAGS="${LDFLAGS} -Wl,-B,dynamic"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if expr "`uname -s`" : ^AIX >/dev/null 2>&1; then
|
||||||
|
found="no, AIX ld uses -G -brtl"
|
||||||
|
LDFLAGS="${LDFLAGS} -Wl,-G,-brtl"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_RESULT($found)
|
||||||
|
|
||||||
|
if test "$found" = yes; then
|
||||||
|
LDFLAGS="${LDFLAGS} -Wl,-export-dynamic"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(for compiler option to produce PIC)
|
||||||
|
dnl The order should be here to check for groups of compilers,
|
||||||
|
dnl then for odd compilers, then if no PICFLAGS were set up,
|
||||||
|
dnl check for GCC and set defaults, or else error. -jmallett
|
||||||
|
if test "$SGS" = "yes"; then
|
||||||
|
AC_MSG_RESULT([SVR4 SGS interfaces: -KPIC -DPIC -G])
|
||||||
|
PICFLAGS="-KPIC -DPIC -G"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$AppleGCC" = "yes"; then
|
||||||
|
AC_MSG_RESULT([Darwin Mach-O bundles: -fno-common -bundle -flat_namespace -undefined suppress])
|
||||||
|
PICFLAGS="-fno-common -bundle -flat_namespace -undefined suppress"
|
||||||
|
fi
|
||||||
|
dnl Please note, that on HPUX two different stages of module compilation occurs, since
|
||||||
|
dnl while compiling modules, the compiler does not allow you to give arguments
|
||||||
|
dnl to the linker. (I did not design this)
|
||||||
|
dnl So we need -c in the first stage of module compilation.
|
||||||
|
dnl In the second stage, we link the modules via ld -b.
|
||||||
|
dnl Additionally, HPUX does not like -export-dynamic, it likes -E instead.
|
||||||
|
dnl -TimeMr14C
|
||||||
|
if test "$HPUX" = "yes" -a "$CC" != gcc; then
|
||||||
|
AC_MSG_RESULT(HP-UX cc: +z -r -q -n)
|
||||||
|
PICFLAGS="+z -r -q -n -c"
|
||||||
|
AC_MSG_CHECKING([if +ESfic is required on this platform])
|
||||||
|
|
||||||
|
if expr "`$CC +ESfic 2>&1`" : ".*neither supported.*" >/dev/null; then
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
PICFLAGS="$PICFLAGS +ESfic"
|
||||||
|
fi
|
||||||
|
|
||||||
|
LDFLAGS="${LDFLAGS} -Wl,-E"
|
||||||
|
fi
|
||||||
|
if test "$Tru" = yes -a "$CC" != gcc; then
|
||||||
|
AC_MSG_RESULT([Tru64: -shared -expect_unresolved '*'])
|
||||||
|
PICFLAGS="-shared -expect_unresolved '*' "
|
||||||
|
LDFLAGS="-call_shared"
|
||||||
|
fi
|
||||||
|
if test -z "$PICFLAGS"; then
|
||||||
|
if test "$ac_cv_c_compiler_gnu" = "yes"; then
|
||||||
|
AC_MSG_RESULT(gcc: -fPIC -DPIC -shared)
|
||||||
|
PICFLAGS="-fPIC -DPIC -shared"
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
shared_modules=no
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
=======
|
||||||
AC_ARG_WITH(asan,
|
AC_ARG_WITH(asan,
|
||||||
AC_HELP_STRING([--with-asan],[Build with Address Sanitizer]),
|
AC_HELP_STRING([--with-asan],[Build with Address Sanitizer]),
|
||||||
[
|
[
|
||||||
CFLAGS="$CFLAGS -fsanitize=address"
|
CFLAGS="$CFLAGS -fsanitize=address"
|
||||||
LDFLAGS="$LDFLAGS -fsanitize=address"
|
LDFLAGS="$LDFLAGS -fsanitize=address"
|
||||||
])
|
])
|
||||||
|
>>>>>>> .merge_file_knjbyY
|
||||||
|
|
||||||
# rpath, for finding librb.so at run time
|
# rpath, for finding librb.so at run time
|
||||||
hold_ldflags=$LDFLAGS
|
hold_ldflags=$LDFLAGS
|
||||||
|
|
26
default.nix
Normal file
26
default.nix
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{ stdenv, bash
|
||||||
|
, flex, bison
|
||||||
|
, openssl, gnutls, zlib }:
|
||||||
|
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
pname = "charybdis";
|
||||||
|
version = "3.5.7";
|
||||||
|
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
patches = [
|
||||||
|
./patches/bandb-remove-setenv.patch
|
||||||
|
];
|
||||||
|
|
||||||
|
configureFlags = [
|
||||||
|
"--enable-epoll"
|
||||||
|
"--enable-ipv6"
|
||||||
|
"--with-zlib-path=${zlib.dev}/lib"
|
||||||
|
"--enable-openssl=${openssl.dev}"
|
||||||
|
"--with-program-prefix=charybdis-"
|
||||||
|
"--sysconfdir=/etc/charybdis"
|
||||||
|
];
|
||||||
|
|
||||||
|
nativeBuildInputs = [ bison flex ];
|
||||||
|
buildInputs = [ openssl gnutls zlib ];
|
||||||
|
}
|
51
doc/ircd.conf.example
Normal file → Executable file
51
doc/ircd.conf.example
Normal file → Executable file
|
@ -8,6 +8,33 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Extensions */
|
/* Extensions */
|
||||||
|
<<<<<<< .merge_file_MAZNsP
|
||||||
|
#loadmodule "extensions/chm_operonly_compat.so";
|
||||||
|
#loadmodule "extensions/chm_quietunreg_compat.so";
|
||||||
|
#loadmodule "extensions/chm_sslonly_compat.so";
|
||||||
|
#loadmodule "extensions/createauthonly.so";
|
||||||
|
#loadmodule "extensions/extb_account.so";
|
||||||
|
#loadmodule "extensions/extb_canjoin.so";
|
||||||
|
#loadmodule "extensions/extb_channel.so";
|
||||||
|
#loadmodule "extensions/extb_combi.so";
|
||||||
|
#loadmodule "extensions/extb_extgecos.so";
|
||||||
|
#loadmodule "extensions/extb_hostmask.so";
|
||||||
|
#loadmodule "extensions/extb_oper.so";
|
||||||
|
#loadmodule "extensions/extb_realname.so";
|
||||||
|
#loadmodule "extensions/extb_server.so";
|
||||||
|
#loadmodule "extensions/extb_ssl.so";
|
||||||
|
#loadmodule "extensions/extb_usermode.so";
|
||||||
|
#loadmodule "extensions/hurt.so";
|
||||||
|
#loadmodule "extensions/m_findforwards.so";
|
||||||
|
#loadmodule "extensions/m_identify.so";
|
||||||
|
#loadmodule "extensions/no_oper_invis.so";
|
||||||
|
#loadmodule "extensions/sno_farconnect.so";
|
||||||
|
#loadmodule "extensions/sno_globalkline.so";
|
||||||
|
#loadmodule "extensions/sno_globaloper.so";
|
||||||
|
#loadmodule "extensions/sno_whois.so";
|
||||||
|
#loadmodule "extensions/override.so";
|
||||||
|
#loadmodule "extensions/no_kill_services.so";
|
||||||
|
=======
|
||||||
#loadmodule "extensions/chm_nonotice";
|
#loadmodule "extensions/chm_nonotice";
|
||||||
#loadmodule "extensions/chm_operpeace";
|
#loadmodule "extensions/chm_operpeace";
|
||||||
#loadmodule "extensions/createauthonly";
|
#loadmodule "extensions/createauthonly";
|
||||||
|
@ -33,6 +60,7 @@
|
||||||
#loadmodule "extensions/sno_globaloper";
|
#loadmodule "extensions/sno_globaloper";
|
||||||
#loadmodule "extensions/override";
|
#loadmodule "extensions/override";
|
||||||
#loadmodule "extensions/no_kill_services";
|
#loadmodule "extensions/no_kill_services";
|
||||||
|
>>>>>>> .merge_file_DV7Blq
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IP cloaking extensions: use ip_cloaking_4.0
|
* IP cloaking extensions: use ip_cloaking_4.0
|
||||||
|
@ -530,6 +558,14 @@ alias "MS" {
|
||||||
target = "MemoServ";
|
target = "MemoServ";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
fakechannel "#honeypot" {
|
||||||
|
topic = "Come in";
|
||||||
|
users_min = 50;
|
||||||
|
users_max = 300;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
general {
|
general {
|
||||||
hide_error_messages = opers;
|
hide_error_messages = opers;
|
||||||
hide_spoof_ips = yes;
|
hide_spoof_ips = yes;
|
||||||
|
@ -607,6 +643,7 @@ general {
|
||||||
caller_id_wait = 1 minute;
|
caller_id_wait = 1 minute;
|
||||||
pace_wait_simple = 1 second;
|
pace_wait_simple = 1 second;
|
||||||
pace_wait = 10 seconds;
|
pace_wait = 10 seconds;
|
||||||
|
listfake_wait = 180 seconds;
|
||||||
short_motd = no;
|
short_motd = no;
|
||||||
ping_cookie = no;
|
ping_cookie = no;
|
||||||
connect_timeout = 30 seconds;
|
connect_timeout = 30 seconds;
|
||||||
|
@ -638,3 +675,17 @@ modules {
|
||||||
path = "modules";
|
path = "modules";
|
||||||
path = "modules/autoload";
|
path = "modules/autoload";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
vhost "selfsigned.hades.arpa" {
|
||||||
|
ssl_private_key = "etc/selfssl.key";
|
||||||
|
ssl_cert = "etc/selfssl.pem";
|
||||||
|
};
|
||||||
|
|
||||||
|
vhost "oldca.hades.arpa" {
|
||||||
|
ssl_private_key = "etc/oldssl.key";
|
||||||
|
ssl_cert = "etc/oldssl2.pem";
|
||||||
|
ssl_dh_params = "etc/olddh.pem";
|
||||||
|
ssl_cipher_list = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL";;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
|
@ -87,12 +87,21 @@ hub
|
||||||
serving as a hub, i.e. have multiple servers connected to it.
|
serving as a hub, i.e. have multiple servers connected to it.
|
||||||
|
|
||||||
vhost
|
vhost
|
||||||
|
<<<<<<< .merge_file_cTfvge
|
||||||
|
An optional text field which defines an IP from which to connect
|
||||||
|
outward to other IRC servers.
|
||||||
|
|
||||||
|
vhost6
|
||||||
|
An optional text field which defines an IPv6 IP from which to
|
||||||
|
connect outward to other IRC servers.
|
||||||
|
=======
|
||||||
An optional text field which defines an IPv4 address from which
|
An optional text field which defines an IPv4 address from which
|
||||||
to connect outward to other IRC servers.
|
to connect outward to other IRC servers.
|
||||||
|
|
||||||
vhost6
|
vhost6
|
||||||
An optional text field which defines an IPv6 address from which
|
An optional text field which defines an IPv6 address from which
|
||||||
to connect outward to other IRC servers.
|
to connect outward to other IRC servers.
|
||||||
|
>>>>>>> .merge_file_3UzJEV
|
||||||
|
|
||||||
admin {} block
|
admin {} block
|
||||||
--------------
|
--------------
|
||||||
|
@ -255,9 +264,12 @@ flags
|
||||||
class
|
class
|
||||||
A name of a class to put users matching this auth{} block into.
|
A name of a class to put users matching this auth{} block into.
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_cTfvge
|
||||||
|
=======
|
||||||
umodes
|
umodes
|
||||||
Additional umodes to apply to the default_umodes upon connect.
|
Additional umodes to apply to the default_umodes upon connect.
|
||||||
|
|
||||||
|
>>>>>>> .merge_file_3UzJEV
|
||||||
auth {} flags
|
auth {} flags
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -449,6 +461,13 @@ host
|
||||||
``A`` or ``AAAA`` record (no ``CNAME``) and it must be
|
``A`` or ``AAAA`` record (no ``CNAME``) and it must be
|
||||||
the primary hostname for inbound connections to work.
|
the primary hostname for inbound connections to work.
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_cTfvge
|
||||||
|
IPv6 addresses must be in ``::`` shortened form; addresses which
|
||||||
|
then start with a colon must be prepended with a zero, for
|
||||||
|
example ``0::1``.
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_3UzJEV
|
||||||
send\_password
|
send\_password
|
||||||
The password to send to the other server.
|
The password to send to the other server.
|
||||||
|
|
||||||
|
@ -477,8 +496,12 @@ flags
|
||||||
|
|
||||||
aftype
|
aftype
|
||||||
The protocol that should be used to connect with, either ipv4 or
|
The protocol that should be used to connect with, either ipv4 or
|
||||||
|
<<<<<<< .merge_file_cTfvge
|
||||||
|
ipv6. This defaults to ipv4 unless host is a numeric IPv6 address.
|
||||||
|
=======
|
||||||
ipv6. This defaults to neither, allowing connection using either
|
ipv6. This defaults to neither, allowing connection using either
|
||||||
address family.
|
address family.
|
||||||
|
>>>>>>> .merge_file_3UzJEV
|
||||||
|
|
||||||
**connect {} flags**
|
**connect {} flags**
|
||||||
|
|
||||||
|
|
110
doc/reference.conf
Normal file → Executable file
110
doc/reference.conf
Normal file → Executable file
|
@ -47,6 +47,69 @@
|
||||||
* Charybdis contains several extensions that are not enabled by default.
|
* Charybdis contains several extensions that are not enabled by default.
|
||||||
* To use them, uncomment the lines below.
|
* To use them, uncomment the lines below.
|
||||||
*
|
*
|
||||||
|
<<<<<<< .merge_file_UmjhEh
|
||||||
|
* Channel mode +-A (admin only) -- chm_adminonly.so
|
||||||
|
* Channel mode +-O (oper only) -- chm_operonly.so
|
||||||
|
* Channel mode +-S (ssl only) -- chm_sslonly.so
|
||||||
|
* Emulates channel mode +-O (oper only) (+-iI $o) -- chm_operonly_compat.so
|
||||||
|
* Emulates channel mode +-R (quiet unreg) (+-q $~a) -- chm_quietunreg_compat.so
|
||||||
|
* Emulates channel mode +-S (ssl only) (+-b $~z) -- chm_sslonly_compat.so
|
||||||
|
* Restrict channel creation to logged in users -- createauthonly.so
|
||||||
|
* Account bans (+b $a[:mask]) -- extb_account.so
|
||||||
|
* Banned from another channel (+b $j:mask) -- extb_canjoin.so
|
||||||
|
* Other-channel bans (+b $c:mask) -- extb_channel.so
|
||||||
|
* Combination extbans -- extb_combi.so
|
||||||
|
* Extended ban (+b $x:mask) -- extb_extgecos.so
|
||||||
|
* Hostmask bans (for combination extbans) -- extb_hostmask.so
|
||||||
|
* Oper bans (+b $o) -- extb_oper.so
|
||||||
|
* Realname (gecos) bans (+b $r:mask) -- extb_realname.so
|
||||||
|
* Server bans (+b $s:mask) -- extb_server.so
|
||||||
|
* SSL bans (+b $z) -- extb_ssl.so
|
||||||
|
* User mode bans (+b $u:modes) -- extb_usermode.so
|
||||||
|
* HURT system -- hurt.so
|
||||||
|
* New host mangling (umode +x) -- ip_cloaking_4.0.so
|
||||||
|
* Old host mangling (umode +h) -- ip_cloaking.so
|
||||||
|
* Find channel forwards -- m_findforwards.so
|
||||||
|
* /identify support -- m_identify.so
|
||||||
|
* Opers cannot be invisible (umode +i) -- no_oper_invis.so
|
||||||
|
* Far connection notices (snomask +F) -- sno_farconnect.so
|
||||||
|
* Remote k/d/x line active notices -- sno_globalkline.so
|
||||||
|
* Remote oper up notices -- sno_globaloper.so
|
||||||
|
* /whois notifications (snomask +W) -- sno_whois.so
|
||||||
|
* Oper-override (modehacking only) -- override.so
|
||||||
|
* Stop services kills -- no_kill_services.so
|
||||||
|
*/
|
||||||
|
#loadmodule "extensions/chm_adminonly.so";
|
||||||
|
#loadmodule "extensions/chm_operonly.so";
|
||||||
|
#loadmodule "extensions/chm_sslonly.so";
|
||||||
|
#loadmodule "extensions/chm_operonly_compat.so";
|
||||||
|
#loadmodule "extensions/chm_quietunreg_compat.so";
|
||||||
|
#loadmodule "extensions/chm_sslonly_compat.so";
|
||||||
|
#loadmodule "extensions/createauthonly.so";
|
||||||
|
#loadmodule "extensions/extb_account.so";
|
||||||
|
#loadmodule "extensions/extb_canjoin.so";
|
||||||
|
#loadmodule "extensions/extb_channel.so";
|
||||||
|
#loadmodule "extensions/extb_combi.so";
|
||||||
|
#loadmodule "extensions/extb_extgecos.so";
|
||||||
|
#loadmodule "extensions/extb_hostmask.so";
|
||||||
|
#loadmodule "extensions/extb_oper.so";
|
||||||
|
#loadmodule "extensions/extb_realname.so";
|
||||||
|
#loadmodule "extensions/extb_server.so";
|
||||||
|
#loadmodule "extensions/extb_ssl.so";
|
||||||
|
#loadmodule "extensions/extb_usermode.so";
|
||||||
|
#loadmodule "extensions/hurt.so";
|
||||||
|
#loadmodule "extensions/ip_cloaking_4.0.so";
|
||||||
|
#loadmodule "extensions/ip_cloaking.so";
|
||||||
|
#loadmodule "extensions/m_findforwards.so";
|
||||||
|
#loadmodule "extensions/m_identify.so";
|
||||||
|
#loadmodule "extensions/no_oper_invis.so";
|
||||||
|
#loadmodule "extensions/sno_farconnect.so";
|
||||||
|
#loadmodule "extensions/sno_globalkline.so";
|
||||||
|
#loadmodule "extensions/sno_globaloper.so";
|
||||||
|
#loadmodule "extensions/sno_whois.so";
|
||||||
|
#loadmodule "extensions/override.so";
|
||||||
|
#loadmodule "extensions/no_kill_services.so";
|
||||||
|
=======
|
||||||
* Channel mode +-A (admin only) -- chm_adminonly
|
* Channel mode +-A (admin only) -- chm_adminonly
|
||||||
* Channel mode +-T (blocks notices) -- chm_nonotice
|
* Channel mode +-T (blocks notices) -- chm_nonotice
|
||||||
* Channel mode +-O (oper only) -- chm_operonly
|
* Channel mode +-O (oper only) -- chm_operonly
|
||||||
|
@ -112,6 +175,7 @@
|
||||||
#loadmodule "extensions/override";
|
#loadmodule "extensions/override";
|
||||||
#loadmodule "extensions/no_kill_services";
|
#loadmodule "extensions/no_kill_services";
|
||||||
#loadmodule "extensions/umode_hide_idle_time";
|
#loadmodule "extensions/umode_hide_idle_time";
|
||||||
|
>>>>>>> .merge_file_Mh5Whq
|
||||||
|
|
||||||
/* serverinfo {}: Contains information about the server. (OLD M:) */
|
/* serverinfo {}: Contains information about the server. (OLD M:) */
|
||||||
serverinfo {
|
serverinfo {
|
||||||
|
@ -145,6 +209,12 @@ serverinfo {
|
||||||
* This should be an ipv6 IP only.
|
* This should be an ipv6 IP only.
|
||||||
*/
|
*/
|
||||||
#vhost6 = "2001:db8:2::6";
|
#vhost6 = "2001:db8:2::6";
|
||||||
|
<<<<<<< .merge_file_UmjhEh
|
||||||
|
|
||||||
|
/* ssl_private_key: our ssl private key */
|
||||||
|
ssl_private_key = "etc/ssl.key";
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_Mh5Whq
|
||||||
|
|
||||||
/* ssl_cert: certificate (and optionally key) for our ssl server */
|
/* ssl_cert: certificate (and optionally key) for our ssl server */
|
||||||
ssl_cert = "etc/ssl.pem";
|
ssl_cert = "etc/ssl.pem";
|
||||||
|
@ -1014,6 +1084,14 @@ alias "MS" {
|
||||||
target = "MemoServ";
|
target = "MemoServ";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
fakechannel "#honeypot" {
|
||||||
|
topic = "Come in";
|
||||||
|
users_min = 50;
|
||||||
|
users_max = 300;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
/* The general block contains many of the options that were once compiled
|
/* The general block contains many of the options that were once compiled
|
||||||
* in options in config.h. The general block is read at start time.
|
* in options in config.h. The general block is read at start time.
|
||||||
*/
|
*/
|
||||||
|
@ -1316,6 +1394,9 @@ general {
|
||||||
*/
|
*/
|
||||||
pace_wait = 10 seconds;
|
pace_wait = 10 seconds;
|
||||||
|
|
||||||
|
/* listfake_wait: time until real list command can be used */
|
||||||
|
listfake_wait = 180 seconds;
|
||||||
|
|
||||||
/* short motd: send clients a notice telling them to read the motd
|
/* short motd: send clients a notice telling them to read the motd
|
||||||
* instead of forcing a motd to clients who may simply ignore it.
|
* instead of forcing a motd to clients who may simply ignore it.
|
||||||
*/
|
*/
|
||||||
|
@ -1465,6 +1546,20 @@ general {
|
||||||
* "SPKI:SHA2-256:" or "SPKI:SHA2-512:" depending on the hash type. These fingerprints
|
* "SPKI:SHA2-256:" or "SPKI:SHA2-512:" depending on the hash type. These fingerprints
|
||||||
* are not supported on servers running charybdis 3.5.3 or earlier.
|
* are not supported on servers running charybdis 3.5.3 or earlier.
|
||||||
*
|
*
|
||||||
|
<<<<<<< .merge_file_UmjhEh
|
||||||
|
* To generate a fingerprint from a certificate file, run the following:
|
||||||
|
* $ openssl x509 -outform DER -in your.crt | sha1sum (or sha256sum, or sha512sum)
|
||||||
|
*
|
||||||
|
* To generate a SPKI SHA-256 fingerprint, run the following:
|
||||||
|
* $ openssl x509 -pubkey -noout -in your.crt | openssl pkey -pubin -outform DER | \
|
||||||
|
* sha256sum | sed -r -e 's/^/SPKI:SHA2-256:/'
|
||||||
|
*
|
||||||
|
* To generate a SPKI SHA-512 fingerprint, run the following:
|
||||||
|
* $ openssl x509 -pubkey -noout -in your.crt | openssl pkey -pubin -outform DER | \
|
||||||
|
* sha512sum | sed -r -e 's/^/SPKI:SHA2-512:/'
|
||||||
|
*/
|
||||||
|
certfp_method = sha256;
|
||||||
|
=======
|
||||||
* To generate a fingerprint from a certificate file, please use the mkfingerprint utility
|
* To generate a fingerprint from a certificate file, please use the mkfingerprint utility
|
||||||
* program located in the bin/ subdirectory of your IRCd installation. Running it with no
|
* program located in the bin/ subdirectory of your IRCd installation. Running it with no
|
||||||
* arguments will give you a brief usage message; it takes method and filename arguments.
|
* arguments will give you a brief usage message; it takes method and filename arguments.
|
||||||
|
@ -1490,6 +1585,7 @@ general {
|
||||||
* requires extensions/drain to be loaded.
|
* requires extensions/drain to be loaded.
|
||||||
*/
|
*/
|
||||||
drain_reason = "This server is not accepting connections.";
|
drain_reason = "This server is not accepting connections.";
|
||||||
|
>>>>>>> .merge_file_Mh5Whq
|
||||||
};
|
};
|
||||||
|
|
||||||
modules {
|
modules {
|
||||||
|
@ -1502,3 +1598,17 @@ modules {
|
||||||
/* module: the name of a module to load on startup/rehash */
|
/* module: the name of a module to load on startup/rehash */
|
||||||
#module = "some_module";
|
#module = "some_module";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
vhost "selfsigned.hades.arpa" {
|
||||||
|
ssl_private_key = "etc/selfssl.key";
|
||||||
|
ssl_cert = "etc/selfssl.pem";
|
||||||
|
};
|
||||||
|
|
||||||
|
vhost "oldca.hades.arpa" {
|
||||||
|
ssl_private_key = "etc/oldssl.key";
|
||||||
|
ssl_cert = "etc/oldssl2.pem";
|
||||||
|
ssl_dh_params = "etc/olddh.pem";
|
||||||
|
ssl_cipher_list = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL";
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
/* SSL extban type: matches ssl users */
|
/* SSL extban type: matches ssl users */
|
||||||
|
|
||||||
|
/* This file is available under the same conditions as the rest of
|
||||||
|
https://github.com/asterIRC/ircd-chatd, and by extension, the rest
|
||||||
|
of Charybdis. */
|
||||||
|
|
||||||
#include "stdinc.h"
|
#include "stdinc.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
@ -11,7 +15,11 @@ static int _modinit(void);
|
||||||
static void _moddeinit(void);
|
static void _moddeinit(void);
|
||||||
static int eb_ssl(const char *data, struct Client *client_p, struct Channel *chptr, long mode_type);
|
static int eb_ssl(const char *data, struct Client *client_p, struct Channel *chptr, long mode_type);
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_utDAI3
|
||||||
|
DECLARE_MODULE_AV1(extb_ssl, _modinit, _moddeinit, NULL, NULL, NULL, "1.05");
|
||||||
|
=======
|
||||||
DECLARE_MODULE_AV2(extb_ssl, _modinit, _moddeinit, NULL, NULL, NULL, NULL, NULL, extb_desc);
|
DECLARE_MODULE_AV2(extb_ssl, _modinit, _moddeinit, NULL, NULL, NULL, NULL, NULL, extb_desc);
|
||||||
|
>>>>>>> .merge_file_lvPLfm
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_modinit(void)
|
_modinit(void)
|
||||||
|
@ -28,13 +36,17 @@ _moddeinit(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int eb_ssl(const char *data, struct Client *client_p,
|
static int eb_ssl(const char *data, struct Client *client_p,
|
||||||
struct Channel *chptr, long mode_type)
|
struct Channel *chptr, long mode_type)
|
||||||
{
|
{
|
||||||
|
|
||||||
(void)chptr;
|
(void)chptr;
|
||||||
(void)mode_type;
|
(void)mode_type;
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_utDAI3
|
||||||
|
if (! IsSSLClient(client_p))
|
||||||
|
=======
|
||||||
if (!IsSecureClient(client_p))
|
if (!IsSecureClient(client_p))
|
||||||
|
>>>>>>> .merge_file_lvPLfm
|
||||||
return EXTBAN_NOMATCH;
|
return EXTBAN_NOMATCH;
|
||||||
|
|
||||||
if (data != NULL)
|
if (data != NULL)
|
||||||
|
|
|
@ -197,9 +197,17 @@ mo_hurt(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parc == 3)
|
if (parc == 3)
|
||||||
expire = NULL, ip = parv[1], reason = parv[2];
|
{
|
||||||
|
expire = NULL;
|
||||||
|
ip = parv[1];
|
||||||
|
reason = parv[2];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
expire = parv[1], ip = parv[2], reason = parv[3];
|
{
|
||||||
|
expire = parv[1];
|
||||||
|
ip = parv[2];
|
||||||
|
reason = parv[3];
|
||||||
|
}
|
||||||
|
|
||||||
if (!expire)
|
if (!expire)
|
||||||
expire_time = HURT_DEFAULT_EXPIRE;
|
expire_time = HURT_DEFAULT_EXPIRE;
|
||||||
|
|
|
@ -76,7 +76,10 @@ static const char *expand_xline(const char *mask)
|
||||||
while (*p != '\0')
|
while (*p != '\0')
|
||||||
{
|
{
|
||||||
if (*p == ' ')
|
if (*p == ' ')
|
||||||
*q++ = '\\', *q++ = 's';
|
{
|
||||||
|
*q++ = '\\';
|
||||||
|
*q++ = 's';
|
||||||
|
}
|
||||||
else
|
else
|
||||||
*q++ = *p;
|
*q++ = *p;
|
||||||
p++;
|
p++;
|
||||||
|
|
|
@ -87,6 +87,8 @@ mr_webirc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
const char *encr;
|
const char *encr;
|
||||||
struct rb_sockaddr_storage addr;
|
struct rb_sockaddr_storage addr;
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_65X4Nj
|
||||||
|
=======
|
||||||
int secure = 0;
|
int secure = 0;
|
||||||
|
|
||||||
if (source_p->flags & FLAGS_SENTUSER || !EmptyString(source_p->name))
|
if (source_p->flags & FLAGS_SENTUSER || !EmptyString(source_p->name))
|
||||||
|
@ -94,6 +96,7 @@ mr_webirc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
exit_client(client_p, source_p, &me, "WEBIRC may not follow NICK/USER");
|
exit_client(client_p, source_p, &me, "WEBIRC may not follow NICK/USER");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
>>>>>>> .merge_file_ryG7XZ
|
||||||
aconf = find_address_conf(client_p->host, client_p->sockhost,
|
aconf = find_address_conf(client_p->host, client_p->sockhost,
|
||||||
IsGotId(client_p) ? client_p->username : "webirc",
|
IsGotId(client_p) ? client_p->username : "webirc",
|
||||||
IsGotId(client_p) ? client_p->username : "webirc",
|
IsGotId(client_p) ? client_p->username : "webirc",
|
||||||
|
@ -140,6 +143,8 @@ mr_webirc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
}
|
}
|
||||||
|
|
||||||
source_p->localClient->ip = addr;
|
source_p->localClient->ip = addr;
|
||||||
|
<<<<<<< .merge_file_65X4Nj
|
||||||
|
=======
|
||||||
source_p->username[0] = '\0';
|
source_p->username[0] = '\0';
|
||||||
ClearGotId(source_p);
|
ClearGotId(source_p);
|
||||||
|
|
||||||
|
@ -163,6 +168,7 @@ mr_webirc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
{
|
{
|
||||||
ClearSecure(source_p);
|
ClearSecure(source_p);
|
||||||
}
|
}
|
||||||
|
>>>>>>> .merge_file_ryG7XZ
|
||||||
|
|
||||||
rb_inet_ntop_sock((struct sockaddr *)&source_p->localClient->ip, source_p->sockhost, sizeof(source_p->sockhost));
|
rb_inet_ntop_sock((struct sockaddr *)&source_p->localClient->ip, source_p->sockhost, sizeof(source_p->sockhost));
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,10 @@ Unless noted below, all types can be used with +b, +q, +e and +I.
|
||||||
$a:<mask> - Matches users logged in with a username matching the mask
|
$a:<mask> - Matches users logged in with a username matching the mask
|
||||||
(* and ? wildcards)
|
(* and ? wildcards)
|
||||||
$c:<chan> - Matches users who are on the given channel
|
$c:<chan> - Matches users who are on the given channel
|
||||||
|
<<<<<<< .merge_file_IbT0MO
|
||||||
|
=======
|
||||||
$g:<mask> - Matches as a normal ban but excludes logged in users
|
$g:<mask> - Matches as a normal ban but excludes logged in users
|
||||||
|
>>>>>>> .merge_file_pGDMRH
|
||||||
$o - Matches opers (most useful with +I)
|
$o - Matches opers (most useful with +I)
|
||||||
$r:<mask> - Matches users with a realname (gecos) matching the mask
|
$r:<mask> - Matches users with a realname (gecos) matching the mask
|
||||||
(* and ? wildcards); this can only be used with +b and +q
|
(* and ? wildcards); this can only be used with +b and +q
|
||||||
|
@ -29,4 +32,5 @@ Unless noted below, all types can be used with +b, +q, +e and +I.
|
||||||
channel
|
channel
|
||||||
$x:<mask> - Bans all users with matching nick!user@host#gecos
|
$x:<mask> - Bans all users with matching nick!user@host#gecos
|
||||||
$z - Matches all SSL users
|
$z - Matches all SSL users
|
||||||
|
$z:<data> - Matches all SSL users with a fingerprint matching the data
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,10 @@ X f - Shows File Descriptors
|
||||||
* q - Shows temporary and global resv'd nicks and channels
|
* q - Shows temporary and global resv'd nicks and channels
|
||||||
* Q - Shows resv'd nicks and channels
|
* Q - Shows resv'd nicks and channels
|
||||||
* r - Shows resource usage by ircd
|
* r - Shows resource usage by ircd
|
||||||
|
<<<<<<< .merge_file_9l1jJa
|
||||||
|
=======
|
||||||
* s - Shows secure blocks
|
* s - Shows secure blocks
|
||||||
|
>>>>>>> .merge_file_OEoqTz
|
||||||
X S - Shows ssld processes
|
X S - Shows ssld processes
|
||||||
* t - Shows generic server stats
|
* t - Shows generic server stats
|
||||||
u - Shows server uptime
|
u - Shows server uptime
|
||||||
|
|
|
@ -99,10 +99,18 @@ extern int testing_conf;
|
||||||
|
|
||||||
extern struct ev_entry *check_splitmode_ev;
|
extern struct ev_entry *check_splitmode_ev;
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_iW7mBk
|
||||||
|
extern int ircd_ssl_ok;
|
||||||
|
extern int ircd_zlib_ok;
|
||||||
|
extern int maxconnections;
|
||||||
|
|
||||||
|
extern void rehash_ulimit();
|
||||||
|
=======
|
||||||
extern bool ircd_ssl_ok;
|
extern bool ircd_ssl_ok;
|
||||||
extern bool ircd_zlib_ok;
|
extern bool ircd_zlib_ok;
|
||||||
extern int maxconnections;
|
extern int maxconnections;
|
||||||
|
|
||||||
|
>>>>>>> .merge_file_fQC2Ek
|
||||||
void ircd_shutdown(const char *reason) __attribute__((noreturn));
|
void ircd_shutdown(const char *reason) __attribute__((noreturn));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,7 +37,11 @@ struct lgetopt
|
||||||
|
|
||||||
extern struct lgetopt myopts[];
|
extern struct lgetopt myopts[];
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_v0j8Uc
|
||||||
|
void parseargs(int *, char ***, struct lgetopt *);
|
||||||
|
=======
|
||||||
void usage(const char *) __attribute__((noreturn));
|
void usage(const char *) __attribute__((noreturn));
|
||||||
void parseargs(int *, char * const **, struct lgetopt *);
|
void parseargs(int *, char * const **, struct lgetopt *);
|
||||||
|
>>>>>>> .merge_file_OM6tzi
|
||||||
|
|
||||||
#endif /* __GETOPT_H_INCLUDED__ */
|
#endif /* __GETOPT_H_INCLUDED__ */
|
||||||
|
|
|
@ -39,7 +39,12 @@ extern void mod_add_cmd(struct Message *msg);
|
||||||
extern void mod_del_cmd(struct Message *msg);
|
extern void mod_del_cmd(struct Message *msg);
|
||||||
extern char *reconstruct_parv(int parc, const char *parv[]);
|
extern char *reconstruct_parv(int parc, const char *parv[]);
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_8Ju36V
|
||||||
|
extern struct Dictionary *alias_dict;
|
||||||
|
extern struct Dictionary *fakechannel_dict;
|
||||||
|
=======
|
||||||
extern rb_dictionary *alias_dict;
|
extern rb_dictionary *alias_dict;
|
||||||
extern rb_dictionary *cmd_dict;
|
extern rb_dictionary *cmd_dict;
|
||||||
|
>>>>>>> .merge_file_g15suK
|
||||||
|
|
||||||
#endif /* INCLUDED_parse_h_h */
|
#endif /* INCLUDED_parse_h_h */
|
||||||
|
|
|
@ -204,7 +204,11 @@ struct config_file_entry
|
||||||
int operspy_admin_only;
|
int operspy_admin_only;
|
||||||
int pace_wait;
|
int pace_wait;
|
||||||
int pace_wait_simple;
|
int pace_wait_simple;
|
||||||
|
<<<<<<< .merge_file_Ey8dam
|
||||||
|
int listfake_wait;
|
||||||
|
=======
|
||||||
int ping_warn_time;
|
int ping_warn_time;
|
||||||
|
>>>>>>> .merge_file_WzePKN
|
||||||
int short_motd;
|
int short_motd;
|
||||||
int no_oper_flood;
|
int no_oper_flood;
|
||||||
int hide_server;
|
int hide_server;
|
||||||
|
@ -340,6 +344,16 @@ struct alias_entry
|
||||||
int flags; /* reserved for later use */
|
int flags; /* reserved for later use */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fakechannel_entry
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
char *topic;
|
||||||
|
|
||||||
|
int users_min;
|
||||||
|
int users_max;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* All variables are GLOBAL */
|
/* All variables are GLOBAL */
|
||||||
extern struct config_file_entry ConfigFileEntry; /* defined in ircd.c */
|
extern struct config_file_entry ConfigFileEntry; /* defined in ircd.c */
|
||||||
extern struct config_channel_entry ConfigChannel; /* defined in channel.c */
|
extern struct config_channel_entry ConfigChannel; /* defined in channel.c */
|
||||||
|
|
|
@ -52,6 +52,7 @@ extern rb_dlink_list xline_conf_list;
|
||||||
extern rb_dlink_list resv_conf_list;
|
extern rb_dlink_list resv_conf_list;
|
||||||
extern rb_dlink_list nd_list;
|
extern rb_dlink_list nd_list;
|
||||||
extern rb_dlink_list tgchange_list;
|
extern rb_dlink_list tgchange_list;
|
||||||
|
extern rb_dlink_list vhost_conf_list;
|
||||||
|
|
||||||
extern struct _rb_patricia_tree_t *tgchange_tree;
|
extern struct _rb_patricia_tree_t *tgchange_tree;
|
||||||
|
|
||||||
|
@ -255,5 +256,16 @@ extern void add_nd_entry(const char *name);
|
||||||
extern void free_nd_entry(struct nd_entry *);
|
extern void free_nd_entry(struct nd_entry *);
|
||||||
extern unsigned long get_nd_count(void);
|
extern unsigned long get_nd_count(void);
|
||||||
|
|
||||||
#endif
|
struct vhost_conf
|
||||||
|
{
|
||||||
|
char *hostname;
|
||||||
|
char *ssl_private_key;
|
||||||
|
char *ssl_cert;
|
||||||
|
char *ssl_dh_params;
|
||||||
|
char *ssl_cipher_list;
|
||||||
|
rb_dlink_node node;
|
||||||
|
};
|
||||||
|
extern struct vhost_conf *make_vhost_conf(void);
|
||||||
|
extern void free_vhost_conf(struct vhost_conf *);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -25,7 +25,12 @@
|
||||||
#ifndef INCLUDED_s_user_h
|
#ifndef INCLUDED_s_user_h
|
||||||
#define INCLUDED_s_user_h
|
#define INCLUDED_s_user_h
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_TICs6q
|
||||||
|
#include "config.h"
|
||||||
|
#include "ircd_defs.h"
|
||||||
|
=======
|
||||||
#include "defaults.h"
|
#include "defaults.h"
|
||||||
|
>>>>>>> .merge_file_R44nIw
|
||||||
|
|
||||||
struct Client;
|
struct Client;
|
||||||
struct User;
|
struct User;
|
||||||
|
@ -45,7 +50,8 @@ extern void introduce_client(struct Client *client_p, struct Client *source_p,
|
||||||
struct User *user, const char *nick, int use_euid);
|
struct User *user, const char *nick, int use_euid);
|
||||||
|
|
||||||
extern void change_nick_user_host(struct Client *target_p, const char *nick, const char *user,
|
extern void change_nick_user_host(struct Client *target_p, const char *nick, const char *user,
|
||||||
const char *host, int newts, const char *format, ...);
|
const char *host, int newts, const char *format, ...)
|
||||||
|
AFP(6, 7);
|
||||||
|
|
||||||
extern int user_modes[256];
|
extern int user_modes[256];
|
||||||
extern unsigned int find_umode_slot(void);
|
extern unsigned int find_umode_slot(void);
|
||||||
|
|
|
@ -33,6 +33,17 @@ enum ssld_status {
|
||||||
|
|
||||||
void init_ssld(void);
|
void init_ssld(void);
|
||||||
void restart_ssld(void);
|
void restart_ssld(void);
|
||||||
|
<<<<<<< .merge_file_CConFf
|
||||||
|
int start_ssldaemon(int count, const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list);
|
||||||
|
ssl_ctl_t *start_ssld_accept(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
|
||||||
|
ssl_ctl_t *start_ssld_connect(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
|
||||||
|
void start_zlib_session(void *data);
|
||||||
|
void send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list, const int method, const char *hostname);
|
||||||
|
void send_remove_ssl_vhost(const char *hostname);
|
||||||
|
void ssld_decrement_clicount(ssl_ctl_t *ctl);
|
||||||
|
int get_ssld_count(void);
|
||||||
|
void ssld_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum ssld_status status), void *data);
|
||||||
|
=======
|
||||||
int start_ssldaemon(int count);
|
int start_ssldaemon(int count);
|
||||||
ssl_ctl_t *start_ssld_accept(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
|
ssl_ctl_t *start_ssld_accept(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
|
||||||
ssl_ctl_t *start_ssld_connect(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
|
ssl_ctl_t *start_ssld_connect(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
|
||||||
|
@ -41,6 +52,6 @@ void ssld_update_config(void);
|
||||||
void ssld_decrement_clicount(ssl_ctl_t *ctl);
|
void ssld_decrement_clicount(ssl_ctl_t *ctl);
|
||||||
int get_ssld_count(void);
|
int get_ssld_count(void);
|
||||||
void ssld_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum ssld_status status, const char *version), void *data);
|
void ssld_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum ssld_status status, const char *version), void *data);
|
||||||
|
>>>>>>> .merge_file_pjqFeX
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
886
libratbox/Makefile.in
Normal file
886
libratbox/Makefile.in
Normal file
|
@ -0,0 +1,886 @@
|
||||||
|
# Makefile.in generated by automake 1.15.1 from Makefile.am.
|
||||||
|
# @configure_input@
|
||||||
|
|
||||||
|
# Copyright (C) 1994-2017 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
@SET_MAKE@
|
||||||
|
|
||||||
|
VPATH = @srcdir@
|
||||||
|
am__is_gnu_make = { \
|
||||||
|
if test -z '$(MAKELEVEL)'; then \
|
||||||
|
false; \
|
||||||
|
elif test -n '$(MAKE_HOST)'; then \
|
||||||
|
true; \
|
||||||
|
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||||
|
true; \
|
||||||
|
else \
|
||||||
|
false; \
|
||||||
|
fi; \
|
||||||
|
}
|
||||||
|
am__make_running_with_option = \
|
||||||
|
case $${target_option-} in \
|
||||||
|
?) ;; \
|
||||||
|
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||||
|
"target option '$${target_option-}' specified" >&2; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
has_opt=no; \
|
||||||
|
sane_makeflags=$$MAKEFLAGS; \
|
||||||
|
if $(am__is_gnu_make); then \
|
||||||
|
sane_makeflags=$$MFLAGS; \
|
||||||
|
else \
|
||||||
|
case $$MAKEFLAGS in \
|
||||||
|
*\\[\ \ ]*) \
|
||||||
|
bs=\\; \
|
||||||
|
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||||
|
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||||
|
esac; \
|
||||||
|
fi; \
|
||||||
|
skip_next=no; \
|
||||||
|
strip_trailopt () \
|
||||||
|
{ \
|
||||||
|
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||||
|
}; \
|
||||||
|
for flg in $$sane_makeflags; do \
|
||||||
|
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||||
|
case $$flg in \
|
||||||
|
*=*|--*) continue;; \
|
||||||
|
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||||
|
-*I?*) strip_trailopt 'I';; \
|
||||||
|
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||||
|
-*O?*) strip_trailopt 'O';; \
|
||||||
|
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||||
|
-*l?*) strip_trailopt 'l';; \
|
||||||
|
-[dEDm]) skip_next=yes;; \
|
||||||
|
-[JT]) skip_next=yes;; \
|
||||||
|
esac; \
|
||||||
|
case $$flg in \
|
||||||
|
*$$target_option*) has_opt=yes; break;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
test $$has_opt = yes
|
||||||
|
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||||
|
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||||
|
pkgdatadir = $(datadir)/@PACKAGE@
|
||||||
|
pkgincludedir = $(includedir)/@PACKAGE@
|
||||||
|
pkglibdir = $(libdir)/@PACKAGE@
|
||||||
|
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||||
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||||
|
install_sh_DATA = $(install_sh) -c -m 644
|
||||||
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
|
transform = $(program_transform_name)
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
build_triplet = @build@
|
||||||
|
host_triplet = @host@
|
||||||
|
subdir = .
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
|
||||||
|
$(top_srcdir)/configure.ac
|
||||||
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
|
$(ACLOCAL_M4)
|
||||||
|
DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
|
||||||
|
$(am__configure_deps) $(am__DIST_COMMON)
|
||||||
|
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
|
||||||
|
configure.lineno config.status.lineno
|
||||||
|
mkinstalldirs = $(install_sh) -d
|
||||||
|
CONFIG_HEADER = $(top_builddir)/include/libratbox_config.h
|
||||||
|
CONFIG_CLEAN_FILES = libratbox.pc
|
||||||
|
CONFIG_CLEAN_VPATH_FILES =
|
||||||
|
AM_V_P = $(am__v_P_@AM_V@)
|
||||||
|
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||||
|
am__v_P_0 = false
|
||||||
|
am__v_P_1 = :
|
||||||
|
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||||
|
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||||
|
am__v_GEN_0 = @echo " GEN " $@;
|
||||||
|
am__v_GEN_1 =
|
||||||
|
AM_V_at = $(am__v_at_@AM_V@)
|
||||||
|
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||||
|
am__v_at_0 = @
|
||||||
|
am__v_at_1 =
|
||||||
|
SOURCES =
|
||||||
|
DIST_SOURCES =
|
||||||
|
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
|
||||||
|
ctags-recursive dvi-recursive html-recursive info-recursive \
|
||||||
|
install-data-recursive install-dvi-recursive \
|
||||||
|
install-exec-recursive install-html-recursive \
|
||||||
|
install-info-recursive install-pdf-recursive \
|
||||||
|
install-ps-recursive install-recursive installcheck-recursive \
|
||||||
|
installdirs-recursive pdf-recursive ps-recursive \
|
||||||
|
tags-recursive uninstall-recursive
|
||||||
|
am__can_run_installinfo = \
|
||||||
|
case $$AM_UPDATE_INFO_DIR in \
|
||||||
|
n|no|NO) false;; \
|
||||||
|
*) (install-info --version) >/dev/null 2>&1;; \
|
||||||
|
esac
|
||||||
|
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||||
|
am__vpath_adj = case $$p in \
|
||||||
|
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
*) f=$$p;; \
|
||||||
|
esac;
|
||||||
|
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||||
|
am__install_max = 40
|
||||||
|
am__nobase_strip_setup = \
|
||||||
|
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||||
|
am__nobase_strip = \
|
||||||
|
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||||
|
am__nobase_list = $(am__nobase_strip_setup); \
|
||||||
|
for p in $$list; do echo "$$p $$p"; done | \
|
||||||
|
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||||
|
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||||
|
if (++n[$$2] == $(am__install_max)) \
|
||||||
|
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||||
|
END { for (dir in files) print dir, files[dir] }'
|
||||||
|
am__base_list = \
|
||||||
|
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||||
|
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||||
|
am__uninstall_files_from_dir = { \
|
||||||
|
test -z "$$files" \
|
||||||
|
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||||
|
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||||
|
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||||
|
}
|
||||||
|
am__installdirs = "$(DESTDIR)$(pkgconfigdir)"
|
||||||
|
DATA = $(pkgconfig_DATA)
|
||||||
|
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
||||||
|
distclean-recursive maintainer-clean-recursive
|
||||||
|
am__recursive_targets = \
|
||||||
|
$(RECURSIVE_TARGETS) \
|
||||||
|
$(RECURSIVE_CLEAN_TARGETS) \
|
||||||
|
$(am__extra_recursive_targets)
|
||||||
|
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
|
||||||
|
cscope distdir dist dist-all distcheck
|
||||||
|
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||||
|
# Read a list of newline-separated strings from the standard input,
|
||||||
|
# and print each of them once, without duplicates. Input order is
|
||||||
|
# *not* preserved.
|
||||||
|
am__uniquify_input = $(AWK) '\
|
||||||
|
BEGIN { nonempty = 0; } \
|
||||||
|
{ items[$$0] = 1; nonempty = 1; } \
|
||||||
|
END { if (nonempty) { for (i in items) print i; }; } \
|
||||||
|
'
|
||||||
|
# Make sure the list of sources is unique. This is necessary because,
|
||||||
|
# e.g., the same source file might be shared among _SOURCES variables
|
||||||
|
# for different programs/libraries.
|
||||||
|
am__define_uniq_tagged_files = \
|
||||||
|
list='$(am__tagged_files)'; \
|
||||||
|
unique=`for i in $$list; do \
|
||||||
|
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||||
|
done | $(am__uniquify_input)`
|
||||||
|
ETAGS = etags
|
||||||
|
CTAGS = ctags
|
||||||
|
CSCOPE = cscope
|
||||||
|
DIST_SUBDIRS = $(SUBDIRS)
|
||||||
|
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/libratbox.pc.in \
|
||||||
|
$(top_srcdir)/include/libratbox_config.h.in COPYING ChangeLog \
|
||||||
|
INSTALL README TODO compile config.guess config.sub install-sh \
|
||||||
|
ltmain.sh missing
|
||||||
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
distdir = $(PACKAGE)-$(VERSION)
|
||||||
|
top_distdir = $(distdir)
|
||||||
|
am__remove_distdir = \
|
||||||
|
if test -d "$(distdir)"; then \
|
||||||
|
find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
|
||||||
|
&& rm -rf "$(distdir)" \
|
||||||
|
|| { sleep 5 && rm -rf "$(distdir)"; }; \
|
||||||
|
else :; fi
|
||||||
|
am__post_remove_distdir = $(am__remove_distdir)
|
||||||
|
am__relativize = \
|
||||||
|
dir0=`pwd`; \
|
||||||
|
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
|
||||||
|
sed_rest='s,^[^/]*/*,,'; \
|
||||||
|
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
|
||||||
|
sed_butlast='s,/*[^/]*$$,,'; \
|
||||||
|
while test -n "$$dir1"; do \
|
||||||
|
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
|
||||||
|
if test "$$first" != "."; then \
|
||||||
|
if test "$$first" = ".."; then \
|
||||||
|
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
|
||||||
|
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
|
||||||
|
else \
|
||||||
|
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
|
||||||
|
if test "$$first2" = "$$first"; then \
|
||||||
|
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
|
||||||
|
else \
|
||||||
|
dir2="../$$dir2"; \
|
||||||
|
fi; \
|
||||||
|
dir0="$$dir0"/"$$first"; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
|
||||||
|
done; \
|
||||||
|
reldir="$$dir2"
|
||||||
|
DIST_ARCHIVES = $(distdir).tar.gz
|
||||||
|
GZIP_ENV = --best
|
||||||
|
DIST_TARGETS = dist-gzip
|
||||||
|
distuninstallcheck_listfiles = find . -type f -print
|
||||||
|
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
|
||||||
|
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
|
||||||
|
distcleancheck_listfiles = find . -type f -print
|
||||||
|
ACLOCAL = @ACLOCAL@
|
||||||
|
ALLOCA = @ALLOCA@
|
||||||
|
AMTAR = @AMTAR@
|
||||||
|
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||||
|
AR = @AR@
|
||||||
|
AS = @AS@
|
||||||
|
AUTOCONF = @AUTOCONF@
|
||||||
|
AUTOHEADER = @AUTOHEADER@
|
||||||
|
AUTOMAKE = @AUTOMAKE@
|
||||||
|
AWK = @AWK@
|
||||||
|
CC = @CC@
|
||||||
|
CCDEPMODE = @CCDEPMODE@
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
CP = @CP@
|
||||||
|
CPP = @CPP@
|
||||||
|
CPPFLAGS = @CPPFLAGS@
|
||||||
|
CYGPATH_W = @CYGPATH_W@
|
||||||
|
DEFS = @DEFS@
|
||||||
|
DEPDIR = @DEPDIR@
|
||||||
|
DLLTOOL = @DLLTOOL@
|
||||||
|
DSYMUTIL = @DSYMUTIL@
|
||||||
|
DUMPBIN = @DUMPBIN@
|
||||||
|
ECHO_C = @ECHO_C@
|
||||||
|
ECHO_N = @ECHO_N@
|
||||||
|
ECHO_T = @ECHO_T@
|
||||||
|
EGREP = @EGREP@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
|
FGREP = @FGREP@
|
||||||
|
GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
|
||||||
|
GNUTLS_LIBS = @GNUTLS_LIBS@
|
||||||
|
GREP = @GREP@
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||||
|
LD = @LD@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
LIBOBJS = @LIBOBJS@
|
||||||
|
LIBS = @LIBS@
|
||||||
|
LIBTOOL = @LIBTOOL@
|
||||||
|
LIPO = @LIPO@
|
||||||
|
LN = @LN@
|
||||||
|
LN_S = @LN_S@
|
||||||
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
|
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||||
|
MAINT = @MAINT@
|
||||||
|
MAKEINFO = @MAKEINFO@
|
||||||
|
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||||
|
MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@
|
||||||
|
MBEDTLS_LIBS = @MBEDTLS_LIBS@
|
||||||
|
MKDIR_P = @MKDIR_P@
|
||||||
|
MV = @MV@
|
||||||
|
NM = @NM@
|
||||||
|
NMEDIT = @NMEDIT@
|
||||||
|
OBJDUMP = @OBJDUMP@
|
||||||
|
OBJEXT = @OBJEXT@
|
||||||
|
OTOOL = @OTOOL@
|
||||||
|
OTOOL64 = @OTOOL64@
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||||
|
PACKAGE_NAME = @PACKAGE_NAME@
|
||||||
|
PACKAGE_STRING = @PACKAGE_STRING@
|
||||||
|
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||||
|
PACKAGE_URL = @PACKAGE_URL@
|
||||||
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||||
|
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||||
|
PICFLAGS = @PICFLAGS@
|
||||||
|
PKG_CONFIG = @PKG_CONFIG@
|
||||||
|
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||||
|
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
RB_PREFIX = @RB_PREFIX@
|
||||||
|
RM = @RM@
|
||||||
|
SED = @SED@
|
||||||
|
SEDOBJ = @SEDOBJ@
|
||||||
|
SET_MAKE = @SET_MAKE@
|
||||||
|
SHELL = @SHELL@
|
||||||
|
SSL_CFLAGS = @SSL_CFLAGS@
|
||||||
|
SSL_LIBS = @SSL_LIBS@
|
||||||
|
STRIP = @STRIP@
|
||||||
|
TOUCH = @TOUCH@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
abs_builddir = @abs_builddir@
|
||||||
|
abs_srcdir = @abs_srcdir@
|
||||||
|
abs_top_builddir = @abs_top_builddir@
|
||||||
|
abs_top_srcdir = @abs_top_srcdir@
|
||||||
|
ac_ct_AR = @ac_ct_AR@
|
||||||
|
ac_ct_CC = @ac_ct_CC@
|
||||||
|
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||||
|
am__include = @am__include@
|
||||||
|
am__leading_dot = @am__leading_dot@
|
||||||
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
|
bindir = @bindir@
|
||||||
|
build = @build@
|
||||||
|
build_alias = @build_alias@
|
||||||
|
build_cpu = @build_cpu@
|
||||||
|
build_os = @build_os@
|
||||||
|
build_vendor = @build_vendor@
|
||||||
|
builddir = @builddir@
|
||||||
|
datadir = @datadir@
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
docdir = @docdir@
|
||||||
|
dvidir = @dvidir@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
host = @host@
|
||||||
|
host_alias = @host_alias@
|
||||||
|
host_cpu = @host_cpu@
|
||||||
|
host_os = @host_os@
|
||||||
|
host_vendor = @host_vendor@
|
||||||
|
htmldir = @htmldir@
|
||||||
|
includedir = @includedir@
|
||||||
|
infodir = @infodir@
|
||||||
|
install_sh = @install_sh@
|
||||||
|
libdir = @libdir@
|
||||||
|
libexecdir = @libexecdir@
|
||||||
|
localedir = @localedir@
|
||||||
|
localstatedir = @localstatedir@
|
||||||
|
mandir = @mandir@
|
||||||
|
mkdir_p = @mkdir_p@
|
||||||
|
oldincludedir = @oldincludedir@
|
||||||
|
pdfdir = @pdfdir@
|
||||||
|
prefix = @prefix@
|
||||||
|
program_transform_name = @program_transform_name@
|
||||||
|
psdir = @psdir@
|
||||||
|
runstatedir = @runstatedir@
|
||||||
|
sbindir = @sbindir@
|
||||||
|
sharedstatedir = @sharedstatedir@
|
||||||
|
srcdir = @srcdir@
|
||||||
|
sysconfdir = @sysconfdir@
|
||||||
|
target_alias = @target_alias@
|
||||||
|
top_build_prefix = @top_build_prefix@
|
||||||
|
top_builddir = @top_builddir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
AUTOMAKE_OPTIONS = foreign
|
||||||
|
SUBDIRS = src
|
||||||
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
|
pkgconfig_DATA = libratbox.pc
|
||||||
|
all: all-recursive
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
am--refresh: Makefile
|
||||||
|
@:
|
||||||
|
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||||
|
@for dep in $?; do \
|
||||||
|
case '$(am__configure_deps)' in \
|
||||||
|
*$$dep*) \
|
||||||
|
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
|
||||||
|
$(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
|
||||||
|
&& exit 0; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
|
||||||
|
$(am__cd) $(top_srcdir) && \
|
||||||
|
$(AUTOMAKE) --foreign Makefile
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
|
@case '$?' in \
|
||||||
|
*config.status*) \
|
||||||
|
echo ' $(SHELL) ./config.status'; \
|
||||||
|
$(SHELL) ./config.status;; \
|
||||||
|
*) \
|
||||||
|
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
|
||||||
|
esac;
|
||||||
|
|
||||||
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
|
$(SHELL) ./config.status --recheck
|
||||||
|
|
||||||
|
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||||
|
$(am__cd) $(srcdir) && $(AUTOCONF)
|
||||||
|
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||||
|
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
|
||||||
|
$(am__aclocal_m4_deps):
|
||||||
|
|
||||||
|
include/libratbox_config.h: include/stamp-h1
|
||||||
|
@test -f $@ || rm -f include/stamp-h1
|
||||||
|
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) include/stamp-h1
|
||||||
|
|
||||||
|
include/stamp-h1: $(top_srcdir)/include/libratbox_config.h.in $(top_builddir)/config.status
|
||||||
|
@rm -f include/stamp-h1
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status include/libratbox_config.h
|
||||||
|
$(top_srcdir)/include/libratbox_config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||||
|
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
|
||||||
|
rm -f include/stamp-h1
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
distclean-hdr:
|
||||||
|
-rm -f include/libratbox_config.h include/stamp-h1
|
||||||
|
libratbox.pc: $(top_builddir)/config.status $(srcdir)/libratbox.pc.in
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $@
|
||||||
|
|
||||||
|
mostlyclean-libtool:
|
||||||
|
-rm -f *.lo
|
||||||
|
|
||||||
|
clean-libtool:
|
||||||
|
-rm -rf .libs _libs
|
||||||
|
|
||||||
|
distclean-libtool:
|
||||||
|
-rm -f libtool config.lt
|
||||||
|
install-pkgconfigDATA: $(pkgconfig_DATA)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
|
||||||
|
if test -n "$$list"; then \
|
||||||
|
echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
|
||||||
|
$(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
|
||||||
|
fi; \
|
||||||
|
for p in $$list; do \
|
||||||
|
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||||
|
echo "$$d$$p"; \
|
||||||
|
done | $(am__base_list) | \
|
||||||
|
while read files; do \
|
||||||
|
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
|
||||||
|
$(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
|
||||||
|
done
|
||||||
|
|
||||||
|
uninstall-pkgconfigDATA:
|
||||||
|
@$(NORMAL_UNINSTALL)
|
||||||
|
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
|
||||||
|
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
|
||||||
|
dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
|
||||||
|
|
||||||
|
# This directory's subdirectories are mostly independent; you can cd
|
||||||
|
# into them and run 'make' without going through this Makefile.
|
||||||
|
# To change the values of 'make' variables: instead of editing Makefiles,
|
||||||
|
# (1) if the variable is set in 'config.status', edit 'config.status'
|
||||||
|
# (which will cause the Makefiles to be regenerated when you run 'make');
|
||||||
|
# (2) otherwise, pass the desired values on the 'make' command line.
|
||||||
|
$(am__recursive_targets):
|
||||||
|
@fail=; \
|
||||||
|
if $(am__make_keepgoing); then \
|
||||||
|
failcom='fail=yes'; \
|
||||||
|
else \
|
||||||
|
failcom='exit 1'; \
|
||||||
|
fi; \
|
||||||
|
dot_seen=no; \
|
||||||
|
target=`echo $@ | sed s/-recursive//`; \
|
||||||
|
case "$@" in \
|
||||||
|
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||||
|
*) list='$(SUBDIRS)' ;; \
|
||||||
|
esac; \
|
||||||
|
for subdir in $$list; do \
|
||||||
|
echo "Making $$target in $$subdir"; \
|
||||||
|
if test "$$subdir" = "."; then \
|
||||||
|
dot_seen=yes; \
|
||||||
|
local_target="$$target-am"; \
|
||||||
|
else \
|
||||||
|
local_target="$$target"; \
|
||||||
|
fi; \
|
||||||
|
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||||
|
|| eval $$failcom; \
|
||||||
|
done; \
|
||||||
|
if test "$$dot_seen" = "no"; then \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||||
|
fi; test -z "$$fail"
|
||||||
|
|
||||||
|
ID: $(am__tagged_files)
|
||||||
|
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||||
|
tags: tags-recursive
|
||||||
|
TAGS: tags
|
||||||
|
|
||||||
|
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||||
|
set x; \
|
||||||
|
here=`pwd`; \
|
||||||
|
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||||
|
include_option=--etags-include; \
|
||||||
|
empty_fix=.; \
|
||||||
|
else \
|
||||||
|
include_option=--include; \
|
||||||
|
empty_fix=; \
|
||||||
|
fi; \
|
||||||
|
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||||
|
if test "$$subdir" = .; then :; else \
|
||||||
|
test ! -f $$subdir/TAGS || \
|
||||||
|
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
$(am__define_uniq_tagged_files); \
|
||||||
|
shift; \
|
||||||
|
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||||
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
|
if test $$# -gt 0; then \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
"$$@" $$unique; \
|
||||||
|
else \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$unique; \
|
||||||
|
fi; \
|
||||||
|
fi
|
||||||
|
ctags: ctags-recursive
|
||||||
|
|
||||||
|
CTAGS: ctags
|
||||||
|
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||||
|
$(am__define_uniq_tagged_files); \
|
||||||
|
test -z "$(CTAGS_ARGS)$$unique" \
|
||||||
|
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||||
|
$$unique
|
||||||
|
|
||||||
|
GTAGS:
|
||||||
|
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||||
|
&& $(am__cd) $(top_srcdir) \
|
||||||
|
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||||
|
cscope: cscope.files
|
||||||
|
test ! -s cscope.files \
|
||||||
|
|| $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
|
||||||
|
clean-cscope:
|
||||||
|
-rm -f cscope.files
|
||||||
|
cscope.files: clean-cscope cscopelist
|
||||||
|
cscopelist: cscopelist-recursive
|
||||||
|
|
||||||
|
cscopelist-am: $(am__tagged_files)
|
||||||
|
list='$(am__tagged_files)'; \
|
||||||
|
case "$(srcdir)" in \
|
||||||
|
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||||
|
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||||
|
esac; \
|
||||||
|
for i in $$list; do \
|
||||||
|
if test -f "$$i"; then \
|
||||||
|
echo "$(subdir)/$$i"; \
|
||||||
|
else \
|
||||||
|
echo "$$sdir/$$i"; \
|
||||||
|
fi; \
|
||||||
|
done >> $(top_builddir)/cscope.files
|
||||||
|
|
||||||
|
distclean-tags:
|
||||||
|
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||||
|
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
$(am__remove_distdir)
|
||||||
|
test -d "$(distdir)" || mkdir "$(distdir)"
|
||||||
|
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
list='$(DISTFILES)'; \
|
||||||
|
dist_files=`for file in $$list; do echo $$file; done | \
|
||||||
|
sed -e "s|^$$srcdirstrip/||;t" \
|
||||||
|
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||||
|
case $$dist_files in \
|
||||||
|
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||||
|
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||||
|
sort -u` ;; \
|
||||||
|
esac; \
|
||||||
|
for file in $$dist_files; do \
|
||||||
|
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||||
|
if test -d "$(distdir)/$$file"; then \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||||
|
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
else \
|
||||||
|
test -f "$(distdir)/$$file" \
|
||||||
|
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||||
|
if test "$$subdir" = .; then :; else \
|
||||||
|
$(am__make_dryrun) \
|
||||||
|
|| test -d "$(distdir)/$$subdir" \
|
||||||
|
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|
||||||
|
|| exit 1; \
|
||||||
|
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
|
||||||
|
$(am__relativize); \
|
||||||
|
new_distdir=$$reldir; \
|
||||||
|
dir1=$$subdir; dir2="$(top_distdir)"; \
|
||||||
|
$(am__relativize); \
|
||||||
|
new_top_distdir=$$reldir; \
|
||||||
|
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
|
||||||
|
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
|
||||||
|
($(am__cd) $$subdir && \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) \
|
||||||
|
top_distdir="$$new_top_distdir" \
|
||||||
|
distdir="$$new_distdir" \
|
||||||
|
am__remove_distdir=: \
|
||||||
|
am__skip_length_check=: \
|
||||||
|
am__skip_mode_fix=: \
|
||||||
|
distdir) \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
-test -n "$(am__skip_mode_fix)" \
|
||||||
|
|| find "$(distdir)" -type d ! -perm -755 \
|
||||||
|
-exec chmod u+rwx,go+rx {} \; -o \
|
||||||
|
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
|
||||||
|
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
|
||||||
|
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||||
|
|| chmod -R a+r "$(distdir)"
|
||||||
|
dist-gzip: distdir
|
||||||
|
tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-bzip2: distdir
|
||||||
|
tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-lzip: distdir
|
||||||
|
tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-xz: distdir
|
||||||
|
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-tarZ: distdir
|
||||||
|
@echo WARNING: "Support for distribution archives compressed with" \
|
||||||
|
"legacy program 'compress' is deprecated." >&2
|
||||||
|
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||||
|
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-shar: distdir
|
||||||
|
@echo WARNING: "Support for shar distribution archives is" \
|
||||||
|
"deprecated." >&2
|
||||||
|
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||||
|
shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-zip: distdir
|
||||||
|
-rm -f $(distdir).zip
|
||||||
|
zip -rq $(distdir).zip $(distdir)
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist dist-all:
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
# This target untars the dist file and tries a VPATH configuration. Then
|
||||||
|
# it guarantees that the distribution is self-contained by making another
|
||||||
|
# tarfile.
|
||||||
|
distcheck: dist
|
||||||
|
case '$(DIST_ARCHIVES)' in \
|
||||||
|
*.tar.gz*) \
|
||||||
|
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
|
||||||
|
*.tar.bz2*) \
|
||||||
|
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||||
|
*.tar.lz*) \
|
||||||
|
lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
|
||||||
|
*.tar.xz*) \
|
||||||
|
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
|
||||||
|
*.tar.Z*) \
|
||||||
|
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||||
|
*.shar.gz*) \
|
||||||
|
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
|
||||||
|
*.zip*) \
|
||||||
|
unzip $(distdir).zip ;;\
|
||||||
|
esac
|
||||||
|
chmod -R a-w $(distdir)
|
||||||
|
chmod u+w $(distdir)
|
||||||
|
mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
|
||||||
|
chmod a-w $(distdir)
|
||||||
|
test -d $(distdir)/_build || exit 0; \
|
||||||
|
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
|
||||||
|
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
|
||||||
|
&& am__cwd=`pwd` \
|
||||||
|
&& $(am__cd) $(distdir)/_build/sub \
|
||||||
|
&& ../../configure \
|
||||||
|
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
|
||||||
|
$(DISTCHECK_CONFIGURE_FLAGS) \
|
||||||
|
--srcdir=../.. --prefix="$$dc_install_base" \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) check \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) install \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
|
||||||
|
distuninstallcheck \
|
||||||
|
&& chmod -R a-w "$$dc_install_base" \
|
||||||
|
&& ({ \
|
||||||
|
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
|
||||||
|
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
|
||||||
|
} || { rm -rf "$$dc_destdir"; exit 1; }) \
|
||||||
|
&& rm -rf "$$dc_destdir" \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) dist \
|
||||||
|
&& rm -rf $(DIST_ARCHIVES) \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
|
||||||
|
&& cd "$$am__cwd" \
|
||||||
|
|| exit 1
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
@(echo "$(distdir) archives ready for distribution: "; \
|
||||||
|
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
|
||||||
|
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
|
||||||
|
distuninstallcheck:
|
||||||
|
@test -n '$(distuninstallcheck_dir)' || { \
|
||||||
|
echo 'ERROR: trying to run $@ with an empty' \
|
||||||
|
'$$(distuninstallcheck_dir)' >&2; \
|
||||||
|
exit 1; \
|
||||||
|
}; \
|
||||||
|
$(am__cd) '$(distuninstallcheck_dir)' || { \
|
||||||
|
echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
|
||||||
|
exit 1; \
|
||||||
|
}; \
|
||||||
|
test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
|
||||||
|
|| { echo "ERROR: files left after uninstall:" ; \
|
||||||
|
if test -n "$(DESTDIR)"; then \
|
||||||
|
echo " (check DESTDIR support)"; \
|
||||||
|
fi ; \
|
||||||
|
$(distuninstallcheck_listfiles) ; \
|
||||||
|
exit 1; } >&2
|
||||||
|
distcleancheck: distclean
|
||||||
|
@if test '$(srcdir)' = . ; then \
|
||||||
|
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
|
||||||
|
exit 1 ; \
|
||||||
|
fi
|
||||||
|
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|
||||||
|
|| { echo "ERROR: files left in build directory after distclean:" ; \
|
||||||
|
$(distcleancheck_listfiles) ; \
|
||||||
|
exit 1; } >&2
|
||||||
|
check-am: all-am
|
||||||
|
check: check-recursive
|
||||||
|
all-am: Makefile $(DATA)
|
||||||
|
installdirs: installdirs-recursive
|
||||||
|
installdirs-am:
|
||||||
|
for dir in "$(DESTDIR)$(pkgconfigdir)"; do \
|
||||||
|
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||||
|
done
|
||||||
|
install: install-recursive
|
||||||
|
install-exec: install-exec-recursive
|
||||||
|
install-data: install-data-recursive
|
||||||
|
uninstall: uninstall-recursive
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
|
||||||
|
installcheck: installcheck-recursive
|
||||||
|
install-strip:
|
||||||
|
if test -z '$(STRIP)'; then \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
install; \
|
||||||
|
else \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||||
|
fi
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
clean: clean-recursive
|
||||||
|
|
||||||
|
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||||
|
|
||||||
|
distclean: distclean-recursive
|
||||||
|
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||||
|
-rm -f Makefile
|
||||||
|
distclean-am: clean-am distclean-generic distclean-hdr \
|
||||||
|
distclean-libtool distclean-tags
|
||||||
|
|
||||||
|
dvi: dvi-recursive
|
||||||
|
|
||||||
|
dvi-am:
|
||||||
|
|
||||||
|
html: html-recursive
|
||||||
|
|
||||||
|
html-am:
|
||||||
|
|
||||||
|
info: info-recursive
|
||||||
|
|
||||||
|
info-am:
|
||||||
|
|
||||||
|
install-data-am: install-pkgconfigDATA
|
||||||
|
|
||||||
|
install-dvi: install-dvi-recursive
|
||||||
|
|
||||||
|
install-dvi-am:
|
||||||
|
|
||||||
|
install-exec-am:
|
||||||
|
|
||||||
|
install-html: install-html-recursive
|
||||||
|
|
||||||
|
install-html-am:
|
||||||
|
|
||||||
|
install-info: install-info-recursive
|
||||||
|
|
||||||
|
install-info-am:
|
||||||
|
|
||||||
|
install-man:
|
||||||
|
|
||||||
|
install-pdf: install-pdf-recursive
|
||||||
|
|
||||||
|
install-pdf-am:
|
||||||
|
|
||||||
|
install-ps: install-ps-recursive
|
||||||
|
|
||||||
|
install-ps-am:
|
||||||
|
|
||||||
|
installcheck-am:
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-recursive
|
||||||
|
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||||
|
-rm -rf $(top_srcdir)/autom4te.cache
|
||||||
|
-rm -f Makefile
|
||||||
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-recursive
|
||||||
|
|
||||||
|
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||||
|
|
||||||
|
pdf: pdf-recursive
|
||||||
|
|
||||||
|
pdf-am:
|
||||||
|
|
||||||
|
ps: ps-recursive
|
||||||
|
|
||||||
|
ps-am:
|
||||||
|
|
||||||
|
uninstall-am: uninstall-pkgconfigDATA
|
||||||
|
|
||||||
|
.MAKE: $(am__recursive_targets) install-am install-strip
|
||||||
|
|
||||||
|
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
|
||||||
|
am--refresh check check-am clean clean-cscope clean-generic \
|
||||||
|
clean-libtool cscope cscopelist-am ctags ctags-am dist \
|
||||||
|
dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \
|
||||||
|
dist-xz dist-zip distcheck distclean distclean-generic \
|
||||||
|
distclean-hdr distclean-libtool distclean-tags distcleancheck \
|
||||||
|
distdir distuninstallcheck dvi dvi-am html html-am info \
|
||||||
|
info-am install install-am install-data install-data-am \
|
||||||
|
install-dvi install-dvi-am install-exec install-exec-am \
|
||||||
|
install-html install-html-am install-info install-info-am \
|
||||||
|
install-man install-pdf install-pdf-am install-pkgconfigDATA \
|
||||||
|
install-ps install-ps-am install-strip installcheck \
|
||||||
|
installcheck-am installdirs installdirs-am maintainer-clean \
|
||||||
|
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
||||||
|
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
|
||||||
|
uninstall-am uninstall-pkgconfigDATA
|
||||||
|
|
||||||
|
.PRECIOUS: Makefile
|
||||||
|
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
10541
libratbox/aclocal.m4
vendored
Normal file
10541
libratbox/aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load diff
1480
libratbox/config.guess
vendored
Executable file
1480
libratbox/config.guess
vendored
Executable file
File diff suppressed because it is too large
Load diff
1801
libratbox/config.sub
vendored
Executable file
1801
libratbox/config.sub
vendored
Executable file
File diff suppressed because it is too large
Load diff
17916
libratbox/configure
vendored
Executable file
17916
libratbox/configure
vendored
Executable file
File diff suppressed because it is too large
Load diff
698
libratbox/configure.ac
Normal file
698
libratbox/configure.ac
Normal file
|
@ -0,0 +1,698 @@
|
||||||
|
dnl $Id: configure.ac 26260 2008-12-10 04:08:39Z androsyn $
|
||||||
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
|
dnl TODO: clean up all the OpenSSL and shared module checking stuff;
|
||||||
|
dnl the most major changes have already been made and it looks like
|
||||||
|
dnl said functions need to be just about as complex as they already are.
|
||||||
|
|
||||||
|
AC_PREREQ(2.63)
|
||||||
|
AUTOMAKE_OPTIONS = 1.10
|
||||||
|
dnl Sneaky way to get an Id tag into the configure script
|
||||||
|
AC_COPYRIGHT([$Id: configure.ac 26260 2008-12-10 04:08:39Z androsyn $])
|
||||||
|
AC_INIT([libratbox],[devel])
|
||||||
|
AM_INIT_AUTOMAKE(AC_PACKAGE_TARNAME, AC_PACKAGE_VERSION, -)
|
||||||
|
|
||||||
|
AM_CONFIG_HEADER(include/libratbox_config.h)
|
||||||
|
|
||||||
|
AC_PREFIX_DEFAULT(/usr/local/libratbox)
|
||||||
|
AC_GNU_SOURCE
|
||||||
|
|
||||||
|
dnl Checks for programs.
|
||||||
|
AC_PROG_CC_C99
|
||||||
|
|
||||||
|
if test x"$ac_cv_prog_cc_c99" = "xno"; then
|
||||||
|
AC_ERROR([ircd-ratbox requires a C99 capable compiler])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PROG_EGREP
|
||||||
|
AC_PROG_SED
|
||||||
|
|
||||||
|
F77=no
|
||||||
|
CXX=no
|
||||||
|
GCJ=no
|
||||||
|
|
||||||
|
AM_DISABLE_STATIC
|
||||||
|
AM_ENABLE_SHARED
|
||||||
|
AM_MAINTAINER_MODE
|
||||||
|
|
||||||
|
AC_ISC_POSIX
|
||||||
|
AC_C_INLINE
|
||||||
|
AC_C_CONST
|
||||||
|
AC_C_BIGENDIAN
|
||||||
|
AC_PROG_MAKE_SET
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PATH_PROG(AUTOMAKE, automake)
|
||||||
|
AC_PATH_PROG(ACLOCAL, aclocal)
|
||||||
|
AC_PATH_PROG(AUTOHEADER, autoheader)
|
||||||
|
AC_PATH_PROG(AS, as)
|
||||||
|
AC_PATH_PROG(RM, rm)
|
||||||
|
AC_PATH_PROG(CP, cp)
|
||||||
|
AC_PATH_PROG(MV, mv)
|
||||||
|
AC_PATH_PROG(LN, ln)
|
||||||
|
AC_PATH_PROG(TOUCH, touch)
|
||||||
|
AC_LANG(C)
|
||||||
|
|
||||||
|
AC_PROG_LIBTOOL
|
||||||
|
|
||||||
|
LIBTOOL="$LIBTOOL --silent"
|
||||||
|
|
||||||
|
case "$host_os" in
|
||||||
|
*cygwin*)
|
||||||
|
AC_DEFINE_UNQUOTED(CYGWIN,1,[This is a Cygwin system])
|
||||||
|
AC_DEFINE_UNQUOTED(WINDOWS,1,[This is a Windows system])
|
||||||
|
;;
|
||||||
|
*mingw*)
|
||||||
|
AC_DEFINE_UNQUOTED(MINGW,1,[This is a MinGW system])
|
||||||
|
AC_DEFINE_UNQUOTED(WINDOWS,1,[This is a Windows system])
|
||||||
|
AC_CHECK_HEADER(windows.h, , [AC_MSG_ERROR([** MinGW and no windows.h. I give up.])])
|
||||||
|
AC_CHECK_HEADER(winsock2.h, , [AC_MSG_ERROR([** MinGW and no winsock2.h. I give up.])])
|
||||||
|
AC_DEFINE_UNQUOTED(HAVE_WINSOCK2_H, 1, [Have WINSOCK2_H])
|
||||||
|
AC_DEFINE_UNQUOTED(HAVE_WINSOCK_H, 1, [Have WINSOCK_H])
|
||||||
|
LIBS="$LIBS -lws2_32 -liphlpapi"
|
||||||
|
is_mingw="yes"
|
||||||
|
;;
|
||||||
|
*interix*)
|
||||||
|
CPPFLAGS="$CFLAGS -D_ALL_SOURCE -D_XOPEN_SOURCE=500"
|
||||||
|
;;
|
||||||
|
*solaris*)
|
||||||
|
CPPFLAGS="$CFLAGS -D_POSIX_PTHREAD_SEMANTICS -D_XPG4_2"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
AM_CONDITIONAL([MINGW], [test "$is_mingw" = "yes"])
|
||||||
|
|
||||||
|
|
||||||
|
# backwards support for IRC_CFLAGS
|
||||||
|
CFLAGS="$IRC_CFLAGS $CFLAGS -Wall"
|
||||||
|
|
||||||
|
dnl use directory structure of cached as default (hack)
|
||||||
|
if test "$libexecdir" = '${exec_prefix}/libexec' &&
|
||||||
|
test "$localstatedir" = '${prefix}/var'; then
|
||||||
|
libexecdir='${bindir}'
|
||||||
|
localstatedir='${prefix}'
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_TYPE_PID_T
|
||||||
|
AC_TYPE_SIZE_T
|
||||||
|
AC_TYPE_SSIZE_T
|
||||||
|
AC_TYPE_UID_T
|
||||||
|
|
||||||
|
|
||||||
|
dnl Checks for header files.
|
||||||
|
AC_HEADER_STDC
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS([crypt.h unistd.h sys/socket.h sys/stat.h sys/time.h time.h netinet/in.h arpa/inet.h errno.h sys/uio.h spawn.h sys/poll.h sys/epoll.h sys/select.h sys/devpoll.h sys/event.h port.h signal.h sys/signalfd.h sys/timerfd.h linux/tcp.h])
|
||||||
|
AC_HEADER_TIME
|
||||||
|
|
||||||
|
dnl Networking Functions
|
||||||
|
dnl ====================
|
||||||
|
|
||||||
|
AC_SEARCH_LIBS(socket, [socket],,)
|
||||||
|
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([struct sockaddr.sa_len], [AC_DEFINE(SOCKADDR_IN_HAS_LEN, 1, [Define to 1 if sockaddr has a 'sa_len'
|
||||||
|
member.])],,[[
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_WINSOCK2_H
|
||||||
|
#include <winsock2.h>
|
||||||
|
#endif
|
||||||
|
]])
|
||||||
|
|
||||||
|
AC_CHECK_TYPE([socklen_t], rb_cv_socklen_t=socklen_t,[
|
||||||
|
AC_MSG_CHECKING([for socklen_t equivalent])
|
||||||
|
AC_CACHE_VAL([rb_cv_socklen_t],
|
||||||
|
[
|
||||||
|
# Systems have either "struct sockaddr *" or
|
||||||
|
# "void *" as the second argument to getpeername
|
||||||
|
rb_cv_socklen_t=
|
||||||
|
for arg2 in "struct sockaddr" void; do
|
||||||
|
for t in int size_t unsigned long "unsigned long"; do
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_WINSOCK2_H
|
||||||
|
#include <winsock2.h>
|
||||||
|
#endif
|
||||||
|
int getpeername (int, $arg2 *, $t *);
|
||||||
|
],[
|
||||||
|
$t len;
|
||||||
|
getpeername(0,0,&len);
|
||||||
|
],[
|
||||||
|
rb_cv_socklen_t="$t"
|
||||||
|
break
|
||||||
|
])
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
if test "x$rb_cv_socklen_t" = x; then
|
||||||
|
AC_MSG_WARN([Cannot find a type to use in place of socklen_t using int])
|
||||||
|
rb_cv_socklen_t=int
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
AC_MSG_RESULT($rb_cv_socklen_t)],
|
||||||
|
[#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>])
|
||||||
|
|
||||||
|
rb_socklen_t=$rb_cv_socklen_t
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(ipv6,AC_HELP_STRING([--disable-ipv6],[Disable IPv6 support]),[ipv6=$enableval],[ipv6=yes])
|
||||||
|
|
||||||
|
if test x$ipv6 != xyes; then
|
||||||
|
have_v6="no"
|
||||||
|
else
|
||||||
|
|
||||||
|
have_v6=yes
|
||||||
|
RB_PROTO_INET6([], [
|
||||||
|
AC_MSG_NOTICE([Disabling IPv6 support: PF_INET6 not found])
|
||||||
|
have_v6=no
|
||||||
|
])
|
||||||
|
|
||||||
|
if test "X$have_v6" = "Xyes"; then
|
||||||
|
RB_TYPE_STRUCT_SOCKADDR_IN6([], [
|
||||||
|
AC_MSG_NOTICE([Disabling IPv6 support: struct sockaddr_in6 not found])
|
||||||
|
have_v6=no
|
||||||
|
])
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CHECK_TYPES([struct sockaddr_storage],[
|
||||||
|
rb_have_sockaddr_storage=yes
|
||||||
|
],[], [
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Check for stdarg.h - if we cant find it, halt configure
|
||||||
|
AC_CHECK_HEADER(stdarg.h, , [AC_MSG_ERROR([** stdarg.h could not be found - libratbox will not compile without it **])])
|
||||||
|
|
||||||
|
AC_CHECK_TYPE([sa_family_t], [],
|
||||||
|
[AC_DEFINE(sa_family_t, [u_int16_t], [If system does not define sa_family_t, define it here.])],
|
||||||
|
[[#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>]])
|
||||||
|
|
||||||
|
|
||||||
|
dnl check for various functions...
|
||||||
|
AC_CHECK_FUNCS([socketpair gettimeofday writev sendmsg gmtime_r strtok_r usleep posix_spawn strlcpy strlcat strnlen fstat signalfd select poll kevent port_create epoll_ctl arc4random getrusage timerfd_create])
|
||||||
|
|
||||||
|
AC_SEARCH_LIBS(nanosleep, rt posix4, AC_DEFINE(HAVE_NANOSLEEP, 1, [Define if you have nanosleep]))
|
||||||
|
AC_SEARCH_LIBS(timer_create, rt, AC_DEFINE(HAVE_TIMER_CREATE, 1, [Define if you have timer_create]))
|
||||||
|
RB_CHECK_TIMER_CREATE
|
||||||
|
RB_CHECK_TIMERFD_CREATE
|
||||||
|
|
||||||
|
AC_FUNC_ALLOCA
|
||||||
|
AC_FUNC_VFORK
|
||||||
|
AC_FUNC_MMAP
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(for /dev/poll)
|
||||||
|
if test -c "/dev/poll"; then
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
AC_DEFINE(HAVE_DEVPOLL, [1], [Define to 1 if you have devpoll])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if test "$is_mingw" = "yes"; then
|
||||||
|
AC_DEFINE(HAVE_WIN32, [1], [Define to 1 if you are on windows])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
dnl OpenSSL support
|
||||||
|
AC_MSG_CHECKING(for OpenSSL)
|
||||||
|
AC_ARG_ENABLE(openssl,
|
||||||
|
[AC_HELP_STRING([--enable-openssl[=DIR]],[Enable OpenSSL support (DIR optional).])
|
||||||
|
AC_HELP_STRING([--disable-openssl],[Disable OpenSSL support.])],
|
||||||
|
[cf_enable_openssl=$enableval],
|
||||||
|
[cf_enable_openssl="auto"])
|
||||||
|
|
||||||
|
if test "$cf_enable_openssl" != "no" ; then
|
||||||
|
cf_openssl_basedir=""
|
||||||
|
if test "$cf_enable_openssl" != "auto" &&
|
||||||
|
test "$cf_enable_openssl" != "yes" ; then
|
||||||
|
dnl Support for --enable-openssl=/some/place
|
||||||
|
cf_openssl_basedir="`echo ${cf_enable_openssl} | sed 's/\/$//'`"
|
||||||
|
else
|
||||||
|
dnl Do the auto-probe here. Check some common directory paths.
|
||||||
|
for dirs in /usr/local/ssl /usr/pkg /usr/local \
|
||||||
|
/usr/local/openssl ; do
|
||||||
|
if test -f "${dirs}/include/openssl/opensslv.h" ; then
|
||||||
|
cf_openssl_basedir="${dirs}"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
unset dirs
|
||||||
|
fi
|
||||||
|
dnl Now check cf_openssl_found to see if we found anything.
|
||||||
|
if test ! -z "$cf_openssl_basedir"; then
|
||||||
|
if test -f "${cf_openssl_basedir}/include/openssl/opensslv.h" ; then
|
||||||
|
SSL_CFLAGS="-I${cf_openssl_basedir}/include"
|
||||||
|
SSL_LIBS="-L${cf_openssl_basedir}/lib"
|
||||||
|
else
|
||||||
|
dnl OpenSSL wasn't found in the directory specified. Naughty
|
||||||
|
dnl administrator...
|
||||||
|
cf_openssl_basedir=""
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
dnl Check for stock FreeBSD 4.x and 5.x systems, since their files
|
||||||
|
dnl are in /usr/include and /usr/lib. In this case, we don't want to
|
||||||
|
dnl change INCLUDES or LIBS, but still want to enable OpenSSL.
|
||||||
|
dnl We can't do this check above, because some people want two versions
|
||||||
|
dnl of OpenSSL installed (stock FreeBSD 4.x/5.x and /usr/local/ssl)
|
||||||
|
dnl and they want /usr/local/ssl to have preference.
|
||||||
|
if test -f "/usr/include/openssl/opensslv.h" ; then
|
||||||
|
cf_openssl_basedir="/usr"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl If we have a basedir defined, then everything is okay. Otherwise,
|
||||||
|
dnl we have a problem.
|
||||||
|
if test ! -z "$cf_openssl_basedir"; then
|
||||||
|
AC_MSG_RESULT($cf_openssl_basedir)
|
||||||
|
cf_enable_openssl="yes"
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([not found. Specify a correct path?])
|
||||||
|
cf_enable_openssl="no"
|
||||||
|
fi
|
||||||
|
unset cf_openssl_basedir
|
||||||
|
else
|
||||||
|
dnl If --disable-openssl was specified
|
||||||
|
AC_MSG_RESULT(disabled)
|
||||||
|
fi
|
||||||
|
|
||||||
|
save_CPPFLAGS="$CPPFLAGS"
|
||||||
|
CPPFLAGS="$CPPFLAGS $SSL_CFLAGS"
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS $SSL_LIBS"
|
||||||
|
if test "$cf_enable_openssl" != no; then
|
||||||
|
dnl Check OpenSSL version (must be 0.9.7 or above!)
|
||||||
|
AC_MSG_CHECKING(for OpenSSL 0.9.7 or above)
|
||||||
|
AC_RUN_IFELSE(
|
||||||
|
AC_LANG_PROGRAM(
|
||||||
|
[#include <openssl/opensslv.h>
|
||||||
|
#include <stdlib.h>],
|
||||||
|
[[if (OPENSSL_VERSION_NUMBER >= 0x00907000)
|
||||||
|
exit(0); else exit(1);]]),
|
||||||
|
cf_enable_openssl=yes,
|
||||||
|
cf_enable_openssl=no,
|
||||||
|
cf_enable_openssl=no)
|
||||||
|
|
||||||
|
if test "$cf_enable_openssl" != no; then
|
||||||
|
AC_MSG_RESULT(found)
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT(no - OpenSSL support disabled)
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if test "$cf_enable_openssl" != no; then
|
||||||
|
CPPFLAGS="$CPPFLAGS $SSL_LIBS"
|
||||||
|
AC_CHECK_LIB(crypto, RAND_status,
|
||||||
|
[cf_enable_openssl=yes],
|
||||||
|
[cf_enable_openssl=no])
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$cf_enable_openssl" != no; then
|
||||||
|
CPPFLAGS="$CPPFLAGS $SSL_LIBS"
|
||||||
|
AC_CHECK_LIB(ssl, SSL_read,
|
||||||
|
[SSL_LIBS="$SSL_LIBS -lssl -lcrypto"],
|
||||||
|
[cf_enable_openssl=no], [-lcrypto])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
dnl mbedTLS support
|
||||||
|
AC_ARG_ENABLE(mbedtls,
|
||||||
|
[AC_HELP_STRING([--enable-mbedtls], [Enable mbedTLS support.])
|
||||||
|
AC_HELP_STRING([--disable-mbedtls], [Disable mbedTLS support.])],
|
||||||
|
[cf_enable_mbedtls=$enableval],
|
||||||
|
[cf_enable_mbedtls="auto"])
|
||||||
|
|
||||||
|
if test "$cf_enable_mbedtls" != no; then
|
||||||
|
save_CPPFLAGS="$CPPFLAGS"
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS $MBEDTLS_LIBS"
|
||||||
|
AC_CHECK_LIB(mbedtls, mbedtls_ssl_init, [
|
||||||
|
MBEDTLS_LIBS="$MBEDTLS_LIBS -lmbedtls -lmbedx509 -lmbedcrypto"
|
||||||
|
cf_enable_mbedtls=yes
|
||||||
|
], [cf_enable_mbedtls=no], [-lmbedx509 -lmbedcrypto])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl GnuTLS support
|
||||||
|
AC_MSG_CHECKING(for GnuTLS)
|
||||||
|
AC_ARG_ENABLE(gnutls,
|
||||||
|
[AC_HELP_STRING([--enable-gnutls],[Enable GnuTLS support.])
|
||||||
|
AC_HELP_STRING([--disable-gnutls],[Disable GnuTLS support.])],
|
||||||
|
[cf_enable_gnutls=$enableval],
|
||||||
|
[cf_enable_gnutls="auto"])
|
||||||
|
|
||||||
|
if test "$cf_enable_gnutls" != no; then
|
||||||
|
PKG_CHECK_MODULES(GNUTLS, [gnutls], [
|
||||||
|
cf_enable_gnutls="yes"
|
||||||
|
], [cf_enable_gnutls="no"])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl mbed TLS is given highest preference when no specified TLS library is provided
|
||||||
|
if test "$cf_enable_openssl" = "auto" -a "$cf_enable_mbedtls" = "yes"; then
|
||||||
|
cf_enable_openssl="no"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$cf_enable_gnutls" = "auto" -a "$cf_enable_openssl" = "yes" -a "$cf_enable_mbedtls" = "yes"; then
|
||||||
|
cf_enable_gnutls="no"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x"$cf_enable_openssl" != xno; then
|
||||||
|
AC_DEFINE(HAVE_OPENSSL,1,[Has OpenSSL])
|
||||||
|
GNUTLS_CFLAGS=""
|
||||||
|
GNUTLS_LIBS=""
|
||||||
|
MBEDTLS_LIBS=""
|
||||||
|
MBEDTLS_CFLAGS=""
|
||||||
|
SSL_TYPE="openssl"
|
||||||
|
elif test x"$cf_enable_mbedtls" != xno; then
|
||||||
|
AC_DEFINE(HAVE_MBEDTLS, 1, [Has mbedTLS])
|
||||||
|
SSL_LIBS=""
|
||||||
|
SSL_CFLAGS=""
|
||||||
|
GNUTLS_CFLAGS=""
|
||||||
|
GNUTLS_LIBS=""
|
||||||
|
SSL_TYPE="mbedtls"
|
||||||
|
elif test x"$cf_enable_gnutls" != xno; then
|
||||||
|
AC_DEFINE(HAVE_GNUTLS, 1, [Has GnuTLS])
|
||||||
|
SSL_LIBS=""
|
||||||
|
SSL_CFLAGS=""
|
||||||
|
MBEDTLS_LIBS=""
|
||||||
|
MBEDTLS_CFLAGS=""
|
||||||
|
SSL_TYPE="gnutls"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CPPFLAGS="$save_CPPFLAGS"
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
|
||||||
|
dnl End OpenSSL detection
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
dnl Debug-related options
|
||||||
|
dnl =====================
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(assert,
|
||||||
|
AC_HELP_STRING([--enable-assert],[Enable assert(). Choose between soft(warnings) and hard(aborts the daemon)]),
|
||||||
|
[assert=$enableval], [assert=no])
|
||||||
|
|
||||||
|
if test "$assert" = no; then
|
||||||
|
AC_DEFINE(NDEBUG, 1, [Define this to disable debugging support.])
|
||||||
|
elif test "$assert" = soft; then
|
||||||
|
AC_DEFINE(SOFT_ASSERT, 1, [Define this to enable soft asserts.])
|
||||||
|
AC_DEFINE(NDEBUG, 1, [Define this to disable debugging support.])
|
||||||
|
elif test "$assert" = yes; then
|
||||||
|
assert = "hard";
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(if you want to do a profile build)
|
||||||
|
AC_ARG_ENABLE(profile,
|
||||||
|
AC_HELP_STRING([--enable-profile],[Enable profiling]),
|
||||||
|
[profile=$enableval], [profile=no])
|
||||||
|
|
||||||
|
if test "$profile" = yes; then
|
||||||
|
if test "$ac_cv_c_compiler_gnu" = yes; then
|
||||||
|
CFLAGS="$CFLAGS -pg -static"
|
||||||
|
AC_MSG_RESULT([yes, adding -pg -static])
|
||||||
|
AC_DEFINE(RATBOX_PROFILE, 1, [Defined to mark profiling is enabled])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([no, profile builds only work with gcc])
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(balloc,
|
||||||
|
AC_HELP_STRING([--disable-balloc],[Disable the block allocator.]),
|
||||||
|
[balloc=$enableval], [balloc=yes])
|
||||||
|
|
||||||
|
if test "$balloc" = no; then
|
||||||
|
AC_DEFINE([NOBALLOC], 1, [Define to 1 if you wish to disable the block allocator.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(warnings,
|
||||||
|
AC_HELP_STRING([--enable-warnings],[Enable all sorts of warnings for debugging.]),
|
||||||
|
[CFLAGS="$CFLAGS -Wall -Werror -Wcast-qual -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wshadow -Wwrite-strings -W -Wno-unused -Wunused-function -Wunused-variable"],[])
|
||||||
|
|
||||||
|
AC_SUBST(LDFLAGS)
|
||||||
|
AC_SUBST(PICFLAGS)
|
||||||
|
AC_SUBST(CFLAGS)
|
||||||
|
AC_SUBST(SEDOBJ)
|
||||||
|
AC_SUBST(SSL_CFLAGS)
|
||||||
|
AC_SUBST(SSL_LIBS)
|
||||||
|
AC_SUBST(GNUTLS_CFLAGS)
|
||||||
|
AC_SUBST(GNUTLS_LIBS)
|
||||||
|
AC_SUBST(MBEDTLS_CFLAGS)
|
||||||
|
AC_SUBST(MBEDTLS_LIBS)
|
||||||
|
|
||||||
|
if test "$prefix" = "NONE"; then
|
||||||
|
AC_DEFINE_UNQUOTED(RB_PREFIX, "$ac_default_prefix", [Prefix where libratbox is installed.])
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
dnl Don't get bitten by Cygwin's stupidity if the user specified
|
||||||
|
dnl a custom prefix with a trailing slash
|
||||||
|
|
||||||
|
prefix=`echo $prefix | sed 's/\/$//'`
|
||||||
|
AC_DEFINE_UNQUOTED(RB_PREFIX, "$prefix", [Prefix where libratbox is installed.])
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST(RB_PREFIX)
|
||||||
|
|
||||||
|
AC_CONFIG_COMMANDS([include/librb-config.h],
|
||||||
|
[
|
||||||
|
outfile=include/librb-config.h.tmp
|
||||||
|
cat > $outfile <<\_______EOF
|
||||||
|
/*
|
||||||
|
* librb-config.h: libratbox config file. Please modify configure.ac
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBRB_CONFIG_H
|
||||||
|
#define __LIBRB_CONFIG_H
|
||||||
|
|
||||||
|
_______EOF
|
||||||
|
|
||||||
|
if test "x$rb_have_ipv6" = "xyes"; then
|
||||||
|
echo "#define RB_IPV6 1" >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_windows_h" = "xyes"; then
|
||||||
|
echo '#define WIN32_LEAN_AND_MEAN 1' >> $outfile
|
||||||
|
echo '#include <windows.h>' >> $outfile
|
||||||
|
echo '#include <winsock2.h>' >> $outfile
|
||||||
|
echo '#include <iphlpapi.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_alloca_h" = "xyes"; then
|
||||||
|
echo '#define RB_HAVE_ALLOCA_H 1' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_header_stdc" = "xyes"; then
|
||||||
|
echo '#include <stdlib.h>' >> $outfile
|
||||||
|
echo '#include <stddef.h>' >> $outfile
|
||||||
|
elif test "x$rb_header_stdlib" = "xyes"; then
|
||||||
|
echo '#include <stdlib.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_header_string_h" = "xyes"; then
|
||||||
|
echo '#include <string.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_stdint_h" = "xyes"; then
|
||||||
|
echo '#include <stdint.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_inttypes_h" = "xyes"; then
|
||||||
|
echo '#include <inttypes.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_sys_types_h" = "xyes"; then
|
||||||
|
echo '#include <sys/types.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
if test "x$rb_sys_time_h" = "xyes"; then
|
||||||
|
echo '#include <sys/time.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
if test "x$rb_sys_stat_h" = "xyes"; then
|
||||||
|
echo '#include <sys/stat.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
if test "x$rb_time_h" = "xyes"; then
|
||||||
|
echo '#include <time.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_sys_socket_h" = "xyes"; then
|
||||||
|
echo '#include <sys/socket.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_netinet_in_h" = "xyes"; then
|
||||||
|
echo '#include <netinet/in.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_arpa_inet_h" = "xyes"; then
|
||||||
|
echo '#include <arpa/inet.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_unistd_h" = "xyes"; then
|
||||||
|
echo '#include <unistd.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_crypt_h" = "xyes"; then
|
||||||
|
echo '#include <crypt.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_errno_h" = "xyes"; then
|
||||||
|
echo '#include <errno.h>' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "typedef $rb_socklen_t rb_socklen_t;" >> $outfile
|
||||||
|
|
||||||
|
|
||||||
|
if test "x$rb_sockaddr_sa_len" = "xyes"; then
|
||||||
|
echo '#define RB_SOCKADDR_HAS_SA_LEN 1' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$rb_sockaddr_storage" = "xyes"; then
|
||||||
|
echo '#define rb_sockaddr_storage sockaddr_storage' >> $outfile
|
||||||
|
else
|
||||||
|
echo 'struct rb_sockaddr_storage { uint8_t _padding[[128]]; };' >> $outfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat >> $outfile <<\_______EOF
|
||||||
|
#endif /* __LIBRB_CONFIG_H */
|
||||||
|
_______EOF
|
||||||
|
|
||||||
|
if cmp -s $outfile include/librb-config.h; then
|
||||||
|
AC_MSG_NOTICE([include/librb-config.h is unchanged])
|
||||||
|
${rb_rm} -f $outfile
|
||||||
|
else
|
||||||
|
${rb_mv} $outfile include/librb-config.h
|
||||||
|
fi
|
||||||
|
|
||||||
|
],[
|
||||||
|
if test x$ac_cv_header_stdc = xyes; then
|
||||||
|
rb_header_stdc=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_stdlib_h = xyes; then
|
||||||
|
rb_header_stdlib_h=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_string_h = xyes; then
|
||||||
|
rb_header_string_h=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_memory_h = xyes; then
|
||||||
|
rb_header_memory_h=yes
|
||||||
|
fi
|
||||||
|
if test "x${ac_cv_working_alloca_h+set}" = xset ; then
|
||||||
|
rb_alloca_h="$ac_cv_working_alloca_h"
|
||||||
|
else
|
||||||
|
rb_alloc_h="$ac_cv_header_alloca_h"
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_member_struct_sockaddr_sa_len = xyes; then
|
||||||
|
rb_sockaddr_sa_len=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_sys_socket_h = xyes; then
|
||||||
|
rb_sys_socket_h=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_sys_types_h = xyes; then
|
||||||
|
rb_sys_types_h=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_sys_stat_h = xyes; then
|
||||||
|
rb_sys_stat_h=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_sys_time_h = xyes; then
|
||||||
|
rb_sys_time_h=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_time = xyes; then
|
||||||
|
rb_time_h=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x$ac_cv_header_stdint_h = xyes; then
|
||||||
|
rb_stdint_h=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_inttypes_h = xyes; then
|
||||||
|
rb_inttypes_h=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_netinet_in_h = xyes; then
|
||||||
|
rb_netinet_in_h=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x$ac_cv_header_crypt_h = xyes; then
|
||||||
|
rb_crypt_h=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_errno_h = xyes; then
|
||||||
|
rb_errno_h=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_unistd_h = xyes; then
|
||||||
|
rb_unistd_h=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_windows_h = xyes; then
|
||||||
|
rb_windows_h=yes
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_winsock2_h = xyes; then
|
||||||
|
rb_winsock2_h=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
rb_socklen_t=$rb_socklen_t
|
||||||
|
|
||||||
|
if test "x$rb_have_sockaddr_storage" = "xyes"; then
|
||||||
|
rb_sockaddr_storage="yes"
|
||||||
|
else
|
||||||
|
rb_sockaddr_storage="no"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rb_have_ipv6="$have_v6"
|
||||||
|
|
||||||
|
rb_mv="$MV"
|
||||||
|
rb_rm="$RM"
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
AC_CONFIG_FILES( \
|
||||||
|
src/Makefile \
|
||||||
|
Makefile \
|
||||||
|
libratbox.pc
|
||||||
|
)
|
||||||
|
|
||||||
|
AC_OUTPUT
|
||||||
|
|
||||||
|
dnl Make it look sexay!
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Compiling $PACKAGE_NAME $PACKAGE_VERSION"
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "Installing into: $prefix"
|
||||||
|
|
||||||
|
echo "IPv6 support ................... $have_v6"
|
||||||
|
echo "Assert debugging ............... $assert"
|
||||||
|
echo "Block allocator ................ $balloc"
|
||||||
|
echo "SSL Type........................ $SSL_TYPE"
|
||||||
|
echo
|
||||||
|
|
791
libratbox/depcomp
Executable file
791
libratbox/depcomp
Executable file
|
@ -0,0 +1,791 @@
|
||||||
|
#! /bin/sh
|
||||||
|
# depcomp - compile a program generating dependencies as side-effects
|
||||||
|
|
||||||
|
scriptversion=2016-01-11.22; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1999-2017 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
'')
|
||||||
|
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||||
|
exit 1;
|
||||||
|
;;
|
||||||
|
-h | --h*)
|
||||||
|
cat <<\EOF
|
||||||
|
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||||
|
|
||||||
|
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||||
|
as side-effects.
|
||||||
|
|
||||||
|
Environment variables:
|
||||||
|
depmode Dependency tracking mode.
|
||||||
|
source Source file read by 'PROGRAMS ARGS'.
|
||||||
|
object Object file output by 'PROGRAMS ARGS'.
|
||||||
|
DEPDIR directory where to store dependencies.
|
||||||
|
depfile Dependency file to output.
|
||||||
|
tmpdepfile Temporary file to use when outputting dependencies.
|
||||||
|
libtool Whether libtool is used (yes/no).
|
||||||
|
|
||||||
|
Report bugs to <bug-automake@gnu.org>.
|
||||||
|
EOF
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
-v | --v*)
|
||||||
|
echo "depcomp $scriptversion"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Get the directory component of the given path, and save it in the
|
||||||
|
# global variables '$dir'. Note that this directory component will
|
||||||
|
# be either empty or ending with a '/' character. This is deliberate.
|
||||||
|
set_dir_from ()
|
||||||
|
{
|
||||||
|
case $1 in
|
||||||
|
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
|
||||||
|
*) dir=;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the suffix-stripped basename of the given path, and save it the
|
||||||
|
# global variable '$base'.
|
||||||
|
set_base_from ()
|
||||||
|
{
|
||||||
|
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
|
||||||
|
}
|
||||||
|
|
||||||
|
# If no dependency file was actually created by the compiler invocation,
|
||||||
|
# we still have to create a dummy depfile, to avoid errors with the
|
||||||
|
# Makefile "include basename.Plo" scheme.
|
||||||
|
make_dummy_depfile ()
|
||||||
|
{
|
||||||
|
echo "#dummy" > "$depfile"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Factor out some common post-processing of the generated depfile.
|
||||||
|
# Requires the auxiliary global variable '$tmpdepfile' to be set.
|
||||||
|
aix_post_process_depfile ()
|
||||||
|
{
|
||||||
|
# If the compiler actually managed to produce a dependency file,
|
||||||
|
# post-process it.
|
||||||
|
if test -f "$tmpdepfile"; then
|
||||||
|
# Each line is of the form 'foo.o: dependency.h'.
|
||||||
|
# Do two passes, one to just change these to
|
||||||
|
# $object: dependency.h
|
||||||
|
# and one to simply output
|
||||||
|
# dependency.h:
|
||||||
|
# which is needed to avoid the deleted-header problem.
|
||||||
|
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
|
||||||
|
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
|
||||||
|
} > "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
else
|
||||||
|
make_dummy_depfile
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# A tabulation character.
|
||||||
|
tab=' '
|
||||||
|
# A newline character.
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
# Character ranges might be problematic outside the C locale.
|
||||||
|
# These definitions help.
|
||||||
|
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||||
|
lower=abcdefghijklmnopqrstuvwxyz
|
||||||
|
digits=0123456789
|
||||||
|
alpha=${upper}${lower}
|
||||||
|
|
||||||
|
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||||
|
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||||
|
depfile=${depfile-`echo "$object" |
|
||||||
|
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||||
|
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||||
|
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
|
||||||
|
# Avoid interferences from the environment.
|
||||||
|
gccflag= dashmflag=
|
||||||
|
|
||||||
|
# Some modes work just like other modes, but use different flags. We
|
||||||
|
# parameterize here, but still list the modes in the big case below,
|
||||||
|
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||||
|
# here, because this file can only contain one case statement.
|
||||||
|
if test "$depmode" = hp; then
|
||||||
|
# HP compiler uses -M and no extra arg.
|
||||||
|
gccflag=-M
|
||||||
|
depmode=gcc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$depmode" = dashXmstdout; then
|
||||||
|
# This is just like dashmstdout with a different argument.
|
||||||
|
dashmflag=-xM
|
||||||
|
depmode=dashmstdout
|
||||||
|
fi
|
||||||
|
|
||||||
|
cygpath_u="cygpath -u -f -"
|
||||||
|
if test "$depmode" = msvcmsys; then
|
||||||
|
# This is just like msvisualcpp but w/o cygpath translation.
|
||||||
|
# Just convert the backslash-escaped backslashes to single forward
|
||||||
|
# slashes to satisfy depend.m4
|
||||||
|
cygpath_u='sed s,\\\\,/,g'
|
||||||
|
depmode=msvisualcpp
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$depmode" = msvc7msys; then
|
||||||
|
# This is just like msvc7 but w/o cygpath translation.
|
||||||
|
# Just convert the backslash-escaped backslashes to single forward
|
||||||
|
# slashes to satisfy depend.m4
|
||||||
|
cygpath_u='sed s,\\\\,/,g'
|
||||||
|
depmode=msvc7
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$depmode" = xlc; then
|
||||||
|
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
|
||||||
|
gccflag=-qmakedep=gcc,-MF
|
||||||
|
depmode=gcc
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$depmode" in
|
||||||
|
gcc3)
|
||||||
|
## gcc 3 implements dependency tracking that does exactly what
|
||||||
|
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||||
|
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||||
|
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||||
|
## the command line argument order; so add the flags where they
|
||||||
|
## appear in depend2.am. Note that the slowdown incurred here
|
||||||
|
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||||
|
*) set fnord "$@" "$arg" ;;
|
||||||
|
esac
|
||||||
|
shift # fnord
|
||||||
|
shift # $arg
|
||||||
|
done
|
||||||
|
"$@"
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
mv "$tmpdepfile" "$depfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
gcc)
|
||||||
|
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
|
||||||
|
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
|
||||||
|
## (see the conditional assignment to $gccflag above).
|
||||||
|
## There are various ways to get dependency output from gcc. Here's
|
||||||
|
## why we pick this rather obscure method:
|
||||||
|
## - Don't want to use -MD because we'd like the dependencies to end
|
||||||
|
## up in a subdir. Having to rename by hand is ugly.
|
||||||
|
## (We might end up doing this anyway to support other compilers.)
|
||||||
|
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||||
|
## -MM, not -M (despite what the docs say). Also, it might not be
|
||||||
|
## supported by the other compilers which use the 'gcc' depmode.
|
||||||
|
## - Using -M directly means running the compiler twice (even worse
|
||||||
|
## than renaming).
|
||||||
|
if test -z "$gccflag"; then
|
||||||
|
gccflag=-MD,
|
||||||
|
fi
|
||||||
|
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
# The second -e expression handles DOS-style file names with drive
|
||||||
|
# letters.
|
||||||
|
sed -e 's/^[^:]*: / /' \
|
||||||
|
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||||
|
## This next piece of magic avoids the "deleted header file" problem.
|
||||||
|
## The problem is that when a header file which appears in a .P file
|
||||||
|
## is deleted, the dependency causes make to die (because there is
|
||||||
|
## typically no way to rebuild the header). We avoid this by adding
|
||||||
|
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||||
|
## this for us directly.
|
||||||
|
## Some versions of gcc put a space before the ':'. On the theory
|
||||||
|
## that the space means something, we add a space to the output as
|
||||||
|
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||||
|
## to the object. Take care to not repeat it in the output.
|
||||||
|
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||||
|
## correctly. Breaking it into two sed invocations is a workaround.
|
||||||
|
tr ' ' "$nl" < "$tmpdepfile" \
|
||||||
|
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||||
|
| sed -e 's/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
hp)
|
||||||
|
# This case exists only to let depend.m4 do its work. It works by
|
||||||
|
# looking at the text of this script. This case will never be run,
|
||||||
|
# since it is checked for above.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
sgi)
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||||
|
else
|
||||||
|
"$@" -MDupdate "$tmpdepfile"
|
||||||
|
fi
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
|
||||||
|
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
# Clip off the initial element (the dependent). Don't try to be
|
||||||
|
# clever and replace this with sed code, as IRIX sed won't handle
|
||||||
|
# lines with more than a fixed number of characters (4096 in
|
||||||
|
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||||
|
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||||
|
# dependency line.
|
||||||
|
tr ' ' "$nl" < "$tmpdepfile" \
|
||||||
|
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
|
||||||
|
| tr "$nl" ' ' >> "$depfile"
|
||||||
|
echo >> "$depfile"
|
||||||
|
# The second pass generates a dummy entry for each header file.
|
||||||
|
tr ' ' "$nl" < "$tmpdepfile" \
|
||||||
|
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||||
|
>> "$depfile"
|
||||||
|
else
|
||||||
|
make_dummy_depfile
|
||||||
|
fi
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
xlc)
|
||||||
|
# This case exists only to let depend.m4 do its work. It works by
|
||||||
|
# looking at the text of this script. This case will never be run,
|
||||||
|
# since it is checked for above.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
aix)
|
||||||
|
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||||
|
# in a .u file. In older versions, this file always lives in the
|
||||||
|
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||||
|
# start of each line; $object doesn't have directory information.
|
||||||
|
# Version 6 uses the directory in both cases.
|
||||||
|
set_dir_from "$object"
|
||||||
|
set_base_from "$object"
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
tmpdepfile1=$dir$base.u
|
||||||
|
tmpdepfile2=$base.u
|
||||||
|
tmpdepfile3=$dir.libs/$base.u
|
||||||
|
"$@" -Wc,-M
|
||||||
|
else
|
||||||
|
tmpdepfile1=$dir$base.u
|
||||||
|
tmpdepfile2=$dir$base.u
|
||||||
|
tmpdepfile3=$dir$base.u
|
||||||
|
"$@" -M
|
||||||
|
fi
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
do
|
||||||
|
test -f "$tmpdepfile" && break
|
||||||
|
done
|
||||||
|
aix_post_process_depfile
|
||||||
|
;;
|
||||||
|
|
||||||
|
tcc)
|
||||||
|
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
|
||||||
|
# FIXME: That version still under development at the moment of writing.
|
||||||
|
# Make that this statement remains true also for stable, released
|
||||||
|
# versions.
|
||||||
|
# It will wrap lines (doesn't matter whether long or short) with a
|
||||||
|
# trailing '\', as in:
|
||||||
|
#
|
||||||
|
# foo.o : \
|
||||||
|
# foo.c \
|
||||||
|
# foo.h \
|
||||||
|
#
|
||||||
|
# It will put a trailing '\' even on the last line, and will use leading
|
||||||
|
# spaces rather than leading tabs (at least since its commit 0394caf7
|
||||||
|
# "Emit spaces for -MD").
|
||||||
|
"$@" -MD -MF "$tmpdepfile"
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
|
||||||
|
# We have to change lines of the first kind to '$object: \'.
|
||||||
|
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
|
||||||
|
# And for each line of the second kind, we have to emit a 'dep.h:'
|
||||||
|
# dummy dependency, to avoid the deleted-header problem.
|
||||||
|
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
## The order of this option in the case statement is important, since the
|
||||||
|
## shell code in configure will try each of these formats in the order
|
||||||
|
## listed in this file. A plain '-MD' option would be understood by many
|
||||||
|
## compilers, so we must ensure this comes after the gcc and icc options.
|
||||||
|
pgcc)
|
||||||
|
# Portland's C compiler understands '-MD'.
|
||||||
|
# Will always output deps to 'file.d' where file is the root name of the
|
||||||
|
# source file under compilation, even if file resides in a subdirectory.
|
||||||
|
# The object file name does not affect the name of the '.d' file.
|
||||||
|
# pgcc 10.2 will output
|
||||||
|
# foo.o: sub/foo.c sub/foo.h
|
||||||
|
# and will wrap long lines using '\' :
|
||||||
|
# foo.o: sub/foo.c ... \
|
||||||
|
# sub/foo.h ... \
|
||||||
|
# ...
|
||||||
|
set_dir_from "$object"
|
||||||
|
# Use the source, not the object, to determine the base name, since
|
||||||
|
# that's sadly what pgcc will do too.
|
||||||
|
set_base_from "$source"
|
||||||
|
tmpdepfile=$base.d
|
||||||
|
|
||||||
|
# For projects that build the same source file twice into different object
|
||||||
|
# files, the pgcc approach of using the *source* file root name can cause
|
||||||
|
# problems in parallel builds. Use a locking strategy to avoid stomping on
|
||||||
|
# the same $tmpdepfile.
|
||||||
|
lockdir=$base.d-lock
|
||||||
|
trap "
|
||||||
|
echo '$0: caught signal, cleaning up...' >&2
|
||||||
|
rmdir '$lockdir'
|
||||||
|
exit 1
|
||||||
|
" 1 2 13 15
|
||||||
|
numtries=100
|
||||||
|
i=$numtries
|
||||||
|
while test $i -gt 0; do
|
||||||
|
# mkdir is a portable test-and-set.
|
||||||
|
if mkdir "$lockdir" 2>/dev/null; then
|
||||||
|
# This process acquired the lock.
|
||||||
|
"$@" -MD
|
||||||
|
stat=$?
|
||||||
|
# Release the lock.
|
||||||
|
rmdir "$lockdir"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
# If the lock is being held by a different process, wait
|
||||||
|
# until the winning process is done or we timeout.
|
||||||
|
while test -d "$lockdir" && test $i -gt 0; do
|
||||||
|
sleep 1
|
||||||
|
i=`expr $i - 1`
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
i=`expr $i - 1`
|
||||||
|
done
|
||||||
|
trap - 1 2 13 15
|
||||||
|
if test $i -le 0; then
|
||||||
|
echo "$0: failed to acquire lock after $numtries attempts" >&2
|
||||||
|
echo "$0: check lockdir '$lockdir'" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
# Each line is of the form `foo.o: dependent.h',
|
||||||
|
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||||
|
# Do two passes, one to just change these to
|
||||||
|
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||||
|
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||||
|
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||||
|
# correctly. Breaking it into two sed invocations is a workaround.
|
||||||
|
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
|
||||||
|
| sed -e 's/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
hp2)
|
||||||
|
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||||
|
# compilers, which have integrated preprocessors. The correct option
|
||||||
|
# to use with these is +Maked; it writes dependencies to a file named
|
||||||
|
# 'foo.d', which lands next to the object file, wherever that
|
||||||
|
# happens to be.
|
||||||
|
# Much of this is similar to the tru64 case; see comments there.
|
||||||
|
set_dir_from "$object"
|
||||||
|
set_base_from "$object"
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
tmpdepfile1=$dir$base.d
|
||||||
|
tmpdepfile2=$dir.libs/$base.d
|
||||||
|
"$@" -Wc,+Maked
|
||||||
|
else
|
||||||
|
tmpdepfile1=$dir$base.d
|
||||||
|
tmpdepfile2=$dir$base.d
|
||||||
|
"$@" +Maked
|
||||||
|
fi
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||||
|
do
|
||||||
|
test -f "$tmpdepfile" && break
|
||||||
|
done
|
||||||
|
if test -f "$tmpdepfile"; then
|
||||||
|
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||||
|
# Add 'dependent.h:' lines.
|
||||||
|
sed -ne '2,${
|
||||||
|
s/^ *//
|
||||||
|
s/ \\*$//
|
||||||
|
s/$/:/
|
||||||
|
p
|
||||||
|
}' "$tmpdepfile" >> "$depfile"
|
||||||
|
else
|
||||||
|
make_dummy_depfile
|
||||||
|
fi
|
||||||
|
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||||
|
;;
|
||||||
|
|
||||||
|
tru64)
|
||||||
|
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||||
|
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||||
|
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||||
|
# dependencies in 'foo.d' instead, so we check for that too.
|
||||||
|
# Subdirectories are respected.
|
||||||
|
set_dir_from "$object"
|
||||||
|
set_base_from "$object"
|
||||||
|
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
# Libtool generates 2 separate objects for the 2 libraries. These
|
||||||
|
# two compilations output dependencies in $dir.libs/$base.o.d and
|
||||||
|
# in $dir$base.o.d. We have to check for both files, because
|
||||||
|
# one of the two compilations can be disabled. We should prefer
|
||||||
|
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||||
|
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||||
|
# the former would cause a distcleancheck panic.
|
||||||
|
tmpdepfile1=$dir$base.o.d # libtool 1.5
|
||||||
|
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
|
||||||
|
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||||
|
"$@" -Wc,-MD
|
||||||
|
else
|
||||||
|
tmpdepfile1=$dir$base.d
|
||||||
|
tmpdepfile2=$dir$base.d
|
||||||
|
tmpdepfile3=$dir$base.d
|
||||||
|
"$@" -MD
|
||||||
|
fi
|
||||||
|
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
do
|
||||||
|
test -f "$tmpdepfile" && break
|
||||||
|
done
|
||||||
|
# Same post-processing that is required for AIX mode.
|
||||||
|
aix_post_process_depfile
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvc7)
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
showIncludes=-Wc,-showIncludes
|
||||||
|
else
|
||||||
|
showIncludes=-showIncludes
|
||||||
|
fi
|
||||||
|
"$@" $showIncludes > "$tmpdepfile"
|
||||||
|
stat=$?
|
||||||
|
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
# The first sed program below extracts the file names and escapes
|
||||||
|
# backslashes for cygpath. The second sed program outputs the file
|
||||||
|
# name when reading, but also accumulates all include files in the
|
||||||
|
# hold buffer in order to output them again at the end. This only
|
||||||
|
# works with sed implementations that can handle large buffers.
|
||||||
|
sed < "$tmpdepfile" -n '
|
||||||
|
/^Note: including file: *\(.*\)/ {
|
||||||
|
s//\1/
|
||||||
|
s/\\/\\\\/g
|
||||||
|
p
|
||||||
|
}' | $cygpath_u | sort -u | sed -n '
|
||||||
|
s/ /\\ /g
|
||||||
|
s/\(.*\)/'"$tab"'\1 \\/p
|
||||||
|
s/.\(.*\) \\/\1:/
|
||||||
|
H
|
||||||
|
$ {
|
||||||
|
s/.*/'"$tab"'/
|
||||||
|
G
|
||||||
|
p
|
||||||
|
}' >> "$depfile"
|
||||||
|
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvc7msys)
|
||||||
|
# This case exists only to let depend.m4 do its work. It works by
|
||||||
|
# looking at the text of this script. This case will never be run,
|
||||||
|
# since it is checked for above.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
#nosideeffect)
|
||||||
|
# This comment above is used by automake to tell side-effect
|
||||||
|
# dependency tracking mechanisms from slower ones.
|
||||||
|
|
||||||
|
dashmstdout)
|
||||||
|
# Important note: in order to support this mode, a compiler *must*
|
||||||
|
# always write the preprocessed file to stdout, regardless of -o.
|
||||||
|
"$@" || exit $?
|
||||||
|
|
||||||
|
# Remove the call to Libtool.
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
while test "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove '-o $object'.
|
||||||
|
IFS=" "
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
-o)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
$object)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"
|
||||||
|
shift # fnord
|
||||||
|
shift # $arg
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
test -z "$dashmflag" && dashmflag=-M
|
||||||
|
# Require at least two characters before searching for ':'
|
||||||
|
# in the target name. This is to cope with DOS-style filenames:
|
||||||
|
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||||
|
"$@" $dashmflag |
|
||||||
|
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
|
||||||
|
rm -f "$depfile"
|
||||||
|
cat < "$tmpdepfile" > "$depfile"
|
||||||
|
# Some versions of the HPUX 10.20 sed can't process this sed invocation
|
||||||
|
# correctly. Breaking it into two sed invocations is a workaround.
|
||||||
|
tr ' ' "$nl" < "$tmpdepfile" \
|
||||||
|
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||||
|
| sed -e 's/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
dashXmstdout)
|
||||||
|
# This case only exists to satisfy depend.m4. It is never actually
|
||||||
|
# run, as this mode is specially recognized in the preamble.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
makedepend)
|
||||||
|
"$@" || exit $?
|
||||||
|
# Remove any Libtool call
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
while test "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
# X makedepend
|
||||||
|
shift
|
||||||
|
cleared=no eat=no
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $cleared in
|
||||||
|
no)
|
||||||
|
set ""; shift
|
||||||
|
cleared=yes ;;
|
||||||
|
esac
|
||||||
|
if test $eat = yes; then
|
||||||
|
eat=no
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
case "$arg" in
|
||||||
|
-D*|-I*)
|
||||||
|
set fnord "$@" "$arg"; shift ;;
|
||||||
|
# Strip any option that makedepend may not understand. Remove
|
||||||
|
# the object too, otherwise makedepend will parse it as a source file.
|
||||||
|
-arch)
|
||||||
|
eat=yes ;;
|
||||||
|
-*|$object)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"; shift ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||||
|
touch "$tmpdepfile"
|
||||||
|
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||||
|
rm -f "$depfile"
|
||||||
|
# makedepend may prepend the VPATH from the source file name to the object.
|
||||||
|
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||||
|
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||||
|
# Some versions of the HPUX 10.20 sed can't process the last invocation
|
||||||
|
# correctly. Breaking it into two sed invocations is a workaround.
|
||||||
|
sed '1,2d' "$tmpdepfile" \
|
||||||
|
| tr ' ' "$nl" \
|
||||||
|
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||||
|
| sed -e 's/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||||
|
;;
|
||||||
|
|
||||||
|
cpp)
|
||||||
|
# Important note: in order to support this mode, a compiler *must*
|
||||||
|
# always write the preprocessed file to stdout.
|
||||||
|
"$@" || exit $?
|
||||||
|
|
||||||
|
# Remove the call to Libtool.
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
while test "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove '-o $object'.
|
||||||
|
IFS=" "
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
-o)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
$object)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"
|
||||||
|
shift # fnord
|
||||||
|
shift # $arg
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
"$@" -E \
|
||||||
|
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||||
|
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||||
|
| sed '$ s: \\$::' > "$tmpdepfile"
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
cat < "$tmpdepfile" >> "$depfile"
|
||||||
|
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvisualcpp)
|
||||||
|
# Important note: in order to support this mode, a compiler *must*
|
||||||
|
# always write the preprocessed file to stdout.
|
||||||
|
"$@" || exit $?
|
||||||
|
|
||||||
|
# Remove the call to Libtool.
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
while test "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS=" "
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case "$arg" in
|
||||||
|
-o)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
$object)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||||
|
set fnord "$@"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
"$@" -E 2>/dev/null |
|
||||||
|
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||||
|
echo "$tab" >> "$depfile"
|
||||||
|
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvcmsys)
|
||||||
|
# This case exists only to let depend.m4 do its work. It works by
|
||||||
|
# looking at the text of this script. This case will never be run,
|
||||||
|
# since it is checked for above.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
none)
|
||||||
|
exec "$@"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Unknown depmode $depmode" 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# mode: shell-script
|
||||||
|
# sh-indentation: 2
|
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
46
libratbox/include/commio-ssl.h
Normal file
46
libratbox/include/commio-ssl.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: A slightly useful ircd.
|
||||||
|
* commio-ssl.h: A header for the ssl code
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: commio-ssl.h 26280 2008-12-10 20:25:29Z androsyn $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _COMMIO_SSL_H
|
||||||
|
#define _COMMIO_SSL_H
|
||||||
|
|
||||||
|
int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list, const char *hostname);
|
||||||
|
int rb_init_ssl(void);
|
||||||
|
|
||||||
|
int rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept);
|
||||||
|
int rb_init_prng(const char *path, prng_seed_t seed_type);
|
||||||
|
|
||||||
|
int rb_get_random(void *buf, size_t length);
|
||||||
|
const char *rb_get_ssl_strerror(rb_fde_t *F);
|
||||||
|
void rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout);
|
||||||
|
void rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout);
|
||||||
|
void rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest, struct sockaddr *clocal, int socklen,
|
||||||
|
CNCB * callback, void *data, int timeout);
|
||||||
|
void rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrlen);
|
||||||
|
void rb_ssl_shutdown(rb_fde_t *F);
|
||||||
|
ssize_t rb_ssl_read(rb_fde_t *F, void *buf, size_t count);
|
||||||
|
ssize_t rb_ssl_write(rb_fde_t *F, const void *buf, size_t count);
|
||||||
|
void rb_get_ssl_info(char *buf, size_t length);
|
||||||
|
|
||||||
|
#endif
|
225
libratbox/include/ratbox_lib.h
Normal file
225
libratbox/include/ratbox_lib.h
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
* $Id: ratbox_lib.h 26256 2008-12-10 04:05:26Z androsyn $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RB_LIB_H
|
||||||
|
#define RB_LIB_H 1
|
||||||
|
|
||||||
|
#include <librb-config.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_LINUX_TCP_H
|
||||||
|
# include <linux/tcp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#undef alloca
|
||||||
|
#define alloca __builtin_alloca
|
||||||
|
#else
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
# include <malloc.h>
|
||||||
|
# define alloca _alloca
|
||||||
|
# else
|
||||||
|
# if RB_HAVE_ALLOCA_H
|
||||||
|
# include <alloca.h>
|
||||||
|
# else
|
||||||
|
# ifdef _AIX
|
||||||
|
#pragma alloca
|
||||||
|
# else
|
||||||
|
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||||
|
char *alloca();
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif /* __GNUC__ */
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
|
||||||
|
#ifdef rb_likely
|
||||||
|
#undef rb_likely
|
||||||
|
#endif
|
||||||
|
#ifdef rb_unlikely
|
||||||
|
#undef rb_unlikely
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
|
||||||
|
# define __builtin_expect(x, expected_value) (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define rb_likely(x) __builtin_expect(!!(x), 1)
|
||||||
|
#define rb_unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
|
||||||
|
#else /* !__GNUC__ */
|
||||||
|
|
||||||
|
#define UNUSED(x) x
|
||||||
|
|
||||||
|
#ifdef rb_likely
|
||||||
|
#undef rb_likely
|
||||||
|
#endif
|
||||||
|
#ifdef rb_unlikely
|
||||||
|
#undef rb_unlikely
|
||||||
|
#endif
|
||||||
|
#define rb_likely(x) (x)
|
||||||
|
#define rb_unlikely(x) (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <process.h>
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX 128
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef strerror
|
||||||
|
#undef strerror
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define strerror(x) rb_strerror(x)
|
||||||
|
char *rb_strerror(int error);
|
||||||
|
|
||||||
|
|
||||||
|
#define ENOBUFS WSAENOBUFS
|
||||||
|
#define EINPROGRESS WSAEINPROGRESS
|
||||||
|
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||||
|
#define EMSGSIZE WSAEMSGSIZE
|
||||||
|
#define EALREADY WSAEALREADY
|
||||||
|
#define EISCONN WSAEISCONN
|
||||||
|
#define EADDRINUSE WSAEADDRINUSE
|
||||||
|
#define EAFNOSUPPORT WSAEAFNOSUPPORT
|
||||||
|
|
||||||
|
#define pipe(x) _pipe(x, 1024, O_BINARY)
|
||||||
|
#define ioctl(x,y,z) ioctlsocket(x,y, (u_long *)z)
|
||||||
|
|
||||||
|
#define WNOHANG 1
|
||||||
|
|
||||||
|
#ifndef SIGKILL
|
||||||
|
#define SIGKILL SIGTERM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HOSTIPLEN
|
||||||
|
#define HOSTIPLEN 53
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define slrb_assert(expr) do \
|
||||||
|
if(rb_unlikely(!(expr))) { \
|
||||||
|
rb_lib_log( \
|
||||||
|
"file: %s line: %d (%s): Assertion failed: (%s)", \
|
||||||
|
__FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \
|
||||||
|
} \
|
||||||
|
while(0)
|
||||||
|
#else
|
||||||
|
#define slrb_assert(expr) do \
|
||||||
|
if(rb_unlikely(!(expr))) { \
|
||||||
|
rb_lib_log( \
|
||||||
|
"file: %s line: %d: Assertion failed: (%s)", \
|
||||||
|
__FILE__, __LINE__, #expr); \
|
||||||
|
} \
|
||||||
|
while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SOFT_ASSERT
|
||||||
|
#define lrb_assert(expr) slrb_assert(expr)
|
||||||
|
#else
|
||||||
|
#define lrb_assert(expr) do { slrb_assert(expr); assert(expr); } while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RB_SOCKADDR_HAS_SA_LEN
|
||||||
|
#define ss_len sa_len
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GET_SS_FAMILY(x) (((const struct sockaddr *)(x))->sa_family)
|
||||||
|
#define SET_SS_FAMILY(x, y) ((((struct sockaddr *)(x))->sa_family) = y)
|
||||||
|
#ifdef RB_SOCKADDR_HAS_SA_LEN
|
||||||
|
#define SET_SS_LEN(x, y) do { \
|
||||||
|
struct sockaddr *storage; \
|
||||||
|
storage = ((struct sockaddr *)(x));\
|
||||||
|
storage->sa_len = (y); \
|
||||||
|
} while (0)
|
||||||
|
#define GET_SS_LEN(x) (((struct sockaddr *)(x))->sa_len)
|
||||||
|
#else /* !RB_SOCKADDR_HAS_SA_LEN */
|
||||||
|
#define SET_SS_LEN(x, y) (((struct sockaddr *)(x))->sa_family = ((struct sockaddr *)(x))->sa_family)
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
#define GET_SS_LEN(x) (((struct sockaddr *)(x))->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6))
|
||||||
|
#else
|
||||||
|
#define GET_SS_LEN(x) (((struct sockaddr *)(x))->sa_family == AF_INET ? sizeof(struct sockaddr_in) : 0)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef INADDRSZ
|
||||||
|
#define INADDRSZ 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef IN6ADDRSZ
|
||||||
|
#define IN6ADDRSZ 16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef INT16SZ
|
||||||
|
#define INT16SZ 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef void log_cb(const char *buffer);
|
||||||
|
typedef void restart_cb(const char *buffer);
|
||||||
|
typedef void die_cb(const char *buffer);
|
||||||
|
|
||||||
|
char *rb_ctime(const time_t, char *, size_t);
|
||||||
|
char *rb_date(const time_t, char *, size_t);
|
||||||
|
void rb_lib_log(const char *, ...);
|
||||||
|
void rb_lib_restart(const char *, ...) __attribute__((noreturn));
|
||||||
|
void rb_lib_die(const char *, ...);
|
||||||
|
void rb_set_time(void);
|
||||||
|
const char *rb_lib_version(void);
|
||||||
|
|
||||||
|
void rb_lib_init(log_cb * xilog, restart_cb * irestart, die_cb * idie, int closeall, int maxfds,
|
||||||
|
size_t dh_size, size_t fd_heap_size);
|
||||||
|
void rb_lib_loop(long delay) __attribute__((noreturn));
|
||||||
|
|
||||||
|
time_t rb_current_time(void);
|
||||||
|
const struct timeval *rb_current_time_tv(void);
|
||||||
|
pid_t rb_spawn_process(const char *, const char **);
|
||||||
|
|
||||||
|
char *rb_strtok_r(char *, const char *, char **);
|
||||||
|
|
||||||
|
int rb_gettimeofday(struct timeval *, void *);
|
||||||
|
|
||||||
|
void rb_sleep(unsigned int seconds, unsigned int useconds);
|
||||||
|
char *rb_crypt(const char *, const char *);
|
||||||
|
|
||||||
|
unsigned char *rb_base64_encode(const unsigned char *str, int length);
|
||||||
|
unsigned char *rb_base64_decode(const unsigned char *str, int length, int *ret);
|
||||||
|
int rb_kill(pid_t, int);
|
||||||
|
char *rb_strerror(int);
|
||||||
|
|
||||||
|
int rb_setenv(const char *, const char *, int);
|
||||||
|
|
||||||
|
pid_t rb_waitpid(pid_t pid, int *status, int options);
|
||||||
|
pid_t rb_getpid(void);
|
||||||
|
//unsigned int rb_geteuid(void);
|
||||||
|
|
||||||
|
|
||||||
|
#include <rb_tools.h>
|
||||||
|
#include <rb_memory.h>
|
||||||
|
#include <rb_commio.h>
|
||||||
|
#include <rb_balloc.h>
|
||||||
|
#include <rb_linebuf.h>
|
||||||
|
#include <rb_snprintf.h>
|
||||||
|
#include <rb_event.h>
|
||||||
|
#include <rb_helper.h>
|
||||||
|
#include <rb_rawbuf.h>
|
||||||
|
#include <rb_patricia.h>
|
||||||
|
|
||||||
|
#endif
|
210
libratbox/include/rb_commio.h
Normal file
210
libratbox/include/rb_commio.h
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: A slightly useful ircd.
|
||||||
|
* commio.h: A header for the network subsystem.
|
||||||
|
*
|
||||||
|
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||||
|
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||||
|
* Copyright (C) 2002-2005 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: rb_commio.h 26092 2008-09-19 15:13:52Z androsyn $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RB_LIB_H
|
||||||
|
# error "Do not use commio.h directly"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef INCLUDED_commio_h
|
||||||
|
#define INCLUDED_commio_h
|
||||||
|
|
||||||
|
|
||||||
|
struct sockaddr;
|
||||||
|
struct _fde;
|
||||||
|
typedef struct _fde rb_fde_t;
|
||||||
|
|
||||||
|
/* Callback for completed IO events */
|
||||||
|
typedef void PF(rb_fde_t *, void *);
|
||||||
|
|
||||||
|
/* Callback for completed connections */
|
||||||
|
/* int fd, int status, void * */
|
||||||
|
typedef void CNCB(rb_fde_t *, int, void *);
|
||||||
|
/* callback for fd table dumps */
|
||||||
|
typedef void DUMPCB(int, const char *desc, void *);
|
||||||
|
/* callback for accept callbacks */
|
||||||
|
typedef void ACCB(rb_fde_t *, int status, struct sockaddr *addr, rb_socklen_t len, void *);
|
||||||
|
/* callback for pre-accept callback */
|
||||||
|
typedef int ACPRE(rb_fde_t *, struct sockaddr *addr, rb_socklen_t len, void *);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RB_OK,
|
||||||
|
RB_ERR_BIND,
|
||||||
|
RB_ERR_DNS,
|
||||||
|
RB_ERR_TIMEOUT,
|
||||||
|
RB_ERR_CONNECT,
|
||||||
|
RB_ERROR,
|
||||||
|
RB_ERROR_SSL,
|
||||||
|
RB_ERR_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
#define RB_FD_NONE 0x01
|
||||||
|
#define RB_FD_FILE 0x02
|
||||||
|
#define RB_FD_SOCKET 0x04
|
||||||
|
#ifndef _WIN32
|
||||||
|
#define RB_FD_PIPE 0x08
|
||||||
|
#else
|
||||||
|
#define RB_FD_PIPE RB_FD_SOCKET
|
||||||
|
#endif
|
||||||
|
#define RB_FD_LISTEN 0x10
|
||||||
|
#define RB_FD_SSL 0x20
|
||||||
|
#define RB_FD_UNKNOWN 0x40
|
||||||
|
|
||||||
|
#define RB_RW_IO_ERROR -1 /* System call error */
|
||||||
|
#define RB_RW_SSL_ERROR -2 /* SSL Error */
|
||||||
|
#define RB_RW_SSL_NEED_READ -3 /* SSL Needs read */
|
||||||
|
#define RB_RW_SSL_NEED_WRITE -4 /* SSL Needs write */
|
||||||
|
|
||||||
|
|
||||||
|
struct rb_iovec
|
||||||
|
{
|
||||||
|
void *iov_base;
|
||||||
|
size_t iov_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void rb_fdlist_init(int closeall, int maxfds, size_t heapsize);
|
||||||
|
|
||||||
|
rb_fde_t *rb_open(int, uint8_t, const char *);
|
||||||
|
void rb_close(rb_fde_t *);
|
||||||
|
void rb_dump_fd(DUMPCB *, void *xdata);
|
||||||
|
void rb_note(rb_fde_t *, const char *);
|
||||||
|
|
||||||
|
/* Type of IO */
|
||||||
|
#define RB_SELECT_READ 0x1
|
||||||
|
#define RB_SELECT_WRITE 0x2
|
||||||
|
|
||||||
|
#define RB_SELECT_ACCEPT RB_SELECT_READ
|
||||||
|
#define RB_SELECT_CONNECT RB_SELECT_WRITE
|
||||||
|
|
||||||
|
#define RB_SSL_CERTFP_LEN 64
|
||||||
|
|
||||||
|
/* Methods for certfp */
|
||||||
|
/* Digest of full X.509 certificate */
|
||||||
|
#define RB_SSL_CERTFP_METH_CERT_SHA1 0x0000
|
||||||
|
#define RB_SSL_CERTFP_METH_CERT_SHA256 0x0001
|
||||||
|
#define RB_SSL_CERTFP_METH_CERT_SHA512 0x0002
|
||||||
|
/* Digest of SubjectPublicKeyInfo (RFC 5280), used by DANE (RFC 6698) */
|
||||||
|
#define RB_SSL_CERTFP_METH_SPKI_SHA256 0x1001
|
||||||
|
#define RB_SSL_CERTFP_METH_SPKI_SHA512 0x1002
|
||||||
|
|
||||||
|
/* Names for certfp */
|
||||||
|
#define CERTFP_NAME_CERT_SHA1 "sha1"
|
||||||
|
#define CERTFP_PREFIX_CERT_SHA1 ""
|
||||||
|
#define CERTFP_NAME_CERT_SHA256 "sha256"
|
||||||
|
#define CERTFP_PREFIX_CERT_SHA256 ""
|
||||||
|
#define CERTFP_NAME_CERT_SHA512 "sha512"
|
||||||
|
#define CERTFP_PREFIX_CERT_SHA512 ""
|
||||||
|
/* These prefixes are copied from RFC 7218 */
|
||||||
|
#define CERTFP_NAME_SPKI_SHA256 "spki_sha256"
|
||||||
|
#define CERTFP_PREFIX_SPKI_SHA256 "SPKI:SHA2-256:"
|
||||||
|
#define CERTFP_NAME_SPKI_SHA512 "spki_sha512"
|
||||||
|
#define CERTFP_PREFIX_SPKI_SHA512 "SPKI:SHA2-512:"
|
||||||
|
|
||||||
|
|
||||||
|
#define RB_SSL_CERTFP_LEN_SHA1 20
|
||||||
|
#define RB_SSL_CERTFP_LEN_SHA256 32
|
||||||
|
#define RB_SSL_CERTFP_LEN_SHA512 64
|
||||||
|
|
||||||
|
int rb_set_nb(rb_fde_t *);
|
||||||
|
int rb_set_buffers(rb_fde_t *, int);
|
||||||
|
|
||||||
|
int rb_get_sockerr(rb_fde_t *);
|
||||||
|
|
||||||
|
void rb_settimeout(rb_fde_t *, time_t, PF *, void *);
|
||||||
|
void rb_checktimeouts(void *);
|
||||||
|
void rb_connect_tcp(rb_fde_t *, struct sockaddr *, struct sockaddr *, int, CNCB *, void *, int);
|
||||||
|
void rb_connect_tcp_ssl(rb_fde_t *, struct sockaddr *, struct sockaddr *, int, CNCB *, void *, int);
|
||||||
|
int rb_connect_sockaddr(rb_fde_t *, struct sockaddr *addr, int len);
|
||||||
|
|
||||||
|
const char *rb_errstr(int status);
|
||||||
|
rb_fde_t *rb_socket(int family, int sock_type, int proto, const char *note);
|
||||||
|
int rb_socketpair(int family, int sock_type, int proto, rb_fde_t **F1, rb_fde_t **F2,
|
||||||
|
const char *note);
|
||||||
|
|
||||||
|
void rb_accept_tcp(rb_fde_t *, ACPRE * precb, ACCB * callback, void *data);
|
||||||
|
ssize_t rb_write(rb_fde_t *, const void *buf, int count);
|
||||||
|
ssize_t rb_writev(rb_fde_t *, struct rb_iovec *vector, int count);
|
||||||
|
|
||||||
|
ssize_t rb_read(rb_fde_t *, void *buf, int count);
|
||||||
|
int rb_pipe(rb_fde_t **, rb_fde_t **, const char *desc);
|
||||||
|
|
||||||
|
int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list, const char *hostname);
|
||||||
|
int rb_ssl_listen(rb_fde_t *, int backlog, int defer_accept);
|
||||||
|
int rb_listen(rb_fde_t *, int backlog, int defer_accept);
|
||||||
|
int rb_remove_ssl_vserver(const char *hostname);
|
||||||
|
|
||||||
|
const char *rb_inet_ntop(int af, const void *src, char *dst, unsigned int size);
|
||||||
|
int rb_inet_pton(int af, const char *src, void *dst);
|
||||||
|
const char *rb_inet_ntop_sock(struct sockaddr *src, char *dst, unsigned int size);
|
||||||
|
int rb_inet_pton_sock(const char *src, struct sockaddr *dst);
|
||||||
|
int rb_getmaxconnect(void);
|
||||||
|
int rb_ignore_errno(int);
|
||||||
|
|
||||||
|
/* Generic wrappers */
|
||||||
|
void rb_setselect(rb_fde_t *, unsigned int type, PF * handler, void *client_data);
|
||||||
|
void rb_init_netio(void);
|
||||||
|
int rb_select(unsigned long);
|
||||||
|
int rb_fd_ssl(rb_fde_t *F);
|
||||||
|
int rb_get_fd(rb_fde_t *F);
|
||||||
|
const char *rb_get_ssl_strerror(rb_fde_t *F);
|
||||||
|
int rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method);
|
||||||
|
|
||||||
|
rb_fde_t *rb_get_fde(int fd);
|
||||||
|
|
||||||
|
int rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasize, pid_t pid);
|
||||||
|
int rb_recv_fd_buf(rb_fde_t *F, void *data, size_t datasize, rb_fde_t **xF, int count);
|
||||||
|
|
||||||
|
void rb_set_type(rb_fde_t *F, uint8_t type);
|
||||||
|
uint8_t rb_get_type(rb_fde_t *F);
|
||||||
|
|
||||||
|
const char *rb_get_iotype(void);
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
RB_PRNG_FILE,
|
||||||
|
#ifdef _WIN32
|
||||||
|
RB_PRNGWIN32,
|
||||||
|
#endif
|
||||||
|
RB_PRNG_DEFAULT,
|
||||||
|
} prng_seed_t;
|
||||||
|
|
||||||
|
int rb_init_prng(const char *path, prng_seed_t seed_type);
|
||||||
|
int rb_get_random(void *buf, size_t len);
|
||||||
|
void rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout);
|
||||||
|
void rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout);
|
||||||
|
int rb_supports_ssl(void);
|
||||||
|
|
||||||
|
unsigned int rb_ssl_handshake_count(rb_fde_t *F);
|
||||||
|
void rb_ssl_clear_handshake_count(rb_fde_t *F);
|
||||||
|
|
||||||
|
|
||||||
|
int rb_pass_fd_to_process(rb_fde_t *, pid_t, rb_fde_t *);
|
||||||
|
rb_fde_t *rb_recv_fd(rb_fde_t *);
|
||||||
|
|
||||||
|
const char *rb_ssl_get_cipher(rb_fde_t *F);
|
||||||
|
|
||||||
|
#endif /* INCLUDED_commio_h */
|
63
libratbox/include/rb_helper.h
Normal file
63
libratbox/include/rb_helper.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: A slightly useful ircd
|
||||||
|
* helper.h: Starts and deals with ircd helpers
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Aaron Sethman <androsyn@ratbox.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: rb_helper.h 26092 2008-09-19 15:13:52Z androsyn $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RB_LIB_H
|
||||||
|
# error "Do not use helper.h directly"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef INCLUDED_helper_h
|
||||||
|
#define INCLUDED_helper_h
|
||||||
|
|
||||||
|
struct _rb_helper;
|
||||||
|
typedef struct _rb_helper rb_helper;
|
||||||
|
|
||||||
|
typedef void rb_helper_cb(rb_helper *);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
rb_helper *rb_helper_start(const char *name, const char *fullpath, rb_helper_cb * read_cb,
|
||||||
|
rb_helper_cb * error_cb);
|
||||||
|
|
||||||
|
rb_helper *rb_helper_child(rb_helper_cb * read_cb, rb_helper_cb * error_cb,
|
||||||
|
log_cb * ilog, restart_cb * irestart, die_cb * idie,
|
||||||
|
size_t lb_heap_size, size_t dh_size, size_t fd_heap_size);
|
||||||
|
|
||||||
|
void rb_helper_restart(rb_helper *helper);
|
||||||
|
#ifdef __GNUC__
|
||||||
|
void
|
||||||
|
rb_helper_write(rb_helper *helper, const char *format, ...)
|
||||||
|
__attribute((format(printf, 2, 3)));
|
||||||
|
void rb_helper_write_queue(rb_helper *helper, const char *format, ...)
|
||||||
|
__attribute((format(printf, 2, 3)));
|
||||||
|
#else
|
||||||
|
void rb_helper_write(rb_helper *helper, const char *format, ...);
|
||||||
|
void rb_helper_write_queue(rb_helper *helper, const char *format, ...);
|
||||||
|
#endif
|
||||||
|
void rb_helper_write_flush(rb_helper *helper);
|
||||||
|
|
||||||
|
void rb_helper_run(rb_helper *helper);
|
||||||
|
void rb_helper_close(rb_helper *helper);
|
||||||
|
int rb_helper_read(rb_helper *helper, void *buf, size_t bufsize);
|
||||||
|
void rb_helper_loop(rb_helper *helper, long delay) __attribute__((noreturn));
|
||||||
|
#endif
|
86
libratbox/include/rb_memory.h
Normal file
86
libratbox/include/rb_memory.h
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: A slightly useful ircd.
|
||||||
|
* memory.h: A header for the memory functions.
|
||||||
|
*
|
||||||
|
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||||
|
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||||
|
* Copyright (C) 2002-2005 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: rb_memory.h 26092 2008-09-19 15:13:52Z androsyn $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RB_LIB_H
|
||||||
|
#error "Do not use rb_memory.h directly"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _RB_MEMORY_H
|
||||||
|
#define _RB_MEMORY_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
void rb_outofmemory(void) __attribute__((noreturn));
|
||||||
|
|
||||||
|
static inline void *
|
||||||
|
rb_malloc(size_t size)
|
||||||
|
{
|
||||||
|
void *ret = calloc(1, size);
|
||||||
|
if(rb_unlikely(ret == NULL))
|
||||||
|
rb_outofmemory();
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *
|
||||||
|
rb_realloc(void *x, size_t y)
|
||||||
|
{
|
||||||
|
void *ret = realloc(x, y);
|
||||||
|
|
||||||
|
if(rb_unlikely(ret == NULL))
|
||||||
|
rb_outofmemory();
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char *
|
||||||
|
rb_strndup(const char *x, size_t y)
|
||||||
|
{
|
||||||
|
char *ret = malloc(y);
|
||||||
|
if(rb_unlikely(ret == NULL))
|
||||||
|
rb_outofmemory();
|
||||||
|
rb_strlcpy(ret, x, y);
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char *
|
||||||
|
rb_strdup(const char *x)
|
||||||
|
{
|
||||||
|
char *ret = malloc(strlen(x) + 1);
|
||||||
|
if(rb_unlikely(ret == NULL))
|
||||||
|
rb_outofmemory();
|
||||||
|
strcpy(ret, x);
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
rb_free(void *ptr)
|
||||||
|
{
|
||||||
|
if(rb_likely(ptr != NULL))
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _I_MEMORY_H */
|
508
libratbox/install-sh
Executable file
508
libratbox/install-sh
Executable file
|
@ -0,0 +1,508 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# install - install a program, script, or datafile
|
||||||
|
|
||||||
|
scriptversion=2014-09-12.12; # UTC
|
||||||
|
|
||||||
|
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||||
|
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||||
|
# following copyright and license.
|
||||||
|
#
|
||||||
|
# Copyright (C) 1994 X Consortium
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to
|
||||||
|
# deal in the Software without restriction, including without limitation the
|
||||||
|
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
# sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||||
|
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Except as contained in this notice, the name of the X Consortium shall not
|
||||||
|
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||||
|
# ings in this Software without prior written authorization from the X Consor-
|
||||||
|
# tium.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# FSF changes to this file are in the public domain.
|
||||||
|
#
|
||||||
|
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||||
|
# 'make' implicit rules from creating a file called install from it
|
||||||
|
# when there is no Makefile.
|
||||||
|
#
|
||||||
|
# This script is compatible with the BSD install script, but was written
|
||||||
|
# from scratch.
|
||||||
|
|
||||||
|
tab=' '
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
IFS=" $tab$nl"
|
||||||
|
|
||||||
|
# Set DOITPROG to "echo" to test this script.
|
||||||
|
|
||||||
|
doit=${DOITPROG-}
|
||||||
|
doit_exec=${doit:-exec}
|
||||||
|
|
||||||
|
# Put in absolute file names if you don't have them in your path;
|
||||||
|
# or use environment vars.
|
||||||
|
|
||||||
|
chgrpprog=${CHGRPPROG-chgrp}
|
||||||
|
chmodprog=${CHMODPROG-chmod}
|
||||||
|
chownprog=${CHOWNPROG-chown}
|
||||||
|
cmpprog=${CMPPROG-cmp}
|
||||||
|
cpprog=${CPPROG-cp}
|
||||||
|
mkdirprog=${MKDIRPROG-mkdir}
|
||||||
|
mvprog=${MVPROG-mv}
|
||||||
|
rmprog=${RMPROG-rm}
|
||||||
|
stripprog=${STRIPPROG-strip}
|
||||||
|
|
||||||
|
posix_mkdir=
|
||||||
|
|
||||||
|
# Desired mode of installed file.
|
||||||
|
mode=0755
|
||||||
|
|
||||||
|
chgrpcmd=
|
||||||
|
chmodcmd=$chmodprog
|
||||||
|
chowncmd=
|
||||||
|
mvcmd=$mvprog
|
||||||
|
rmcmd="$rmprog -f"
|
||||||
|
stripcmd=
|
||||||
|
|
||||||
|
src=
|
||||||
|
dst=
|
||||||
|
dir_arg=
|
||||||
|
dst_arg=
|
||||||
|
|
||||||
|
copy_on_change=false
|
||||||
|
is_target_a_directory=possibly
|
||||||
|
|
||||||
|
usage="\
|
||||||
|
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||||
|
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||||
|
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||||
|
or: $0 [OPTION]... -d DIRECTORIES...
|
||||||
|
|
||||||
|
In the 1st form, copy SRCFILE to DSTFILE.
|
||||||
|
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||||
|
In the 4th, create DIRECTORIES.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--help display this help and exit.
|
||||||
|
--version display version info and exit.
|
||||||
|
|
||||||
|
-c (ignored)
|
||||||
|
-C install only if different (preserve the last data modification time)
|
||||||
|
-d create directories instead of installing files.
|
||||||
|
-g GROUP $chgrpprog installed files to GROUP.
|
||||||
|
-m MODE $chmodprog installed files to MODE.
|
||||||
|
-o USER $chownprog installed files to USER.
|
||||||
|
-s $stripprog installed files.
|
||||||
|
-t DIRECTORY install into DIRECTORY.
|
||||||
|
-T report an error if DSTFILE is a directory.
|
||||||
|
|
||||||
|
Environment variables override the default commands:
|
||||||
|
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||||
|
RMPROG STRIPPROG
|
||||||
|
"
|
||||||
|
|
||||||
|
while test $# -ne 0; do
|
||||||
|
case $1 in
|
||||||
|
-c) ;;
|
||||||
|
|
||||||
|
-C) copy_on_change=true;;
|
||||||
|
|
||||||
|
-d) dir_arg=true;;
|
||||||
|
|
||||||
|
-g) chgrpcmd="$chgrpprog $2"
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
--help) echo "$usage"; exit $?;;
|
||||||
|
|
||||||
|
-m) mode=$2
|
||||||
|
case $mode in
|
||||||
|
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
|
||||||
|
echo "$0: invalid mode: $mode" >&2
|
||||||
|
exit 1;;
|
||||||
|
esac
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-o) chowncmd="$chownprog $2"
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-s) stripcmd=$stripprog;;
|
||||||
|
|
||||||
|
-t)
|
||||||
|
is_target_a_directory=always
|
||||||
|
dst_arg=$2
|
||||||
|
# Protect names problematic for 'test' and other utilities.
|
||||||
|
case $dst_arg in
|
||||||
|
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||||
|
esac
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-T) is_target_a_directory=never;;
|
||||||
|
|
||||||
|
--version) echo "$0 $scriptversion"; exit $?;;
|
||||||
|
|
||||||
|
--) shift
|
||||||
|
break;;
|
||||||
|
|
||||||
|
-*) echo "$0: invalid option: $1" >&2
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
*) break;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# We allow the use of options -d and -T together, by making -d
|
||||||
|
# take the precedence; this is for compatibility with GNU install.
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
if test -n "$dst_arg"; then
|
||||||
|
echo "$0: target directory not allowed when installing a directory." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||||
|
# When -d is used, all remaining arguments are directories to create.
|
||||||
|
# When -t is used, the destination is already specified.
|
||||||
|
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$dst_arg"; then
|
||||||
|
# $@ is not empty: it contains at least $arg.
|
||||||
|
set fnord "$@" "$dst_arg"
|
||||||
|
shift # fnord
|
||||||
|
fi
|
||||||
|
shift # arg
|
||||||
|
dst_arg=$arg
|
||||||
|
# Protect names problematic for 'test' and other utilities.
|
||||||
|
case $dst_arg in
|
||||||
|
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $# -eq 0; then
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
echo "$0: no input file specified." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# It's OK to call 'install-sh -d' without argument.
|
||||||
|
# This can happen when creating conditional directories.
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
if test $# -gt 1 || test "$is_target_a_directory" = always; then
|
||||||
|
if test ! -d "$dst_arg"; then
|
||||||
|
echo "$0: $dst_arg: Is not a directory." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
do_exit='(exit $ret); exit $ret'
|
||||||
|
trap "ret=129; $do_exit" 1
|
||||||
|
trap "ret=130; $do_exit" 2
|
||||||
|
trap "ret=141; $do_exit" 13
|
||||||
|
trap "ret=143; $do_exit" 15
|
||||||
|
|
||||||
|
# Set umask so as not to create temps with too-generous modes.
|
||||||
|
# However, 'strip' requires both read and write access to temps.
|
||||||
|
case $mode in
|
||||||
|
# Optimize common cases.
|
||||||
|
*644) cp_umask=133;;
|
||||||
|
*755) cp_umask=22;;
|
||||||
|
|
||||||
|
*[0-7])
|
||||||
|
if test -z "$stripcmd"; then
|
||||||
|
u_plus_rw=
|
||||||
|
else
|
||||||
|
u_plus_rw='% 200'
|
||||||
|
fi
|
||||||
|
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||||
|
*)
|
||||||
|
if test -z "$stripcmd"; then
|
||||||
|
u_plus_rw=
|
||||||
|
else
|
||||||
|
u_plus_rw=,u+rw
|
||||||
|
fi
|
||||||
|
cp_umask=$mode$u_plus_rw;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
for src
|
||||||
|
do
|
||||||
|
# Protect names problematic for 'test' and other utilities.
|
||||||
|
case $src in
|
||||||
|
-* | [=\(\)!]) src=./$src;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
dst=$src
|
||||||
|
dstdir=$dst
|
||||||
|
test -d "$dstdir"
|
||||||
|
dstdir_status=$?
|
||||||
|
else
|
||||||
|
|
||||||
|
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||||
|
# might cause directories to be created, which would be especially bad
|
||||||
|
# if $src (and thus $dsttmp) contains '*'.
|
||||||
|
if test ! -f "$src" && test ! -d "$src"; then
|
||||||
|
echo "$0: $src does not exist." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dst_arg"; then
|
||||||
|
echo "$0: no destination specified." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
dst=$dst_arg
|
||||||
|
|
||||||
|
# If destination is a directory, append the input filename; won't work
|
||||||
|
# if double slashes aren't ignored.
|
||||||
|
if test -d "$dst"; then
|
||||||
|
if test "$is_target_a_directory" = never; then
|
||||||
|
echo "$0: $dst_arg: Is a directory" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
dstdir=$dst
|
||||||
|
dst=$dstdir/`basename "$src"`
|
||||||
|
dstdir_status=0
|
||||||
|
else
|
||||||
|
dstdir=`dirname "$dst"`
|
||||||
|
test -d "$dstdir"
|
||||||
|
dstdir_status=$?
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
obsolete_mkdir_used=false
|
||||||
|
|
||||||
|
if test $dstdir_status != 0; then
|
||||||
|
case $posix_mkdir in
|
||||||
|
'')
|
||||||
|
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||||
|
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||||
|
umask=`umask`
|
||||||
|
case $stripcmd.$umask in
|
||||||
|
# Optimize common cases.
|
||||||
|
*[2367][2367]) mkdir_umask=$umask;;
|
||||||
|
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||||
|
|
||||||
|
*[0-7])
|
||||||
|
mkdir_umask=`expr $umask + 22 \
|
||||||
|
- $umask % 100 % 40 + $umask % 20 \
|
||||||
|
- $umask % 10 % 4 + $umask % 2
|
||||||
|
`;;
|
||||||
|
*) mkdir_umask=$umask,go-w;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# With -d, create the new directory with the user-specified mode.
|
||||||
|
# Otherwise, rely on $mkdir_umask.
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
mkdir_mode=-m$mode
|
||||||
|
else
|
||||||
|
mkdir_mode=
|
||||||
|
fi
|
||||||
|
|
||||||
|
posix_mkdir=false
|
||||||
|
case $umask in
|
||||||
|
*[123567][0-7][0-7])
|
||||||
|
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||||
|
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# $RANDOM is not portable (e.g. dash); use it when possible to
|
||||||
|
# lower collision chance
|
||||||
|
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||||
|
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||||
|
|
||||||
|
# As "mkdir -p" follows symlinks and we work in /tmp possibly; so
|
||||||
|
# create the $tmpdir first (and fail if unsuccessful) to make sure
|
||||||
|
# that nobody tries to guess the $tmpdir name.
|
||||||
|
if (umask $mkdir_umask &&
|
||||||
|
$mkdirprog $mkdir_mode "$tmpdir" &&
|
||||||
|
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
if test -z "$dir_arg" || {
|
||||||
|
# Check for POSIX incompatibilities with -m.
|
||||||
|
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||||
|
# other-writable bit of parent directory when it shouldn't.
|
||||||
|
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||||
|
test_tmpdir="$tmpdir/a"
|
||||||
|
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
|
||||||
|
case $ls_ld_tmpdir in
|
||||||
|
d????-?r-*) different_mode=700;;
|
||||||
|
d????-?--*) different_mode=755;;
|
||||||
|
*) false;;
|
||||||
|
esac &&
|
||||||
|
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
|
||||||
|
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
|
||||||
|
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
then posix_mkdir=:
|
||||||
|
fi
|
||||||
|
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
|
||||||
|
else
|
||||||
|
# Remove any dirs left behind by ancient mkdir implementations.
|
||||||
|
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
|
||||||
|
fi
|
||||||
|
trap '' 0;;
|
||||||
|
esac;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if
|
||||||
|
$posix_mkdir && (
|
||||||
|
umask $mkdir_umask &&
|
||||||
|
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||||
|
)
|
||||||
|
then :
|
||||||
|
else
|
||||||
|
|
||||||
|
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||||
|
# or it failed possibly due to a race condition. Create the
|
||||||
|
# directory the slow way, step by step, checking for races as we go.
|
||||||
|
|
||||||
|
case $dstdir in
|
||||||
|
/*) prefix='/';;
|
||||||
|
[-=\(\)!]*) prefix='./';;
|
||||||
|
*) prefix='';;
|
||||||
|
esac
|
||||||
|
|
||||||
|
oIFS=$IFS
|
||||||
|
IFS=/
|
||||||
|
set -f
|
||||||
|
set fnord $dstdir
|
||||||
|
shift
|
||||||
|
set +f
|
||||||
|
IFS=$oIFS
|
||||||
|
|
||||||
|
prefixes=
|
||||||
|
|
||||||
|
for d
|
||||||
|
do
|
||||||
|
test X"$d" = X && continue
|
||||||
|
|
||||||
|
prefix=$prefix$d
|
||||||
|
if test -d "$prefix"; then
|
||||||
|
prefixes=
|
||||||
|
else
|
||||||
|
if $posix_mkdir; then
|
||||||
|
(umask=$mkdir_umask &&
|
||||||
|
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||||
|
# Don't fail if two instances are running concurrently.
|
||||||
|
test -d "$prefix" || exit 1
|
||||||
|
else
|
||||||
|
case $prefix in
|
||||||
|
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||||
|
*) qprefix=$prefix;;
|
||||||
|
esac
|
||||||
|
prefixes="$prefixes '$qprefix'"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
prefix=$prefix/
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -n "$prefixes"; then
|
||||||
|
# Don't fail if two instances are running concurrently.
|
||||||
|
(umask $mkdir_umask &&
|
||||||
|
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||||
|
test -d "$dstdir" || exit 1
|
||||||
|
obsolete_mkdir_used=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||||
|
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||||
|
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||||
|
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||||
|
else
|
||||||
|
|
||||||
|
# Make a couple of temp file names in the proper directory.
|
||||||
|
dsttmp=$dstdir/_inst.$$_
|
||||||
|
rmtmp=$dstdir/_rm.$$_
|
||||||
|
|
||||||
|
# Trap to clean up those temp files at exit.
|
||||||
|
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||||
|
|
||||||
|
# Copy the file name to the temp name.
|
||||||
|
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||||
|
|
||||||
|
# and set any options; do chmod last to preserve setuid bits.
|
||||||
|
#
|
||||||
|
# If any of these fail, we abort the whole thing. If we want to
|
||||||
|
# ignore errors from any of these, just make sure not to ignore
|
||||||
|
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||||
|
#
|
||||||
|
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||||
|
|
||||||
|
# If -C, don't bother to copy if it wouldn't change the file.
|
||||||
|
if $copy_on_change &&
|
||||||
|
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||||
|
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||||
|
set -f &&
|
||||||
|
set X $old && old=:$2:$4:$5:$6 &&
|
||||||
|
set X $new && new=:$2:$4:$5:$6 &&
|
||||||
|
set +f &&
|
||||||
|
test "$old" = "$new" &&
|
||||||
|
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
rm -f "$dsttmp"
|
||||||
|
else
|
||||||
|
# Rename the file to the real destination.
|
||||||
|
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||||
|
|
||||||
|
# The rename failed, perhaps because mv can't rename something else
|
||||||
|
# to itself, or perhaps because mv is so ancient that it does not
|
||||||
|
# support -f.
|
||||||
|
{
|
||||||
|
# Now remove or move aside any old file at destination location.
|
||||||
|
# We try this two ways since rm can't unlink itself on some
|
||||||
|
# systems and the destination file might be busy for other
|
||||||
|
# reasons. In this case, the final cleanup might fail but the new
|
||||||
|
# file should still install successfully.
|
||||||
|
{
|
||||||
|
test ! -f "$dst" ||
|
||||||
|
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||||
|
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||||
|
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||||
|
} ||
|
||||||
|
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||||
|
(exit 1); exit 1
|
||||||
|
}
|
||||||
|
} &&
|
||||||
|
|
||||||
|
# Now rename the file to the real destination.
|
||||||
|
$doit $mvcmd "$dsttmp" "$dst"
|
||||||
|
}
|
||||||
|
fi || exit 1
|
||||||
|
|
||||||
|
trap '' 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
11156
libratbox/ltmain.sh
Normal file
11156
libratbox/ltmain.sh
Normal file
File diff suppressed because it is too large
Load diff
215
libratbox/missing
Executable file
215
libratbox/missing
Executable file
|
@ -0,0 +1,215 @@
|
||||||
|
#! /bin/sh
|
||||||
|
# Common wrapper for a few potentially missing GNU programs.
|
||||||
|
|
||||||
|
scriptversion=2013-10-28.13; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
|
||||||
|
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
if test $# -eq 0; then
|
||||||
|
echo 1>&2 "Try '$0 --help' for more information"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
|
||||||
|
--is-lightweight)
|
||||||
|
# Used by our autoconf macros to check whether the available missing
|
||||||
|
# script is modern enough.
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--run)
|
||||||
|
# Back-compat with the calling convention used by older automake.
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
|
||||||
|
-h|--h|--he|--hel|--help)
|
||||||
|
echo "\
|
||||||
|
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||||
|
|
||||||
|
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
|
||||||
|
to PROGRAM being missing or too old.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help display this help and exit
|
||||||
|
-v, --version output version information and exit
|
||||||
|
|
||||||
|
Supported PROGRAM values:
|
||||||
|
aclocal autoconf autoheader autom4te automake makeinfo
|
||||||
|
bison yacc flex lex help2man
|
||||||
|
|
||||||
|
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
|
||||||
|
'g' are ignored when checking the name.
|
||||||
|
|
||||||
|
Send bug reports to <bug-automake@gnu.org>."
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
|
||||||
|
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||||
|
echo "missing $scriptversion (GNU Automake)"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
|
||||||
|
-*)
|
||||||
|
echo 1>&2 "$0: unknown '$1' option"
|
||||||
|
echo 1>&2 "Try '$0 --help' for more information"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Run the given program, remember its exit status.
|
||||||
|
"$@"; st=$?
|
||||||
|
|
||||||
|
# If it succeeded, we are done.
|
||||||
|
test $st -eq 0 && exit 0
|
||||||
|
|
||||||
|
# Also exit now if we it failed (or wasn't found), and '--version' was
|
||||||
|
# passed; such an option is passed most likely to detect whether the
|
||||||
|
# program is present and works.
|
||||||
|
case $2 in --version|--help) exit $st;; esac
|
||||||
|
|
||||||
|
# Exit code 63 means version mismatch. This often happens when the user
|
||||||
|
# tries to use an ancient version of a tool on a file that requires a
|
||||||
|
# minimum version.
|
||||||
|
if test $st -eq 63; then
|
||||||
|
msg="probably too old"
|
||||||
|
elif test $st -eq 127; then
|
||||||
|
# Program was missing.
|
||||||
|
msg="missing on your system"
|
||||||
|
else
|
||||||
|
# Program was found and executed, but failed. Give up.
|
||||||
|
exit $st
|
||||||
|
fi
|
||||||
|
|
||||||
|
perl_URL=http://www.perl.org/
|
||||||
|
flex_URL=http://flex.sourceforge.net/
|
||||||
|
gnu_software_URL=http://www.gnu.org/software
|
||||||
|
|
||||||
|
program_details ()
|
||||||
|
{
|
||||||
|
case $1 in
|
||||||
|
aclocal|automake)
|
||||||
|
echo "The '$1' program is part of the GNU Automake package:"
|
||||||
|
echo "<$gnu_software_URL/automake>"
|
||||||
|
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
|
||||||
|
echo "<$gnu_software_URL/autoconf>"
|
||||||
|
echo "<$gnu_software_URL/m4/>"
|
||||||
|
echo "<$perl_URL>"
|
||||||
|
;;
|
||||||
|
autoconf|autom4te|autoheader)
|
||||||
|
echo "The '$1' program is part of the GNU Autoconf package:"
|
||||||
|
echo "<$gnu_software_URL/autoconf/>"
|
||||||
|
echo "It also requires GNU m4 and Perl in order to run:"
|
||||||
|
echo "<$gnu_software_URL/m4/>"
|
||||||
|
echo "<$perl_URL>"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
give_advice ()
|
||||||
|
{
|
||||||
|
# Normalize program name to check for.
|
||||||
|
normalized_program=`echo "$1" | sed '
|
||||||
|
s/^gnu-//; t
|
||||||
|
s/^gnu//; t
|
||||||
|
s/^g//; t'`
|
||||||
|
|
||||||
|
printf '%s\n' "'$1' is $msg."
|
||||||
|
|
||||||
|
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
|
||||||
|
case $normalized_program in
|
||||||
|
autoconf*)
|
||||||
|
echo "You should only need it if you modified 'configure.ac',"
|
||||||
|
echo "or m4 files included by it."
|
||||||
|
program_details 'autoconf'
|
||||||
|
;;
|
||||||
|
autoheader*)
|
||||||
|
echo "You should only need it if you modified 'acconfig.h' or"
|
||||||
|
echo "$configure_deps."
|
||||||
|
program_details 'autoheader'
|
||||||
|
;;
|
||||||
|
automake*)
|
||||||
|
echo "You should only need it if you modified 'Makefile.am' or"
|
||||||
|
echo "$configure_deps."
|
||||||
|
program_details 'automake'
|
||||||
|
;;
|
||||||
|
aclocal*)
|
||||||
|
echo "You should only need it if you modified 'acinclude.m4' or"
|
||||||
|
echo "$configure_deps."
|
||||||
|
program_details 'aclocal'
|
||||||
|
;;
|
||||||
|
autom4te*)
|
||||||
|
echo "You might have modified some maintainer files that require"
|
||||||
|
echo "the 'autom4te' program to be rebuilt."
|
||||||
|
program_details 'autom4te'
|
||||||
|
;;
|
||||||
|
bison*|yacc*)
|
||||||
|
echo "You should only need it if you modified a '.y' file."
|
||||||
|
echo "You may want to install the GNU Bison package:"
|
||||||
|
echo "<$gnu_software_URL/bison/>"
|
||||||
|
;;
|
||||||
|
lex*|flex*)
|
||||||
|
echo "You should only need it if you modified a '.l' file."
|
||||||
|
echo "You may want to install the Fast Lexical Analyzer package:"
|
||||||
|
echo "<$flex_URL>"
|
||||||
|
;;
|
||||||
|
help2man*)
|
||||||
|
echo "You should only need it if you modified a dependency" \
|
||||||
|
"of a man page."
|
||||||
|
echo "You may want to install the GNU Help2man package:"
|
||||||
|
echo "<$gnu_software_URL/help2man/>"
|
||||||
|
;;
|
||||||
|
makeinfo*)
|
||||||
|
echo "You should only need it if you modified a '.texi' file, or"
|
||||||
|
echo "any other file indirectly affecting the aspect of the manual."
|
||||||
|
echo "You might want to install the Texinfo package:"
|
||||||
|
echo "<$gnu_software_URL/texinfo/>"
|
||||||
|
echo "The spurious makeinfo call might also be the consequence of"
|
||||||
|
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
|
||||||
|
echo "want to install GNU make:"
|
||||||
|
echo "<$gnu_software_URL/make/>"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "You might have modified some files without having the proper"
|
||||||
|
echo "tools for further handling them. Check the 'README' file, it"
|
||||||
|
echo "often tells you about the needed prerequisites for installing"
|
||||||
|
echo "this package. You may also peek at any GNU archive site, in"
|
||||||
|
echo "case some other package contains this missing '$1' program."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
give_advice "$1" | sed -e '1s/^/WARNING: /' \
|
||||||
|
-e '2,$s/^/ /' >&2
|
||||||
|
|
||||||
|
# Propagate the correct exit status (expected to be 127 for a program
|
||||||
|
# not found, 63 for a program that failed due to version mismatch).
|
||||||
|
exit $st
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
736
libratbox/src/Makefile.in
Normal file
736
libratbox/src/Makefile.in
Normal file
|
@ -0,0 +1,736 @@
|
||||||
|
# Makefile.in generated by automake 1.15.1 from Makefile.am.
|
||||||
|
# @configure_input@
|
||||||
|
|
||||||
|
# Copyright (C) 1994-2017 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
@SET_MAKE@
|
||||||
|
|
||||||
|
# $Id: Makefile.am 26046 2008-09-09 16:37:30Z androsyn $
|
||||||
|
|
||||||
|
VPATH = @srcdir@
|
||||||
|
am__is_gnu_make = { \
|
||||||
|
if test -z '$(MAKELEVEL)'; then \
|
||||||
|
false; \
|
||||||
|
elif test -n '$(MAKE_HOST)'; then \
|
||||||
|
true; \
|
||||||
|
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||||
|
true; \
|
||||||
|
else \
|
||||||
|
false; \
|
||||||
|
fi; \
|
||||||
|
}
|
||||||
|
am__make_running_with_option = \
|
||||||
|
case $${target_option-} in \
|
||||||
|
?) ;; \
|
||||||
|
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||||
|
"target option '$${target_option-}' specified" >&2; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
has_opt=no; \
|
||||||
|
sane_makeflags=$$MAKEFLAGS; \
|
||||||
|
if $(am__is_gnu_make); then \
|
||||||
|
sane_makeflags=$$MFLAGS; \
|
||||||
|
else \
|
||||||
|
case $$MAKEFLAGS in \
|
||||||
|
*\\[\ \ ]*) \
|
||||||
|
bs=\\; \
|
||||||
|
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||||
|
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||||
|
esac; \
|
||||||
|
fi; \
|
||||||
|
skip_next=no; \
|
||||||
|
strip_trailopt () \
|
||||||
|
{ \
|
||||||
|
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||||
|
}; \
|
||||||
|
for flg in $$sane_makeflags; do \
|
||||||
|
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||||
|
case $$flg in \
|
||||||
|
*=*|--*) continue;; \
|
||||||
|
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||||
|
-*I?*) strip_trailopt 'I';; \
|
||||||
|
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||||
|
-*O?*) strip_trailopt 'O';; \
|
||||||
|
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||||
|
-*l?*) strip_trailopt 'l';; \
|
||||||
|
-[dEDm]) skip_next=yes;; \
|
||||||
|
-[JT]) skip_next=yes;; \
|
||||||
|
esac; \
|
||||||
|
case $$flg in \
|
||||||
|
*$$target_option*) has_opt=yes; break;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
test $$has_opt = yes
|
||||||
|
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||||
|
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||||
|
pkgdatadir = $(datadir)/@PACKAGE@
|
||||||
|
pkgincludedir = $(includedir)/@PACKAGE@
|
||||||
|
pkglibdir = $(libdir)/@PACKAGE@
|
||||||
|
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||||
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||||
|
install_sh_DATA = $(install_sh) -c -m 644
|
||||||
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
|
transform = $(program_transform_name)
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
build_triplet = @build@
|
||||||
|
host_triplet = @host@
|
||||||
|
subdir = src
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
|
||||||
|
$(top_srcdir)/configure.ac
|
||||||
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
|
$(ACLOCAL_M4)
|
||||||
|
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
||||||
|
mkinstalldirs = $(install_sh) -d
|
||||||
|
CONFIG_HEADER = $(top_builddir)/include/libratbox_config.h
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
CONFIG_CLEAN_VPATH_FILES =
|
||||||
|
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||||
|
am__vpath_adj = case $$p in \
|
||||||
|
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
*) f=$$p;; \
|
||||||
|
esac;
|
||||||
|
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||||
|
am__install_max = 40
|
||||||
|
am__nobase_strip_setup = \
|
||||||
|
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||||
|
am__nobase_strip = \
|
||||||
|
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||||
|
am__nobase_list = $(am__nobase_strip_setup); \
|
||||||
|
for p in $$list; do echo "$$p $$p"; done | \
|
||||||
|
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||||
|
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||||
|
if (++n[$$2] == $(am__install_max)) \
|
||||||
|
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||||
|
END { for (dir in files) print dir, files[dir] }'
|
||||||
|
am__base_list = \
|
||||||
|
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||||
|
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||||
|
am__uninstall_files_from_dir = { \
|
||||||
|
test -z "$$files" \
|
||||||
|
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||||
|
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||||
|
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||||
|
}
|
||||||
|
am__installdirs = "$(DESTDIR)$(libdir)"
|
||||||
|
LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||||
|
libratbox_la_DEPENDENCIES =
|
||||||
|
am_libratbox_la_OBJECTS = unix.lo win32.lo crypt.lo balloc.lo \
|
||||||
|
commio.lo mbedtls.lo openssl.lo gnutls.lo nossl.lo event.lo \
|
||||||
|
ratbox_lib.lo rb_memory.lo linebuf.lo snprintf.lo tools.lo \
|
||||||
|
helper.lo devpoll.lo epoll.lo poll.lo ports.lo sigio.lo \
|
||||||
|
select.lo kqueue.lo rawbuf.lo patricia.lo arc4random.lo \
|
||||||
|
version.lo
|
||||||
|
libratbox_la_OBJECTS = $(am_libratbox_la_OBJECTS)
|
||||||
|
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||||
|
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||||
|
am__v_lt_0 = --silent
|
||||||
|
am__v_lt_1 =
|
||||||
|
libratbox_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||||
|
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||||
|
$(libratbox_la_LDFLAGS) $(LDFLAGS) -o $@
|
||||||
|
AM_V_P = $(am__v_P_@AM_V@)
|
||||||
|
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||||
|
am__v_P_0 = false
|
||||||
|
am__v_P_1 = :
|
||||||
|
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||||
|
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||||
|
am__v_GEN_0 = @echo " GEN " $@;
|
||||||
|
am__v_GEN_1 =
|
||||||
|
AM_V_at = $(am__v_at_@AM_V@)
|
||||||
|
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||||
|
am__v_at_0 = @
|
||||||
|
am__v_at_1 =
|
||||||
|
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
|
||||||
|
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||||
|
am__depfiles_maybe = depfiles
|
||||||
|
am__mv = mv -f
|
||||||
|
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||||
|
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||||
|
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||||
|
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
|
||||||
|
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||||
|
$(AM_CFLAGS) $(CFLAGS)
|
||||||
|
AM_V_CC = $(am__v_CC_@AM_V@)
|
||||||
|
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
|
||||||
|
am__v_CC_0 = @echo " CC " $@;
|
||||||
|
am__v_CC_1 =
|
||||||
|
CCLD = $(CC)
|
||||||
|
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||||
|
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||||
|
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||||
|
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
|
||||||
|
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
|
||||||
|
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||||
|
am__v_CCLD_1 =
|
||||||
|
SOURCES = $(libratbox_la_SOURCES)
|
||||||
|
DIST_SOURCES = $(libratbox_la_SOURCES)
|
||||||
|
am__can_run_installinfo = \
|
||||||
|
case $$AM_UPDATE_INFO_DIR in \
|
||||||
|
n|no|NO) false;; \
|
||||||
|
*) (install-info --version) >/dev/null 2>&1;; \
|
||||||
|
esac
|
||||||
|
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||||
|
# Read a list of newline-separated strings from the standard input,
|
||||||
|
# and print each of them once, without duplicates. Input order is
|
||||||
|
# *not* preserved.
|
||||||
|
am__uniquify_input = $(AWK) '\
|
||||||
|
BEGIN { nonempty = 0; } \
|
||||||
|
{ items[$$0] = 1; nonempty = 1; } \
|
||||||
|
END { if (nonempty) { for (i in items) print i; }; } \
|
||||||
|
'
|
||||||
|
# Make sure the list of sources is unique. This is necessary because,
|
||||||
|
# e.g., the same source file might be shared among _SOURCES variables
|
||||||
|
# for different programs/libraries.
|
||||||
|
am__define_uniq_tagged_files = \
|
||||||
|
list='$(am__tagged_files)'; \
|
||||||
|
unique=`for i in $$list; do \
|
||||||
|
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||||
|
done | $(am__uniquify_input)`
|
||||||
|
ETAGS = etags
|
||||||
|
CTAGS = ctags
|
||||||
|
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
|
||||||
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
ACLOCAL = @ACLOCAL@
|
||||||
|
ALLOCA = @ALLOCA@
|
||||||
|
AMTAR = @AMTAR@
|
||||||
|
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||||
|
AR = @AR@
|
||||||
|
AS = @AS@
|
||||||
|
AUTOCONF = @AUTOCONF@
|
||||||
|
AUTOHEADER = @AUTOHEADER@
|
||||||
|
AUTOMAKE = @AUTOMAKE@
|
||||||
|
AWK = @AWK@
|
||||||
|
CC = @CC@
|
||||||
|
CCDEPMODE = @CCDEPMODE@
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
CP = @CP@
|
||||||
|
CPP = @CPP@
|
||||||
|
CPPFLAGS = @CPPFLAGS@
|
||||||
|
CYGPATH_W = @CYGPATH_W@
|
||||||
|
DEFS = @DEFS@
|
||||||
|
DEPDIR = @DEPDIR@
|
||||||
|
DLLTOOL = @DLLTOOL@
|
||||||
|
DSYMUTIL = @DSYMUTIL@
|
||||||
|
DUMPBIN = @DUMPBIN@
|
||||||
|
ECHO_C = @ECHO_C@
|
||||||
|
ECHO_N = @ECHO_N@
|
||||||
|
ECHO_T = @ECHO_T@
|
||||||
|
EGREP = @EGREP@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
|
FGREP = @FGREP@
|
||||||
|
GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
|
||||||
|
GNUTLS_LIBS = @GNUTLS_LIBS@
|
||||||
|
GREP = @GREP@
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||||
|
LD = @LD@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
LIBOBJS = @LIBOBJS@
|
||||||
|
LIBS = @LIBS@
|
||||||
|
LIBTOOL = @LIBTOOL@
|
||||||
|
LIPO = @LIPO@
|
||||||
|
LN = @LN@
|
||||||
|
LN_S = @LN_S@
|
||||||
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
|
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||||
|
MAINT = @MAINT@
|
||||||
|
MAKEINFO = @MAKEINFO@
|
||||||
|
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||||
|
MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@
|
||||||
|
MBEDTLS_LIBS = @MBEDTLS_LIBS@
|
||||||
|
MKDIR_P = @MKDIR_P@
|
||||||
|
MV = @MV@
|
||||||
|
NM = @NM@
|
||||||
|
NMEDIT = @NMEDIT@
|
||||||
|
OBJDUMP = @OBJDUMP@
|
||||||
|
OBJEXT = @OBJEXT@
|
||||||
|
OTOOL = @OTOOL@
|
||||||
|
OTOOL64 = @OTOOL64@
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||||
|
PACKAGE_NAME = @PACKAGE_NAME@
|
||||||
|
PACKAGE_STRING = @PACKAGE_STRING@
|
||||||
|
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||||
|
PACKAGE_URL = @PACKAGE_URL@
|
||||||
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||||
|
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||||
|
PICFLAGS = @PICFLAGS@
|
||||||
|
PKG_CONFIG = @PKG_CONFIG@
|
||||||
|
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||||
|
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
RB_PREFIX = @RB_PREFIX@
|
||||||
|
RM = @RM@
|
||||||
|
SED = @SED@
|
||||||
|
SEDOBJ = @SEDOBJ@
|
||||||
|
SET_MAKE = @SET_MAKE@
|
||||||
|
SHELL = @SHELL@
|
||||||
|
SSL_CFLAGS = @SSL_CFLAGS@
|
||||||
|
SSL_LIBS = @SSL_LIBS@
|
||||||
|
STRIP = @STRIP@
|
||||||
|
TOUCH = @TOUCH@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
abs_builddir = @abs_builddir@
|
||||||
|
abs_srcdir = @abs_srcdir@
|
||||||
|
abs_top_builddir = @abs_top_builddir@
|
||||||
|
abs_top_srcdir = @abs_top_srcdir@
|
||||||
|
ac_ct_AR = @ac_ct_AR@
|
||||||
|
ac_ct_CC = @ac_ct_CC@
|
||||||
|
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||||
|
am__include = @am__include@
|
||||||
|
am__leading_dot = @am__leading_dot@
|
||||||
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
|
bindir = @bindir@
|
||||||
|
build = @build@
|
||||||
|
build_alias = @build_alias@
|
||||||
|
build_cpu = @build_cpu@
|
||||||
|
build_os = @build_os@
|
||||||
|
build_vendor = @build_vendor@
|
||||||
|
builddir = @builddir@
|
||||||
|
datadir = @datadir@
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
docdir = @docdir@
|
||||||
|
dvidir = @dvidir@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
host = @host@
|
||||||
|
host_alias = @host_alias@
|
||||||
|
host_cpu = @host_cpu@
|
||||||
|
host_os = @host_os@
|
||||||
|
host_vendor = @host_vendor@
|
||||||
|
htmldir = @htmldir@
|
||||||
|
includedir = @includedir@
|
||||||
|
infodir = @infodir@
|
||||||
|
install_sh = @install_sh@
|
||||||
|
libdir = @libdir@
|
||||||
|
libexecdir = @libexecdir@
|
||||||
|
localedir = @localedir@
|
||||||
|
localstatedir = @localstatedir@
|
||||||
|
mandir = @mandir@
|
||||||
|
mkdir_p = @mkdir_p@
|
||||||
|
oldincludedir = @oldincludedir@
|
||||||
|
pdfdir = @pdfdir@
|
||||||
|
prefix = @prefix@
|
||||||
|
program_transform_name = @program_transform_name@
|
||||||
|
psdir = @psdir@
|
||||||
|
runstatedir = @runstatedir@
|
||||||
|
sbindir = @sbindir@
|
||||||
|
sharedstatedir = @sharedstatedir@
|
||||||
|
srcdir = @srcdir@
|
||||||
|
sysconfdir = @sysconfdir@
|
||||||
|
target_alias = @target_alias@
|
||||||
|
top_build_prefix = @top_build_prefix@
|
||||||
|
top_builddir = @top_builddir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
AUTOMAKE_OPTIONS = foreign
|
||||||
|
INCLUDES = -I. -I../include @SSL_CFLAGS@ @GNUTLS_CFLAGS@ @MBEDTLS_CFLAGS@
|
||||||
|
BUILT_SOURCES = version.c
|
||||||
|
libratbox_la_SOURCES = \
|
||||||
|
unix.c \
|
||||||
|
win32.c \
|
||||||
|
crypt.c \
|
||||||
|
balloc.c \
|
||||||
|
commio.c \
|
||||||
|
mbedtls.c \
|
||||||
|
openssl.c \
|
||||||
|
gnutls.c \
|
||||||
|
nossl.c \
|
||||||
|
event.c \
|
||||||
|
ratbox_lib.c \
|
||||||
|
rb_memory.c \
|
||||||
|
linebuf.c \
|
||||||
|
snprintf.c \
|
||||||
|
tools.c \
|
||||||
|
helper.c \
|
||||||
|
devpoll.c \
|
||||||
|
epoll.c \
|
||||||
|
poll.c \
|
||||||
|
ports.c \
|
||||||
|
sigio.c \
|
||||||
|
select.c \
|
||||||
|
kqueue.c \
|
||||||
|
rawbuf.c \
|
||||||
|
patricia.c \
|
||||||
|
arc4random.c \
|
||||||
|
version.c
|
||||||
|
|
||||||
|
libratbox_la_LDFLAGS = @SSL_LIBS@ @GNUTLS_LIBS@ @MBEDTLS_LIBS@ -avoid-version -no-undefined -export-symbols export-syms.txt
|
||||||
|
libratbox_la_LIBADD = @SSL_LIBS@ @GNUTLS_LIBS@ @MBEDTLS_LIBS@
|
||||||
|
lib_LTLIBRARIES = libratbox.la
|
||||||
|
all: $(BUILT_SOURCES)
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) all-am
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.SUFFIXES: .c .lo .o .obj
|
||||||
|
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||||
|
@for dep in $?; do \
|
||||||
|
case '$(am__configure_deps)' in \
|
||||||
|
*$$dep*) \
|
||||||
|
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||||
|
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
|
||||||
|
$(am__cd) $(top_srcdir) && \
|
||||||
|
$(AUTOMAKE) --foreign src/Makefile
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
|
@case '$?' in \
|
||||||
|
*config.status*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||||
|
*) \
|
||||||
|
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||||
|
esac;
|
||||||
|
|
||||||
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
|
||||||
|
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(am__aclocal_m4_deps):
|
||||||
|
|
||||||
|
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
|
||||||
|
list2=; for p in $$list; do \
|
||||||
|
if test -f $$p; then \
|
||||||
|
list2="$$list2 $$p"; \
|
||||||
|
else :; fi; \
|
||||||
|
done; \
|
||||||
|
test -z "$$list2" || { \
|
||||||
|
echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
|
||||||
|
$(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
|
||||||
|
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
|
||||||
|
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
|
||||||
|
}
|
||||||
|
|
||||||
|
uninstall-libLTLIBRARIES:
|
||||||
|
@$(NORMAL_UNINSTALL)
|
||||||
|
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
|
||||||
|
for p in $$list; do \
|
||||||
|
$(am__strip_dir) \
|
||||||
|
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
|
||||||
|
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
|
||||||
|
done
|
||||||
|
|
||||||
|
clean-libLTLIBRARIES:
|
||||||
|
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
|
||||||
|
@list='$(lib_LTLIBRARIES)'; \
|
||||||
|
locs=`for p in $$list; do echo $$p; done | \
|
||||||
|
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
|
||||||
|
sort -u`; \
|
||||||
|
test -z "$$locs" || { \
|
||||||
|
echo rm -f $${locs}; \
|
||||||
|
rm -f $${locs}; \
|
||||||
|
}
|
||||||
|
|
||||||
|
libratbox.la: $(libratbox_la_OBJECTS) $(libratbox_la_DEPENDENCIES) $(EXTRA_libratbox_la_DEPENDENCIES)
|
||||||
|
$(AM_V_CCLD)$(libratbox_la_LINK) -rpath $(libdir) $(libratbox_la_OBJECTS) $(libratbox_la_LIBADD) $(LIBS)
|
||||||
|
|
||||||
|
mostlyclean-compile:
|
||||||
|
-rm -f *.$(OBJEXT)
|
||||||
|
|
||||||
|
distclean-compile:
|
||||||
|
-rm -f *.tab.c
|
||||||
|
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc4random.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/balloc.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commio.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypt.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devpoll.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epoll.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kqueue.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linebuf.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbedtls.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nossl.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/patricia.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poll.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ports.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ratbox_lib.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rawbuf.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rb_memory.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/select.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigio.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snprintf.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tools.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32.Plo@am__quote@
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
|
||||||
|
|
||||||
|
.c.obj:
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||||
|
|
||||||
|
.c.lo:
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
|
||||||
|
|
||||||
|
mostlyclean-libtool:
|
||||||
|
-rm -f *.lo
|
||||||
|
|
||||||
|
clean-libtool:
|
||||||
|
-rm -rf .libs _libs
|
||||||
|
|
||||||
|
ID: $(am__tagged_files)
|
||||||
|
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||||
|
tags: tags-am
|
||||||
|
TAGS: tags
|
||||||
|
|
||||||
|
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||||
|
set x; \
|
||||||
|
here=`pwd`; \
|
||||||
|
$(am__define_uniq_tagged_files); \
|
||||||
|
shift; \
|
||||||
|
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||||
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
|
if test $$# -gt 0; then \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
"$$@" $$unique; \
|
||||||
|
else \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$unique; \
|
||||||
|
fi; \
|
||||||
|
fi
|
||||||
|
ctags: ctags-am
|
||||||
|
|
||||||
|
CTAGS: ctags
|
||||||
|
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||||
|
$(am__define_uniq_tagged_files); \
|
||||||
|
test -z "$(CTAGS_ARGS)$$unique" \
|
||||||
|
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||||
|
$$unique
|
||||||
|
|
||||||
|
GTAGS:
|
||||||
|
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||||
|
&& $(am__cd) $(top_srcdir) \
|
||||||
|
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||||
|
cscopelist: cscopelist-am
|
||||||
|
|
||||||
|
cscopelist-am: $(am__tagged_files)
|
||||||
|
list='$(am__tagged_files)'; \
|
||||||
|
case "$(srcdir)" in \
|
||||||
|
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||||
|
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||||
|
esac; \
|
||||||
|
for i in $$list; do \
|
||||||
|
if test -f "$$i"; then \
|
||||||
|
echo "$(subdir)/$$i"; \
|
||||||
|
else \
|
||||||
|
echo "$$sdir/$$i"; \
|
||||||
|
fi; \
|
||||||
|
done >> $(top_builddir)/cscope.files
|
||||||
|
|
||||||
|
distclean-tags:
|
||||||
|
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
list='$(DISTFILES)'; \
|
||||||
|
dist_files=`for file in $$list; do echo $$file; done | \
|
||||||
|
sed -e "s|^$$srcdirstrip/||;t" \
|
||||||
|
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||||
|
case $$dist_files in \
|
||||||
|
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||||
|
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||||
|
sort -u` ;; \
|
||||||
|
esac; \
|
||||||
|
for file in $$dist_files; do \
|
||||||
|
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||||
|
if test -d "$(distdir)/$$file"; then \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||||
|
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
else \
|
||||||
|
test -f "$(distdir)/$$file" \
|
||||||
|
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
check-am: all-am
|
||||||
|
check: $(BUILT_SOURCES)
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) check-am
|
||||||
|
all-am: Makefile $(LTLIBRARIES)
|
||||||
|
installdirs:
|
||||||
|
for dir in "$(DESTDIR)$(libdir)"; do \
|
||||||
|
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||||
|
done
|
||||||
|
install: $(BUILT_SOURCES)
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) install-am
|
||||||
|
install-exec: install-exec-am
|
||||||
|
install-data: install-data-am
|
||||||
|
uninstall: uninstall-am
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
|
||||||
|
installcheck: installcheck-am
|
||||||
|
install-strip:
|
||||||
|
if test -z '$(STRIP)'; then \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
install; \
|
||||||
|
else \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||||
|
fi
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
|
||||||
|
clean: clean-am
|
||||||
|
|
||||||
|
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
|
||||||
|
mostlyclean-am
|
||||||
|
|
||||||
|
distclean: distclean-am
|
||||||
|
-rm -rf ./$(DEPDIR)
|
||||||
|
-rm -f Makefile
|
||||||
|
distclean-am: clean-am distclean-compile distclean-generic \
|
||||||
|
distclean-tags
|
||||||
|
|
||||||
|
dvi: dvi-am
|
||||||
|
|
||||||
|
dvi-am:
|
||||||
|
|
||||||
|
html: html-am
|
||||||
|
|
||||||
|
html-am:
|
||||||
|
|
||||||
|
info: info-am
|
||||||
|
|
||||||
|
info-am:
|
||||||
|
|
||||||
|
install-data-am:
|
||||||
|
|
||||||
|
install-dvi: install-dvi-am
|
||||||
|
|
||||||
|
install-dvi-am:
|
||||||
|
|
||||||
|
install-exec-am: install-libLTLIBRARIES
|
||||||
|
|
||||||
|
install-html: install-html-am
|
||||||
|
|
||||||
|
install-html-am:
|
||||||
|
|
||||||
|
install-info: install-info-am
|
||||||
|
|
||||||
|
install-info-am:
|
||||||
|
|
||||||
|
install-man:
|
||||||
|
|
||||||
|
install-pdf: install-pdf-am
|
||||||
|
|
||||||
|
install-pdf-am:
|
||||||
|
|
||||||
|
install-ps: install-ps-am
|
||||||
|
|
||||||
|
install-ps-am:
|
||||||
|
|
||||||
|
installcheck-am:
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-am
|
||||||
|
-rm -rf ./$(DEPDIR)
|
||||||
|
-rm -f Makefile
|
||||||
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
|
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||||
|
mostlyclean-libtool
|
||||||
|
|
||||||
|
pdf: pdf-am
|
||||||
|
|
||||||
|
pdf-am:
|
||||||
|
|
||||||
|
ps: ps-am
|
||||||
|
|
||||||
|
ps-am:
|
||||||
|
|
||||||
|
uninstall-am: uninstall-libLTLIBRARIES
|
||||||
|
|
||||||
|
.MAKE: all check install install-am install-strip
|
||||||
|
|
||||||
|
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
|
||||||
|
clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \
|
||||||
|
ctags-am distclean distclean-compile distclean-generic \
|
||||||
|
distclean-libtool distclean-tags distdir dvi dvi-am html \
|
||||||
|
html-am info info-am install install-am install-data \
|
||||||
|
install-data-am install-dvi install-dvi-am install-exec \
|
||||||
|
install-exec-am install-html install-html-am install-info \
|
||||||
|
install-info-am install-libLTLIBRARIES install-man install-pdf \
|
||||||
|
install-pdf-am install-ps install-ps-am install-strip \
|
||||||
|
installcheck installcheck-am installdirs maintainer-clean \
|
||||||
|
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||||
|
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||||
|
tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES
|
||||||
|
|
||||||
|
.PRECIOUS: Makefile
|
||||||
|
|
||||||
|
|
||||||
|
version.c: version.c.SH ../CREDITS
|
||||||
|
$(SHELL) ./version.c.SH
|
||||||
|
$(CP) version.c version.c.last
|
||||||
|
|
||||||
|
version.lo: version.c ../include/serno.h
|
||||||
|
$(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
601
libratbox/src/balloc.c
Normal file
601
libratbox/src/balloc.c
Normal file
|
@ -0,0 +1,601 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: A slightly useful ircd.
|
||||||
|
* balloc.c: A block allocator.
|
||||||
|
*
|
||||||
|
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||||
|
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||||
|
* Copyright (C) 2002-2006 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* Below are the orignal headers from the old blalloc.c
|
||||||
|
*
|
||||||
|
* File: blalloc.c
|
||||||
|
* Owner: Wohali (Joan Touzet)
|
||||||
|
*
|
||||||
|
* Modified 2001/11/29 for mmap() support by Aaron Sethman <androsyn@ratbox.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: balloc.c 26100 2008-09-20 01:27:19Z androsyn $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* About the block allocator
|
||||||
|
*
|
||||||
|
* Basically we have three ways of getting memory off of the operating
|
||||||
|
* system. Below are this list of methods and the order of preference.
|
||||||
|
*
|
||||||
|
* 1. mmap() anonymous pages with the MMAP_ANON flag.
|
||||||
|
* 2. mmap() via the /dev/zero trick.
|
||||||
|
* 3. HeapCreate/HeapAlloc (on win32)
|
||||||
|
* 4. malloc()
|
||||||
|
*
|
||||||
|
* The advantages of 1 and 2 are this. We can munmap() the pages which will
|
||||||
|
* return the pages back to the operating system, thus reducing the size
|
||||||
|
* of the process as the memory is unused. malloc() on many systems just keeps
|
||||||
|
* a heap of memory to itself, which never gets given back to the OS, except on
|
||||||
|
* exit. This of course is bad, if say we have an event that causes us to allocate
|
||||||
|
* say, 200MB of memory, while our normal memory consumption would be 15MB. In the
|
||||||
|
* malloc() case, the amount of memory allocated to our process never goes down, as
|
||||||
|
* malloc() has it locked up in its heap. With the mmap() method, we can munmap()
|
||||||
|
* the block and return it back to the OS, thus causing our memory consumption to go
|
||||||
|
* down after we no longer need it.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <libratbox_config.h>
|
||||||
|
#include <ratbox_lib.h>
|
||||||
|
|
||||||
|
#ifndef NOBALLOC
|
||||||
|
#ifdef HAVE_MMAP /* We've got mmap() that is good */
|
||||||
|
#include <sys/mman.h>
|
||||||
|
/* HP-UX sucks */
|
||||||
|
#ifdef MAP_ANONYMOUS
|
||||||
|
#ifndef MAP_ANON
|
||||||
|
#define MAP_ANON MAP_ANONYMOUS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static uintptr_t offset_pad;
|
||||||
|
|
||||||
|
/* status information for an allocated block in heap */
|
||||||
|
struct rb_heap_block
|
||||||
|
{
|
||||||
|
size_t alloc_size;
|
||||||
|
rb_dlink_node node;
|
||||||
|
unsigned long free_count;
|
||||||
|
void *elems; /* Points to allocated memory */
|
||||||
|
};
|
||||||
|
typedef struct rb_heap_block rb_heap_block;
|
||||||
|
|
||||||
|
/* information for the root node of the heap */
|
||||||
|
struct rb_bh
|
||||||
|
{
|
||||||
|
rb_dlink_node hlist;
|
||||||
|
size_t elemSize; /* Size of each element to be stored */
|
||||||
|
unsigned long elemsPerBlock; /* Number of elements per block */
|
||||||
|
rb_dlink_list block_list;
|
||||||
|
rb_dlink_list free_list;
|
||||||
|
char *desc;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef NOBALLOC
|
||||||
|
static int newblock(rb_bh *bh);
|
||||||
|
static void rb_bh_gc_event(void *unused);
|
||||||
|
#endif /* !NOBALLOC */
|
||||||
|
static rb_dlink_list *heap_lists;
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
static HANDLE block_heap;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define rb_bh_fail(x) _rb_bh_fail(x, __FILE__, __LINE__)
|
||||||
|
|
||||||
|
static void __attribute__((noreturn))
|
||||||
|
_rb_bh_fail(const char *reason, const char *file, int line)
|
||||||
|
{
|
||||||
|
rb_lib_log("rb_heap_blockheap failure: %s (%s:%d)", reason, file, line);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NOBALLOC
|
||||||
|
/*
|
||||||
|
* static inline void free_block(void *ptr, size_t size)
|
||||||
|
*
|
||||||
|
* Inputs: The block and its size
|
||||||
|
* Output: None
|
||||||
|
* Side Effects: Returns memory for the block back to the OS
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
free_block(void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_MMAP
|
||||||
|
munmap(ptr, size);
|
||||||
|
#else
|
||||||
|
#ifdef _WIN32
|
||||||
|
HeapFree(block_heap, 0, ptr);
|
||||||
|
#else
|
||||||
|
free(ptr);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif /* !NOBALLOC */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void rb_init_bh(void)
|
||||||
|
*
|
||||||
|
* Inputs: None
|
||||||
|
* Outputs: None
|
||||||
|
* Side Effects: Initializes the block heap
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_init_bh(void)
|
||||||
|
{
|
||||||
|
heap_lists = rb_malloc(sizeof(rb_dlink_list));
|
||||||
|
offset_pad = sizeof(void *);
|
||||||
|
/* XXX if you get SIGBUS when trying to use a long long..here is where you need to
|
||||||
|
* fix your shit
|
||||||
|
*/
|
||||||
|
#ifdef __sparc__
|
||||||
|
if((offset_pad % __alignof__(long long)) != 0)
|
||||||
|
{
|
||||||
|
offset_pad += __alignof__(long long);
|
||||||
|
offset_pad &= ~(__alignof__(long long) - 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NOBALLOC
|
||||||
|
#ifdef _WIN32
|
||||||
|
block_heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
|
||||||
|
#endif
|
||||||
|
rb_event_addish("rb_bh_gc_event", rb_bh_gc_event, NULL, 300);
|
||||||
|
#endif /* !NOBALLOC */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NOBALLOC
|
||||||
|
/*
|
||||||
|
* static inline void *get_block(size_t size)
|
||||||
|
*
|
||||||
|
* Input: Size of block to allocate
|
||||||
|
* Output: Pointer to new block
|
||||||
|
* Side Effects: None
|
||||||
|
*/
|
||||||
|
static inline void *
|
||||||
|
get_block(size_t size)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
#ifdef HAVE_MMAP
|
||||||
|
#ifdef MAP_ANON
|
||||||
|
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||||
|
#else
|
||||||
|
int zero_fd;
|
||||||
|
zero_fd = open("/dev/zero", O_RDWR);
|
||||||
|
if(zero_fd < 0)
|
||||||
|
rb_bh_fail("Failed opening /dev/zero");
|
||||||
|
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
|
||||||
|
close(zero_fd);
|
||||||
|
#endif /* MAP_ANON */
|
||||||
|
if(ptr == MAP_FAILED)
|
||||||
|
ptr = NULL;
|
||||||
|
#else
|
||||||
|
#ifdef _WIN32
|
||||||
|
ptr = HeapAlloc(block_heap, 0, size);
|
||||||
|
#else
|
||||||
|
ptr = malloc(size);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return (ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_bh_gc_event(void *unused)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
RB_DLINK_FOREACH(ptr, heap_lists->head)
|
||||||
|
{
|
||||||
|
rb_bh_gc(ptr->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************ */
|
||||||
|
/* FUNCTION DOCUMENTATION: */
|
||||||
|
/* newblock */
|
||||||
|
/* Description: */
|
||||||
|
/* Allocates a new block for addition to a blockheap */
|
||||||
|
/* Parameters: */
|
||||||
|
/* bh (IN): Pointer to parent blockheap. */
|
||||||
|
/* Returns: */
|
||||||
|
/* 0 if successful, 1 if not */
|
||||||
|
/* ************************************************************************ */
|
||||||
|
|
||||||
|
static int
|
||||||
|
newblock(rb_bh *bh)
|
||||||
|
{
|
||||||
|
rb_heap_block *b;
|
||||||
|
unsigned long i;
|
||||||
|
uintptr_t offset;
|
||||||
|
rb_dlink_node *node;
|
||||||
|
/* Setup the initial data structure. */
|
||||||
|
b = rb_malloc(sizeof(rb_heap_block));
|
||||||
|
|
||||||
|
b->alloc_size = bh->elemsPerBlock * bh->elemSize;
|
||||||
|
|
||||||
|
b->elems = get_block(b->alloc_size);
|
||||||
|
if(rb_unlikely(b->elems == NULL))
|
||||||
|
{
|
||||||
|
rb_free(b);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
offset = (uintptr_t)b->elems;
|
||||||
|
/* Setup our blocks now */
|
||||||
|
for(i = 0; i < bh->elemsPerBlock; i++, offset += bh->elemSize)
|
||||||
|
{
|
||||||
|
*((void **)offset) = b;
|
||||||
|
node = (void *)(offset + offset_pad);
|
||||||
|
rb_dlinkAdd((void *)offset, node, &bh->free_list);
|
||||||
|
}
|
||||||
|
rb_dlinkAdd(b, &b->node, &bh->block_list);
|
||||||
|
b->free_count = bh->elemsPerBlock;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
#endif /* !NOBALLOC */
|
||||||
|
|
||||||
|
/* ************************************************************************ */
|
||||||
|
/* FUNCTION DOCUMENTATION: */
|
||||||
|
/* rb_bh_create */
|
||||||
|
/* Description: */
|
||||||
|
/* Creates a new blockheap from which smaller blocks can be allocated. */
|
||||||
|
/* Intended to be used instead of multiple calls to malloc() when */
|
||||||
|
/* performance is an issue. */
|
||||||
|
/* Parameters: */
|
||||||
|
/* elemsize (IN): Size of the basic element to be stored */
|
||||||
|
/* elemsperblock (IN): Number of elements to be stored in a single block */
|
||||||
|
/* of memory. When the blockheap runs out of free memory, it will */
|
||||||
|
/* allocate elemsize * elemsperblock more. */
|
||||||
|
/* Returns: */
|
||||||
|
/* Pointer to new rb_bh, or NULL if unsuccessful */
|
||||||
|
/* ************************************************************************ */
|
||||||
|
rb_bh *
|
||||||
|
rb_bh_create(size_t elemsize, int elemsperblock, const char *desc)
|
||||||
|
{
|
||||||
|
rb_bh *bh;
|
||||||
|
lrb_assert(elemsize > 0 && elemsperblock > 0);
|
||||||
|
lrb_assert(elemsize >= sizeof(rb_dlink_node));
|
||||||
|
|
||||||
|
/* Catch idiotic requests up front */
|
||||||
|
if((elemsize == 0) || (elemsperblock <= 0))
|
||||||
|
{
|
||||||
|
rb_bh_fail("Attempting to rb_bh_create idiotic sizes");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(elemsize < sizeof(rb_dlink_node))
|
||||||
|
rb_bh_fail("Attempt to rb_bh_create smaller than sizeof(rb_dlink_node)");
|
||||||
|
|
||||||
|
/* Allocate our new rb_bh */
|
||||||
|
bh = rb_malloc(sizeof(rb_bh));
|
||||||
|
#ifndef NOBALLOC
|
||||||
|
elemsize += offset_pad;
|
||||||
|
if((elemsize % sizeof(void *)) != 0)
|
||||||
|
{
|
||||||
|
/* Pad to even pointer boundary */
|
||||||
|
elemsize += sizeof(void *);
|
||||||
|
elemsize &= ~(sizeof(void *) - 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bh->elemSize = elemsize;
|
||||||
|
bh->elemsPerBlock = elemsperblock;
|
||||||
|
if(desc != NULL)
|
||||||
|
bh->desc = rb_strdup(desc);
|
||||||
|
|
||||||
|
#ifndef NOBALLOC
|
||||||
|
/* Be sure our malloc was successful */
|
||||||
|
if(newblock(bh))
|
||||||
|
{
|
||||||
|
if(bh != NULL)
|
||||||
|
free(bh);
|
||||||
|
rb_lib_log("newblock() failed");
|
||||||
|
rb_outofmemory(); /* die.. out of memory */
|
||||||
|
}
|
||||||
|
#endif /* !NOBALLOC */
|
||||||
|
|
||||||
|
if(bh == NULL)
|
||||||
|
{
|
||||||
|
rb_bh_fail("bh == NULL when it shouldn't be");
|
||||||
|
}
|
||||||
|
rb_dlinkAdd(bh, &bh->hlist, heap_lists);
|
||||||
|
return (bh);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************ */
|
||||||
|
/* FUNCTION DOCUMENTATION: */
|
||||||
|
/* rb_bh_alloc */
|
||||||
|
/* Description: */
|
||||||
|
/* Returns a pointer to a struct within our rb_bh that's free for */
|
||||||
|
/* the taking. */
|
||||||
|
/* Parameters: */
|
||||||
|
/* bh (IN): Pointer to the Blockheap. */
|
||||||
|
/* Returns: */
|
||||||
|
/* Pointer to a structure (void *), or NULL if unsuccessful. */
|
||||||
|
/* ************************************************************************ */
|
||||||
|
|
||||||
|
void *
|
||||||
|
rb_bh_alloc(rb_bh *bh)
|
||||||
|
{
|
||||||
|
#ifndef NOBALLOC
|
||||||
|
rb_dlink_node *new_node;
|
||||||
|
rb_heap_block **block;
|
||||||
|
void *ptr;
|
||||||
|
#endif
|
||||||
|
lrb_assert(bh != NULL);
|
||||||
|
if(rb_unlikely(bh == NULL))
|
||||||
|
{
|
||||||
|
rb_bh_fail("Cannot allocate if bh == NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NOBALLOC
|
||||||
|
return (rb_malloc(bh->elemSize));
|
||||||
|
#else
|
||||||
|
if(bh->free_list.head == NULL)
|
||||||
|
{
|
||||||
|
/* Allocate new block and assign */
|
||||||
|
/* newblock returns 1 if unsuccessful, 0 if not */
|
||||||
|
|
||||||
|
if(rb_unlikely(newblock(bh)))
|
||||||
|
{
|
||||||
|
rb_lib_log("newblock() failed");
|
||||||
|
rb_outofmemory(); /* Well that didn't work either...bail */
|
||||||
|
}
|
||||||
|
if(bh->free_list.head == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("out of memory after newblock()...");
|
||||||
|
rb_outofmemory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new_node = bh->free_list.head;
|
||||||
|
block = (rb_heap_block **) new_node->data;
|
||||||
|
ptr = (void *)((uintptr_t)new_node->data + (uintptr_t)offset_pad);
|
||||||
|
rb_dlinkDelete(new_node, &bh->free_list);
|
||||||
|
(*block)->free_count--;
|
||||||
|
memset(ptr, 0, bh->elemSize - offset_pad);
|
||||||
|
return (ptr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ************************************************************************ */
|
||||||
|
/* FUNCTION DOCUMENTATION: */
|
||||||
|
/* rb_bh_free */
|
||||||
|
/* Description: */
|
||||||
|
/* Returns an element to the free pool, does not free() */
|
||||||
|
/* Parameters: */
|
||||||
|
/* bh (IN): Pointer to rb_bh containing element */
|
||||||
|
/* ptr (in): Pointer to element to be "freed" */
|
||||||
|
/* Returns: */
|
||||||
|
/* 0 if successful, 1 if element not contained within rb_bh. */
|
||||||
|
/* ************************************************************************ */
|
||||||
|
int
|
||||||
|
rb_bh_free(rb_bh *bh, void *ptr)
|
||||||
|
{
|
||||||
|
#ifndef NOBALLOC
|
||||||
|
rb_heap_block *block;
|
||||||
|
void *data;
|
||||||
|
#endif
|
||||||
|
lrb_assert(bh != NULL);
|
||||||
|
lrb_assert(ptr != NULL);
|
||||||
|
|
||||||
|
if(rb_unlikely(bh == NULL))
|
||||||
|
{
|
||||||
|
rb_lib_log("balloc.c:rb_bhFree() bh == NULL");
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rb_unlikely(ptr == NULL))
|
||||||
|
{
|
||||||
|
rb_lib_log("balloc.rb_bhFree() ptr == NULL");
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NOBALLOC
|
||||||
|
rb_free(ptr);
|
||||||
|
#else
|
||||||
|
data = (void *)((uintptr_t)ptr - (uintptr_t)offset_pad);
|
||||||
|
block = *(rb_heap_block **) data;
|
||||||
|
/* XXX */
|
||||||
|
if(rb_unlikely
|
||||||
|
(!((uintptr_t)ptr >= (uintptr_t)block->elems
|
||||||
|
&& (uintptr_t)ptr < (uintptr_t)block->elems + (uintptr_t)block->alloc_size)))
|
||||||
|
{
|
||||||
|
rb_bh_fail("rb_bh_free() bogus pointer");
|
||||||
|
}
|
||||||
|
block->free_count++;
|
||||||
|
|
||||||
|
rb_dlinkAdd(data, (rb_dlink_node *)ptr, &bh->free_list);
|
||||||
|
#endif /* !NOBALLOC */
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ************************************************************************ */
|
||||||
|
/* FUNCTION DOCUMENTATION: */
|
||||||
|
/* rb_bhDestroy */
|
||||||
|
/* Description: */
|
||||||
|
/* Completely free()s a rb_bh. Use for cleanup. */
|
||||||
|
/* Parameters: */
|
||||||
|
/* bh (IN): Pointer to the rb_bh to be destroyed. */
|
||||||
|
/* Returns: */
|
||||||
|
/* 0 if successful, 1 if bh == NULL */
|
||||||
|
/* ************************************************************************ */
|
||||||
|
int
|
||||||
|
rb_bh_destroy(rb_bh *bh)
|
||||||
|
{
|
||||||
|
#ifndef NOBALLOC
|
||||||
|
rb_dlink_node *ptr, *next;
|
||||||
|
rb_heap_block *b;
|
||||||
|
#endif
|
||||||
|
if(bh == NULL)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
#ifndef NOBALLOC
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next, bh->block_list.head)
|
||||||
|
{
|
||||||
|
b = ptr->data;
|
||||||
|
free_block(b->elems, b->alloc_size);
|
||||||
|
rb_free(b);
|
||||||
|
}
|
||||||
|
#endif /* !NOBALLOC */
|
||||||
|
|
||||||
|
rb_dlinkDelete(&bh->hlist, heap_lists);
|
||||||
|
rb_free(bh->desc);
|
||||||
|
rb_free(bh);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_bh_usage(rb_bh *bh, size_t *bused, size_t *bfree, size_t *bmemusage, const char **desc)
|
||||||
|
{
|
||||||
|
#ifndef NOBALLOC
|
||||||
|
size_t used, freem, memusage;
|
||||||
|
|
||||||
|
if(bh == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
freem = rb_dlink_list_length(&bh->free_list);
|
||||||
|
used = (rb_dlink_list_length(&bh->block_list) * bh->elemsPerBlock) - freem;
|
||||||
|
memusage = used * bh->elemSize;
|
||||||
|
if(bused != NULL)
|
||||||
|
*bused = used;
|
||||||
|
if(bfree != NULL)
|
||||||
|
*bfree = freem;
|
||||||
|
if(bmemusage != NULL)
|
||||||
|
*bmemusage = memusage;
|
||||||
|
if(desc != NULL)
|
||||||
|
*desc = bh->desc;
|
||||||
|
#else
|
||||||
|
if(bused != NULL)
|
||||||
|
*bused = 0;
|
||||||
|
if(bfree != NULL)
|
||||||
|
*bfree = 0;
|
||||||
|
if(bmemusage != NULL)
|
||||||
|
*bmemusage = 0;
|
||||||
|
if(desc != NULL)
|
||||||
|
*desc = "no blockheap";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_bh_usage_all(rb_bh_usage_cb *cb, void *data)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
rb_bh *bh;
|
||||||
|
size_t used, freem, memusage, heapalloc;
|
||||||
|
static const char *unnamed = "(unnamed_heap)";
|
||||||
|
const char *desc = unnamed;
|
||||||
|
|
||||||
|
if(cb == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, heap_lists->head)
|
||||||
|
{
|
||||||
|
bh = (rb_bh *)ptr->data;
|
||||||
|
freem = rb_dlink_list_length(&bh->free_list);
|
||||||
|
used = (rb_dlink_list_length(&bh->block_list) * bh->elemsPerBlock) - freem;
|
||||||
|
memusage = used * bh->elemSize;
|
||||||
|
heapalloc = (freem + used) * bh->elemSize;
|
||||||
|
if(bh->desc != NULL)
|
||||||
|
desc = bh->desc;
|
||||||
|
cb(used, freem, memusage, heapalloc, desc, data);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_bh_total_usage(size_t *total_alloc, size_t *total_used)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
size_t total_memory = 0, used_memory = 0, used, freem;
|
||||||
|
rb_bh *bh;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, heap_lists->head)
|
||||||
|
{
|
||||||
|
bh = (rb_bh *)ptr->data;
|
||||||
|
freem = rb_dlink_list_length(&bh->free_list);
|
||||||
|
used = (rb_dlink_list_length(&bh->block_list) * bh->elemsPerBlock) - freem;
|
||||||
|
used_memory += used * bh->elemSize;
|
||||||
|
total_memory += (freem + used) * bh->elemSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(total_alloc != NULL)
|
||||||
|
*total_alloc = total_memory;
|
||||||
|
if(total_used != NULL)
|
||||||
|
*total_used = used_memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NOBALLOC
|
||||||
|
int
|
||||||
|
rb_bh_gc(rb_bh *bh)
|
||||||
|
{
|
||||||
|
rb_heap_block *b;
|
||||||
|
rb_dlink_node *ptr, *next;
|
||||||
|
unsigned long i;
|
||||||
|
uintptr_t offset;
|
||||||
|
|
||||||
|
if(bh == NULL)
|
||||||
|
{
|
||||||
|
/* somebody is smoking some craq..(probably lee, but don't tell him that) */
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rb_dlink_list_length(&bh->free_list) < bh->elemsPerBlock)
|
||||||
|
|| rb_dlink_list_length(&bh->block_list) == 1)
|
||||||
|
{
|
||||||
|
/* There couldn't possibly be an entire free block. Return. */
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next, bh->block_list.head)
|
||||||
|
{
|
||||||
|
b = ptr->data;
|
||||||
|
if(rb_dlink_list_length(&bh->block_list) == 1)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
if(b->free_count == bh->elemsPerBlock)
|
||||||
|
{
|
||||||
|
/* i'm seriously going to hell for this.. */
|
||||||
|
|
||||||
|
offset = (uintptr_t)b->elems;
|
||||||
|
for(i = 0; i < bh->elemsPerBlock; i++, offset += (uintptr_t)bh->elemSize)
|
||||||
|
{
|
||||||
|
rb_dlinkDelete((rb_dlink_node *)(offset + offset_pad),
|
||||||
|
&bh->free_list);
|
||||||
|
}
|
||||||
|
rb_dlinkDelete(&b->node, &bh->block_list);
|
||||||
|
free_block(b->elems, b->alloc_size);
|
||||||
|
rb_free(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
#endif /* !NOBALLOC */
|
2279
libratbox/src/commio.c
Normal file
2279
libratbox/src/commio.c
Normal file
File diff suppressed because it is too large
Load diff
2313
libratbox/src/crypt.c
Normal file
2313
libratbox/src/crypt.c
Normal file
File diff suppressed because it is too large
Load diff
170
libratbox/src/export-syms.txt
Normal file
170
libratbox/src/export-syms.txt
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
rb_bh_alloc
|
||||||
|
rb_bh_create
|
||||||
|
rb_bh_destroy
|
||||||
|
rb_bh_free
|
||||||
|
rb_bh_gc
|
||||||
|
rb_bh_total_usage
|
||||||
|
rb_bh_usage
|
||||||
|
rb_bh_usage_all
|
||||||
|
rb_init_bh
|
||||||
|
rb_accept_tcp
|
||||||
|
rb_checktimeouts
|
||||||
|
rb_close
|
||||||
|
rb_connect_sockaddr
|
||||||
|
rb_connect_tcp
|
||||||
|
rb_connect_tcp_ssl
|
||||||
|
rb_dump_fd
|
||||||
|
rb_errstr
|
||||||
|
rb_fd_ssl
|
||||||
|
rb_fdlist_init
|
||||||
|
rb_get_fd
|
||||||
|
rb_get_fde
|
||||||
|
rb_get_iotype
|
||||||
|
rb_get_random
|
||||||
|
rb_get_sockerr
|
||||||
|
rb_get_ssl_certfp
|
||||||
|
rb_get_ssl_strerror
|
||||||
|
rb_get_type
|
||||||
|
rb_getmaxconnect
|
||||||
|
rb_ignore_errno
|
||||||
|
rb_inet_ntop
|
||||||
|
rb_inet_ntop_sock
|
||||||
|
rb_inet_pton
|
||||||
|
rb_inet_pton_sock
|
||||||
|
rb_init_netio
|
||||||
|
rb_init_prng
|
||||||
|
rb_listen
|
||||||
|
rb_note
|
||||||
|
rb_open
|
||||||
|
rb_pipe
|
||||||
|
rb_read
|
||||||
|
rb_recv_fd_buf
|
||||||
|
rb_select
|
||||||
|
rb_send_fd_buf
|
||||||
|
rb_set_buffers
|
||||||
|
rb_set_nb
|
||||||
|
rb_set_type
|
||||||
|
rb_setselect
|
||||||
|
rb_settimeout
|
||||||
|
rb_setup_fd
|
||||||
|
rb_setup_ssl_server
|
||||||
|
rb_setup_ssl_server_hostname
|
||||||
|
rb_remove_ssl_vserver
|
||||||
|
rb_socket
|
||||||
|
rb_socketpair
|
||||||
|
rb_ssl_listen
|
||||||
|
rb_ssl_start_accepted
|
||||||
|
rb_ssl_start_connected
|
||||||
|
rb_write
|
||||||
|
rb_writev
|
||||||
|
rb_crypt
|
||||||
|
rb_dump_events
|
||||||
|
rb_event_add
|
||||||
|
rb_event_addish
|
||||||
|
rb_event_addonce
|
||||||
|
rb_event_delete
|
||||||
|
rb_event_find_delete
|
||||||
|
rb_event_init
|
||||||
|
rb_event_next
|
||||||
|
rb_event_run
|
||||||
|
rb_event_update
|
||||||
|
rb_run_event
|
||||||
|
rb_helper_child
|
||||||
|
rb_helper_close
|
||||||
|
rb_helper_loop
|
||||||
|
rb_helper_read
|
||||||
|
rb_helper_restart
|
||||||
|
rb_helper_run
|
||||||
|
rb_helper_start
|
||||||
|
rb_helper_write
|
||||||
|
rb_helper_write_queue
|
||||||
|
rb_count_rb_linebuf_memory
|
||||||
|
rb_linebuf_attach
|
||||||
|
rb_linebuf_donebuf
|
||||||
|
rb_linebuf_flush
|
||||||
|
rb_linebuf_get
|
||||||
|
rb_linebuf_init
|
||||||
|
rb_linebuf_newbuf
|
||||||
|
rb_linebuf_parse
|
||||||
|
rb_linebuf_put
|
||||||
|
rb_linebuf_putbuf
|
||||||
|
rb_linebuf_putmsg
|
||||||
|
make_and_lookup
|
||||||
|
make_and_lookup_ip
|
||||||
|
rb_clear_patricia
|
||||||
|
rb_destroy_patricia
|
||||||
|
rb_init_patricia
|
||||||
|
rb_match_exact_string
|
||||||
|
rb_match_ip
|
||||||
|
rb_match_ip_exact
|
||||||
|
rb_match_string
|
||||||
|
rb_new_patricia
|
||||||
|
rb_patricia_lookup
|
||||||
|
rb_patricia_process
|
||||||
|
rb_patricia_remove
|
||||||
|
rb_patricia_search_best
|
||||||
|
rb_patricia_search_best2
|
||||||
|
rb_patricia_search_exact
|
||||||
|
rb_base64_decode
|
||||||
|
rb_base64_encode
|
||||||
|
rb_ctime
|
||||||
|
rb_current_time
|
||||||
|
rb_current_time_tv
|
||||||
|
rb_date
|
||||||
|
rb_lib_die
|
||||||
|
rb_lib_init
|
||||||
|
rb_lib_log
|
||||||
|
rb_lib_loop
|
||||||
|
rb_lib_restart
|
||||||
|
rb_lib_version
|
||||||
|
rb_set_time
|
||||||
|
rb_strtok_r
|
||||||
|
rb_free_rawbuffer
|
||||||
|
rb_init_rawbuffers
|
||||||
|
rb_new_rawbuffer
|
||||||
|
rb_rawbuf_append
|
||||||
|
rb_rawbuf_flush
|
||||||
|
rb_rawbuf_get
|
||||||
|
rb_rawbuf_length
|
||||||
|
rb_outofmemory
|
||||||
|
rb_snprintf
|
||||||
|
rb_snprintf_append
|
||||||
|
rb_sprintf
|
||||||
|
rb_sprintf_append
|
||||||
|
rb_vsnprintf
|
||||||
|
rb_vsnprintf_append
|
||||||
|
rb_vsprintf
|
||||||
|
rb_vsprintf_append
|
||||||
|
rb_free_rb_dlink_node
|
||||||
|
rb_init_rb_dlink_nodes
|
||||||
|
rb_make_rb_dlink_node
|
||||||
|
rb_string_to_array
|
||||||
|
rb_strlcat
|
||||||
|
rb_strlcpy
|
||||||
|
rb_strnlen
|
||||||
|
rb_gettimeofday
|
||||||
|
rb_sleep
|
||||||
|
rb_spawn_process
|
||||||
|
rb_supports_ssl
|
||||||
|
rb_ssl_handshake_count
|
||||||
|
rb_ssl_clear_handshake_count
|
||||||
|
rb_strerror
|
||||||
|
rb_kill
|
||||||
|
rb_setenv
|
||||||
|
rb_getpid
|
||||||
|
rb_waitpid
|
||||||
|
rb_basename
|
||||||
|
rb_dirname
|
||||||
|
rb_ssl_get_cipher
|
||||||
|
rb_zstring_alloc
|
||||||
|
rb_zstring_append_from_c
|
||||||
|
rb_zstring_append_from_zstring
|
||||||
|
rb_zstring_deserialize
|
||||||
|
rb_zstring_free
|
||||||
|
rb_zstring_from_c
|
||||||
|
rb_zstring_from_c_len
|
||||||
|
rb_zstring_len
|
||||||
|
rb_zstring_serialized
|
||||||
|
rb_zstring_to_c
|
||||||
|
rb_zstring_to_c_alloc
|
||||||
|
rb_zstring_to_ptr
|
917
libratbox/src/gnutls.c
Normal file
917
libratbox/src/gnutls.c
Normal file
|
@ -0,0 +1,917 @@
|
||||||
|
/*
|
||||||
|
* libratbox: a library used by ircd-ratbox and other things
|
||||||
|
* gnutls.c: gnutls related code
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2008 ircd-ratbox development team
|
||||||
|
* Copyright (C) 2007-2008 Aaron Sethman <androsyn@ratbox.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libratbox_config.h>
|
||||||
|
#include <ratbox_lib.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_GNUTLS
|
||||||
|
|
||||||
|
#include <commio-int.h>
|
||||||
|
#include <commio-ssl.h>
|
||||||
|
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
|
||||||
|
#include <gnutls/abstract.h>
|
||||||
|
#include <gnutls/x509.h>
|
||||||
|
|
||||||
|
#if (GNUTLS_VERSION_MAJOR < 3)
|
||||||
|
# include <gcrypt.h>
|
||||||
|
#else
|
||||||
|
# include <gnutls/crypto.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gnutls_ratbox.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
RB_FD_TLS_DIRECTION_IN = 0,
|
||||||
|
RB_FD_TLS_DIRECTION_OUT = 1
|
||||||
|
} rb_fd_tls_direction;
|
||||||
|
|
||||||
|
#define SSL_P(x) *((gnutls_session_t *) ((x)->ssl))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Server side variables
|
||||||
|
static gnutls_certificate_credentials_t server_cert_key;
|
||||||
|
static gnutls_dh_params_t server_dhp;
|
||||||
|
|
||||||
|
// Client side variables
|
||||||
|
#define MAX_CERTS 6
|
||||||
|
static gnutls_x509_crt_t client_cert[MAX_CERTS];
|
||||||
|
static gnutls_x509_privkey_t client_key;
|
||||||
|
static unsigned int client_cert_count;
|
||||||
|
|
||||||
|
// Shared variables
|
||||||
|
static gnutls_priority_t default_priority;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct ssl_connect
|
||||||
|
{
|
||||||
|
CNCB *callback;
|
||||||
|
void *data;
|
||||||
|
int timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *rb_ssl_strerror(int);
|
||||||
|
static void rb_ssl_connect_realcb(rb_fde_t *, int, struct ssl_connect *);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal GNUTLS-specific code
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We only have one certificate to authenticate with, as both a client and server.
|
||||||
|
*
|
||||||
|
* Unfortunately, GNUTLS tries to be clever, and as client, will attempt to use a certificate that the server will
|
||||||
|
* trust. We usually use self-signed certs, though, so the result of this search is always nothing. Therefore, it
|
||||||
|
* uses no certificate to authenticate as a client. This is undesirable, as it breaks fingerprint authentication;
|
||||||
|
* e.g. the connect::fingerprint on the remote ircd will not match.
|
||||||
|
*
|
||||||
|
* Thus, we use this callback to force GNUTLS to authenticate with our (server) certificate as a client.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
rb_ssl_cert_auth_cb(gnutls_session_t session,
|
||||||
|
const gnutls_datum_t *const req_ca_rdn, const int req_ca_rdn_len,
|
||||||
|
const gnutls_pk_algorithm_t *const sign_algos, const int sign_algos_len,
|
||||||
|
#if (GNUTLS_VERSION_MAJOR < 3)
|
||||||
|
gnutls_retr_st *const st)
|
||||||
|
#else
|
||||||
|
gnutls_retr2_st *const st)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if (GNUTLS_VERSION_MAJOR < 3)
|
||||||
|
st->type = GNUTLS_CRT_X509;
|
||||||
|
#else
|
||||||
|
st->cert_type = GNUTLS_CRT_X509;
|
||||||
|
st->key_type = GNUTLS_PRIVKEY_X509;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
st->ncerts = client_cert_count;
|
||||||
|
st->cert.x509 = client_cert;
|
||||||
|
st->key.x509 = client_key;
|
||||||
|
st->deinit_all = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
rb_sock_net_recv(gnutls_transport_ptr_t context_ptr, void *const buf, const size_t count)
|
||||||
|
{
|
||||||
|
const int fd = rb_get_fd((rb_fde_t *)context_ptr);
|
||||||
|
|
||||||
|
return recv(fd, buf, count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
rb_sock_net_xmit(gnutls_transport_ptr_t context_ptr, const void *const buf, const size_t count)
|
||||||
|
{
|
||||||
|
const int fd = rb_get_fd((rb_fde_t *)context_ptr);
|
||||||
|
|
||||||
|
return send(fd, buf, count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_init_fd(rb_fde_t *const F, const rb_fd_tls_direction dir)
|
||||||
|
{
|
||||||
|
F->ssl = rb_malloc(sizeof(gnutls_session_t));
|
||||||
|
|
||||||
|
if(F->ssl == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: rb_malloc: allocation failure", __func__);
|
||||||
|
rb_close(F);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int init_flags = 0;
|
||||||
|
|
||||||
|
switch(dir)
|
||||||
|
{
|
||||||
|
case RB_FD_TLS_DIRECTION_IN:
|
||||||
|
init_flags |= GNUTLS_SERVER;
|
||||||
|
break;
|
||||||
|
case RB_FD_TLS_DIRECTION_OUT:
|
||||||
|
init_flags |= GNUTLS_CLIENT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_init((gnutls_session_t *) F->ssl, init_flags);
|
||||||
|
gnutls_credentials_set(SSL_P(F), GNUTLS_CRD_CERTIFICATE, server_cert_key);
|
||||||
|
gnutls_dh_set_prime_bits(SSL_P(F), 2048);
|
||||||
|
|
||||||
|
gnutls_transport_set_ptr(SSL_P(F), (gnutls_transport_ptr_t) F);
|
||||||
|
gnutls_transport_set_pull_function(SSL_P(F), rb_sock_net_recv);
|
||||||
|
gnutls_transport_set_push_function(SSL_P(F), rb_sock_net_xmit);
|
||||||
|
|
||||||
|
if (gnutls_priority_set(SSL_P(F), default_priority) != GNUTLS_E_SUCCESS)
|
||||||
|
gnutls_set_default_priority(SSL_P(F));
|
||||||
|
|
||||||
|
if(dir == RB_FD_TLS_DIRECTION_IN)
|
||||||
|
gnutls_certificate_server_set_request(SSL_P(F), GNUTLS_CERT_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_accept_common(rb_fde_t *const F, void *const data)
|
||||||
|
{
|
||||||
|
lrb_assert(F != NULL);
|
||||||
|
lrb_assert(F->accept != NULL);
|
||||||
|
lrb_assert(F->accept->callback != NULL);
|
||||||
|
lrb_assert(F->ssl != NULL);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
const int ret = gnutls_handshake(SSL_P(F));
|
||||||
|
const int err = errno;
|
||||||
|
|
||||||
|
if(ret == GNUTLS_E_AGAIN || (ret == GNUTLS_E_INTERRUPTED && (err == 0 || rb_ignore_errno(err))))
|
||||||
|
{
|
||||||
|
unsigned int flags = (gnutls_record_get_direction(SSL_P(F)) == 0) ? RB_SELECT_READ : RB_SELECT_WRITE;
|
||||||
|
rb_setselect(F, flags, rb_ssl_accept_common, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// These 2 calls may affect errno, which is why we save it above and restore it below
|
||||||
|
rb_settimeout(F, 0, NULL, NULL);
|
||||||
|
rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
|
||||||
|
|
||||||
|
struct acceptdata *const ad = F->accept;
|
||||||
|
F->accept = NULL;
|
||||||
|
|
||||||
|
if(ret == GNUTLS_E_SUCCESS)
|
||||||
|
{
|
||||||
|
F->handshake_count++;
|
||||||
|
ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
|
||||||
|
}
|
||||||
|
else if(ret == GNUTLS_E_INTERRUPTED && err != 0)
|
||||||
|
{
|
||||||
|
errno = err;
|
||||||
|
ad->callback(F, RB_ERROR, NULL, 0, ad->data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errno = EIO;
|
||||||
|
F->ssl_errno = (unsigned long) -ret;
|
||||||
|
ad->callback(F, RB_ERROR_SSL, NULL, 0, ad->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_free(ad);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_connect_common(rb_fde_t *const F, void *const data)
|
||||||
|
{
|
||||||
|
lrb_assert(F != NULL);
|
||||||
|
lrb_assert(F->ssl != NULL);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
const int ret = gnutls_handshake(SSL_P(F));
|
||||||
|
const int err = errno;
|
||||||
|
|
||||||
|
if(ret == GNUTLS_E_AGAIN || (ret == GNUTLS_E_INTERRUPTED && (err == 0 || rb_ignore_errno(err))))
|
||||||
|
{
|
||||||
|
unsigned int flags = (gnutls_record_get_direction(SSL_P(F)) == 0) ? RB_SELECT_READ : RB_SELECT_WRITE;
|
||||||
|
rb_setselect(F, flags, rb_ssl_connect_common, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// These 2 calls may affect errno, which is why we save it above and restore it below
|
||||||
|
rb_settimeout(F, 0, NULL, NULL);
|
||||||
|
rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
|
||||||
|
|
||||||
|
struct ssl_connect *const sconn = data;
|
||||||
|
|
||||||
|
if(ret == GNUTLS_E_SUCCESS)
|
||||||
|
{
|
||||||
|
F->handshake_count++;
|
||||||
|
rb_ssl_connect_realcb(F, RB_OK, sconn);
|
||||||
|
}
|
||||||
|
else if(ret == GNUTLS_E_INTERRUPTED && err != 0)
|
||||||
|
{
|
||||||
|
errno = err;
|
||||||
|
rb_ssl_connect_realcb(F, RB_ERROR, sconn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errno = EIO;
|
||||||
|
F->ssl_errno = (unsigned long) -ret;
|
||||||
|
rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
rb_ssl_strerror(const int err)
|
||||||
|
{
|
||||||
|
return gnutls_strerror(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, const void *const wbuf, const size_t count)
|
||||||
|
{
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
if(r_or_w == 0)
|
||||||
|
ret = gnutls_record_recv(SSL_P(F), rbuf, count);
|
||||||
|
else
|
||||||
|
ret = gnutls_record_send(SSL_P(F), wbuf, count);
|
||||||
|
|
||||||
|
if(ret >= 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if(ret == GNUTLS_E_AGAIN || (ret == GNUTLS_E_INTERRUPTED && (errno == 0 || rb_ignore_errno(errno))))
|
||||||
|
{
|
||||||
|
if(gnutls_record_get_direction(SSL_P(F)) == 0)
|
||||||
|
return RB_RW_SSL_NEED_READ;
|
||||||
|
else
|
||||||
|
return RB_RW_SSL_NEED_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret == GNUTLS_E_INTERRUPTED && errno != 0)
|
||||||
|
return RB_RW_IO_ERROR;
|
||||||
|
|
||||||
|
errno = EIO;
|
||||||
|
F->ssl_errno = (unsigned long) -ret;
|
||||||
|
return RB_RW_SSL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (GNUTLS_VERSION_MAJOR < 3)
|
||||||
|
static void
|
||||||
|
rb_gcry_random_seed(void *const unused)
|
||||||
|
{
|
||||||
|
gcry_fast_random_poll();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_free_datum_t(gnutls_datum_t *const datum)
|
||||||
|
{
|
||||||
|
if(datum == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rb_free(datum->data);
|
||||||
|
rb_free(datum);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gnutls_datum_t *
|
||||||
|
rb_load_file_into_datum_t(const char *const file)
|
||||||
|
{
|
||||||
|
const int datum_fd = open(file, O_RDONLY);
|
||||||
|
if(datum_fd < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct stat fileinfo;
|
||||||
|
if(fstat(datum_fd, &fileinfo) != 0)
|
||||||
|
{
|
||||||
|
(void) close(datum_fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t datum_size = (fileinfo.st_size < 131072) ? (size_t) fileinfo.st_size : 131072;
|
||||||
|
if(datum_size == 0)
|
||||||
|
{
|
||||||
|
(void) close(datum_fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_datum_t *datum;
|
||||||
|
if((datum = rb_malloc(sizeof *datum)) == NULL)
|
||||||
|
{
|
||||||
|
(void) close(datum_fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if((datum->data = rb_malloc(datum_size + 1)) == NULL)
|
||||||
|
{
|
||||||
|
rb_free(datum);
|
||||||
|
(void) close(datum_fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t data_read = 0; data_read < datum_size; )
|
||||||
|
{
|
||||||
|
ssize_t ret = read(datum_fd, ((unsigned char *)datum->data) + data_read, datum_size - data_read);
|
||||||
|
|
||||||
|
if(ret <= 0)
|
||||||
|
{
|
||||||
|
rb_free_datum_t(datum);
|
||||||
|
(void) close(datum_fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_read += (size_t) ret;
|
||||||
|
}
|
||||||
|
(void) close(datum_fd);
|
||||||
|
|
||||||
|
datum->data[datum_size] = '\0';
|
||||||
|
datum->size = (unsigned int) datum_size;
|
||||||
|
return datum;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
make_certfp(gnutls_x509_crt_t cert, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int hashlen;
|
||||||
|
gnutls_digest_algorithm_t md_type;
|
||||||
|
|
||||||
|
int spki = 0;
|
||||||
|
|
||||||
|
switch(method)
|
||||||
|
{
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA1:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA1;
|
||||||
|
md_type = GNUTLS_DIG_SHA1;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA256:
|
||||||
|
spki = 1;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA256:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA256;
|
||||||
|
md_type = GNUTLS_DIG_SHA256;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA512:
|
||||||
|
spki = 1;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA512:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA512;
|
||||||
|
md_type = GNUTLS_DIG_SHA512;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rb_lib_log("%s: invalid method %d", __func__, method);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(! spki)
|
||||||
|
{
|
||||||
|
size_t digest_size = (size_t) hashlen;
|
||||||
|
|
||||||
|
if((ret = gnutls_x509_crt_get_fingerprint(cert, md_type, certfp, &digest_size)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_x509_crt_get_fingerprint: %d", __func__, ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_pubkey_t pubkey;
|
||||||
|
|
||||||
|
if((ret = gnutls_pubkey_init(&pubkey)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_pubkey_init: %d", __func__, ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((ret = gnutls_pubkey_import_x509(pubkey, cert, 0)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_pubkey_import_x509: %d", __func__, ret);
|
||||||
|
gnutls_pubkey_deinit(pubkey);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char derkey[262144]; // Should be big enough to hold any SubjectPublicKeyInfo structure
|
||||||
|
size_t derkey_len = sizeof derkey;
|
||||||
|
|
||||||
|
if((ret = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, derkey, &derkey_len)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_pubkey_export: %d", __func__, ret);
|
||||||
|
gnutls_pubkey_deinit(pubkey);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_pubkey_deinit(pubkey);
|
||||||
|
|
||||||
|
if((ret = gnutls_hash_fast(md_type, derkey, derkey_len, certfp)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_hash_fast: %d", __func__, ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External GNUTLS-specific code
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_shutdown(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
if(F == NULL || F->ssl == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
int ret = gnutls_bye(SSL_P(F), GNUTLS_SHUT_RDWR);
|
||||||
|
|
||||||
|
if(ret != GNUTLS_E_INTERRUPTED && ret != GNUTLS_E_AGAIN)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_deinit(SSL_P(F));
|
||||||
|
|
||||||
|
rb_free(F->ssl);
|
||||||
|
F->ssl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_init_ssl(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if((ret = gnutls_global_init()) != GNUTLS_E_SUCCESS)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_global_init: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (GNUTLS_VERSION_MAJOR < 3)
|
||||||
|
rb_event_addish("rb_gcry_random_seed", rb_gcry_random_seed, NULL, 300);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_setup_ssl_server(const char *const certfile, const char *keyfile,
|
||||||
|
const char *const dhfile, const char *cipherlist, char *hostname)
|
||||||
|
{
|
||||||
|
if(certfile == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: no certificate file specified", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(keyfile == NULL)
|
||||||
|
keyfile = certfile;
|
||||||
|
|
||||||
|
if(cipherlist == NULL)
|
||||||
|
cipherlist = rb_gnutls_default_priority_str;
|
||||||
|
|
||||||
|
|
||||||
|
gnutls_datum_t *const d_cert = rb_load_file_into_datum_t(certfile);
|
||||||
|
if(d_cert == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: Error loading certificate: %s", __func__, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_datum_t *const d_key = rb_load_file_into_datum_t(keyfile);
|
||||||
|
if(d_key == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: Error loading key: %s", __func__, strerror(errno));
|
||||||
|
rb_free_datum_t(d_cert);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if((ret = gnutls_certificate_allocate_credentials(&server_cert_key)) != GNUTLS_E_SUCCESS)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_certificate_allocate_credentials: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
rb_free_datum_t(d_cert);
|
||||||
|
rb_free_datum_t(d_key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (GNUTLS_VERSION_MAJOR < 3)
|
||||||
|
gnutls_certificate_client_set_retrieve_function(server_cert_key, rb_ssl_cert_auth_cb);
|
||||||
|
#else
|
||||||
|
gnutls_certificate_set_retrieve_function(server_cert_key, rb_ssl_cert_auth_cb);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if((ret = gnutls_certificate_set_x509_key_mem(server_cert_key, d_cert, d_key,
|
||||||
|
GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_certificate_set_x509_key_mem: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
gnutls_certificate_free_credentials(server_cert_key);
|
||||||
|
rb_free_datum_t(d_cert);
|
||||||
|
rb_free_datum_t(d_key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
client_cert_count = MAX_CERTS;
|
||||||
|
if((ret = gnutls_x509_crt_list_import(client_cert, &client_cert_count, d_cert, GNUTLS_X509_FMT_PEM,
|
||||||
|
GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED)) < 1)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_x509_crt_list_import: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
gnutls_certificate_free_credentials(server_cert_key);
|
||||||
|
rb_free_datum_t(d_cert);
|
||||||
|
rb_free_datum_t(d_key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
client_cert_count = (unsigned int) ret;
|
||||||
|
|
||||||
|
if((ret = gnutls_x509_privkey_init(&client_key)) != GNUTLS_E_SUCCESS)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_x509_privkey_init: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
gnutls_certificate_free_credentials(server_cert_key);
|
||||||
|
for(unsigned int i = 0; i < client_cert_count; i++)
|
||||||
|
gnutls_x509_crt_deinit(client_cert[i]);
|
||||||
|
rb_free_datum_t(d_cert);
|
||||||
|
rb_free_datum_t(d_key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if((ret = gnutls_x509_privkey_import(client_key, d_key, GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_x509_privkey_import: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
gnutls_certificate_free_credentials(server_cert_key);
|
||||||
|
for(unsigned int i = 0; i < client_cert_count; i++)
|
||||||
|
gnutls_x509_crt_deinit(client_cert[i]);
|
||||||
|
gnutls_x509_privkey_deinit(client_key);
|
||||||
|
rb_free_datum_t(d_cert);
|
||||||
|
rb_free_datum_t(d_key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_free_datum_t(d_cert);
|
||||||
|
rb_free_datum_t(d_key);
|
||||||
|
|
||||||
|
if(dhfile != NULL)
|
||||||
|
{
|
||||||
|
gnutls_datum_t *const d_dhp = rb_load_file_into_datum_t(dhfile);
|
||||||
|
|
||||||
|
if(d_dhp == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: Error parsing DH parameters: %s", __func__, strerror(errno));
|
||||||
|
gnutls_certificate_free_credentials(server_cert_key);
|
||||||
|
for(unsigned int i = 0; i < client_cert_count; i++)
|
||||||
|
gnutls_x509_crt_deinit(client_cert[i]);
|
||||||
|
gnutls_x509_privkey_deinit(client_key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if((ret = gnutls_dh_params_init(&server_dhp)) != GNUTLS_E_SUCCESS)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: Error parsing DH parameters: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
gnutls_certificate_free_credentials(server_cert_key);
|
||||||
|
for(unsigned int i = 0; i < client_cert_count; i++)
|
||||||
|
gnutls_x509_crt_deinit(client_cert[i]);
|
||||||
|
gnutls_x509_privkey_deinit(client_key);
|
||||||
|
rb_free_datum_t(d_dhp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if((ret = gnutls_dh_params_import_pkcs3(server_dhp, d_dhp, GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: Error parsing DH parameters: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
gnutls_certificate_free_credentials(server_cert_key);
|
||||||
|
for(unsigned int i = 0; i < client_cert_count; i++)
|
||||||
|
gnutls_x509_crt_deinit(client_cert[i]);
|
||||||
|
gnutls_x509_privkey_deinit(client_key);
|
||||||
|
gnutls_dh_params_deinit(server_dhp);
|
||||||
|
rb_free_datum_t(d_dhp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_certificate_set_dh_params(server_cert_key, server_dhp);
|
||||||
|
rb_free_datum_t(d_dhp);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *err = NULL;
|
||||||
|
if((ret = gnutls_priority_init(&default_priority, cipherlist, &err)) != GNUTLS_E_SUCCESS)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_priority_init: %s, error begins at '%s'? -- using defaults instead",
|
||||||
|
__func__, rb_ssl_strerror(ret), err ? err : "<unknown>");
|
||||||
|
|
||||||
|
(void) gnutls_priority_init(&default_priority, NULL, &err);
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_lib_log("%s: TLS configuration successful", __func__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_init_prng(const char *const path, prng_seed_t seed_type)
|
||||||
|
{
|
||||||
|
#if (GNUTLS_VERSION_MAJOR < 3)
|
||||||
|
gcry_fast_random_poll();
|
||||||
|
rb_lib_log("%s: PRNG initialised", __func__);
|
||||||
|
#else
|
||||||
|
rb_lib_log("%s: Skipping PRNG initialisation; not required by GNUTLS v3+ backend", __func__);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_get_random(void *const buf, const size_t length)
|
||||||
|
{
|
||||||
|
#if (GNUTLS_VERSION_MAJOR < 3)
|
||||||
|
gcry_randomize(buf, length, GCRY_STRONG_RANDOM);
|
||||||
|
#else
|
||||||
|
gnutls_rnd(GNUTLS_RND_KEY, buf, length);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
rb_get_ssl_strerror(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
const int err = (int) F->ssl_errno;
|
||||||
|
return rb_ssl_strerror(-err);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if(F == NULL || F->ssl == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: no GNUTLS context", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(gnutls_certificate_type_get(SSL_P(F)) != GNUTLS_CRT_X509)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: not an X.509 certificate", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int cert_list_size = 0;
|
||||||
|
const gnutls_datum_t *const cert_list = gnutls_certificate_get_peers(SSL_P(F), &cert_list_size);
|
||||||
|
if(cert_list == NULL || cert_list_size < 1)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: no peer certificate chain returned", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_x509_crt_t peer_cert;
|
||||||
|
if((ret = gnutls_x509_crt_init(&peer_cert)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_x509_crt_init: %d", __func__, ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((ret = gnutls_x509_crt_import(peer_cert, &cert_list[0], GNUTLS_X509_FMT_DER)) < 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: gnutls_x509_crt_import: %d", __func__, ret);
|
||||||
|
gnutls_x509_crt_deinit(peer_cert);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int len = make_certfp(peer_cert, certfp, method);
|
||||||
|
|
||||||
|
gnutls_x509_crt_deinit(peer_cert);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_get_ssl_info(char *const buf, const size_t len)
|
||||||
|
{
|
||||||
|
(void) rb_snprintf(buf, len, "GNUTLS: compiled (v%s), library (v%s)",
|
||||||
|
LIBGNUTLS_VERSION, gnutls_check_version(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
rb_ssl_get_cipher(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
if(F == NULL || F->ssl == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
static char buf[512];
|
||||||
|
|
||||||
|
gnutls_protocol_t version_ptr = gnutls_protocol_get_version(SSL_P(F));
|
||||||
|
gnutls_cipher_algorithm_t cipher_ptr = gnutls_cipher_get(SSL_P(F));
|
||||||
|
|
||||||
|
const char *const version = gnutls_protocol_get_name(version_ptr);
|
||||||
|
const char *const cipher = gnutls_cipher_get_name(cipher_ptr);
|
||||||
|
|
||||||
|
(void) rb_snprintf(buf, sizeof buf, "%s, %s", version, cipher);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
rb_ssl_read(rb_fde_t *const F, void *const buf, const size_t count)
|
||||||
|
{
|
||||||
|
return rb_ssl_read_or_write(0, F, buf, NULL, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
rb_ssl_write(rb_fde_t *const F, const void *const buf, const size_t count)
|
||||||
|
{
|
||||||
|
return rb_ssl_read_or_write(1, F, NULL, buf, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal library-agnostic code
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_connect_realcb(rb_fde_t *const F, const int status, struct ssl_connect *const sconn)
|
||||||
|
{
|
||||||
|
lrb_assert(F != NULL);
|
||||||
|
lrb_assert(F->connect != NULL);
|
||||||
|
|
||||||
|
F->connect->callback = sconn->callback;
|
||||||
|
F->connect->data = sconn->data;
|
||||||
|
|
||||||
|
rb_connect_callback(F, status);
|
||||||
|
rb_free(sconn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_timeout_cb(rb_fde_t *const F, void *const data)
|
||||||
|
{
|
||||||
|
lrb_assert(F->accept != NULL);
|
||||||
|
lrb_assert(F->accept->callback != NULL);
|
||||||
|
|
||||||
|
F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_tryconn_timeout_cb(rb_fde_t *const F, void *const data)
|
||||||
|
{
|
||||||
|
rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data)
|
||||||
|
{
|
||||||
|
lrb_assert(F != NULL);
|
||||||
|
|
||||||
|
struct ssl_connect *const sconn = data;
|
||||||
|
|
||||||
|
if(status != RB_OK)
|
||||||
|
{
|
||||||
|
rb_ssl_connect_realcb(F, status, sconn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
F->type |= RB_FD_SSL;
|
||||||
|
|
||||||
|
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
|
||||||
|
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
|
||||||
|
rb_ssl_connect_common(F, sconn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External library-agnostic code
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_supports_ssl(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
rb_ssl_handshake_count(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
return F->handshake_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_clear_handshake_count(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
F->handshake_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_start_accepted(rb_fde_t *const F, ACCB *const cb, void *const data, const int timeout)
|
||||||
|
{
|
||||||
|
F->type |= RB_FD_SSL;
|
||||||
|
|
||||||
|
F->accept = rb_malloc(sizeof(struct acceptdata));
|
||||||
|
F->accept->callback = cb;
|
||||||
|
F->accept->data = data;
|
||||||
|
F->accept->addrlen = 0;
|
||||||
|
(void) memset(&F->accept->S, 0x00, sizeof F->accept->S);
|
||||||
|
|
||||||
|
rb_settimeout(F, timeout, rb_ssl_timeout_cb, NULL);
|
||||||
|
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_IN);
|
||||||
|
rb_ssl_accept_common(F, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_accept_setup(rb_fde_t *const srv_F, rb_fde_t *const cli_F, struct sockaddr *const st, const int addrlen)
|
||||||
|
{
|
||||||
|
cli_F->type |= RB_FD_SSL;
|
||||||
|
|
||||||
|
cli_F->accept = rb_malloc(sizeof(struct acceptdata));
|
||||||
|
cli_F->accept->callback = srv_F->accept->callback;
|
||||||
|
cli_F->accept->data = srv_F->accept->data;
|
||||||
|
cli_F->accept->addrlen = (rb_socklen_t) addrlen;
|
||||||
|
(void) memset(&cli_F->accept->S, 0x00, sizeof cli_F->accept->S);
|
||||||
|
(void) memcpy(&cli_F->accept->S, st, (size_t) addrlen);
|
||||||
|
|
||||||
|
rb_settimeout(cli_F, 10, rb_ssl_timeout_cb, NULL);
|
||||||
|
rb_ssl_init_fd(cli_F, RB_FD_TLS_DIRECTION_IN);
|
||||||
|
rb_ssl_accept_common(cli_F, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_ssl_listen(rb_fde_t *const F, const int backlog, const int defer_accept)
|
||||||
|
{
|
||||||
|
int result = rb_listen(F, backlog, defer_accept);
|
||||||
|
|
||||||
|
F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_connect_tcp_ssl(rb_fde_t *const F, struct sockaddr *const dest, struct sockaddr *const clocal,
|
||||||
|
const int socklen, CNCB *const callback, void *const data, const int timeout)
|
||||||
|
{
|
||||||
|
if(F == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
|
||||||
|
sconn->data = data;
|
||||||
|
sconn->callback = callback;
|
||||||
|
sconn->timeout = timeout;
|
||||||
|
|
||||||
|
rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data, const int timeout)
|
||||||
|
{
|
||||||
|
if(F == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
|
||||||
|
sconn->data = data;
|
||||||
|
sconn->callback = callback;
|
||||||
|
sconn->timeout = timeout;
|
||||||
|
|
||||||
|
F->connect = rb_malloc(sizeof(struct conndata));
|
||||||
|
F->connect->callback = callback;
|
||||||
|
F->connect->data = data;
|
||||||
|
|
||||||
|
F->type |= RB_FD_SSL;
|
||||||
|
|
||||||
|
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
|
||||||
|
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
|
||||||
|
rb_ssl_connect_common(F, sconn);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_GNUTLS */
|
37
libratbox/src/gnutls_ratbox.h
Normal file
37
libratbox/src/gnutls_ratbox.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* libratbox: a library used by ircd-ratbox and other things
|
||||||
|
* gnutls_ratbox.h: embedded data for GNUTLS backend
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2008 ircd-ratbox development team
|
||||||
|
* Copyright (C) 2007-2008 Aaron Sethman <androsyn@ratbox.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const char rb_gnutls_default_priority_str[] = ""
|
||||||
|
"+SECURE256:"
|
||||||
|
"+SECURE128:"
|
||||||
|
"!RSA:"
|
||||||
|
"+NORMAL:"
|
||||||
|
"!ARCFOUR-128:"
|
||||||
|
"!3DES-CBC:"
|
||||||
|
"!MD5:"
|
||||||
|
"+VERS-TLS1.2:"
|
||||||
|
"+VERS-TLS1.1:"
|
||||||
|
"!VERS-TLS1.0:"
|
||||||
|
"!VERS-SSL3.0:"
|
||||||
|
"%SAFE_RENEGOTIATION";
|
839
libratbox/src/linebuf.c
Normal file
839
libratbox/src/linebuf.c
Normal file
|
@ -0,0 +1,839 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: A slightly useful ircd.
|
||||||
|
* linebuf.c: Maintains linebuffers.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001-2002 Adrian Chadd <adrian@creative.net.au>
|
||||||
|
* Copyright (C) 2002 Hybrid Development Team
|
||||||
|
* Copyright (C) 2002-2005 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: linebuf.c 26092 2008-09-19 15:13:52Z androsyn $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libratbox_config.h>
|
||||||
|
#include <ratbox_lib.h>
|
||||||
|
#include <commio-int.h>
|
||||||
|
|
||||||
|
static rb_bh *rb_linebuf_heap;
|
||||||
|
|
||||||
|
static int bufline_count = 0;
|
||||||
|
|
||||||
|
#ifndef LINEBUF_HEAP_SIZE
|
||||||
|
#define LINEBUF_HEAP_SIZE 2048
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rb_linebuf_init
|
||||||
|
*
|
||||||
|
* Initialise the linebuf mechanism
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_linebuf_init(size_t heap_size)
|
||||||
|
{
|
||||||
|
rb_linebuf_heap = rb_bh_create(sizeof(buf_line_t), heap_size, "librb_linebuf_heap");
|
||||||
|
}
|
||||||
|
|
||||||
|
static buf_line_t *
|
||||||
|
rb_linebuf_allocate(void)
|
||||||
|
{
|
||||||
|
buf_line_t *t;
|
||||||
|
t = rb_bh_alloc(rb_linebuf_heap);
|
||||||
|
return (t);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_linebuf_free(buf_line_t * p)
|
||||||
|
{
|
||||||
|
rb_bh_free(rb_linebuf_heap, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rb_linebuf_new_line
|
||||||
|
*
|
||||||
|
* Create a new line, and link it to the given linebuf.
|
||||||
|
* It will be initially empty.
|
||||||
|
*/
|
||||||
|
static buf_line_t *
|
||||||
|
rb_linebuf_new_line(buf_head_t * bufhead)
|
||||||
|
{
|
||||||
|
buf_line_t *bufline;
|
||||||
|
rb_dlink_node *node;
|
||||||
|
|
||||||
|
bufline = rb_linebuf_allocate();
|
||||||
|
if(bufline == NULL)
|
||||||
|
return NULL;
|
||||||
|
++bufline_count;
|
||||||
|
|
||||||
|
|
||||||
|
node = rb_make_rb_dlink_node();
|
||||||
|
|
||||||
|
/* Stick it at the end of the buf list */
|
||||||
|
rb_dlinkAddTail(bufline, node, &bufhead->list);
|
||||||
|
bufline->refcount++;
|
||||||
|
|
||||||
|
/* And finally, update the allocated size */
|
||||||
|
bufhead->alloclen++;
|
||||||
|
bufhead->numlines++;
|
||||||
|
|
||||||
|
return bufline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rb_linebuf_done_line
|
||||||
|
*
|
||||||
|
* We've finished with the given line, so deallocate it
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
rb_linebuf_done_line(buf_head_t * bufhead, buf_line_t * bufline, rb_dlink_node *node)
|
||||||
|
{
|
||||||
|
/* Remove it from the linked list */
|
||||||
|
rb_dlinkDestroy(node, &bufhead->list);
|
||||||
|
|
||||||
|
/* Update the allocated size */
|
||||||
|
bufhead->alloclen--;
|
||||||
|
bufhead->len -= bufline->len;
|
||||||
|
lrb_assert(bufhead->len >= 0);
|
||||||
|
bufhead->numlines--;
|
||||||
|
|
||||||
|
bufline->refcount--;
|
||||||
|
lrb_assert(bufline->refcount >= 0);
|
||||||
|
|
||||||
|
if(bufline->refcount == 0)
|
||||||
|
{
|
||||||
|
/* and finally, deallocate the buf */
|
||||||
|
--bufline_count;
|
||||||
|
lrb_assert(bufline_count >= 0);
|
||||||
|
rb_linebuf_free(bufline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* skip to end of line or the crlfs, return the number of bytes ..
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
rb_linebuf_skip_crlf(char *ch, int len)
|
||||||
|
{
|
||||||
|
int orig_len = len;
|
||||||
|
|
||||||
|
/* First, skip until the first non-CRLF */
|
||||||
|
for(; len; len--, ch++)
|
||||||
|
{
|
||||||
|
if(*ch == '\r')
|
||||||
|
break;
|
||||||
|
else if(*ch == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then, skip until the last CRLF */
|
||||||
|
for(; len; len--, ch++)
|
||||||
|
{
|
||||||
|
if((*ch != '\r') && (*ch != '\n'))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lrb_assert(orig_len > len);
|
||||||
|
return (orig_len - len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rb_linebuf_newbuf
|
||||||
|
*
|
||||||
|
* Initialise the new buffer
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
rb_linebuf_newbuf(buf_head_t * bufhead)
|
||||||
|
{
|
||||||
|
/* not much to do right now :) */
|
||||||
|
memset(bufhead, 0, sizeof(buf_head_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rb_linebuf_donebuf
|
||||||
|
*
|
||||||
|
* Flush all the lines associated with this buffer
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
rb_linebuf_donebuf(buf_head_t * bufhead)
|
||||||
|
{
|
||||||
|
while(bufhead->list.head != NULL)
|
||||||
|
{
|
||||||
|
rb_linebuf_done_line(bufhead, (buf_line_t *) bufhead->list.head->data,
|
||||||
|
bufhead->list.head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rb_linebuf_copy_line
|
||||||
|
*
|
||||||
|
* Okay..this functions comments made absolutely no sense.
|
||||||
|
*
|
||||||
|
* Basically what we do is this. Find the first chunk of text
|
||||||
|
* and then scan for a CRLF. If we didn't find it, but we didn't
|
||||||
|
* overflow our buffer..we wait for some more data.
|
||||||
|
* If we found a CRLF, we replace them with a \0 character.
|
||||||
|
* If we overflowed, we copy the most our buffer can handle, terminate
|
||||||
|
* it with a \0 and return.
|
||||||
|
*
|
||||||
|
* The return value is the amount of data we consumed. This could
|
||||||
|
* be different than the size of the linebuffer, as when we discard
|
||||||
|
* the overflow, we don't want to process it again.
|
||||||
|
*
|
||||||
|
* This still sucks in my opinion, but it seems to work.
|
||||||
|
*
|
||||||
|
* -Aaron
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
rb_linebuf_copy_line(buf_head_t * bufhead, buf_line_t * bufline, char *data, int len)
|
||||||
|
{
|
||||||
|
int cpylen = 0; /* how many bytes we've copied */
|
||||||
|
char *ch = data; /* Pointer to where we are in the read data */
|
||||||
|
char *bufch = bufline->buf + bufline->len;
|
||||||
|
int clen = 0; /* how many bytes we've processed,
|
||||||
|
and don't ever want to see again.. */
|
||||||
|
|
||||||
|
/* If its full or terminated, ignore it */
|
||||||
|
|
||||||
|
bufline->raw = 0;
|
||||||
|
lrb_assert(bufline->len < BUF_DATA_SIZE);
|
||||||
|
if(bufline->terminated == 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
clen = cpylen = rb_linebuf_skip_crlf(ch, len);
|
||||||
|
if(clen == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* This is the ~overflow case..This doesn't happen often.. */
|
||||||
|
if(cpylen > (BUF_DATA_SIZE - bufline->len - 1))
|
||||||
|
{
|
||||||
|
cpylen = BUF_DATA_SIZE - bufline->len - 1;
|
||||||
|
memcpy(bufch, ch, cpylen);
|
||||||
|
bufline->buf[BUF_DATA_SIZE - 1] = '\0';
|
||||||
|
bufch = bufline->buf + BUF_DATA_SIZE - 2;
|
||||||
|
while(cpylen && (*bufch == '\r' || *bufch == '\n'))
|
||||||
|
{
|
||||||
|
*bufch = '\0';
|
||||||
|
cpylen--;
|
||||||
|
bufch--;
|
||||||
|
}
|
||||||
|
bufline->terminated = 1;
|
||||||
|
bufline->len = BUF_DATA_SIZE - 1;
|
||||||
|
bufhead->len += BUF_DATA_SIZE - 1;
|
||||||
|
return clen;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(bufch, ch, cpylen);
|
||||||
|
bufch += cpylen;
|
||||||
|
*bufch = '\0';
|
||||||
|
bufch--;
|
||||||
|
|
||||||
|
if(*bufch != '\r' && *bufch != '\n')
|
||||||
|
{
|
||||||
|
/* No linefeed, bail for the next time */
|
||||||
|
bufhead->len += cpylen;
|
||||||
|
bufline->len += cpylen;
|
||||||
|
bufline->terminated = 0;
|
||||||
|
return clen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Yank the CRLF off this, replace with a \0 */
|
||||||
|
while(cpylen && (*bufch == '\r' || *bufch == '\n'))
|
||||||
|
{
|
||||||
|
*bufch = '\0';
|
||||||
|
cpylen--;
|
||||||
|
bufch--;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufline->terminated = 1;
|
||||||
|
bufhead->len += cpylen;
|
||||||
|
bufline->len += cpylen;
|
||||||
|
return clen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rb_linebuf_copy_raw
|
||||||
|
*
|
||||||
|
* Copy as much data as possible directly into a linebuf,
|
||||||
|
* splitting at \r\n, but without altering any data.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
rb_linebuf_copy_raw(buf_head_t * bufhead, buf_line_t * bufline, char *data, int len)
|
||||||
|
{
|
||||||
|
int cpylen = 0; /* how many bytes we've copied */
|
||||||
|
char *ch = data; /* Pointer to where we are in the read data */
|
||||||
|
char *bufch = bufline->buf + bufline->len;
|
||||||
|
int clen = 0; /* how many bytes we've processed,
|
||||||
|
and don't ever want to see again.. */
|
||||||
|
|
||||||
|
/* If its full or terminated, ignore it */
|
||||||
|
|
||||||
|
bufline->raw = 1;
|
||||||
|
lrb_assert(bufline->len < BUF_DATA_SIZE);
|
||||||
|
if(bufline->terminated == 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
clen = cpylen = rb_linebuf_skip_crlf(ch, len);
|
||||||
|
if(clen == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* This is the overflow case..This doesn't happen often.. */
|
||||||
|
if(cpylen > (BUF_DATA_SIZE - bufline->len - 1))
|
||||||
|
{
|
||||||
|
clen = BUF_DATA_SIZE - bufline->len - 1;
|
||||||
|
memcpy(bufch, ch, clen);
|
||||||
|
bufline->buf[BUF_DATA_SIZE - 1] = '\0';
|
||||||
|
bufline->terminated = 1;
|
||||||
|
bufline->len = BUF_DATA_SIZE - 1;
|
||||||
|
bufhead->len += BUF_DATA_SIZE - 1;
|
||||||
|
return clen;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(bufch, ch, cpylen);
|
||||||
|
bufch += cpylen;
|
||||||
|
*bufch = '\0';
|
||||||
|
bufch--;
|
||||||
|
|
||||||
|
if(*bufch != '\r' && *bufch != '\n')
|
||||||
|
{
|
||||||
|
/* No linefeed, bail for the next time */
|
||||||
|
bufhead->len += cpylen;
|
||||||
|
bufline->len += cpylen;
|
||||||
|
bufline->terminated = 0;
|
||||||
|
return clen;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufline->terminated = 1;
|
||||||
|
bufhead->len += cpylen;
|
||||||
|
bufline->len += cpylen;
|
||||||
|
return clen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rb_linebuf_parse
|
||||||
|
*
|
||||||
|
* Take a given buffer and break out as many buffers as we can.
|
||||||
|
* If we find a CRLF, we terminate that buffer and create a new one.
|
||||||
|
* If we don't find a CRLF whilst parsing a buffer, we don't mark it
|
||||||
|
* 'finished', so the next loop through we can continue appending ..
|
||||||
|
*
|
||||||
|
* A few notes here, which you'll need to understand before continuing.
|
||||||
|
*
|
||||||
|
* - right now I'm only dealing with single sized buffers. Later on,
|
||||||
|
* I might consider chaining buffers together to get longer "lines"
|
||||||
|
* but seriously, I don't see the advantage right now.
|
||||||
|
*
|
||||||
|
* - This *is* designed to turn into a reference-counter-protected setup
|
||||||
|
* to dodge copious copies.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
rb_linebuf_parse(buf_head_t * bufhead, char *data, int len, int raw)
|
||||||
|
{
|
||||||
|
buf_line_t *bufline;
|
||||||
|
int cpylen;
|
||||||
|
int linecnt = 0;
|
||||||
|
|
||||||
|
/* First, if we have a partial buffer, try to squeze data into it */
|
||||||
|
if(bufhead->list.tail != NULL)
|
||||||
|
{
|
||||||
|
/* Check we're doing the partial buffer thing */
|
||||||
|
bufline = bufhead->list.tail->data;
|
||||||
|
/* just try, the worst it could do is *reject* us .. */
|
||||||
|
if(!raw)
|
||||||
|
cpylen = rb_linebuf_copy_line(bufhead, bufline, data, len);
|
||||||
|
else
|
||||||
|
cpylen = rb_linebuf_copy_raw(bufhead, bufline, data, len);
|
||||||
|
|
||||||
|
if(cpylen == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
linecnt++;
|
||||||
|
/* If we've copied the same as what we've got, quit now */
|
||||||
|
if(cpylen == len)
|
||||||
|
return linecnt; /* all the data done so soon? */
|
||||||
|
|
||||||
|
/* Skip the data and update len .. */
|
||||||
|
len -= cpylen;
|
||||||
|
lrb_assert(len >= 0);
|
||||||
|
data += cpylen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next, the loop */
|
||||||
|
while(len > 0)
|
||||||
|
{
|
||||||
|
/* We obviously need a new buffer, so .. */
|
||||||
|
bufline = rb_linebuf_new_line(bufhead);
|
||||||
|
|
||||||
|
/* And parse */
|
||||||
|
if(!raw)
|
||||||
|
cpylen = rb_linebuf_copy_line(bufhead, bufline, data, len);
|
||||||
|
else
|
||||||
|
cpylen = rb_linebuf_copy_raw(bufhead, bufline, data, len);
|
||||||
|
|
||||||
|
if(cpylen == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
len -= cpylen;
|
||||||
|
lrb_assert(len >= 0);
|
||||||
|
data += cpylen;
|
||||||
|
linecnt++;
|
||||||
|
}
|
||||||
|
return linecnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rb_linebuf_get
|
||||||
|
*
|
||||||
|
* get the next buffer from our line. For the time being it will copy
|
||||||
|
* data into the given buffer and free the underlying linebuf.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
rb_linebuf_get(buf_head_t * bufhead, char *buf, int buflen, int partial, int raw)
|
||||||
|
{
|
||||||
|
buf_line_t *bufline;
|
||||||
|
int cpylen;
|
||||||
|
char *start, *ch;
|
||||||
|
|
||||||
|
/* make sure we have a line */
|
||||||
|
if(bufhead->list.head == NULL)
|
||||||
|
return 0; /* Obviously not.. hrm. */
|
||||||
|
|
||||||
|
bufline = bufhead->list.head->data;
|
||||||
|
|
||||||
|
/* make sure that the buffer was actually *terminated */
|
||||||
|
if(!(partial || bufline->terminated))
|
||||||
|
return 0; /* Wait for more data! */
|
||||||
|
|
||||||
|
if(buflen < bufline->len)
|
||||||
|
cpylen = buflen - 1;
|
||||||
|
else
|
||||||
|
cpylen = bufline->len;
|
||||||
|
|
||||||
|
/* Copy it */
|
||||||
|
start = bufline->buf;
|
||||||
|
|
||||||
|
/* if we left extraneous '\r\n' characters in the string,
|
||||||
|
* and we don't want to read the raw data, clean up the string.
|
||||||
|
*/
|
||||||
|
if(bufline->raw && !raw)
|
||||||
|
{
|
||||||
|
/* skip leading EOL characters */
|
||||||
|
while(cpylen && (*start == '\r' || *start == '\n'))
|
||||||
|
{
|
||||||
|
start++;
|
||||||
|
cpylen--;
|
||||||
|
}
|
||||||
|
/* skip trailing EOL characters */
|
||||||
|
ch = &start[cpylen - 1];
|
||||||
|
while(cpylen && (*ch == '\r' || *ch == '\n'))
|
||||||
|
{
|
||||||
|
ch--;
|
||||||
|
cpylen--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf, start, cpylen);
|
||||||
|
|
||||||
|
/* convert CR/LF to NULL */
|
||||||
|
if(!raw)
|
||||||
|
buf[cpylen] = '\0';
|
||||||
|
|
||||||
|
lrb_assert(cpylen >= 0);
|
||||||
|
|
||||||
|
/* Deallocate the line */
|
||||||
|
rb_linebuf_done_line(bufhead, bufline, bufhead->list.head);
|
||||||
|
|
||||||
|
/* return how much we copied */
|
||||||
|
return cpylen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rb_linebuf_attach
|
||||||
|
*
|
||||||
|
* attach the lines in a buf_head_t to another buf_head_t
|
||||||
|
* without copying the data (using refcounts).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
rb_linebuf_attach(buf_head_t * bufhead, buf_head_t * new)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
buf_line_t *line;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, new->list.head)
|
||||||
|
{
|
||||||
|
line = ptr->data;
|
||||||
|
rb_dlinkAddTailAlloc(line, &bufhead->list);
|
||||||
|
|
||||||
|
/* Update the allocated size */
|
||||||
|
bufhead->alloclen++;
|
||||||
|
bufhead->len += line->len;
|
||||||
|
bufhead->numlines++;
|
||||||
|
|
||||||
|
line->refcount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rb_linebuf_putmsg
|
||||||
|
*
|
||||||
|
* Similar to rb_linebuf_put, but designed for use by send.c.
|
||||||
|
*
|
||||||
|
* prefixfmt is used as a format for the varargs, and is inserted first.
|
||||||
|
* Then format/va_args is appended to the buffer.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
rb_linebuf_putmsg(buf_head_t * bufhead, const char *format, va_list * va_args,
|
||||||
|
const char *prefixfmt, ...)
|
||||||
|
{
|
||||||
|
buf_line_t *bufline;
|
||||||
|
int len = 0;
|
||||||
|
va_list prefix_args;
|
||||||
|
|
||||||
|
/* make sure the previous line is terminated */
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if(bufhead->list.tail)
|
||||||
|
{
|
||||||
|
bufline = bufhead->list.tail->data;
|
||||||
|
lrb_assert(bufline->terminated);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* Create a new line */
|
||||||
|
bufline = rb_linebuf_new_line(bufhead);
|
||||||
|
|
||||||
|
if(prefixfmt != NULL)
|
||||||
|
{
|
||||||
|
va_start(prefix_args, prefixfmt);
|
||||||
|
len = rb_vsnprintf(bufline->buf, BUF_DATA_SIZE, prefixfmt, prefix_args);
|
||||||
|
va_end(prefix_args);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(va_args != NULL)
|
||||||
|
{
|
||||||
|
len += rb_vsnprintf((bufline->buf + len), (BUF_DATA_SIZE - len), format, *va_args);
|
||||||
|
}
|
||||||
|
|
||||||
|
bufline->terminated = 1;
|
||||||
|
|
||||||
|
/* Truncate the data if required */
|
||||||
|
if(rb_unlikely(len > 510))
|
||||||
|
{
|
||||||
|
len = 510;
|
||||||
|
bufline->buf[len++] = '\r';
|
||||||
|
bufline->buf[len++] = '\n';
|
||||||
|
}
|
||||||
|
else if(rb_unlikely(len == 0))
|
||||||
|
{
|
||||||
|
bufline->buf[len++] = '\r';
|
||||||
|
bufline->buf[len++] = '\n';
|
||||||
|
bufline->buf[len] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Chop trailing CRLF's .. */
|
||||||
|
while((bufline->buf[len] == '\r') || (bufline->buf[len] == '\n')
|
||||||
|
|| (bufline->buf[len] == '\0'))
|
||||||
|
{
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufline->buf[++len] = '\r';
|
||||||
|
bufline->buf[++len] = '\n';
|
||||||
|
bufline->buf[++len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
bufline->len = len;
|
||||||
|
bufhead->len += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_linebuf_putbuf(buf_head_t * bufhead, const char *buffer)
|
||||||
|
{
|
||||||
|
buf_line_t *bufline;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
/* make sure the previous line is terminated */
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if(bufhead->list.tail)
|
||||||
|
{
|
||||||
|
bufline = bufhead->list.tail->data;
|
||||||
|
lrb_assert(bufline->terminated);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* Create a new line */
|
||||||
|
bufline = rb_linebuf_new_line(bufhead);
|
||||||
|
|
||||||
|
if(rb_unlikely(buffer != NULL))
|
||||||
|
len = rb_strlcpy(bufline->buf, buffer, BUF_DATA_SIZE);
|
||||||
|
|
||||||
|
bufline->terminated = 1;
|
||||||
|
|
||||||
|
/* Truncate the data if required */
|
||||||
|
if(rb_unlikely(len > 510))
|
||||||
|
{
|
||||||
|
len = 510;
|
||||||
|
bufline->buf[len++] = '\r';
|
||||||
|
bufline->buf[len++] = '\n';
|
||||||
|
}
|
||||||
|
else if(rb_unlikely(len == 0))
|
||||||
|
{
|
||||||
|
bufline->buf[len++] = '\r';
|
||||||
|
bufline->buf[len++] = '\n';
|
||||||
|
bufline->buf[len] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Chop trailing CRLF's .. */
|
||||||
|
while((bufline->buf[len] == '\r') || (bufline->buf[len] == '\n')
|
||||||
|
|| (bufline->buf[len] == '\0'))
|
||||||
|
{
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufline->buf[++len] = '\r';
|
||||||
|
bufline->buf[++len] = '\n';
|
||||||
|
bufline->buf[++len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
bufline->len = len;
|
||||||
|
bufhead->len += len;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_linebuf_put(buf_head_t * bufhead, const char *format, ...)
|
||||||
|
{
|
||||||
|
buf_line_t *bufline;
|
||||||
|
int len = 0;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
/* make sure the previous line is terminated */
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if(bufhead->list.tail)
|
||||||
|
{
|
||||||
|
bufline = bufhead->list.tail->data;
|
||||||
|
lrb_assert(bufline->terminated);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* Create a new line */
|
||||||
|
bufline = rb_linebuf_new_line(bufhead);
|
||||||
|
|
||||||
|
if(rb_unlikely(format != NULL))
|
||||||
|
{
|
||||||
|
va_start(args, format);
|
||||||
|
len = rb_vsnprintf(bufline->buf, BUF_DATA_SIZE, format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
bufline->terminated = 1;
|
||||||
|
|
||||||
|
/* Truncate the data if required */
|
||||||
|
if(rb_unlikely(len > 510))
|
||||||
|
{
|
||||||
|
len = 510;
|
||||||
|
bufline->buf[len++] = '\r';
|
||||||
|
bufline->buf[len++] = '\n';
|
||||||
|
}
|
||||||
|
else if(rb_unlikely(len == 0))
|
||||||
|
{
|
||||||
|
bufline->buf[len++] = '\r';
|
||||||
|
bufline->buf[len++] = '\n';
|
||||||
|
bufline->buf[len] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Chop trailing CRLF's .. */
|
||||||
|
while((bufline->buf[len] == '\r') || (bufline->buf[len] == '\n')
|
||||||
|
|| (bufline->buf[len] == '\0'))
|
||||||
|
{
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufline->buf[++len] = '\r';
|
||||||
|
bufline->buf[++len] = '\n';
|
||||||
|
bufline->buf[++len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
bufline->len = len;
|
||||||
|
bufhead->len += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rb_linebuf_flush
|
||||||
|
*
|
||||||
|
* Flush data to the buffer. It tries to write as much data as possible
|
||||||
|
* to the given socket. Any return values are passed straight through.
|
||||||
|
* If there is no data in the socket, EWOULDBLOCK is set as an errno
|
||||||
|
* rather than returning 0 (which would map to an EOF..)
|
||||||
|
*
|
||||||
|
* Notes: XXX We *should* have a clue here when a non-full buffer is arrived.
|
||||||
|
* and tag it so that we don't re-schedule another write until
|
||||||
|
* we have a CRLF.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
rb_linebuf_flush(rb_fde_t *F, buf_head_t * bufhead)
|
||||||
|
{
|
||||||
|
buf_line_t *bufline;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* autoconf checks for this..but really just want to use it if we have a
|
||||||
|
* native version even if libircd provides a fake version...
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_WRITEV
|
||||||
|
if(!rb_fd_ssl(F))
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
int x = 0, y;
|
||||||
|
int xret;
|
||||||
|
static struct rb_iovec vec[RB_UIO_MAXIOV];
|
||||||
|
|
||||||
|
memset(vec, 0, sizeof(vec));
|
||||||
|
/* Check we actually have a first buffer */
|
||||||
|
if(bufhead->list.head == NULL)
|
||||||
|
{
|
||||||
|
/* nope, so we return none .. */
|
||||||
|
errno = EWOULDBLOCK;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = bufhead->list.head;
|
||||||
|
|
||||||
|
bufline = ptr->data;
|
||||||
|
if(!bufline->terminated)
|
||||||
|
{
|
||||||
|
errno = EWOULDBLOCK;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
vec[x].iov_base = bufline->buf + bufhead->writeofs;
|
||||||
|
vec[x++].iov_len = bufline->len - bufhead->writeofs;
|
||||||
|
ptr = ptr->next;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(ptr == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bufline = ptr->data;
|
||||||
|
if(!bufline->terminated)
|
||||||
|
break;
|
||||||
|
|
||||||
|
vec[x].iov_base = bufline->buf;
|
||||||
|
vec[x].iov_len = bufline->len;
|
||||||
|
ptr = ptr->next;
|
||||||
|
|
||||||
|
}
|
||||||
|
while(++x < RB_UIO_MAXIOV);
|
||||||
|
|
||||||
|
if(x == 0)
|
||||||
|
{
|
||||||
|
errno = EWOULDBLOCK;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xret = retval = rb_writev(F, vec, x);
|
||||||
|
if(retval <= 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
ptr = bufhead->list.head;
|
||||||
|
|
||||||
|
for(y = 0; y < x; y++)
|
||||||
|
{
|
||||||
|
bufline = ptr->data;
|
||||||
|
|
||||||
|
if(xret >= bufline->len - bufhead->writeofs)
|
||||||
|
{
|
||||||
|
xret -= bufline->len - bufhead->writeofs;
|
||||||
|
ptr = ptr->next;
|
||||||
|
rb_linebuf_done_line(bufhead, bufline, bufhead->list.head);
|
||||||
|
bufhead->writeofs = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bufhead->writeofs += xret;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* this is the non-writev case */
|
||||||
|
|
||||||
|
/* Check we actually have a first buffer */
|
||||||
|
if(bufhead->list.head == NULL)
|
||||||
|
{
|
||||||
|
/* nope, so we return none .. */
|
||||||
|
errno = EWOULDBLOCK;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufline = bufhead->list.head->data;
|
||||||
|
|
||||||
|
/* And that its actually full .. */
|
||||||
|
if(!bufline->terminated)
|
||||||
|
{
|
||||||
|
errno = EWOULDBLOCK;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now, try writing data */
|
||||||
|
retval = rb_write(F, bufline->buf + bufhead->writeofs, bufline->len - bufhead->writeofs);
|
||||||
|
|
||||||
|
if(retval <= 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* we've got data, so update the write offset */
|
||||||
|
bufhead->writeofs += retval;
|
||||||
|
|
||||||
|
/* if we've written everything *and* the CRLF, deallocate and update
|
||||||
|
bufhead */
|
||||||
|
if(bufhead->writeofs == bufline->len)
|
||||||
|
{
|
||||||
|
bufhead->writeofs = 0;
|
||||||
|
lrb_assert(bufhead->len >= 0);
|
||||||
|
rb_linebuf_done_line(bufhead, bufline, bufhead->list.head);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return line length */
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* count linebufs for stats z
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_count_rb_linebuf_memory(size_t *count, size_t *rb_linebuf_memory_used)
|
||||||
|
{
|
||||||
|
rb_bh_usage(rb_linebuf_heap, count, NULL, rb_linebuf_memory_used, NULL);
|
||||||
|
}
|
896
libratbox/src/mbedtls.c
Normal file
896
libratbox/src/mbedtls.c
Normal file
|
@ -0,0 +1,896 @@
|
||||||
|
/*
|
||||||
|
* libratbox: a library used by ircd-ratbox and other things
|
||||||
|
* mbedtls.c: ARM MbedTLS backend
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2008 ircd-ratbox development team
|
||||||
|
* Copyright (C) 2007-2008 Aaron Sethman <androsyn@ratbox.org>
|
||||||
|
* Copyright (C) 2015 William Pitcock <nenolod@dereferenced.org>
|
||||||
|
* Copyright (C) 2016 Aaron Jones <aaronmdjones@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libratbox_config.h>
|
||||||
|
#include <ratbox_lib.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_MBEDTLS
|
||||||
|
|
||||||
|
#include <commio-int.h>
|
||||||
|
#include <commio-ssl.h>
|
||||||
|
|
||||||
|
#include "mbedtls_ratbox.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
RB_FD_TLS_DIRECTION_IN = 0,
|
||||||
|
RB_FD_TLS_DIRECTION_OUT = 1
|
||||||
|
} rb_fd_tls_direction;
|
||||||
|
|
||||||
|
#define RB_MAX_CIPHERSUITES 512
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
mbedtls_x509_crt crt;
|
||||||
|
mbedtls_pk_context key;
|
||||||
|
mbedtls_dhm_context dhp;
|
||||||
|
mbedtls_ssl_config server_cfg;
|
||||||
|
mbedtls_ssl_config client_cfg;
|
||||||
|
size_t refcount;
|
||||||
|
int suites[RB_MAX_CIPHERSUITES + 1];
|
||||||
|
} rb_mbedtls_cfg_context;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
rb_mbedtls_cfg_context *cfg;
|
||||||
|
mbedtls_ssl_context ssl;
|
||||||
|
} rb_mbedtls_ssl_context;
|
||||||
|
|
||||||
|
#define SSL_C(x) ((rb_mbedtls_ssl_context *) (x)->ssl)->cfg
|
||||||
|
#define SSL_P(x) &((rb_mbedtls_ssl_context *) (x)->ssl)->ssl
|
||||||
|
|
||||||
|
static mbedtls_ctr_drbg_context ctr_drbg_ctx;
|
||||||
|
static mbedtls_entropy_context entropy_ctx;
|
||||||
|
|
||||||
|
static rb_mbedtls_cfg_context *rb_mbedtls_cfg = NULL;
|
||||||
|
|
||||||
|
#if (MBEDTLS_VERSION_NUMBER < 0x02050100)
|
||||||
|
static mbedtls_x509_crt dummy_ca_ctx;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct ssl_connect
|
||||||
|
{
|
||||||
|
CNCB *callback;
|
||||||
|
void *data;
|
||||||
|
int timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *rb_ssl_strerror(int);
|
||||||
|
static void rb_ssl_connect_realcb(rb_fde_t *, int, struct ssl_connect *);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal MbedTLS-specific code
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_mbedtls_cfg_incref(rb_mbedtls_cfg_context *const cfg)
|
||||||
|
{
|
||||||
|
lrb_assert(cfg->refcount > 0);
|
||||||
|
|
||||||
|
cfg->refcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_mbedtls_cfg_decref(rb_mbedtls_cfg_context *const cfg)
|
||||||
|
{
|
||||||
|
if(cfg == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lrb_assert(cfg->refcount > 0);
|
||||||
|
|
||||||
|
if((--cfg->refcount) > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mbedtls_ssl_config_free(&cfg->client_cfg);
|
||||||
|
mbedtls_ssl_config_free(&cfg->server_cfg);
|
||||||
|
mbedtls_dhm_free(&cfg->dhp);
|
||||||
|
mbedtls_pk_free(&cfg->key);
|
||||||
|
mbedtls_x509_crt_free(&cfg->crt);
|
||||||
|
|
||||||
|
rb_free(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rb_sock_net_recv(void *const context_ptr, unsigned char *const buf, const size_t count)
|
||||||
|
{
|
||||||
|
const int fd = rb_get_fd((rb_fde_t *)context_ptr);
|
||||||
|
|
||||||
|
const int ret = (int) read(fd, buf, count);
|
||||||
|
|
||||||
|
if(ret < 0 && rb_ignore_errno(errno))
|
||||||
|
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rb_sock_net_xmit(void *const context_ptr, const unsigned char *const buf, const size_t count)
|
||||||
|
{
|
||||||
|
const int fd = rb_get_fd((rb_fde_t *)context_ptr);
|
||||||
|
|
||||||
|
const int ret = (int) write(fd, buf, count);
|
||||||
|
|
||||||
|
if(ret < 0 && rb_ignore_errno(errno))
|
||||||
|
return MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_init_fd(rb_fde_t *const F, const rb_fd_tls_direction dir)
|
||||||
|
{
|
||||||
|
rb_mbedtls_ssl_context *const mbed_ssl_ctx = rb_malloc(sizeof *mbed_ssl_ctx);
|
||||||
|
|
||||||
|
if(mbed_ssl_ctx == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: rb_malloc: allocation failure", __func__);
|
||||||
|
rb_close(F);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_ssl_config *mbed_config = NULL;
|
||||||
|
|
||||||
|
switch(dir)
|
||||||
|
{
|
||||||
|
case RB_FD_TLS_DIRECTION_IN:
|
||||||
|
mbed_config = &rb_mbedtls_cfg->server_cfg;
|
||||||
|
break;
|
||||||
|
case RB_FD_TLS_DIRECTION_OUT:
|
||||||
|
mbed_config = &rb_mbedtls_cfg->client_cfg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_ssl_init(&mbed_ssl_ctx->ssl);
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if((ret = mbedtls_ssl_setup(&mbed_ssl_ctx->ssl, mbed_config)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: ssl_setup: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
mbedtls_ssl_free(&mbed_ssl_ctx->ssl);
|
||||||
|
rb_free(mbed_ssl_ctx);
|
||||||
|
rb_close(F);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_ssl_set_bio(&mbed_ssl_ctx->ssl, F, rb_sock_net_xmit, rb_sock_net_recv, NULL);
|
||||||
|
|
||||||
|
rb_mbedtls_cfg_incref(rb_mbedtls_cfg);
|
||||||
|
mbed_ssl_ctx->cfg = rb_mbedtls_cfg;
|
||||||
|
|
||||||
|
F->ssl = mbed_ssl_ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rb_mbedtls_cfg_context *
|
||||||
|
rb_mbedtls_cfg_new(void)
|
||||||
|
{
|
||||||
|
rb_mbedtls_cfg_context *const cfg = rb_malloc(sizeof *cfg);
|
||||||
|
|
||||||
|
if(cfg == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mbedtls_x509_crt_init(&cfg->crt);
|
||||||
|
mbedtls_pk_init(&cfg->key);
|
||||||
|
mbedtls_dhm_init(&cfg->dhp);
|
||||||
|
mbedtls_ssl_config_init(&cfg->server_cfg);
|
||||||
|
mbedtls_ssl_config_init(&cfg->client_cfg);
|
||||||
|
|
||||||
|
(void) memset(cfg->suites, 0x00, sizeof cfg->suites);
|
||||||
|
|
||||||
|
cfg->refcount = 1;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if((ret = mbedtls_ssl_config_defaults(&cfg->server_cfg,
|
||||||
|
MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||||
|
MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: ssl_config_defaults (server): %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
rb_mbedtls_cfg_decref(cfg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((ret = mbedtls_ssl_config_defaults(&cfg->client_cfg,
|
||||||
|
MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||||
|
MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: ssl_config_defaults (client): %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
rb_mbedtls_cfg_decref(cfg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_ssl_conf_rng(&cfg->server_cfg, mbedtls_ctr_drbg_random, &ctr_drbg_ctx);
|
||||||
|
mbedtls_ssl_conf_rng(&cfg->client_cfg, mbedtls_ctr_drbg_random, &ctr_drbg_ctx);
|
||||||
|
|
||||||
|
#if (MBEDTLS_VERSION_NUMBER < 0x02050100)
|
||||||
|
mbedtls_ssl_conf_ca_chain(&cfg->server_cfg, &dummy_ca_ctx, NULL);
|
||||||
|
mbedtls_ssl_conf_ca_chain(&cfg->client_cfg, &dummy_ca_ctx, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mbedtls_ssl_conf_authmode(&cfg->server_cfg, MBEDTLS_SSL_VERIFY_OPTIONAL);
|
||||||
|
mbedtls_ssl_conf_authmode(&cfg->client_cfg, MBEDTLS_SSL_VERIFY_NONE);
|
||||||
|
|
||||||
|
mbedtls_ssl_conf_min_version(&cfg->server_cfg, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_2);
|
||||||
|
mbedtls_ssl_conf_min_version(&cfg->client_cfg, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_2);
|
||||||
|
|
||||||
|
#ifdef MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE
|
||||||
|
mbedtls_ssl_conf_legacy_renegotiation(&cfg->client_cfg, MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MBEDTLS_SSL_SESSION_TICKETS_DISABLED
|
||||||
|
mbedtls_ssl_conf_session_tickets(&cfg->client_cfg, MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_accept_common(rb_fde_t *const F, void *const data)
|
||||||
|
{
|
||||||
|
lrb_assert(F != NULL);
|
||||||
|
lrb_assert(F->accept != NULL);
|
||||||
|
lrb_assert(F->accept->callback != NULL);
|
||||||
|
lrb_assert(F->ssl != NULL);
|
||||||
|
|
||||||
|
(void) data;
|
||||||
|
|
||||||
|
const int ret = mbedtls_ssl_handshake(SSL_P(F));
|
||||||
|
|
||||||
|
switch(ret)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
F->handshake_count++;
|
||||||
|
break;
|
||||||
|
case MBEDTLS_ERR_SSL_WANT_READ:
|
||||||
|
rb_setselect(F, RB_SELECT_READ, rb_ssl_accept_common, NULL);
|
||||||
|
return;
|
||||||
|
case MBEDTLS_ERR_SSL_WANT_WRITE:
|
||||||
|
rb_setselect(F, RB_SELECT_WRITE, rb_ssl_accept_common, NULL);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
errno = EIO;
|
||||||
|
F->ssl_errno = (unsigned long) -ret;
|
||||||
|
F->accept->callback(F, RB_ERROR_SSL, NULL, 0, F->accept->data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_settimeout(F, 0, NULL, NULL);
|
||||||
|
rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
|
||||||
|
|
||||||
|
struct acceptdata *const ad = F->accept;
|
||||||
|
F->accept = NULL;
|
||||||
|
ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
|
||||||
|
rb_free(ad);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_connect_common(rb_fde_t *const F, void *const data)
|
||||||
|
{
|
||||||
|
lrb_assert(F != NULL);
|
||||||
|
lrb_assert(F->ssl != NULL);
|
||||||
|
|
||||||
|
const int ret = mbedtls_ssl_handshake(SSL_P(F));
|
||||||
|
|
||||||
|
switch(ret)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
F->handshake_count++;
|
||||||
|
break;
|
||||||
|
case MBEDTLS_ERR_SSL_WANT_READ:
|
||||||
|
rb_setselect(F, RB_SELECT_READ, rb_ssl_connect_common, data);
|
||||||
|
return;
|
||||||
|
case MBEDTLS_ERR_SSL_WANT_WRITE:
|
||||||
|
rb_setselect(F, RB_SELECT_WRITE, rb_ssl_connect_common, data);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
errno = EIO;
|
||||||
|
F->ssl_errno = (unsigned long) -ret;
|
||||||
|
rb_ssl_connect_realcb(F, RB_ERROR_SSL, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_ssl_connect_realcb(F, RB_OK, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
rb_ssl_strerror(int err)
|
||||||
|
{
|
||||||
|
static char errbuf[512];
|
||||||
|
|
||||||
|
if (err < 0)
|
||||||
|
err = -err;
|
||||||
|
|
||||||
|
#ifdef MBEDTLS_ERROR_C
|
||||||
|
char mbed_errbuf[512];
|
||||||
|
mbedtls_strerror(err, mbed_errbuf, sizeof mbed_errbuf);
|
||||||
|
(void) rb_snprintf(errbuf, sizeof errbuf, "-0x%X: %s", (unsigned int) err, mbed_errbuf);
|
||||||
|
#else
|
||||||
|
(void) rb_snprintf(errbuf, sizeof errbuf, "-0x%X", (unsigned int) err);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return errbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rb_make_certfp(const mbedtls_x509_crt *const peer_cert, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
|
||||||
|
{
|
||||||
|
size_t hashlen = 0;
|
||||||
|
mbedtls_md_type_t md_type;
|
||||||
|
int spki = 0;
|
||||||
|
|
||||||
|
switch(method)
|
||||||
|
{
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA1:
|
||||||
|
md_type = MBEDTLS_MD_SHA1;
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA1;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA256:
|
||||||
|
spki = 1;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA256:
|
||||||
|
md_type = MBEDTLS_MD_SHA256;
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA256;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA512:
|
||||||
|
spki = 1;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA512:
|
||||||
|
md_type = MBEDTLS_MD_SHA512;
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA512;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mbedtls_md_info_t *const md_info = mbedtls_md_info_from_type(md_type);
|
||||||
|
if(md_info == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
void* data = peer_cert->raw.p;
|
||||||
|
size_t datalen = peer_cert->raw.len;
|
||||||
|
|
||||||
|
if(spki)
|
||||||
|
{
|
||||||
|
// Compiler may complain about dropping const qualifier on the cast below
|
||||||
|
// See <https://github.com/ARMmbed/mbedtls/issues/396> -- this is okay
|
||||||
|
|
||||||
|
unsigned char der_pubkey[8192];
|
||||||
|
if((ret = mbedtls_pk_write_pubkey_der((mbedtls_pk_context *)&peer_cert->pk,
|
||||||
|
der_pubkey, sizeof der_pubkey)) < 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: pk_write_pubkey_der: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
data = der_pubkey + (sizeof(der_pubkey) - (size_t)ret);
|
||||||
|
datalen = (size_t)ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((ret = mbedtls_md(md_info, data, datalen, certfp)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: mbedtls_md: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) hashlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External MbedTLS-specific code
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_shutdown(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
if(F == NULL || F->ssl == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
int ret = mbedtls_ssl_close_notify(SSL_P(F));
|
||||||
|
|
||||||
|
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_ssl_free(SSL_P(F));
|
||||||
|
rb_mbedtls_cfg_decref(SSL_C(F));
|
||||||
|
|
||||||
|
rb_free(F->ssl);
|
||||||
|
F->ssl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_init_ssl(void)
|
||||||
|
{
|
||||||
|
mbedtls_ctr_drbg_init(&ctr_drbg_ctx);
|
||||||
|
mbedtls_entropy_init(&entropy_ctx);
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg_ctx, mbedtls_entropy_func, &entropy_ctx,
|
||||||
|
(const unsigned char *)rb_mbedtls_personal_str, sizeof(rb_mbedtls_personal_str))) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: ctr_drbg_seed: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (MBEDTLS_VERSION_NUMBER < 0x02050100)
|
||||||
|
if((ret = mbedtls_x509_crt_parse_der(&dummy_ca_ctx, rb_mbedtls_dummy_ca_certificate,
|
||||||
|
sizeof(rb_mbedtls_dummy_ca_certificate))) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: x509_crt_parse_der (Dummy CA): %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rb_lib_log("%s: MbedTLS backend initialised", __func__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_setup_ssl_server(const char *const certfile, const char *keyfile,
|
||||||
|
const char *const dhfile, const char *const cipherlist, const char *hostname)
|
||||||
|
{
|
||||||
|
if(certfile == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: no certificate file specified", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(keyfile == NULL)
|
||||||
|
keyfile = certfile;
|
||||||
|
|
||||||
|
rb_mbedtls_cfg_context *const newcfg = rb_mbedtls_cfg_new();
|
||||||
|
|
||||||
|
if(newcfg == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: rb_mbedtls_cfg_new: allocation failed", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if((ret = mbedtls_x509_crt_parse_file(&newcfg->crt, certfile)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: x509_crt_parse_file ('%s'): %s", __func__, certfile, rb_ssl_strerror(ret));
|
||||||
|
rb_mbedtls_cfg_decref(newcfg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if((ret = mbedtls_pk_parse_keyfile(&newcfg->key, keyfile, NULL)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: pk_parse_keyfile ('%s'): %s", __func__, keyfile, rb_ssl_strerror(ret));
|
||||||
|
rb_mbedtls_cfg_decref(newcfg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if((ret = mbedtls_pk_check_pair(&newcfg->crt.pk, &newcfg->key)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: pk_check_pair: public/private key mismatch", __func__);
|
||||||
|
rb_mbedtls_cfg_decref(newcfg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if((ret = mbedtls_ssl_conf_own_cert(&newcfg->server_cfg, &newcfg->crt, &newcfg->key)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: ssl_conf_own_cert (server): %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
rb_mbedtls_cfg_decref(newcfg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if((ret = mbedtls_ssl_conf_own_cert(&newcfg->client_cfg, &newcfg->crt, &newcfg->key)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: ssl_conf_own_cert (client): %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
rb_mbedtls_cfg_decref(newcfg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Absense of DH parameters does not matter with mbedTLS, as it comes with its own defaults
|
||||||
|
Thus, clients can still use DHE- ciphersuites, just over a weaker, common DH group
|
||||||
|
So, we do not consider failure to parse DH parameters as fatal */
|
||||||
|
if(dhfile == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: no DH parameters file specified", __func__);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if((ret = mbedtls_dhm_parse_dhmfile(&newcfg->dhp, dhfile)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: dhm_parse_dhmfile ('%s'): %s", __func__, dhfile, rb_ssl_strerror(ret));
|
||||||
|
}
|
||||||
|
else if((ret = mbedtls_ssl_conf_dh_param_ctx(&newcfg->server_cfg, &newcfg->dhp)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: ssl_conf_dh_param_ctx: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const int *rb_ciphersuites = newcfg->suites;
|
||||||
|
size_t suites_count = 0;
|
||||||
|
|
||||||
|
if(cipherlist != NULL)
|
||||||
|
{
|
||||||
|
// The cipherlist is (const char *) -- we should not modify it
|
||||||
|
char *const cipherlist_dup = strdup(cipherlist);
|
||||||
|
|
||||||
|
if(cipherlist_dup != NULL)
|
||||||
|
{
|
||||||
|
char *cipher_str = cipherlist_dup;
|
||||||
|
char *cipher_idx;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// Arbitrary, but the same separator as OpenSSL uses
|
||||||
|
cipher_idx = strchr(cipher_str, ':');
|
||||||
|
|
||||||
|
// This could legitimately be NULL (last ciphersuite in the list)
|
||||||
|
if(cipher_idx != NULL)
|
||||||
|
*cipher_idx = '\0';
|
||||||
|
|
||||||
|
size_t cipher_len = strlen(cipher_str);
|
||||||
|
int cipher_idn = 0;
|
||||||
|
|
||||||
|
// All MbedTLS ciphersuite names begin with these 4 characters
|
||||||
|
if(cipher_len > 4 && strncmp(cipher_str, "TLS-", 4) == 0)
|
||||||
|
cipher_idn = mbedtls_ssl_get_ciphersuite_id(cipher_str);
|
||||||
|
|
||||||
|
// Prevent the same ciphersuite being added multiple times
|
||||||
|
for(size_t x = 0; cipher_idn != 0 && newcfg->suites[x] != 0; x++)
|
||||||
|
if(newcfg->suites[x] == cipher_idn)
|
||||||
|
cipher_idn = 0;
|
||||||
|
|
||||||
|
// Add the suite to the list
|
||||||
|
if(cipher_idn != 0)
|
||||||
|
newcfg->suites[suites_count++] = cipher_idn;
|
||||||
|
|
||||||
|
// Advance the string to the next entry
|
||||||
|
if(cipher_idx)
|
||||||
|
cipher_str = cipher_idx + 1;
|
||||||
|
|
||||||
|
} while(cipher_idx && suites_count < RB_MAX_CIPHERSUITES);
|
||||||
|
|
||||||
|
if(suites_count == 0)
|
||||||
|
rb_lib_log("%s: Ciphersuites provided, but could not parse any", __func__);
|
||||||
|
|
||||||
|
free(cipherlist_dup);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: strdup: %s", __func__, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: No ciphersuite list provided", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(suites_count == 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: Using default ciphersuites", __func__);
|
||||||
|
|
||||||
|
rb_ciphersuites = rb_mbedtls_ciphersuites;
|
||||||
|
suites_count = (sizeof(rb_mbedtls_ciphersuites) / sizeof(rb_mbedtls_ciphersuites[0])) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_ssl_conf_ciphersuites(&newcfg->server_cfg, rb_ciphersuites);
|
||||||
|
mbedtls_ssl_conf_ciphersuites(&newcfg->client_cfg, rb_ciphersuites);
|
||||||
|
rb_lib_log("%s: Configured %zu ciphersuites", __func__, suites_count);
|
||||||
|
|
||||||
|
|
||||||
|
rb_mbedtls_cfg_decref(rb_mbedtls_cfg);
|
||||||
|
rb_mbedtls_cfg = newcfg;
|
||||||
|
|
||||||
|
rb_lib_log("%s: TLS configuration successful", __func__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_init_prng(const char *const path, prng_seed_t seed_type)
|
||||||
|
{
|
||||||
|
(void) path;
|
||||||
|
(void) seed_type;
|
||||||
|
|
||||||
|
rb_lib_log("%s: Skipping PRNG initialisation; not required by MbedTLS backend", __func__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_get_random(void *const buf, const size_t length)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if((ret = mbedtls_ctr_drbg_random(&ctr_drbg_ctx, buf, length)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: ctr_drbg_random: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
rb_get_ssl_strerror(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
const int err = (int) F->ssl_errno;
|
||||||
|
return rb_ssl_strerror(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
|
||||||
|
{
|
||||||
|
if(F == NULL || F->ssl == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const mbedtls_x509_crt *const peer_cert = mbedtls_ssl_get_peer_cert(SSL_P(F));
|
||||||
|
|
||||||
|
if(peer_cert == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return rb_make_certfp(peer_cert, certfp, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_get_ssl_info(char *const buf, const size_t len)
|
||||||
|
{
|
||||||
|
char version_str[512];
|
||||||
|
|
||||||
|
mbedtls_version_get_string(version_str);
|
||||||
|
|
||||||
|
(void) rb_snprintf(buf, len, "ARM mbedTLS: compiled (v%s), library (v%s)",
|
||||||
|
MBEDTLS_VERSION_STRING, version_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
rb_ssl_get_cipher(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
if(F == NULL || F->ssl == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
static char buf[512];
|
||||||
|
|
||||||
|
const char *const version = mbedtls_ssl_get_version(SSL_P(F));
|
||||||
|
const char *const cipher = mbedtls_ssl_get_ciphersuite(SSL_P(F));
|
||||||
|
|
||||||
|
(void) rb_snprintf(buf, sizeof buf, "%s, %s", version, cipher);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
rb_ssl_read(rb_fde_t *const F, void *const buf, const size_t count)
|
||||||
|
{
|
||||||
|
lrb_assert(F != NULL);
|
||||||
|
lrb_assert(F->ssl != NULL);
|
||||||
|
|
||||||
|
const int ret = mbedtls_ssl_read(SSL_P(F), buf, count);
|
||||||
|
|
||||||
|
if(ret >= 0)
|
||||||
|
return (ssize_t) ret;
|
||||||
|
|
||||||
|
switch(ret)
|
||||||
|
{
|
||||||
|
case MBEDTLS_ERR_SSL_WANT_READ:
|
||||||
|
errno = EAGAIN;
|
||||||
|
return RB_RW_SSL_NEED_READ;
|
||||||
|
case MBEDTLS_ERR_SSL_WANT_WRITE:
|
||||||
|
errno = EAGAIN;
|
||||||
|
return RB_RW_SSL_NEED_WRITE;
|
||||||
|
default:
|
||||||
|
errno = EIO;
|
||||||
|
F->ssl_errno = (unsigned long) -ret;
|
||||||
|
return RB_RW_SSL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
rb_ssl_write(rb_fde_t *const F, const void *const buf, const size_t count)
|
||||||
|
{
|
||||||
|
lrb_assert(F != NULL);
|
||||||
|
lrb_assert(F->ssl != NULL);
|
||||||
|
|
||||||
|
const int ret = mbedtls_ssl_write(SSL_P(F), buf, count);
|
||||||
|
|
||||||
|
if(ret >= 0)
|
||||||
|
return (ssize_t) ret;
|
||||||
|
|
||||||
|
switch(ret)
|
||||||
|
{
|
||||||
|
case MBEDTLS_ERR_SSL_WANT_READ:
|
||||||
|
errno = EAGAIN;
|
||||||
|
return RB_RW_SSL_NEED_READ;
|
||||||
|
case MBEDTLS_ERR_SSL_WANT_WRITE:
|
||||||
|
errno = EAGAIN;
|
||||||
|
return RB_RW_SSL_NEED_WRITE;
|
||||||
|
default:
|
||||||
|
errno = EIO;
|
||||||
|
F->ssl_errno = (unsigned long) -ret;
|
||||||
|
return RB_RW_SSL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal library-agnostic code
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_connect_realcb(rb_fde_t *const F, const int status, struct ssl_connect *const sconn)
|
||||||
|
{
|
||||||
|
lrb_assert(F != NULL);
|
||||||
|
lrb_assert(F->connect != NULL);
|
||||||
|
|
||||||
|
F->connect->callback = sconn->callback;
|
||||||
|
F->connect->data = sconn->data;
|
||||||
|
|
||||||
|
rb_connect_callback(F, status);
|
||||||
|
rb_free(sconn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_timeout_cb(rb_fde_t *const F, void *const data)
|
||||||
|
{
|
||||||
|
(void) data;
|
||||||
|
|
||||||
|
lrb_assert(F->accept != NULL);
|
||||||
|
lrb_assert(F->accept->callback != NULL);
|
||||||
|
|
||||||
|
F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_tryconn_timeout_cb(rb_fde_t *const F, void *const data)
|
||||||
|
{
|
||||||
|
rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data)
|
||||||
|
{
|
||||||
|
lrb_assert(F != NULL);
|
||||||
|
|
||||||
|
struct ssl_connect *const sconn = data;
|
||||||
|
|
||||||
|
if(status != RB_OK)
|
||||||
|
{
|
||||||
|
rb_ssl_connect_realcb(F, status, sconn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
F->type |= RB_FD_SSL;
|
||||||
|
|
||||||
|
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
|
||||||
|
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
|
||||||
|
rb_ssl_connect_common(F, sconn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External library-agnostic code
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_supports_ssl(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
rb_ssl_handshake_count(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
return F->handshake_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_clear_handshake_count(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
F->handshake_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_start_accepted(rb_fde_t *const F, ACCB *const cb, void *const data, const int timeout)
|
||||||
|
{
|
||||||
|
F->type |= RB_FD_SSL;
|
||||||
|
|
||||||
|
F->accept = rb_malloc(sizeof(struct acceptdata));
|
||||||
|
F->accept->callback = cb;
|
||||||
|
F->accept->data = data;
|
||||||
|
F->accept->addrlen = 0;
|
||||||
|
(void) memset(&F->accept->S, 0x00, sizeof F->accept->S);
|
||||||
|
|
||||||
|
rb_settimeout(F, timeout, rb_ssl_timeout_cb, NULL);
|
||||||
|
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_IN);
|
||||||
|
rb_ssl_accept_common(F, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_accept_setup(rb_fde_t *const srv_F, rb_fde_t *const cli_F, struct sockaddr *const st, const int addrlen)
|
||||||
|
{
|
||||||
|
cli_F->type |= RB_FD_SSL;
|
||||||
|
|
||||||
|
cli_F->accept = rb_malloc(sizeof(struct acceptdata));
|
||||||
|
cli_F->accept->callback = srv_F->accept->callback;
|
||||||
|
cli_F->accept->data = srv_F->accept->data;
|
||||||
|
cli_F->accept->addrlen = (rb_socklen_t) addrlen;
|
||||||
|
(void) memset(&cli_F->accept->S, 0x00, sizeof cli_F->accept->S);
|
||||||
|
(void) memcpy(&cli_F->accept->S, st, (size_t) addrlen);
|
||||||
|
|
||||||
|
rb_settimeout(cli_F, 10, rb_ssl_timeout_cb, NULL);
|
||||||
|
rb_ssl_init_fd(cli_F, RB_FD_TLS_DIRECTION_IN);
|
||||||
|
rb_ssl_accept_common(cli_F, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_ssl_listen(rb_fde_t *const F, const int backlog, const int defer_accept)
|
||||||
|
{
|
||||||
|
int result = rb_listen(F, backlog, defer_accept);
|
||||||
|
|
||||||
|
F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_connect_tcp_ssl(rb_fde_t *const F, struct sockaddr *const dest, struct sockaddr *const clocal,
|
||||||
|
const int socklen, CNCB *const callback, void *const data, const int timeout)
|
||||||
|
{
|
||||||
|
if(F == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
|
||||||
|
sconn->data = data;
|
||||||
|
sconn->callback = callback;
|
||||||
|
sconn->timeout = timeout;
|
||||||
|
|
||||||
|
rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data, const int timeout)
|
||||||
|
{
|
||||||
|
if(F == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
|
||||||
|
sconn->data = data;
|
||||||
|
sconn->callback = callback;
|
||||||
|
sconn->timeout = timeout;
|
||||||
|
|
||||||
|
F->connect = rb_malloc(sizeof(struct conndata));
|
||||||
|
F->connect->callback = callback;
|
||||||
|
F->connect->data = data;
|
||||||
|
|
||||||
|
F->type |= RB_FD_SSL;
|
||||||
|
|
||||||
|
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
|
||||||
|
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
|
||||||
|
rb_ssl_connect_common(F, sconn);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_MBEDTLS */
|
237
libratbox/src/mbedtls_ratbox.h
Normal file
237
libratbox/src/mbedtls_ratbox.h
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
/*
|
||||||
|
* libratbox: a library used by ircd-ratbox and other things
|
||||||
|
* mbedtls_ratbox.h: embedded data for ARM MbedTLS backend
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Aaron Jones <aaronmdjones@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RB_MBEDTLS_EMBEDDED_DATA_H
|
||||||
|
#define RB_MBEDTLS_EMBEDDED_DATA_H
|
||||||
|
|
||||||
|
#include "mbedtls/entropy.h"
|
||||||
|
#include "mbedtls/ctr_drbg.h"
|
||||||
|
#include "mbedtls/certs.h"
|
||||||
|
#include "mbedtls/x509.h"
|
||||||
|
#include "mbedtls/ssl.h"
|
||||||
|
#include "mbedtls/ssl_ciphersuites.h"
|
||||||
|
#include "mbedtls/error.h"
|
||||||
|
#include "mbedtls/debug.h"
|
||||||
|
#include "mbedtls/dhm.h"
|
||||||
|
#include "mbedtls/version.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Personalization string for CTR-DRBG initialization
|
||||||
|
*/
|
||||||
|
static const char rb_mbedtls_personal_str[] = "charybdis/librb personalization string";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default list of supported ciphersuites
|
||||||
|
* The user can override this with the ssl_cipher_list option in ircd.conf
|
||||||
|
*
|
||||||
|
* The format for this option is the same as the macro names below, but
|
||||||
|
* with underscores replaced with hyphens, and without the initial MBEDTLS_
|
||||||
|
*
|
||||||
|
* For example;
|
||||||
|
* ssl_cipher_list = "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384"
|
||||||
|
*
|
||||||
|
* Multiple ciphersuites can be separated by colons (:)
|
||||||
|
*
|
||||||
|
* ************************************************************************
|
||||||
|
*
|
||||||
|
* The ordering of the following list should be intuitive. Within the list;
|
||||||
|
*
|
||||||
|
* * All AEAD forward-secret ciphersuites are located first [1]
|
||||||
|
* * All SHA2 forward-secret ciphersuites are located second
|
||||||
|
* * All remaining forward-secret ciphersuites are located third
|
||||||
|
* * All non-forward-secret ciphersuites are located last, in the same order
|
||||||
|
*
|
||||||
|
* [1] Because in practice, they are the only secure ciphersuites available;
|
||||||
|
* the ETM extension for CBC ciphersuites has not seen wide adoption.
|
||||||
|
*
|
||||||
|
* In practice, all clients SHOULD support an AEAD forward-secret cipher,
|
||||||
|
* which the server will then negotiate as they are preferred.
|
||||||
|
*
|
||||||
|
* This choice can be revisited in future; please consult me first. -- amdj
|
||||||
|
*/
|
||||||
|
static const int rb_mbedtls_ciphersuites[] = {
|
||||||
|
|
||||||
|
// AEAD forward-secret ciphersuites
|
||||||
|
|
||||||
|
#ifdef MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
|
||||||
|
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
|
MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,
|
||||||
|
|
||||||
|
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,
|
||||||
|
|
||||||
|
// SHA2 forward-secret ciphersuites
|
||||||
|
|
||||||
|
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
|
||||||
|
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
|
||||||
|
// Remaining forward-secret ciphersuites
|
||||||
|
|
||||||
|
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
|
||||||
|
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
|
||||||
|
// Non-forward-secret ciphersuites
|
||||||
|
|
||||||
|
MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
MBEDTLS_TLS_RSA_WITH_AES_256_CCM,
|
||||||
|
|
||||||
|
MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
MBEDTLS_TLS_RSA_WITH_AES_128_CCM,
|
||||||
|
|
||||||
|
MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
|
||||||
|
MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
|
||||||
|
MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
|
||||||
|
MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
|
||||||
|
// The end of list sentinel
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* YES, this is a hardcoded CA certificate.
|
||||||
|
*
|
||||||
|
* BEFORE YOU THROW YOUR ARMS UP IN A PANIC ABOUT A BACKDOOR, READ THIS TEXT!
|
||||||
|
*
|
||||||
|
* ARM mbedTLS required a CA certificate to be set in its configuration before it will
|
||||||
|
* process a client certificate from peers. Since we want to do that, and not all
|
||||||
|
* installations will have a CA certificate to hand, we have this.
|
||||||
|
*
|
||||||
|
* Its key was securely destroyed after being generated, but even if it wasn't, that
|
||||||
|
* doesn't matter; the IRCd will accept ALL certificates, whether signed by this CA
|
||||||
|
* certificate or not!
|
||||||
|
*
|
||||||
|
* After all, it only cares about certificates in as far as to generate a fingerprint
|
||||||
|
* for them.
|
||||||
|
*
|
||||||
|
* Yes, this is a massive hack, but there is no alternative for older versions.
|
||||||
|
*
|
||||||
|
* This issue was fixed in commit 39ae8cd2077d on the MbedTLS 2.5 development branch,
|
||||||
|
* released in version 2.5.1 on 19 June 2017. This certificate will not be used if
|
||||||
|
* that version (or greater) is installed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (MBEDTLS_VERSION_NUMBER < 0x02050100)
|
||||||
|
|
||||||
|
static const unsigned char rb_mbedtls_dummy_ca_certificate[825] = {
|
||||||
|
0x30, 0x82, 0x03, 0x35, 0x30, 0x82, 0x02, 0x1D, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
|
||||||
|
0x86, 0xC5, 0x1F, 0x62, 0xBE, 0xFC, 0x0B, 0xA8, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
|
||||||
|
0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x31, 0x31, 0x2F, 0x30, 0x2D, 0x06, 0x03, 0x55,
|
||||||
|
0x04, 0x03, 0x0C, 0x26, 0x43, 0x68, 0x61, 0x72, 0x79, 0x62, 0x64, 0x69, 0x73, 0x20, 0x6D, 0x62,
|
||||||
|
0x65, 0x64, 0x54, 0x4C, 0x53, 0x20, 0x44, 0x75, 0x6D, 0x6D, 0x79, 0x20, 0x43, 0x41, 0x20, 0x43,
|
||||||
|
0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x36,
|
||||||
|
0x30, 0x35, 0x30, 0x34, 0x30, 0x38, 0x35, 0x32, 0x35, 0x33, 0x5A, 0x17, 0x0D, 0x34, 0x33, 0x30,
|
||||||
|
0x39, 0x32, 0x30, 0x30, 0x38, 0x35, 0x32, 0x35, 0x33, 0x5A, 0x30, 0x31, 0x31, 0x2F, 0x30, 0x2D,
|
||||||
|
0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x26, 0x43, 0x68, 0x61, 0x72, 0x79, 0x62, 0x64, 0x69, 0x73,
|
||||||
|
0x20, 0x6D, 0x62, 0x65, 0x64, 0x54, 0x4C, 0x53, 0x20, 0x44, 0x75, 0x6D, 0x6D, 0x79, 0x20, 0x43,
|
||||||
|
0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x82, 0x01,
|
||||||
|
0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00,
|
||||||
|
0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xCA, 0x4B,
|
||||||
|
0xA6, 0xA1, 0x82, 0x5B, 0x06, 0xC6, 0x82, 0x76, 0x8E, 0xB2, 0x22, 0x37, 0x83, 0x91, 0x4B, 0xD0,
|
||||||
|
0xAE, 0x2F, 0xEE, 0x8E, 0x60, 0x04, 0xBA, 0x77, 0x8C, 0xD0, 0xCF, 0x5E, 0xA4, 0xFD, 0x80, 0xA1,
|
||||||
|
0x2E, 0xDC, 0x1F, 0xD9, 0x72, 0x2C, 0x28, 0x03, 0x27, 0x48, 0x23, 0x6E, 0x41, 0x49, 0x62, 0x09,
|
||||||
|
0x2D, 0xCF, 0x87, 0xA1, 0x45, 0x9D, 0x2B, 0x43, 0x6F, 0xBB, 0xDB, 0x23, 0xD8, 0xD9, 0x6D, 0x36,
|
||||||
|
0x4E, 0xA3, 0x85, 0x40, 0x4D, 0x72, 0xEC, 0x7B, 0xEF, 0x2B, 0x13, 0xE4, 0x6F, 0xDA, 0x23, 0x4F,
|
||||||
|
0x1C, 0xE7, 0xEA, 0xD9, 0x17, 0x2B, 0xD6, 0x67, 0x79, 0x42, 0xC3, 0x81, 0x9A, 0x77, 0x64, 0xC7,
|
||||||
|
0xC5, 0x44, 0xE1, 0xA4, 0xA3, 0x50, 0x8C, 0x1F, 0xCA, 0xD3, 0x6F, 0xC7, 0xFF, 0x2C, 0xBA, 0x7B,
|
||||||
|
0x21, 0x0C, 0xF3, 0xA9, 0x6A, 0x89, 0x74, 0x33, 0x60, 0xA1, 0xF8, 0x9F, 0xAA, 0x39, 0xA9, 0x45,
|
||||||
|
0x7E, 0x3D, 0x41, 0x67, 0x04, 0xF5, 0x9F, 0x47, 0x62, 0xAC, 0x65, 0xE0, 0x8D, 0x46, 0x9E, 0xD9,
|
||||||
|
0xE5, 0x77, 0xD5, 0x8C, 0x47, 0xA2, 0xFB, 0x7D, 0x94, 0x27, 0xC9, 0xB9, 0x3F, 0x4D, 0xF4, 0xFD,
|
||||||
|
0x19, 0x3C, 0xF6, 0x24, 0xAE, 0x70, 0xD7, 0x23, 0xE4, 0x64, 0x0A, 0xFC, 0x63, 0x89, 0x8A, 0xFE,
|
||||||
|
0xD0, 0x8E, 0x48, 0x1A, 0xD8, 0xC3, 0xA9, 0xEC, 0x9D, 0x0F, 0xC7, 0xC5, 0x22, 0xBC, 0x45, 0x4A,
|
||||||
|
0x2F, 0x4D, 0xF5, 0x0E, 0x4F, 0xFF, 0xAC, 0xE0, 0x55, 0xF4, 0x86, 0x04, 0x1B, 0x60, 0xDF, 0x4C,
|
||||||
|
0x25, 0xB9, 0xEC, 0x10, 0x0C, 0x54, 0x16, 0xDF, 0x42, 0xF0, 0x07, 0x00, 0x28, 0x81, 0x7C, 0x95,
|
||||||
|
0xAA, 0xC1, 0x01, 0xA3, 0xB8, 0xDF, 0x68, 0xCB, 0x55, 0xA7, 0x80, 0xCC, 0xE5, 0x3D, 0xE1, 0x68,
|
||||||
|
0x10, 0x27, 0x56, 0x94, 0x67, 0xEC, 0x82, 0x66, 0x3D, 0x96, 0x76, 0xC3, 0xEE, 0x23, 0x02, 0x03,
|
||||||
|
0x01, 0x00, 0x01, 0xA3, 0x50, 0x30, 0x4E, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16,
|
||||||
|
0x04, 0x14, 0xFF, 0xC8, 0xBA, 0x56, 0x74, 0xB1, 0x03, 0xA9, 0x79, 0x55, 0xFA, 0x58, 0x86, 0x13,
|
||||||
|
0xDE, 0xC0, 0xFA, 0xF2, 0x94, 0x62, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30,
|
||||||
|
0x16, 0x80, 0x14, 0xFF, 0xC8, 0xBA, 0x56, 0x74, 0xB1, 0x03, 0xA9, 0x79, 0x55, 0xFA, 0x58, 0x86,
|
||||||
|
0x13, 0xDE, 0xC0, 0xFA, 0xF2, 0x94, 0x62, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05,
|
||||||
|
0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
|
||||||
|
0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x3D, 0x35, 0x69, 0x87, 0xEB, 0x41, 0xA9,
|
||||||
|
0x2A, 0x51, 0xF3, 0x28, 0x71, 0xB4, 0x06, 0x7F, 0x15, 0x5A, 0x6D, 0x88, 0x5B, 0xC8, 0x4C, 0xE1,
|
||||||
|
0x6C, 0xC7, 0xCB, 0x93, 0x63, 0x69, 0xFB, 0xA6, 0x6D, 0xC7, 0x44, 0x6B, 0xD6, 0x39, 0x46, 0x34,
|
||||||
|
0xFC, 0x45, 0x23, 0xD2, 0x29, 0x1B, 0xCC, 0x1C, 0x13, 0xD7, 0x63, 0x10, 0x81, 0xF5, 0x82, 0x45,
|
||||||
|
0xEC, 0xDC, 0x20, 0x5F, 0xBB, 0xC3, 0xE6, 0x4A, 0x07, 0xA7, 0xBD, 0x9E, 0xFC, 0x5D, 0xFE, 0xC5,
|
||||||
|
0x43, 0x3A, 0xC6, 0xA4, 0x6C, 0x5B, 0xF9, 0x63, 0x8F, 0xF9, 0xEB, 0xC2, 0xF4, 0xA7, 0xE4, 0x1B,
|
||||||
|
0x23, 0xFA, 0xE1, 0x5A, 0x79, 0xC5, 0x1D, 0x1D, 0xFC, 0xAA, 0x81, 0xF7, 0x21, 0x52, 0xC9, 0x46,
|
||||||
|
0x17, 0x1B, 0x24, 0x4B, 0x14, 0x5C, 0xF9, 0xB5, 0x86, 0x04, 0x80, 0x51, 0x95, 0xCF, 0x4E, 0x47,
|
||||||
|
0x32, 0x8A, 0x1E, 0x52, 0x2E, 0xBF, 0x08, 0x8E, 0x9E, 0xE3, 0x88, 0x45, 0xC3, 0x75, 0xD7, 0xAE,
|
||||||
|
0xC3, 0x7E, 0x7E, 0xE9, 0xC9, 0x5B, 0xD8, 0x58, 0x3B, 0x25, 0x53, 0x0C, 0x00, 0x21, 0x1A, 0x71,
|
||||||
|
0x12, 0x23, 0xA0, 0x35, 0x6E, 0xC9, 0x7D, 0x83, 0x5C, 0x19, 0xE4, 0x05, 0x84, 0x46, 0x4E, 0x50,
|
||||||
|
0xE2, 0x9E, 0x70, 0x2E, 0x74, 0x05, 0xEA, 0x31, 0x04, 0x55, 0xA7, 0xF4, 0x67, 0x95, 0xDC, 0x86,
|
||||||
|
0x1F, 0x9D, 0xA0, 0x5D, 0x7F, 0x29, 0x48, 0x84, 0xEF, 0x13, 0xB8, 0xB3, 0xBF, 0x65, 0xD4, 0x52,
|
||||||
|
0x98, 0x06, 0xE6, 0x8A, 0xB1, 0x36, 0xEA, 0x39, 0xB3, 0x04, 0x2B, 0x6E, 0x64, 0x6E, 0xF3, 0x20,
|
||||||
|
0x74, 0xB6, 0x6E, 0x21, 0x3B, 0x99, 0xFE, 0x6E, 0x70, 0x48, 0x78, 0xEA, 0x31, 0x95, 0xB3, 0xB0,
|
||||||
|
0x0E, 0x48, 0x83, 0x35, 0xA9, 0x74, 0xBF, 0x45, 0x07, 0xC8, 0x5A, 0x12, 0xA2, 0x4D, 0x16, 0xDB,
|
||||||
|
0xB3, 0x1F, 0x72, 0xDE, 0x2A, 0x28, 0xFE, 0x7C, 0x2D
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MBEDTLS_VERSION_NUMBER */
|
||||||
|
|
||||||
|
#endif /* RB_MBEDTLS_EMBEDDED_DATA_H */
|
185
libratbox/src/nossl.c
Normal file
185
libratbox/src/nossl.c
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
/*
|
||||||
|
* libratbox: a library used by ircd-ratbox and other things
|
||||||
|
* nossl.c: ssl stub code
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2008 ircd-ratbox development team
|
||||||
|
* Copyright (C) 2007-2008 Aaron Sethman <androsyn@ratbox.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: commio.c 24808 2008-01-02 08:17:05Z androsyn $
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <libratbox_config.h>
|
||||||
|
#include <ratbox_lib.h>
|
||||||
|
#if !defined(HAVE_OPENSSL) && !defined(HAVE_GNUTLS) && !defined(HAVE_MBEDTLS)
|
||||||
|
|
||||||
|
#include "arc4random.h"
|
||||||
|
|
||||||
|
#include <commio-int.h>
|
||||||
|
#include <commio-ssl.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list, const char *hostname)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_init_ssl(void)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_stir_arc4random(void *unused)
|
||||||
|
{
|
||||||
|
arc4random_stir();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_init_prng(const char *path, prng_seed_t seed_type)
|
||||||
|
{
|
||||||
|
/* xxx this ignores the parameters above */
|
||||||
|
arc4random_stir();
|
||||||
|
rb_event_addish("rb_stir_arc4random", rb_stir_arc4random, NULL, 300);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_get_random(void *buf, size_t length)
|
||||||
|
{
|
||||||
|
uint32_t rnd = 0, i;
|
||||||
|
uint8_t *xbuf = buf;
|
||||||
|
for(i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
if(i % 4 == 0)
|
||||||
|
rnd = arc4random();
|
||||||
|
xbuf[i] = rnd;
|
||||||
|
rnd >>= 8;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
rb_get_ssl_strerror(rb_fde_t *F)
|
||||||
|
{
|
||||||
|
static const char *nosupport = "SSL/TLS not supported";
|
||||||
|
return nosupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest,
|
||||||
|
struct sockaddr *clocal, int socklen, CNCB * callback, void *data, int timeout)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_supports_ssl(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_shutdown(rb_fde_t *F)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrlen)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
rb_ssl_read(rb_fde_t *F, void *buf, size_t count)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
rb_ssl_write(rb_fde_t *F, const void *buf, size_t count)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
rb_ssl_handshake_count(rb_fde_t *F)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_clear_handshake_count(rb_fde_t *F)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_get_ssl_info(char *buf, size_t len)
|
||||||
|
{
|
||||||
|
rb_snprintf(buf, len, "Not compiled with SSL support");
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_ssl_get_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN])
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
rb_ssl_get_cipher(rb_fde_t *F)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !HAVE_OPENSSL */
|
850
libratbox/src/openssl.c
Normal file
850
libratbox/src/openssl.c
Normal file
|
@ -0,0 +1,850 @@
|
||||||
|
/*
|
||||||
|
* libratbox: a library used by ircd-ratbox and other things
|
||||||
|
* openssl.c: OpenSSL backend
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2008 ircd-ratbox development team
|
||||||
|
* Copyright (C) 2007-2008 Aaron Sethman <androsyn@ratbox.org>
|
||||||
|
* Copyright (C) 2015-2016 Aaron Jones <aaronmdjones@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libratbox_config.h>
|
||||||
|
#include <ratbox_lib.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
|
||||||
|
#include <commio-int.h>
|
||||||
|
#include <commio-ssl.h>
|
||||||
|
|
||||||
|
#include "openssl_ratbox.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
RB_FD_TLS_DIRECTION_IN = 0,
|
||||||
|
RB_FD_TLS_DIRECTION_OUT = 1
|
||||||
|
} rb_fd_tls_direction;
|
||||||
|
|
||||||
|
#define SSL_P(x) ((SSL *)((x)->ssl))
|
||||||
|
|
||||||
|
typedef struct ssl_vhost_s
|
||||||
|
{
|
||||||
|
char *hostname;
|
||||||
|
SSL_CTX *ctx;
|
||||||
|
rb_dlink_node node;
|
||||||
|
} ssl_vhost;
|
||||||
|
|
||||||
|
static SSL_CTX *ssl_ctx = NULL;
|
||||||
|
rb_dlink_list ssl_vhosts;
|
||||||
|
|
||||||
|
rb_dlink_node *
|
||||||
|
find_ssl_vhost(const char *hostname)
|
||||||
|
{
|
||||||
|
ssl_vhost *vhost_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, ssl_vhosts.head)
|
||||||
|
{
|
||||||
|
vhost_p = ptr->data;
|
||||||
|
|
||||||
|
if(!strcmp(hostname,vhost_p->hostname))
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssl_connect
|
||||||
|
{
|
||||||
|
CNCB *callback;
|
||||||
|
void *data;
|
||||||
|
int timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *rb_ssl_strerror(unsigned long);
|
||||||
|
static void rb_ssl_connect_realcb(rb_fde_t *, int, struct ssl_connect *);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal OpenSSL-specific code
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned long
|
||||||
|
rb_ssl_last_err(void)
|
||||||
|
{
|
||||||
|
unsigned long err_saved, err = 0;
|
||||||
|
|
||||||
|
while((err_saved = ERR_get_error()) != 0)
|
||||||
|
err = err_saved;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_init_fd(rb_fde_t *const F, const rb_fd_tls_direction dir)
|
||||||
|
{
|
||||||
|
(void) rb_ssl_last_err();
|
||||||
|
|
||||||
|
F->ssl = SSL_new(ssl_ctx);
|
||||||
|
|
||||||
|
if(F->ssl == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: SSL_new: %s", __func__, rb_ssl_strerror(rb_ssl_last_err()));
|
||||||
|
rb_close(F);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(dir)
|
||||||
|
{
|
||||||
|
case RB_FD_TLS_DIRECTION_IN:
|
||||||
|
SSL_set_accept_state(SSL_P(F));
|
||||||
|
break;
|
||||||
|
case RB_FD_TLS_DIRECTION_OUT:
|
||||||
|
SSL_set_connect_state(SSL_P(F));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_set_fd(SSL_P(F), rb_get_fd(F));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_accept_common(rb_fde_t *const F, void *const data)
|
||||||
|
{
|
||||||
|
lrb_assert(F != NULL);
|
||||||
|
lrb_assert(F->accept != NULL);
|
||||||
|
lrb_assert(F->accept->callback != NULL);
|
||||||
|
lrb_assert(F->ssl != NULL);
|
||||||
|
|
||||||
|
(void) rb_ssl_last_err();
|
||||||
|
|
||||||
|
int ret = SSL_do_handshake(SSL_P(F));
|
||||||
|
int err = SSL_get_error(SSL_P(F), ret);
|
||||||
|
|
||||||
|
if(ret == 1)
|
||||||
|
{
|
||||||
|
F->handshake_count++;
|
||||||
|
|
||||||
|
rb_settimeout(F, 0, NULL, NULL);
|
||||||
|
rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
|
||||||
|
|
||||||
|
struct acceptdata *const ad = F->accept;
|
||||||
|
F->accept = NULL;
|
||||||
|
ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
|
||||||
|
rb_free(ad);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(ret == -1 && err == SSL_ERROR_WANT_READ)
|
||||||
|
{
|
||||||
|
rb_setselect(F, RB_SELECT_READ, rb_ssl_accept_common, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(ret == -1 && err == SSL_ERROR_WANT_WRITE)
|
||||||
|
{
|
||||||
|
rb_setselect(F, RB_SELECT_WRITE, rb_ssl_accept_common, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = EIO;
|
||||||
|
F->ssl_errno = (unsigned long) err;
|
||||||
|
F->accept->callback(F, RB_ERROR_SSL, NULL, 0, F->accept->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_connect_common(rb_fde_t *const F, void *const data)
|
||||||
|
{
|
||||||
|
lrb_assert(F != NULL);
|
||||||
|
lrb_assert(F->ssl != NULL);
|
||||||
|
|
||||||
|
(void) rb_ssl_last_err();
|
||||||
|
|
||||||
|
int ret = SSL_do_handshake(SSL_P(F));
|
||||||
|
int err = SSL_get_error(SSL_P(F), ret);
|
||||||
|
|
||||||
|
if(ret == 1)
|
||||||
|
{
|
||||||
|
F->handshake_count++;
|
||||||
|
|
||||||
|
rb_settimeout(F, 0, NULL, NULL);
|
||||||
|
rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
|
||||||
|
|
||||||
|
rb_ssl_connect_realcb(F, RB_OK, data);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(ret == -1 && err == SSL_ERROR_WANT_READ)
|
||||||
|
{
|
||||||
|
rb_setselect(F, RB_SELECT_READ, rb_ssl_connect_common, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(ret == -1 && err == SSL_ERROR_WANT_WRITE)
|
||||||
|
{
|
||||||
|
rb_setselect(F, RB_SELECT_WRITE, rb_ssl_connect_common, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = EIO;
|
||||||
|
F->ssl_errno = (unsigned long) err;
|
||||||
|
rb_ssl_connect_realcb(F, RB_ERROR_SSL, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
rb_ssl_strerror(const unsigned long err)
|
||||||
|
{
|
||||||
|
static char errbuf[512];
|
||||||
|
|
||||||
|
ERR_error_string_n(err, errbuf, sizeof errbuf);
|
||||||
|
|
||||||
|
return errbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
verify_accept_all_cb(const int preverify_ok, X509_STORE_CTX *const x509_ctx)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, const void *const wbuf, const size_t count)
|
||||||
|
{
|
||||||
|
ssize_t ret;
|
||||||
|
unsigned long err;
|
||||||
|
|
||||||
|
(void) rb_ssl_last_err();
|
||||||
|
|
||||||
|
if(r_or_w == 0)
|
||||||
|
ret = (ssize_t) SSL_read(SSL_P(F), rbuf, (int)count);
|
||||||
|
else
|
||||||
|
ret = (ssize_t) SSL_write(SSL_P(F), wbuf, (int)count);
|
||||||
|
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
switch(SSL_get_error(SSL_P(F), ret))
|
||||||
|
{
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
errno = EAGAIN;
|
||||||
|
return RB_RW_SSL_NEED_READ;
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
errno = EAGAIN;
|
||||||
|
return RB_RW_SSL_NEED_WRITE;
|
||||||
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
|
return 0;
|
||||||
|
case SSL_ERROR_SYSCALL:
|
||||||
|
err = rb_ssl_last_err();
|
||||||
|
if(err == 0)
|
||||||
|
{
|
||||||
|
F->ssl_errno = 0;
|
||||||
|
return RB_RW_IO_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = rb_ssl_last_err();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
F->ssl_errno = err;
|
||||||
|
if(err > 0)
|
||||||
|
{
|
||||||
|
errno = EIO; /* not great but... */
|
||||||
|
return RB_RW_SSL_ERROR;
|
||||||
|
}
|
||||||
|
return RB_RW_IO_ERROR;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
make_certfp(X509 *const cert, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
|
||||||
|
{
|
||||||
|
unsigned int hashlen = 0;
|
||||||
|
const EVP_MD *md_type = NULL;
|
||||||
|
const ASN1_ITEM *item = NULL;
|
||||||
|
void *data = NULL;
|
||||||
|
|
||||||
|
switch(method)
|
||||||
|
{
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA1:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA1;
|
||||||
|
md_type = EVP_sha1();
|
||||||
|
item = ASN1_ITEM_rptr(X509);
|
||||||
|
data = cert;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA256:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA256;
|
||||||
|
md_type = EVP_sha256();
|
||||||
|
item = ASN1_ITEM_rptr(X509);
|
||||||
|
data = cert;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA512:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA512;
|
||||||
|
md_type = EVP_sha512();
|
||||||
|
item = ASN1_ITEM_rptr(X509);
|
||||||
|
data = cert;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA256:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA256;
|
||||||
|
md_type = EVP_sha256();
|
||||||
|
item = ASN1_ITEM_rptr(X509_PUBKEY);
|
||||||
|
data = X509_get_X509_PUBKEY(cert);
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA512:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA512;
|
||||||
|
md_type = EVP_sha512();
|
||||||
|
item = ASN1_ITEM_rptr(X509_PUBKEY);
|
||||||
|
data = X509_get_X509_PUBKEY(cert);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ASN1_item_digest(item, md_type, data, certfp, &hashlen) != 1)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: ASN1_item_digest: %s", __func__, rb_ssl_strerror(rb_ssl_last_err()));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) hashlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External OpenSSL-specific code
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_shutdown(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
if(F == NULL || F->ssl == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
(void) rb_ssl_last_err();
|
||||||
|
|
||||||
|
for(int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
int ret = SSL_shutdown(SSL_P(F));
|
||||||
|
int err = SSL_get_error(SSL_P(F), ret);
|
||||||
|
|
||||||
|
if(ret >= 0 || (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_free(SSL_P(F));
|
||||||
|
F->ssl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_init_ssl(void)
|
||||||
|
{
|
||||||
|
#ifndef LRB_SSL_NO_EXPLICIT_INIT
|
||||||
|
(void) SSL_library_init();
|
||||||
|
SSL_load_error_strings();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rb_lib_log("%s: OpenSSL backend initialised", __func__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rb_ssl_servername_cb(SSL *s, int *ad, void *arg)
|
||||||
|
{
|
||||||
|
ssl_vhost *vhost_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
rb_dlink_node *next_ptr;
|
||||||
|
|
||||||
|
const char * servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
|
||||||
|
|
||||||
|
rb_lib_log("Hostname in TLS extension?");
|
||||||
|
if (servername)
|
||||||
|
{
|
||||||
|
rb_lib_log("Hostname in TLS extension %s", servername);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, ssl_vhosts.head)
|
||||||
|
{
|
||||||
|
vhost_p = ptr->data;
|
||||||
|
|
||||||
|
if (strcmp(servername, vhost_p->hostname) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (vhost_p->ctx)
|
||||||
|
{
|
||||||
|
rb_lib_log("Switching server context %s", servername);
|
||||||
|
SSL_set_SSL_CTX(s,vhost_p->ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SSL_TLSEXT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free_ssl_vhost(ssl_vhost *vhost_p)
|
||||||
|
{
|
||||||
|
if(vhost_p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rb_free(vhost_p->hostname);
|
||||||
|
|
||||||
|
SSL_CTX_free(vhost_p->ctx);
|
||||||
|
rb_free(vhost_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_remove_ssl_vserver(const char *hostname)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr = find_ssl_vhost(hostname);
|
||||||
|
if(ptr != NULL && ptr) {
|
||||||
|
rb_dlinkDelete(ptr, &ssl_vhosts);
|
||||||
|
free_ssl_vhost(ptr->data);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_setup_ssl_server(const char *const certfile, const char *keyfile,
|
||||||
|
const char *const dhfile, const char *cipherlist,
|
||||||
|
const char *hostname)
|
||||||
|
{
|
||||||
|
if(certfile == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: no certificate file specified", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(keyfile == NULL)
|
||||||
|
keyfile = certfile;
|
||||||
|
|
||||||
|
if(cipherlist == NULL)
|
||||||
|
cipherlist = rb_default_ciphers;
|
||||||
|
|
||||||
|
|
||||||
|
(void) rb_ssl_last_err();
|
||||||
|
|
||||||
|
#ifdef LRB_HAVE_TLS_METHOD_API
|
||||||
|
SSL_CTX *const ssl_ctx_new = SSL_CTX_new(TLS_method());
|
||||||
|
#else
|
||||||
|
SSL_CTX *const ssl_ctx_new = SSL_CTX_new(SSLv23_method());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(ssl_ctx_new == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: SSL_CTX_new: %s", __func__, rb_ssl_strerror(rb_ssl_last_err()));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SSL_CTX_use_certificate_chain_file(ssl_ctx_new, certfile) != 1)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: SSL_CTX_use_certificate_chain_file ('%s'): %s", __func__, certfile,
|
||||||
|
rb_ssl_strerror(rb_ssl_last_err()));
|
||||||
|
|
||||||
|
SSL_CTX_free(ssl_ctx_new);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SSL_CTX_use_PrivateKey_file(ssl_ctx_new, keyfile, SSL_FILETYPE_PEM) != 1)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: SSL_CTX_use_PrivateKey_file ('%s'): %s", __func__, keyfile,
|
||||||
|
rb_ssl_strerror(rb_ssl_last_err()));
|
||||||
|
|
||||||
|
SSL_CTX_free(ssl_ctx_new);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dhfile == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: no DH parameters file specified", __func__);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FILE *const dhf = fopen(dhfile, "r");
|
||||||
|
DH *dhp = NULL;
|
||||||
|
|
||||||
|
if(dhf == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: fopen ('%s'): %s", __func__, dhfile, strerror(errno));
|
||||||
|
}
|
||||||
|
else if(PEM_read_DHparams(dhf, &dhp, NULL, NULL) == NULL)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: PEM_read_DHparams ('%s'): %s", __func__, dhfile,
|
||||||
|
rb_ssl_strerror(rb_ssl_last_err()));
|
||||||
|
fclose(dhf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SSL_CTX_set_tmp_dh(ssl_ctx_new, dhp);
|
||||||
|
DH_free(dhp);
|
||||||
|
fclose(dhf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SSL_CTX_set_cipher_list(ssl_ctx_new, cipherlist) != 1)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: SSL_CTX_set_cipher_list: could not configure any ciphers", __func__);
|
||||||
|
SSL_CTX_free(ssl_ctx_new);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SSL_CTX_set_tlsext_servername_callback(ssl_ctx_new, rb_ssl_servername_cb);
|
||||||
|
|
||||||
|
SSL_CTX_set_session_cache_mode(ssl_ctx_new, SSL_SESS_CACHE_OFF);
|
||||||
|
SSL_CTX_set_verify(ssl_ctx_new, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb);
|
||||||
|
|
||||||
|
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
|
||||||
|
(void) SSL_CTX_clear_options(ssl_ctx_new, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LRB_HAVE_TLS_METHOD_API
|
||||||
|
(void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SSL_OP_NO_TLSv1
|
||||||
|
(void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_NO_TLSv1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SSL_OP_NO_TICKET
|
||||||
|
(void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_NO_TICKET);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
|
||||||
|
(void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SSL_OP_SINGLE_DH_USE
|
||||||
|
(void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_SINGLE_DH_USE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SSL_OP_SINGLE_ECDH_USE
|
||||||
|
(void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_SINGLE_ECDH_USE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LRB_HAVE_TLS_ECDH_AUTO
|
||||||
|
(void) SSL_CTX_set_ecdh_auto(ssl_ctx_new, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LRB_HAVE_TLS_SET_CURVES
|
||||||
|
(void) SSL_CTX_set1_curves_list(ssl_ctx_new, rb_default_curves);
|
||||||
|
#else
|
||||||
|
# if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && !defined(OPENSSL_NO_ECDH) && defined(NID_secp384r1)
|
||||||
|
EC_KEY *const ec_key = EC_KEY_new_by_curve_name(NID_secp384r1);
|
||||||
|
if(ec_key != NULL)
|
||||||
|
{
|
||||||
|
SSL_CTX_set_tmp_ecdh(ssl_ctx_new, ec_key);
|
||||||
|
EC_KEY_free(ec_key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rb_lib_log("%s: EC_KEY_new_by_curve_name failed; will not enable ECDHE- ciphers", __func__);
|
||||||
|
# else
|
||||||
|
rb_lib_log("%s: OpenSSL built without ECDH support; will not enable ECDHE- ciphers", __func__);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rb_lib_log("%s: TLS configuration successful", __func__);
|
||||||
|
if(hostname == NULL) {
|
||||||
|
if(ssl_ctx)
|
||||||
|
SSL_CTX_free(ssl_ctx);
|
||||||
|
|
||||||
|
ssl_ctx = ssl_ctx_new;
|
||||||
|
} else {
|
||||||
|
ssl_vhost *vhost_p = NULL;
|
||||||
|
|
||||||
|
rb_lib_log("rb_setup_ssl_server: SETUP [%s]", hostname);
|
||||||
|
rb_dlink_node *ptr = find_ssl_vhost(hostname);
|
||||||
|
if(ptr != NULL && ptr)
|
||||||
|
vhost_p = ptr->data;
|
||||||
|
|
||||||
|
if(vhost_p == NULL) {
|
||||||
|
vhost_p = rb_malloc(sizeof(ssl_vhost));
|
||||||
|
vhost_p->hostname = rb_strdup(hostname);
|
||||||
|
|
||||||
|
rb_dlinkAdd(vhost_p, &vhost_p->node, &ssl_vhosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(vhost_p->ctx)
|
||||||
|
SSL_CTX_free(vhost_p->ctx);
|
||||||
|
|
||||||
|
vhost_p->ctx = ssl_ctx_new;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_init_prng(const char *const path, prng_seed_t seed_type)
|
||||||
|
{
|
||||||
|
(void) rb_ssl_last_err();
|
||||||
|
|
||||||
|
if(seed_type == RB_PRNG_FILE && RAND_load_file(path, -1) < 0)
|
||||||
|
rb_lib_log("%s: RAND_load_file: %s", __func__, rb_ssl_strerror(rb_ssl_last_err()));
|
||||||
|
|
||||||
|
if(RAND_status() != 1)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: RAND_status: %s", __func__, rb_ssl_strerror(rb_ssl_last_err()));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_lib_log("%s: PRNG initialised", __func__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_get_random(void *const buf, const size_t length)
|
||||||
|
{
|
||||||
|
(void) rb_ssl_last_err();
|
||||||
|
|
||||||
|
if(RAND_bytes(buf, (int) length) != 1)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: RAND_bytes: %s", __func__, rb_ssl_strerror(rb_ssl_last_err()));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
rb_get_ssl_strerror(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
return rb_ssl_strerror(F->ssl_errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
|
||||||
|
{
|
||||||
|
if(F == NULL || F->ssl == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
X509 *const peer_cert = SSL_get_peer_certificate(SSL_P(F));
|
||||||
|
if(peer_cert == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
switch(SSL_get_verify_result(SSL_P(F)))
|
||||||
|
{
|
||||||
|
case X509_V_OK:
|
||||||
|
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
|
||||||
|
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
|
||||||
|
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
|
||||||
|
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
|
||||||
|
case X509_V_ERR_CERT_UNTRUSTED:
|
||||||
|
len = make_certfp(peer_cert, certfp, method);
|
||||||
|
default:
|
||||||
|
X509_free(peer_cert);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_get_ssl_info(char *const buf, const size_t len)
|
||||||
|
{
|
||||||
|
#ifdef LRB_SSL_FULL_VERSION_INFO
|
||||||
|
if(LRB_SSL_VNUM_RUNTIME == LRB_SSL_VNUM_COMPILETIME)
|
||||||
|
(void) rb_snprintf(buf, len, "OpenSSL: compiled 0x%lx, library %s",
|
||||||
|
LRB_SSL_VNUM_COMPILETIME, LRB_SSL_VTEXT_COMPILETIME);
|
||||||
|
else
|
||||||
|
(void) rb_snprintf(buf, len, "OpenSSL: compiled (0x%lx, %s), library (0x%lx, %s)",
|
||||||
|
LRB_SSL_VNUM_COMPILETIME, LRB_SSL_VTEXT_COMPILETIME,
|
||||||
|
LRB_SSL_VNUM_RUNTIME, LRB_SSL_VTEXT_RUNTIME);
|
||||||
|
#else
|
||||||
|
(void) rb_snprintf(buf, len, "OpenSSL: compiled 0x%lx, library %s",
|
||||||
|
LRB_SSL_VNUM_COMPILETIME, LRB_SSL_VTEXT_RUNTIME);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
rb_ssl_get_cipher(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
if(F == NULL || F->ssl == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
static char buf[512];
|
||||||
|
|
||||||
|
const char *const version = SSL_get_version(SSL_P(F));
|
||||||
|
const char *const cipher = SSL_get_cipher_name(SSL_P(F));
|
||||||
|
|
||||||
|
(void) rb_snprintf(buf, sizeof buf, "%s, %s", version, cipher);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
rb_ssl_read(rb_fde_t *const F, void *const buf, const size_t count)
|
||||||
|
{
|
||||||
|
return rb_ssl_read_or_write(0, F, buf, NULL, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
rb_ssl_write(rb_fde_t *const F, const void *const buf, const size_t count)
|
||||||
|
{
|
||||||
|
return rb_ssl_read_or_write(1, F, NULL, buf, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal library-agnostic code
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_connect_realcb(rb_fde_t *const F, const int status, struct ssl_connect *const sconn)
|
||||||
|
{
|
||||||
|
lrb_assert(F->connect != NULL);
|
||||||
|
|
||||||
|
F->connect->callback = sconn->callback;
|
||||||
|
F->connect->data = sconn->data;
|
||||||
|
|
||||||
|
rb_connect_callback(F, status);
|
||||||
|
rb_free(sconn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_timeout_cb(rb_fde_t *const F, void *const data)
|
||||||
|
{
|
||||||
|
lrb_assert(F->accept != NULL);
|
||||||
|
lrb_assert(F->accept->callback != NULL);
|
||||||
|
|
||||||
|
F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_tryconn_timeout_cb(rb_fde_t *const F, void *const data)
|
||||||
|
{
|
||||||
|
rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data)
|
||||||
|
{
|
||||||
|
lrb_assert(F != NULL);
|
||||||
|
|
||||||
|
struct ssl_connect *const sconn = data;
|
||||||
|
|
||||||
|
if(status != RB_OK)
|
||||||
|
{
|
||||||
|
rb_ssl_connect_realcb(F, status, sconn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
F->type |= RB_FD_SSL;
|
||||||
|
|
||||||
|
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
|
||||||
|
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
|
||||||
|
rb_ssl_connect_common(F, sconn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External library-agnostic code
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_supports_ssl(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
rb_ssl_handshake_count(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
return F->handshake_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_clear_handshake_count(rb_fde_t *const F)
|
||||||
|
{
|
||||||
|
F->handshake_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_start_accepted(rb_fde_t *const F, ACCB *const cb, void *const data, const int timeout)
|
||||||
|
{
|
||||||
|
F->type |= RB_FD_SSL;
|
||||||
|
|
||||||
|
F->accept = rb_malloc(sizeof(struct acceptdata));
|
||||||
|
F->accept->callback = cb;
|
||||||
|
F->accept->data = data;
|
||||||
|
F->accept->addrlen = 0;
|
||||||
|
(void) memset(&F->accept->S, 0x00, sizeof F->accept->S);
|
||||||
|
|
||||||
|
rb_settimeout(F, timeout, rb_ssl_timeout_cb, NULL);
|
||||||
|
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_IN);
|
||||||
|
rb_ssl_accept_common(F, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_accept_setup(rb_fde_t *const srv_F, rb_fde_t *const cli_F, struct sockaddr *const st, const int addrlen)
|
||||||
|
{
|
||||||
|
cli_F->type |= RB_FD_SSL;
|
||||||
|
|
||||||
|
cli_F->accept = rb_malloc(sizeof(struct acceptdata));
|
||||||
|
cli_F->accept->callback = srv_F->accept->callback;
|
||||||
|
cli_F->accept->data = srv_F->accept->data;
|
||||||
|
cli_F->accept->addrlen = (rb_socklen_t) addrlen;
|
||||||
|
(void) memset(&cli_F->accept->S, 0x00, sizeof cli_F->accept->S);
|
||||||
|
(void) memcpy(&cli_F->accept->S, st, (size_t) addrlen);
|
||||||
|
|
||||||
|
rb_settimeout(cli_F, 10, rb_ssl_timeout_cb, NULL);
|
||||||
|
rb_ssl_init_fd(cli_F, RB_FD_TLS_DIRECTION_IN);
|
||||||
|
rb_ssl_accept_common(cli_F, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_ssl_listen(rb_fde_t *const F, const int backlog, const int defer_accept)
|
||||||
|
{
|
||||||
|
int result = rb_listen(F, backlog, defer_accept);
|
||||||
|
|
||||||
|
F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_connect_tcp_ssl(rb_fde_t *const F, struct sockaddr *const dest, struct sockaddr *const clocal,
|
||||||
|
const int socklen, CNCB *const callback, void *const data, const int timeout)
|
||||||
|
{
|
||||||
|
if(F == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
|
||||||
|
sconn->data = data;
|
||||||
|
sconn->callback = callback;
|
||||||
|
sconn->timeout = timeout;
|
||||||
|
|
||||||
|
rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data, const int timeout)
|
||||||
|
{
|
||||||
|
if(F == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
|
||||||
|
sconn->data = data;
|
||||||
|
sconn->callback = callback;
|
||||||
|
sconn->timeout = timeout;
|
||||||
|
|
||||||
|
F->connect = rb_malloc(sizeof(struct conndata));
|
||||||
|
F->connect->callback = callback;
|
||||||
|
F->connect->data = data;
|
||||||
|
F->type |= RB_FD_SSL;
|
||||||
|
|
||||||
|
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
|
||||||
|
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
|
||||||
|
rb_ssl_connect_common(F, sconn);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_OPENSSL */
|
141
libratbox/src/openssl_ratbox.h
Normal file
141
libratbox/src/openssl_ratbox.h
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* libratbox: a library used by ircd-ratbox and other things
|
||||||
|
* openssl_ratbox.h: OpenSSL backend data
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015-2016 Aaron Jones <aaronmdjones@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LRB_OPENSSL_H_INC
|
||||||
|
#define LRB_OPENSSL_H_INC 1
|
||||||
|
|
||||||
|
#include <openssl/dh.h>
|
||||||
|
#include <openssl/ec.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
#include <openssl/opensslv.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A long time ago, in a world far away, OpenSSL had a well-established mechanism for ensuring compatibility with
|
||||||
|
* regards to added, changed, and removed functions, by having an SSLEAY_VERSION_NUMBER macro. This was then
|
||||||
|
* renamed to OPENSSL_VERSION_NUMBER, but the old macro was kept around for compatibility until OpenSSL version
|
||||||
|
* 1.1.0.
|
||||||
|
*
|
||||||
|
* Then the OpenBSD developers decided that having OpenSSL in their codebase was a bad idea. They forked it to
|
||||||
|
* create LibreSSL, gutted all of the functionality they didn't want or need, and generally improved the library
|
||||||
|
* a lot. Then, as the OpenBSD developers are want to do, they packaged up LibreSSL for release to other
|
||||||
|
* operating systems, as LibreSSL Portable. Think along the lines of OpenSSH where they have also done this.
|
||||||
|
*
|
||||||
|
* The fun part of this story ends there. LibreSSL has an OPENSSL_VERSION_NUMBER macro, but they have set it to a
|
||||||
|
* stupidly high value, version 2.0. OpenSSL version 2.0 does not exist, and LibreSSL 2.2 does not implement
|
||||||
|
* everything OpenSSL 1.0.2 or 1.1.0 do. This completely breaks the entire purpose of the macro.
|
||||||
|
*
|
||||||
|
* The ifdef soup below is for LibreSSL compatibility. Please find whoever thought setting OPENSSL_VERSION_NUMBER
|
||||||
|
* to a version that does not exist was a good idea. Encourage them to realise that it is not. -- amdj
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
|
||||||
|
# define LRB_SSL_NO_EXPLICIT_INIT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10002000L)
|
||||||
|
# define LRB_HAVE_TLS_SET_CURVES 1
|
||||||
|
# if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||||
|
# define LRB_HAVE_TLS_ECDH_AUTO 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x20020002L)
|
||||||
|
# define LRB_HAVE_TLS_METHOD_API 1
|
||||||
|
#else
|
||||||
|
# if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
|
||||||
|
# define LRB_HAVE_TLS_METHOD_API 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
|
||||||
|
# define LRB_SSL_VTEXT_COMPILETIME OPENSSL_VERSION_TEXT
|
||||||
|
# define LRB_SSL_VTEXT_RUNTIME OpenSSL_version(OPENSSL_VERSION)
|
||||||
|
# define LRB_SSL_VNUM_COMPILETIME OPENSSL_VERSION_NUMBER
|
||||||
|
# define LRB_SSL_VNUM_RUNTIME OpenSSL_version_num()
|
||||||
|
# define LRB_SSL_FULL_VERSION_INFO 1
|
||||||
|
#else
|
||||||
|
# if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x20200000L)
|
||||||
|
# define LRB_SSL_VTEXT_RUNTIME SSLeay_version(SSLEAY_VERSION)
|
||||||
|
# define LRB_SSL_VNUM_COMPILETIME LIBRESSL_VERSION_NUMBER
|
||||||
|
# else
|
||||||
|
# define LRB_SSL_VTEXT_RUNTIME SSLeay_version(SSLEAY_VERSION)
|
||||||
|
# define LRB_SSL_VNUM_COMPILETIME SSLEAY_VERSION_NUMBER
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10101000L)
|
||||||
|
# define LRB_HAVE_TLS_ECDH_X25519 1
|
||||||
|
#else
|
||||||
|
# if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER > 0x2050100fL)
|
||||||
|
# define LRB_HAVE_TLS_ECDH_X25519 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default supported ciphersuites (if the user does not provide any) and
|
||||||
|
* curves (OpenSSL 1.0.2+). Hardcoded secp384r1 (NIST P-384) is used on
|
||||||
|
* OpenSSL 1.0.0 and 1.0.1 (if available).
|
||||||
|
*
|
||||||
|
* We prefer AEAD ciphersuites first in order of strength, then SHA2
|
||||||
|
* ciphersuites, then remaining suites.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const char rb_default_ciphers[] = ""
|
||||||
|
"aECDSA+kEECDH+CHACHA20:"
|
||||||
|
"aRSA+kEECDH+CHACHA20:"
|
||||||
|
"aRSA+kEDH+CHACHA20:"
|
||||||
|
"aECDSA+kEECDH+AESGCM:"
|
||||||
|
"aRSA+kEECDH+AESGCM:"
|
||||||
|
"aRSA+kEDH+AESGCM:"
|
||||||
|
"aECDSA+kEECDH+AESCCM:"
|
||||||
|
"aRSA+kEECDH+AESCCM:"
|
||||||
|
"aRSA+kEDH+AESCCM:"
|
||||||
|
"@STRENGTH:"
|
||||||
|
"aECDSA+kEECDH+HIGH+SHA384:"
|
||||||
|
"aRSA+kEECDH+HIGH+SHA384:"
|
||||||
|
"aRSA+kEDH+HIGH+SHA384:"
|
||||||
|
"aECDSA+kEECDH+HIGH+SHA256:"
|
||||||
|
"aRSA+kEECDH+HIGH+SHA256:"
|
||||||
|
"aRSA+kEDH+HIGH+SHA256:"
|
||||||
|
"aECDSA+kEECDH+HIGH:"
|
||||||
|
"aRSA+kEECDH+HIGH:"
|
||||||
|
"aRSA+kEDH+HIGH:"
|
||||||
|
"HIGH:"
|
||||||
|
"!3DES:"
|
||||||
|
"!aNULL";
|
||||||
|
|
||||||
|
#ifdef LRB_HAVE_TLS_SET_CURVES
|
||||||
|
# ifdef LRB_HAVE_TLS_ECDH_X25519
|
||||||
|
static char rb_default_curves[] = "X25519:P-521:P-384:P-256";
|
||||||
|
# else
|
||||||
|
static char rb_default_curves[] = "P-521:P-384:P-256";
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LRB_OPENSSL_H_INC */
|
424
libratbox/src/ratbox_lib.c
Normal file
424
libratbox/src/ratbox_lib.c
Normal file
|
@ -0,0 +1,424 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: A slightly useful ircd.
|
||||||
|
* ratbox_lib.c: libircd initialization functions at the like
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005,2006 ircd-ratbox development team
|
||||||
|
* Copyright (C) 2005,2006 Aaron Sethman <androsyn@ratbox.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: ratbox_lib.c 26282 2008-12-10 20:33:21Z androsyn $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libratbox_config.h>
|
||||||
|
#include <ratbox_lib.h>
|
||||||
|
#include <commio-int.h>
|
||||||
|
#include <commio-ssl.h>
|
||||||
|
|
||||||
|
static log_cb *rb_log;
|
||||||
|
static restart_cb *rb_restart;
|
||||||
|
static die_cb *rb_die;
|
||||||
|
|
||||||
|
static struct timeval rb_time;
|
||||||
|
static char errbuf[512];
|
||||||
|
|
||||||
|
/* this doesn't do locales...oh well i guess */
|
||||||
|
|
||||||
|
static const char *months[] = {
|
||||||
|
"January", "February", "March", "April",
|
||||||
|
"May", "June", "July", "August",
|
||||||
|
"September", "October", "November", "December"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *weekdays[] = {
|
||||||
|
"Sunday", "Monday", "Tuesday", "Wednesday",
|
||||||
|
"Thursday", "Friday", "Saturday"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *s_month[] = {
|
||||||
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
|
||||||
|
"Aug", "Sep", "Oct", "Nov", "Dec"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *s_weekdays[] = {
|
||||||
|
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||||
|
};
|
||||||
|
|
||||||
|
char *
|
||||||
|
rb_ctime(const time_t t, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
struct tm *tp;
|
||||||
|
static char timex[128];
|
||||||
|
size_t tlen;
|
||||||
|
#if defined(HAVE_GMTIME_R)
|
||||||
|
struct tm tmr;
|
||||||
|
tp = gmtime_r(&t, &tmr);
|
||||||
|
#else
|
||||||
|
tp = gmtime(&t);
|
||||||
|
#endif
|
||||||
|
if(buf == NULL)
|
||||||
|
{
|
||||||
|
p = timex;
|
||||||
|
tlen = sizeof(timex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = buf;
|
||||||
|
tlen = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rb_unlikely(tp == NULL))
|
||||||
|
{
|
||||||
|
rb_strlcpy(p, "", tlen);
|
||||||
|
return (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_snprintf(p, tlen, "%s %s %d %02u:%02u:%02u %d",
|
||||||
|
s_weekdays[tp->tm_wday], s_month[tp->tm_mon],
|
||||||
|
tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec, tp->tm_year + 1900);
|
||||||
|
return (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* I hate this..but its sort of ircd standard now.. */
|
||||||
|
char *
|
||||||
|
rb_date(const time_t t, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
struct tm *gm;
|
||||||
|
#if defined(HAVE_GMTIME_R)
|
||||||
|
struct tm gmbuf;
|
||||||
|
gm = gmtime_r(&t, &gmbuf);
|
||||||
|
#else
|
||||||
|
gm = gmtime(&t);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(rb_unlikely(gm == NULL))
|
||||||
|
{
|
||||||
|
rb_strlcpy(buf, "", len);
|
||||||
|
return (buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_snprintf(buf, len, "%s %s %d %d -- %02u:%02u:%02u +00:00",
|
||||||
|
weekdays[gm->tm_wday], months[gm->tm_mon], gm->tm_mday,
|
||||||
|
gm->tm_year + 1900, gm->tm_hour, gm->tm_min, gm->tm_sec);
|
||||||
|
return (buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t
|
||||||
|
rb_current_time(void)
|
||||||
|
{
|
||||||
|
return rb_time.tv_sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct timeval *
|
||||||
|
rb_current_time_tv(void)
|
||||||
|
{
|
||||||
|
return &rb_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_lib_log(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
if(rb_log == NULL)
|
||||||
|
return;
|
||||||
|
va_start(args, format);
|
||||||
|
rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
|
||||||
|
va_end(args);
|
||||||
|
rb_log(errbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_lib_die(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
if(rb_die == NULL)
|
||||||
|
abort();
|
||||||
|
va_start(args, format);
|
||||||
|
rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
|
||||||
|
va_end(args);
|
||||||
|
rb_die(errbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_lib_restart(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
if(rb_restart == NULL)
|
||||||
|
abort();
|
||||||
|
va_start(args, format);
|
||||||
|
rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
|
||||||
|
va_end(args);
|
||||||
|
rb_restart(errbuf);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_set_time(void)
|
||||||
|
{
|
||||||
|
struct timeval newtime;
|
||||||
|
|
||||||
|
if(rb_unlikely(rb_gettimeofday(&newtime, NULL) == -1))
|
||||||
|
{
|
||||||
|
rb_lib_log("Clock Failure (%s)", strerror(errno));
|
||||||
|
rb_lib_restart("Clock Failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(newtime.tv_sec < rb_time.tv_sec)
|
||||||
|
rb_set_back_events(rb_time.tv_sec - newtime.tv_sec);
|
||||||
|
|
||||||
|
memcpy(&rb_time, &newtime, sizeof(struct timeval));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const char *libratbox_serno;
|
||||||
|
|
||||||
|
const char *
|
||||||
|
rb_lib_version(void)
|
||||||
|
{
|
||||||
|
static char version_info[512];
|
||||||
|
char ssl_info[512];
|
||||||
|
rb_get_ssl_info(ssl_info, sizeof(ssl_info));
|
||||||
|
rb_snprintf(version_info, sizeof(version_info), "libratbox version: %s - %s", libratbox_serno, ssl_info);
|
||||||
|
return version_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_lib_init(log_cb * ilog, restart_cb * irestart, die_cb * idie, int closeall, int maxcon,
|
||||||
|
size_t dh_size, size_t fd_heap_size)
|
||||||
|
{
|
||||||
|
rb_set_time();
|
||||||
|
rb_log = ilog;
|
||||||
|
rb_restart = irestart;
|
||||||
|
rb_die = idie;
|
||||||
|
rb_event_init();
|
||||||
|
rb_init_bh();
|
||||||
|
rb_fdlist_init(closeall, maxcon, fd_heap_size);
|
||||||
|
rb_init_netio();
|
||||||
|
rb_init_rb_dlink_nodes(dh_size);
|
||||||
|
if(rb_io_supports_event())
|
||||||
|
{
|
||||||
|
rb_io_init_event();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_lib_loop(long delay)
|
||||||
|
{
|
||||||
|
time_t next;
|
||||||
|
rb_set_time();
|
||||||
|
|
||||||
|
if(rb_io_supports_event())
|
||||||
|
{
|
||||||
|
while(1)
|
||||||
|
rb_select(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
if(delay == 0)
|
||||||
|
{
|
||||||
|
if((next = rb_event_next()) > 0)
|
||||||
|
{
|
||||||
|
next -= rb_current_time();
|
||||||
|
if(next <= 0)
|
||||||
|
next = 1000;
|
||||||
|
else
|
||||||
|
next *= 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
next = -1;
|
||||||
|
rb_select(next);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rb_select(delay);
|
||||||
|
rb_event_run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_STRTOK_R
|
||||||
|
char *
|
||||||
|
rb_strtok_r(char *s, const char *delim, char **save)
|
||||||
|
{
|
||||||
|
char *token;
|
||||||
|
|
||||||
|
if(s == NULL)
|
||||||
|
s = *save;
|
||||||
|
|
||||||
|
/* Scan leading delimiters. */
|
||||||
|
s += strspn(s, delim);
|
||||||
|
|
||||||
|
if(*s == '\0')
|
||||||
|
{
|
||||||
|
*save = s;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
token = s;
|
||||||
|
s = strpbrk(token, delim);
|
||||||
|
|
||||||
|
if(s == NULL)
|
||||||
|
*save = (token + strlen(token));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*s = '\0';
|
||||||
|
*save = s + 1;
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
char *
|
||||||
|
rb_strtok_r(char *s, const char *delim, char **save)
|
||||||
|
{
|
||||||
|
return strtok_r(s, delim, save);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static const char base64_table[] =
|
||||||
|
{ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||||
|
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||||
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||||
|
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char base64_pad = '=';
|
||||||
|
|
||||||
|
static const short base64_reverse_table[256] = {
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
|
||||||
|
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||||
|
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
|
||||||
|
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||||
|
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char *
|
||||||
|
rb_base64_encode(const unsigned char *str, int length)
|
||||||
|
{
|
||||||
|
const unsigned char *current = str;
|
||||||
|
unsigned char *p;
|
||||||
|
unsigned char *result;
|
||||||
|
|
||||||
|
if((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2)))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = rb_malloc(((length + 2) / 3) * 5);
|
||||||
|
p = result;
|
||||||
|
|
||||||
|
while(length > 2)
|
||||||
|
{
|
||||||
|
*p++ = base64_table[current[0] >> 2];
|
||||||
|
*p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
|
||||||
|
*p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
|
||||||
|
*p++ = base64_table[current[2] & 0x3f];
|
||||||
|
|
||||||
|
current += 3;
|
||||||
|
length -= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(length != 0)
|
||||||
|
{
|
||||||
|
*p++ = base64_table[current[0] >> 2];
|
||||||
|
if(length > 1)
|
||||||
|
{
|
||||||
|
*p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
|
||||||
|
*p++ = base64_table[(current[1] & 0x0f) << 2];
|
||||||
|
*p++ = base64_pad;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*p++ = base64_table[(current[0] & 0x03) << 4];
|
||||||
|
*p++ = base64_pad;
|
||||||
|
*p++ = base64_pad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *
|
||||||
|
rb_base64_decode(const unsigned char *str, int length, int *ret)
|
||||||
|
{
|
||||||
|
const unsigned char *current = str;
|
||||||
|
int ch, i = 0, j = 0, k;
|
||||||
|
unsigned char *result;
|
||||||
|
|
||||||
|
result = rb_malloc(length + 1);
|
||||||
|
|
||||||
|
while((ch = *current++) != '\0' && length-- > 0)
|
||||||
|
{
|
||||||
|
if(ch == base64_pad)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ch = base64_reverse_table[ch];
|
||||||
|
if(ch < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (i % 4)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
result[j] = ch << 2;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
result[j++] |= ch >> 4;
|
||||||
|
result[j] = (ch & 0x0f) << 4;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
result[j++] |= ch >> 2;
|
||||||
|
result[j] = (ch & 0x03) << 6;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
result[j++] |= ch;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
k = j;
|
||||||
|
|
||||||
|
if(ch == base64_pad)
|
||||||
|
{
|
||||||
|
switch (i % 4)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
free(result);
|
||||||
|
return NULL;
|
||||||
|
case 2:
|
||||||
|
k++;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case 3:
|
||||||
|
result[k++] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result[j] = '\0';
|
||||||
|
*ret = j;
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -105,4 +105,8 @@ do_die(struct Client *source_p, const char *servername)
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd_shutdown(get_client_name(source_p, HIDE_IP));
|
ircd_shutdown(get_client_name(source_p, HIDE_IP));
|
||||||
|
<<<<<<< .merge_file_0nztsK
|
||||||
|
/* UNREACHABLE */
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_F0prEH
|
||||||
}
|
}
|
||||||
|
|
|
@ -424,7 +424,7 @@ ms_join(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
|
||||||
if(parv[2][0] == '&')
|
if(parv[2][0] == '&')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mbuf = modebuf;
|
char *mbuf = modebuf;
|
||||||
mode.key[0] = mode.forward[0] = '\0';
|
mode.key[0] = mode.forward[0] = '\0';
|
||||||
mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
|
mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
|
||||||
|
|
||||||
|
@ -539,8 +539,11 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
||||||
int i, joinc = 0, timeslice = 0;
|
int i, joinc = 0, timeslice = 0;
|
||||||
static char empty[] = "";
|
static char empty[] = "";
|
||||||
rb_dlink_node *ptr, *next_ptr;
|
rb_dlink_node *ptr, *next_ptr;
|
||||||
|
<<<<<<< .merge_file_gR6TZa
|
||||||
|
=======
|
||||||
char *mbuf;
|
char *mbuf;
|
||||||
int pargs;
|
int pargs;
|
||||||
|
>>>>>>> .merge_file_qhnxdu
|
||||||
const char *para[MAXMODEPARAMS];
|
const char *para[MAXMODEPARAMS];
|
||||||
|
|
||||||
if(parc < 5)
|
if(parc < 5)
|
||||||
|
@ -554,7 +557,7 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
||||||
return;
|
return;
|
||||||
|
|
||||||
modebuf[0] = parabuf[0] = mode.key[0] = mode.forward[0] = '\0';
|
modebuf[0] = parabuf[0] = mode.key[0] = mode.forward[0] = '\0';
|
||||||
pargs = mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
|
mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
|
||||||
|
|
||||||
/* Hide connecting server on netburst -- jilles */
|
/* Hide connecting server on netburst -- jilles */
|
||||||
if (ConfigServerHide.flatten_links && !HasSentEob(source_p))
|
if (ConfigServerHide.flatten_links && !HasSentEob(source_p))
|
||||||
|
@ -562,7 +565,7 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
||||||
else
|
else
|
||||||
fakesource_p = source_p;
|
fakesource_p = source_p;
|
||||||
|
|
||||||
mbuf = modebuf;
|
char *mbuf = modebuf;
|
||||||
newts = atol(parv[1]);
|
newts = atol(parv[1]);
|
||||||
|
|
||||||
s = parv[3];
|
s = parv[3];
|
||||||
|
@ -769,9 +772,10 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
||||||
|
|
||||||
mbuf = modebuf;
|
mbuf = modebuf;
|
||||||
para[0] = para[1] = para[2] = para[3] = empty;
|
para[0] = para[1] = para[2] = para[3] = empty;
|
||||||
pargs = 0;
|
|
||||||
len_uid = 0;
|
len_uid = 0;
|
||||||
|
|
||||||
|
int pargs = 0;
|
||||||
|
|
||||||
/* if theres a space, theres going to be more than one nick, change the
|
/* if theres a space, theres going to be more than one nick, change the
|
||||||
* first space to \0, so s is just the first nick, and point p to the
|
* first space to \0, so s is just the first nick, and point p to the
|
||||||
* second nick
|
* second nick
|
||||||
|
@ -1171,8 +1175,12 @@ set_final_mode(char *mbuf, char *parabuf, struct Mode *mode, struct Mode *oldmod
|
||||||
len = sprintf(pbuf, "%s ", mode->forward);
|
len = sprintf(pbuf, "%s ", mode->forward);
|
||||||
pbuf += len;
|
pbuf += len;
|
||||||
}
|
}
|
||||||
*mbuf = '\0';
|
|
||||||
|
|
||||||
|
*mbuf = '\0';
|
||||||
|
<<<<<<< .merge_file_gR6TZa
|
||||||
|
=======
|
||||||
|
|
||||||
|
>>>>>>> .merge_file_qhnxdu
|
||||||
return mbuf;
|
return mbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1194,6 +1202,10 @@ remove_our_modes(struct Channel *chptr, struct Client *source_p)
|
||||||
int i;
|
int i;
|
||||||
char *mbuf = lmodebuf;
|
char *mbuf = lmodebuf;
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_gR6TZa
|
||||||
|
char *mbuf = lmodebuf;
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_qhnxdu
|
||||||
*mbuf++ = '-';
|
*mbuf++ = '-';
|
||||||
|
|
||||||
for(i = 0; i < MAXMODEPARAMS; i++)
|
for(i = 0; i < MAXMODEPARAMS; i++)
|
||||||
|
@ -1296,8 +1308,13 @@ remove_ban_list(struct Channel *chptr, struct Client *source_p,
|
||||||
|
|
||||||
pbuf = lparabuf;
|
pbuf = lparabuf;
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_gR6TZa
|
||||||
|
cur_len = mlen = rb_sprintf(lmodebuf, ":%s MODE %s -", source_p->name, chptr->chname);
|
||||||
|
char *mbuf = lmodebuf + mlen;
|
||||||
|
=======
|
||||||
cur_len = mlen = sprintf(lmodebuf, ":%s MODE %s -", source_p->name, chptr->chname);
|
cur_len = mlen = sprintf(lmodebuf, ":%s MODE %s -", source_p->name, chptr->chname);
|
||||||
mbuf = lmodebuf + mlen;
|
mbuf = lmodebuf + mlen;
|
||||||
|
>>>>>>> .merge_file_qhnxdu
|
||||||
|
|
||||||
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
|
||||||
{
|
{
|
||||||
|
|
|
@ -370,7 +370,10 @@ do_bmask(bool extended, struct MsgBuf *msgbuf_p, struct Client *client_p, struct
|
||||||
{
|
{
|
||||||
*forward++ = '\0';
|
*forward++ = '\0';
|
||||||
if(*forward == '\0')
|
if(*forward == '\0')
|
||||||
tlen--, forward = NULL;
|
{
|
||||||
|
tlen--;
|
||||||
|
forward = NULL;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
possibly_remove_lower_forward(fakesource_p,
|
possibly_remove_lower_forward(fakesource_p,
|
||||||
mems, chptr, banlist,
|
mems, chptr, banlist,
|
||||||
|
|
|
@ -133,9 +133,13 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_client(client_p, client_p, client_p, "Invalid servername.");
|
exit_client(client_p, client_p, client_p, "Invalid servername.");
|
||||||
|
<<<<<<< .merge_file_pjgqgl
|
||||||
|
return 0;
|
||||||
|
=======
|
||||||
return;
|
return;
|
||||||
/* NOT REACHED */
|
/* NOT REACHED */
|
||||||
break;
|
break;
|
||||||
|
>>>>>>> .merge_file_QmFPuY
|
||||||
|
|
||||||
case -2:
|
case -2:
|
||||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||||
|
@ -148,9 +152,13 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
log_client_name(client_p, SHOW_IP));
|
log_client_name(client_p, SHOW_IP));
|
||||||
|
|
||||||
exit_client(client_p, client_p, client_p, "Invalid credentials.");
|
exit_client(client_p, client_p, client_p, "Invalid credentials.");
|
||||||
|
<<<<<<< .merge_file_pjgqgl
|
||||||
|
return 0;
|
||||||
|
=======
|
||||||
return;
|
return;
|
||||||
/* NOT REACHED */
|
/* NOT REACHED */
|
||||||
break;
|
break;
|
||||||
|
>>>>>>> .merge_file_QmFPuY
|
||||||
|
|
||||||
case -3:
|
case -3:
|
||||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||||
|
@ -163,9 +171,13 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
log_client_name(client_p, SHOW_IP));
|
log_client_name(client_p, SHOW_IP));
|
||||||
|
|
||||||
exit_client(client_p, client_p, client_p, "Invalid host.");
|
exit_client(client_p, client_p, client_p, "Invalid host.");
|
||||||
|
<<<<<<< .merge_file_pjgqgl
|
||||||
|
return 0;
|
||||||
|
=======
|
||||||
return;
|
return;
|
||||||
/* NOT REACHED */
|
/* NOT REACHED */
|
||||||
break;
|
break;
|
||||||
|
>>>>>>> .merge_file_QmFPuY
|
||||||
|
|
||||||
/* servername is > HOSTLEN */
|
/* servername is > HOSTLEN */
|
||||||
case -4:
|
case -4:
|
||||||
|
@ -176,9 +188,14 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
log_client_name(client_p, SHOW_IP));
|
log_client_name(client_p, SHOW_IP));
|
||||||
|
|
||||||
exit_client(client_p, client_p, client_p, "Invalid servername.");
|
exit_client(client_p, client_p, client_p, "Invalid servername.");
|
||||||
|
<<<<<<< .merge_file_pjgqgl
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
=======
|
||||||
return;
|
return;
|
||||||
/* NOT REACHED */
|
/* NOT REACHED */
|
||||||
break;
|
break;
|
||||||
|
>>>>>>> .merge_file_QmFPuY
|
||||||
case -5:
|
case -5:
|
||||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||||
"Connection from servername %s requires SSL/TLS but is plaintext",
|
"Connection from servername %s requires SSL/TLS but is plaintext",
|
||||||
|
@ -187,11 +204,20 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
log_client_name(client_p, SHOW_IP));
|
log_client_name(client_p, SHOW_IP));
|
||||||
|
|
||||||
exit_client(client_p, client_p, client_p, "Access denied, requires SSL/TLS but is plaintext");
|
exit_client(client_p, client_p, client_p, "Access denied, requires SSL/TLS but is plaintext");
|
||||||
|
<<<<<<< .merge_file_pjgqgl
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case -6:
|
||||||
|
if (client_p->certfp)
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
=======
|
||||||
return;
|
return;
|
||||||
case -6:
|
case -6:
|
||||||
if (client_p->certfp)
|
if (client_p->certfp)
|
||||||
{
|
{
|
||||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||||
|
>>>>>>> .merge_file_QmFPuY
|
||||||
"Connection from servername %s has invalid certificate fingerprint %s",
|
"Connection from servername %s has invalid certificate fingerprint %s",
|
||||||
name, client_p->certfp);
|
name, client_p->certfp);
|
||||||
ilog(L_SERVER, "Access denied, invalid certificate fingerprint %s from %s",
|
ilog(L_SERVER, "Access denied, invalid certificate fingerprint %s from %s",
|
||||||
|
@ -200,7 +226,11 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
<<<<<<< .merge_file_pjgqgl
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
=======
|
||||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||||
|
>>>>>>> .merge_file_QmFPuY
|
||||||
"Connection from servername %s failed certificate validation",
|
"Connection from servername %s failed certificate validation",
|
||||||
name);
|
name);
|
||||||
ilog(L_SERVER, "Access denied; certificate validation failed for certificate from %s",
|
ilog(L_SERVER, "Access denied; certificate validation failed for certificate from %s",
|
||||||
|
@ -208,6 +238,12 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
exit_client(client_p, client_p, client_p, "Invalid certificate.");
|
exit_client(client_p, client_p, client_p, "Invalid certificate.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_pjgqgl
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
=======
|
||||||
return;
|
return;
|
||||||
case -7:
|
case -7:
|
||||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||||
|
@ -220,6 +256,7 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||||
|
>>>>>>> .merge_file_QmFPuY
|
||||||
"Connection from servername %s rejected, unknown error %d",
|
"Connection from servername %s rejected, unknown error %d",
|
||||||
name, ret);
|
name, ret);
|
||||||
ilog(L_SERVER, "Access denied, unknown error %d for server %s%s", ret,
|
ilog(L_SERVER, "Access denied, unknown error %d for server %s%s", ret,
|
||||||
|
@ -227,7 +264,11 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
log_client_name(client_p, SHOW_IP));
|
log_client_name(client_p, SHOW_IP));
|
||||||
|
|
||||||
exit_client(client_p, client_p, client_p, "Unknown error.");
|
exit_client(client_p, client_p, client_p, "Unknown error.");
|
||||||
|
<<<<<<< .merge_file_pjgqgl
|
||||||
|
return 0;
|
||||||
|
=======
|
||||||
return;
|
return;
|
||||||
|
>>>>>>> .merge_file_QmFPuY
|
||||||
}
|
}
|
||||||
|
|
||||||
/* require TS6 for direct links */
|
/* require TS6 for direct links */
|
||||||
|
@ -298,7 +339,11 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
|
|
||||||
if (client_p->preClient && !EmptyString(client_p->preClient->id)) {
|
if (client_p->preClient && !EmptyString(client_p->preClient->id)) {
|
||||||
if ((target_p = find_id(client_p->preClient->id)) != NULL) {
|
if ((target_p = find_id(client_p->preClient->id)) != NULL) {
|
||||||
|
<<<<<<< .merge_file_pjgqgl
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL,
|
||||||
|
=======
|
||||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||||
|
>>>>>>> .merge_file_QmFPuY
|
||||||
"Attempt to re-introduce SID %s from %s%s (already in use by %s)",
|
"Attempt to re-introduce SID %s from %s%s (already in use by %s)",
|
||||||
client_p->preClient->id,
|
client_p->preClient->id,
|
||||||
EmptyString(client_p->name) ? name : "",
|
EmptyString(client_p->name) ? name : "",
|
||||||
|
@ -311,7 +356,11 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
|
|
||||||
sendto_one(client_p, "ERROR :SID already exists.");
|
sendto_one(client_p, "ERROR :SID already exists.");
|
||||||
exit_client(client_p, client_p, client_p, "SID Exists");
|
exit_client(client_p, client_p, client_p, "SID Exists");
|
||||||
|
<<<<<<< .merge_file_pjgqgl
|
||||||
|
return 0;
|
||||||
|
=======
|
||||||
return;
|
return;
|
||||||
|
>>>>>>> .merge_file_QmFPuY
|
||||||
} else {
|
} else {
|
||||||
rb_strlcpy(client_p->id, client_p->preClient->id, sizeof(client_p->id));
|
rb_strlcpy(client_p->id, client_p->preClient->id, sizeof(client_p->id));
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,6 +152,16 @@ clicap_find(const char *data, int *negate, int *finished)
|
||||||
static void
|
static void
|
||||||
clicap_generate(struct Client *source_p, const char *subcmd, int flags)
|
clicap_generate(struct Client *source_p, const char *subcmd, int flags)
|
||||||
{
|
{
|
||||||
|
<<<<<<< .merge_file_FIhLV9
|
||||||
|
char buf[BUFSIZE] = { 0 };
|
||||||
|
char capbuf[BUFSIZE] = { 0 };
|
||||||
|
char *p;
|
||||||
|
int buflen = 0;
|
||||||
|
int curlen, mlen;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
mlen = rb_sprintf(buf, ":%s CAP %s %s",
|
||||||
|
=======
|
||||||
const char *str_cont = "* :";
|
const char *str_cont = "* :";
|
||||||
const char *str_final = ":";
|
const char *str_final = ":";
|
||||||
struct CapabilityEntry *entry;
|
struct CapabilityEntry *entry;
|
||||||
|
@ -160,6 +170,7 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags)
|
||||||
enum multiline_item_result multiline_item_ret;
|
enum multiline_item_result multiline_item_ret;
|
||||||
|
|
||||||
multiline_ret = send_multiline_init(source_p, " ", ":%s CAP %s %s %s",
|
multiline_ret = send_multiline_init(source_p, " ", ":%s CAP %s %s %s",
|
||||||
|
>>>>>>> .merge_file_J3fUTs
|
||||||
me.name,
|
me.name,
|
||||||
EmptyString(source_p->name) ? "*" : source_p->name,
|
EmptyString(source_p->name) ? "*" : source_p->name,
|
||||||
subcmd,
|
subcmd,
|
||||||
|
@ -207,10 +218,30 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags)
|
||||||
if (!flags && clicap != NULL && clicap->data != NULL)
|
if (!flags && clicap != NULL && clicap->data != NULL)
|
||||||
data = clicap->data(source_p);
|
data = clicap->data(source_p);
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_FIhLV9
|
||||||
|
/* \r\n\0, possible "-~=", space, " *" */
|
||||||
|
if(buflen + clicap_list[i].namelen >= BUFSIZE - 10)
|
||||||
|
{
|
||||||
|
/* remove our trailing space -- if buflen == mlen
|
||||||
|
* here, we didnt even succeed in adding one.
|
||||||
|
*/
|
||||||
|
if(buflen != mlen)
|
||||||
|
*(p - 1) = '\0';
|
||||||
|
else
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
sendto_one(source_p, "%s * :%s", buf, capbuf);
|
||||||
|
|
||||||
|
p = capbuf;
|
||||||
|
buflen = mlen;
|
||||||
|
memset(capbuf, 0, sizeof(capbuf));
|
||||||
|
}
|
||||||
|
=======
|
||||||
multiline_item_ret = send_multiline_item(source_p, "%s%s%s",
|
multiline_item_ret = send_multiline_item(source_p, "%s%s%s",
|
||||||
entry->cap,
|
entry->cap,
|
||||||
data != NULL ? "=" : "",
|
data != NULL ? "=" : "",
|
||||||
data != NULL ? data : "");
|
data != NULL ? data : "");
|
||||||
|
>>>>>>> .merge_file_J3fUTs
|
||||||
|
|
||||||
if (multiline_item_ret == MULTILINE_FAILURE)
|
if (multiline_item_ret == MULTILINE_FAILURE)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -416,6 +416,12 @@ static struct InfoStruct info_table[] = {
|
||||||
"Minimum delay between less intensive commands",
|
"Minimum delay between less intensive commands",
|
||||||
INFO_DECIMAL(&ConfigFileEntry.pace_wait_simple),
|
INFO_DECIMAL(&ConfigFileEntry.pace_wait_simple),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"listfake_wait",
|
||||||
|
OUTPUT_DECIMAL,
|
||||||
|
&ConfigFileEntry.listfake_wait,
|
||||||
|
"Time until real list command can be used"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ping_cookie",
|
"ping_cookie",
|
||||||
"Require ping cookies to connect",
|
"Require ping cookies to connect",
|
||||||
|
|
|
@ -156,7 +156,37 @@ m_list(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
|
||||||
last_used = rb_current_time();
|
last_used = rb_current_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_PyqEuU
|
||||||
|
/* Disable LIST for a configured timespan after connect and send configured fake
|
||||||
|
* channels instead.
|
||||||
|
* Exempts: Opers, identifed users and users with spambot_exempt flag
|
||||||
|
*/
|
||||||
|
if (((source_p->localClient->firsttime + ConfigFileEntry.listfake_wait) > rb_current_time())
|
||||||
|
&& !IsOper(source_p) && !IsExemptSpambot(source_p) &&
|
||||||
|
!(source_p->user != NULL && !EmptyString(source_p->user->suser)))
|
||||||
|
{
|
||||||
|
struct fakechannel_entry *fakechannel;
|
||||||
|
struct DictionaryIter iter;
|
||||||
|
|
||||||
|
sendto_one(source_p, form_str(RPL_LISTSTART), me.name, source_p->name);
|
||||||
|
|
||||||
|
DICTIONARY_FOREACH(fakechannel, &iter, fakechannel_dict)
|
||||||
|
{
|
||||||
|
sendto_one(source_p, form_str(RPL_LIST), me.name, source_p->name,
|
||||||
|
"",
|
||||||
|
fakechannel->name,
|
||||||
|
(rand() % fakechannel->users_max + fakechannel->users_min),
|
||||||
|
fakechannel->topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mo_list(client_p, source_p, parc, parv);
|
||||||
|
=======
|
||||||
mo_list(msgbuf_p, client_p, source_p, parc, parv);
|
mo_list(msgbuf_p, client_p, source_p, parc, parv);
|
||||||
|
>>>>>>> .merge_file_yv6CiZ
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mo_list()
|
/* mo_list()
|
||||||
|
|
|
@ -40,11 +40,15 @@
|
||||||
#include "reject.h"
|
#include "reject.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
<<<<<<< .merge_file_Kl8bB5
|
||||||
|
#include "sslproc.h"
|
||||||
|
=======
|
||||||
#include "rb_radixtree.h"
|
#include "rb_radixtree.h"
|
||||||
#include "sslproc.h"
|
#include "sslproc.h"
|
||||||
|
|
||||||
static const char rehash_desc[] =
|
static const char rehash_desc[] =
|
||||||
"Provides the REHASH command to reload configuration and other files";
|
"Provides the REHASH command to reload configuration and other files";
|
||||||
|
>>>>>>> .merge_file_4WlQOU
|
||||||
|
|
||||||
static void mo_rehash(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
|
static void mo_rehash(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
|
||||||
static void me_rehash(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
|
static void me_rehash(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
|
||||||
|
@ -102,6 +106,22 @@ rehash_ssld(struct Client *source_p)
|
||||||
restart_ssld();
|
restart_ssld();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rehash_ssld(struct Client *source_p)
|
||||||
|
{
|
||||||
|
if (!IsOperAdmin(source_p))
|
||||||
|
{
|
||||||
|
sendto_one(source_p, form_str(ERR_NOPRIVS),
|
||||||
|
me.name, source_p->name, "admin");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s is restarting ssld",
|
||||||
|
get_oper_name(source_p));
|
||||||
|
|
||||||
|
restart_ssld();
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rehash_motd(struct Client *source_p)
|
rehash_motd(struct Client *source_p)
|
||||||
{
|
{
|
||||||
|
@ -350,7 +370,12 @@ do_rehash(struct Client *source_p, const char *type)
|
||||||
remote_rehash_oper_p = source_p;
|
remote_rehash_oper_p = source_p;
|
||||||
ilog(L_MAIN, "REHASH From %s[%s]", get_oper_name(source_p),
|
ilog(L_MAIN, "REHASH From %s[%s]", get_oper_name(source_p),
|
||||||
source_p->sockhost);
|
source_p->sockhost);
|
||||||
|
<<<<<<< .merge_file_Kl8bB5
|
||||||
|
rehash(0);
|
||||||
|
rehash_ulimit();
|
||||||
|
=======
|
||||||
rehash(false);
|
rehash(false);
|
||||||
|
>>>>>>> .merge_file_4WlQOU
|
||||||
remote_rehash_oper_p = NULL;
|
remote_rehash_oper_p = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,13 +399,25 @@ mo_rehash(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parc > 2)
|
if (parc > 2)
|
||||||
type = parv[1], target_server = parv[2];
|
{
|
||||||
|
type = parv[1];
|
||||||
|
target_server = parv[2];
|
||||||
|
}
|
||||||
else if (parc > 1 && (strchr(parv[1], '.') || strchr(parv[1], '?') || strchr(parv[1], '*')))
|
else if (parc > 1 && (strchr(parv[1], '.') || strchr(parv[1], '?') || strchr(parv[1], '*')))
|
||||||
type = NULL, target_server = parv[1];
|
{
|
||||||
|
type = NULL;
|
||||||
|
target_server = parv[1];
|
||||||
|
}
|
||||||
else if (parc > 1)
|
else if (parc > 1)
|
||||||
type = parv[1], target_server = NULL;
|
{
|
||||||
|
type = parv[1];
|
||||||
|
target_server = NULL;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
type = NULL, target_server = NULL;
|
{
|
||||||
|
type = NULL;
|
||||||
|
target_server = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (target_server != NULL)
|
if (target_server != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -127,4 +127,8 @@ do_restart(struct Client *source_p, const char *servername)
|
||||||
|
|
||||||
sprintf(buf, "Server RESTART by %s", get_client_name(source_p, HIDE_IP));
|
sprintf(buf, "Server RESTART by %s", get_client_name(source_p, HIDE_IP));
|
||||||
restart(buf);
|
restart(buf);
|
||||||
|
<<<<<<< .merge_file_Q6Imwg
|
||||||
|
/* UNREACHABLE */
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_lKBA0a
|
||||||
}
|
}
|
||||||
|
|
118
modules/m_sasl.c
118
modules/m_sasl.c
|
@ -52,8 +52,17 @@ static void me_mechlist(struct MsgBuf *, struct Client *, struct Client *, int,
|
||||||
static void abort_sasl(void *);
|
static void abort_sasl(void *);
|
||||||
static void abort_sasl_exit(void *);
|
static void abort_sasl_exit(void *);
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_j0yiRK
|
||||||
|
static void advertise_sasl_cap(int);
|
||||||
|
static void advertise_sasl_new(struct Client *);
|
||||||
|
static void advertise_sasl_exit(void *);
|
||||||
|
static void advertise_sasl_config(void *);
|
||||||
|
|
||||||
|
static int sasl_agent_present = 0;
|
||||||
|
=======
|
||||||
static unsigned int CLICAP_SASL = 0;
|
static unsigned int CLICAP_SASL = 0;
|
||||||
static char mechlist_buf[BUFSIZE];
|
static char mechlist_buf[BUFSIZE];
|
||||||
|
>>>>>>> .merge_file_hyMtKJ
|
||||||
|
|
||||||
struct Message authenticate_msgtab = {
|
struct Message authenticate_msgtab = {
|
||||||
"AUTHENTICATE", 0, 0, 0, 0,
|
"AUTHENTICATE", 0, 0, 0, 0,
|
||||||
|
@ -72,6 +81,42 @@ mapi_clist_av1 sasl_clist[] = {
|
||||||
&authenticate_msgtab, &sasl_msgtab, &mechlist_msgtab, NULL
|
&authenticate_msgtab, &sasl_msgtab, &mechlist_msgtab, NULL
|
||||||
};
|
};
|
||||||
mapi_hfn_list_av1 sasl_hfnlist[] = {
|
mapi_hfn_list_av1 sasl_hfnlist[] = {
|
||||||
|
<<<<<<< .merge_file_j0yiRK
|
||||||
|
{ "new_local_user", (hookfn) abort_sasl },
|
||||||
|
{ "client_exit", (hookfn) abort_sasl_exit },
|
||||||
|
{ "new_remote_user", (hookfn) advertise_sasl_new },
|
||||||
|
{ "after_client_exit", (hookfn) advertise_sasl_exit },
|
||||||
|
{ "conf_read_end", (hookfn) advertise_sasl_config },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
sasl_visible(void)
|
||||||
|
{
|
||||||
|
struct Client *agent_p = NULL;
|
||||||
|
|
||||||
|
if (ConfigFileEntry.sasl_service)
|
||||||
|
agent_p = find_named_client(ConfigFileEntry.sasl_service);
|
||||||
|
|
||||||
|
return agent_p != NULL && IsService(agent_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_modinit(void)
|
||||||
|
{
|
||||||
|
sasl_agent_present = 0;
|
||||||
|
advertise_sasl_config(NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_moddeinit(void)
|
||||||
|
{
|
||||||
|
advertise_sasl_cap(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_MODULE_AV1(sasl, _modinit, _moddeinit, sasl_clist, NULL, sasl_hfnlist, "$Revision: 1409 $");
|
||||||
|
=======
|
||||||
{ "client_exit", abort_sasl_exit },
|
{ "client_exit", abort_sasl_exit },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
@ -91,6 +136,7 @@ mapi_cap_list_av2 sasl_cap_list[] = {
|
||||||
{ MAPI_CAP_CLIENT, "sasl", &capdata_sasl, &CLICAP_SASL },
|
{ MAPI_CAP_CLIENT, "sasl", &capdata_sasl, &CLICAP_SASL },
|
||||||
{ 0, NULL, NULL, NULL },
|
{ 0, NULL, NULL, NULL },
|
||||||
};
|
};
|
||||||
|
>>>>>>> .merge_file_hyMtKJ
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_modinit(void)
|
_modinit(void)
|
||||||
|
@ -130,6 +176,12 @@ m_authenticate(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*parv[1] == ':' || strchr(parv[1], ' '))
|
||||||
|
{
|
||||||
|
exit_client(client_p, client_p, client_p, "Malformed AUTHENTICATE");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
saslserv_p = find_named_client(ConfigFileEntry.sasl_service);
|
saslserv_p = find_named_client(ConfigFileEntry.sasl_service);
|
||||||
if(saslserv_p == NULL || !IsService(saslserv_p))
|
if(saslserv_p == NULL || !IsService(saslserv_p))
|
||||||
{
|
{
|
||||||
|
@ -165,13 +217,21 @@ m_authenticate(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *
|
||||||
{
|
{
|
||||||
sendto_one(source_p, form_str(ERR_SASLABORTED), me.name, EmptyString(source_p->name) ? "*" : source_p->name);
|
sendto_one(source_p, form_str(ERR_SASLABORTED), me.name, EmptyString(source_p->name) ? "*" : source_p->name);
|
||||||
source_p->localClient->sasl_out = 0;
|
source_p->localClient->sasl_out = 0;
|
||||||
|
<<<<<<< .merge_file_j0yiRK
|
||||||
|
return 0;
|
||||||
|
=======
|
||||||
return;
|
return;
|
||||||
|
>>>>>>> .merge_file_hyMtKJ
|
||||||
}
|
}
|
||||||
|
|
||||||
sendto_one(saslserv_p, ":%s ENCAP %s SASL %s %s H %s %s %c",
|
sendto_one(saslserv_p, ":%s ENCAP %s SASL %s %s H %s %s %c",
|
||||||
me.id, saslserv_p->servptr->name, source_p->id, saslserv_p->id,
|
me.id, saslserv_p->servptr->name, source_p->id, saslserv_p->id,
|
||||||
source_p->host, source_p->sockhost,
|
source_p->host, source_p->sockhost,
|
||||||
|
<<<<<<< .merge_file_j0yiRK
|
||||||
|
IsSSL(source_p) ? 'S' : 'P');
|
||||||
|
=======
|
||||||
IsSecure(source_p) ? 'S' : 'P');
|
IsSecure(source_p) ? 'S' : 'P');
|
||||||
|
>>>>>>> .merge_file_hyMtKJ
|
||||||
|
|
||||||
if (source_p->certfp != NULL)
|
if (source_p->certfp != NULL)
|
||||||
sendto_one(saslserv_p, ":%s ENCAP %s SASL %s %s S %s %s",
|
sendto_one(saslserv_p, ":%s ENCAP %s SASL %s %s S %s %s",
|
||||||
|
@ -191,13 +251,22 @@ m_authenticate(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *
|
||||||
sendto_one(source_p, form_str(ERR_SASLABORTED), me.name, EmptyString(source_p->name) ? "*" : source_p->name);
|
sendto_one(source_p, form_str(ERR_SASLABORTED), me.name, EmptyString(source_p->name) ? "*" : source_p->name);
|
||||||
sendto_one(agent_p, ":%s ENCAP %s SASL %s %s D A", me.id, agent_p->servptr->name, source_p->id, agent_p->id);
|
sendto_one(agent_p, ":%s ENCAP %s SASL %s %s D A", me.id, agent_p->servptr->name, source_p->id, agent_p->id);
|
||||||
source_p->localClient->sasl_out = 0;
|
source_p->localClient->sasl_out = 0;
|
||||||
|
<<<<<<< .merge_file_j0yiRK
|
||||||
|
return 0;
|
||||||
|
=======
|
||||||
return;
|
return;
|
||||||
|
>>>>>>> .merge_file_hyMtKJ
|
||||||
}
|
}
|
||||||
|
|
||||||
sendto_one(agent_p, ":%s ENCAP %s SASL %s %s C %s",
|
sendto_one(agent_p, ":%s ENCAP %s SASL %s %s C %s",
|
||||||
me.id, agent_p->servptr->name, source_p->id, agent_p->id,
|
me.id, agent_p->servptr->name, source_p->id, agent_p->id,
|
||||||
parv[1]);
|
parv[1]);
|
||||||
}
|
}
|
||||||
|
<<<<<<< .merge_file_j0yiRK
|
||||||
|
|
||||||
|
source_p->localClient->sasl_out++;
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_hyMtKJ
|
||||||
|
|
||||||
source_p->localClient->sasl_out++;
|
source_p->localClient->sasl_out++;
|
||||||
}
|
}
|
||||||
|
@ -233,6 +302,10 @@ me_sasl(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
|
||||||
/* If SASL has been aborted, we only want to track authentication failures. */
|
/* If SASL has been aborted, we only want to track authentication failures. */
|
||||||
in_progress = target_p->localClient->sasl_out != 0;
|
in_progress = target_p->localClient->sasl_out != 0;
|
||||||
|
|
||||||
|
/* If SASL has been aborted, do nothing. */
|
||||||
|
if (target_p->localClient->sasl_out == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Reject if someone has already answered. */
|
/* Reject if someone has already answered. */
|
||||||
if(*target_p->localClient->sasl_agent && strncmp(parv[1], target_p->localClient->sasl_agent, IDLEN))
|
if(*target_p->localClient->sasl_agent && strncmp(parv[1], target_p->localClient->sasl_agent, IDLEN))
|
||||||
return;
|
return;
|
||||||
|
@ -334,3 +407,48 @@ abort_sasl_exit(void *data_)
|
||||||
if (data->target->localClient)
|
if (data->target->localClient)
|
||||||
abort_sasl(data->target);
|
abort_sasl(data->target);
|
||||||
}
|
}
|
||||||
|
<<<<<<< .merge_file_j0yiRK
|
||||||
|
|
||||||
|
static void
|
||||||
|
advertise_sasl_cap(int available)
|
||||||
|
{
|
||||||
|
if (sasl_agent_present != available) {
|
||||||
|
if (available) {
|
||||||
|
sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * NEW :sasl", me.name);
|
||||||
|
} else {
|
||||||
|
sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * DEL :sasl", me.name);
|
||||||
|
}
|
||||||
|
sasl_agent_present = available;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
advertise_sasl_new(struct Client *client_p)
|
||||||
|
{
|
||||||
|
if (!ConfigFileEntry.sasl_service)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (irccmp(client_p->name, ConfigFileEntry.sasl_service))
|
||||||
|
return;
|
||||||
|
|
||||||
|
advertise_sasl_cap(IsService(client_p));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
advertise_sasl_exit(void *ignored)
|
||||||
|
{
|
||||||
|
if (!ConfigFileEntry.sasl_service)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sasl_agent_present) {
|
||||||
|
advertise_sasl_cap(sasl_visible());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
advertise_sasl_config(void *ignored)
|
||||||
|
{
|
||||||
|
advertise_sasl_cap(sasl_visible());
|
||||||
|
}
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_hyMtKJ
|
||||||
|
|
|
@ -99,9 +99,13 @@ mr_starttls(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou
|
||||||
sendto_one_numeric(client_p, RPL_STARTTLS, form_str(RPL_STARTTLS));
|
sendto_one_numeric(client_p, RPL_STARTTLS, form_str(RPL_STARTTLS));
|
||||||
send_queued(client_p);
|
send_queued(client_p);
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_2ab79i
|
||||||
|
ctl = start_ssld_accept(client_p->localClient->F, F[1], client_p->localClient->connid);
|
||||||
|
=======
|
||||||
/* TODO: set localClient->ssl_callback and handle success/failure */
|
/* TODO: set localClient->ssl_callback and handle success/failure */
|
||||||
|
|
||||||
ctl = start_ssld_accept(client_p->localClient->F, F[1], connid_get(client_p));
|
ctl = start_ssld_accept(client_p->localClient->F, F[1], connid_get(client_p));
|
||||||
|
>>>>>>> .merge_file_h35QVt
|
||||||
if (ctl != NULL)
|
if (ctl != NULL)
|
||||||
{
|
{
|
||||||
client_p->localClient->F = F[0];
|
client_p->localClient->F = F[0];
|
||||||
|
@ -109,4 +113,11 @@ mr_starttls(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou
|
||||||
SetSSL(client_p);
|
SetSSL(client_p);
|
||||||
SetSecure(client_p);
|
SetSecure(client_p);
|
||||||
}
|
}
|
||||||
|
<<<<<<< .merge_file_2ab79i
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_h35QVt
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,12 +44,19 @@
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "reject.h"
|
#include "reject.h"
|
||||||
#include "whowas.h"
|
#include "whowas.h"
|
||||||
|
<<<<<<< .merge_file_voAp55
|
||||||
|
#include "sslproc.h"
|
||||||
|
|
||||||
|
#define Lformat "%s %u %u %u %u %u :%ld %ld %s"
|
||||||
|
#define Sformat ":%s %d %s %s %u %u %u %u %u :%ld %ld %s"
|
||||||
|
=======
|
||||||
#include "rb_radixtree.h"
|
#include "rb_radixtree.h"
|
||||||
#include "sslproc.h"
|
#include "sslproc.h"
|
||||||
#include "s_assert.h"
|
#include "s_assert.h"
|
||||||
|
|
||||||
static const char stats_desc[] =
|
static const char stats_desc[] =
|
||||||
"Provides the STATS command to inspect various server/network information";
|
"Provides the STATS command to inspect various server/network information";
|
||||||
|
>>>>>>> .merge_file_gExsVy
|
||||||
|
|
||||||
static void m_stats (struct MsgBuf *, struct Client *, struct Client *, int, const char **);
|
static void m_stats (struct MsgBuf *, struct Client *, struct Client *, int, const char **);
|
||||||
|
|
||||||
|
@ -72,10 +79,15 @@ mapi_hlist_av1 stats_hlist[] = {
|
||||||
|
|
||||||
DECLARE_MODULE_AV2(stats, NULL, NULL, stats_clist, stats_hlist, NULL, NULL, NULL, stats_desc);
|
DECLARE_MODULE_AV2(stats, NULL, NULL, stats_clist, stats_hlist, NULL, NULL, NULL, stats_desc);
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_voAp55
|
||||||
|
static void stats_l_list(struct Client *s, const char *, int, int, rb_dlink_list *, char,
|
||||||
|
int (*check_fn)(struct Client *target_p));
|
||||||
|
=======
|
||||||
const char *Lformat = "%s %u %u %u %u %u :%u %u %s";
|
const char *Lformat = "%s %u %u %u %u %u :%u %u %s";
|
||||||
|
|
||||||
static void stats_l_list(struct Client *s, const char *, bool, bool, rb_dlink_list *, char,
|
static void stats_l_list(struct Client *s, const char *, bool, bool, rb_dlink_list *, char,
|
||||||
bool (*check_fn)(struct Client *source_p, struct Client *target_p));
|
bool (*check_fn)(struct Client *source_p, struct Client *target_p));
|
||||||
|
>>>>>>> .merge_file_gExsVy
|
||||||
static void stats_l_client(struct Client *source_p, struct Client *target_p,
|
static void stats_l_client(struct Client *source_p, struct Client *target_p,
|
||||||
char statchar);
|
char statchar);
|
||||||
|
|
||||||
|
@ -117,7 +129,10 @@ static void stats_operedup(struct Client *);
|
||||||
static void stats_ports(struct Client *);
|
static void stats_ports(struct Client *);
|
||||||
static void stats_tresv(struct Client *);
|
static void stats_tresv(struct Client *);
|
||||||
static void stats_resv(struct Client *);
|
static void stats_resv(struct Client *);
|
||||||
|
<<<<<<< .merge_file_voAp55
|
||||||
|
=======
|
||||||
static void stats_secure(struct Client *);
|
static void stats_secure(struct Client *);
|
||||||
|
>>>>>>> .merge_file_gExsVy
|
||||||
static void stats_ssld(struct Client *);
|
static void stats_ssld(struct Client *);
|
||||||
static void stats_usage(struct Client *);
|
static void stats_usage(struct Client *);
|
||||||
static void stats_tstats(struct Client *);
|
static void stats_tstats(struct Client *);
|
||||||
|
@ -144,6 +159,58 @@ static void stats_capability(struct Client *);
|
||||||
* C initalisers so we don't have to iterate anymore
|
* C initalisers so we don't have to iterate anymore
|
||||||
* --Elizafox
|
* --Elizafox
|
||||||
*/
|
*/
|
||||||
|
<<<<<<< .merge_file_voAp55
|
||||||
|
static struct StatsStruct stats_cmd_table[] = {
|
||||||
|
/* letter function need_oper need_admin */
|
||||||
|
{'a', stats_dns_servers, 1, 1, },
|
||||||
|
{'A', stats_dns_servers, 1, 1, },
|
||||||
|
{'b', stats_delay, 1, 1, },
|
||||||
|
{'B', stats_hash, 1, 1, },
|
||||||
|
{'c', stats_connect, 0, 0, },
|
||||||
|
{'C', stats_capability, 1, 0, },
|
||||||
|
{'d', stats_tdeny, 1, 0, },
|
||||||
|
{'D', stats_deny, 1, 0, },
|
||||||
|
{'e', stats_exempt, 1, 0, },
|
||||||
|
{'E', stats_events, 1, 1, },
|
||||||
|
{'f', stats_comm, 1, 1, },
|
||||||
|
{'F', stats_comm, 1, 1, },
|
||||||
|
{'g', stats_prop_klines, 1, 0, },
|
||||||
|
{'h', stats_hubleaf, 0, 0, },
|
||||||
|
{'H', stats_hubleaf, 0, 0, },
|
||||||
|
{'i', stats_auth, 0, 0, },
|
||||||
|
{'I', stats_auth, 0, 0, },
|
||||||
|
{'k', stats_tklines, 0, 0, },
|
||||||
|
{'K', stats_klines, 0, 0, },
|
||||||
|
{'l', NULL /* special */, 0, 0, },
|
||||||
|
{'L', NULL /* special */, 0, 0, },
|
||||||
|
{'m', stats_messages, 0, 0, },
|
||||||
|
{'M', stats_messages, 0, 0, },
|
||||||
|
{'n', stats_dnsbl, 0, 0, },
|
||||||
|
{'o', stats_oper, 0, 0, },
|
||||||
|
{'O', stats_privset, 1, 0, },
|
||||||
|
{'p', stats_operedup, 0, 0, },
|
||||||
|
{'P', stats_ports, 0, 0, },
|
||||||
|
{'q', stats_tresv, 1, 0, },
|
||||||
|
{'Q', stats_resv, 1, 0, },
|
||||||
|
{'r', stats_usage, 1, 0, },
|
||||||
|
{'R', stats_usage, 1, 0, },
|
||||||
|
{'s', stats_ssld, 1, 1, },
|
||||||
|
{'S', stats_ssld, 1, 1, },
|
||||||
|
{'t', stats_tstats, 1, 0, },
|
||||||
|
{'T', stats_tstats, 1, 0, },
|
||||||
|
{'u', stats_uptime, 0, 0, },
|
||||||
|
{'U', stats_shared, 1, 0, },
|
||||||
|
{'v', stats_servers, 0, 0, },
|
||||||
|
{'V', stats_servers, 0, 0, },
|
||||||
|
{'x', stats_tgecos, 1, 0, },
|
||||||
|
{'X', stats_gecos, 1, 0, },
|
||||||
|
{'y', stats_class, 0, 0, },
|
||||||
|
{'Y', stats_class, 0, 0, },
|
||||||
|
{'z', stats_memory, 1, 0, },
|
||||||
|
{'Z', stats_ziplinks, 1, 0, },
|
||||||
|
{'?', stats_servlinks, 0, 0, },
|
||||||
|
{(char) 0, (void (*)(struct Client *)) 0, 0, 0, }
|
||||||
|
=======
|
||||||
static struct stats_cmd stats_cmd_table[256] = {
|
static struct stats_cmd stats_cmd_table[256] = {
|
||||||
/* letter handler admin priv */
|
/* letter handler admin priv */
|
||||||
['a'] = HANDLER_NORM(stats_dns_servers, true, NULL),
|
['a'] = HANDLER_NORM(stats_dns_servers, true, NULL),
|
||||||
|
@ -189,6 +256,7 @@ static struct stats_cmd stats_cmd_table[256] = {
|
||||||
['Y'] = HANDLER_NORM(stats_class, false, NULL),
|
['Y'] = HANDLER_NORM(stats_class, false, NULL),
|
||||||
['z'] = HANDLER_NORM(stats_memory, false, "oper:general"),
|
['z'] = HANDLER_NORM(stats_memory, false, "oper:general"),
|
||||||
['?'] = HANDLER_NORM(stats_servlinks, false, NULL),
|
['?'] = HANDLER_NORM(stats_servlinks, false, NULL),
|
||||||
|
>>>>>>> .merge_file_gExsVy
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -921,6 +989,24 @@ stats_ssld(struct Client *source_p)
|
||||||
ssld_foreach_info(stats_ssld_foreach, source_p);
|
ssld_foreach_info(stats_ssld_foreach, source_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
stats_ssld_foreach(void *data, pid_t pid, int cli_count, enum ssld_status status)
|
||||||
|
{
|
||||||
|
struct Client *source_p = data;
|
||||||
|
|
||||||
|
sendto_one_numeric(source_p, RPL_STATSDEBUG,
|
||||||
|
"S :%u %c %u",
|
||||||
|
pid,
|
||||||
|
status == SSLD_DEAD ? 'D' : (status == SSLD_SHUTDOWN ? 'S' : 'A'),
|
||||||
|
cli_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
stats_ssld(struct Client *source_p)
|
||||||
|
{
|
||||||
|
ssld_foreach_info(stats_ssld_foreach, source_p);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stats_usage (struct Client *source_p)
|
stats_usage (struct Client *source_p)
|
||||||
{
|
{
|
||||||
|
@ -1399,7 +1485,6 @@ stats_memory (struct Client *source_p)
|
||||||
static void
|
static void
|
||||||
stats_servlinks (struct Client *source_p)
|
stats_servlinks (struct Client *source_p)
|
||||||
{
|
{
|
||||||
static char Sformat[] = ":%s %d %s %s %u %u %u %u %u :%u %u %s";
|
|
||||||
long uptime, sendK, receiveK;
|
long uptime, sendK, receiveK;
|
||||||
struct Client *target_p;
|
struct Client *target_p;
|
||||||
rb_dlink_node *ptr;
|
rb_dlink_node *ptr;
|
||||||
|
@ -1434,8 +1519,13 @@ stats_servlinks (struct Client *source_p)
|
||||||
(int) target_p->localClient->receiveK,
|
(int) target_p->localClient->receiveK,
|
||||||
rb_current_time() - target_p->localClient->firsttime,
|
rb_current_time() - target_p->localClient->firsttime,
|
||||||
(rb_current_time() > target_p->localClient->lasttime) ?
|
(rb_current_time() > target_p->localClient->lasttime) ?
|
||||||
|
<<<<<<< .merge_file_voAp55
|
||||||
|
(rb_current_time() - target_p->localClient->lasttime) : (long) 0,
|
||||||
|
IsOper (source_p) ? show_capabilities (target_p) : "TS");
|
||||||
|
=======
|
||||||
(rb_current_time() - target_p->localClient->lasttime) : 0,
|
(rb_current_time() - target_p->localClient->lasttime) : 0,
|
||||||
IsOperGeneral (source_p) ? show_capabilities (target_p) : "TS");
|
IsOperGeneral (source_p) ? show_capabilities (target_p) : "TS");
|
||||||
|
>>>>>>> .merge_file_gExsVy
|
||||||
}
|
}
|
||||||
|
|
||||||
sendto_one_numeric(source_p, RPL_STATSDEBUG,
|
sendto_one_numeric(source_p, RPL_STATSDEBUG,
|
||||||
|
@ -1615,8 +1705,13 @@ stats_l_client(struct Client *source_p, struct Client *target_p,
|
||||||
(int) target_p->localClient->receiveK,
|
(int) target_p->localClient->receiveK,
|
||||||
rb_current_time() - target_p->localClient->firsttime,
|
rb_current_time() - target_p->localClient->firsttime,
|
||||||
(rb_current_time() > target_p->localClient->lasttime) ?
|
(rb_current_time() > target_p->localClient->lasttime) ?
|
||||||
|
<<<<<<< .merge_file_voAp55
|
||||||
|
(rb_current_time() - target_p->localClient->lasttime) : (long) 0,
|
||||||
|
IsOper(source_p) ? show_capabilities(target_p) : "-");
|
||||||
|
=======
|
||||||
(rb_current_time() - target_p->localClient->lasttime) : 0,
|
(rb_current_time() - target_p->localClient->lasttime) : 0,
|
||||||
IsOperGeneral(source_p) ? show_capabilities(target_p) : "-");
|
IsOperGeneral(source_p) ? show_capabilities(target_p) : "-");
|
||||||
|
>>>>>>> .merge_file_gExsVy
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
|
@ -1641,8 +1736,13 @@ stats_l_client(struct Client *source_p, struct Client *target_p,
|
||||||
hdata_showidle.approved ? (int) target_p->localClient->receiveM : 0,
|
hdata_showidle.approved ? (int) target_p->localClient->receiveM : 0,
|
||||||
hdata_showidle.approved ? (int) target_p->localClient->receiveK : 0,
|
hdata_showidle.approved ? (int) target_p->localClient->receiveK : 0,
|
||||||
rb_current_time() - target_p->localClient->firsttime,
|
rb_current_time() - target_p->localClient->firsttime,
|
||||||
|
<<<<<<< .merge_file_voAp55
|
||||||
|
(rb_current_time() > target_p->localClient->lasttime) ?
|
||||||
|
(rb_current_time() - target_p->localClient->lasttime) : (long) 0,
|
||||||
|
=======
|
||||||
(rb_current_time() > target_p->localClient->lasttime) && hdata_showidle.approved ?
|
(rb_current_time() > target_p->localClient->lasttime) && hdata_showidle.approved ?
|
||||||
(rb_current_time() - target_p->localClient->lasttime) : 0,
|
(rb_current_time() - target_p->localClient->lasttime) : 0,
|
||||||
|
>>>>>>> .merge_file_gExsVy
|
||||||
"-");
|
"-");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,6 +300,16 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy)
|
||||||
{
|
{
|
||||||
s = ConfigFileEntry.servicestring;
|
s = ConfigFileEntry.servicestring;
|
||||||
}
|
}
|
||||||
|
<<<<<<< .merge_file_zYZ429
|
||||||
|
|
||||||
|
if(MyClient(target_p) && !EmptyString(target_p->localClient->opername) && IsOper(target_p) && IsOper(source_p))
|
||||||
|
{
|
||||||
|
char obuf[512];
|
||||||
|
rb_snprintf(obuf, sizeof(obuf), "is opered as %s, privset %s",
|
||||||
|
target_p->localClient->opername, target_p->localClient->privset->name);
|
||||||
|
sendto_one_numeric(source_p, RPL_WHOISSPECIAL, form_str(RPL_WHOISSPECIAL),
|
||||||
|
target_p->name, obuf);
|
||||||
|
=======
|
||||||
if (!EmptyString(target_p->user->opername) && IsOper(target_p))
|
if (!EmptyString(target_p->user->opername) && IsOper(target_p))
|
||||||
{
|
{
|
||||||
if (target_p == source_p || HasPrivilege(source_p, "oper:privs"))
|
if (target_p == source_p || HasPrivilege(source_p, "oper:privs"))
|
||||||
|
@ -325,6 +335,7 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy)
|
||||||
{
|
{
|
||||||
sendto_one_numeric(source_p, RPL_WHOISOPERATOR, form_str(RPL_WHOISOPERATOR),
|
sendto_one_numeric(source_p, RPL_WHOISOPERATOR, form_str(RPL_WHOISOPERATOR),
|
||||||
target_p->name, s);
|
target_p->name, s);
|
||||||
|
>>>>>>> .merge_file_AQS60w
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IsSecureClient(target_p))
|
if(IsSecureClient(target_p))
|
||||||
|
|
106
modules/static_modules.c.SH
Normal file
106
modules/static_modules.c.SH
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# static_modules.c.SH: Generates our static module list
|
||||||
|
# $Id: static_modules.c.SH 6 2005-09-10 01:02:21Z nenolod $
|
||||||
|
#
|
||||||
|
SYMS=`for x in $*; do basename $x .o|sed -es/^m_//; done`
|
||||||
|
cat > static_modules.c <<EOF
|
||||||
|
/*
|
||||||
|
* This file is automatically generated: do not modify
|
||||||
|
* ircd-ratbox: A slightly useful ircd
|
||||||
|
*
|
||||||
|
* Copyright (C) 2003 Aaron Sethman <androsyn@ratbox.org>
|
||||||
|
* Copyright (C) 2003-2005 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "modules.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
for x in $SYMS; do
|
||||||
|
echo extern struct mapi_header_av1 "$x"_mheader\;
|
||||||
|
done >> static_modules.c
|
||||||
|
|
||||||
|
|
||||||
|
echo static const struct mapi_header_av1 *mapi_headers[] = { >> static_modules.c
|
||||||
|
for x in $SYMS; do
|
||||||
|
echo \&"$x"_mheader,
|
||||||
|
done >> static_modules.c
|
||||||
|
|
||||||
|
echo NULL }\; >> static_modules.c
|
||||||
|
|
||||||
|
cat >> static_modules.c <<EOF
|
||||||
|
void load_static_modules(void)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int *mapi_version;
|
||||||
|
for(x = 0; mapi_headers[x] != NULL; x++)
|
||||||
|
{
|
||||||
|
mapi_version = (int *)mapi_headers[x];
|
||||||
|
if(MAPI_MAGIC(*mapi_version) != MAPI_MAGIC_HDR)
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "Error: linked in module without a MAPI header..giving up");
|
||||||
|
exit(70);
|
||||||
|
}
|
||||||
|
switch(MAPI_VERSION(*mapi_version))
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
struct mapi_mheader_av1 *mheader = (struct mapi_mheader_av1*)mapi_version;
|
||||||
|
if (mheader->mapi_register && (mheader->mapi_register() == -1))
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "Error: linked in module failed loading..giving up");
|
||||||
|
exit(70);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mheader->mapi_command_list)
|
||||||
|
{
|
||||||
|
struct Message **m;
|
||||||
|
for(m = mheader->mapi_command_list; *m; ++m)
|
||||||
|
mod_add_cmd(*m);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mheader->mapi_hook_list)
|
||||||
|
{
|
||||||
|
mapi_hlist_av1 *m;
|
||||||
|
for(m = mheader->mapi_hook_list; m->hapi_name; ++m)
|
||||||
|
*m->hapi_id = register_hook(m->hapi_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mheader->mapi_hfn_list)
|
||||||
|
{
|
||||||
|
mapi_hfn_list_av1 *m;
|
||||||
|
for(m = mheader->mapi_hfn_list; m->hapi_name; ++m)
|
||||||
|
add_hook(m->hapi_name, m->fn);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "Error: Unknown MAPI version in linked in module..giving up");
|
||||||
|
exit(70);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
12
patches/bandb-remove-setenv.patch
Normal file
12
patches/bandb-remove-setenv.patch
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
diff --git a/src/bandbi.c b/src/bandbi.c
|
||||||
|
index 96f65b4..0a85a92 100644
|
||||||
|
--- a/src/bandbi.c
|
||||||
|
+++ b/src/bandbi.c
|
||||||
|
@@ -82,7 +82,6 @@ start_bandb(void)
|
||||||
|
const char *suffix = "";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- rb_setenv("BANDB_DBPATH", PKGLOCALSTATEDIR "/ban.db", 1);
|
||||||
|
if(bandb_path == NULL)
|
||||||
|
{
|
||||||
|
rb_snprintf(fullpath, sizeof(fullpath), "%s/bandb%s", PKGLIBEXECDIR, suffix);
|
454
src/bandbi.c
Normal file
454
src/bandbi.c
Normal file
|
@ -0,0 +1,454 @@
|
||||||
|
/* src/bandbi.c
|
||||||
|
* An interface to the ban db.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Lee Hardy <lee -at- leeh.co.uk>
|
||||||
|
* Copyright (C) 2006 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* 1.Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2.Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3.The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "ratbox_lib.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "match.h"
|
||||||
|
#include "bandbi.h"
|
||||||
|
#include "parse.h"
|
||||||
|
#include "channel.h"
|
||||||
|
#include "hostmask.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "s_newconf.h"
|
||||||
|
#include "reject.h"
|
||||||
|
#include "send.h"
|
||||||
|
#include "ircd.h"
|
||||||
|
#include "msg.h" /* XXX: MAXPARA */
|
||||||
|
#include "operhash.h"
|
||||||
|
|
||||||
|
static char bandb_add_letter[LAST_BANDB_TYPE] = {
|
||||||
|
'K', 'D', 'X', 'R'
|
||||||
|
};
|
||||||
|
|
||||||
|
rb_dlink_list bandb_pending;
|
||||||
|
|
||||||
|
static rb_helper *bandb_helper;
|
||||||
|
static int start_bandb(void);
|
||||||
|
|
||||||
|
static void bandb_parse(rb_helper *);
|
||||||
|
static void bandb_restart_cb(rb_helper *);
|
||||||
|
static char *bandb_path;
|
||||||
|
|
||||||
|
void
|
||||||
|
init_bandb(void)
|
||||||
|
{
|
||||||
|
if(start_bandb())
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "Unable to start bandb helper: %s", strerror(errno));
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
start_bandb(void)
|
||||||
|
{
|
||||||
|
char fullpath[PATH_MAX + 1];
|
||||||
|
#ifdef _WIN32
|
||||||
|
const char *suffix = ".exe";
|
||||||
|
#else
|
||||||
|
const char *suffix = "";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rb_setenv("BANDB_DBPATH", PKGLOCALSTATEDIR "/ban.db", 1);
|
||||||
|
if(bandb_path == NULL)
|
||||||
|
{
|
||||||
|
rb_snprintf(fullpath, sizeof(fullpath), "%s/bandb%s", PKGLIBEXECDIR, suffix);
|
||||||
|
|
||||||
|
if(access(fullpath, X_OK) == -1)
|
||||||
|
{
|
||||||
|
rb_snprintf(fullpath, sizeof(fullpath), "%s/bin/bandb%s",
|
||||||
|
ConfigFileEntry.dpath, suffix);
|
||||||
|
|
||||||
|
if(access(fullpath, X_OK) == -1)
|
||||||
|
{
|
||||||
|
ilog(L_MAIN,
|
||||||
|
"Unable to execute bandb%s in %s or %s/bin",
|
||||||
|
suffix, PKGLIBEXECDIR, ConfigFileEntry.dpath);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bandb_path = rb_strdup(fullpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bandb_helper = rb_helper_start("bandb", bandb_path, bandb_parse, bandb_restart_cb);
|
||||||
|
|
||||||
|
if(bandb_helper == NULL)
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "Unable to start bandb: %s", strerror(errno));
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL, "Unable to start bandb: %s",
|
||||||
|
strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_helper_run(bandb_helper);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bandb_add(bandb_type type, struct Client *source_p, const char *mask1,
|
||||||
|
const char *mask2, const char *reason, const char *oper_reason, int perm)
|
||||||
|
{
|
||||||
|
if(bandb_helper == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
static char buf[BUFSIZE];
|
||||||
|
|
||||||
|
rb_snprintf(buf, sizeof(buf), "%c %s ", bandb_add_letter[type], mask1);
|
||||||
|
|
||||||
|
if(!EmptyString(mask2))
|
||||||
|
rb_snprintf_append(buf, sizeof(buf), "%s ", mask2);
|
||||||
|
|
||||||
|
rb_snprintf_append(buf, sizeof(buf), "%s %ld %d :%s",
|
||||||
|
get_oper_name(source_p), (long int)rb_current_time(), perm, reason);
|
||||||
|
|
||||||
|
if(!EmptyString(oper_reason))
|
||||||
|
rb_snprintf_append(buf, sizeof(buf), "|%s", oper_reason);
|
||||||
|
|
||||||
|
rb_helper_write(bandb_helper, "%s", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char bandb_del_letter[LAST_BANDB_TYPE] = {
|
||||||
|
'k', 'd', 'x', 'r'
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
bandb_del(bandb_type type, const char *mask1, const char *mask2)
|
||||||
|
{
|
||||||
|
if(bandb_helper == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
static char buf[BUFSIZE];
|
||||||
|
|
||||||
|
buf[0] = '\0';
|
||||||
|
|
||||||
|
rb_snprintf_append(buf, sizeof(buf), "%c %s", bandb_del_letter[type], mask1);
|
||||||
|
|
||||||
|
if(!EmptyString(mask2))
|
||||||
|
rb_snprintf_append(buf, sizeof(buf), " %s", mask2);
|
||||||
|
|
||||||
|
rb_helper_write(bandb_helper, "%s", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bandb_handle_ban(char *parv[], int parc)
|
||||||
|
{
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
char *p;
|
||||||
|
int para = 1;
|
||||||
|
|
||||||
|
aconf = make_conf();
|
||||||
|
aconf->port = 0;
|
||||||
|
|
||||||
|
if(parv[0][0] == 'K')
|
||||||
|
aconf->user = rb_strdup(parv[para++]);
|
||||||
|
|
||||||
|
aconf->host = rb_strdup(parv[para++]);
|
||||||
|
aconf->info.oper = operhash_add(parv[para++]);
|
||||||
|
|
||||||
|
switch (parv[0][0])
|
||||||
|
{
|
||||||
|
case 'K':
|
||||||
|
aconf->status = CONF_KILL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'D':
|
||||||
|
aconf->status = CONF_DLINE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
aconf->status = CONF_XLINE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'R':
|
||||||
|
if(IsChannelName(aconf->host))
|
||||||
|
aconf->status = CONF_RESV_CHANNEL;
|
||||||
|
else
|
||||||
|
aconf->status = CONF_RESV_NICK;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((p = strchr(parv[para], '|')))
|
||||||
|
{
|
||||||
|
*p++ = '\0';
|
||||||
|
aconf->spasswd = rb_strdup(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
aconf->passwd = rb_strdup(parv[para]);
|
||||||
|
|
||||||
|
rb_dlinkAddAlloc(aconf, &bandb_pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bandb_check_kline(struct ConfItem *aconf)
|
||||||
|
{
|
||||||
|
struct rb_sockaddr_storage daddr;
|
||||||
|
struct ConfItem *kconf = NULL;
|
||||||
|
int aftype;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
aftype = parse_netmask(aconf->host, &daddr, NULL);
|
||||||
|
|
||||||
|
if(aftype != HM_HOST)
|
||||||
|
{
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
if(aftype == HM_IPV6)
|
||||||
|
aftype = AF_INET6;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
aftype = AF_INET;
|
||||||
|
|
||||||
|
kconf = find_conf_by_address(aconf->host, NULL, NULL, (struct sockaddr *)&daddr,
|
||||||
|
CONF_KILL, aftype, aconf->user, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
kconf = find_conf_by_address(aconf->host, NULL, NULL, NULL, CONF_KILL, 0, aconf->user, NULL);
|
||||||
|
|
||||||
|
if(kconf && ((kconf->flags & CONF_FLAGS_TEMPORARY) == 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for(p = aconf->user; *p; p++)
|
||||||
|
{
|
||||||
|
if(!IsUserChar(*p) && !IsKWildChar(*p))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(p = aconf->host; *p; p++)
|
||||||
|
{
|
||||||
|
if(!IsHostChar(*p) && !IsKWildChar(*p))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bandb_check_dline(struct ConfItem *aconf)
|
||||||
|
{
|
||||||
|
struct rb_sockaddr_storage daddr;
|
||||||
|
int bits;
|
||||||
|
|
||||||
|
if(!parse_netmask(aconf->host, &daddr, &bits))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bandb_check_xline(struct ConfItem *aconf)
|
||||||
|
{
|
||||||
|
struct ConfItem *xconf;
|
||||||
|
/* XXX perhaps convert spaces to \s? -- jilles */
|
||||||
|
|
||||||
|
xconf = find_xline_mask(aconf->host);
|
||||||
|
if(xconf != NULL && !(xconf->flags & CONF_FLAGS_TEMPORARY))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bandb_check_resv_channel(struct ConfItem *aconf)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
if(hash_find_resv(aconf->host) || strlen(aconf->host) > CHANNELLEN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for(p = aconf->host; *p; p++)
|
||||||
|
{
|
||||||
|
if(!IsChanChar(*p))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bandb_check_resv_nick(struct ConfItem *aconf)
|
||||||
|
{
|
||||||
|
if(!clean_resv_nick(aconf->host))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(find_nick_resv(aconf->host))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bandb_handle_clear(void)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr, *next_ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
|
||||||
|
{
|
||||||
|
free_conf(ptr->data);
|
||||||
|
rb_dlinkDestroy(ptr, &bandb_pending);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bandb_handle_finish(void)
|
||||||
|
{
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
rb_dlink_node *ptr, *next_ptr;
|
||||||
|
|
||||||
|
clear_out_address_conf_bans();
|
||||||
|
clear_s_newconf_bans();
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
|
||||||
|
{
|
||||||
|
aconf = ptr->data;
|
||||||
|
|
||||||
|
rb_dlinkDestroy(ptr, &bandb_pending);
|
||||||
|
|
||||||
|
switch (aconf->status)
|
||||||
|
{
|
||||||
|
case CONF_KILL:
|
||||||
|
if(bandb_check_kline(aconf))
|
||||||
|
add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
|
||||||
|
else
|
||||||
|
free_conf(aconf);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CONF_DLINE:
|
||||||
|
if(bandb_check_dline(aconf))
|
||||||
|
add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf);
|
||||||
|
else
|
||||||
|
free_conf(aconf);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CONF_XLINE:
|
||||||
|
if(bandb_check_xline(aconf))
|
||||||
|
rb_dlinkAddAlloc(aconf, &xline_conf_list);
|
||||||
|
else
|
||||||
|
free_conf(aconf);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CONF_RESV_CHANNEL:
|
||||||
|
if(bandb_check_resv_channel(aconf))
|
||||||
|
add_to_resv_hash(aconf->host, aconf);
|
||||||
|
else
|
||||||
|
free_conf(aconf);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CONF_RESV_NICK:
|
||||||
|
if(bandb_check_resv_nick(aconf))
|
||||||
|
rb_dlinkAddAlloc(aconf, &resv_conf_list);
|
||||||
|
else
|
||||||
|
free_conf(aconf);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check_banned_lines();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((noreturn))
|
||||||
|
bandb_handle_failure(rb_helper *helper, char **parv, int parc)
|
||||||
|
{
|
||||||
|
if(server_state_foreground)
|
||||||
|
fprintf(stderr, "bandb - bandb failure: %s\n", parv[1]);
|
||||||
|
|
||||||
|
ilog(L_MAIN, "bandb - bandb failure: %s", parv[1]);
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL, "bandb - bandb failure: %s", parv[1]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bandb_parse(rb_helper *helper)
|
||||||
|
{
|
||||||
|
static char buf[READBUF_SIZE];
|
||||||
|
char *parv[MAXPARA + 1];
|
||||||
|
int len, parc;
|
||||||
|
|
||||||
|
while((len = rb_helper_read(helper, buf, sizeof(buf))))
|
||||||
|
{
|
||||||
|
parc = rb_string_to_array(buf, parv, MAXPARA);
|
||||||
|
|
||||||
|
if(parc < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (parv[0][0])
|
||||||
|
{
|
||||||
|
case '!':
|
||||||
|
bandb_handle_failure(helper, parv, parc);
|
||||||
|
/* UNREACHABLE */
|
||||||
|
case 'K':
|
||||||
|
case 'D':
|
||||||
|
case 'X':
|
||||||
|
case 'R':
|
||||||
|
bandb_handle_ban(parv, parc);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
bandb_handle_clear();
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
bandb_handle_finish();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bandb_rehash_bans(void)
|
||||||
|
{
|
||||||
|
if(bandb_helper != NULL)
|
||||||
|
rb_helper_write(bandb_helper, "L");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bandb_restart_cb(rb_helper *helper)
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "bandb - bandb_restart_cb called, bandb helper died?");
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"bandb - bandb_restart_cb called, bandb helper died?");
|
||||||
|
if(helper != NULL)
|
||||||
|
{
|
||||||
|
rb_helper_close(helper);
|
||||||
|
bandb_helper = NULL;
|
||||||
|
}
|
||||||
|
start_bandb();
|
||||||
|
return;
|
||||||
|
}
|
396
src/cache.c
Normal file
396
src/cache.c
Normal file
|
@ -0,0 +1,396 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd).
|
||||||
|
* cache.c - code for caching files
|
||||||
|
*
|
||||||
|
* Copyright (C) 2003 Lee Hardy <lee@leeh.co.uk>
|
||||||
|
* Copyright (C) 2003-2005 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* 1.Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2.Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3.The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id: cache.c 25119 2008-03-13 16:57:05Z androsyn $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "ircd_defs.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "cache.h"
|
||||||
|
#include "irc_dictionary.h"
|
||||||
|
#include "numeric.h"
|
||||||
|
#include "send.h"
|
||||||
|
|
||||||
|
struct cachefile *user_motd = NULL;
|
||||||
|
struct cachefile *oper_motd = NULL;
|
||||||
|
struct cacheline *emptyline = NULL;
|
||||||
|
rb_dlink_list links_cache_list;
|
||||||
|
char user_motd_changed[MAX_DATE_STRING];
|
||||||
|
|
||||||
|
struct Dictionary *help_dict_oper = NULL;
|
||||||
|
struct Dictionary *help_dict_user = NULL;
|
||||||
|
|
||||||
|
/* init_cache()
|
||||||
|
*
|
||||||
|
* inputs -
|
||||||
|
* outputs -
|
||||||
|
* side effects - inits the file/line cache blockheaps, loads motds
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
init_cache(void)
|
||||||
|
{
|
||||||
|
/* allocate the emptyline */
|
||||||
|
emptyline = rb_malloc(sizeof(struct cacheline));
|
||||||
|
emptyline->data = rb_strdup(" ");
|
||||||
|
|
||||||
|
user_motd_changed[0] = '\0';
|
||||||
|
|
||||||
|
user_motd = cache_file(MPATH, "ircd.motd", 0);
|
||||||
|
oper_motd = cache_file(OPATH, "opers.motd", 0);
|
||||||
|
memset(&links_cache_list, 0, sizeof(links_cache_list));
|
||||||
|
|
||||||
|
help_dict_oper = irc_dictionary_create(strcasecmp);
|
||||||
|
help_dict_user = irc_dictionary_create(strcasecmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* removes tabs from src, replaces with 8 spaces, and returns the length
|
||||||
|
* of the new string. if the new string would be greater than destlen,
|
||||||
|
* it is truncated to destlen - 1
|
||||||
|
*/
|
||||||
|
static size_t
|
||||||
|
untabify(char *dest, const char *src, size_t destlen)
|
||||||
|
{
|
||||||
|
size_t x = 0, i;
|
||||||
|
const char *s = src;
|
||||||
|
char *d = dest;
|
||||||
|
|
||||||
|
while(*s != '\0' && x < destlen - 1)
|
||||||
|
{
|
||||||
|
if(*s == '\t')
|
||||||
|
{
|
||||||
|
for(i = 0; i < 8 && x < destlen - 1; i++, x++, d++)
|
||||||
|
*d = ' ';
|
||||||
|
s++;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
*d++ = *s++;
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*d = '\0';
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cache_file()
|
||||||
|
*
|
||||||
|
* inputs - file to cache, files "shortname", flags to set
|
||||||
|
* outputs - pointer to file cached, else NULL
|
||||||
|
* side effects -
|
||||||
|
*/
|
||||||
|
struct cachefile *
|
||||||
|
cache_file(const char *filename, const char *shortname, int flags)
|
||||||
|
{
|
||||||
|
FILE *in;
|
||||||
|
struct cachefile *cacheptr;
|
||||||
|
struct cacheline *lineptr;
|
||||||
|
char line[BUFSIZE];
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if((in = fopen(filename, "r")) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
|
cacheptr = rb_malloc(sizeof(struct cachefile));
|
||||||
|
|
||||||
|
rb_strlcpy(cacheptr->name, shortname, sizeof(cacheptr->name));
|
||||||
|
cacheptr->flags = flags;
|
||||||
|
|
||||||
|
/* cache the file... */
|
||||||
|
while(fgets(line, sizeof(line), in) != NULL)
|
||||||
|
{
|
||||||
|
if((p = strpbrk(line, "\r\n")) != NULL)
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
if(!EmptyString(line))
|
||||||
|
{
|
||||||
|
char untabline[BUFSIZE];
|
||||||
|
|
||||||
|
lineptr = rb_malloc(sizeof(struct cacheline));
|
||||||
|
|
||||||
|
untabify(untabline, line, sizeof(untabline));
|
||||||
|
lineptr->data = rb_strdup(untabline);
|
||||||
|
|
||||||
|
rb_dlinkAddTail(lineptr, &lineptr->linenode, &cacheptr->contents);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rb_dlinkAddTailAlloc(emptyline, &cacheptr->contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == rb_dlink_list_length(&cacheptr->contents))
|
||||||
|
{
|
||||||
|
/* No contents. Don't cache it after all. */
|
||||||
|
rb_free(cacheptr);
|
||||||
|
cacheptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(in);
|
||||||
|
return cacheptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cache_links(void *unused)
|
||||||
|
{
|
||||||
|
struct Client *target_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
rb_dlink_node *next_ptr;
|
||||||
|
char *links_line;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, links_cache_list.head)
|
||||||
|
{
|
||||||
|
rb_free(ptr->data);
|
||||||
|
rb_free_rb_dlink_node(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
links_cache_list.head = links_cache_list.tail = NULL;
|
||||||
|
links_cache_list.length = 0;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, global_serv_list.head)
|
||||||
|
{
|
||||||
|
target_p = ptr->data;
|
||||||
|
|
||||||
|
/* skip ourselves (done in /links) and hidden servers */
|
||||||
|
if(IsMe(target_p) ||
|
||||||
|
(IsHidden(target_p) && !ConfigServerHide.disable_hidden))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* if the below is ever modified, change LINKSLINELEN */
|
||||||
|
links_line = rb_malloc(LINKSLINELEN);
|
||||||
|
rb_snprintf(links_line, LINKSLINELEN, "%s %s :1 %s",
|
||||||
|
target_p->name, me.name,
|
||||||
|
target_p->info[0] ? target_p->info :
|
||||||
|
"(Unknown Location)");
|
||||||
|
|
||||||
|
rb_dlinkAddTailAlloc(links_line, &links_cache_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free_cachefile()
|
||||||
|
*
|
||||||
|
* inputs - cachefile to free
|
||||||
|
* outputs -
|
||||||
|
* side effects - cachefile and its data is free'd
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
free_cachefile(struct cachefile *cacheptr)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
rb_dlink_node *next_ptr;
|
||||||
|
|
||||||
|
if(cacheptr == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, cacheptr->contents.head)
|
||||||
|
{
|
||||||
|
if(ptr->data != emptyline)
|
||||||
|
{
|
||||||
|
struct cacheline *line = ptr->data;
|
||||||
|
rb_free(line->data);
|
||||||
|
rb_free(line);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rb_free_rb_dlink_node(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_free(cacheptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load_help()
|
||||||
|
*
|
||||||
|
* inputs -
|
||||||
|
* outputs -
|
||||||
|
* side effects - old help cache deleted
|
||||||
|
* - contents of help directories are loaded.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
load_help(void)
|
||||||
|
{
|
||||||
|
DIR *helpfile_dir = NULL;
|
||||||
|
struct dirent *ldirent= NULL;
|
||||||
|
char filename[PATH_MAX];
|
||||||
|
struct cachefile *cacheptr;
|
||||||
|
struct DictionaryIter iter;
|
||||||
|
|
||||||
|
#if defined(S_ISLNK) && defined(HAVE_LSTAT)
|
||||||
|
struct stat sb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DICTIONARY_FOREACH(cacheptr, &iter, help_dict_oper)
|
||||||
|
{
|
||||||
|
irc_dictionary_delete(help_dict_oper, cacheptr->name);
|
||||||
|
free_cachefile(cacheptr);
|
||||||
|
}
|
||||||
|
DICTIONARY_FOREACH(cacheptr, &iter, help_dict_user)
|
||||||
|
{
|
||||||
|
irc_dictionary_delete(help_dict_user, cacheptr->name);
|
||||||
|
free_cachefile(cacheptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
helpfile_dir = opendir(HPATH);
|
||||||
|
|
||||||
|
if(helpfile_dir == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while((ldirent = readdir(helpfile_dir)) != NULL)
|
||||||
|
{
|
||||||
|
if(ldirent->d_name[0] == '.')
|
||||||
|
continue;
|
||||||
|
rb_snprintf(filename, sizeof(filename), "%s/%s", HPATH, ldirent->d_name);
|
||||||
|
cacheptr = cache_file(filename, ldirent->d_name, HELP_OPER);
|
||||||
|
irc_dictionary_add(help_dict_oper, cacheptr->name, cacheptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(helpfile_dir);
|
||||||
|
helpfile_dir = opendir(UHPATH);
|
||||||
|
|
||||||
|
if(helpfile_dir == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while((ldirent = readdir(helpfile_dir)) != NULL)
|
||||||
|
{
|
||||||
|
if(ldirent->d_name[0] == '.')
|
||||||
|
continue;
|
||||||
|
rb_snprintf(filename, sizeof(filename), "%s/%s", UHPATH, ldirent->d_name);
|
||||||
|
|
||||||
|
#if defined(S_ISLNK) && defined(HAVE_LSTAT)
|
||||||
|
if(lstat(filename, &sb) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* ok, if its a symlink, we work on the presumption if an
|
||||||
|
* oper help exists of that name, its a symlink to that --fl
|
||||||
|
*/
|
||||||
|
if(S_ISLNK(sb.st_mode))
|
||||||
|
{
|
||||||
|
cacheptr = irc_dictionary_retrieve(help_dict_oper, ldirent->d_name);
|
||||||
|
|
||||||
|
if(cacheptr != NULL)
|
||||||
|
{
|
||||||
|
cacheptr->flags |= HELP_USER;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cacheptr = cache_file(filename, ldirent->d_name, HELP_USER);
|
||||||
|
irc_dictionary_add(help_dict_user, cacheptr->name, cacheptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(helpfile_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send_user_motd()
|
||||||
|
*
|
||||||
|
* inputs - client to send motd to
|
||||||
|
* outputs - client is sent motd if exists, else ERR_NOMOTD
|
||||||
|
* side effects -
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
send_user_motd(struct Client *source_p)
|
||||||
|
{
|
||||||
|
struct cacheline *lineptr;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
const char *myname = get_id(&me, source_p);
|
||||||
|
const char *nick = get_id(source_p, source_p);
|
||||||
|
if(user_motd == NULL || rb_dlink_list_length(&user_motd->contents) == 0)
|
||||||
|
{
|
||||||
|
sendto_one(source_p, form_str(ERR_NOMOTD), myname, nick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendto_one(source_p, form_str(RPL_MOTDSTART), myname, nick, me.name);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, user_motd->contents.head)
|
||||||
|
{
|
||||||
|
lineptr = ptr->data;
|
||||||
|
sendto_one(source_p, form_str(RPL_MOTD), myname, nick, lineptr->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendto_one(source_p, form_str(RPL_ENDOFMOTD), myname, nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cache_user_motd(void)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
struct tm *local_tm;
|
||||||
|
|
||||||
|
if(stat(MPATH, &sb) == 0)
|
||||||
|
{
|
||||||
|
local_tm = localtime(&sb.st_mtime);
|
||||||
|
|
||||||
|
if(local_tm != NULL)
|
||||||
|
{
|
||||||
|
rb_snprintf(user_motd_changed, sizeof(user_motd_changed),
|
||||||
|
"%d/%d/%d %d:%d",
|
||||||
|
local_tm->tm_mday, local_tm->tm_mon + 1,
|
||||||
|
1900 + local_tm->tm_year, local_tm->tm_hour,
|
||||||
|
local_tm->tm_min);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free_cachefile(user_motd);
|
||||||
|
user_motd = cache_file(MPATH, "ircd.motd", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* send_oper_motd()
|
||||||
|
*
|
||||||
|
* inputs - client to send motd to
|
||||||
|
* outputs - client is sent oper motd if exists
|
||||||
|
* side effects -
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
send_oper_motd(struct Client *source_p)
|
||||||
|
{
|
||||||
|
struct cacheline *lineptr;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
|
||||||
|
if(oper_motd == NULL || rb_dlink_list_length(&oper_motd->contents) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sendto_one(source_p, form_str(RPL_OMOTDSTART),
|
||||||
|
me.name, source_p->name);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, oper_motd->contents.head)
|
||||||
|
{
|
||||||
|
lineptr = ptr->data;
|
||||||
|
sendto_one(source_p, form_str(RPL_OMOTD),
|
||||||
|
me.name, source_p->name, lineptr->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendto_one(source_p, form_str(RPL_ENDOFOMOTD),
|
||||||
|
me.name, source_p->name);
|
||||||
|
}
|
1406
src/channel.c
Normal file
1406
src/channel.c
Normal file
File diff suppressed because it is too large
Load diff
1830
src/chmode.c
Normal file
1830
src/chmode.c
Normal file
File diff suppressed because it is too large
Load diff
2030
src/client.c
Normal file
2030
src/client.c
Normal file
File diff suppressed because it is too large
Load diff
142
src/getopt.c
Normal file
142
src/getopt.c
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: A slightly useful ircd.
|
||||||
|
* getopt.c: Uses getopt to fetch the command line options.
|
||||||
|
*
|
||||||
|
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||||
|
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||||
|
* Copyright (C) 2002-2005 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: getopt.c 6 2005-09-10 01:02:21Z nenolod $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdinc.h"
|
||||||
|
|
||||||
|
#include "ircd_getopt.h"
|
||||||
|
|
||||||
|
# define OPTCHAR '-'
|
||||||
|
|
||||||
|
static void usage(char *name) __attribute__((noreturn));
|
||||||
|
|
||||||
|
void
|
||||||
|
parseargs(int *argc, char ***argv, struct lgetopt *opts)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *progname = (*argv)[0];
|
||||||
|
|
||||||
|
/* loop through each argument */
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
(*argc)--;
|
||||||
|
(*argv)++;
|
||||||
|
|
||||||
|
if(*argc < 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if it *is* an arg.. */
|
||||||
|
if((*argv)[0][0] != OPTCHAR)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*argv)[0]++;
|
||||||
|
|
||||||
|
/* search through our argument list, and see if it matches */
|
||||||
|
for (i = 0; opts[i].opt; i++)
|
||||||
|
{
|
||||||
|
if(!strcmp(opts[i].opt, (*argv)[0]))
|
||||||
|
{
|
||||||
|
/* found our argument */
|
||||||
|
found = 1;
|
||||||
|
|
||||||
|
switch (opts[i].argtype)
|
||||||
|
{
|
||||||
|
case YESNO:
|
||||||
|
*((int *) opts[i].argloc) = 1;
|
||||||
|
break;
|
||||||
|
case INTEGER:
|
||||||
|
if(*argc < 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error: option '%c%s' requires an argument\n",
|
||||||
|
OPTCHAR, opts[i].opt);
|
||||||
|
usage((*argv)[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
*((int *) opts[i].argloc) = atoi((*argv)[1]);
|
||||||
|
|
||||||
|
(*argc)--;
|
||||||
|
(*argv)++;
|
||||||
|
break;
|
||||||
|
case STRING:
|
||||||
|
if(*argc < 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"error: option '%c%s' requires an argument\n",
|
||||||
|
OPTCHAR, opts[i].opt);
|
||||||
|
usage(progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
*((char **) opts[i].argloc) =
|
||||||
|
malloc(strlen((*argv)[1]) + 1);
|
||||||
|
strcpy(*((char **) opts[i].argloc), (*argv)[1]);
|
||||||
|
|
||||||
|
(*argc)--;
|
||||||
|
(*argv)++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case USAGE:
|
||||||
|
usage(progname);
|
||||||
|
/*NOTREACHED*/ default:
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error: internal error in parseargs() at %s:%d\n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "error: unknown argument '%c%s'\n", OPTCHAR, (*argv)[0]);
|
||||||
|
usage(progname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(char *name)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
fprintf(stderr, "Usage: %s [options]\n", name);
|
||||||
|
fprintf(stderr, "Where valid options are:\n");
|
||||||
|
|
||||||
|
for (i = 0; myopts[i].opt; i++)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "\t%c%-10s %-20s%s\n", OPTCHAR,
|
||||||
|
myopts[i].opt, (myopts[i].argtype == YESNO
|
||||||
|
|| myopts[i].argtype ==
|
||||||
|
USAGE) ? "" : myopts[i].argtype ==
|
||||||
|
INTEGER ? "<number>" : "<string>", myopts[i].desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
805
src/hash.c
Normal file
805
src/hash.c
Normal file
|
@ -0,0 +1,805 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: A slightly useful ircd.
|
||||||
|
* hash.c: Maintains hashtables.
|
||||||
|
*
|
||||||
|
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||||
|
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||||
|
* Copyright (C) 2002-2005 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: hash.c 3177 2007-02-01 00:19:14Z jilles $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "ircd_defs.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "channel.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "match.h"
|
||||||
|
#include "ircd.h"
|
||||||
|
#include "numeric.h"
|
||||||
|
#include "send.h"
|
||||||
|
#include "msg.h"
|
||||||
|
#include "cache.h"
|
||||||
|
#include "s_newconf.h"
|
||||||
|
#include "s_assert.h"
|
||||||
|
|
||||||
|
#define ZCONNID_MAX 64 /* i doubt we'll have this many ziplinks ;) */
|
||||||
|
|
||||||
|
#define hash_cli_connid(x) (x % CLI_CONNID_MAX)
|
||||||
|
#define hash_zconnid(x) (x % ZCONNID_MAX)
|
||||||
|
|
||||||
|
static rb_dlink_list clientbyconnidTable[CLI_CONNID_MAX];
|
||||||
|
static rb_dlink_list clientbyzconnidTable[ZCONNID_MAX];
|
||||||
|
|
||||||
|
rb_dlink_list *clientTable;
|
||||||
|
rb_dlink_list *channelTable;
|
||||||
|
rb_dlink_list *idTable;
|
||||||
|
rb_dlink_list *resvTable;
|
||||||
|
rb_dlink_list *hostTable;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* look in whowas.c for the missing ...[WW_MAX]; entry
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hashing.
|
||||||
|
*
|
||||||
|
* The server uses a chained hash table to provide quick and efficient
|
||||||
|
* hash table maintenance (providing the hash function works evenly over
|
||||||
|
* the input range). The hash table is thus not susceptible to problems
|
||||||
|
* of filling all the buckets or the need to rehash.
|
||||||
|
* It is expected that the hash table would look something like this
|
||||||
|
* during use:
|
||||||
|
* +-----+ +-----+ +-----+ +-----+
|
||||||
|
* ---| 224 |----| 225 |----| 226 |---| 227 |---
|
||||||
|
* +-----+ +-----+ +-----+ +-----+
|
||||||
|
* | | |
|
||||||
|
* +-----+ +-----+ +-----+
|
||||||
|
* | A | | C | | D |
|
||||||
|
* +-----+ +-----+ +-----+
|
||||||
|
* |
|
||||||
|
* +-----+
|
||||||
|
* | B |
|
||||||
|
* +-----+
|
||||||
|
*
|
||||||
|
* A - GOPbot, B - chang, C - hanuaway, D - *.mu.OZ.AU
|
||||||
|
*
|
||||||
|
* The order shown above is just one instant of the server.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The hash functions currently used are based Fowler/Noll/Vo hashes
|
||||||
|
* which work amazingly well and have a extremely low collision rate
|
||||||
|
* For more info see http://www.isthe.com/chongo/tech/comp/fnv/index.html
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* init_hash()
|
||||||
|
*
|
||||||
|
* clears the various hashtables
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
init_hash(void)
|
||||||
|
{
|
||||||
|
clientTable = rb_malloc(sizeof(rb_dlink_list) * U_MAX);
|
||||||
|
idTable = rb_malloc(sizeof(rb_dlink_list) * U_MAX);
|
||||||
|
channelTable = rb_malloc(sizeof(rb_dlink_list) * CH_MAX);
|
||||||
|
hostTable = rb_malloc(sizeof(rb_dlink_list) * HOST_MAX);
|
||||||
|
resvTable = rb_malloc(sizeof(rb_dlink_list) * R_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef RICER_HASHING
|
||||||
|
u_int32_t
|
||||||
|
fnv_hash_upper(const unsigned char *s, int bits)
|
||||||
|
{
|
||||||
|
u_int32_t h = FNV1_32_INIT;
|
||||||
|
|
||||||
|
while (*s)
|
||||||
|
{
|
||||||
|
h ^= ToUpper(*s++);
|
||||||
|
h += (h<<1) + (h<<4) + (h<<7) + (h << 8) + (h << 24);
|
||||||
|
}
|
||||||
|
if (bits < 32)
|
||||||
|
h = ((h >> bits) ^ h) & ((1<<bits)-1);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_int32_t
|
||||||
|
fnv_hash(const unsigned char *s, int bits)
|
||||||
|
{
|
||||||
|
u_int32_t h = FNV1_32_INIT;
|
||||||
|
|
||||||
|
while (*s)
|
||||||
|
{
|
||||||
|
h ^= *s++;
|
||||||
|
h += (h<<1) + (h<<4) + (h<<7) + (h << 8) + (h << 24);
|
||||||
|
}
|
||||||
|
if (bits < 32)
|
||||||
|
h = ((h >> bits) ^ h) & ((1<<bits)-1);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_int32_t
|
||||||
|
fnv_hash_len(const unsigned char *s, int bits, int len)
|
||||||
|
{
|
||||||
|
u_int32_t h = FNV1_32_INIT;
|
||||||
|
const unsigned char *x = s + len;
|
||||||
|
while (*s && s < x)
|
||||||
|
{
|
||||||
|
h ^= *s++;
|
||||||
|
h += (h<<1) + (h<<4) + (h<<7) + (h << 8) + (h << 24);
|
||||||
|
}
|
||||||
|
if (bits < 32)
|
||||||
|
h = ((h >> bits) ^ h) & ((1<<bits)-1);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_int32_t
|
||||||
|
fnv_hash_upper_len(const unsigned char *s, int bits, int len)
|
||||||
|
{
|
||||||
|
u_int32_t h = FNV1_32_INIT;
|
||||||
|
const unsigned char *x = s + len;
|
||||||
|
while (*s && s < x)
|
||||||
|
{
|
||||||
|
h ^= ToUpper(*s++);
|
||||||
|
h += (h<<1) + (h<<4) + (h<<7) + (h << 8) + (h << 24);
|
||||||
|
}
|
||||||
|
if (bits < 32)
|
||||||
|
h = ((h >> bits) ^ h) & ((1<<bits)-1);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* hash_nick()
|
||||||
|
*
|
||||||
|
* hashes a nickname, first converting to lowercase
|
||||||
|
*/
|
||||||
|
static u_int32_t
|
||||||
|
hash_nick(const char *name)
|
||||||
|
{
|
||||||
|
return fnv_hash_upper((const unsigned char *) name, U_MAX_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hash_id()
|
||||||
|
*
|
||||||
|
* hashes an id, case is kept
|
||||||
|
*/
|
||||||
|
static u_int32_t
|
||||||
|
hash_id(const char *name)
|
||||||
|
{
|
||||||
|
return fnv_hash((const unsigned char *) name, U_MAX_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hash_channel()
|
||||||
|
*
|
||||||
|
* hashes a channel name, based on first 30 chars only for efficiency
|
||||||
|
*/
|
||||||
|
static u_int32_t
|
||||||
|
hash_channel(const char *name)
|
||||||
|
{
|
||||||
|
return fnv_hash_upper_len((const unsigned char *) name, CH_MAX_BITS, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hash_hostname()
|
||||||
|
*
|
||||||
|
* hashes a hostname, based on first 30 chars only, as thats likely to
|
||||||
|
* be more dynamic than rest.
|
||||||
|
*/
|
||||||
|
static u_int32_t
|
||||||
|
hash_hostname(const char *name)
|
||||||
|
{
|
||||||
|
return fnv_hash_upper_len((const unsigned char *) name, HOST_MAX_BITS, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hash_resv()
|
||||||
|
*
|
||||||
|
* hashes a resv channel name, based on first 30 chars only
|
||||||
|
*/
|
||||||
|
static u_int32_t
|
||||||
|
hash_resv(const char *name)
|
||||||
|
{
|
||||||
|
return fnv_hash_upper_len((const unsigned char *) name, R_MAX_BITS, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add_to_id_hash()
|
||||||
|
*
|
||||||
|
* adds an entry to the id hash table
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
add_to_id_hash(const char *name, struct Client *client_p)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
if(EmptyString(name) || (client_p == NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
hashv = hash_id(name);
|
||||||
|
rb_dlinkAddAlloc(client_p, &idTable[hashv]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add_to_client_hash()
|
||||||
|
*
|
||||||
|
* adds an entry (client/server) to the client hash table
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
add_to_client_hash(const char *name, struct Client *client_p)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
s_assert(name != NULL);
|
||||||
|
s_assert(client_p != NULL);
|
||||||
|
if(EmptyString(name) || (client_p == NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
hashv = hash_nick(name);
|
||||||
|
rb_dlinkAddAlloc(client_p, &clientTable[hashv]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add_to_hostname_hash()
|
||||||
|
*
|
||||||
|
* adds a client entry to the hostname hash table
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
add_to_hostname_hash(const char *hostname, struct Client *client_p)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
s_assert(hostname != NULL);
|
||||||
|
s_assert(client_p != NULL);
|
||||||
|
if(EmptyString(hostname) || (client_p == NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
hashv = hash_hostname(hostname);
|
||||||
|
rb_dlinkAddAlloc(client_p, &hostTable[hashv]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add_to_resv_hash()
|
||||||
|
*
|
||||||
|
* adds a resv channel entry to the resv hash table
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
add_to_resv_hash(const char *name, struct ConfItem *aconf)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
s_assert(!EmptyString(name));
|
||||||
|
s_assert(aconf != NULL);
|
||||||
|
if(EmptyString(name) || aconf == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hashv = hash_resv(name);
|
||||||
|
rb_dlinkAddAlloc(aconf, &resvTable[hashv]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* del_from_id_hash()
|
||||||
|
*
|
||||||
|
* removes an id from the id hash table
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
del_from_id_hash(const char *id, struct Client *client_p)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
s_assert(id != NULL);
|
||||||
|
s_assert(client_p != NULL);
|
||||||
|
if(EmptyString(id) || client_p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hashv = hash_id(id);
|
||||||
|
rb_dlinkFindDestroy(client_p, &idTable[hashv]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* del_from_client_hash()
|
||||||
|
*
|
||||||
|
* removes a client/server from the client hash table
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
del_from_client_hash(const char *name, struct Client *client_p)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
/* no s_asserts, this can happen when removing a client that
|
||||||
|
* is unregistered.
|
||||||
|
*/
|
||||||
|
if(EmptyString(name) || client_p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hashv = hash_nick(name);
|
||||||
|
rb_dlinkFindDestroy(client_p, &clientTable[hashv]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* del_from_channel_hash()
|
||||||
|
*
|
||||||
|
* removes a channel from the channel hash table
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
del_from_channel_hash(const char *name, struct Channel *chptr)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
s_assert(name != NULL);
|
||||||
|
s_assert(chptr != NULL);
|
||||||
|
|
||||||
|
if(EmptyString(name) || chptr == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hashv = hash_channel(name);
|
||||||
|
rb_dlinkFindDestroy(chptr, &channelTable[hashv]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* del_from_hostname_hash()
|
||||||
|
*
|
||||||
|
* removes a client entry from the hostname hash table
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
del_from_hostname_hash(const char *hostname, struct Client *client_p)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
if(hostname == NULL || client_p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hashv = hash_hostname(hostname);
|
||||||
|
|
||||||
|
rb_dlinkFindDestroy(client_p, &hostTable[hashv]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* del_from_resv_hash()
|
||||||
|
*
|
||||||
|
* removes a resv entry from the resv hash table
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
del_from_resv_hash(const char *name, struct ConfItem *aconf)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
s_assert(name != NULL);
|
||||||
|
s_assert(aconf != NULL);
|
||||||
|
if(EmptyString(name) || aconf == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hashv = hash_resv(name);
|
||||||
|
|
||||||
|
rb_dlinkFindDestroy(aconf, &resvTable[hashv]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find_id()
|
||||||
|
*
|
||||||
|
* finds a client entry from the id hash table
|
||||||
|
*/
|
||||||
|
struct Client *
|
||||||
|
find_id(const char *name)
|
||||||
|
{
|
||||||
|
struct Client *target_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
if(EmptyString(name))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
hashv = hash_id(name);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, idTable[hashv].head)
|
||||||
|
{
|
||||||
|
target_p = ptr->data;
|
||||||
|
|
||||||
|
if(strcmp(name, target_p->id) == 0)
|
||||||
|
return target_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find_client()
|
||||||
|
*
|
||||||
|
* finds a client/server entry from the client hash table
|
||||||
|
*/
|
||||||
|
struct Client *
|
||||||
|
find_client(const char *name)
|
||||||
|
{
|
||||||
|
struct Client *target_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
s_assert(name != NULL);
|
||||||
|
if(EmptyString(name))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* hunting for an id, not a nick */
|
||||||
|
if(IsDigit(*name))
|
||||||
|
return (find_id(name));
|
||||||
|
|
||||||
|
hashv = hash_nick(name);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, clientTable[hashv].head)
|
||||||
|
{
|
||||||
|
target_p = ptr->data;
|
||||||
|
|
||||||
|
if(irccmp(name, target_p->name) == 0)
|
||||||
|
return target_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find_named_client()
|
||||||
|
*
|
||||||
|
* finds a client/server entry from the client hash table
|
||||||
|
*/
|
||||||
|
struct Client *
|
||||||
|
find_named_client(const char *name)
|
||||||
|
{
|
||||||
|
struct Client *target_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
s_assert(name != NULL);
|
||||||
|
if(EmptyString(name))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
hashv = hash_nick(name);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, clientTable[hashv].head)
|
||||||
|
{
|
||||||
|
target_p = ptr->data;
|
||||||
|
|
||||||
|
if(irccmp(name, target_p->name) == 0)
|
||||||
|
return target_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find_server()
|
||||||
|
*
|
||||||
|
* finds a server from the client hash table
|
||||||
|
*/
|
||||||
|
struct Client *
|
||||||
|
find_server(struct Client *source_p, const char *name)
|
||||||
|
{
|
||||||
|
struct Client *target_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
if(EmptyString(name))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if((source_p == NULL || !MyClient(source_p)) &&
|
||||||
|
IsDigit(*name) && strlen(name) == 3)
|
||||||
|
{
|
||||||
|
target_p = find_id(name);
|
||||||
|
return(target_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
hashv = hash_nick(name);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, clientTable[hashv].head)
|
||||||
|
{
|
||||||
|
target_p = ptr->data;
|
||||||
|
|
||||||
|
if((IsServer(target_p) || IsMe(target_p)) &&
|
||||||
|
irccmp(name, target_p->name) == 0)
|
||||||
|
return target_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find_hostname()
|
||||||
|
*
|
||||||
|
* finds a hostname rb_dlink list from the hostname hash table.
|
||||||
|
* we return the full rb_dlink list, because you can have multiple
|
||||||
|
* entries with the same hostname
|
||||||
|
*/
|
||||||
|
rb_dlink_node *
|
||||||
|
find_hostname(const char *hostname)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
if(EmptyString(hostname))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
hashv = hash_hostname(hostname);
|
||||||
|
|
||||||
|
return hostTable[hashv].head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find_channel()
|
||||||
|
*
|
||||||
|
* finds a channel from the channel hash table
|
||||||
|
*/
|
||||||
|
struct Channel *
|
||||||
|
find_channel(const char *name)
|
||||||
|
{
|
||||||
|
struct Channel *chptr;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
s_assert(name != NULL);
|
||||||
|
if(EmptyString(name))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
hashv = hash_channel(name);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, channelTable[hashv].head)
|
||||||
|
{
|
||||||
|
chptr = ptr->data;
|
||||||
|
|
||||||
|
if(irccmp(name, chptr->chname) == 0)
|
||||||
|
return chptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_or_create_channel
|
||||||
|
* inputs - client pointer
|
||||||
|
* - channel name
|
||||||
|
* - pointer to int flag whether channel was newly created or not
|
||||||
|
* output - returns channel block or NULL if illegal name
|
||||||
|
* - also modifies *isnew
|
||||||
|
*
|
||||||
|
* Get Channel block for chname (and allocate a new channel
|
||||||
|
* block, if it didn't exist before).
|
||||||
|
*/
|
||||||
|
struct Channel *
|
||||||
|
get_or_create_channel(struct Client *client_p, const char *chname, int *isnew)
|
||||||
|
{
|
||||||
|
struct Channel *chptr;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
unsigned int hashv;
|
||||||
|
int len;
|
||||||
|
const char *s = chname;
|
||||||
|
|
||||||
|
if(EmptyString(s))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
len = strlen(s);
|
||||||
|
if(len > CHANNELLEN)
|
||||||
|
{
|
||||||
|
char *t;
|
||||||
|
if(IsServer(client_p))
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_DEBUG, L_ALL,
|
||||||
|
"*** Long channel name from %s (%d > %d): %s",
|
||||||
|
client_p->name, len, CHANNELLEN, s);
|
||||||
|
}
|
||||||
|
len = CHANNELLEN;
|
||||||
|
t = LOCAL_COPY(s);
|
||||||
|
*(t + CHANNELLEN) = '\0';
|
||||||
|
s = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashv = hash_channel(s);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, channelTable[hashv].head)
|
||||||
|
{
|
||||||
|
chptr = ptr->data;
|
||||||
|
|
||||||
|
if(irccmp(s, chptr->chname) == 0)
|
||||||
|
{
|
||||||
|
if(isnew != NULL)
|
||||||
|
*isnew = 0;
|
||||||
|
return chptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isnew != NULL)
|
||||||
|
*isnew = 1;
|
||||||
|
|
||||||
|
chptr = allocate_channel(s);
|
||||||
|
|
||||||
|
rb_dlinkAdd(chptr, &chptr->node, &global_channel_list);
|
||||||
|
|
||||||
|
chptr->channelts = rb_current_time(); /* doesn't hurt to set it here */
|
||||||
|
|
||||||
|
rb_dlinkAddAlloc(chptr, &channelTable[hashv]);
|
||||||
|
|
||||||
|
return chptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hash_find_resv()
|
||||||
|
*
|
||||||
|
* hunts for a resv entry in the resv hash table
|
||||||
|
*/
|
||||||
|
struct ConfItem *
|
||||||
|
hash_find_resv(const char *name)
|
||||||
|
{
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
unsigned int hashv;
|
||||||
|
|
||||||
|
s_assert(name != NULL);
|
||||||
|
if(EmptyString(name))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
hashv = hash_resv(name);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, resvTable[hashv].head)
|
||||||
|
{
|
||||||
|
aconf = ptr->data;
|
||||||
|
|
||||||
|
if(!irccmp(name, aconf->host))
|
||||||
|
{
|
||||||
|
aconf->port++;
|
||||||
|
return aconf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clear_resv_hash(void)
|
||||||
|
{
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
rb_dlink_node *next_ptr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
HASH_WALK_SAFE(i, R_MAX, ptr, next_ptr, resvTable)
|
||||||
|
{
|
||||||
|
aconf = ptr->data;
|
||||||
|
|
||||||
|
/* skip temp resvs */
|
||||||
|
if(aconf->hold)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
free_conf(ptr->data);
|
||||||
|
rb_dlinkDestroy(ptr, &resvTable[i]);
|
||||||
|
}
|
||||||
|
HASH_WALK_END
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
add_to_zconnid_hash(struct Client *client_p)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
hashv = hash_zconnid(client_p->localClient->zconnid);
|
||||||
|
rb_dlinkAddAlloc(client_p, &clientbyzconnidTable[hashv]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
del_from_zconnid_hash(struct Client *client_p)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
hashv = hash_zconnid(client_p->localClient->zconnid);
|
||||||
|
rb_dlinkFindDestroy(client_p, &clientbyzconnidTable[hashv]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
add_to_cli_connid_hash(struct Client *client_p)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
hashv = hash_cli_connid(client_p->localClient->connid);
|
||||||
|
rb_dlinkAddAlloc(client_p, &clientbyconnidTable[hashv]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
del_from_cli_connid_hash(struct Client *client_p)
|
||||||
|
{
|
||||||
|
unsigned int hashv;
|
||||||
|
hashv = hash_cli_connid(client_p->localClient->connid);
|
||||||
|
rb_dlinkFindDestroy(client_p, &clientbyconnidTable[hashv]);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Client *
|
||||||
|
find_cli_connid_hash(int connid)
|
||||||
|
{
|
||||||
|
struct Client *target_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
unsigned int hashv;
|
||||||
|
hashv = hash_cli_connid(connid);
|
||||||
|
RB_DLINK_FOREACH(ptr, clientbyconnidTable[hashv].head)
|
||||||
|
{
|
||||||
|
target_p = ptr->data;
|
||||||
|
if(target_p->localClient->connid == (uint32_t)connid)
|
||||||
|
return target_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashv = hash_zconnid(connid);
|
||||||
|
RB_DLINK_FOREACH(ptr, clientbyzconnidTable[hashv].head)
|
||||||
|
{
|
||||||
|
target_p = ptr->data;
|
||||||
|
if(target_p->localClient->zconnid == (uint32_t)connid)
|
||||||
|
return target_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
output_hash(struct Client *source_p, const char *name, int length, int *counts, unsigned long deepest)
|
||||||
|
{
|
||||||
|
unsigned long total = 0;
|
||||||
|
int i;
|
||||||
|
char buf[128];
|
||||||
|
|
||||||
|
sendto_one_numeric(source_p, RPL_STATSDEBUG,
|
||||||
|
"B :%s Hash Statistics", name);
|
||||||
|
|
||||||
|
snprintf(buf, sizeof buf, "%.3f%%",
|
||||||
|
(float) ((counts[0]*100) / (float) length));
|
||||||
|
sendto_one_numeric(source_p, RPL_STATSDEBUG,
|
||||||
|
"B :Size: %d Empty: %d (%s)",
|
||||||
|
length, counts[0], buf);
|
||||||
|
|
||||||
|
for(i = 1; i < 11; i++)
|
||||||
|
{
|
||||||
|
total += (counts[i] * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dont want to divide by 0! --fl */
|
||||||
|
if(counts[0] != length)
|
||||||
|
{
|
||||||
|
snprintf(buf, sizeof buf, "%.3f/%.3f",
|
||||||
|
(float) (total / (length - counts[0])),
|
||||||
|
(float) (total / length));
|
||||||
|
sendto_one_numeric(source_p, RPL_STATSDEBUG,
|
||||||
|
"B :Average depth: %s Highest depth: %lu",
|
||||||
|
buf, deepest);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < 11; i++)
|
||||||
|
{
|
||||||
|
sendto_one_numeric(source_p, RPL_STATSDEBUG,
|
||||||
|
"B :Nodes with %d entries: %d",
|
||||||
|
i, counts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
count_hash(struct Client *source_p, rb_dlink_list *table, int length, const char *name)
|
||||||
|
{
|
||||||
|
int counts[11];
|
||||||
|
unsigned long deepest = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(counts, 0, sizeof(counts));
|
||||||
|
|
||||||
|
for(i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
if(rb_dlink_list_length(&table[i]) >= 10)
|
||||||
|
counts[10]++;
|
||||||
|
else
|
||||||
|
counts[rb_dlink_list_length(&table[i])]++;
|
||||||
|
|
||||||
|
if(rb_dlink_list_length(&table[i]) > deepest)
|
||||||
|
deepest = rb_dlink_list_length(&table[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
output_hash(source_p, name, length, counts, deepest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hash_stats(struct Client *source_p)
|
||||||
|
{
|
||||||
|
count_hash(source_p, channelTable, CH_MAX, "Channel");
|
||||||
|
sendto_one_numeric(source_p, RPL_STATSDEBUG, "B :--");
|
||||||
|
count_hash(source_p, clientTable, U_MAX, "Client");
|
||||||
|
sendto_one_numeric(source_p, RPL_STATSDEBUG, "B :--");
|
||||||
|
count_hash(source_p, idTable, U_MAX, "ID");
|
||||||
|
sendto_one_numeric(source_p, RPL_STATSDEBUG, "B :--");
|
||||||
|
count_hash(source_p, hostTable, HOST_MAX, "Hostname");
|
||||||
|
sendto_one_numeric(source_p, RPL_STATSDEBUG, "B :--");
|
||||||
|
count_hash(source_p, clientbyconnidTable, CLI_CONNID_MAX, "Client by connection id");
|
||||||
|
}
|
225
src/hook.c
Normal file
225
src/hook.c
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd).
|
||||||
|
* hook.c - code for dealing with the hook system
|
||||||
|
*
|
||||||
|
* This code is basically a slow leaking array. Events are simply just a
|
||||||
|
* position in this array. When hooks are added, events will be created if
|
||||||
|
* they dont exist - this means modules with hooks can be loaded in any
|
||||||
|
* order, and events are preserved through module reloads.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-2005 Lee Hardy <lee -at- leeh.co.uk>
|
||||||
|
* Copyright (C) 2004-2005 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* 1.Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2.Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3.The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id: hook.c 712 2006-02-06 04:42:14Z gxti $
|
||||||
|
*/
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "hook.h"
|
||||||
|
#include "match.h"
|
||||||
|
|
||||||
|
hook *hooks;
|
||||||
|
|
||||||
|
#define HOOK_INCREMENT 1000
|
||||||
|
|
||||||
|
int num_hooks = 0;
|
||||||
|
int last_hook = 0;
|
||||||
|
int max_hooks = HOOK_INCREMENT;
|
||||||
|
|
||||||
|
#ifdef USE_IODEBUG_HOOKS
|
||||||
|
int h_iosend_id;
|
||||||
|
int h_iorecv_id;
|
||||||
|
int h_iorecvctrl_id;
|
||||||
|
#endif
|
||||||
|
int h_burst_client;
|
||||||
|
int h_burst_channel;
|
||||||
|
int h_burst_finished;
|
||||||
|
int h_server_introduced;
|
||||||
|
int h_server_eob;
|
||||||
|
int h_client_exit;
|
||||||
|
int h_after_client_exit;
|
||||||
|
int h_umode_changed;
|
||||||
|
int h_new_local_user;
|
||||||
|
int h_new_remote_user;
|
||||||
|
int h_introduce_client;
|
||||||
|
int h_can_kick;
|
||||||
|
int h_privmsg_user;
|
||||||
|
int h_privmsg_channel;
|
||||||
|
int h_conf_read_start;
|
||||||
|
int h_conf_read_end;
|
||||||
|
|
||||||
|
void
|
||||||
|
init_hook(void)
|
||||||
|
{
|
||||||
|
hooks = rb_malloc(sizeof(hook) * HOOK_INCREMENT);
|
||||||
|
|
||||||
|
#ifdef USE_IODEBUG_HOOKS
|
||||||
|
h_iosend_id = register_hook("iosend");
|
||||||
|
h_iorecv_id = register_hook("iorecv");
|
||||||
|
h_iorecvctrl_id = register_hook("iorecvctrl");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
h_burst_client = register_hook("burst_client");
|
||||||
|
h_burst_channel = register_hook("burst_channel");
|
||||||
|
h_burst_finished = register_hook("burst_finished");
|
||||||
|
h_server_introduced = register_hook("server_introduced");
|
||||||
|
h_server_eob = register_hook("server_eob");
|
||||||
|
h_client_exit = register_hook("client_exit");
|
||||||
|
h_after_client_exit = register_hook("after_client_exit");
|
||||||
|
h_umode_changed = register_hook("umode_changed");
|
||||||
|
h_new_local_user = register_hook("new_local_user");
|
||||||
|
h_new_remote_user = register_hook("new_remote_user");
|
||||||
|
h_introduce_client = register_hook("introduce_client");
|
||||||
|
h_can_kick = register_hook("can_kick");
|
||||||
|
h_privmsg_user = register_hook("privmsg_user");
|
||||||
|
h_privmsg_channel = register_hook("privmsg_channel");
|
||||||
|
h_conf_read_start = register_hook("conf_read_start");
|
||||||
|
h_conf_read_end = register_hook("conf_read_end");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* grow_hooktable()
|
||||||
|
* Enlarges the hook table by HOOK_INCREMENT
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
grow_hooktable(void)
|
||||||
|
{
|
||||||
|
hook *newhooks;
|
||||||
|
|
||||||
|
newhooks = rb_malloc(sizeof(hook) * (max_hooks + HOOK_INCREMENT));
|
||||||
|
memcpy(newhooks, hooks, sizeof(hook) * num_hooks);
|
||||||
|
|
||||||
|
rb_free(hooks);
|
||||||
|
hooks = newhooks;
|
||||||
|
max_hooks += HOOK_INCREMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find_freehookslot()
|
||||||
|
* Finds the next free slot in the hook table, given by an entry with
|
||||||
|
* h->name being NULL.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
find_freehookslot(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if((num_hooks + 1) > max_hooks)
|
||||||
|
grow_hooktable();
|
||||||
|
|
||||||
|
for(i = 0; i < max_hooks; i++)
|
||||||
|
{
|
||||||
|
if(!hooks[i].name)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* shouldnt ever get here */
|
||||||
|
return(max_hooks - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find_hook()
|
||||||
|
* Finds an event in the hook table.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
find_hook(const char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < max_hooks; i++)
|
||||||
|
{
|
||||||
|
if(!hooks[i].name)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!irccmp(hooks[i].name, name))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* register_hook()
|
||||||
|
* Finds an events position in the hook table, creating it if it doesnt
|
||||||
|
* exist.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
register_hook(const char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if((i = find_hook(name)) < 0)
|
||||||
|
{
|
||||||
|
i = find_freehookslot();
|
||||||
|
hooks[i].name = rb_strdup(name);
|
||||||
|
num_hooks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add_hook()
|
||||||
|
* Adds a hook to an event in the hook table, creating event first if
|
||||||
|
* needed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
add_hook(const char *name, hookfn fn)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = register_hook(name);
|
||||||
|
|
||||||
|
rb_dlinkAddAlloc(fn, &hooks[i].hooks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove_hook()
|
||||||
|
* Removes a hook from an event in the hook table.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
remove_hook(const char *name, hookfn fn)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if((i = find_hook(name)) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rb_dlinkFindDestroy(fn, &hooks[i].hooks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* call_hook()
|
||||||
|
* Calls functions from a given event in the hook table.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
call_hook(int id, void *arg)
|
||||||
|
{
|
||||||
|
hookfn fn;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
|
||||||
|
/* The ID we were passed is the position in the hook table of this
|
||||||
|
* hook
|
||||||
|
*/
|
||||||
|
RB_DLINK_FOREACH(ptr, hooks[id].hooks.head)
|
||||||
|
{
|
||||||
|
fn = ptr->data;
|
||||||
|
fn(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
774
src/hostmask.c
Normal file
774
src/hostmask.c
Normal file
|
@ -0,0 +1,774 @@
|
||||||
|
/*
|
||||||
|
* charybdis: an advanced internet relay chat daemon (ircd).
|
||||||
|
* hostmask.c: Code to efficiently find IP & hostmask based configs.
|
||||||
|
*
|
||||||
|
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||||
|
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||||
|
* Copyright (C) 2002-2005 ircd-ratbox development team
|
||||||
|
* Copyright (C) 2005-2008 charybdis development team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: hostmask.c 2757 2006-11-10 22:58:15Z jilles $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "ircd_defs.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "hostmask.h"
|
||||||
|
#include "numeric.h"
|
||||||
|
#include "send.h"
|
||||||
|
#include "match.h"
|
||||||
|
#include "ipv4_from_ipv6.h"
|
||||||
|
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
static unsigned long hash_ipv6(struct sockaddr *, int);
|
||||||
|
#endif
|
||||||
|
static unsigned long hash_ipv4(struct sockaddr *, int);
|
||||||
|
|
||||||
|
|
||||||
|
/* int parse_netmask(const char *, struct rb_sockaddr_storage *, int *);
|
||||||
|
* Input: A hostmask, or an IPV4/6 address.
|
||||||
|
* Output: An integer describing whether it is an IPV4, IPV6 address or a
|
||||||
|
* hostmask, an address(if it is an IP mask),
|
||||||
|
* a bitlength(if it is IP mask).
|
||||||
|
* Side effects: None
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
parse_netmask(const char *text, struct rb_sockaddr_storage *naddr, int *nb)
|
||||||
|
{
|
||||||
|
char *ip = LOCAL_COPY(text);
|
||||||
|
char *ptr;
|
||||||
|
struct rb_sockaddr_storage *addr, xaddr;
|
||||||
|
int *b, xb;
|
||||||
|
if(nb == NULL)
|
||||||
|
b = &xb;
|
||||||
|
else
|
||||||
|
b = nb;
|
||||||
|
|
||||||
|
if(naddr == NULL)
|
||||||
|
addr = &xaddr;
|
||||||
|
else
|
||||||
|
addr = naddr;
|
||||||
|
|
||||||
|
if(strpbrk(ip, "*?") != NULL)
|
||||||
|
{
|
||||||
|
return HM_HOST;
|
||||||
|
}
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
if(strchr(ip, ':'))
|
||||||
|
{
|
||||||
|
if((ptr = strchr(ip, '/')))
|
||||||
|
{
|
||||||
|
*ptr = '\0';
|
||||||
|
ptr++;
|
||||||
|
*b = atoi(ptr);
|
||||||
|
if(*b > 128)
|
||||||
|
*b = 128;
|
||||||
|
else if(*b < 0)
|
||||||
|
return HM_HOST;
|
||||||
|
} else
|
||||||
|
*b = 128;
|
||||||
|
if(rb_inet_pton_sock(ip, (struct sockaddr *)addr) > 0)
|
||||||
|
return HM_IPV6;
|
||||||
|
else
|
||||||
|
return HM_HOST;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if(strchr(text, '.'))
|
||||||
|
{
|
||||||
|
if((ptr = strchr(ip, '/')))
|
||||||
|
{
|
||||||
|
*ptr = '\0';
|
||||||
|
ptr++;
|
||||||
|
*b = atoi(ptr);
|
||||||
|
if(*b > 32)
|
||||||
|
*b = 32;
|
||||||
|
else if(*b < 0)
|
||||||
|
return HM_HOST;
|
||||||
|
} else
|
||||||
|
*b = 32;
|
||||||
|
if(rb_inet_pton_sock(ip, (struct sockaddr *)addr) > 0)
|
||||||
|
return HM_IPV4;
|
||||||
|
else
|
||||||
|
return HM_HOST;
|
||||||
|
}
|
||||||
|
return HM_HOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hashtable stuff...now external as its used in m_stats.c */
|
||||||
|
struct AddressRec *atable[ATABLE_SIZE];
|
||||||
|
|
||||||
|
void
|
||||||
|
init_host_hash(void)
|
||||||
|
{
|
||||||
|
memset(&atable, 0, sizeof(atable));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unsigned long hash_ipv4(struct rb_sockaddr_storage*)
|
||||||
|
* Input: An IP address.
|
||||||
|
* Output: A hash value of the IP address.
|
||||||
|
* Side effects: None
|
||||||
|
*/
|
||||||
|
static unsigned long
|
||||||
|
hash_ipv4(struct sockaddr *saddr, int bits)
|
||||||
|
{
|
||||||
|
struct sockaddr_in *addr = (struct sockaddr_in *)(void *)saddr;
|
||||||
|
|
||||||
|
if(bits != 0)
|
||||||
|
{
|
||||||
|
unsigned long av = ntohl(addr->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
|
||||||
|
return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unsigned long hash_ipv6(struct rb_sockaddr_storage*)
|
||||||
|
* Input: An IP address.
|
||||||
|
* Output: A hash value of the IP address.
|
||||||
|
* Side effects: None
|
||||||
|
*/
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
static unsigned long
|
||||||
|
hash_ipv6(struct sockaddr *saddr, int bits)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(void *)saddr;
|
||||||
|
unsigned long v = 0, n;
|
||||||
|
for (n = 0; n < 16; n++)
|
||||||
|
{
|
||||||
|
if(bits >= 8)
|
||||||
|
{
|
||||||
|
v ^= addr->sin6_addr.s6_addr[n];
|
||||||
|
bits -= 8;
|
||||||
|
}
|
||||||
|
else if(bits)
|
||||||
|
{
|
||||||
|
v ^= addr->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
|
||||||
|
return v & (ATABLE_SIZE - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return v & (ATABLE_SIZE - 1);
|
||||||
|
}
|
||||||
|
return v & (ATABLE_SIZE - 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* int hash_text(const char *start)
|
||||||
|
* Input: The start of the text to hash.
|
||||||
|
* Output: The hash of the string between 1 and (TH_MAX-1)
|
||||||
|
* Side-effects: None.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
hash_text(const char *start)
|
||||||
|
{
|
||||||
|
const char *p = start;
|
||||||
|
unsigned long h = 0;
|
||||||
|
|
||||||
|
while(*p)
|
||||||
|
{
|
||||||
|
h = (h << 4) - (h + (unsigned char) ToLower(*p++));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (h & (ATABLE_SIZE - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unsigned long get_hash_mask(const char *)
|
||||||
|
* Input: The text to hash.
|
||||||
|
* Output: The hash of the string right of the first '.' past the last
|
||||||
|
* wildcard in the string.
|
||||||
|
* Side-effects: None.
|
||||||
|
*/
|
||||||
|
static unsigned long
|
||||||
|
get_mask_hash(const char *text)
|
||||||
|
{
|
||||||
|
const char *hp = "", *p;
|
||||||
|
|
||||||
|
for (p = text + strlen(text) - 1; p >= text; p--)
|
||||||
|
if(*p == '*' || *p == '?')
|
||||||
|
return hash_text(hp);
|
||||||
|
else if(*p == '.')
|
||||||
|
hp = p + 1;
|
||||||
|
return hash_text(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* struct ConfItem* find_conf_by_address(const char*, struct rb_sockaddr_storage*,
|
||||||
|
* int type, int fam, const char *username)
|
||||||
|
* Input: The hostname, the address, the type of mask to find, the address
|
||||||
|
* family, the username.
|
||||||
|
* Output: The matching value with the highest precedence.
|
||||||
|
* Side-effects: None
|
||||||
|
* Note: Setting bit 0 of the type means that the username is ignored.
|
||||||
|
*/
|
||||||
|
struct ConfItem *
|
||||||
|
find_conf_by_address(const char *name, const char *sockhost,
|
||||||
|
const char *orighost,
|
||||||
|
struct sockaddr *addr, int type, int fam,
|
||||||
|
const char *username, const char *auth_user)
|
||||||
|
{
|
||||||
|
unsigned long hprecv = 0;
|
||||||
|
struct ConfItem *hprec = NULL;
|
||||||
|
struct AddressRec *arec;
|
||||||
|
int b;
|
||||||
|
|
||||||
|
if(username == NULL)
|
||||||
|
username = "";
|
||||||
|
|
||||||
|
if(addr)
|
||||||
|
{
|
||||||
|
/* Check for IPV6 matches... */
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
if(fam == AF_INET6)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (b = 128; b >= 0; b -= 16)
|
||||||
|
{
|
||||||
|
for (arec = atable[hash_ipv6(addr, b)]; arec; arec = arec->next)
|
||||||
|
if(arec->type == (type & ~0x1) &&
|
||||||
|
arec->masktype == HM_IPV6 &&
|
||||||
|
comp_with_mask_sock(addr, (struct sockaddr *)&arec->Mask.ipa.addr,
|
||||||
|
arec->Mask.ipa.bits) &&
|
||||||
|
(type & 0x1 || match(arec-> username, username)) &&
|
||||||
|
(type != CONF_CLIENT || !arec->auth_user ||
|
||||||
|
(auth_user && match(arec->auth_user, auth_user))) &&
|
||||||
|
arec->precedence > hprecv)
|
||||||
|
{
|
||||||
|
hprecv = arec->precedence;
|
||||||
|
hprec = arec->aconf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if(fam == AF_INET)
|
||||||
|
{
|
||||||
|
for (b = 32; b >= 0; b -= 8)
|
||||||
|
{
|
||||||
|
for (arec = atable[hash_ipv4(addr, b)]; arec; arec = arec->next)
|
||||||
|
if(arec->type == (type & ~0x1) &&
|
||||||
|
arec->masktype == HM_IPV4 &&
|
||||||
|
comp_with_mask_sock(addr, (struct sockaddr *)&arec->Mask.ipa.addr,
|
||||||
|
arec->Mask.ipa.bits) &&
|
||||||
|
(type & 0x1 || match(arec->username, username)) &&
|
||||||
|
(type != CONF_CLIENT || !arec->auth_user ||
|
||||||
|
(auth_user && match(arec->auth_user, auth_user))) &&
|
||||||
|
arec->precedence > hprecv)
|
||||||
|
{
|
||||||
|
hprecv = arec->precedence;
|
||||||
|
hprec = arec->aconf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(orighost != NULL)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
for (p = orighost; p != NULL;)
|
||||||
|
{
|
||||||
|
for (arec = atable[hash_text(p)]; arec; arec = arec->next)
|
||||||
|
|
||||||
|
if((arec->type == (type & ~0x1)) &&
|
||||||
|
(arec->masktype == HM_HOST) &&
|
||||||
|
arec->precedence > hprecv &&
|
||||||
|
match(arec->Mask.hostname, orighost) &&
|
||||||
|
(type != CONF_CLIENT || !arec->auth_user ||
|
||||||
|
(auth_user && match(arec->auth_user, auth_user))) &&
|
||||||
|
(type & 0x1 || match(arec->username, username)))
|
||||||
|
{
|
||||||
|
hprecv = arec->precedence;
|
||||||
|
hprec = arec->aconf;
|
||||||
|
}
|
||||||
|
p = strchr(p, '.');
|
||||||
|
if(p != NULL)
|
||||||
|
p++;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (arec = atable[0]; arec; arec = arec->next)
|
||||||
|
{
|
||||||
|
if(arec->type == (type & ~0x1) &&
|
||||||
|
arec->masktype == HM_HOST &&
|
||||||
|
arec->precedence > hprecv &&
|
||||||
|
(match(arec->Mask.hostname, orighost) ||
|
||||||
|
(sockhost && match(arec->Mask.hostname, sockhost))) &&
|
||||||
|
(type != CONF_CLIENT || !arec->auth_user ||
|
||||||
|
(auth_user && match(arec->auth_user, auth_user))) &&
|
||||||
|
(type & 0x1 || match(arec->username, username)))
|
||||||
|
{
|
||||||
|
hprecv = arec->precedence;
|
||||||
|
hprec = arec->aconf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(name != NULL)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
/* And yes - we have to check p after strchr and p after increment for
|
||||||
|
* NULL -kre */
|
||||||
|
for (p = name; p != NULL;)
|
||||||
|
{
|
||||||
|
for (arec = atable[hash_text(p)]; arec; arec = arec->next)
|
||||||
|
if((arec->type == (type & ~0x1)) &&
|
||||||
|
(arec->masktype == HM_HOST) &&
|
||||||
|
arec->precedence > hprecv &&
|
||||||
|
match(arec->Mask.hostname, name) &&
|
||||||
|
(type != CONF_CLIENT || !arec->auth_user ||
|
||||||
|
(auth_user && match(arec->auth_user, auth_user))) &&
|
||||||
|
(type & 0x1 || match(arec->username, username)))
|
||||||
|
{
|
||||||
|
hprecv = arec->precedence;
|
||||||
|
hprec = arec->aconf;
|
||||||
|
}
|
||||||
|
p = strchr(p, '.');
|
||||||
|
if(p != NULL)
|
||||||
|
p++;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (arec = atable[0]; arec; arec = arec->next)
|
||||||
|
{
|
||||||
|
if(arec->type == (type & ~0x1) &&
|
||||||
|
arec->masktype == HM_HOST &&
|
||||||
|
arec->precedence > hprecv &&
|
||||||
|
(match(arec->Mask.hostname, name) ||
|
||||||
|
(sockhost && match(arec->Mask.hostname, sockhost))) &&
|
||||||
|
(type != CONF_CLIENT || !arec->auth_user ||
|
||||||
|
(auth_user && match(arec->auth_user, auth_user))) &&
|
||||||
|
(type & 0x1 || match(arec->username, username)))
|
||||||
|
{
|
||||||
|
hprecv = arec->precedence;
|
||||||
|
hprec = arec->aconf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hprec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* struct ConfItem* find_address_conf(const char*, const char*,
|
||||||
|
* struct rb_sockaddr_storage*, int);
|
||||||
|
* Input: The hostname, username, address, address family.
|
||||||
|
* Output: The applicable ConfItem.
|
||||||
|
* Side-effects: None
|
||||||
|
*/
|
||||||
|
struct ConfItem *
|
||||||
|
find_address_conf(const char *host, const char *sockhost, const char *user,
|
||||||
|
const char *notildeuser, struct sockaddr *ip, int aftype, char *auth_user)
|
||||||
|
{
|
||||||
|
struct ConfItem *iconf, *kconf;
|
||||||
|
const char *vuser;
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
struct sockaddr_in ip4;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Find the best I-line... If none, return NULL -A1kmm */
|
||||||
|
if(!(iconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_CLIENT, aftype, user, auth_user)))
|
||||||
|
return NULL;
|
||||||
|
/* Find what their visible username will be.
|
||||||
|
* Note that the username without tilde may contain one char more.
|
||||||
|
* -- jilles */
|
||||||
|
vuser = IsNoTilde(iconf) ? notildeuser : user;
|
||||||
|
|
||||||
|
/* If they are exempt from K-lines, return the best I-line. -A1kmm */
|
||||||
|
if(IsConfExemptKline(iconf))
|
||||||
|
return iconf;
|
||||||
|
|
||||||
|
/* Find the best K-line... -A1kmm */
|
||||||
|
kconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_KILL, aftype, user, NULL);
|
||||||
|
|
||||||
|
/* If they are K-lined, return the K-line */
|
||||||
|
if(kconf)
|
||||||
|
return kconf;
|
||||||
|
|
||||||
|
/* if theres a spoof, check it against klines.. */
|
||||||
|
if(IsConfDoSpoofIp(iconf))
|
||||||
|
{
|
||||||
|
char *p = strchr(iconf->info.name, '@');
|
||||||
|
|
||||||
|
/* note, we dont need to pass sockhost here, as its
|
||||||
|
* guaranteed to not match by whats above.. --anfl
|
||||||
|
*/
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
*p = '\0';
|
||||||
|
kconf = find_conf_by_address(p+1, NULL, NULL, ip, CONF_KILL, aftype, iconf->info.name, NULL);
|
||||||
|
*p = '@';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
kconf = find_conf_by_address(iconf->info.name, NULL, NULL, ip, CONF_KILL, aftype, vuser, NULL);
|
||||||
|
|
||||||
|
if(kconf)
|
||||||
|
return kconf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if no_tilde, check the username without tilde against klines too
|
||||||
|
* -- jilles */
|
||||||
|
if(user != vuser)
|
||||||
|
{
|
||||||
|
kconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_KILL, aftype, vuser, NULL);
|
||||||
|
if(kconf)
|
||||||
|
return kconf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
if(ip != NULL && ip->sa_family == AF_INET6 &&
|
||||||
|
ipv4_from_ipv6((const struct sockaddr_in6 *)(const void *)ip, &ip4))
|
||||||
|
{
|
||||||
|
kconf = find_conf_by_address(NULL, NULL, NULL, (struct sockaddr *)&ip4, CONF_KILL, AF_INET, vuser, NULL);
|
||||||
|
if(kconf)
|
||||||
|
return kconf;
|
||||||
|
}
|
||||||
|
#endif /* RB_IPV6 */
|
||||||
|
|
||||||
|
return iconf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* struct ConfItem* find_dline(struct rb_sockaddr_storage*, int)
|
||||||
|
* Input: An address, an address family.
|
||||||
|
* Output: The best matching D-line or exempt line.
|
||||||
|
* Side effects: None.
|
||||||
|
*/
|
||||||
|
struct ConfItem *
|
||||||
|
find_dline(struct sockaddr *addr, int aftype)
|
||||||
|
{
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
struct sockaddr_in addr2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
aconf = find_conf_by_address(NULL, NULL, NULL, addr, CONF_EXEMPTDLINE | 1, aftype, NULL, NULL);
|
||||||
|
if(aconf)
|
||||||
|
return aconf;
|
||||||
|
aconf = find_conf_by_address(NULL, NULL, NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL);
|
||||||
|
if(aconf)
|
||||||
|
return aconf;
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
if(addr->sa_family == AF_INET6 &&
|
||||||
|
ipv4_from_ipv6((const struct sockaddr_in6 *)(const void *)addr, &addr2))
|
||||||
|
{
|
||||||
|
aconf = find_conf_by_address(NULL, NULL, NULL, (struct sockaddr *)&addr2, CONF_DLINE | 1, AF_INET, NULL, NULL);
|
||||||
|
if(aconf)
|
||||||
|
return aconf;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* void find_exact_conf_by_address(const char*, int, const char *)
|
||||||
|
* Input:
|
||||||
|
* Output: ConfItem if found
|
||||||
|
* Side-effects: None
|
||||||
|
*/
|
||||||
|
struct ConfItem *
|
||||||
|
find_exact_conf_by_address(const char *address, int type, const char *username)
|
||||||
|
{
|
||||||
|
int masktype, bits;
|
||||||
|
unsigned long hv;
|
||||||
|
struct AddressRec *arec;
|
||||||
|
struct rb_sockaddr_storage addr;
|
||||||
|
|
||||||
|
if(address == NULL)
|
||||||
|
address = "/NOMATCH!/";
|
||||||
|
masktype = parse_netmask(address, &addr, &bits);
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
if(masktype == HM_IPV6)
|
||||||
|
{
|
||||||
|
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
|
||||||
|
hv = hash_ipv6((struct sockaddr *)&addr, bits - bits % 16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if(masktype == HM_IPV4)
|
||||||
|
{
|
||||||
|
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
|
||||||
|
hv = hash_ipv4((struct sockaddr *)&addr, bits - bits % 8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hv = get_mask_hash(address);
|
||||||
|
}
|
||||||
|
for (arec = atable[hv]; arec; arec = arec->next)
|
||||||
|
{
|
||||||
|
if (arec->type == type &&
|
||||||
|
arec->masktype == masktype &&
|
||||||
|
(arec->username == NULL || username == NULL ? arec->username == username : !irccmp(arec->username, username)))
|
||||||
|
{
|
||||||
|
if (masktype == HM_HOST)
|
||||||
|
{
|
||||||
|
if (!irccmp(arec->Mask.hostname, address))
|
||||||
|
return arec->aconf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (arec->Mask.ipa.bits == bits &&
|
||||||
|
comp_with_mask_sock((struct sockaddr *)&arec->Mask.ipa.addr, (struct sockaddr *)&addr, bits))
|
||||||
|
return arec->aconf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* void add_conf_by_address(const char*, int, const char *,
|
||||||
|
* struct ConfItem *aconf)
|
||||||
|
* Input:
|
||||||
|
* Output: None
|
||||||
|
* Side-effects: Adds this entry to the hash table.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
add_conf_by_address(const char *address, int type, const char *username, const char *auth_user, struct ConfItem *aconf)
|
||||||
|
{
|
||||||
|
static unsigned long prec_value = 0xFFFFFFFF;
|
||||||
|
int bits;
|
||||||
|
unsigned long hv;
|
||||||
|
struct AddressRec *arec;
|
||||||
|
|
||||||
|
if(address == NULL)
|
||||||
|
address = "/NOMATCH!/";
|
||||||
|
arec = rb_malloc(sizeof(struct AddressRec));
|
||||||
|
arec->masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
if(arec->masktype == HM_IPV6)
|
||||||
|
{
|
||||||
|
arec->Mask.ipa.bits = bits;
|
||||||
|
|
||||||
|
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
|
||||||
|
bits -= bits % 16;
|
||||||
|
arec->next = atable[(hv = hash_ipv6((struct sockaddr *)&arec->Mask.ipa.addr, bits))];
|
||||||
|
atable[hv] = arec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if(arec->masktype == HM_IPV4)
|
||||||
|
{
|
||||||
|
arec->Mask.ipa.bits = bits;
|
||||||
|
|
||||||
|
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
|
||||||
|
bits -= bits % 8;
|
||||||
|
arec->next = atable[(hv = hash_ipv4((struct sockaddr *)&arec->Mask.ipa.addr, bits))];
|
||||||
|
atable[hv] = arec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arec->Mask.hostname = address;
|
||||||
|
arec->next = atable[(hv = get_mask_hash(address))];
|
||||||
|
atable[hv] = arec;
|
||||||
|
}
|
||||||
|
arec->username = username;
|
||||||
|
arec->auth_user = auth_user;
|
||||||
|
arec->aconf = aconf;
|
||||||
|
arec->precedence = prec_value--;
|
||||||
|
arec->type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* void delete_one_address(const char*, struct ConfItem*)
|
||||||
|
* Input: An address string, the associated ConfItem.
|
||||||
|
* Output: None
|
||||||
|
* Side effects: Deletes an address record. Frees the ConfItem if there
|
||||||
|
* is nothing referencing it, sets it as illegal otherwise.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
delete_one_address_conf(const char *address, struct ConfItem *aconf)
|
||||||
|
{
|
||||||
|
int masktype, bits;
|
||||||
|
unsigned long hv;
|
||||||
|
struct AddressRec *arec, *arecl = NULL;
|
||||||
|
struct rb_sockaddr_storage addr;
|
||||||
|
masktype = parse_netmask(address, &addr, &bits);
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
if(masktype == HM_IPV6)
|
||||||
|
{
|
||||||
|
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
|
||||||
|
bits -= bits % 16;
|
||||||
|
hv = hash_ipv6((struct sockaddr *)&addr, bits);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if(masktype == HM_IPV4)
|
||||||
|
{
|
||||||
|
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
|
||||||
|
bits -= bits % 8;
|
||||||
|
hv = hash_ipv4((struct sockaddr *)&addr, bits);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hv = get_mask_hash(address);
|
||||||
|
for (arec = atable[hv]; arec; arec = arec->next)
|
||||||
|
{
|
||||||
|
if(arec->aconf == aconf)
|
||||||
|
{
|
||||||
|
if(arecl)
|
||||||
|
arecl->next = arec->next;
|
||||||
|
else
|
||||||
|
atable[hv] = arec->next;
|
||||||
|
aconf->status |= CONF_ILLEGAL;
|
||||||
|
if(!aconf->clients)
|
||||||
|
free_conf(aconf);
|
||||||
|
rb_free(arec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
arecl = arec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* void clear_out_address_conf(void)
|
||||||
|
* Input: None
|
||||||
|
* Output: None
|
||||||
|
* Side effects: Clears out all address records in the hash table,
|
||||||
|
* frees them, and frees the ConfItems if nothing references
|
||||||
|
* them, otherwise sets them as illegal.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clear_out_address_conf(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct AddressRec **store_next;
|
||||||
|
struct AddressRec *arec, *arecn;
|
||||||
|
|
||||||
|
for (i = 0; i < ATABLE_SIZE; i++)
|
||||||
|
{
|
||||||
|
store_next = &atable[i];
|
||||||
|
for (arec = atable[i]; arec; arec = arecn)
|
||||||
|
{
|
||||||
|
arecn = arec->next;
|
||||||
|
/* We keep the temporary K-lines and destroy the
|
||||||
|
* permanent ones, just to be confusing :) -A1kmm */
|
||||||
|
if(arec->aconf->flags & CONF_FLAGS_TEMPORARY ||
|
||||||
|
(arec->type != CONF_CLIENT && arec->type != CONF_EXEMPTDLINE))
|
||||||
|
{
|
||||||
|
*store_next = arec;
|
||||||
|
store_next = &arec->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arec->aconf->status |= CONF_ILLEGAL;
|
||||||
|
if(!arec->aconf->clients)
|
||||||
|
free_conf(arec->aconf);
|
||||||
|
rb_free(arec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*store_next = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clear_out_address_conf_bans(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct AddressRec **store_next;
|
||||||
|
struct AddressRec *arec, *arecn;
|
||||||
|
|
||||||
|
for (i = 0; i < ATABLE_SIZE; i++)
|
||||||
|
{
|
||||||
|
store_next = &atable[i];
|
||||||
|
for (arec = atable[i]; arec; arec = arecn)
|
||||||
|
{
|
||||||
|
arecn = arec->next;
|
||||||
|
/* We keep the temporary K-lines and destroy the
|
||||||
|
* permanent ones, just to be confusing :) -A1kmm */
|
||||||
|
if(arec->aconf->flags & CONF_FLAGS_TEMPORARY ||
|
||||||
|
(arec->type == CONF_CLIENT || arec->type == CONF_EXEMPTDLINE))
|
||||||
|
{
|
||||||
|
*store_next = arec;
|
||||||
|
store_next = &arec->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arec->aconf->status |= CONF_ILLEGAL;
|
||||||
|
if(!arec->aconf->clients)
|
||||||
|
free_conf(arec->aconf);
|
||||||
|
rb_free(arec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*store_next = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* show_iline_prefix()
|
||||||
|
*
|
||||||
|
* inputs - pointer to struct Client requesting output
|
||||||
|
* - pointer to struct ConfItem
|
||||||
|
* - name to which iline prefix will be prefixed to
|
||||||
|
* output - pointer to static string with prefixes listed in ascii form
|
||||||
|
* side effects - NONE
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
show_iline_prefix(struct Client *sptr, struct ConfItem *aconf, char *name)
|
||||||
|
{
|
||||||
|
static char prefix_of_host[USERLEN + 15];
|
||||||
|
char *prefix_ptr;
|
||||||
|
|
||||||
|
prefix_ptr = prefix_of_host;
|
||||||
|
if(IsNoTilde(aconf))
|
||||||
|
*prefix_ptr++ = '-';
|
||||||
|
if(IsNeedIdentd(aconf))
|
||||||
|
*prefix_ptr++ = '+';
|
||||||
|
if(IsConfDoSpoofIp(aconf))
|
||||||
|
*prefix_ptr++ = '=';
|
||||||
|
if(IsOper(sptr) && IsConfExemptFlood(aconf))
|
||||||
|
*prefix_ptr++ = '|';
|
||||||
|
if(IsOper(sptr) && IsConfExemptDNSBL(aconf) && !IsConfExemptKline(aconf))
|
||||||
|
*prefix_ptr++ = '$';
|
||||||
|
if(IsOper(sptr) && IsConfExemptKline(aconf))
|
||||||
|
*prefix_ptr++ = '^';
|
||||||
|
if(IsOper(sptr) && IsConfExemptLimits(aconf))
|
||||||
|
*prefix_ptr++ = '>';
|
||||||
|
*prefix_ptr = '\0';
|
||||||
|
strncpy(prefix_ptr, name, USERLEN);
|
||||||
|
return (prefix_of_host);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* report_auth()
|
||||||
|
*
|
||||||
|
* Inputs: pointer to client to report to
|
||||||
|
* Output: None
|
||||||
|
* Side effects: Reports configured auth{} blocks to client_p
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
report_auth(struct Client *client_p)
|
||||||
|
{
|
||||||
|
char *name, *host, *user, *classname;
|
||||||
|
const char *pass;
|
||||||
|
struct AddressRec *arec;
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
int i, port;
|
||||||
|
|
||||||
|
for (i = 0; i < ATABLE_SIZE; i++)
|
||||||
|
for (arec = atable[i]; arec; arec = arec->next)
|
||||||
|
if(arec->type == CONF_CLIENT)
|
||||||
|
{
|
||||||
|
aconf = arec->aconf;
|
||||||
|
|
||||||
|
if(!IsOper(client_p) && IsConfDoSpoofIp(aconf))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
get_printable_conf(aconf, &name, &host, &pass, &user, &port,
|
||||||
|
&classname);
|
||||||
|
|
||||||
|
if(!EmptyString(aconf->spasswd))
|
||||||
|
pass = aconf->spasswd;
|
||||||
|
|
||||||
|
sendto_one_numeric(client_p, RPL_STATSILINE,
|
||||||
|
form_str(RPL_STATSILINE),
|
||||||
|
name, pass, show_iline_prefix(client_p, aconf, user),
|
||||||
|
show_ip_conf(aconf, client_p) ? host : "255.255.255.255",
|
||||||
|
port, classname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
785
src/ircd.c
Normal file
785
src/ircd.c
Normal file
|
@ -0,0 +1,785 @@
|
||||||
|
/*
|
||||||
|
* charybdis: A slightly useful ircd.
|
||||||
|
* ircd.c: Starts up and runs the ircd.
|
||||||
|
*
|
||||||
|
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||||
|
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||||
|
* Copyright (C) 2002-2008 ircd-ratbox development team
|
||||||
|
* Copyright (C) 2005-2013 charybdis development team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ratbox_lib.h"
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "setup.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "ircd.h"
|
||||||
|
#include "channel.h"
|
||||||
|
#include "class.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "match.h"
|
||||||
|
#include "ircd_signal.h"
|
||||||
|
#include "msg.h" /* msgtab */
|
||||||
|
#include "hostmask.h"
|
||||||
|
#include "numeric.h"
|
||||||
|
#include "parse.h"
|
||||||
|
#include "res.h"
|
||||||
|
#include "restart.h"
|
||||||
|
#include "s_auth.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "s_serv.h" /* try_connections */
|
||||||
|
#include "s_user.h"
|
||||||
|
#include "s_stats.h"
|
||||||
|
#include "scache.h"
|
||||||
|
#include "send.h"
|
||||||
|
#include "supported.h"
|
||||||
|
#include "whowas.h"
|
||||||
|
#include "modules.h"
|
||||||
|
#include "hook.h"
|
||||||
|
#include "ircd_getopt.h"
|
||||||
|
#include "newconf.h"
|
||||||
|
#include "reject.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "s_newconf.h"
|
||||||
|
#include "cache.h"
|
||||||
|
#include "monitor.h"
|
||||||
|
#include "patchlevel.h"
|
||||||
|
#include "serno.h"
|
||||||
|
#include "sslproc.h"
|
||||||
|
#include "chmode.h"
|
||||||
|
#include "privilege.h"
|
||||||
|
#include "bandbi.h"
|
||||||
|
|
||||||
|
/* /quote set variables */
|
||||||
|
struct SetOptions GlobalSetOptions;
|
||||||
|
|
||||||
|
/* configuration set from ircd.conf */
|
||||||
|
struct config_file_entry ConfigFileEntry;
|
||||||
|
/* server info set from ircd.conf */
|
||||||
|
struct server_info ServerInfo;
|
||||||
|
/* admin info set from ircd.conf */
|
||||||
|
struct admin_info AdminInfo;
|
||||||
|
|
||||||
|
struct Counter Count;
|
||||||
|
struct ServerStatistics ServerStats;
|
||||||
|
|
||||||
|
int maxconnections;
|
||||||
|
struct Client me; /* That's me */
|
||||||
|
struct LocalUser meLocalUser; /* That's also part of me */
|
||||||
|
|
||||||
|
rb_dlink_list global_client_list;
|
||||||
|
|
||||||
|
/* unknown/client pointer lists */
|
||||||
|
rb_dlink_list unknown_list; /* unknown clients ON this server only */
|
||||||
|
rb_dlink_list lclient_list; /* local clients only ON this server */
|
||||||
|
rb_dlink_list serv_list; /* local servers to this server ONLY */
|
||||||
|
rb_dlink_list global_serv_list; /* global servers on the network */
|
||||||
|
rb_dlink_list local_oper_list; /* our opers, duplicated in lclient_list */
|
||||||
|
rb_dlink_list oper_list; /* network opers */
|
||||||
|
|
||||||
|
const char *logFileName = LPATH;
|
||||||
|
const char *pidFileName = PPATH;
|
||||||
|
|
||||||
|
char **myargv;
|
||||||
|
int dorehash = 0;
|
||||||
|
int dorehashbans = 0;
|
||||||
|
int doremotd = 0;
|
||||||
|
int kline_queued = 0;
|
||||||
|
int server_state_foreground = 0;
|
||||||
|
int opers_see_all_users = 0;
|
||||||
|
int ircd_ssl_ok = 0;
|
||||||
|
int ircd_zlib_ok = 1;
|
||||||
|
|
||||||
|
int testing_conf = 0;
|
||||||
|
time_t startup_time;
|
||||||
|
|
||||||
|
int default_server_capabs;
|
||||||
|
|
||||||
|
int splitmode;
|
||||||
|
int splitchecking;
|
||||||
|
int split_users;
|
||||||
|
int split_servers;
|
||||||
|
int eob_count;
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd_shutdown(const char *reason)
|
||||||
|
{
|
||||||
|
struct Client *target_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, lclient_list.head)
|
||||||
|
{
|
||||||
|
target_p = ptr->data;
|
||||||
|
|
||||||
|
sendto_one(target_p, ":%s NOTICE %s :Server Terminating. %s",
|
||||||
|
me.name, target_p->name, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, serv_list.head)
|
||||||
|
{
|
||||||
|
target_p = ptr->data;
|
||||||
|
|
||||||
|
sendto_one(target_p, ":%s ERROR :Terminated by %s",
|
||||||
|
me.name, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
ilog(L_MAIN, "Server Terminating. %s", reason);
|
||||||
|
close_logfiles();
|
||||||
|
|
||||||
|
unlink(pidFileName);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_sys
|
||||||
|
*
|
||||||
|
* inputs - boot_daemon flag
|
||||||
|
* output - none
|
||||||
|
* side effects - if boot_daemon flag is not set, don't daemonize
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
init_sys(void)
|
||||||
|
{
|
||||||
|
#if defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)
|
||||||
|
struct rlimit limit;
|
||||||
|
|
||||||
|
if(!getrlimit(RLIMIT_NOFILE, &limit))
|
||||||
|
{
|
||||||
|
maxconnections = limit.rlim_cur;
|
||||||
|
if(maxconnections <= MAX_BUFFER)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Shell FD limits are too low.\n");
|
||||||
|
fprintf(stderr, "ERROR: charybdis reserves %d FDs, shell limits must be above this\n", MAX_BUFFER);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* RLIMIT_FD_MAX */
|
||||||
|
maxconnections = MAXCONNECTIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rehash_ulimit(void)
|
||||||
|
{
|
||||||
|
#if defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)
|
||||||
|
struct rlimit limit;
|
||||||
|
|
||||||
|
if(!getrlimit(RLIMIT_NOFILE, &limit) && limit.rlim_cur != maxconnections)
|
||||||
|
{
|
||||||
|
if(limit.rlim_cur <= MAX_BUFFER)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Shell FD limits are too low.\n");
|
||||||
|
fprintf(stderr, "ERROR: charybdis reserves %d FDs, shell limits must be above this\n", MAX_BUFFER);
|
||||||
|
fprintf(stderr, "ERROR: keeping old limits\n");
|
||||||
|
return;
|
||||||
|
} else if(limit.rlim_cur < maxconnections)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: ulimit decreased\n");
|
||||||
|
fprintf(stderr, "ERROR: keeping old limits\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
maxconnections = limit.rlim_cur;
|
||||||
|
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Setting maxconnections to %d", maxconnections);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* RLIMIT_FD_MAX */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
make_daemon(void)
|
||||||
|
{
|
||||||
|
int pid, nullfd, fdx;
|
||||||
|
|
||||||
|
/* The below is approximately what daemon(1, 0) does, but
|
||||||
|
we need control over the parent after forking to print
|
||||||
|
the startup message -- Aaron */
|
||||||
|
|
||||||
|
if((nullfd = open("/dev/null", O_RDWR)) < 0)
|
||||||
|
{
|
||||||
|
perror("open /dev/null");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((pid = fork()) < 0)
|
||||||
|
{
|
||||||
|
perror("fork");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
else if(pid > 0)
|
||||||
|
{
|
||||||
|
inotice("now running in background mode from %s as pid %d ...",
|
||||||
|
ConfigFileEntry.dpath, pid);
|
||||||
|
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(fdx = 0; fdx <= 2; fdx++)
|
||||||
|
if (fdx != nullfd)
|
||||||
|
(void) dup2(nullfd, fdx);
|
||||||
|
|
||||||
|
if(nullfd > 2)
|
||||||
|
(void) close(nullfd);
|
||||||
|
|
||||||
|
(void) setsid();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int printVersion = 0;
|
||||||
|
|
||||||
|
struct lgetopt myopts[] = {
|
||||||
|
{"configfile", &ConfigFileEntry.configfile,
|
||||||
|
STRING, "File to use for ircd.conf"},
|
||||||
|
{"logfile", &logFileName,
|
||||||
|
STRING, "File to use for ircd.log"},
|
||||||
|
{"pidfile", &pidFileName,
|
||||||
|
STRING, "File to use for process ID"},
|
||||||
|
{"foreground", &server_state_foreground,
|
||||||
|
YESNO, "Run in foreground (don't detach)"},
|
||||||
|
{"version", &printVersion,
|
||||||
|
YESNO, "Print version and exit"},
|
||||||
|
{"conftest", &testing_conf,
|
||||||
|
YESNO, "Test the configuration files and exit"},
|
||||||
|
{"help", NULL, USAGE, "Print this text"},
|
||||||
|
{NULL, NULL, STRING, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_rehash(void *unused)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Check to see whether we have to rehash the configuration ..
|
||||||
|
*/
|
||||||
|
if(dorehash)
|
||||||
|
{
|
||||||
|
rehash(1);
|
||||||
|
rehash_ulimit();
|
||||||
|
dorehash = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dorehashbans)
|
||||||
|
{
|
||||||
|
rehash_bans(1);
|
||||||
|
dorehashbans = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(doremotd)
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Got signal SIGUSR1, reloading ircd motd file");
|
||||||
|
cache_user_motd();
|
||||||
|
doremotd = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initalialize_global_set_options
|
||||||
|
*
|
||||||
|
* inputs - none
|
||||||
|
* output - none
|
||||||
|
* side effects - This sets all global set options needed
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
initialize_global_set_options(void)
|
||||||
|
{
|
||||||
|
memset(&GlobalSetOptions, 0, sizeof(GlobalSetOptions));
|
||||||
|
/* memset( &ConfigFileEntry, 0, sizeof(ConfigFileEntry)); */
|
||||||
|
|
||||||
|
GlobalSetOptions.maxclients = ServerInfo.default_max_clients;
|
||||||
|
|
||||||
|
if(GlobalSetOptions.maxclients > (maxconnections - MAX_BUFFER) || (GlobalSetOptions.maxclients <= 0))
|
||||||
|
GlobalSetOptions.maxclients = maxconnections - MAX_BUFFER;
|
||||||
|
|
||||||
|
GlobalSetOptions.autoconn = 1;
|
||||||
|
|
||||||
|
GlobalSetOptions.spam_time = MIN_JOIN_LEAVE_TIME;
|
||||||
|
GlobalSetOptions.spam_num = MAX_JOIN_LEAVE_COUNT;
|
||||||
|
|
||||||
|
GlobalSetOptions.floodcount = ConfigFileEntry.default_floodcount;
|
||||||
|
|
||||||
|
split_servers = ConfigChannel.default_split_server_count;
|
||||||
|
split_users = ConfigChannel.default_split_user_count;
|
||||||
|
|
||||||
|
if(split_users && split_servers
|
||||||
|
&& (ConfigChannel.no_create_on_split || ConfigChannel.no_join_on_split))
|
||||||
|
{
|
||||||
|
splitmode = 1;
|
||||||
|
splitchecking = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalSetOptions.ident_timeout = ConfigFileEntry.default_ident_timeout;
|
||||||
|
|
||||||
|
rb_strlcpy(GlobalSetOptions.operstring,
|
||||||
|
ConfigFileEntry.default_operstring,
|
||||||
|
sizeof(GlobalSetOptions.operstring));
|
||||||
|
rb_strlcpy(GlobalSetOptions.adminstring,
|
||||||
|
ConfigFileEntry.default_adminstring,
|
||||||
|
sizeof(GlobalSetOptions.adminstring));
|
||||||
|
|
||||||
|
/* memset( &ConfigChannel, 0, sizeof(ConfigChannel)); */
|
||||||
|
|
||||||
|
/* End of global set options */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initialize_server_capabs
|
||||||
|
*
|
||||||
|
* inputs - none
|
||||||
|
* output - none
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
initialize_server_capabs(void)
|
||||||
|
{
|
||||||
|
default_server_capabs &= ~CAP_ZIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* write_pidfile
|
||||||
|
*
|
||||||
|
* inputs - filename+path of pid file
|
||||||
|
* output - none
|
||||||
|
* side effects - write the pid of the ircd to filename
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
write_pidfile(const char *filename)
|
||||||
|
{
|
||||||
|
FILE *fb;
|
||||||
|
char buff[32];
|
||||||
|
if((fb = fopen(filename, "w")))
|
||||||
|
{
|
||||||
|
unsigned int pid = (unsigned int) getpid();
|
||||||
|
|
||||||
|
rb_snprintf(buff, sizeof(buff), "%u\n", pid);
|
||||||
|
if((fputs(buff, fb) == -1))
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "Error writing %u to pid file %s (%s)",
|
||||||
|
pid, filename, strerror(errno));
|
||||||
|
}
|
||||||
|
fclose(fb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "Error opening pid file %s", filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check_pidfile
|
||||||
|
*
|
||||||
|
* inputs - filename+path of pid file
|
||||||
|
* output - none
|
||||||
|
* side effects - reads pid from pidfile and checks if ircd is in process
|
||||||
|
* list. if it is, gracefully exits
|
||||||
|
* -kre
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
check_pidfile(const char *filename)
|
||||||
|
{
|
||||||
|
FILE *fb;
|
||||||
|
char buff[32];
|
||||||
|
pid_t pidfromfile;
|
||||||
|
|
||||||
|
/* Don't do logging here, since we don't have log() initialised */
|
||||||
|
if((fb = fopen(filename, "r")))
|
||||||
|
{
|
||||||
|
if(fgets(buff, 20, fb) != NULL)
|
||||||
|
{
|
||||||
|
pidfromfile = atoi(buff);
|
||||||
|
if(!kill(pidfromfile, 0))
|
||||||
|
{
|
||||||
|
printf("ircd: daemon is already running\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setup_corefile
|
||||||
|
*
|
||||||
|
* inputs - nothing
|
||||||
|
* output - nothing
|
||||||
|
* side effects - setups corefile to system limits.
|
||||||
|
* -kre
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
setup_corefile(void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_SYS_RESOURCE_H
|
||||||
|
struct rlimit rlim; /* resource limits */
|
||||||
|
|
||||||
|
/* Set corefilesize to maximum */
|
||||||
|
if(!getrlimit(RLIMIT_CORE, &rlim))
|
||||||
|
{
|
||||||
|
rlim.rlim_cur = rlim.rlim_max;
|
||||||
|
setrlimit(RLIMIT_CORE, &rlim);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ircd_log_cb(const char *str)
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "libratbox reports: %s", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((noreturn))
|
||||||
|
ircd_restart_cb(const char *str)
|
||||||
|
{
|
||||||
|
inotice("libratbox has called the restart callback: %s", str);
|
||||||
|
restart(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Why EXIT_FAILURE here?
|
||||||
|
* Because if ircd_die_cb() is called it's because of a fatal
|
||||||
|
* error inside libcharybdis, and we don't know how to handle the
|
||||||
|
* exception, so it is logical to return a FAILURE exit code here.
|
||||||
|
* --nenolod
|
||||||
|
*/
|
||||||
|
static void __attribute__((noreturn))
|
||||||
|
ircd_die_cb(const char *str)
|
||||||
|
{
|
||||||
|
if(str != NULL)
|
||||||
|
{
|
||||||
|
/* Try to get the message out to currently logged in operators. */
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "libratbox has called the die callback..aborting: %s", str);
|
||||||
|
inotice("libratbox has called the die callback..aborting: %s", str);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
inotice("libratbox has called the die callback..aborting");
|
||||||
|
|
||||||
|
unlink(pidFileName);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ev_entry *check_splitmode_ev = NULL;
|
||||||
|
|
||||||
|
static int
|
||||||
|
seed_with_urandom(void)
|
||||||
|
{
|
||||||
|
unsigned int seed;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open("/dev/urandom", O_RDONLY);
|
||||||
|
if(fd >= 0)
|
||||||
|
{
|
||||||
|
if(read(fd, &seed, sizeof(seed)) == sizeof(seed))
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
srand(seed);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
seed_with_clock(void)
|
||||||
|
{
|
||||||
|
const struct timeval *tv;
|
||||||
|
rb_set_time();
|
||||||
|
tv = rb_current_time_tv();
|
||||||
|
srand(tv->tv_sec ^ (tv->tv_usec | (getpid() << 20)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
seed_random(void *unused)
|
||||||
|
{
|
||||||
|
unsigned int seed;
|
||||||
|
if(rb_get_random(&seed, sizeof(seed)) == -1)
|
||||||
|
{
|
||||||
|
if(!seed_with_urandom())
|
||||||
|
seed_with_clock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
srand(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* main
|
||||||
|
*
|
||||||
|
* Initializes the IRCd.
|
||||||
|
*
|
||||||
|
* Inputs - number of commandline args, args themselves
|
||||||
|
* Outputs - none
|
||||||
|
* Side Effects - this is where the ircd gets going right now
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct vhost_conf *vhost_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
rb_dlink_node *next_ptr;
|
||||||
|
|
||||||
|
/* Check to see if the user is running us as root, which is a nono */
|
||||||
|
if(geteuid() == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Don't run ircd as root!!!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_sys();
|
||||||
|
|
||||||
|
ConfigFileEntry.dpath = DPATH;
|
||||||
|
ConfigFileEntry.configfile = CPATH; /* Server configuration file */
|
||||||
|
ConfigFileEntry.connect_timeout = 30; /* Default to 30 */
|
||||||
|
|
||||||
|
umask(077); /* better safe than sorry --SRB */
|
||||||
|
|
||||||
|
myargv = argv;
|
||||||
|
parseargs(&argc, &argv, myopts);
|
||||||
|
|
||||||
|
if(chdir(ConfigFileEntry.dpath))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unable to chdir to %s: %s\n", ConfigFileEntry.dpath, strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_set_time();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup corefile size immediately after boot -kre
|
||||||
|
*/
|
||||||
|
setup_corefile();
|
||||||
|
|
||||||
|
memset(&me, 0, sizeof(me));
|
||||||
|
memset(&meLocalUser, 0, sizeof(meLocalUser));
|
||||||
|
me.localClient = &meLocalUser;
|
||||||
|
|
||||||
|
/* Make sure all lists are zeroed */
|
||||||
|
memset(&unknown_list, 0, sizeof(unknown_list));
|
||||||
|
memset(&lclient_list, 0, sizeof(lclient_list));
|
||||||
|
memset(&serv_list, 0, sizeof(serv_list));
|
||||||
|
memset(&global_serv_list, 0, sizeof(global_serv_list));
|
||||||
|
memset(&local_oper_list, 0, sizeof(local_oper_list));
|
||||||
|
memset(&oper_list, 0, sizeof(oper_list));
|
||||||
|
|
||||||
|
rb_dlinkAddTail(&me, &me.node, &global_client_list);
|
||||||
|
|
||||||
|
memset(&Count, 0, sizeof(Count));
|
||||||
|
memset(&ServerInfo, 0, sizeof(ServerInfo));
|
||||||
|
memset(&AdminInfo, 0, sizeof(AdminInfo));
|
||||||
|
memset(&ServerStats, 0, sizeof(struct ServerStatistics));
|
||||||
|
|
||||||
|
if(printVersion)
|
||||||
|
{
|
||||||
|
printf("ircd: version %s(%s)\n", ircd_version, serno);
|
||||||
|
#ifdef CUSTOM_BRANDING
|
||||||
|
printf("ircd: based on %s-%s\n", PACKAGE_NAME, PACKAGE_VERSION);
|
||||||
|
#endif
|
||||||
|
printf("ircd: %s\n", rb_lib_version());
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_signals();
|
||||||
|
|
||||||
|
if (testing_conf)
|
||||||
|
server_state_foreground = 1;
|
||||||
|
|
||||||
|
/* Make sure fd 0, 1 and 2 are in use -- jilles */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
fd = open("/dev/null", O_RDWR);
|
||||||
|
} while (fd < 2 && fd != -1);
|
||||||
|
if (fd > 2)
|
||||||
|
close(fd);
|
||||||
|
else if (fd == -1)
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
/* Check if there is pidfile and daemon already running */
|
||||||
|
if(!testing_conf)
|
||||||
|
{
|
||||||
|
check_pidfile(pidFileName);
|
||||||
|
|
||||||
|
inotice("starting %s ...", ircd_version);
|
||||||
|
inotice("%s", rb_lib_version());
|
||||||
|
|
||||||
|
if(!server_state_foreground)
|
||||||
|
make_daemon();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init the event subsystem */
|
||||||
|
rb_lib_init(ircd_log_cb, ircd_restart_cb, ircd_die_cb, !server_state_foreground, maxconnections, DNODE_HEAP_SIZE, FD_HEAP_SIZE);
|
||||||
|
rb_linebuf_init(LINEBUF_HEAP_SIZE);
|
||||||
|
|
||||||
|
rb_init_prng(NULL, RB_PRNG_DEFAULT);
|
||||||
|
|
||||||
|
seed_random(NULL);
|
||||||
|
|
||||||
|
init_builtin_capabs();
|
||||||
|
default_server_capabs = CAP_MASK;
|
||||||
|
|
||||||
|
init_main_logfile();
|
||||||
|
newconf_init();
|
||||||
|
init_s_conf();
|
||||||
|
init_s_newconf();
|
||||||
|
init_hash();
|
||||||
|
clear_scache_hash_table(); /* server cache name table */
|
||||||
|
init_host_hash();
|
||||||
|
clear_hash_parse();
|
||||||
|
init_client();
|
||||||
|
init_hook();
|
||||||
|
init_channels();
|
||||||
|
initclass();
|
||||||
|
initwhowas();
|
||||||
|
init_reject();
|
||||||
|
init_cache();
|
||||||
|
init_monitor();
|
||||||
|
|
||||||
|
construct_cflags_strings();
|
||||||
|
|
||||||
|
load_all_modules(1);
|
||||||
|
#ifndef STATIC_MODULES
|
||||||
|
load_core_modules(1);
|
||||||
|
#endif
|
||||||
|
init_auth(); /* Initialise the auth code */
|
||||||
|
init_resolver(); /* Needs to be setup before the io loop */
|
||||||
|
privilegeset_set_new("default", "", 0);
|
||||||
|
|
||||||
|
if (testing_conf)
|
||||||
|
fprintf(stderr, "\nBeginning config test\n");
|
||||||
|
read_conf_files(YES); /* cold start init conf files */
|
||||||
|
#ifndef STATIC_MODULES
|
||||||
|
|
||||||
|
mod_add_path(MODULE_DIR);
|
||||||
|
mod_add_path(MODULE_DIR "/autoload");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
init_isupport();
|
||||||
|
|
||||||
|
init_bandb();
|
||||||
|
init_ssld();
|
||||||
|
|
||||||
|
rehash_bans(0);
|
||||||
|
|
||||||
|
initialize_server_capabs(); /* Set up default_server_capabs */
|
||||||
|
initialize_global_set_options();
|
||||||
|
|
||||||
|
if(ServerInfo.name == NULL)
|
||||||
|
{
|
||||||
|
ierror("no server name specified in serverinfo block.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rb_strlcpy(me.name, ServerInfo.name, sizeof(me.name));
|
||||||
|
|
||||||
|
if(ServerInfo.sid[0] == '\0')
|
||||||
|
{
|
||||||
|
ierror("no server sid specified in serverinfo block.");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
strcpy(me.id, ServerInfo.sid);
|
||||||
|
init_uid();
|
||||||
|
|
||||||
|
/* serverinfo{} description must exist. If not, error out. */
|
||||||
|
if(ServerInfo.description == NULL)
|
||||||
|
{
|
||||||
|
ierror("no server description specified in serverinfo block.");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
rb_strlcpy(me.info, ServerInfo.description, sizeof(me.info));
|
||||||
|
|
||||||
|
if(ServerInfo.ssl_cert != NULL && ServerInfo.ssl_private_key != NULL)
|
||||||
|
{
|
||||||
|
if(ServerInfo.ssl_cipher_list == NULL)
|
||||||
|
{
|
||||||
|
ierror("no ssl cipher list specified in serverinfo block.");
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* just do the rb_setup_ssl_server to validate the config */
|
||||||
|
if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list, NULL))
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "WARNING: Unable to setup SSL.");
|
||||||
|
ircd_ssl_ok = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ircd_ssl_ok = 1;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, vhost_conf_list.head)
|
||||||
|
{
|
||||||
|
vhost_p = ptr->data;
|
||||||
|
ilog(L_MAIN, "WARNING: h:%s c:%s k:%s d:%s ci:%s", vhost_p->hostname, vhost_p->ssl_cert, vhost_p->ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list);
|
||||||
|
if(rb_setup_ssl_server(vhost_p->ssl_cert, vhost_p->ssl_private_key,
|
||||||
|
vhost_p->ssl_dh_params ? vhost_p->ssl_dh_params : ServerInfo.ssl_dh_params,
|
||||||
|
vhost_p->ssl_cipher_list ? vhost_p->ssl_cipher_list : ServerInfo.ssl_cipher_list, vhost_p->hostname))
|
||||||
|
{
|
||||||
|
ircd_ssl_ok = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testing_conf)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "\nConfig testing complete.\n");
|
||||||
|
fflush(stderr);
|
||||||
|
return 0; /* Why? We want the launcher to exit out. */
|
||||||
|
}
|
||||||
|
|
||||||
|
me.from = &me;
|
||||||
|
me.servptr = &me;
|
||||||
|
SetMe(&me);
|
||||||
|
make_server(&me);
|
||||||
|
startup_time = rb_current_time();
|
||||||
|
add_to_client_hash(me.name, &me);
|
||||||
|
add_to_id_hash(me.id, &me);
|
||||||
|
me.serv->nameinfo = scache_connect(me.name, me.info, 0);
|
||||||
|
|
||||||
|
rb_dlinkAddAlloc(&me, &global_serv_list);
|
||||||
|
|
||||||
|
construct_umodebuf();
|
||||||
|
|
||||||
|
check_class();
|
||||||
|
write_pidfile(pidFileName);
|
||||||
|
load_help();
|
||||||
|
open_logfiles();
|
||||||
|
|
||||||
|
ilog(L_MAIN, "Server Ready");
|
||||||
|
|
||||||
|
/* We want try_connections to be called as soon as possible now! -- adrian */
|
||||||
|
/* No, 'cause after a restart it would cause all sorts of nick collides */
|
||||||
|
/* um. by waiting even longer, that just means we have even *more*
|
||||||
|
* nick collisions. what a stupid idea. set an event for the IO loop --fl
|
||||||
|
*/
|
||||||
|
rb_event_addish("try_connections", try_connections, NULL, STARTUP_CONNECTIONS_TIME);
|
||||||
|
rb_event_addonce("try_connections_startup", try_connections, NULL, 2);
|
||||||
|
rb_event_add("check_rehash", check_rehash, NULL, 3);
|
||||||
|
rb_event_addish("reseed_srand", seed_random, NULL, 300); /* reseed every 10 minutes */
|
||||||
|
|
||||||
|
if(splitmode)
|
||||||
|
check_splitmode_ev = rb_event_add("check_splitmode", check_splitmode, NULL, 5);
|
||||||
|
|
||||||
|
if(server_state_foreground)
|
||||||
|
inotice("now running in foreground mode from %s as pid %d ...",
|
||||||
|
ConfigFileEntry.dpath, getpid());
|
||||||
|
|
||||||
|
rb_lib_loop(0);
|
||||||
|
/* UNREACHABLE */
|
||||||
|
}
|
260
src/ircd_lexer.l
Normal file
260
src/ircd_lexer.l
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
/* src/ircd_lexer.l
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: ircd_lexer.l 3540 2007-07-30 17:26:00Z jilles $
|
||||||
|
*/
|
||||||
|
|
||||||
|
%option case-insensitive
|
||||||
|
%option noyywrap
|
||||||
|
%option nounput
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#define WE_ARE_MEMORY_C
|
||||||
|
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "ircd_defs.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "newconf.h"
|
||||||
|
|
||||||
|
#include "y.tab.h"
|
||||||
|
|
||||||
|
int yylex(void);
|
||||||
|
|
||||||
|
#define MAX_INCLUDE_DEPTH 10
|
||||||
|
|
||||||
|
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
|
||||||
|
int include_stack_ptr=0;
|
||||||
|
int lineno = 1;
|
||||||
|
void ccomment(void);
|
||||||
|
void cinclude(void);
|
||||||
|
void hashcomment(void);
|
||||||
|
int ieof(void);
|
||||||
|
int lineno_stack[MAX_INCLUDE_DEPTH];
|
||||||
|
char conffile_stack[MAX_INCLUDE_DEPTH][IRCD_BUFSIZE];
|
||||||
|
char conffilebuf[IRCD_BUFSIZE+1];
|
||||||
|
char *current_file = conffilebuf;
|
||||||
|
|
||||||
|
FILE *inc_fbfile_in[MAX_INCLUDE_DEPTH];
|
||||||
|
|
||||||
|
char yy_linebuf[16384];
|
||||||
|
|
||||||
|
#undef YY_INPUT
|
||||||
|
|
||||||
|
#define YY_FATAL_ERROR(msg) conf_yy_fatal_error(msg)
|
||||||
|
|
||||||
|
#define YY_INPUT(buf,result,max_size) \
|
||||||
|
if (!(result = conf_fgets(buf, max_size, conf_fbfile_in))) \
|
||||||
|
YY_FATAL_ERROR("input in flex scanner failed");
|
||||||
|
%}
|
||||||
|
|
||||||
|
ws [ \t]*
|
||||||
|
digit [0-9]
|
||||||
|
comment #.*
|
||||||
|
qstring \"[^\"\n]*[\"\n]
|
||||||
|
string [a-zA-Z_\~\:][a-zA-Z0-9_\:]*
|
||||||
|
include \.include{ws}(\<.*\>|\".*\")
|
||||||
|
|
||||||
|
%%
|
||||||
|
{include} { cinclude(); }
|
||||||
|
"/*" { ccomment(); }
|
||||||
|
\n.* { rb_strlcpy(yy_linebuf, yytext+1, sizeof(yy_linebuf)); lineno++; yyless(1); }
|
||||||
|
|
||||||
|
{ws} ;
|
||||||
|
{comment} { hashcomment(); }
|
||||||
|
|
||||||
|
{digit}+ { yylval.number = atoi(yytext); return NUMBER; }
|
||||||
|
|
||||||
|
{qstring} {
|
||||||
|
if(yytext[yyleng-2] == '\\')
|
||||||
|
{
|
||||||
|
yyless(yyleng-1); /* return last quote */
|
||||||
|
yymore(); /* append next string */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rb_strlcpy(yylval.string, yytext + 1, 1024);
|
||||||
|
if(yylval.string[yyleng-2] != '"')
|
||||||
|
ilog(L_MAIN, "Unterminated character string");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i,j;
|
||||||
|
yylval.string[yyleng-2] = '\0'; /* remove close
|
||||||
|
* quote
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (j=i=0 ;yylval.string[i] != '\0'; i++,j++)
|
||||||
|
{
|
||||||
|
if (yylval.string[i] != '\\')
|
||||||
|
{
|
||||||
|
yylval.string[j] = yylval.string[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if (yylval.string[i] == '\0') /* XXX
|
||||||
|
* should not
|
||||||
|
* happen
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
ilog(L_MAIN,
|
||||||
|
"Unterminated character string");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
yylval.string[j] = yylval.string[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yylval.string[j] = '\0';
|
||||||
|
return QSTRING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
loadmodule { return LOADMODULE; }
|
||||||
|
{string} {
|
||||||
|
rb_strlcpy(yylval.string, yytext, 1024);
|
||||||
|
yylval.string[yyleng] = '\0';
|
||||||
|
return STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
\.\. { return TWODOTS; }
|
||||||
|
. { return yytext[0]; }
|
||||||
|
<<EOF>> { if (ieof()) yyterminate(); }
|
||||||
|
%%
|
||||||
|
|
||||||
|
/* C-comment ignoring routine -kre*/
|
||||||
|
void ccomment()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
/* log(L_NOTICE, "got comment"); */
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
while ((c = input()) != '*' && c != EOF)
|
||||||
|
if (c == '\n') ++lineno;
|
||||||
|
if (c == '*')
|
||||||
|
{
|
||||||
|
while ((c = input()) == '*');
|
||||||
|
if (c == '/')
|
||||||
|
break;
|
||||||
|
if (c == '\n') ++lineno;
|
||||||
|
}
|
||||||
|
if (c == EOF)
|
||||||
|
{
|
||||||
|
YY_FATAL_ERROR("EOF in comment");
|
||||||
|
/* XXX hack alert this disables
|
||||||
|
* the stupid unused function warning
|
||||||
|
* gcc generates
|
||||||
|
*/
|
||||||
|
yy_fatal_error("EOF in comment");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cinclude(void)
|
||||||
|
{
|
||||||
|
char *c;
|
||||||
|
if ((c = strchr(yytext, '<')) == NULL)
|
||||||
|
*strchr(c = strchr(yytext, '"') + 1, '"') = 0;
|
||||||
|
else
|
||||||
|
*strchr(++c, '>') = 0;
|
||||||
|
|
||||||
|
/* do stacking and co. */
|
||||||
|
if (include_stack_ptr >= MAX_INCLUDE_DEPTH)
|
||||||
|
conf_report_error("Includes nested too deep (max is %d)", MAX_INCLUDE_DEPTH);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FILE *tmp_fbfile_in;
|
||||||
|
|
||||||
|
tmp_fbfile_in = fopen(c, "r");
|
||||||
|
|
||||||
|
if (tmp_fbfile_in == NULL)
|
||||||
|
{
|
||||||
|
/* if its not found in PREFIX, look in ETCPATH */
|
||||||
|
char fnamebuf[IRCD_BUFSIZE];
|
||||||
|
|
||||||
|
snprintf(fnamebuf, sizeof(fnamebuf), "%s/%s", ETCPATH, c);
|
||||||
|
tmp_fbfile_in = fopen(fnamebuf, "r");
|
||||||
|
|
||||||
|
/* wasnt found there either.. error. */
|
||||||
|
if(tmp_fbfile_in == NULL)
|
||||||
|
{
|
||||||
|
conf_report_error("Include %s: %s.", c, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lineno_stack[include_stack_ptr] = lineno;
|
||||||
|
lineno = 1;
|
||||||
|
inc_fbfile_in[include_stack_ptr] = conf_fbfile_in;
|
||||||
|
strcpy(conffile_stack[include_stack_ptr], c);
|
||||||
|
current_file = conffile_stack[include_stack_ptr];
|
||||||
|
include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
|
||||||
|
conf_fbfile_in = tmp_fbfile_in;
|
||||||
|
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ieof(void)
|
||||||
|
{
|
||||||
|
if (include_stack_ptr)
|
||||||
|
fclose(conf_fbfile_in);
|
||||||
|
if (--include_stack_ptr < 0)
|
||||||
|
{
|
||||||
|
/* We will now exit the lexer - restore init values if we get /rehash
|
||||||
|
* later and reenter lexer -kre */
|
||||||
|
include_stack_ptr = 0;
|
||||||
|
lineno = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* switch buffer */
|
||||||
|
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||||
|
lineno = lineno_stack[include_stack_ptr];
|
||||||
|
conf_fbfile_in = inc_fbfile_in[include_stack_ptr];
|
||||||
|
|
||||||
|
if(include_stack_ptr)
|
||||||
|
current_file = conffile_stack[include_stack_ptr];
|
||||||
|
else
|
||||||
|
current_file = conffilebuf;
|
||||||
|
|
||||||
|
yy_switch_to_buffer(include_stack[include_stack_ptr]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #-comment style, look for #include */
|
||||||
|
#define INCLUDE "#include"
|
||||||
|
|
||||||
|
void hashcomment(void)
|
||||||
|
{
|
||||||
|
if (strlen(yytext) < sizeof(INCLUDE) - 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!strncasecmp(yytext, INCLUDE, sizeof(INCLUDE) - 1))
|
||||||
|
yyerror("You probably meant '.include', skipping");
|
||||||
|
}
|
333
src/ircd_parser.y
Normal file
333
src/ircd_parser.y
Normal file
|
@ -0,0 +1,333 @@
|
||||||
|
/* This code is in the public domain.
|
||||||
|
* $Nightmare: nightmare/src/main/parser.y,v 1.2.2.1.2.1 2002/07/02 03:42:10 ejb Exp $
|
||||||
|
* $Id: ircd_parser.y 871 2006-02-18 21:56:00Z nenolod $
|
||||||
|
*/
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#define WE_ARE_MEMORY_C
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "setup.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "ircd_defs.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "modules.h"
|
||||||
|
#include "newconf.h"
|
||||||
|
|
||||||
|
#define YY_NO_UNPUT
|
||||||
|
|
||||||
|
int yyparse(void);
|
||||||
|
void yyerror(const char *);
|
||||||
|
int yylex(void);
|
||||||
|
|
||||||
|
static time_t conf_find_time(char*);
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
const char * name;
|
||||||
|
const char * plural;
|
||||||
|
time_t val;
|
||||||
|
} ircd_times[] = {
|
||||||
|
{"second", "seconds", 1},
|
||||||
|
{"minute", "minutes", 60},
|
||||||
|
{"hour", "hours", 60 * 60},
|
||||||
|
{"day", "days", 60 * 60 * 24},
|
||||||
|
{"week", "weeks", 60 * 60 * 24 * 7},
|
||||||
|
{"fortnight", "fortnights", 60 * 60 * 24 * 14},
|
||||||
|
{"month", "months", 60 * 60 * 24 * 7 * 4},
|
||||||
|
{"year", "years", 60 * 60 * 24 * 365},
|
||||||
|
/* ok-- we now do sizes here too. they aren't times, but
|
||||||
|
it's close enough */
|
||||||
|
{"byte", "bytes", 1},
|
||||||
|
{"kb", NULL, 1024},
|
||||||
|
{"kbyte", "kbytes", 1024},
|
||||||
|
{"kilobyte", "kilebytes", 1024},
|
||||||
|
{"mb", NULL, 1024 * 1024},
|
||||||
|
{"mbyte", "mbytes", 1024 * 1024},
|
||||||
|
{"megabyte", "megabytes", 1024 * 1024},
|
||||||
|
{NULL, NULL, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
time_t conf_find_time(char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; ircd_times[i].name; i++)
|
||||||
|
{
|
||||||
|
if (strcasecmp(ircd_times[i].name, name) == 0 ||
|
||||||
|
(ircd_times[i].plural && strcasecmp(ircd_times[i].plural, name) == 0))
|
||||||
|
return ircd_times[i].val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
const char *word;
|
||||||
|
int yesno;
|
||||||
|
} yesno[] = {
|
||||||
|
{"yes", 1},
|
||||||
|
{"no", 0},
|
||||||
|
{"true", 1},
|
||||||
|
{"false", 0},
|
||||||
|
{"on", 1},
|
||||||
|
{"off", 0},
|
||||||
|
{NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int conf_get_yesno_value(char *str)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; yesno[i].word; i++)
|
||||||
|
{
|
||||||
|
if (strcasecmp(str, yesno[i].word) == 0)
|
||||||
|
{
|
||||||
|
return yesno[i].yesno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_cur_list(conf_parm_t* list)
|
||||||
|
{
|
||||||
|
if (list->type == CF_STRING || list->type == CF_QSTRING) {
|
||||||
|
rb_free(list->v.string);
|
||||||
|
} else if (list->type == CF_FLIST) {
|
||||||
|
/* Even though CF_FLIST is a flag, comparing with == is valid
|
||||||
|
* because conf_parm_t.type must be either a type or one flag.
|
||||||
|
*/
|
||||||
|
free_cur_list(list->v.list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list->next) {
|
||||||
|
free_cur_list(list->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
conf_parm_t * cur_list = NULL;
|
||||||
|
|
||||||
|
static void add_cur_list_cpt(conf_parm_t *new)
|
||||||
|
{
|
||||||
|
if (cur_list == NULL)
|
||||||
|
{
|
||||||
|
cur_list = rb_malloc(sizeof(conf_parm_t));
|
||||||
|
cur_list->type = CF_FLIST;
|
||||||
|
cur_list->v.list = new;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new->next = cur_list->v.list;
|
||||||
|
cur_list->v.list = new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_cur_list(int type, char *str, int number)
|
||||||
|
{
|
||||||
|
conf_parm_t *new;
|
||||||
|
|
||||||
|
new = rb_malloc(sizeof(conf_parm_t));
|
||||||
|
new->next = NULL;
|
||||||
|
new->type = type;
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case CF_INT:
|
||||||
|
case CF_TIME:
|
||||||
|
case CF_YESNO:
|
||||||
|
new->v.number = number;
|
||||||
|
break;
|
||||||
|
case CF_STRING:
|
||||||
|
case CF_QSTRING:
|
||||||
|
new->v.string = rb_strdup(str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_cur_list_cpt(new);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%union {
|
||||||
|
int number;
|
||||||
|
char string[1024];
|
||||||
|
conf_parm_t * conf_parm;
|
||||||
|
}
|
||||||
|
|
||||||
|
%token LOADMODULE TWODOTS
|
||||||
|
|
||||||
|
%token <string> QSTRING STRING
|
||||||
|
%token <number> NUMBER
|
||||||
|
|
||||||
|
%type <string> qstring string
|
||||||
|
%type <number> number timespec
|
||||||
|
%type <conf_parm> oneitem single itemlist
|
||||||
|
|
||||||
|
%start conf
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
conf:
|
||||||
|
| conf conf_item
|
||||||
|
| error
|
||||||
|
;
|
||||||
|
|
||||||
|
conf_item: block
|
||||||
|
| loadmodule
|
||||||
|
;
|
||||||
|
|
||||||
|
block: string
|
||||||
|
{
|
||||||
|
conf_start_block($1, NULL);
|
||||||
|
}
|
||||||
|
'{' block_items '}' ';'
|
||||||
|
{
|
||||||
|
if (conf_cur_block)
|
||||||
|
conf_end_block(conf_cur_block);
|
||||||
|
}
|
||||||
|
| string qstring
|
||||||
|
{
|
||||||
|
conf_start_block($1, $2);
|
||||||
|
}
|
||||||
|
'{' block_items '}' ';'
|
||||||
|
{
|
||||||
|
if (conf_cur_block)
|
||||||
|
conf_end_block(conf_cur_block);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
block_items: block_items block_item
|
||||||
|
| block_item
|
||||||
|
;
|
||||||
|
|
||||||
|
block_item: string '=' itemlist ';'
|
||||||
|
{
|
||||||
|
conf_call_set(conf_cur_block, $1, cur_list);
|
||||||
|
free_cur_list(cur_list);
|
||||||
|
cur_list = NULL;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
itemlist: itemlist ',' single
|
||||||
|
| single
|
||||||
|
;
|
||||||
|
|
||||||
|
single: oneitem
|
||||||
|
{
|
||||||
|
add_cur_list_cpt($1);
|
||||||
|
}
|
||||||
|
| oneitem TWODOTS oneitem
|
||||||
|
{
|
||||||
|
/* "1 .. 5" meaning 1,2,3,4,5 - only valid for integers */
|
||||||
|
if ($1->type != CF_INT || $3->type != CF_INT)
|
||||||
|
{
|
||||||
|
conf_report_error("Both arguments in '..' notation must be integers.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = $1->v.number; i <= $3->v.number; i++)
|
||||||
|
{
|
||||||
|
add_cur_list(CF_INT, 0, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
oneitem: qstring
|
||||||
|
{
|
||||||
|
$$ = rb_malloc(sizeof(conf_parm_t));
|
||||||
|
$$->type = CF_QSTRING;
|
||||||
|
$$->v.string = rb_strdup($1);
|
||||||
|
}
|
||||||
|
| timespec
|
||||||
|
{
|
||||||
|
$$ = rb_malloc(sizeof(conf_parm_t));
|
||||||
|
$$->type = CF_TIME;
|
||||||
|
$$->v.number = $1;
|
||||||
|
}
|
||||||
|
| number
|
||||||
|
{
|
||||||
|
$$ = rb_malloc(sizeof(conf_parm_t));
|
||||||
|
$$->type = CF_INT;
|
||||||
|
$$->v.number = $1;
|
||||||
|
}
|
||||||
|
| string
|
||||||
|
{
|
||||||
|
/* a 'string' could also be a yes/no value ..
|
||||||
|
so pass it as that, if so */
|
||||||
|
int val = conf_get_yesno_value($1);
|
||||||
|
|
||||||
|
$$ = rb_malloc(sizeof(conf_parm_t));
|
||||||
|
|
||||||
|
if (val != -1)
|
||||||
|
{
|
||||||
|
$$->type = CF_YESNO;
|
||||||
|
$$->v.number = val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$$->type = CF_STRING;
|
||||||
|
$$->v.string = rb_strdup($1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
loadmodule:
|
||||||
|
LOADMODULE QSTRING
|
||||||
|
{
|
||||||
|
#ifndef STATIC_MODULES
|
||||||
|
char *m_bn;
|
||||||
|
|
||||||
|
m_bn = rb_basename((char *) $2);
|
||||||
|
|
||||||
|
if (findmodule_byname(m_bn) == -1)
|
||||||
|
load_one_module($2, 0);
|
||||||
|
|
||||||
|
rb_free(m_bn);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
';'
|
||||||
|
;
|
||||||
|
|
||||||
|
qstring: QSTRING { strcpy($$, $1); } ;
|
||||||
|
string: STRING { strcpy($$, $1); } ;
|
||||||
|
number: NUMBER { $$ = $1; } ;
|
||||||
|
|
||||||
|
timespec: number string
|
||||||
|
{
|
||||||
|
time_t t;
|
||||||
|
|
||||||
|
if ((t = conf_find_time($2)) == 0)
|
||||||
|
{
|
||||||
|
conf_report_error("Unrecognised time type/size '%s'", $2);
|
||||||
|
t = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$$ = $1 * t;
|
||||||
|
}
|
||||||
|
| timespec timespec
|
||||||
|
{
|
||||||
|
$$ = $1 + $2;
|
||||||
|
}
|
||||||
|
| timespec number
|
||||||
|
{
|
||||||
|
$$ = $1 + $2;
|
||||||
|
}
|
||||||
|
;
|
175
src/ircd_signal.c
Normal file
175
src/ircd_signal.c
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
/************************************************************************
|
||||||
|
* IRC - Internet Relay Chat, src/ircd_signal.c
|
||||||
|
* Copyright (C) 1990 Jarkko Oikarinen and
|
||||||
|
* University of Oulu, Computing Center
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 1, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
* $Id: ircd_signal.c 6 2005-09-10 01:02:21Z nenolod $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "ircd_signal.h"
|
||||||
|
#include "ircd.h" /* dorehash */
|
||||||
|
#include "restart.h" /* server_reboot */
|
||||||
|
#include "logger.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "send.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dummy_handler - don't know if this is really needed but if alarm is still
|
||||||
|
* being used we probably will
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
dummy_handler(int sig)
|
||||||
|
{
|
||||||
|
/* Empty */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
sigchld_handler(int sig)
|
||||||
|
{
|
||||||
|
int status, olderrno;
|
||||||
|
|
||||||
|
olderrno = errno;
|
||||||
|
while (waitpid(-1, &status, WNOHANG) > 0)
|
||||||
|
;
|
||||||
|
errno = olderrno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sigterm_handler - exit the server
|
||||||
|
*/
|
||||||
|
static void __attribute__((noreturn))
|
||||||
|
sigterm_handler(int sig)
|
||||||
|
{
|
||||||
|
ircd_shutdown("Received SIGTERM");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sighup_handler - reread the server configuration
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
sighup_handler(int sig)
|
||||||
|
{
|
||||||
|
dorehash = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sigusr1_handler - reread the motd file
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
sigusr1_handler(int sig)
|
||||||
|
{
|
||||||
|
doremotd = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sigusr2_handler(int sig)
|
||||||
|
{
|
||||||
|
dorehashbans = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sigint_handler - restart the server
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
sigint_handler(int sig)
|
||||||
|
{
|
||||||
|
static int restarting = 0;
|
||||||
|
|
||||||
|
if(server_state_foreground)
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "Server exiting on SIGINT");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "Server Restarting on SIGINT");
|
||||||
|
if(restarting == 0)
|
||||||
|
{
|
||||||
|
restarting = 1;
|
||||||
|
server_reboot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setup_signals - initialize signal handlers for server
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
setup_signals()
|
||||||
|
{
|
||||||
|
sigset_t sigs;
|
||||||
|
struct sigaction act;
|
||||||
|
|
||||||
|
sigemptyset(&sigs);
|
||||||
|
act.sa_flags = 0;
|
||||||
|
act.sa_handler = SIG_IGN;
|
||||||
|
sigemptyset(&act.sa_mask);
|
||||||
|
sigaddset(&act.sa_mask, SIGPIPE);
|
||||||
|
sigaddset(&act.sa_mask, SIGALRM);
|
||||||
|
#ifdef SIGTRAP
|
||||||
|
sigaddset(&act.sa_mask, SIGTRAP);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# ifdef SIGWINCH
|
||||||
|
sigaddset(&act.sa_mask, SIGWINCH);
|
||||||
|
sigaction(SIGWINCH, &act, 0);
|
||||||
|
# endif
|
||||||
|
sigaction(SIGPIPE, &act, 0);
|
||||||
|
#ifdef SIGTRAP
|
||||||
|
sigaction(SIGTRAP, &act, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
act.sa_handler = dummy_handler;
|
||||||
|
sigaction(SIGALRM, &act, 0);
|
||||||
|
sigaddset(&sigs, SIGALRM);
|
||||||
|
|
||||||
|
act.sa_handler = sighup_handler;
|
||||||
|
sigemptyset(&act.sa_mask);
|
||||||
|
sigaddset(&act.sa_mask, SIGHUP);
|
||||||
|
sigaction(SIGHUP, &act, 0);
|
||||||
|
sigaddset(&sigs, SIGHUP);
|
||||||
|
|
||||||
|
act.sa_handler = sigint_handler;
|
||||||
|
sigaddset(&act.sa_mask, SIGINT);
|
||||||
|
sigaction(SIGINT, &act, 0);
|
||||||
|
sigaddset(&sigs, SIGINT);
|
||||||
|
|
||||||
|
act.sa_handler = sigterm_handler;
|
||||||
|
sigaddset(&act.sa_mask, SIGTERM);
|
||||||
|
sigaction(SIGTERM, &act, 0);
|
||||||
|
sigaddset(&sigs, SIGTERM);
|
||||||
|
|
||||||
|
act.sa_handler = sigusr1_handler;
|
||||||
|
sigaddset(&act.sa_mask, SIGUSR1);
|
||||||
|
sigaction(SIGUSR1, &act, 0);
|
||||||
|
sigaddset(&sigs, SIGUSR1);
|
||||||
|
|
||||||
|
act.sa_handler = sigusr2_handler;
|
||||||
|
sigaddset(&act.sa_mask, SIGUSR2);
|
||||||
|
sigaction(SIGUSR2, &act, 0);
|
||||||
|
sigaddset(&sigs, SIGUSR2);
|
||||||
|
|
||||||
|
act.sa_handler = sigchld_handler;
|
||||||
|
sigaddset(&act.sa_mask, SIGCHLD);
|
||||||
|
sigaction(SIGCHLD, &act, 0);
|
||||||
|
sigaddset(&sigs, SIGCHLD);
|
||||||
|
|
||||||
|
sigprocmask(SIG_UNBLOCK, &sigs, NULL);
|
||||||
|
}
|
613
src/listener.c
Normal file
613
src/listener.c
Normal file
|
@ -0,0 +1,613 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: A slightly useful ircd.
|
||||||
|
* listener.c: Listens on a port.
|
||||||
|
*
|
||||||
|
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||||
|
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||||
|
* Copyright (C) 2002-2005 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: listener.c 3460 2007-05-18 20:31:33Z jilles $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "setup.h"
|
||||||
|
#include "listener.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "match.h"
|
||||||
|
#include "ircd.h"
|
||||||
|
#include "ircd_defs.h"
|
||||||
|
#include "numeric.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "s_newconf.h"
|
||||||
|
#include "s_stats.h"
|
||||||
|
#include "send.h"
|
||||||
|
#include "s_auth.h"
|
||||||
|
#include "reject.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "hostmask.h"
|
||||||
|
#include "sslproc.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "s_assert.h"
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
#ifndef INADDR_NONE
|
||||||
|
#define INADDR_NONE ((unsigned int) 0xffffffff)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(NO_IN6ADDR_ANY) && defined(RB_IPV6)
|
||||||
|
static const struct in6_addr in6addr_any =
|
||||||
|
{ { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct Listener *ListenerPollList = NULL;
|
||||||
|
static int accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data);
|
||||||
|
static void accept_callback(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t addrlen, void *data);
|
||||||
|
|
||||||
|
static struct Listener *
|
||||||
|
make_listener(struct rb_sockaddr_storage *addr)
|
||||||
|
{
|
||||||
|
struct Listener *listener = (struct Listener *) rb_malloc(sizeof(struct Listener));
|
||||||
|
s_assert(0 != listener);
|
||||||
|
listener->name = me.name;
|
||||||
|
listener->F = NULL;
|
||||||
|
|
||||||
|
memcpy(&listener->addr, addr, sizeof(struct rb_sockaddr_storage));
|
||||||
|
listener->next = NULL;
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free_listener(struct Listener *listener)
|
||||||
|
{
|
||||||
|
s_assert(NULL != listener);
|
||||||
|
if(listener == NULL)
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
* remove from listener list
|
||||||
|
*/
|
||||||
|
if(listener == ListenerPollList)
|
||||||
|
ListenerPollList = listener->next;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct Listener *prev = ListenerPollList;
|
||||||
|
for (; prev; prev = prev->next)
|
||||||
|
{
|
||||||
|
if(listener == prev->next)
|
||||||
|
{
|
||||||
|
prev->next = listener->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free */
|
||||||
|
rb_free(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PORTNAMELEN 6 /* ":31337" */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_listener_port - return displayable listener port
|
||||||
|
*/
|
||||||
|
static uint16_t
|
||||||
|
get_listener_port(const struct Listener *listener)
|
||||||
|
{
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
if(listener->addr.ss_family == AF_INET6)
|
||||||
|
return ntohs(((const struct sockaddr_in6 *)&listener->addr)->sin6_port);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
return ntohs(((const struct sockaddr_in *)&listener->addr)->sin_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_listener_name - return displayable listener name and port
|
||||||
|
* returns "host.foo.org:6667" for a given listener
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
get_listener_name(const struct Listener *listener)
|
||||||
|
{
|
||||||
|
static char buf[HOSTLEN + HOSTLEN + PORTNAMELEN + 4];
|
||||||
|
|
||||||
|
s_assert(NULL != listener);
|
||||||
|
if(listener == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
rb_snprintf(buf, sizeof(buf), "%s[%s/%u]",
|
||||||
|
me.name, listener->name, get_listener_port(listener));
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* show_ports - send port listing to a client
|
||||||
|
* inputs - pointer to client to show ports to
|
||||||
|
* output - none
|
||||||
|
* side effects - show ports
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
show_ports(struct Client *source_p)
|
||||||
|
{
|
||||||
|
struct Listener *listener = 0;
|
||||||
|
|
||||||
|
for (listener = ListenerPollList; listener; listener = listener->next)
|
||||||
|
{
|
||||||
|
sendto_one_numeric(source_p, RPL_STATSPLINE,
|
||||||
|
form_str(RPL_STATSPLINE), 'P',
|
||||||
|
get_listener_port(listener),
|
||||||
|
IsOperAdmin(source_p) ? listener->name : me.name,
|
||||||
|
listener->ref_count, (listener->active) ? "active" : "disabled",
|
||||||
|
listener->ssl ? " ssl" : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* inetport - create a listener socket in the AF_INET or AF_INET6 domain,
|
||||||
|
* bind it to the port given in 'port' and listen to it
|
||||||
|
* returns true (1) if successful false (0) on error.
|
||||||
|
*
|
||||||
|
* If the operating system has a define for SOMAXCONN, use it, otherwise
|
||||||
|
* use RATBOX_SOMAXCONN
|
||||||
|
*/
|
||||||
|
#ifdef SOMAXCONN
|
||||||
|
#undef RATBOX_SOMAXCONN
|
||||||
|
#define RATBOX_SOMAXCONN SOMAXCONN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
inetport(struct Listener *listener)
|
||||||
|
{
|
||||||
|
rb_fde_t *F;
|
||||||
|
int opt = 1;
|
||||||
|
const char *errstr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At first, open a new socket
|
||||||
|
*/
|
||||||
|
|
||||||
|
F = rb_socket(GET_SS_FAMILY(&listener->addr), SOCK_STREAM, 0, "Listener socket");
|
||||||
|
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
if(listener->addr.ss_family == AF_INET6)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&listener->addr;
|
||||||
|
if(!IN6_ARE_ADDR_EQUAL(&in6->sin6_addr, &in6addr_any))
|
||||||
|
{
|
||||||
|
rb_inet_ntop(AF_INET6, &in6->sin6_addr, listener->vhost, sizeof(listener->vhost));
|
||||||
|
listener->name = listener->vhost;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
struct sockaddr_in *in = (struct sockaddr_in *)&listener->addr;
|
||||||
|
if(in->sin_addr.s_addr != INADDR_ANY)
|
||||||
|
{
|
||||||
|
rb_inet_ntop(AF_INET, &in->sin_addr, listener->vhost, sizeof(listener->vhost));
|
||||||
|
listener->name = listener->vhost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(F == NULL)
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Cannot open socket for listener on port %d",
|
||||||
|
get_listener_port(listener));
|
||||||
|
ilog(L_MAIN, "Cannot open socket for listener %s",
|
||||||
|
get_listener_name(listener));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus*/
|
||||||
|
{
|
||||||
|
ilog_error("no more connections left for listener");
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"No more connections left for listener on port %d",
|
||||||
|
get_listener_port(listener));
|
||||||
|
ilog(L_MAIN, "No more connections left for listener %s",
|
||||||
|
get_listener_name(listener));
|
||||||
|
rb_close(F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX - we don't want to do all this crap for a listener
|
||||||
|
* set_sock_opts(listener);
|
||||||
|
*/
|
||||||
|
if(setsockopt(rb_get_fd(F), SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)))
|
||||||
|
{
|
||||||
|
errstr = strerror(rb_get_sockerr(F));
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Cannot set SO_REUSEADDR for listener on port %d: %s",
|
||||||
|
get_listener_port(listener), errstr);
|
||||||
|
ilog(L_MAIN, "Cannot set SO_REUSEADDR for listener %s: %s",
|
||||||
|
get_listener_name(listener), errstr);
|
||||||
|
rb_close(F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bind a port to listen for new connections if port is non-null,
|
||||||
|
* else assume it is already open and try get something from it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(bind(rb_get_fd(F), (struct sockaddr *) &listener->addr, GET_SS_LEN(&listener->addr)))
|
||||||
|
{
|
||||||
|
errstr = strerror(rb_get_sockerr(F));
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Cannot bind for listener on port %d: %s",
|
||||||
|
get_listener_port(listener), errstr);
|
||||||
|
ilog(L_MAIN, "Cannot bind for listener %s: %s",
|
||||||
|
get_listener_name(listener), errstr);
|
||||||
|
rb_close(F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rb_listen(F, RATBOX_SOMAXCONN, listener->defer_accept))
|
||||||
|
{
|
||||||
|
errstr = strerror(rb_get_sockerr(F));
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Cannot listen() for listener on port %d: %s",
|
||||||
|
get_listener_port(listener), errstr);
|
||||||
|
ilog(L_MAIN, "Cannot listen() for listener %s: %s",
|
||||||
|
get_listener_name(listener), errstr);
|
||||||
|
rb_close(F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
listener->F = F;
|
||||||
|
|
||||||
|
rb_accept_tcp(listener->F, accept_precallback, accept_callback, listener);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct Listener *
|
||||||
|
find_listener(struct rb_sockaddr_storage *addr)
|
||||||
|
{
|
||||||
|
struct Listener *listener = NULL;
|
||||||
|
struct Listener *last_closed = NULL;
|
||||||
|
|
||||||
|
for (listener = ListenerPollList; listener; listener = listener->next)
|
||||||
|
{
|
||||||
|
if(addr->ss_family != listener->addr.ss_family)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch(addr->ss_family)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
{
|
||||||
|
struct sockaddr_in *in4 = (struct sockaddr_in *)addr;
|
||||||
|
struct sockaddr_in *lin4 = (struct sockaddr_in *)&listener->addr;
|
||||||
|
if(in4->sin_addr.s_addr == lin4->sin_addr.s_addr &&
|
||||||
|
in4->sin_port == lin4->sin_port )
|
||||||
|
{
|
||||||
|
if(listener->F == NULL)
|
||||||
|
last_closed = listener;
|
||||||
|
else
|
||||||
|
return(listener);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
case AF_INET6:
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
|
||||||
|
struct sockaddr_in6 *lin6 =(struct sockaddr_in6 *)&listener->addr;
|
||||||
|
if(IN6_ARE_ADDR_EQUAL(&in6->sin6_addr, &lin6->sin6_addr) &&
|
||||||
|
in6->sin6_port == lin6->sin6_port)
|
||||||
|
{
|
||||||
|
if(listener->F == NULL)
|
||||||
|
last_closed = listener;
|
||||||
|
else
|
||||||
|
return(listener);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return last_closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add_listener- create a new listener
|
||||||
|
* port - the port number to listen on
|
||||||
|
* vhost_ip - if non-null must contain a valid IP address string in
|
||||||
|
* the format "255.255.255.255"
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
add_listener(int port, const char *vhost_ip, int family, int ssl, int defer_accept)
|
||||||
|
{
|
||||||
|
struct Listener *listener;
|
||||||
|
struct rb_sockaddr_storage vaddr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if no port in conf line, don't bother
|
||||||
|
*/
|
||||||
|
if(port == 0)
|
||||||
|
return;
|
||||||
|
memset(&vaddr, 0, sizeof(vaddr));
|
||||||
|
vaddr.ss_family = family;
|
||||||
|
|
||||||
|
if(vhost_ip != NULL)
|
||||||
|
{
|
||||||
|
if(family == AF_INET)
|
||||||
|
{
|
||||||
|
if(rb_inet_pton(family, vhost_ip, &((struct sockaddr_in *)&vaddr)->sin_addr) <= 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(rb_inet_pton(family, vhost_ip, &((struct sockaddr_in6 *)&vaddr)->sin6_addr) <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
switch(family)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
((struct sockaddr_in *)&vaddr)->sin_addr.s_addr = INADDR_ANY;
|
||||||
|
break;
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
case AF_INET6:
|
||||||
|
memcpy(&((struct sockaddr_in6 *)&vaddr)->sin6_addr, &in6addr_any, sizeof(struct in6_addr));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch(family)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in));
|
||||||
|
((struct sockaddr_in *)&vaddr)->sin_port = htons(port);
|
||||||
|
break;
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
case AF_INET6:
|
||||||
|
SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in6));
|
||||||
|
((struct sockaddr_in6 *)&vaddr)->sin6_port = htons(port);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if((listener = find_listener(&vaddr)))
|
||||||
|
{
|
||||||
|
if(listener->F != NULL)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listener = make_listener(&vaddr);
|
||||||
|
listener->next = ListenerPollList;
|
||||||
|
ListenerPollList = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
listener->F = NULL;
|
||||||
|
listener->ssl = ssl;
|
||||||
|
listener->defer_accept = defer_accept;
|
||||||
|
|
||||||
|
if(inetport(listener))
|
||||||
|
listener->active = 1;
|
||||||
|
else
|
||||||
|
close_listener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* close_listener - close a single listener
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
close_listener(struct Listener *listener)
|
||||||
|
{
|
||||||
|
s_assert(listener != NULL);
|
||||||
|
if(listener == NULL)
|
||||||
|
return;
|
||||||
|
if(listener->F != NULL)
|
||||||
|
{
|
||||||
|
rb_close(listener->F);
|
||||||
|
listener->F = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
listener->active = 0;
|
||||||
|
|
||||||
|
if(listener->ref_count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
free_listener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* close_listeners - close and free all listeners that are not being used
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
close_listeners()
|
||||||
|
{
|
||||||
|
struct Listener *listener;
|
||||||
|
struct Listener *listener_next = 0;
|
||||||
|
/*
|
||||||
|
* close all 'extra' listening ports we have
|
||||||
|
*/
|
||||||
|
for (listener = ListenerPollList; listener; listener = listener_next)
|
||||||
|
{
|
||||||
|
listener_next = listener->next;
|
||||||
|
close_listener(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DLINE_WARNING "ERROR :You have been D-lined.\r\n"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add_connection - creates a client which has just connected to us on
|
||||||
|
* the given fd. The sockhost field is initialized with the ip# of the host.
|
||||||
|
* The client is sent to the auth module for verification, and not put in
|
||||||
|
* any client list yet.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, struct sockaddr *lai)
|
||||||
|
{
|
||||||
|
struct Client *new_client;
|
||||||
|
s_assert(NULL != listener);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get the client socket name from the socket
|
||||||
|
* the client has already been checked out in accept_connection
|
||||||
|
*/
|
||||||
|
new_client = make_client(NULL);
|
||||||
|
new_client->localClient->F = F;
|
||||||
|
|
||||||
|
memcpy(&new_client->localClient->ip, sai, sizeof(struct rb_sockaddr_storage));
|
||||||
|
memcpy(&new_client->preClient->lip, lai, sizeof(struct rb_sockaddr_storage));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* copy address to 'sockhost' as a string, copy it to host too
|
||||||
|
* so we have something valid to put into error messages...
|
||||||
|
*/
|
||||||
|
rb_inet_ntop_sock((struct sockaddr *)&new_client->localClient->ip, new_client->sockhost,
|
||||||
|
sizeof(new_client->sockhost));
|
||||||
|
|
||||||
|
rb_strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host));
|
||||||
|
|
||||||
|
if (listener->ssl)
|
||||||
|
{
|
||||||
|
rb_fde_t *xF[2];
|
||||||
|
if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming ssld Connection") == -1)
|
||||||
|
{
|
||||||
|
SetIOError(new_client);
|
||||||
|
exit_client(new_client, new_client, new_client, "Fatal Error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
new_client->localClient->ssl_ctl = start_ssld_accept(F, xF[1], new_client->localClient->connid); /* this will close F for us */
|
||||||
|
if(new_client->localClient->ssl_ctl == NULL)
|
||||||
|
{
|
||||||
|
SetIOError(new_client);
|
||||||
|
exit_client(new_client, new_client, new_client, "Service Unavailable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
F = xF[0];
|
||||||
|
new_client->localClient->F = F;
|
||||||
|
SetSSL(new_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_client->localClient->listener = listener;
|
||||||
|
|
||||||
|
++listener->ref_count;
|
||||||
|
|
||||||
|
start_auth(new_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *toofast = "ERROR :Reconnecting too fast, throttled.\r\n";
|
||||||
|
|
||||||
|
static int
|
||||||
|
accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data)
|
||||||
|
{
|
||||||
|
struct Listener *listener = (struct Listener *)data;
|
||||||
|
char buf[BUFSIZE];
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
static time_t last_oper_notice = 0;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if(listener->ssl && (!ircd_ssl_ok || !get_ssld_count()))
|
||||||
|
{
|
||||||
|
rb_close(F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus */
|
||||||
|
{
|
||||||
|
++ServerStats.is_ref;
|
||||||
|
/*
|
||||||
|
* slow down the whining to opers bit
|
||||||
|
*/
|
||||||
|
if((last_oper_notice + 20) <= rb_current_time())
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"All connections in use. (%s)",
|
||||||
|
get_listener_name(listener));
|
||||||
|
last_oper_notice = rb_current_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_write(F, "ERROR :All connections in use\r\n", 31);
|
||||||
|
rb_close(F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
aconf = find_dline(addr, addr->sa_family);
|
||||||
|
if(aconf != NULL && (aconf->status & CONF_EXEMPTDLINE))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Do an initial check we aren't connecting too fast or with too many
|
||||||
|
* from this IP... */
|
||||||
|
if(aconf != NULL)
|
||||||
|
{
|
||||||
|
ServerStats.is_ref++;
|
||||||
|
|
||||||
|
if(ConfigFileEntry.dline_with_reason)
|
||||||
|
{
|
||||||
|
len = rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", get_user_ban_reason(aconf));
|
||||||
|
if (len >= (int)(sizeof(buf)-1))
|
||||||
|
{
|
||||||
|
buf[sizeof(buf) - 3] = '\r';
|
||||||
|
buf[sizeof(buf) - 2] = '\n';
|
||||||
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strcpy(buf, "ERROR :You have been D-lined.\r\n");
|
||||||
|
|
||||||
|
rb_write(F, buf, strlen(buf));
|
||||||
|
rb_close(F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(check_reject(F, addr))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(throttle_add(addr))
|
||||||
|
{
|
||||||
|
rb_write(F, toofast, strlen(toofast));
|
||||||
|
rb_close(F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
accept_callback(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t addrlen, void *data)
|
||||||
|
{
|
||||||
|
struct Listener *listener = data;
|
||||||
|
struct rb_sockaddr_storage lip;
|
||||||
|
unsigned int locallen = sizeof(struct rb_sockaddr_storage);
|
||||||
|
|
||||||
|
ServerStats.is_ac++;
|
||||||
|
|
||||||
|
if(getsockname(rb_get_fd(F), (struct sockaddr *) &lip, &locallen) < 0)
|
||||||
|
{
|
||||||
|
/* this can fail if the connection disappeared in the meantime */
|
||||||
|
rb_close(F);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_connection(listener, F, addr, (struct sockaddr *)&lip);
|
||||||
|
}
|
930
src/modules.c
Normal file
930
src/modules.c
Normal file
|
@ -0,0 +1,930 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: A slightly useful ircd.
|
||||||
|
* modules.c: A module loader.
|
||||||
|
*
|
||||||
|
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||||
|
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||||
|
* Copyright (C) 2002-2005 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: modules.c 3161 2007-01-25 07:23:01Z nenolod $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdinc.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "modules.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "ircd.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "send.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "s_newconf.h"
|
||||||
|
#include "numeric.h"
|
||||||
|
#include "parse.h"
|
||||||
|
#include "ircd_defs.h"
|
||||||
|
#include "match.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef STATIC_MODULES
|
||||||
|
|
||||||
|
struct module **modlist = NULL;
|
||||||
|
|
||||||
|
static const char *core_module_table[] = {
|
||||||
|
"m_ban",
|
||||||
|
"m_die",
|
||||||
|
"m_error",
|
||||||
|
"m_join",
|
||||||
|
"m_kick",
|
||||||
|
"m_kill",
|
||||||
|
"m_message",
|
||||||
|
"m_mode",
|
||||||
|
"m_nick",
|
||||||
|
"m_part",
|
||||||
|
"m_quit",
|
||||||
|
"m_server",
|
||||||
|
"m_squit",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MODS_INCREMENT 10
|
||||||
|
int num_mods = 0;
|
||||||
|
int max_mods = MODS_INCREMENT;
|
||||||
|
|
||||||
|
static rb_dlink_list mod_paths;
|
||||||
|
|
||||||
|
static int mo_modload(struct Client *, struct Client *, int, const char **);
|
||||||
|
static int mo_modlist(struct Client *, struct Client *, int, const char **);
|
||||||
|
static int mo_modreload(struct Client *, struct Client *, int, const char **);
|
||||||
|
static int mo_modunload(struct Client *, struct Client *, int, const char **);
|
||||||
|
static int mo_modrestart(struct Client *, struct Client *, int, const char **);
|
||||||
|
|
||||||
|
struct Message modload_msgtab = {
|
||||||
|
"MODLOAD", 0, 0, 0, MFLG_SLOW,
|
||||||
|
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modload, 2}}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Message modunload_msgtab = {
|
||||||
|
"MODUNLOAD", 0, 0, 0, MFLG_SLOW,
|
||||||
|
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modunload, 2}}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Message modreload_msgtab = {
|
||||||
|
"MODRELOAD", 0, 0, 0, MFLG_SLOW,
|
||||||
|
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modreload, 2}}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Message modlist_msgtab = {
|
||||||
|
"MODLIST", 0, 0, 0, MFLG_SLOW,
|
||||||
|
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modlist, 0}}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Message modrestart_msgtab = {
|
||||||
|
"MODRESTART", 0, 0, 0, MFLG_SLOW,
|
||||||
|
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modrestart, 0}}
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
modules_init(void)
|
||||||
|
{
|
||||||
|
mod_add_cmd(&modload_msgtab);
|
||||||
|
mod_add_cmd(&modunload_msgtab);
|
||||||
|
mod_add_cmd(&modreload_msgtab);
|
||||||
|
mod_add_cmd(&modlist_msgtab);
|
||||||
|
mod_add_cmd(&modrestart_msgtab);
|
||||||
|
|
||||||
|
/* Add the default paths we look in to the module system --nenolod */
|
||||||
|
mod_add_path(MODPATH);
|
||||||
|
mod_add_path(AUTOMODPATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mod_find_path()
|
||||||
|
*
|
||||||
|
* input - path
|
||||||
|
* output - none
|
||||||
|
* side effects - returns a module path from path
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
mod_find_path(const char *path)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
char *mpath;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, mod_paths.head)
|
||||||
|
{
|
||||||
|
mpath = ptr->data;
|
||||||
|
|
||||||
|
if(!strcmp(path, mpath))
|
||||||
|
return mpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mod_add_path
|
||||||
|
*
|
||||||
|
* input - path
|
||||||
|
* ouput -
|
||||||
|
* side effects - adds path to list
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mod_add_path(const char *path)
|
||||||
|
{
|
||||||
|
char *pathst;
|
||||||
|
|
||||||
|
if(mod_find_path(path))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pathst = rb_strdup(path);
|
||||||
|
rb_dlinkAddAlloc(pathst, &mod_paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mod_clear_paths()
|
||||||
|
*
|
||||||
|
* input -
|
||||||
|
* output -
|
||||||
|
* side effects - clear the lists of paths
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mod_clear_paths(void)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr, *next_ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, mod_paths.head)
|
||||||
|
{
|
||||||
|
rb_free(ptr->data);
|
||||||
|
rb_free_rb_dlink_node(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
mod_paths.head = mod_paths.tail = NULL;
|
||||||
|
mod_paths.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* findmodule_byname
|
||||||
|
*
|
||||||
|
* input -
|
||||||
|
* output -
|
||||||
|
* side effects -
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
findmodule_byname(const char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_mods; i++)
|
||||||
|
{
|
||||||
|
if(!irccmp(modlist[i]->name, name))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load_all_modules()
|
||||||
|
*
|
||||||
|
* input -
|
||||||
|
* output -
|
||||||
|
* side effects -
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
load_all_modules(int warn)
|
||||||
|
{
|
||||||
|
DIR *system_module_dir = NULL;
|
||||||
|
struct dirent *ldirent = NULL;
|
||||||
|
char module_fq_name[PATH_MAX + 1];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
modules_init();
|
||||||
|
|
||||||
|
modlist = (struct module **) rb_malloc(sizeof(struct module *) * (MODS_INCREMENT));
|
||||||
|
|
||||||
|
max_mods = MODS_INCREMENT;
|
||||||
|
|
||||||
|
system_module_dir = opendir(AUTOMODPATH);
|
||||||
|
|
||||||
|
if(system_module_dir == NULL)
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "Could not load modules from %s: %s", AUTOMODPATH, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((ldirent = readdir(system_module_dir)) != NULL)
|
||||||
|
{
|
||||||
|
len = strlen(ldirent->d_name);
|
||||||
|
if((len > 3) && !strcmp(ldirent->d_name+len-3, SHARED_SUFFIX))
|
||||||
|
{
|
||||||
|
(void) rb_snprintf(module_fq_name, sizeof(module_fq_name), "%s/%s", AUTOMODPATH, ldirent->d_name);
|
||||||
|
(void) load_a_module(module_fq_name, warn, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
(void) closedir(system_module_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load_core_modules()
|
||||||
|
*
|
||||||
|
* input -
|
||||||
|
* output -
|
||||||
|
* side effects - core modules are loaded, if any fail, kill ircd
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
load_core_modules(int warn)
|
||||||
|
{
|
||||||
|
char module_name[PATH_MAX];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
|
||||||
|
for (i = 0; core_module_table[i]; i++)
|
||||||
|
{
|
||||||
|
rb_snprintf(module_name, sizeof(module_name), "%s/%s%s", MODPATH,
|
||||||
|
core_module_table[i], SHARED_SUFFIX);
|
||||||
|
|
||||||
|
if(load_a_module(module_name, warn, 1) == -1)
|
||||||
|
{
|
||||||
|
ilog(L_MAIN,
|
||||||
|
"Error loading core module %s%s: terminating ircd",
|
||||||
|
core_module_table[i], SHARED_SUFFIX);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load_one_module()
|
||||||
|
*
|
||||||
|
* input -
|
||||||
|
* output -
|
||||||
|
* side effects -
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
load_one_module(const char *path, int coremodule)
|
||||||
|
{
|
||||||
|
char modpath[PATH_MAX];
|
||||||
|
rb_dlink_node *pathst;
|
||||||
|
const char *mpath;
|
||||||
|
|
||||||
|
struct stat statbuf;
|
||||||
|
|
||||||
|
if (server_state_foreground == 1)
|
||||||
|
inotice("loading module %s ...", path);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(pathst, mod_paths.head)
|
||||||
|
{
|
||||||
|
mpath = pathst->data;
|
||||||
|
|
||||||
|
rb_snprintf(modpath, sizeof(modpath), "%s/%s", mpath, path);
|
||||||
|
if((strstr(modpath, "../") == NULL) && (strstr(modpath, "/..") == NULL))
|
||||||
|
{
|
||||||
|
if(stat(modpath, &statbuf) == 0)
|
||||||
|
{
|
||||||
|
if(S_ISREG(statbuf.st_mode))
|
||||||
|
{
|
||||||
|
/* Regular files only please */
|
||||||
|
if(coremodule)
|
||||||
|
return load_a_module(modpath, 1, 1);
|
||||||
|
else
|
||||||
|
return load_a_module(modpath, 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL, "Cannot locate module %s", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* load a module .. */
|
||||||
|
static int
|
||||||
|
mo_modload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
|
||||||
|
{
|
||||||
|
char *m_bn;
|
||||||
|
|
||||||
|
if(!IsOperAdmin(source_p))
|
||||||
|
{
|
||||||
|
sendto_one(source_p, form_str(ERR_NOPRIVS),
|
||||||
|
me.name, source_p->name, "admin");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bn = rb_basename(parv[1]);
|
||||||
|
|
||||||
|
if(findmodule_byname(m_bn) != -1)
|
||||||
|
{
|
||||||
|
sendto_one_notice(source_p, ":Module %s is already loaded", m_bn);
|
||||||
|
rb_free(m_bn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
load_one_module(parv[1], 0);
|
||||||
|
|
||||||
|
rb_free(m_bn);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* unload a module .. */
|
||||||
|
static int
|
||||||
|
mo_modunload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
|
||||||
|
{
|
||||||
|
char *m_bn;
|
||||||
|
int modindex;
|
||||||
|
|
||||||
|
if(!IsOperAdmin(source_p))
|
||||||
|
{
|
||||||
|
sendto_one(source_p, form_str(ERR_NOPRIVS),
|
||||||
|
me.name, source_p->name, "admin");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bn = rb_basename(parv[1]);
|
||||||
|
|
||||||
|
if((modindex = findmodule_byname(m_bn)) == -1)
|
||||||
|
{
|
||||||
|
sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
|
||||||
|
rb_free(m_bn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(modlist[modindex]->core == 1)
|
||||||
|
{
|
||||||
|
sendto_one_notice(source_p, ":Module %s is a core module and may not be unloaded", m_bn);
|
||||||
|
rb_free(m_bn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(unload_one_module(m_bn, 1) == -1)
|
||||||
|
{
|
||||||
|
sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_free(m_bn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unload and load in one! */
|
||||||
|
static int
|
||||||
|
mo_modreload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
|
||||||
|
{
|
||||||
|
char *m_bn;
|
||||||
|
int modindex;
|
||||||
|
int check_core;
|
||||||
|
|
||||||
|
if(!IsOperAdmin(source_p))
|
||||||
|
{
|
||||||
|
sendto_one(source_p, form_str(ERR_NOPRIVS),
|
||||||
|
me.name, source_p->name, "admin");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bn = rb_basename(parv[1]);
|
||||||
|
|
||||||
|
if((modindex = findmodule_byname(m_bn)) == -1)
|
||||||
|
{
|
||||||
|
sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
|
||||||
|
rb_free(m_bn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_core = modlist[modindex]->core;
|
||||||
|
|
||||||
|
if(unload_one_module(m_bn, 1) == -1)
|
||||||
|
{
|
||||||
|
sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
|
||||||
|
rb_free(m_bn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((load_one_module(m_bn, check_core) == -1) && check_core)
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Error reloading core module: %s: terminating ircd", m_bn);
|
||||||
|
ilog(L_MAIN, "Error loading core module %s: terminating ircd", m_bn);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_free(m_bn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* list modules .. */
|
||||||
|
static int
|
||||||
|
mo_modlist(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(!IsOperAdmin(source_p))
|
||||||
|
{
|
||||||
|
sendto_one(source_p, form_str(ERR_NOPRIVS),
|
||||||
|
me.name, source_p->name, "admin");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num_mods; i++)
|
||||||
|
{
|
||||||
|
if(parc > 1)
|
||||||
|
{
|
||||||
|
if(match(parv[1], modlist[i]->name))
|
||||||
|
{
|
||||||
|
sendto_one(source_p, form_str(RPL_MODLIST),
|
||||||
|
me.name, source_p->name,
|
||||||
|
modlist[i]->name,
|
||||||
|
(unsigned long)(uintptr_t)modlist[i]->address,
|
||||||
|
modlist[i]->version, modlist[i]->core ? "(core)" : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendto_one(source_p, form_str(RPL_MODLIST),
|
||||||
|
me.name, source_p->name, modlist[i]->name,
|
||||||
|
(unsigned long)(uintptr_t)modlist[i]->address,
|
||||||
|
modlist[i]->version,
|
||||||
|
modlist[i]->core ? "(core)" : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendto_one(source_p, form_str(RPL_ENDOFMODLIST), me.name, source_p->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unload and reload all modules */
|
||||||
|
static void
|
||||||
|
modules_do_restart(void *unused)
|
||||||
|
{
|
||||||
|
int modnum = num_mods;
|
||||||
|
while (num_mods)
|
||||||
|
unload_one_module(modlist[0]->name, 0);
|
||||||
|
|
||||||
|
load_all_modules(0);
|
||||||
|
load_core_modules(0);
|
||||||
|
rehash(0);
|
||||||
|
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Module Restart: %d modules unloaded, %d modules loaded",
|
||||||
|
modnum, num_mods);
|
||||||
|
ilog(L_MAIN, "Module Restart: %d modules unloaded, %d modules loaded", modnum, num_mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mo_modrestart(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
|
||||||
|
{
|
||||||
|
if(!IsOperAdmin(source_p))
|
||||||
|
{
|
||||||
|
sendto_one(source_p, form_str(ERR_NOPRIVS),
|
||||||
|
me.name, source_p->name, "admin");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendto_one_notice(source_p, ":Reloading all modules");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If a remote MODRESTART is received, m_encap.so will be reloaded,
|
||||||
|
* but ms_encap is in the call stack (it indirectly calls this
|
||||||
|
* function). This will go horribly wrong if m_encap is reloaded to
|
||||||
|
* a different address.
|
||||||
|
*
|
||||||
|
* So, defer the restart to the event loop (above) and return now.
|
||||||
|
*/
|
||||||
|
rb_event_addonce("modules_do_restart", modules_do_restart, NULL, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef RTLD_NOW
|
||||||
|
#define RTLD_NOW RTLD_LAZY /* openbsd deficiency */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RTLD_LOCAL
|
||||||
|
#define RTLD_LOCAL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CHARYBDIS_PROFILE
|
||||||
|
# ifndef RTLD_PROFILE
|
||||||
|
# warning libdl may not support profiling, sucks. :(
|
||||||
|
# define RTLD_PROFILE 0
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void increase_modlist(void);
|
||||||
|
|
||||||
|
#define MODS_INCREMENT 10
|
||||||
|
|
||||||
|
static char unknown_ver[] = "<unknown>";
|
||||||
|
|
||||||
|
/* This file contains the core functions to use dynamic libraries.
|
||||||
|
* -TimeMr14C
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_MACH_O_DYLD_H
|
||||||
|
/*
|
||||||
|
** jmallett's dl*(3) shims for NSModule(3) systems.
|
||||||
|
*/
|
||||||
|
#include <mach-o/dyld.h>
|
||||||
|
|
||||||
|
#ifndef HAVE_DLOPEN
|
||||||
|
#ifndef RTLD_LAZY
|
||||||
|
#define RTLD_LAZY 2185 /* built-in dl*(3) don't care */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void undefinedErrorHandler(const char *);
|
||||||
|
NSModule multipleErrorHandler(NSSymbol, NSModule, NSModule);
|
||||||
|
void linkEditErrorHandler(NSLinkEditErrors, int, const char *, const char *);
|
||||||
|
char *dlerror(void);
|
||||||
|
void *dlopen(char *, int);
|
||||||
|
int dlclose(void *);
|
||||||
|
void *dlsym(void *, char *);
|
||||||
|
|
||||||
|
static int firstLoad = TRUE;
|
||||||
|
static int myDlError;
|
||||||
|
static char *myErrorTable[] = { "Loading file as object failed\n",
|
||||||
|
"Loading file as object succeeded\n",
|
||||||
|
"Not a valid shared object\n",
|
||||||
|
"Architecture of object invalid on this architecture\n",
|
||||||
|
"Invalid or corrupt image\n",
|
||||||
|
"Could not access object\n",
|
||||||
|
"NSCreateObjectFileImageFromFile failed\n",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
undefinedErrorHandler(const char *symbolName)
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL, "Undefined symbol: %s", symbolName);
|
||||||
|
ilog(L_MAIN, "Undefined symbol: %s", symbolName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSModule
|
||||||
|
multipleErrorHandler(NSSymbol s, NSModule old, NSModule new)
|
||||||
|
{
|
||||||
|
/* XXX
|
||||||
|
** This results in substantial leaking of memory... Should free one
|
||||||
|
** module, maybe?
|
||||||
|
*/
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Symbol `%s' found in `%s' and `%s'",
|
||||||
|
NSNameOfSymbol(s), NSNameOfModule(old), NSNameOfModule(new));
|
||||||
|
ilog(L_MAIN, "Symbol `%s' found in `%s' and `%s'",
|
||||||
|
NSNameOfSymbol(s), NSNameOfModule(old), NSNameOfModule(new));
|
||||||
|
/* We return which module should be considered valid, I believe */
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
linkEditErrorHandler(NSLinkEditErrors errorClass, int errnum,
|
||||||
|
const char *fileName, const char *errorString)
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Link editor error: %s for %s", errorString, fileName);
|
||||||
|
ilog(L_MAIN, "Link editor error: %s for %s", errorString, fileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
dlerror(void)
|
||||||
|
{
|
||||||
|
return myDlError == NSObjectFileImageSuccess ? NULL : myErrorTable[myDlError % 7];
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
dlopen(char *filename, int unused)
|
||||||
|
{
|
||||||
|
NSObjectFileImage myImage;
|
||||||
|
NSModule myModule;
|
||||||
|
|
||||||
|
if(firstLoad)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
** If we are loading our first symbol (huzzah!) we should go ahead
|
||||||
|
** and install link editor error handling!
|
||||||
|
*/
|
||||||
|
NSLinkEditErrorHandlers linkEditorErrorHandlers;
|
||||||
|
|
||||||
|
linkEditorErrorHandlers.undefined = undefinedErrorHandler;
|
||||||
|
linkEditorErrorHandlers.multiple = multipleErrorHandler;
|
||||||
|
linkEditorErrorHandlers.linkEdit = linkEditErrorHandler;
|
||||||
|
NSInstallLinkEditErrorHandlers(&linkEditorErrorHandlers);
|
||||||
|
firstLoad = FALSE;
|
||||||
|
}
|
||||||
|
myDlError = NSCreateObjectFileImageFromFile(filename, &myImage);
|
||||||
|
if(myDlError != NSObjectFileImageSuccess)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
myModule = NSLinkModule(myImage, filename, NSLINKMODULE_OPTION_PRIVATE);
|
||||||
|
return (void *) myModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dlclose(void *myModule)
|
||||||
|
{
|
||||||
|
NSUnLinkModule(myModule, FALSE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
dlsym(void *myModule, char *mySymbolName)
|
||||||
|
{
|
||||||
|
NSSymbol mySymbol;
|
||||||
|
|
||||||
|
mySymbol = NSLookupSymbolInModule((NSModule) myModule, mySymbolName);
|
||||||
|
return NSAddressOfSymbol(mySymbol);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HPUX dl compat functions
|
||||||
|
*/
|
||||||
|
#if defined(HAVE_SHL_LOAD) && !defined(HAVE_DLOPEN)
|
||||||
|
#define RTLD_LAZY BIND_DEFERRED
|
||||||
|
#define RTLD_GLOBAL DYNAMIC_PATH
|
||||||
|
#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
|
||||||
|
#define dlclose(handle) shl_unload((shl_t)(handle))
|
||||||
|
#define dlsym(handle,name) hpux_dlsym(handle,name)
|
||||||
|
#define dlerror() strerror(errno)
|
||||||
|
|
||||||
|
static void *
|
||||||
|
hpux_dlsym(void *handle, char *name)
|
||||||
|
{
|
||||||
|
void *sym_addr;
|
||||||
|
if(!shl_findsym((shl_t *) & handle, name, TYPE_UNDEFINED, &sym_addr))
|
||||||
|
return sym_addr;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* unload_one_module()
|
||||||
|
*
|
||||||
|
* inputs - name of module to unload
|
||||||
|
* - 1 to say modules unloaded, 0 to not
|
||||||
|
* output - 0 if successful, -1 if error
|
||||||
|
* side effects - module is unloaded
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
unload_one_module(const char *name, int warn)
|
||||||
|
{
|
||||||
|
int modindex;
|
||||||
|
|
||||||
|
if((modindex = findmodule_byname(name)) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** XXX - The type system in C does not allow direct conversion between
|
||||||
|
** data and function pointers, but as it happens, most C compilers will
|
||||||
|
** safely do this, however it is a theoretical overlow to cast as we
|
||||||
|
** must do here. I have library functions to take care of this, but
|
||||||
|
** despite being more "correct" for the C language, this is more
|
||||||
|
** practical. Removing the abuse of the ability to cast ANY pointer
|
||||||
|
** to and from an integer value here will break some compilers.
|
||||||
|
** -jmallett
|
||||||
|
*/
|
||||||
|
/* Left the comment in but the code isn't here any more -larne */
|
||||||
|
switch (modlist[modindex]->mapi_version)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
struct mapi_mheader_av1 *mheader = modlist[modindex]->mapi_header;
|
||||||
|
if(mheader->mapi_command_list)
|
||||||
|
{
|
||||||
|
struct Message **m;
|
||||||
|
for (m = mheader->mapi_command_list; *m; ++m)
|
||||||
|
mod_del_cmd(*m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hook events are never removed, we simply lose the
|
||||||
|
* ability to call them --fl
|
||||||
|
*/
|
||||||
|
if(mheader->mapi_hfn_list)
|
||||||
|
{
|
||||||
|
mapi_hfn_list_av1 *m;
|
||||||
|
for (m = mheader->mapi_hfn_list; m->hapi_name; ++m)
|
||||||
|
remove_hook(m->hapi_name, m->fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mheader->mapi_unregister)
|
||||||
|
mheader->mapi_unregister();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Unknown/unsupported MAPI version %d when unloading %s!",
|
||||||
|
modlist[modindex]->mapi_version, modlist[modindex]->name);
|
||||||
|
ilog(L_MAIN, "Unknown/unsupported MAPI version %d when unloading %s!",
|
||||||
|
modlist[modindex]->mapi_version, modlist[modindex]->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dlclose(modlist[modindex]->address);
|
||||||
|
|
||||||
|
rb_free(modlist[modindex]->name);
|
||||||
|
memmove(&modlist[modindex], &modlist[modindex + 1],
|
||||||
|
sizeof(struct module *) * ((num_mods - 1) - modindex));
|
||||||
|
|
||||||
|
if(num_mods != 0)
|
||||||
|
num_mods--;
|
||||||
|
|
||||||
|
if(warn == 1)
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "Module %s unloaded", name);
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL, "Module %s unloaded", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* load_a_module()
|
||||||
|
*
|
||||||
|
* inputs - path name of module, int to notice, int of core
|
||||||
|
* output - -1 if error 0 if success
|
||||||
|
* side effects - loads a module if successful
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
load_a_module(const char *path, int warn, int core)
|
||||||
|
{
|
||||||
|
void *tmpptr = NULL;
|
||||||
|
|
||||||
|
char *mod_basename;
|
||||||
|
const char *ver;
|
||||||
|
|
||||||
|
int *mapi_version;
|
||||||
|
|
||||||
|
mod_basename = rb_basename(path);
|
||||||
|
|
||||||
|
#ifdef CHARYBDIS_PROFILE
|
||||||
|
tmpptr = dlopen(path, RTLD_NOW | RTLD_LOCAL | RTLD_PROFILE);
|
||||||
|
#else
|
||||||
|
tmpptr = dlopen(path, RTLD_NOW | RTLD_LOCAL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(tmpptr == NULL)
|
||||||
|
{
|
||||||
|
const char *err = dlerror();
|
||||||
|
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Error loading module %s: %s", mod_basename, err);
|
||||||
|
ilog(L_MAIN, "Error loading module %s: %s", mod_basename, err);
|
||||||
|
rb_free(mod_basename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _mheader is actually a struct mapi_mheader_*, but mapi_version
|
||||||
|
* is always the first member of this structure, so we treate it
|
||||||
|
* as a single int in order to determine the API version.
|
||||||
|
* -larne.
|
||||||
|
*/
|
||||||
|
mapi_version = (int *) dlsym(tmpptr, "_mheader");
|
||||||
|
if((mapi_version == NULL
|
||||||
|
&& (mapi_version = (int *) dlsym(tmpptr, "__mheader")) == NULL)
|
||||||
|
|| MAPI_MAGIC(*mapi_version) != MAPI_MAGIC_HDR)
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Data format error: module %s has no MAPI header.",
|
||||||
|
mod_basename);
|
||||||
|
ilog(L_MAIN, "Data format error: module %s has no MAPI header.", mod_basename);
|
||||||
|
(void) dlclose(tmpptr);
|
||||||
|
rb_free(mod_basename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (MAPI_VERSION(*mapi_version))
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
struct mapi_mheader_av1 *mheader = (struct mapi_mheader_av1 *)(void *)mapi_version; /* see above */
|
||||||
|
if(mheader->mapi_register && (mheader->mapi_register() == -1))
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "Module %s indicated failure during load.",
|
||||||
|
mod_basename);
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Module %s indicated failure during load.",
|
||||||
|
mod_basename);
|
||||||
|
dlclose(tmpptr);
|
||||||
|
rb_free(mod_basename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(mheader->mapi_command_list)
|
||||||
|
{
|
||||||
|
struct Message **m;
|
||||||
|
for (m = mheader->mapi_command_list; *m; ++m)
|
||||||
|
mod_add_cmd(*m);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mheader->mapi_hook_list)
|
||||||
|
{
|
||||||
|
mapi_hlist_av1 *m;
|
||||||
|
for (m = mheader->mapi_hook_list; m->hapi_name; ++m)
|
||||||
|
*m->hapi_id = register_hook(m->hapi_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mheader->mapi_hfn_list)
|
||||||
|
{
|
||||||
|
mapi_hfn_list_av1 *m;
|
||||||
|
for (m = mheader->mapi_hfn_list; m->hapi_name; ++m)
|
||||||
|
add_hook(m->hapi_name, m->fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
ver = mheader->mapi_module_version;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
ilog(L_MAIN, "Module %s has unknown/unsupported MAPI version %d.",
|
||||||
|
mod_basename, MAPI_VERSION(*mapi_version));
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Module %s has unknown/unsupported MAPI version %d.",
|
||||||
|
mod_basename, *mapi_version);
|
||||||
|
dlclose(tmpptr);
|
||||||
|
rb_free(mod_basename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ver == NULL)
|
||||||
|
ver = unknown_ver;
|
||||||
|
|
||||||
|
increase_modlist();
|
||||||
|
|
||||||
|
modlist[num_mods] = rb_malloc(sizeof(struct module));
|
||||||
|
modlist[num_mods]->address = tmpptr;
|
||||||
|
modlist[num_mods]->version = ver;
|
||||||
|
modlist[num_mods]->core = core;
|
||||||
|
modlist[num_mods]->name = rb_strdup(mod_basename);
|
||||||
|
modlist[num_mods]->mapi_header = mapi_version;
|
||||||
|
modlist[num_mods]->mapi_version = MAPI_VERSION(*mapi_version);
|
||||||
|
num_mods++;
|
||||||
|
|
||||||
|
if(warn == 1)
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Module %s [version: %s; MAPI version: %d] loaded at 0x%lx",
|
||||||
|
mod_basename, ver, MAPI_VERSION(*mapi_version),
|
||||||
|
(unsigned long) tmpptr);
|
||||||
|
ilog(L_MAIN, "Module %s [version: %s; MAPI version: %d] loaded at 0x%lx",
|
||||||
|
mod_basename, ver, MAPI_VERSION(*mapi_version), (unsigned long) tmpptr);
|
||||||
|
}
|
||||||
|
rb_free(mod_basename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* increase_modlist
|
||||||
|
*
|
||||||
|
* inputs - NONE
|
||||||
|
* output - NONE
|
||||||
|
* side effects - expand the size of modlist if necessary
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
increase_modlist(void)
|
||||||
|
{
|
||||||
|
struct module **new_modlist = NULL;
|
||||||
|
|
||||||
|
if((num_mods + 1) < max_mods)
|
||||||
|
return;
|
||||||
|
|
||||||
|
new_modlist = (struct module **) rb_malloc(sizeof(struct module *) *
|
||||||
|
(max_mods + MODS_INCREMENT));
|
||||||
|
memcpy((void *) new_modlist, (void *) modlist, sizeof(struct module *) * num_mods);
|
||||||
|
|
||||||
|
rb_free(modlist);
|
||||||
|
modlist = new_modlist;
|
||||||
|
max_mods += MODS_INCREMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* STATIC_MODULES */
|
||||||
|
|
||||||
|
/* load_all_modules()
|
||||||
|
*
|
||||||
|
* input -
|
||||||
|
* output -
|
||||||
|
* side effects - all the msgtabs are added for static modules
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
load_all_modules(int warn)
|
||||||
|
{
|
||||||
|
load_static_modules();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* STATIC_MODULES */
|
2721
src/newconf.c
Normal file
2721
src/newconf.c
Normal file
File diff suppressed because it is too large
Load diff
755
src/parse.c
Normal file
755
src/parse.c
Normal file
|
@ -0,0 +1,755 @@
|
||||||
|
/*
|
||||||
|
* charybdis: an advanced ircd.
|
||||||
|
* parse.c: The message parser.
|
||||||
|
*
|
||||||
|
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||||
|
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||||
|
* Copyright (C) 2002-2005 ircd-ratbox development team
|
||||||
|
* Copyright (C) 2007 William Pitcock
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: parse.c 3177 2007-02-01 00:19:14Z jilles $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "parse.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "channel.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "match.h"
|
||||||
|
#include "ircd.h"
|
||||||
|
#include "numeric.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "s_stats.h"
|
||||||
|
#include "send.h"
|
||||||
|
#include "msg.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "s_serv.h"
|
||||||
|
#include "packet.h"
|
||||||
|
#include "s_assert.h"
|
||||||
|
|
||||||
|
static struct Dictionary *cmd_dict = NULL;
|
||||||
|
struct Dictionary *alias_dict = NULL;
|
||||||
|
struct Dictionary *fakechannel_dict = NULL;
|
||||||
|
|
||||||
|
/* parv[0] is not used, and parv[LAST] == NULL */
|
||||||
|
static char *para[MAXPARA + 2];
|
||||||
|
|
||||||
|
static void cancel_clients(struct Client *, struct Client *);
|
||||||
|
static void remove_unknown(struct Client *, char *, char *);
|
||||||
|
|
||||||
|
static void do_numeric(char[], struct Client *, struct Client *, int, char **);
|
||||||
|
static void do_alias(struct alias_entry *, struct Client *, char *);
|
||||||
|
|
||||||
|
static int handle_command(struct Message *, struct Client *, struct Client *, int, const char**);
|
||||||
|
|
||||||
|
static char buffer[1024];
|
||||||
|
|
||||||
|
/* turn a string into a parc/parv pair */
|
||||||
|
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
string_to_array(char *string, char **parv)
|
||||||
|
{
|
||||||
|
char *p, *buf = string;
|
||||||
|
int x = 1;
|
||||||
|
|
||||||
|
parv[x] = NULL;
|
||||||
|
while (*buf == ' ') /* skip leading spaces */
|
||||||
|
buf++;
|
||||||
|
if(*buf == '\0') /* ignore all-space args */
|
||||||
|
return x;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(*buf == ':') /* Last parameter */
|
||||||
|
{
|
||||||
|
buf++;
|
||||||
|
parv[x++] = buf;
|
||||||
|
parv[x] = NULL;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parv[x++] = buf;
|
||||||
|
parv[x] = NULL;
|
||||||
|
if((p = strchr(buf, ' ')) != NULL)
|
||||||
|
{
|
||||||
|
*p++ = '\0';
|
||||||
|
buf = p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
while (*buf == ' ')
|
||||||
|
buf++;
|
||||||
|
if(*buf == '\0')
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
/* we can go upto parv[MAXPARA], as parv[0] is skipped */
|
||||||
|
while (x < MAXPARA);
|
||||||
|
|
||||||
|
if(*p == ':')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
parv[x++] = p;
|
||||||
|
parv[x] = NULL;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse()
|
||||||
|
*
|
||||||
|
* given a raw buffer, parses it and generates parv and parc
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
parse(struct Client *client_p, char *pbuffer, char *bufend)
|
||||||
|
{
|
||||||
|
struct Client *from = client_p;
|
||||||
|
char *sender;
|
||||||
|
char *ch;
|
||||||
|
char *s;
|
||||||
|
char *end;
|
||||||
|
int i = 1;
|
||||||
|
char *numeric = 0;
|
||||||
|
struct Message *mptr;
|
||||||
|
|
||||||
|
s_assert(MyConnect(client_p));
|
||||||
|
s_assert(client_p->localClient->F != NULL);
|
||||||
|
if(IsAnyDead(client_p))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (ch = pbuffer; *ch == ' '; ch++) /* skip spaces */
|
||||||
|
/* null statement */ ;
|
||||||
|
|
||||||
|
para[0] = from->name;
|
||||||
|
|
||||||
|
if(*ch == ':')
|
||||||
|
{
|
||||||
|
ch++;
|
||||||
|
|
||||||
|
/* point sender to the sender param */
|
||||||
|
sender = ch;
|
||||||
|
|
||||||
|
if((s = strchr(ch, ' ')))
|
||||||
|
{
|
||||||
|
*s = '\0';
|
||||||
|
s++;
|
||||||
|
ch = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*sender && IsServer(client_p))
|
||||||
|
{
|
||||||
|
from = find_client(sender);
|
||||||
|
|
||||||
|
/* didnt find any matching client, issue a kill */
|
||||||
|
if(from == NULL)
|
||||||
|
{
|
||||||
|
ServerStats.is_unpf++;
|
||||||
|
remove_unknown(client_p, sender, pbuffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
para[0] = from->name;
|
||||||
|
|
||||||
|
/* fake direction, hmm. */
|
||||||
|
if(from->from != client_p)
|
||||||
|
{
|
||||||
|
ServerStats.is_wrdi++;
|
||||||
|
cancel_clients(client_p, from);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (*ch == ' ')
|
||||||
|
ch++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*ch == '\0')
|
||||||
|
{
|
||||||
|
ServerStats.is_empt++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* at this point there must be some sort of command parameter */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract the command code from the packet. Point s to the end
|
||||||
|
* of the command code and calculate the length using pointer
|
||||||
|
* arithmetic. Note: only need length for numerics and *all*
|
||||||
|
* numerics must have parameters and thus a space after the command
|
||||||
|
* code. -avalon
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* EOB is 3 chars long but is not a numeric */
|
||||||
|
|
||||||
|
if(*(ch + 3) == ' ' && /* ok, lets see if its a possible numeric.. */
|
||||||
|
IsDigit(*ch) && IsDigit(*(ch + 1)) && IsDigit(*(ch + 2)))
|
||||||
|
{
|
||||||
|
mptr = NULL;
|
||||||
|
numeric = ch;
|
||||||
|
ServerStats.is_num++;
|
||||||
|
s = ch + 3; /* I know this is ' ' from above if */
|
||||||
|
*s++ = '\0'; /* blow away the ' ', and point s to next part */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int ii = 0;
|
||||||
|
|
||||||
|
if((s = strchr(ch, ' ')))
|
||||||
|
*s++ = '\0';
|
||||||
|
|
||||||
|
mptr = irc_dictionary_retrieve(cmd_dict, ch);
|
||||||
|
|
||||||
|
/* no command or its encap only, error */
|
||||||
|
if(!mptr || !mptr->cmd)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Note: Give error message *only* to recognized
|
||||||
|
* persons. It's a nightmare situation to have
|
||||||
|
* two programs sending "Unknown command"'s or
|
||||||
|
* equivalent to each other at full blast....
|
||||||
|
* If it has got to person state, it at least
|
||||||
|
* seems to be well behaving. Perhaps this message
|
||||||
|
* should never be generated, though... --msa
|
||||||
|
* Hm, when is the buffer empty -- if a command
|
||||||
|
* code has been found ?? -Armin
|
||||||
|
*/
|
||||||
|
if(pbuffer[0] != '\0')
|
||||||
|
{
|
||||||
|
if (IsPerson(client_p))
|
||||||
|
{
|
||||||
|
struct alias_entry *aptr = irc_dictionary_retrieve(alias_dict, ch);
|
||||||
|
if (aptr != NULL)
|
||||||
|
{
|
||||||
|
do_alias(aptr, client_p, s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(IsPerson(from))
|
||||||
|
{
|
||||||
|
sendto_one(from, form_str(ERR_UNKNOWNCOMMAND),
|
||||||
|
me.name, from->name, ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ServerStats.is_unco++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ii = bufend - ((s) ? s : ch);
|
||||||
|
mptr->bytes += ii;
|
||||||
|
}
|
||||||
|
|
||||||
|
end = bufend - 1;
|
||||||
|
|
||||||
|
/* XXX this should be done before parse() is called */
|
||||||
|
if(*end == '\n')
|
||||||
|
*end-- = '\0';
|
||||||
|
if(*end == '\r')
|
||||||
|
*end = '\0';
|
||||||
|
|
||||||
|
if(s != NULL)
|
||||||
|
i = string_to_array(s, para);
|
||||||
|
|
||||||
|
if(mptr == NULL)
|
||||||
|
{
|
||||||
|
do_numeric(numeric, client_p, from, i, para);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(handle_command(mptr, client_p, from, i, /* XXX discards const!!! */ (const char **)(void *)para) < -1)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
for (p = pbuffer; p <= end; p += 8)
|
||||||
|
{
|
||||||
|
/* HACK HACK */
|
||||||
|
/* Its expected this nasty code can be removed
|
||||||
|
* or rewritten later if still needed.
|
||||||
|
*/
|
||||||
|
if((unsigned long) (p + 8) > (unsigned long) end)
|
||||||
|
{
|
||||||
|
for (; p <= end; p++)
|
||||||
|
{
|
||||||
|
ilog(L_MAIN, "%02x |%c", p[0], p[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ilog(L_MAIN,
|
||||||
|
"%02x %02x %02x %02x %02x %02x %02x %02x |%c%c%c%c%c%c%c%c",
|
||||||
|
p[0], p[1], p[2], p[3], p[4], p[5],
|
||||||
|
p[6], p[7], p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* handle_command
|
||||||
|
*
|
||||||
|
* inputs - pointer to message block
|
||||||
|
* - pointer to client
|
||||||
|
* - pointer to client message is from
|
||||||
|
* - count of number of args
|
||||||
|
* - pointer to argv[] array
|
||||||
|
* output - -1 if error from server
|
||||||
|
* side effects -
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
handle_command(struct Message *mptr, struct Client *client_p,
|
||||||
|
struct Client *from, int i, const char** hpara)
|
||||||
|
{
|
||||||
|
struct MessageEntry ehandler;
|
||||||
|
MessageHandler handler = 0;
|
||||||
|
char squitreason[80];
|
||||||
|
|
||||||
|
if(IsAnyDead(client_p))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(IsServer(client_p))
|
||||||
|
mptr->rcount++;
|
||||||
|
|
||||||
|
mptr->count++;
|
||||||
|
|
||||||
|
/* New patch to avoid server flooding from unregistered connects
|
||||||
|
- Pie-Man 07/27/2000 */
|
||||||
|
|
||||||
|
if(!IsRegistered(client_p))
|
||||||
|
{
|
||||||
|
/* if its from a possible server connection
|
||||||
|
* ignore it.. more than likely its a header thats sneaked through
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(IsAnyServer(client_p) && !(mptr->flags & MFLG_UNREG))
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ehandler = mptr->handlers[from->handler];
|
||||||
|
handler = ehandler.handler;
|
||||||
|
|
||||||
|
/* check right amount of params is passed... --is */
|
||||||
|
if(i < ehandler.min_para ||
|
||||||
|
(ehandler.min_para && EmptyString(hpara[ehandler.min_para - 1])))
|
||||||
|
{
|
||||||
|
if(!IsServer(client_p))
|
||||||
|
{
|
||||||
|
sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
|
||||||
|
me.name,
|
||||||
|
EmptyString(client_p->name) ? "*" : client_p->name,
|
||||||
|
mptr->cmd);
|
||||||
|
if(MyClient(client_p))
|
||||||
|
return (1);
|
||||||
|
else
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Dropping server %s due to (invalid) command '%s'"
|
||||||
|
" with only %d arguments (expecting %d).",
|
||||||
|
client_p->name, mptr->cmd, i, ehandler.min_para);
|
||||||
|
ilog(L_SERVER,
|
||||||
|
"Insufficient parameters (%d < %d) for command '%s' from %s.",
|
||||||
|
i, ehandler.min_para, mptr->cmd, client_p->name);
|
||||||
|
rb_snprintf(squitreason, sizeof squitreason,
|
||||||
|
"Insufficient parameters (%d < %d) for command '%s'",
|
||||||
|
i, ehandler.min_para, mptr->cmd);
|
||||||
|
exit_client(client_p, client_p, client_p, squitreason);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
(*handler) (client_p, from, i, hpara);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
handle_encap(struct Client *client_p, struct Client *source_p,
|
||||||
|
const char *command, int parc, const char *parv[])
|
||||||
|
{
|
||||||
|
struct Message *mptr;
|
||||||
|
struct MessageEntry ehandler;
|
||||||
|
MessageHandler handler = 0;
|
||||||
|
|
||||||
|
mptr = irc_dictionary_retrieve(cmd_dict, command);
|
||||||
|
|
||||||
|
if(mptr == NULL || mptr->cmd == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ehandler = mptr->handlers[ENCAP_HANDLER];
|
||||||
|
handler = ehandler.handler;
|
||||||
|
|
||||||
|
if(parc < ehandler.min_para ||
|
||||||
|
(ehandler.min_para && EmptyString(parv[ehandler.min_para - 1])))
|
||||||
|
return;
|
||||||
|
|
||||||
|
(*handler) (client_p, source_p, parc, parv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* clear_hash_parse()
|
||||||
|
*
|
||||||
|
* inputs -
|
||||||
|
* output - NONE
|
||||||
|
* side effects - MUST MUST be called at startup ONCE before
|
||||||
|
* any other keyword hash routine is used.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clear_hash_parse()
|
||||||
|
{
|
||||||
|
cmd_dict = irc_dictionary_create(strcasecmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mod_add_cmd
|
||||||
|
*
|
||||||
|
* inputs - command name
|
||||||
|
* - pointer to struct Message
|
||||||
|
* output - none
|
||||||
|
* side effects - load this one command name
|
||||||
|
* msg->count msg->bytes is modified in place, in
|
||||||
|
* modules address space. Might not want to do that...
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mod_add_cmd(struct Message *msg)
|
||||||
|
{
|
||||||
|
s_assert(msg != NULL);
|
||||||
|
if(msg == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (irc_dictionary_find(cmd_dict, msg->cmd) != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
msg->count = 0;
|
||||||
|
msg->rcount = 0;
|
||||||
|
msg->bytes = 0;
|
||||||
|
|
||||||
|
irc_dictionary_add(cmd_dict, msg->cmd, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mod_del_cmd
|
||||||
|
*
|
||||||
|
* inputs - command name
|
||||||
|
* output - none
|
||||||
|
* side effects - unload this one command name
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mod_del_cmd(struct Message *msg)
|
||||||
|
{
|
||||||
|
s_assert(msg != NULL);
|
||||||
|
if(msg == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
irc_dictionary_delete(cmd_dict, msg->cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* report_messages
|
||||||
|
*
|
||||||
|
* inputs - pointer to client to report to
|
||||||
|
* output - NONE
|
||||||
|
* side effects - NONE
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
report_messages(struct Client *source_p)
|
||||||
|
{
|
||||||
|
struct DictionaryIter iter;
|
||||||
|
struct Message *msg;
|
||||||
|
struct alias_entry *amsg;
|
||||||
|
|
||||||
|
DICTIONARY_FOREACH(msg, &iter, cmd_dict)
|
||||||
|
{
|
||||||
|
s_assert(msg->cmd != NULL);
|
||||||
|
sendto_one_numeric(source_p, RPL_STATSCOMMANDS,
|
||||||
|
form_str(RPL_STATSCOMMANDS),
|
||||||
|
msg->cmd, msg->count,
|
||||||
|
msg->bytes, msg->rcount);
|
||||||
|
}
|
||||||
|
|
||||||
|
DICTIONARY_FOREACH(amsg, &iter, alias_dict)
|
||||||
|
{
|
||||||
|
s_assert(amsg->name != NULL);
|
||||||
|
sendto_one_numeric(source_p, RPL_STATSCOMMANDS,
|
||||||
|
form_str(RPL_STATSCOMMANDS),
|
||||||
|
amsg->name, amsg->hits, 0L, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cancel_clients()
|
||||||
|
*
|
||||||
|
* inputs - client who sent us the message, client with fake
|
||||||
|
* direction
|
||||||
|
* outputs - a given warning about the fake direction
|
||||||
|
* side effects -
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
cancel_clients(struct Client *client_p, struct Client *source_p)
|
||||||
|
{
|
||||||
|
/* ok, fake prefix happens naturally during a burst on a nick
|
||||||
|
* collision with TS5, we cant kill them because one client has to
|
||||||
|
* survive, so we just send an error.
|
||||||
|
*/
|
||||||
|
if(IsServer(source_p) || IsMe(source_p))
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_DEBUG, L_ALL,
|
||||||
|
"Message for %s[%s] from %s",
|
||||||
|
source_p->name, source_p->from->name,
|
||||||
|
client_p->name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_DEBUG, L_ALL,
|
||||||
|
"Message for %s[%s@%s!%s] from %s (TS, ignored)",
|
||||||
|
source_p->name,
|
||||||
|
source_p->username,
|
||||||
|
source_p->host,
|
||||||
|
source_p->from->name,
|
||||||
|
client_p->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove_unknown()
|
||||||
|
*
|
||||||
|
* inputs - client who gave us message, supposed sender, buffer
|
||||||
|
* output -
|
||||||
|
* side effects - kills issued for clients, squits for servers
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
remove_unknown(struct Client *client_p, char *lsender, char *lbuffer)
|
||||||
|
{
|
||||||
|
int slen = strlen(lsender);
|
||||||
|
char sid[4];
|
||||||
|
struct Client *server;
|
||||||
|
|
||||||
|
/* meepfoo is a nickname (ignore)
|
||||||
|
* #XXXXXXXX is a UID (KILL)
|
||||||
|
* #XX is a SID (SQUIT)
|
||||||
|
* meep.foo is a server (SQUIT)
|
||||||
|
*/
|
||||||
|
if((IsDigit(lsender[0]) && slen == 3) ||
|
||||||
|
(strchr(lsender, '.') != NULL))
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_DEBUG, L_ALL,
|
||||||
|
"Unknown prefix (%s) from %s, Squitting %s",
|
||||||
|
lbuffer, client_p->name, lsender);
|
||||||
|
|
||||||
|
sendto_one(client_p,
|
||||||
|
":%s SQUIT %s :(Unknown prefix (%s) from %s)",
|
||||||
|
get_id(&me, client_p), lsender,
|
||||||
|
lbuffer, client_p->name);
|
||||||
|
}
|
||||||
|
else if(!IsDigit(lsender[0]))
|
||||||
|
;
|
||||||
|
else if(slen != 9)
|
||||||
|
sendto_realops_snomask(SNO_DEBUG, L_ALL,
|
||||||
|
"Invalid prefix (%s) from %s",
|
||||||
|
lbuffer, client_p->name);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(sid, lsender, 3);
|
||||||
|
sid[3] = '\0';
|
||||||
|
server = find_server(NULL, sid);
|
||||||
|
if (server != NULL && server->from == client_p)
|
||||||
|
sendto_one(client_p, ":%s KILL %s :%s (Unknown Client)",
|
||||||
|
get_id(&me, client_p), lsender, me.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* parc number of arguments ('sender' counted as one!)
|
||||||
|
* parv[1]..parv[parc-1]
|
||||||
|
* pointers to additional parameters, this is a NULL
|
||||||
|
* terminated list (parv[parc] == NULL).
|
||||||
|
*
|
||||||
|
* *WARNING*
|
||||||
|
* Numerics are mostly error reports. If there is something
|
||||||
|
* wrong with the message, just *DROP* it! Don't even think of
|
||||||
|
* sending back a neat error message -- big danger of creating
|
||||||
|
* a ping pong error message...
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
do_numeric(char numeric[], struct Client *client_p, struct Client *source_p, int parc, char *parv[])
|
||||||
|
{
|
||||||
|
struct Client *target_p;
|
||||||
|
struct Channel *chptr;
|
||||||
|
|
||||||
|
if(parc < 2 || !IsServer(source_p))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Remap low number numerics. */
|
||||||
|
if(numeric[0] == '0')
|
||||||
|
numeric[0] = '1';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare the parameter portion of the message into 'buffer'.
|
||||||
|
* (Because the buffer is twice as large as the message buffer
|
||||||
|
* for the socket, no overflow can occur here... ...on current
|
||||||
|
* assumptions--bets are off, if these are changed --msa)
|
||||||
|
* Note: if buffer is non-empty, it will begin with SPACE.
|
||||||
|
*/
|
||||||
|
if(parc > 1)
|
||||||
|
{
|
||||||
|
char *t = buffer; /* Current position within the buffer */
|
||||||
|
int i;
|
||||||
|
int tl; /* current length of presently being built string in t */
|
||||||
|
for (i = 2; i < (parc - 1); i++)
|
||||||
|
{
|
||||||
|
tl = rb_sprintf(t, " %s", parv[i]);
|
||||||
|
t += tl;
|
||||||
|
}
|
||||||
|
rb_sprintf(t, " :%s", parv[parc - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((target_p = find_client(parv[1])) != NULL)
|
||||||
|
{
|
||||||
|
if(IsMe(target_p))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We shouldn't get numerics sent to us,
|
||||||
|
* any numerics we do get indicate a bug somewhere..
|
||||||
|
*/
|
||||||
|
/* ugh. this is here because of nick collisions. when two servers
|
||||||
|
* relink, they burst each other their nicks, then perform collides.
|
||||||
|
* if there is a nick collision, BOTH servers will kill their own
|
||||||
|
* nicks, and BOTH will kill the other servers nick, which wont exist,
|
||||||
|
* because it will have been already killed by the local server.
|
||||||
|
*
|
||||||
|
* unfortunately, as we cant guarantee other servers will do the
|
||||||
|
* "right thing" on a nick collision, we have to keep both kills.
|
||||||
|
* ergo we need to ignore ERR_NOSUCHNICK. --fl_
|
||||||
|
*/
|
||||||
|
/* quick comment. This _was_ tried. i.e. assume the other servers
|
||||||
|
* will do the "right thing" and kill a nick that is colliding.
|
||||||
|
* unfortunately, it did not work. --Dianora
|
||||||
|
*/
|
||||||
|
/* note, now we send PING on server connect, we can
|
||||||
|
* also get ERR_NOSUCHSERVER..
|
||||||
|
*/
|
||||||
|
if(atoi(numeric) != ERR_NOSUCHNICK &&
|
||||||
|
atoi(numeric) != ERR_NOSUCHSERVER)
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ADMIN,
|
||||||
|
"*** %s(via %s) sent a %s numeric to me: %s",
|
||||||
|
source_p->name,
|
||||||
|
client_p->name, numeric, buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(target_p->from == client_p)
|
||||||
|
{
|
||||||
|
/* This message changed direction (nick collision?)
|
||||||
|
* ignore it.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* csircd will send out unknown umode flag for +a (admin), drop it here. */
|
||||||
|
if((atoi(numeric) == ERR_UMODEUNKNOWNFLAG) && MyClient(target_p))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Fake it for server hiding, if its our client */
|
||||||
|
sendto_one(target_p, ":%s %s %s%s",
|
||||||
|
get_id(source_p, target_p), numeric,
|
||||||
|
get_id(target_p, target_p), buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if((chptr = find_channel(parv[1])) != NULL)
|
||||||
|
sendto_channel_flags(client_p, ALL_MEMBERS, source_p, chptr,
|
||||||
|
"%s %s%s",
|
||||||
|
numeric, chptr->chname, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_alias(struct alias_entry *aptr, struct Client *source_p, char *text)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
struct Client *target_p;
|
||||||
|
|
||||||
|
if (!IsFloodDone(source_p) && source_p->localClient->receiveM > 20)
|
||||||
|
flood_endgrace(source_p);
|
||||||
|
|
||||||
|
p = strchr(aptr->target, '@');
|
||||||
|
if (p != NULL)
|
||||||
|
{
|
||||||
|
/* user@server */
|
||||||
|
target_p = find_server(NULL, p + 1);
|
||||||
|
if (target_p != NULL && IsMe(target_p))
|
||||||
|
target_p = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* nick, must be +S */
|
||||||
|
target_p = find_named_person(aptr->target);
|
||||||
|
if (target_p != NULL && !IsService(target_p))
|
||||||
|
target_p = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target_p == NULL)
|
||||||
|
{
|
||||||
|
sendto_one_numeric(source_p, ERR_SERVICESDOWN, form_str(ERR_SERVICESDOWN), aptr->target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text != NULL && *text == ':')
|
||||||
|
text++;
|
||||||
|
if (text == NULL || *text == '\0')
|
||||||
|
{
|
||||||
|
sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), me.name, source_p->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* increment the hitcounter on this alias */
|
||||||
|
aptr->hits++;
|
||||||
|
|
||||||
|
sendto_one(target_p, ":%s PRIVMSG %s :%s",
|
||||||
|
get_id(source_p, target_p),
|
||||||
|
p != NULL ? aptr->target : get_id(target_p, target_p),
|
||||||
|
text);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
m_not_oper(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
|
||||||
|
{
|
||||||
|
sendto_one_numeric(source_p, ERR_NOPRIVILEGES, form_str(ERR_NOPRIVILEGES));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
m_unregistered(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
|
||||||
|
{
|
||||||
|
/* bit of a hack.
|
||||||
|
* I don't =really= want to waste a bit in a flag
|
||||||
|
* number_of_nick_changes is only really valid after the client
|
||||||
|
* is fully registered..
|
||||||
|
*/
|
||||||
|
if(client_p->localClient->number_of_nick_changes == 0)
|
||||||
|
{
|
||||||
|
sendto_one(client_p, form_str(ERR_NOTREGISTERED), me.name);
|
||||||
|
client_p->localClient->number_of_nick_changes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
m_registered(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
|
||||||
|
{
|
||||||
|
sendto_one(client_p, form_str(ERR_ALREADYREGISTRED), me.name, source_p->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
m_ignore(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
934
src/res.c
Normal file
934
src/res.c
Normal file
|
@ -0,0 +1,934 @@
|
||||||
|
/*
|
||||||
|
* A rewrite of Darren Reeds original res.c As there is nothing
|
||||||
|
* left of Darrens original code, this is now licensed by the hybrid group.
|
||||||
|
* (Well, some of the function names are the same, and bits of the structs..)
|
||||||
|
* You can use it where it is useful, free even. Buy us a beer and stuff.
|
||||||
|
*
|
||||||
|
* The authors takes no responsibility for any damage or loss
|
||||||
|
* of property which results from the use of this software.
|
||||||
|
*
|
||||||
|
* $Id: res.c 3301 2007-03-28 15:04:06Z jilles $
|
||||||
|
* from Hybrid Id: res.c 459 2006-02-12 22:21:37Z db $
|
||||||
|
*
|
||||||
|
* July 1999 - Rewrote a bunch of stuff here. Change hostent builder code,
|
||||||
|
* added callbacks and reference counting of returned hostents.
|
||||||
|
* --Bleep (Thomas Helvey <tomh@inxpress.net>)
|
||||||
|
*
|
||||||
|
* This was all needlessly complicated for irc. Simplified. No more hostent
|
||||||
|
* All we really care about is the IP -> hostname mappings. Thats all.
|
||||||
|
*
|
||||||
|
* Apr 28, 2003 --cryogen and Dianora
|
||||||
|
*
|
||||||
|
* DNS server flooding lessened, AAAA-or-A lookup removed, ip6.int support
|
||||||
|
* removed, various robustness fixes
|
||||||
|
*
|
||||||
|
* 2006 --jilles and nenolod
|
||||||
|
*
|
||||||
|
* Resend queries to other servers if the DNS server replies with an error or
|
||||||
|
* an invalid response. Also, avoid servers that return errors or invalid
|
||||||
|
* responses.
|
||||||
|
*
|
||||||
|
* October 2012 --mr_flea
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "ircd_defs.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "ircd.h"
|
||||||
|
#include "res.h"
|
||||||
|
#include "reslib.h"
|
||||||
|
#include "match.h"
|
||||||
|
#include "numeric.h"
|
||||||
|
#include "client.h" /* SNO_* */
|
||||||
|
#include "s_assert.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "send.h"
|
||||||
|
|
||||||
|
#if (CHAR_BIT != 8)
|
||||||
|
#error this code needs to be able to address individual octets
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static PF res_readreply;
|
||||||
|
|
||||||
|
#define MAXPACKET 1024 /* rfc sez 512 but we expand names so ... */
|
||||||
|
#define RES_MAXALIASES 35 /* maximum aliases allowed */
|
||||||
|
#define RES_MAXADDRS 35 /* maximum addresses allowed */
|
||||||
|
#define AR_TTL 600 /* TTL in seconds for dns cache entries */
|
||||||
|
|
||||||
|
/* RFC 1104/1105 wasn't very helpful about what these fields
|
||||||
|
* should be named, so for now, we'll just name them this way.
|
||||||
|
* we probably should look at what named calls them or something.
|
||||||
|
*/
|
||||||
|
#define TYPE_SIZE (size_t)2
|
||||||
|
#define CLASS_SIZE (size_t)2
|
||||||
|
#define TTL_SIZE (size_t)4
|
||||||
|
#define RDLENGTH_SIZE (size_t)2
|
||||||
|
#define ANSWER_FIXED_SIZE (TYPE_SIZE + CLASS_SIZE + TTL_SIZE + RDLENGTH_SIZE)
|
||||||
|
|
||||||
|
struct reslist
|
||||||
|
{
|
||||||
|
rb_dlink_node node;
|
||||||
|
int id;
|
||||||
|
time_t ttl;
|
||||||
|
char type;
|
||||||
|
char queryname[IRCD_RES_HOSTLEN + 1]; /* name currently being queried */
|
||||||
|
char retries; /* retry counter */
|
||||||
|
char sends; /* number of sends (>1 means resent) */
|
||||||
|
time_t sentat;
|
||||||
|
time_t timeout;
|
||||||
|
int lastns; /* index of last server sent to */
|
||||||
|
struct rb_sockaddr_storage addr;
|
||||||
|
char *name;
|
||||||
|
struct DNSQuery *query; /* query callback for this request */
|
||||||
|
};
|
||||||
|
|
||||||
|
static rb_fde_t *res_fd;
|
||||||
|
static rb_dlink_list request_list = { NULL, NULL, 0 };
|
||||||
|
static int ns_failure_count[IRCD_MAXNS]; /* timeouts and invalid/failed replies */
|
||||||
|
|
||||||
|
static void rem_request(struct reslist *request);
|
||||||
|
static struct reslist *make_request(struct DNSQuery *query);
|
||||||
|
static void gethost_byname_type_fqdn(const char *name, struct DNSQuery *query,
|
||||||
|
int type);
|
||||||
|
static void do_query_name(struct DNSQuery *query, const char *name, struct reslist *request, int);
|
||||||
|
static void do_query_number(struct DNSQuery *query, const struct rb_sockaddr_storage *,
|
||||||
|
struct reslist *request);
|
||||||
|
static void query_name(struct reslist *request);
|
||||||
|
static int send_res_msg(const char *buf, int len, int count);
|
||||||
|
static void resend_query(struct reslist *request);
|
||||||
|
static int check_question(struct reslist *request, HEADER * header, char *buf, char *eob);
|
||||||
|
static int proc_answer(struct reslist *request, HEADER * header, char *, char *);
|
||||||
|
static struct reslist *find_id(int id);
|
||||||
|
static struct DNSReply *make_dnsreply(struct reslist *request);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* int
|
||||||
|
* res_ourserver(inp)
|
||||||
|
* looks up "inp" in irc_nsaddr_list[]
|
||||||
|
* returns:
|
||||||
|
* server ID or -1 for not found
|
||||||
|
* author:
|
||||||
|
* paul vixie, 29may94
|
||||||
|
* revised for ircd, cryogen(stu) may03
|
||||||
|
* slightly modified for charybdis, mr_flea oct12
|
||||||
|
*/
|
||||||
|
static int res_ourserver(const struct rb_sockaddr_storage *inp)
|
||||||
|
{
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
const struct sockaddr_in6 *v6;
|
||||||
|
const struct sockaddr_in6 *v6in = (const struct sockaddr_in6 *)inp;
|
||||||
|
#endif
|
||||||
|
const struct sockaddr_in *v4;
|
||||||
|
const struct sockaddr_in *v4in = (const struct sockaddr_in *)inp;
|
||||||
|
int ns;
|
||||||
|
|
||||||
|
for (ns = 0; ns < irc_nscount; ns++)
|
||||||
|
{
|
||||||
|
const struct rb_sockaddr_storage *srv = &irc_nsaddr_list[ns];
|
||||||
|
|
||||||
|
if (srv->ss_family != inp->ss_family)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
v6 = (const struct sockaddr_in6 *)srv;
|
||||||
|
#endif
|
||||||
|
v4 = (const struct sockaddr_in *)srv;
|
||||||
|
|
||||||
|
/* could probably just memcmp(srv, inp, srv.ss_len) here
|
||||||
|
* but we'll err on the side of caution - stu
|
||||||
|
*/
|
||||||
|
switch (srv->ss_family)
|
||||||
|
{
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
case AF_INET6:
|
||||||
|
if (v6->sin6_port == v6in->sin6_port)
|
||||||
|
if ((memcmp(&v6->sin6_addr.s6_addr, &v6in->sin6_addr.s6_addr,
|
||||||
|
sizeof(struct in6_addr)) == 0) ||
|
||||||
|
(memcmp(&v6->sin6_addr.s6_addr, &in6addr_any,
|
||||||
|
sizeof(struct in6_addr)) == 0))
|
||||||
|
{
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case AF_INET:
|
||||||
|
if (v4->sin_port == v4in->sin_port)
|
||||||
|
if ((v4->sin_addr.s_addr == INADDR_ANY)
|
||||||
|
|| (v4->sin_addr.s_addr == v4in->sin_addr.s_addr))
|
||||||
|
{
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* timeout_query_list - Remove queries from the list which have been
|
||||||
|
* there too long without being resolved.
|
||||||
|
*/
|
||||||
|
static time_t timeout_query_list(time_t now)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
rb_dlink_node *next_ptr;
|
||||||
|
struct reslist *request;
|
||||||
|
time_t next_time = 0;
|
||||||
|
time_t timeout = 0;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head)
|
||||||
|
{
|
||||||
|
request = ptr->data;
|
||||||
|
timeout = request->sentat + request->timeout;
|
||||||
|
|
||||||
|
if (now >= timeout)
|
||||||
|
{
|
||||||
|
ns_failure_count[request->lastns]++;
|
||||||
|
request->sentat = now;
|
||||||
|
request->timeout += request->timeout;
|
||||||
|
resend_query(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((next_time == 0) || timeout < next_time)
|
||||||
|
{
|
||||||
|
next_time = timeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (next_time > now) ? next_time : (now + AR_TTL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* timeout_resolver - check request list
|
||||||
|
*/
|
||||||
|
static void timeout_resolver(void *notused)
|
||||||
|
{
|
||||||
|
timeout_query_list(rb_current_time());
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ev_entry *timeout_resolver_ev = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* start_resolver - do everything we need to read the resolv.conf file
|
||||||
|
* and initialize the resolver file descriptor if needed
|
||||||
|
*/
|
||||||
|
static void start_resolver(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
irc_res_init();
|
||||||
|
for (i = 0; i < irc_nscount; i++)
|
||||||
|
ns_failure_count[i] = 0;
|
||||||
|
|
||||||
|
if (res_fd == NULL)
|
||||||
|
{
|
||||||
|
if ((res_fd = rb_socket(irc_nsaddr_list[0].ss_family, SOCK_DGRAM, 0,
|
||||||
|
"UDP resolver socket")) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* At the moment, the resolver FD data is global .. */
|
||||||
|
rb_setselect(res_fd, RB_SELECT_READ, res_readreply, NULL);
|
||||||
|
timeout_resolver_ev = rb_event_add("timeout_resolver", timeout_resolver, NULL, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_resolver - initialize resolver and resolver library
|
||||||
|
*/
|
||||||
|
void init_resolver(void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_SRAND48
|
||||||
|
srand48(rb_current_time());
|
||||||
|
#endif
|
||||||
|
start_resolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* restart_resolver - reread resolv.conf, reopen socket
|
||||||
|
*/
|
||||||
|
void restart_resolver(void)
|
||||||
|
{
|
||||||
|
rb_close(res_fd);
|
||||||
|
res_fd = NULL;
|
||||||
|
rb_event_delete(timeout_resolver_ev); /* -ddosen */
|
||||||
|
start_resolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add_local_domain - Add the domain to hostname, if it is missing
|
||||||
|
* (as suggested by eps@TOASTER.SFSU.EDU)
|
||||||
|
*/
|
||||||
|
void add_local_domain(char *hname, size_t size)
|
||||||
|
{
|
||||||
|
/* try to fix up unqualified names */
|
||||||
|
if (strchr(hname, '.') == NULL)
|
||||||
|
{
|
||||||
|
if (irc_domain[0])
|
||||||
|
{
|
||||||
|
size_t len = strlen(hname);
|
||||||
|
|
||||||
|
if ((strlen(irc_domain) + len + 2) < size)
|
||||||
|
{
|
||||||
|
hname[len++] = '.';
|
||||||
|
strcpy(hname + len, irc_domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rem_request - remove a request from the list.
|
||||||
|
* This must also free any memory that has been allocated for
|
||||||
|
* temporary storage of DNS results.
|
||||||
|
*/
|
||||||
|
static void rem_request(struct reslist *request)
|
||||||
|
{
|
||||||
|
rb_dlinkDelete(&request->node, &request_list);
|
||||||
|
rb_free(request->name);
|
||||||
|
rb_free(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make_request - Create a DNS request record for the server.
|
||||||
|
*/
|
||||||
|
static struct reslist *make_request(struct DNSQuery *query)
|
||||||
|
{
|
||||||
|
struct reslist *request = rb_malloc(sizeof(struct reslist));
|
||||||
|
|
||||||
|
request->sentat = rb_current_time();
|
||||||
|
request->retries = 3;
|
||||||
|
request->timeout = 4; /* start at 4 and exponential inc. */
|
||||||
|
request->query = query;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* generate a unique id
|
||||||
|
* NOTE: we don't have to worry about converting this to and from
|
||||||
|
* network byte order, the nameserver does not interpret this value
|
||||||
|
* and returns it unchanged
|
||||||
|
*
|
||||||
|
* we generate an id per request now (instead of per send) to allow
|
||||||
|
* late replies to be used.
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_LRAND48
|
||||||
|
do
|
||||||
|
{
|
||||||
|
request->id = (request->id + lrand48()) & 0xffff;
|
||||||
|
} while (find_id(request->id));
|
||||||
|
#else
|
||||||
|
int k = 0;
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
request->id = (request->id + k + tv.tv_usec) & 0xffff;
|
||||||
|
k++;
|
||||||
|
} while (find_id(request->id));
|
||||||
|
#endif /* HAVE_LRAND48 */
|
||||||
|
|
||||||
|
rb_dlinkAdd(request, &request->node, &request_list);
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* delete_resolver_queries - cleanup outstanding queries
|
||||||
|
* for which there no longer exist clients or conf lines.
|
||||||
|
*/
|
||||||
|
void delete_resolver_queries(const struct DNSQuery *query)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
rb_dlink_node *next_ptr;
|
||||||
|
struct reslist *request;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head)
|
||||||
|
{
|
||||||
|
if ((request = ptr->data) != NULL)
|
||||||
|
{
|
||||||
|
if (query == request->query)
|
||||||
|
rem_request(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* retryfreq - determine how many queries to wait before resending
|
||||||
|
* if there have been that many consecutive timeouts
|
||||||
|
*/
|
||||||
|
static int retryfreq(int timeouts)
|
||||||
|
{
|
||||||
|
switch (timeouts)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return 3;
|
||||||
|
case 2:
|
||||||
|
return 9;
|
||||||
|
case 3:
|
||||||
|
return 27;
|
||||||
|
case 4:
|
||||||
|
return 81;
|
||||||
|
default:
|
||||||
|
return 243;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* send_res_msg - sends msg to a nameserver.
|
||||||
|
* This should reflect /etc/resolv.conf.
|
||||||
|
* Returns number of nameserver successfully sent to
|
||||||
|
* or -1 if no successful sends.
|
||||||
|
*/
|
||||||
|
static int send_res_msg(const char *msg, int len, int rcount)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int ns;
|
||||||
|
static int retrycnt;
|
||||||
|
|
||||||
|
retrycnt++;
|
||||||
|
/* First try a nameserver that seems to work.
|
||||||
|
* Every once in a while, try a possibly broken one to check
|
||||||
|
* if it is working again.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < irc_nscount; i++)
|
||||||
|
{
|
||||||
|
ns = (i + rcount - 1) % irc_nscount;
|
||||||
|
if (ns_failure_count[ns] && retrycnt % retryfreq(ns_failure_count[ns]))
|
||||||
|
continue;
|
||||||
|
if (sendto(rb_get_fd(res_fd), msg, len, 0,
|
||||||
|
(struct sockaddr *)&(irc_nsaddr_list[ns]),
|
||||||
|
GET_SS_LEN(&irc_nsaddr_list[ns])) == len)
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No known working nameservers, try some broken one. */
|
||||||
|
for (i = 0; i < irc_nscount; i++)
|
||||||
|
{
|
||||||
|
ns = (i + rcount - 1) % irc_nscount;
|
||||||
|
if (!ns_failure_count[ns])
|
||||||
|
continue;
|
||||||
|
if (sendto(rb_get_fd(res_fd), msg, len, 0,
|
||||||
|
(struct sockaddr *)&(irc_nsaddr_list[ns]),
|
||||||
|
GET_SS_LEN(&irc_nsaddr_list[ns])) == len)
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find_id - find a dns request id (id is determined by dn_mkquery)
|
||||||
|
*/
|
||||||
|
static struct reslist *find_id(int id)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
struct reslist *request;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, request_list.head)
|
||||||
|
{
|
||||||
|
request = ptr->data;
|
||||||
|
|
||||||
|
if (request->id == id)
|
||||||
|
return (request);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gethost_byname_type - get host address from name, adding domain if needed
|
||||||
|
*/
|
||||||
|
void gethost_byname_type(const char *name, struct DNSQuery *query, int type)
|
||||||
|
{
|
||||||
|
char fqdn[IRCD_RES_HOSTLEN + 1];
|
||||||
|
assert(name != 0);
|
||||||
|
|
||||||
|
rb_strlcpy(fqdn, name, sizeof fqdn);
|
||||||
|
add_local_domain(fqdn, IRCD_RES_HOSTLEN);
|
||||||
|
gethost_byname_type_fqdn(fqdn, query, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gethost_byname_type_fqdn - get host address from fqdn
|
||||||
|
*/
|
||||||
|
static void gethost_byname_type_fqdn(const char *name, struct DNSQuery *query,
|
||||||
|
int type)
|
||||||
|
{
|
||||||
|
assert(name != 0);
|
||||||
|
do_query_name(query, name, NULL, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gethost_byaddr - get host name from address
|
||||||
|
*/
|
||||||
|
void gethost_byaddr(const struct rb_sockaddr_storage *addr, struct DNSQuery *query)
|
||||||
|
{
|
||||||
|
do_query_number(query, addr, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_query_name - nameserver lookup name
|
||||||
|
*/
|
||||||
|
static void do_query_name(struct DNSQuery *query, const char *name, struct reslist *request,
|
||||||
|
int type)
|
||||||
|
{
|
||||||
|
if (request == NULL)
|
||||||
|
{
|
||||||
|
request = make_request(query);
|
||||||
|
request->name = rb_strdup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_strlcpy(request->queryname, name, sizeof(request->queryname));
|
||||||
|
request->type = type;
|
||||||
|
query_name(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_query_number - Use this to do reverse IP# lookups.
|
||||||
|
*/
|
||||||
|
static void do_query_number(struct DNSQuery *query, const struct rb_sockaddr_storage *addr,
|
||||||
|
struct reslist *request)
|
||||||
|
{
|
||||||
|
const unsigned char *cp;
|
||||||
|
|
||||||
|
if (request == NULL)
|
||||||
|
{
|
||||||
|
request = make_request(query);
|
||||||
|
memcpy(&request->addr, addr, sizeof(struct rb_sockaddr_storage));
|
||||||
|
request->name = (char *)rb_malloc(IRCD_RES_HOSTLEN + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr->ss_family == AF_INET)
|
||||||
|
{
|
||||||
|
const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
|
||||||
|
cp = (const unsigned char *)&v4->sin_addr.s_addr;
|
||||||
|
|
||||||
|
rb_sprintf(request->queryname, "%u.%u.%u.%u.in-addr.arpa", (unsigned int)(cp[3]),
|
||||||
|
(unsigned int)(cp[2]), (unsigned int)(cp[1]), (unsigned int)(cp[0]));
|
||||||
|
}
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
else if (addr->ss_family == AF_INET6)
|
||||||
|
{
|
||||||
|
const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
|
||||||
|
cp = (const unsigned char *)&v6->sin6_addr.s6_addr;
|
||||||
|
|
||||||
|
(void)sprintf(request->queryname, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
|
||||||
|
"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa",
|
||||||
|
(unsigned int)(cp[15] & 0xf), (unsigned int)(cp[15] >> 4),
|
||||||
|
(unsigned int)(cp[14] & 0xf), (unsigned int)(cp[14] >> 4),
|
||||||
|
(unsigned int)(cp[13] & 0xf), (unsigned int)(cp[13] >> 4),
|
||||||
|
(unsigned int)(cp[12] & 0xf), (unsigned int)(cp[12] >> 4),
|
||||||
|
(unsigned int)(cp[11] & 0xf), (unsigned int)(cp[11] >> 4),
|
||||||
|
(unsigned int)(cp[10] & 0xf), (unsigned int)(cp[10] >> 4),
|
||||||
|
(unsigned int)(cp[9] & 0xf), (unsigned int)(cp[9] >> 4),
|
||||||
|
(unsigned int)(cp[8] & 0xf), (unsigned int)(cp[8] >> 4),
|
||||||
|
(unsigned int)(cp[7] & 0xf), (unsigned int)(cp[7] >> 4),
|
||||||
|
(unsigned int)(cp[6] & 0xf), (unsigned int)(cp[6] >> 4),
|
||||||
|
(unsigned int)(cp[5] & 0xf), (unsigned int)(cp[5] >> 4),
|
||||||
|
(unsigned int)(cp[4] & 0xf), (unsigned int)(cp[4] >> 4),
|
||||||
|
(unsigned int)(cp[3] & 0xf), (unsigned int)(cp[3] >> 4),
|
||||||
|
(unsigned int)(cp[2] & 0xf), (unsigned int)(cp[2] >> 4),
|
||||||
|
(unsigned int)(cp[1] & 0xf), (unsigned int)(cp[1] >> 4),
|
||||||
|
(unsigned int)(cp[0] & 0xf), (unsigned int)(cp[0] >> 4));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
request->type = T_PTR;
|
||||||
|
query_name(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* query_name - generate a query based on class, type and name.
|
||||||
|
*/
|
||||||
|
static void query_name(struct reslist *request)
|
||||||
|
{
|
||||||
|
char buf[MAXPACKET];
|
||||||
|
int request_len = 0;
|
||||||
|
int ns;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
if ((request_len =
|
||||||
|
irc_res_mkquery(request->queryname, C_IN, request->type, (unsigned char *)buf, sizeof(buf))) > 0)
|
||||||
|
{
|
||||||
|
HEADER *header = (HEADER *)(void *)buf;
|
||||||
|
header->id = request->id;
|
||||||
|
++request->sends;
|
||||||
|
|
||||||
|
ns = send_res_msg(buf, request_len, request->sends);
|
||||||
|
if (ns != -1)
|
||||||
|
request->lastns = ns;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resend_query(struct reslist *request)
|
||||||
|
{
|
||||||
|
if (--request->retries <= 0)
|
||||||
|
{
|
||||||
|
(*request->query->callback) (request->query->ptr, NULL);
|
||||||
|
rem_request(request);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (request->type)
|
||||||
|
{
|
||||||
|
case T_PTR:
|
||||||
|
do_query_number(NULL, &request->addr, request);
|
||||||
|
break;
|
||||||
|
case T_A:
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
case T_AAAA:
|
||||||
|
#endif
|
||||||
|
do_query_name(NULL, request->name, request, request->type);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check_question - check if the reply really belongs to the
|
||||||
|
* name we queried (to guard against late replies from previous
|
||||||
|
* queries with the same id).
|
||||||
|
*/
|
||||||
|
static int check_question(struct reslist *request, HEADER * header, char *buf, char *eob)
|
||||||
|
{
|
||||||
|
char hostbuf[IRCD_RES_HOSTLEN + 1]; /* working buffer */
|
||||||
|
unsigned char *current; /* current position in buf */
|
||||||
|
int n; /* temp count */
|
||||||
|
|
||||||
|
current = (unsigned char *)buf + sizeof(HEADER);
|
||||||
|
if (header->qdcount != 1)
|
||||||
|
return 0;
|
||||||
|
n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob, current, hostbuf,
|
||||||
|
sizeof(hostbuf));
|
||||||
|
if (n <= 0)
|
||||||
|
return 0;
|
||||||
|
if (strcasecmp(hostbuf, request->queryname))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* proc_answer - process name server reply
|
||||||
|
*/
|
||||||
|
static int proc_answer(struct reslist *request, HEADER * header, char *buf, char *eob)
|
||||||
|
{
|
||||||
|
char hostbuf[IRCD_RES_HOSTLEN + 100]; /* working buffer */
|
||||||
|
unsigned char *current; /* current position in buf */
|
||||||
|
int type; /* answer type */
|
||||||
|
int n; /* temp count */
|
||||||
|
int rd_length;
|
||||||
|
struct sockaddr_in *v4; /* conversion */
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
struct sockaddr_in6 *v6;
|
||||||
|
#endif
|
||||||
|
current = (unsigned char *)buf + sizeof(HEADER);
|
||||||
|
|
||||||
|
for (; header->qdcount > 0; --header->qdcount)
|
||||||
|
{
|
||||||
|
if ((n = irc_dn_skipname(current, (unsigned char *)eob)) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
current += (size_t) n + QFIXEDSZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* process each answer sent to us blech.
|
||||||
|
*/
|
||||||
|
while (header->ancount > 0 && (char *)current < eob)
|
||||||
|
{
|
||||||
|
header->ancount--;
|
||||||
|
|
||||||
|
n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob, current, hostbuf,
|
||||||
|
sizeof(hostbuf));
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* broken message
|
||||||
|
*/
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
else if (n == 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* no more answers left
|
||||||
|
*/
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
hostbuf[IRCD_RES_HOSTLEN] = '\0';
|
||||||
|
|
||||||
|
/* With Address arithmetic you have to be very anal
|
||||||
|
* this code was not working on alpha due to that
|
||||||
|
* (spotted by rodder/jailbird/dianora)
|
||||||
|
*/
|
||||||
|
current += (size_t) n;
|
||||||
|
|
||||||
|
if (!(((char *)current + ANSWER_FIXED_SIZE) < eob))
|
||||||
|
break;
|
||||||
|
|
||||||
|
type = irc_ns_get16(current);
|
||||||
|
current += TYPE_SIZE;
|
||||||
|
|
||||||
|
(void) irc_ns_get16(current);
|
||||||
|
current += CLASS_SIZE;
|
||||||
|
|
||||||
|
request->ttl = irc_ns_get32(current);
|
||||||
|
current += TTL_SIZE;
|
||||||
|
|
||||||
|
rd_length = irc_ns_get16(current);
|
||||||
|
current += RDLENGTH_SIZE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait to set request->type until we verify this structure
|
||||||
|
*/
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case T_A:
|
||||||
|
if (request->type != T_A)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check for invalid rd_length or too many addresses
|
||||||
|
*/
|
||||||
|
if (rd_length != sizeof(struct in_addr))
|
||||||
|
return (0);
|
||||||
|
v4 = (struct sockaddr_in *)&request->addr;
|
||||||
|
SET_SS_LEN(&request->addr, sizeof(struct sockaddr_in));
|
||||||
|
v4->sin_family = AF_INET;
|
||||||
|
memcpy(&v4->sin_addr, current, sizeof(struct in_addr));
|
||||||
|
return (1);
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
case T_AAAA:
|
||||||
|
if (request->type != T_AAAA)
|
||||||
|
return (0);
|
||||||
|
if (rd_length != sizeof(struct in6_addr))
|
||||||
|
return (0);
|
||||||
|
SET_SS_LEN(&request->addr, sizeof(struct sockaddr_in6));
|
||||||
|
v6 = (struct sockaddr_in6 *)&request->addr;
|
||||||
|
v6->sin6_family = AF_INET6;
|
||||||
|
memcpy(&v6->sin6_addr, current, sizeof(struct in6_addr));
|
||||||
|
return (1);
|
||||||
|
#endif
|
||||||
|
case T_PTR:
|
||||||
|
if (request->type != T_PTR)
|
||||||
|
return (0);
|
||||||
|
n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob, current,
|
||||||
|
hostbuf, sizeof(hostbuf));
|
||||||
|
if (n < 0)
|
||||||
|
return (0); /* broken message */
|
||||||
|
else if (n == 0)
|
||||||
|
return (0); /* no more answers left */
|
||||||
|
|
||||||
|
rb_strlcpy(request->name, hostbuf, IRCD_RES_HOSTLEN + 1);
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
case T_CNAME:
|
||||||
|
/* real answer will follow */
|
||||||
|
current += rd_length;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* XXX I'd rather just throw away the entire bogus thing
|
||||||
|
* but its possible its just a broken nameserver with still
|
||||||
|
* valid answers. But lets do some rudimentary logging for now...
|
||||||
|
*/
|
||||||
|
ilog(L_MAIN, "irc_res.c bogus type %d", type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* res_read_single_reply - read a dns reply from the nameserver and process it.
|
||||||
|
* Return value: 1 if a packet was read, 0 otherwise
|
||||||
|
*/
|
||||||
|
static int res_read_single_reply(rb_fde_t *F, void *data)
|
||||||
|
{
|
||||||
|
char buf[sizeof(HEADER) + MAXPACKET]
|
||||||
|
/* Sparc and alpha need 16bit-alignment for accessing header->id
|
||||||
|
* (which is uint16_t). Because of the header = (HEADER*) buf;
|
||||||
|
* lateron, this is neeeded. --FaUl
|
||||||
|
*/
|
||||||
|
#if defined(__sparc__) || defined(__alpha__)
|
||||||
|
__attribute__ ((aligned(16)))
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
HEADER *header;
|
||||||
|
struct reslist *request = NULL;
|
||||||
|
struct DNSReply *reply = NULL;
|
||||||
|
int rc;
|
||||||
|
int answer_count;
|
||||||
|
socklen_t len = sizeof(struct rb_sockaddr_storage);
|
||||||
|
struct rb_sockaddr_storage lsin;
|
||||||
|
int ns;
|
||||||
|
|
||||||
|
rc = recvfrom(rb_get_fd(F), buf, sizeof(buf), 0, (struct sockaddr *)&lsin, &len);
|
||||||
|
|
||||||
|
/* No packet */
|
||||||
|
if (rc == 0 || rc == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Too small */
|
||||||
|
if (rc <= (int)(sizeof(HEADER)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* convert DNS reply reader from Network byte order to CPU byte order.
|
||||||
|
*/
|
||||||
|
header = (HEADER *)(void *)buf;
|
||||||
|
header->ancount = ntohs(header->ancount);
|
||||||
|
header->qdcount = ntohs(header->qdcount);
|
||||||
|
header->nscount = ntohs(header->nscount);
|
||||||
|
header->arcount = ntohs(header->arcount);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* response for an id which we have already received an answer for
|
||||||
|
* just ignore this response.
|
||||||
|
*/
|
||||||
|
if (0 == (request = find_id(header->id)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check against possibly fake replies
|
||||||
|
*/
|
||||||
|
ns = res_ourserver(&lsin);
|
||||||
|
if (ns == -1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ns != request->lastns)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We'll accept the late reply, but penalize it a little more to make
|
||||||
|
* sure a laggy server doesn't end up favored.
|
||||||
|
*/
|
||||||
|
ns_failure_count[ns] += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!check_question(request, header, buf, buf + rc))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if ((header->rcode != NO_ERRORS) || (header->ancount == 0))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* RFC 2136 states that in the event of a server returning SERVFAIL
|
||||||
|
* or NOTIMP, the request should be resent to the next server.
|
||||||
|
* Additionally, if the server refuses our query, resend it as well.
|
||||||
|
* -- mr_flea
|
||||||
|
*/
|
||||||
|
if (SERVFAIL == header->rcode || NOTIMP == header->rcode ||
|
||||||
|
REFUSED == header->rcode)
|
||||||
|
{
|
||||||
|
ns_failure_count[ns]++;
|
||||||
|
resend_query(request);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Either a fatal error was returned or no answer. Cancel the
|
||||||
|
* request.
|
||||||
|
*/
|
||||||
|
if (NXDOMAIN == header->rcode)
|
||||||
|
{
|
||||||
|
/* If the rcode is NXDOMAIN, treat it as a good response. */
|
||||||
|
ns_failure_count[ns] /= 4;
|
||||||
|
}
|
||||||
|
(*request->query->callback) (request->query->ptr, NULL);
|
||||||
|
rem_request(request);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If this fails there was an error decoding the received packet.
|
||||||
|
* -- jilles
|
||||||
|
*/
|
||||||
|
answer_count = proc_answer(request, header, buf, buf + rc);
|
||||||
|
|
||||||
|
if (answer_count)
|
||||||
|
{
|
||||||
|
if (request->type == T_PTR)
|
||||||
|
{
|
||||||
|
if (request->name == NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Got a PTR response with no name, something strange is
|
||||||
|
* happening. Try another DNS server.
|
||||||
|
*/
|
||||||
|
ns_failure_count[ns]++;
|
||||||
|
resend_query(request);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup the 'authoritative' name that we were given for the
|
||||||
|
* ip#.
|
||||||
|
*/
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
if (request->addr.ss_family == AF_INET6)
|
||||||
|
gethost_byname_type_fqdn(request->name, request->query, T_AAAA);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
gethost_byname_type_fqdn(request->name, request->query, T_A);
|
||||||
|
rem_request(request);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* got a name and address response, client resolved
|
||||||
|
*/
|
||||||
|
reply = make_dnsreply(request);
|
||||||
|
(*request->query->callback) (request->query->ptr, reply);
|
||||||
|
rb_free(reply);
|
||||||
|
rem_request(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
ns_failure_count[ns] /= 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Invalid or corrupt reply - try another resolver. */
|
||||||
|
ns_failure_count[ns]++;
|
||||||
|
resend_query(request);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void res_readreply(rb_fde_t *F, void *data)
|
||||||
|
{
|
||||||
|
while (res_read_single_reply(F, data))
|
||||||
|
;
|
||||||
|
rb_setselect(F, RB_SELECT_READ, res_readreply, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct DNSReply *make_dnsreply(struct reslist *request)
|
||||||
|
{
|
||||||
|
struct DNSReply *cp;
|
||||||
|
s_assert(request != 0);
|
||||||
|
|
||||||
|
cp = (struct DNSReply *)rb_malloc(sizeof(struct DNSReply));
|
||||||
|
|
||||||
|
cp->h_name = request->name;
|
||||||
|
memcpy(&cp->addr, &request->addr, sizeof(cp->addr));
|
||||||
|
return (cp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_dns_servers(struct Client *source_p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char ipaddr[128];
|
||||||
|
|
||||||
|
for (i = 0; i < irc_nscount; i++)
|
||||||
|
{
|
||||||
|
if (!rb_inet_ntop_sock((struct sockaddr *)&(irc_nsaddr_list[i]),
|
||||||
|
ipaddr, sizeof ipaddr))
|
||||||
|
rb_strlcpy(ipaddr, "?", sizeof ipaddr);
|
||||||
|
sendto_one_numeric(source_p, RPL_STATSDEBUG,
|
||||||
|
"A %s %d", ipaddr, ns_failure_count[i]);
|
||||||
|
}
|
||||||
|
}
|
646
src/s_auth.c
Normal file
646
src/s_auth.c
Normal file
|
@ -0,0 +1,646 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: A slightly useful ircd.
|
||||||
|
* s_auth.c: Functions for querying a users ident.
|
||||||
|
*
|
||||||
|
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||||
|
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||||
|
* Copyright (C) 2002-2005 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* $Id: s_auth.c 3354 2007-04-03 09:21:31Z nenolod $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Changes:
|
||||||
|
* July 6, 1999 - Rewrote most of the code here. When a client connects
|
||||||
|
* to the server and passes initial socket validation checks, it
|
||||||
|
* is owned by this module (auth) which returns it to the rest of the
|
||||||
|
* server when dns and auth queries are finished. Until the client is
|
||||||
|
* released, the server does not know it exists and does not process
|
||||||
|
* any messages from it.
|
||||||
|
* --Bleep Thomas Helvey <tomh@inxpress.net>
|
||||||
|
*/
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "s_auth.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "match.h"
|
||||||
|
#include "ircd.h"
|
||||||
|
#include "numeric.h"
|
||||||
|
#include "packet.h"
|
||||||
|
#include "res.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "s_stats.h"
|
||||||
|
#include "send.h"
|
||||||
|
#include "hook.h"
|
||||||
|
#include "blacklist.h"
|
||||||
|
#include "s_assert.h"
|
||||||
|
|
||||||
|
struct AuthRequest
|
||||||
|
{
|
||||||
|
rb_dlink_node node;
|
||||||
|
struct Client *client; /* pointer to client struct for request */
|
||||||
|
struct DNSQuery dns_query; /* DNS Query */
|
||||||
|
unsigned int flags; /* current state of request */
|
||||||
|
rb_fde_t *F; /* file descriptor for auth queries */
|
||||||
|
time_t timeout; /* time when query expires */
|
||||||
|
uint16_t lport;
|
||||||
|
uint16_t rport;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* flag values for AuthRequest
|
||||||
|
* NAMESPACE: AM_xxx - Authentication Module
|
||||||
|
*/
|
||||||
|
#define AM_AUTH_CONNECTING (1 << 0)
|
||||||
|
#define AM_AUTH_PENDING (1 << 1)
|
||||||
|
#define AM_DNS_PENDING (1 << 2)
|
||||||
|
|
||||||
|
#define SetDNSPending(x) ((x)->flags |= AM_DNS_PENDING)
|
||||||
|
#define ClearDNSPending(x) ((x)->flags &= ~AM_DNS_PENDING)
|
||||||
|
#define IsDNSPending(x) ((x)->flags & AM_DNS_PENDING)
|
||||||
|
|
||||||
|
#define SetAuthConnect(x) ((x)->flags |= AM_AUTH_CONNECTING)
|
||||||
|
#define ClearAuthConnect(x) ((x)->flags &= ~AM_AUTH_CONNECTING)
|
||||||
|
#define IsAuthConnect(x) ((x)->flags & AM_AUTH_CONNECTING)
|
||||||
|
|
||||||
|
#define SetAuthPending(x) ((x)->flags |= AM_AUTH_PENDING)
|
||||||
|
#define ClearAuthPending(x) ((x)->flags &= AM_AUTH_PENDING)
|
||||||
|
#define IsAuthPending(x) ((x)->flags & AM_AUTH_PENDING)
|
||||||
|
|
||||||
|
#define ClearAuth(x) ((x)->flags &= ~(AM_AUTH_PENDING | AM_AUTH_CONNECTING))
|
||||||
|
#define IsDoingAuth(x) ((x)->flags & (AM_AUTH_PENDING | AM_AUTH_CONNECTING))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* a bit different approach
|
||||||
|
* this replaces the original sendheader macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const char *HeaderMessages[] =
|
||||||
|
{
|
||||||
|
":*** Looking up your hostname...",
|
||||||
|
":*** Found your hostname",
|
||||||
|
":*** Couldn't look up your hostname",
|
||||||
|
":*** Checking Ident",
|
||||||
|
":*** Got Ident response",
|
||||||
|
":*** No Ident response",
|
||||||
|
":*** Your hostname is too long, ignoring hostname",
|
||||||
|
":*** Your forward and reverse DNS do not match, ignoring hostname",
|
||||||
|
":*** Cannot verify hostname validity, ignoring hostname",
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
REPORT_DO_DNS,
|
||||||
|
REPORT_FIN_DNS,
|
||||||
|
REPORT_FAIL_DNS,
|
||||||
|
REPORT_DO_ID,
|
||||||
|
REPORT_FIN_ID,
|
||||||
|
REPORT_FAIL_ID,
|
||||||
|
REPORT_HOST_TOOLONG,
|
||||||
|
REPORT_HOST_MISMATCH,
|
||||||
|
REPORT_HOST_UNKNOWN
|
||||||
|
}
|
||||||
|
ReportType;
|
||||||
|
|
||||||
|
#define sendheader(c, r) sendto_one_notice(c, "%s", HeaderMessages[(r)])
|
||||||
|
|
||||||
|
static rb_dlink_list auth_poll_list;
|
||||||
|
static rb_bh *auth_heap;
|
||||||
|
static EVH timeout_auth_queries_event;
|
||||||
|
|
||||||
|
static PF read_auth_reply;
|
||||||
|
static CNCB auth_connect_callback;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_auth()
|
||||||
|
*
|
||||||
|
* Initialise the auth code
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
init_auth(void)
|
||||||
|
{
|
||||||
|
/* This hook takes a struct Client for its argument */
|
||||||
|
memset(&auth_poll_list, 0, sizeof(auth_poll_list));
|
||||||
|
rb_event_addish("timeout_auth_queries_event", timeout_auth_queries_event, NULL, 1);
|
||||||
|
auth_heap = rb_bh_create(sizeof(struct AuthRequest), LCLIENT_HEAP_SIZE, "auth_heap");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make_auth_request - allocate a new auth request
|
||||||
|
*/
|
||||||
|
static struct AuthRequest *
|
||||||
|
make_auth_request(struct Client *client)
|
||||||
|
{
|
||||||
|
struct AuthRequest *request = rb_bh_alloc(auth_heap);
|
||||||
|
client->localClient->auth_request = request;
|
||||||
|
request->F = NULL;
|
||||||
|
request->client = client;
|
||||||
|
request->timeout = rb_current_time() + ConfigFileEntry.connect_timeout;
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* free_auth_request - cleanup auth request allocations
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
free_auth_request(struct AuthRequest *request)
|
||||||
|
{
|
||||||
|
rb_bh_free(auth_heap, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* release_auth_client - release auth client from auth system
|
||||||
|
* this adds the client into the local client lists so it can be read by
|
||||||
|
* the main io processing loop
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
release_auth_client(struct AuthRequest *auth)
|
||||||
|
{
|
||||||
|
struct Client *client = auth->client;
|
||||||
|
|
||||||
|
if(IsDNSPending(auth) || IsDoingAuth(auth))
|
||||||
|
return;
|
||||||
|
|
||||||
|
client->localClient->auth_request = NULL;
|
||||||
|
rb_dlinkDelete(&auth->node, &auth_poll_list);
|
||||||
|
free_auth_request(auth);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When a client has auth'ed, we want to start reading what it sends
|
||||||
|
* us. This is what read_packet() does.
|
||||||
|
* -- adrian
|
||||||
|
*/
|
||||||
|
rb_dlinkAddTail(client, &client->node, &global_client_list);
|
||||||
|
read_packet(client->localClient->F, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* auth_dns_callback - called when resolver query finishes
|
||||||
|
* if the query resulted in a successful search, hp will contain
|
||||||
|
* a non-null pointer, otherwise hp will be null.
|
||||||
|
* set the client on it's way to a connection completion, regardless
|
||||||
|
* of success of failure
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
auth_dns_callback(void *vptr, struct DNSReply *reply)
|
||||||
|
{
|
||||||
|
struct AuthRequest *auth = (struct AuthRequest *) vptr;
|
||||||
|
ClearDNSPending(auth);
|
||||||
|
|
||||||
|
/* XXX: this shouldn't happen, but it does. -nenolod */
|
||||||
|
if(auth->client->localClient == NULL)
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"auth_dns_callback(): auth->client->localClient (%s) is NULL", get_client_name(auth->client, HIDE_IP));
|
||||||
|
|
||||||
|
rb_dlinkDelete(&auth->node, &auth_poll_list);
|
||||||
|
free_auth_request(auth);
|
||||||
|
|
||||||
|
/* and they will silently drop through and all will hopefully be ok... -nenolod */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(reply)
|
||||||
|
{
|
||||||
|
int good = 1;
|
||||||
|
|
||||||
|
if(auth->client->localClient->ip.ss_family == AF_INET)
|
||||||
|
{
|
||||||
|
struct sockaddr_in *ip, *ip_fwd;
|
||||||
|
|
||||||
|
ip = (struct sockaddr_in *) &auth->client->localClient->ip;
|
||||||
|
ip_fwd = (struct sockaddr_in *) &reply->addr;
|
||||||
|
|
||||||
|
if(ip->sin_addr.s_addr != ip_fwd->sin_addr.s_addr)
|
||||||
|
{
|
||||||
|
sendheader(auth->client, REPORT_HOST_MISMATCH);
|
||||||
|
good = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
else if(auth->client->localClient->ip.ss_family == AF_INET6)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 *ip, *ip_fwd;
|
||||||
|
|
||||||
|
ip = (struct sockaddr_in6 *) &auth->client->localClient->ip;
|
||||||
|
ip_fwd = (struct sockaddr_in6 *) &reply->addr;
|
||||||
|
|
||||||
|
if(memcmp(&ip->sin6_addr, &ip_fwd->sin6_addr, sizeof(struct in6_addr)) != 0)
|
||||||
|
{
|
||||||
|
sendheader(auth->client, REPORT_HOST_MISMATCH);
|
||||||
|
good = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else /* can't verify it, don't know how. reject it. */
|
||||||
|
{
|
||||||
|
sendheader(auth->client, REPORT_HOST_UNKNOWN);
|
||||||
|
good = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(good && strlen(reply->h_name) <= HOSTLEN)
|
||||||
|
{
|
||||||
|
rb_strlcpy(auth->client->host, reply->h_name, sizeof(auth->client->host));
|
||||||
|
sendheader(auth->client, REPORT_FIN_DNS);
|
||||||
|
}
|
||||||
|
else if (strlen(reply->h_name) > HOSTLEN)
|
||||||
|
sendheader(auth->client, REPORT_HOST_TOOLONG);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sendheader(auth->client, REPORT_FAIL_DNS);
|
||||||
|
|
||||||
|
release_auth_client(auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* authsenderr - handle auth send errors
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
auth_error(struct AuthRequest *auth)
|
||||||
|
{
|
||||||
|
++ServerStats.is_abad;
|
||||||
|
|
||||||
|
rb_close(auth->F);
|
||||||
|
auth->F = NULL;
|
||||||
|
|
||||||
|
ClearAuth(auth);
|
||||||
|
sendheader(auth->client, REPORT_FAIL_ID);
|
||||||
|
|
||||||
|
release_auth_client(auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* start_auth_query - Flag the client to show that an attempt to
|
||||||
|
* contact the ident server on
|
||||||
|
* the client's host. The connect and subsequently the socket are all put
|
||||||
|
* into 'non-blocking' mode. Should the connect or any later phase of the
|
||||||
|
* identifing process fail, it is aborted and the user is given a username
|
||||||
|
* of "unknown".
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
start_auth_query(struct AuthRequest *auth)
|
||||||
|
{
|
||||||
|
struct rb_sockaddr_storage localaddr, destaddr;
|
||||||
|
rb_fde_t *F;
|
||||||
|
int family;
|
||||||
|
|
||||||
|
if(IsAnyDead(auth->client))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
family = auth->client->localClient->ip.ss_family;
|
||||||
|
if((F = rb_socket(family, SOCK_STREAM, 0, "ident")) == NULL)
|
||||||
|
{
|
||||||
|
ilog_error("creating auth stream socket");
|
||||||
|
++ServerStats.is_abad;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TBD: this is a pointless arbitrary limit .. we either have a socket or not. -nenolod
|
||||||
|
*/
|
||||||
|
if((maxconnections - 10) < rb_get_fd(F))
|
||||||
|
{
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Can't allocate fd for auth on %s",
|
||||||
|
get_client_name(auth->client, SHOW_IP));
|
||||||
|
rb_close(F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendheader(auth->client, REPORT_DO_ID);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get the local address of the client and bind to that to
|
||||||
|
* make the auth request. This used to be done only for
|
||||||
|
* ifdef VIRTUAL_HOST, but needs to be done for all clients
|
||||||
|
* since the ident request must originate from that same address--
|
||||||
|
* and machines with multiple IP addresses are common now
|
||||||
|
*/
|
||||||
|
localaddr = auth->client->preClient->lip;
|
||||||
|
|
||||||
|
/* XXX mangle_mapped_sockaddr((struct sockaddr *)&localaddr); */
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
if(localaddr.ss_family == AF_INET6)
|
||||||
|
{
|
||||||
|
auth->lport = ntohs(((struct sockaddr_in6 *)&localaddr)->sin6_port);
|
||||||
|
((struct sockaddr_in6 *)&localaddr)->sin6_port = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
auth->lport = ntohs(((struct sockaddr_in *)&localaddr)->sin_port);
|
||||||
|
((struct sockaddr_in *)&localaddr)->sin_port = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
destaddr = auth->client->localClient->ip;
|
||||||
|
#ifdef RB_IPV6
|
||||||
|
if(localaddr.ss_family == AF_INET6)
|
||||||
|
{
|
||||||
|
auth->rport = ntohs(((struct sockaddr_in6 *)&destaddr)->sin6_port);
|
||||||
|
((struct sockaddr_in6 *)&destaddr)->sin6_port = htons(113);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
auth->rport = ntohs(((struct sockaddr_in *)&destaddr)->sin_port);
|
||||||
|
((struct sockaddr_in *)&destaddr)->sin_port = htons(113);
|
||||||
|
}
|
||||||
|
|
||||||
|
auth->F = F;
|
||||||
|
SetAuthConnect(auth);
|
||||||
|
|
||||||
|
rb_connect_tcp(F, (struct sockaddr *)&destaddr,
|
||||||
|
(struct sockaddr *) &localaddr, GET_SS_LEN(&localaddr),
|
||||||
|
auth_connect_callback, auth,
|
||||||
|
GlobalSetOptions.ident_timeout);
|
||||||
|
return 1; /* We suceed here for now */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GetValidIdent - parse ident query reply from identd server
|
||||||
|
*
|
||||||
|
* Inputs - pointer to ident buf
|
||||||
|
* Output - NULL if no valid ident found, otherwise pointer to name
|
||||||
|
* Side effects -
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
GetValidIdent(char *buf)
|
||||||
|
{
|
||||||
|
int remp = 0;
|
||||||
|
int locp = 0;
|
||||||
|
char *colon1Ptr;
|
||||||
|
char *colon2Ptr;
|
||||||
|
char *colon3Ptr;
|
||||||
|
char *commaPtr;
|
||||||
|
char *remotePortString;
|
||||||
|
|
||||||
|
/* All this to get rid of a sscanf() fun. */
|
||||||
|
remotePortString = buf;
|
||||||
|
|
||||||
|
colon1Ptr = strchr(remotePortString, ':');
|
||||||
|
if(!colon1Ptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*colon1Ptr = '\0';
|
||||||
|
colon1Ptr++;
|
||||||
|
colon2Ptr = strchr(colon1Ptr, ':');
|
||||||
|
if(!colon2Ptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*colon2Ptr = '\0';
|
||||||
|
colon2Ptr++;
|
||||||
|
commaPtr = strchr(remotePortString, ',');
|
||||||
|
|
||||||
|
if(!commaPtr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*commaPtr = '\0';
|
||||||
|
commaPtr++;
|
||||||
|
|
||||||
|
remp = atoi(remotePortString);
|
||||||
|
if(!remp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
locp = atoi(commaPtr);
|
||||||
|
if(!locp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* look for USERID bordered by first pair of colons */
|
||||||
|
if(!strstr(colon1Ptr, "USERID"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
colon3Ptr = strchr(colon2Ptr, ':');
|
||||||
|
if(!colon3Ptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*colon3Ptr = '\0';
|
||||||
|
colon3Ptr++;
|
||||||
|
return (colon3Ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* start_auth - starts auth (identd) and dns queries for a client
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
start_auth(struct Client *client)
|
||||||
|
{
|
||||||
|
struct AuthRequest *auth = 0;
|
||||||
|
s_assert(0 != client);
|
||||||
|
if(client == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auth = make_auth_request(client);
|
||||||
|
|
||||||
|
auth->dns_query.ptr = auth;
|
||||||
|
auth->dns_query.callback = auth_dns_callback;
|
||||||
|
|
||||||
|
sendheader(client, REPORT_DO_DNS);
|
||||||
|
|
||||||
|
/* No DNS cache now, remember? -- adrian */
|
||||||
|
gethost_byaddr(&client->localClient->ip, &auth->dns_query);
|
||||||
|
|
||||||
|
SetDNSPending(auth);
|
||||||
|
|
||||||
|
if(ConfigFileEntry.disable_auth == 0)
|
||||||
|
start_auth_query(auth);
|
||||||
|
|
||||||
|
rb_dlinkAdd(auth, &auth->node, &auth_poll_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* timeout_auth_queries - timeout resolver and identd requests
|
||||||
|
* allow clients through if requests failed
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
timeout_auth_queries_event(void *notused)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
rb_dlink_node *next_ptr;
|
||||||
|
struct AuthRequest *auth;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, auth_poll_list.head)
|
||||||
|
{
|
||||||
|
auth = ptr->data;
|
||||||
|
|
||||||
|
if(auth->timeout < rb_current_time())
|
||||||
|
{
|
||||||
|
if(auth->F != NULL)
|
||||||
|
rb_close(auth->F);
|
||||||
|
|
||||||
|
if(IsDoingAuth(auth))
|
||||||
|
{
|
||||||
|
ClearAuth(auth);
|
||||||
|
++ServerStats.is_abad;
|
||||||
|
sendheader(auth->client, REPORT_FAIL_ID);
|
||||||
|
auth->client->localClient->auth_request = NULL;
|
||||||
|
}
|
||||||
|
if(IsDNSPending(auth))
|
||||||
|
{
|
||||||
|
ClearDNSPending(auth);
|
||||||
|
delete_resolver_queries(&auth->dns_query);
|
||||||
|
sendheader(auth->client, REPORT_FAIL_DNS);
|
||||||
|
}
|
||||||
|
|
||||||
|
auth->client->localClient->lasttime = rb_current_time();
|
||||||
|
release_auth_client(auth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* auth_connect_callback() - deal with the result of rb_connect_tcp()
|
||||||
|
*
|
||||||
|
* If the connection failed, we simply close the auth fd and report
|
||||||
|
* a failure. If the connection suceeded send the ident server a query
|
||||||
|
* giving "theirport , ourport". The write is only attempted *once* so
|
||||||
|
* it is deemed to be a fail if the entire write doesn't write all the
|
||||||
|
* data given. This shouldnt be a problem since the socket should have
|
||||||
|
* a write buffer far greater than this message to store it in should
|
||||||
|
* problems arise. -avalon
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
auth_connect_callback(rb_fde_t *F, int error, void *data)
|
||||||
|
{
|
||||||
|
struct AuthRequest *auth = data;
|
||||||
|
char authbuf[32];
|
||||||
|
int authlen;
|
||||||
|
|
||||||
|
/* Check the error */
|
||||||
|
if(error != RB_OK)
|
||||||
|
{
|
||||||
|
/* We had an error during connection :( */
|
||||||
|
auth_error(auth);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_snprintf(authbuf, sizeof(authbuf), "%u , %u\r\n",
|
||||||
|
auth->rport, auth->lport);
|
||||||
|
authlen = strlen(authbuf);
|
||||||
|
|
||||||
|
if(rb_write(auth->F, authbuf, authlen) != authlen)
|
||||||
|
{
|
||||||
|
auth_error(auth);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ClearAuthConnect(auth);
|
||||||
|
SetAuthPending(auth);
|
||||||
|
read_auth_reply(auth->F, auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* read_auth_reply - read the reply (if any) from the ident server
|
||||||
|
* we connected to.
|
||||||
|
* We only give it one shot, if the reply isn't good the first time
|
||||||
|
* fail the authentication entirely. --Bleep
|
||||||
|
*/
|
||||||
|
#define AUTH_BUFSIZ 128
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_auth_reply(rb_fde_t *F, void *data)
|
||||||
|
{
|
||||||
|
struct AuthRequest *auth = data;
|
||||||
|
char *s = NULL;
|
||||||
|
char *t = NULL;
|
||||||
|
int len;
|
||||||
|
int count;
|
||||||
|
char buf[AUTH_BUFSIZ + 1] = { 0 }; /* buffer to read auth reply into */
|
||||||
|
|
||||||
|
len = rb_read(F, buf, AUTH_BUFSIZ);
|
||||||
|
|
||||||
|
if(len < 0 && rb_ignore_errno(errno))
|
||||||
|
{
|
||||||
|
rb_setselect(F, RB_SELECT_READ, read_auth_reply, auth);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(len > 0)
|
||||||
|
{
|
||||||
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
if((s = GetValidIdent(buf)))
|
||||||
|
{
|
||||||
|
t = auth->client->username;
|
||||||
|
|
||||||
|
while (*s == '~' || *s == '^')
|
||||||
|
s++;
|
||||||
|
|
||||||
|
for (count = USERLEN; *s && count; s++)
|
||||||
|
{
|
||||||
|
if(*s == '@')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!IsSpace(*s) && *s != ':' && *s != '[')
|
||||||
|
{
|
||||||
|
*t++ = *s;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*t = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_close(auth->F);
|
||||||
|
auth->F = NULL;
|
||||||
|
ClearAuth(auth);
|
||||||
|
|
||||||
|
if(s == NULL)
|
||||||
|
{
|
||||||
|
++ServerStats.is_abad;
|
||||||
|
strcpy(auth->client->username, "unknown");
|
||||||
|
sendheader(auth->client, REPORT_FAIL_ID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendheader(auth->client, REPORT_FIN_ID);
|
||||||
|
++ServerStats.is_asuc;
|
||||||
|
SetGotId(auth->client);
|
||||||
|
}
|
||||||
|
|
||||||
|
release_auth_client(auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* delete_auth_queries()
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
delete_auth_queries(struct Client *target_p)
|
||||||
|
{
|
||||||
|
struct AuthRequest *auth;
|
||||||
|
|
||||||
|
if(target_p == NULL || target_p->localClient == NULL ||
|
||||||
|
target_p->localClient->auth_request == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auth = target_p->localClient->auth_request;
|
||||||
|
target_p->localClient->auth_request = NULL;
|
||||||
|
|
||||||
|
if(IsDNSPending(auth))
|
||||||
|
delete_resolver_queries(&auth->dns_query);
|
||||||
|
|
||||||
|
if(auth->F != NULL)
|
||||||
|
rb_close(auth->F);
|
||||||
|
|
||||||
|
rb_dlinkDelete(&auth->node, &auth_poll_list);
|
||||||
|
free_auth_request(auth);
|
||||||
|
}
|
1721
src/s_conf.c
Normal file
1721
src/s_conf.c
Normal file
File diff suppressed because it is too large
Load diff
847
src/s_newconf.c
Normal file
847
src/s_newconf.c
Normal file
|
@ -0,0 +1,847 @@
|
||||||
|
/*
|
||||||
|
* ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd).
|
||||||
|
* s_newconf.c - code for dealing with conf stuff
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004 Lee Hardy <lee@leeh.co.uk>
|
||||||
|
* Copyright (C) 2004-2005 ircd-ratbox development team
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* 1.Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2.Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3.The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id: s_newconf.c 3508 2007-06-04 16:04:49Z jilles $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "ircd_defs.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "s_newconf.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "s_serv.h"
|
||||||
|
#include "send.h"
|
||||||
|
#include "hostmask.h"
|
||||||
|
#include "newconf.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "irc_dictionary.h"
|
||||||
|
#include "s_assert.h"
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
rb_dlink_list shared_conf_list;
|
||||||
|
rb_dlink_list cluster_conf_list;
|
||||||
|
rb_dlink_list oper_conf_list;
|
||||||
|
rb_dlink_list hubleaf_conf_list;
|
||||||
|
rb_dlink_list server_conf_list;
|
||||||
|
rb_dlink_list xline_conf_list;
|
||||||
|
rb_dlink_list resv_conf_list; /* nicks only! */
|
||||||
|
rb_dlink_list nd_list; /* nick delay */
|
||||||
|
rb_dlink_list tgchange_list;
|
||||||
|
rb_dlink_list vhost_conf_list;
|
||||||
|
|
||||||
|
rb_patricia_tree_t *tgchange_tree;
|
||||||
|
|
||||||
|
static rb_bh *nd_heap = NULL;
|
||||||
|
|
||||||
|
static void expire_temp_rxlines(void *unused);
|
||||||
|
static void expire_nd_entries(void *unused);
|
||||||
|
|
||||||
|
struct ev_entry *expire_nd_entries_ev = NULL;
|
||||||
|
struct ev_entry *expire_temp_rxlines_ev = NULL;
|
||||||
|
|
||||||
|
void
|
||||||
|
init_s_newconf(void)
|
||||||
|
{
|
||||||
|
tgchange_tree = rb_new_patricia(PATRICIA_BITS);
|
||||||
|
nd_heap = rb_bh_create(sizeof(struct nd_entry), ND_HEAP_SIZE, "nd_heap");
|
||||||
|
expire_nd_entries_ev = rb_event_addish("expire_nd_entries", expire_nd_entries, NULL, 30);
|
||||||
|
expire_temp_rxlines_ev = rb_event_addish("expire_temp_rxlines", expire_temp_rxlines, NULL, 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clear_s_newconf(void)
|
||||||
|
{
|
||||||
|
struct server_conf *server_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
rb_dlink_node *next_ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, shared_conf_list.head)
|
||||||
|
{
|
||||||
|
/* ptr here is ptr->data->node */
|
||||||
|
rb_dlinkDelete(ptr, &shared_conf_list);
|
||||||
|
free_remote_conf(ptr->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, cluster_conf_list.head)
|
||||||
|
{
|
||||||
|
rb_dlinkDelete(ptr, &cluster_conf_list);
|
||||||
|
free_remote_conf(ptr->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, hubleaf_conf_list.head)
|
||||||
|
{
|
||||||
|
rb_dlinkDelete(ptr, &hubleaf_conf_list);
|
||||||
|
free_remote_conf(ptr->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, oper_conf_list.head)
|
||||||
|
{
|
||||||
|
free_oper_conf(ptr->data);
|
||||||
|
rb_dlinkDestroy(ptr, &oper_conf_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, server_conf_list.head)
|
||||||
|
{
|
||||||
|
server_p = ptr->data;
|
||||||
|
|
||||||
|
if(!server_p->servers)
|
||||||
|
{
|
||||||
|
rb_dlinkDelete(ptr, &server_conf_list);
|
||||||
|
free_server_conf(ptr->data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
server_p->flags |= SERVER_ILLEGAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clear_s_newconf_bans(void)
|
||||||
|
{
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
rb_dlink_node *ptr, *next_ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, xline_conf_list.head)
|
||||||
|
{
|
||||||
|
aconf = ptr->data;
|
||||||
|
|
||||||
|
if(aconf->hold)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
free_conf(aconf);
|
||||||
|
rb_dlinkDestroy(ptr, &xline_conf_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, resv_conf_list.head)
|
||||||
|
{
|
||||||
|
aconf = ptr->data;
|
||||||
|
|
||||||
|
/* temporary resv */
|
||||||
|
if(aconf->hold)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
free_conf(aconf);
|
||||||
|
rb_dlinkDestroy(ptr, &resv_conf_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_resv_hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct remote_conf *
|
||||||
|
make_remote_conf(void)
|
||||||
|
{
|
||||||
|
struct remote_conf *remote_p = rb_malloc(sizeof(struct remote_conf));
|
||||||
|
return remote_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free_remote_conf(struct remote_conf *remote_p)
|
||||||
|
{
|
||||||
|
s_assert(remote_p != NULL);
|
||||||
|
if(remote_p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rb_free(remote_p->username);
|
||||||
|
rb_free(remote_p->host);
|
||||||
|
rb_free(remote_p->server);
|
||||||
|
rb_free(remote_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
find_shared_conf(const char *username, const char *host,
|
||||||
|
const char *server, int flags)
|
||||||
|
{
|
||||||
|
struct remote_conf *shared_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, shared_conf_list.head)
|
||||||
|
{
|
||||||
|
shared_p = ptr->data;
|
||||||
|
|
||||||
|
if(match(shared_p->username, username) &&
|
||||||
|
match(shared_p->host, host) &&
|
||||||
|
match(shared_p->server, server))
|
||||||
|
{
|
||||||
|
if(shared_p->flags & flags)
|
||||||
|
return YES;
|
||||||
|
else
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
propagate_generic(struct Client *source_p, const char *command,
|
||||||
|
const char *target, int cap, const char *format, ...)
|
||||||
|
{
|
||||||
|
char buffer[BUFSIZE];
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
rb_vsnprintf(buffer, sizeof(buffer), format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
sendto_match_servs(source_p, target, cap, NOCAPS,
|
||||||
|
"%s %s %s",
|
||||||
|
command, target, buffer);
|
||||||
|
sendto_match_servs(source_p, target, CAP_ENCAP, cap,
|
||||||
|
"ENCAP %s %s %s",
|
||||||
|
target, command, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cluster_generic(struct Client *source_p, const char *command,
|
||||||
|
int cltype, int cap, const char *format, ...)
|
||||||
|
{
|
||||||
|
char buffer[BUFSIZE];
|
||||||
|
struct remote_conf *shared_p;
|
||||||
|
va_list args;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
rb_vsnprintf(buffer, sizeof(buffer), format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, cluster_conf_list.head)
|
||||||
|
{
|
||||||
|
shared_p = ptr->data;
|
||||||
|
|
||||||
|
if(!(shared_p->flags & cltype))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sendto_match_servs(source_p, shared_p->server, cap, NOCAPS,
|
||||||
|
"%s %s %s",
|
||||||
|
command, shared_p->server, buffer);
|
||||||
|
sendto_match_servs(source_p, shared_p->server, CAP_ENCAP, cap,
|
||||||
|
"ENCAP %s %s %s",
|
||||||
|
shared_p->server, command, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct oper_conf *
|
||||||
|
make_oper_conf(void)
|
||||||
|
{
|
||||||
|
struct oper_conf *oper_p = rb_malloc(sizeof(struct oper_conf));
|
||||||
|
return oper_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free_oper_conf(struct oper_conf *oper_p)
|
||||||
|
{
|
||||||
|
s_assert(oper_p != NULL);
|
||||||
|
if(oper_p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rb_free(oper_p->username);
|
||||||
|
rb_free(oper_p->host);
|
||||||
|
rb_free(oper_p->name);
|
||||||
|
rb_free(oper_p->certfp);
|
||||||
|
|
||||||
|
if(oper_p->passwd)
|
||||||
|
{
|
||||||
|
memset(oper_p->passwd, 0, strlen(oper_p->passwd));
|
||||||
|
rb_free(oper_p->passwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCRYPTO
|
||||||
|
rb_free(oper_p->rsa_pubkey_file);
|
||||||
|
|
||||||
|
if(oper_p->rsa_pubkey)
|
||||||
|
RSA_free(oper_p->rsa_pubkey);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rb_free(oper_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct oper_conf *
|
||||||
|
find_oper_conf(const char *username, const char *host, const char *locip, const char *name)
|
||||||
|
{
|
||||||
|
struct oper_conf *oper_p;
|
||||||
|
struct rb_sockaddr_storage ip, cip;
|
||||||
|
char addr[HOSTLEN+1];
|
||||||
|
int bits, cbits;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
|
||||||
|
parse_netmask(locip, &cip, &cbits);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, oper_conf_list.head)
|
||||||
|
{
|
||||||
|
oper_p = ptr->data;
|
||||||
|
|
||||||
|
/* name/username doesnt match.. */
|
||||||
|
if(irccmp(oper_p->name, name) || !match(oper_p->username, username))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rb_strlcpy(addr, oper_p->host, sizeof(addr));
|
||||||
|
|
||||||
|
if(parse_netmask(addr, &ip, &bits) != HM_HOST)
|
||||||
|
{
|
||||||
|
if(ip.ss_family == cip.ss_family &&
|
||||||
|
comp_with_mask_sock((struct sockaddr *)&ip, (struct sockaddr *)&cip, bits))
|
||||||
|
return oper_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we have to compare against the host as well, because its
|
||||||
|
* valid to set a spoof to an IP, which if we only compare
|
||||||
|
* in ip form to sockhost will not necessarily match --anfl
|
||||||
|
*/
|
||||||
|
if(match(oper_p->host, host))
|
||||||
|
return oper_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct server_conf *
|
||||||
|
make_server_conf(void)
|
||||||
|
{
|
||||||
|
struct server_conf *server_p = rb_malloc(sizeof(struct server_conf));
|
||||||
|
server_p->aftype = AF_INET;
|
||||||
|
return server_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free_server_conf(struct server_conf *server_p)
|
||||||
|
{
|
||||||
|
s_assert(server_p != NULL);
|
||||||
|
if(server_p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!EmptyString(server_p->passwd))
|
||||||
|
{
|
||||||
|
memset(server_p->passwd, 0, strlen(server_p->passwd));
|
||||||
|
rb_free(server_p->passwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!EmptyString(server_p->spasswd))
|
||||||
|
{
|
||||||
|
memset(server_p->spasswd, 0, strlen(server_p->spasswd));
|
||||||
|
rb_free(server_p->spasswd);
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_free(server_p->name);
|
||||||
|
rb_free(server_p->host);
|
||||||
|
rb_free(server_p->class_name);
|
||||||
|
rb_free(server_p->certfp);
|
||||||
|
rb_free(server_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
add_server_conf(struct server_conf *server_p)
|
||||||
|
{
|
||||||
|
if(EmptyString(server_p->class_name))
|
||||||
|
{
|
||||||
|
server_p->class_name = rb_strdup("default");
|
||||||
|
server_p->class = default_class;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
server_p->class = find_class(server_p->class_name);
|
||||||
|
|
||||||
|
if(server_p->class == default_class)
|
||||||
|
{
|
||||||
|
conf_report_error("Warning connect::class invalid for %s",
|
||||||
|
server_p->name);
|
||||||
|
|
||||||
|
rb_free(server_p->class_name);
|
||||||
|
server_p->class_name = rb_strdup("default");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strchr(server_p->host, '*') || strchr(server_p->host, '?'))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct server_conf *
|
||||||
|
find_server_conf(const char *name)
|
||||||
|
{
|
||||||
|
struct server_conf *server_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, server_conf_list.head)
|
||||||
|
{
|
||||||
|
server_p = ptr->data;
|
||||||
|
|
||||||
|
if(ServerConfIllegal(server_p))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(match(name, server_p->name))
|
||||||
|
return server_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
attach_server_conf(struct Client *client_p, struct server_conf *server_p)
|
||||||
|
{
|
||||||
|
/* already have an attached conf */
|
||||||
|
if(client_p->localClient->att_sconf)
|
||||||
|
{
|
||||||
|
/* short circuit this special case :) */
|
||||||
|
if(client_p->localClient->att_sconf == server_p)
|
||||||
|
return;
|
||||||
|
|
||||||
|
detach_server_conf(client_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrUsers(server_p->class)++;
|
||||||
|
|
||||||
|
client_p->localClient->att_sconf = server_p;
|
||||||
|
server_p->servers++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
detach_server_conf(struct Client *client_p)
|
||||||
|
{
|
||||||
|
struct server_conf *server_p = client_p->localClient->att_sconf;
|
||||||
|
|
||||||
|
if(server_p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
client_p->localClient->att_sconf = NULL;
|
||||||
|
server_p->servers--;
|
||||||
|
CurrUsers(server_p->class)--;
|
||||||
|
|
||||||
|
if(ServerConfIllegal(server_p) && !server_p->servers)
|
||||||
|
{
|
||||||
|
/* the class this one is using may need destroying too */
|
||||||
|
if(MaxUsers(server_p->class) < 0 && CurrUsers(server_p->class) <= 0)
|
||||||
|
free_class(server_p->class);
|
||||||
|
|
||||||
|
rb_dlinkDelete(&server_p->node, &server_conf_list);
|
||||||
|
free_server_conf(server_p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_server_conf_autoconn(struct Client *source_p, const char *name, int newval)
|
||||||
|
{
|
||||||
|
struct server_conf *server_p;
|
||||||
|
|
||||||
|
if((server_p = find_server_conf(name)) != NULL)
|
||||||
|
{
|
||||||
|
if(newval)
|
||||||
|
server_p->flags |= SERVER_AUTOCONN;
|
||||||
|
else
|
||||||
|
server_p->flags &= ~SERVER_AUTOCONN;
|
||||||
|
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"%s has changed AUTOCONN for %s to %i",
|
||||||
|
get_oper_name(source_p), name, newval);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sendto_one_notice(source_p, ":Can't find %s", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
disable_server_conf_autoconn(const char *name)
|
||||||
|
{
|
||||||
|
struct server_conf *server_p;
|
||||||
|
|
||||||
|
server_p = find_server_conf(name);
|
||||||
|
if(server_p != NULL && server_p->flags & SERVER_AUTOCONN)
|
||||||
|
{
|
||||||
|
server_p->flags &= ~SERVER_AUTOCONN;
|
||||||
|
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Disabling AUTOCONN for %s because of error",
|
||||||
|
name);
|
||||||
|
ilog(L_SERVER, "Disabling AUTOCONN for %s because of error",
|
||||||
|
name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConfItem *
|
||||||
|
find_xline(const char *gecos, int counter)
|
||||||
|
{
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, xline_conf_list.head)
|
||||||
|
{
|
||||||
|
aconf = ptr->data;
|
||||||
|
|
||||||
|
if(match_esc(aconf->host, gecos))
|
||||||
|
{
|
||||||
|
if(counter)
|
||||||
|
aconf->port++;
|
||||||
|
return aconf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConfItem *
|
||||||
|
find_xline_mask(const char *gecos)
|
||||||
|
{
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, xline_conf_list.head)
|
||||||
|
{
|
||||||
|
aconf = ptr->data;
|
||||||
|
|
||||||
|
if(!irccmp(aconf->host, gecos))
|
||||||
|
return aconf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConfItem *
|
||||||
|
find_nick_resv(const char *name)
|
||||||
|
{
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, resv_conf_list.head)
|
||||||
|
{
|
||||||
|
aconf = ptr->data;
|
||||||
|
|
||||||
|
if(match_esc(aconf->host, name))
|
||||||
|
{
|
||||||
|
aconf->port++;
|
||||||
|
return aconf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConfItem *
|
||||||
|
find_nick_resv_mask(const char *name)
|
||||||
|
{
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, resv_conf_list.head)
|
||||||
|
{
|
||||||
|
aconf = ptr->data;
|
||||||
|
|
||||||
|
if(!irccmp(aconf->host, name))
|
||||||
|
return aconf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clean_resv_nick()
|
||||||
|
*
|
||||||
|
* inputs - nick
|
||||||
|
* outputs - 1 if nick is vaild resv, 0 otherwise
|
||||||
|
* side effects -
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clean_resv_nick(const char *nick)
|
||||||
|
{
|
||||||
|
char tmpch;
|
||||||
|
int as = 0;
|
||||||
|
int q = 0;
|
||||||
|
int ch = 0;
|
||||||
|
|
||||||
|
if(*nick == '-' || IsDigit(*nick))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while ((tmpch = *nick++))
|
||||||
|
{
|
||||||
|
if(tmpch == '?' || tmpch == '@' || tmpch == '#')
|
||||||
|
q++;
|
||||||
|
else if(tmpch == '*')
|
||||||
|
as++;
|
||||||
|
else if(IsNickChar(tmpch))
|
||||||
|
ch++;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ch && as)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* valid_wild_card_simple()
|
||||||
|
*
|
||||||
|
* inputs - "thing" to test
|
||||||
|
* outputs - 1 if enough wildcards, else 0
|
||||||
|
* side effects -
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
valid_wild_card_simple(const char *data)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
char tmpch;
|
||||||
|
int nonwild = 0;
|
||||||
|
int wild = 0;
|
||||||
|
|
||||||
|
/* check the string for minimum number of nonwildcard chars */
|
||||||
|
p = data;
|
||||||
|
|
||||||
|
while((tmpch = *p++))
|
||||||
|
{
|
||||||
|
/* found an escape, p points to the char after it, so skip
|
||||||
|
* that and move on.
|
||||||
|
*/
|
||||||
|
if(tmpch == '\\' && *p)
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
if(++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if(!IsMWildChar(tmpch))
|
||||||
|
{
|
||||||
|
/* if we have enough nonwildchars, return */
|
||||||
|
if(++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
wild++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* strings without wilds are also ok */
|
||||||
|
return wild == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t
|
||||||
|
valid_temp_time(const char *p)
|
||||||
|
{
|
||||||
|
time_t result = 0;
|
||||||
|
|
||||||
|
while(*p)
|
||||||
|
{
|
||||||
|
if(IsDigit(*p))
|
||||||
|
{
|
||||||
|
result *= 10;
|
||||||
|
result += ((*p) & 0xF);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result > (60 * 24 * 7 * 52))
|
||||||
|
result = (60 * 24 * 7 * 52);
|
||||||
|
|
||||||
|
return(result * 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Propagated bans are expired elsewhere. */
|
||||||
|
static void
|
||||||
|
expire_temp_rxlines(void *unused)
|
||||||
|
{
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
rb_dlink_node *next_ptr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
HASH_WALK_SAFE(i, R_MAX, ptr, next_ptr, resvTable)
|
||||||
|
{
|
||||||
|
aconf = ptr->data;
|
||||||
|
|
||||||
|
if(aconf->lifetime != 0)
|
||||||
|
continue;
|
||||||
|
if(aconf->hold && aconf->hold <= rb_current_time())
|
||||||
|
{
|
||||||
|
if(ConfigFileEntry.tkline_expire_notices)
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Temporary RESV for [%s] expired",
|
||||||
|
aconf->host);
|
||||||
|
|
||||||
|
free_conf(aconf);
|
||||||
|
rb_dlinkDestroy(ptr, &resvTable[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HASH_WALK_END
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, resv_conf_list.head)
|
||||||
|
{
|
||||||
|
aconf = ptr->data;
|
||||||
|
|
||||||
|
if(aconf->lifetime != 0)
|
||||||
|
continue;
|
||||||
|
if(aconf->hold && aconf->hold <= rb_current_time())
|
||||||
|
{
|
||||||
|
if(ConfigFileEntry.tkline_expire_notices)
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Temporary RESV for [%s] expired",
|
||||||
|
aconf->host);
|
||||||
|
free_conf(aconf);
|
||||||
|
rb_dlinkDestroy(ptr, &resv_conf_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, xline_conf_list.head)
|
||||||
|
{
|
||||||
|
aconf = ptr->data;
|
||||||
|
|
||||||
|
if(aconf->lifetime != 0)
|
||||||
|
continue;
|
||||||
|
if(aconf->hold && aconf->hold <= rb_current_time())
|
||||||
|
{
|
||||||
|
if(ConfigFileEntry.tkline_expire_notices)
|
||||||
|
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||||
|
"Temporary X-line for [%s] expired",
|
||||||
|
aconf->host);
|
||||||
|
free_conf(aconf);
|
||||||
|
rb_dlinkDestroy(ptr, &xline_conf_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long
|
||||||
|
get_nd_count(void)
|
||||||
|
{
|
||||||
|
return(rb_dlink_list_length(&nd_list));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
add_nd_entry(const char *name)
|
||||||
|
{
|
||||||
|
struct nd_entry *nd;
|
||||||
|
|
||||||
|
if(irc_dictionary_find(nd_dict, name) != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nd = rb_bh_alloc(nd_heap);
|
||||||
|
|
||||||
|
rb_strlcpy(nd->name, name, sizeof(nd->name));
|
||||||
|
nd->expire = rb_current_time() + ConfigFileEntry.nick_delay;
|
||||||
|
|
||||||
|
/* this list is ordered */
|
||||||
|
rb_dlinkAddTail(nd, &nd->lnode, &nd_list);
|
||||||
|
|
||||||
|
irc_dictionary_add(nd_dict, nd->name, nd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free_nd_entry(struct nd_entry *nd)
|
||||||
|
{
|
||||||
|
irc_dictionary_delete(nd_dict, nd->name);
|
||||||
|
|
||||||
|
rb_dlinkDelete(&nd->lnode, &nd_list);
|
||||||
|
rb_bh_free(nd_heap, nd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
expire_nd_entries(void *unused)
|
||||||
|
{
|
||||||
|
struct nd_entry *nd;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
rb_dlink_node *next_ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, nd_list.head)
|
||||||
|
{
|
||||||
|
nd = ptr->data;
|
||||||
|
|
||||||
|
/* this list is ordered - we can stop when we hit the first
|
||||||
|
* entry that doesnt expire..
|
||||||
|
*/
|
||||||
|
if(nd->expire > rb_current_time())
|
||||||
|
return;
|
||||||
|
|
||||||
|
free_nd_entry(nd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
add_tgchange(const char *host)
|
||||||
|
{
|
||||||
|
tgchange *target;
|
||||||
|
rb_patricia_node_t *pnode;
|
||||||
|
|
||||||
|
if(find_tgchange(host))
|
||||||
|
return;
|
||||||
|
|
||||||
|
target = rb_malloc(sizeof(tgchange));
|
||||||
|
pnode = make_and_lookup(tgchange_tree, host);
|
||||||
|
|
||||||
|
pnode->data = target;
|
||||||
|
target->pnode = pnode;
|
||||||
|
|
||||||
|
target->ip = rb_strdup(host);
|
||||||
|
target->expiry = rb_current_time() + (60*60*12);
|
||||||
|
|
||||||
|
rb_dlinkAdd(target, &target->node, &tgchange_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
tgchange *
|
||||||
|
find_tgchange(const char *host)
|
||||||
|
{
|
||||||
|
rb_patricia_node_t *pnode;
|
||||||
|
|
||||||
|
if((pnode = rb_match_exact_string(tgchange_tree, host)))
|
||||||
|
return pnode->data;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct vhost_conf *
|
||||||
|
find_ssl_vhost(const char *hostname)
|
||||||
|
{
|
||||||
|
struct vhost_conf *vhost_p;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, vhost_conf_list.head)
|
||||||
|
{
|
||||||
|
vhost_p = ptr->data;
|
||||||
|
|
||||||
|
if(!strcmp(hostname,vhost_p->hostname))
|
||||||
|
return vhost_p;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct vhost_conf *
|
||||||
|
make_vhost_conf(void)
|
||||||
|
{
|
||||||
|
struct vhost_conf *vhost_p = rb_malloc(sizeof(struct vhost_conf));
|
||||||
|
return vhost_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free_vhost_conf(struct vhost_conf *vhost_p)
|
||||||
|
{
|
||||||
|
s_assert(vhost_p != NULL);
|
||||||
|
if(vhost_p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rb_free(vhost_p->hostname);
|
||||||
|
rb_free(vhost_p->ssl_private_key);
|
||||||
|
rb_free(vhost_p->ssl_cert);
|
||||||
|
rb_free(vhost_p->ssl_dh_params);
|
||||||
|
rb_free(vhost_p->ssl_cipher_list);
|
||||||
|
|
||||||
|
rb_free(vhost_p);
|
||||||
|
}
|
||||||
|
// TODO: Free vhost_conf_list
|
1400
src/s_serv.c
Normal file
1400
src/s_serv.c
Normal file
File diff suppressed because it is too large
Load diff
1517
src/s_user.c
Normal file
1517
src/s_user.c
Normal file
File diff suppressed because it is too large
Load diff
1023
src/sslproc.c
Normal file
1023
src/sslproc.c
Normal file
File diff suppressed because it is too large
Load diff
348
src/supported.c
Normal file
348
src/supported.c
Normal file
|
@ -0,0 +1,348 @@
|
||||||
|
/*
|
||||||
|
* charybdis: A slightly useful ircd.
|
||||||
|
* supported.c: isupport (005) numeric
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Jilles Tjoelker
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* 1.Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2.Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3.The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id: supported.c 3568 2007-09-09 18:59:08Z jilles $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* From the old supported.h which is
|
||||||
|
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||||
|
* Copyright (C) 2002-2004 ircd-ratbox development team
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* - from mirc's versions.txt
|
||||||
|
*
|
||||||
|
* mIRC now supports the numeric 005 tokens: CHANTYPES=# and
|
||||||
|
* PREFIX=(ohv)@%+ and can handle a dynamic set of channel and
|
||||||
|
* nick prefixes.
|
||||||
|
*
|
||||||
|
* mIRC assumes that @ is supported on all networks, any mode
|
||||||
|
* left of @ is assumed to have at least equal power to @, and
|
||||||
|
* any mode right of @ has less power.
|
||||||
|
*
|
||||||
|
* mIRC has internal support for @%+ modes.
|
||||||
|
*
|
||||||
|
* $nick() can now handle all mode letters listed in PREFIX.
|
||||||
|
*
|
||||||
|
* Also added support for CHANMODES=A,B,C,D token (not currently
|
||||||
|
* supported by any servers), which lists all modes supported
|
||||||
|
* by a channel, where:
|
||||||
|
*
|
||||||
|
* A = modes that take a parameter, and add or remove nicks
|
||||||
|
* or addresses to a list, such as +bIe for the ban,
|
||||||
|
* invite, and exception lists.
|
||||||
|
*
|
||||||
|
* B = modes that change channel settings, but which take
|
||||||
|
* a parameter when they are set and unset, such as
|
||||||
|
* +k key, and -k key.
|
||||||
|
*
|
||||||
|
* C = modes that change channel settings, but which take
|
||||||
|
* a parameter only when they are set, such as +l N,
|
||||||
|
* and -l.
|
||||||
|
*
|
||||||
|
* D = modes that change channel settings, such as +imnpst
|
||||||
|
* and take no parameters.
|
||||||
|
*
|
||||||
|
* All unknown/unlisted modes are treated as type D.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "numeric.h"
|
||||||
|
#include "ircd.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "s_user.h"
|
||||||
|
#include "supported.h"
|
||||||
|
#include "chmode.h"
|
||||||
|
#include "send.h"
|
||||||
|
|
||||||
|
rb_dlink_list isupportlist;
|
||||||
|
|
||||||
|
struct isupportitem
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
const char *(*func)(const void *);
|
||||||
|
const void *param;
|
||||||
|
rb_dlink_node node;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
add_isupport(const char *name, const char *(*func)(const void *), const void *param)
|
||||||
|
{
|
||||||
|
struct isupportitem *item;
|
||||||
|
|
||||||
|
item = rb_malloc(sizeof(struct isupportitem));
|
||||||
|
item->name = name;
|
||||||
|
item->func = func;
|
||||||
|
item->param = param;
|
||||||
|
rb_dlinkAddTail(item, &item->node, &isupportlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
change_isupport(const char *name, const char *(*func)(const void *), const void *param)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
struct isupportitem *item;
|
||||||
|
const void *oldvalue = NULL;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, isupportlist.head)
|
||||||
|
{
|
||||||
|
item = ptr->data;
|
||||||
|
|
||||||
|
if (!strcmp(item->name, name))
|
||||||
|
{
|
||||||
|
oldvalue = item->param;
|
||||||
|
|
||||||
|
// item->name = name;
|
||||||
|
item->func = func;
|
||||||
|
item->param = param;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return oldvalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
delete_isupport(const char *name)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr, *next_ptr;
|
||||||
|
struct isupportitem *item;
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, isupportlist.head)
|
||||||
|
{
|
||||||
|
item = ptr->data;
|
||||||
|
|
||||||
|
if (!strcmp(item->name, name))
|
||||||
|
{
|
||||||
|
rb_dlinkDelete(ptr, &isupportlist);
|
||||||
|
rb_free(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX caching? */
|
||||||
|
void
|
||||||
|
show_isupport(struct Client *client_p)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
struct isupportitem *item;
|
||||||
|
const char *value;
|
||||||
|
char buf[512];
|
||||||
|
int extra_space;
|
||||||
|
unsigned int nchars, nparams;
|
||||||
|
int l;
|
||||||
|
|
||||||
|
extra_space = strlen(client_p->name);
|
||||||
|
/* UID */
|
||||||
|
if (!MyClient(client_p) && extra_space < 9)
|
||||||
|
extra_space = 9;
|
||||||
|
/* :<me.name> 005 <nick> <params> :are supported by this server */
|
||||||
|
/* form_str(RPL_ISUPPORT) is %s :are supported by this server */
|
||||||
|
extra_space += strlen(me.name) + 1 + strlen(form_str(RPL_ISUPPORT));
|
||||||
|
|
||||||
|
nchars = extra_space;
|
||||||
|
nparams = 0;
|
||||||
|
buf[0] = '\0';
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH(ptr, isupportlist.head)
|
||||||
|
{
|
||||||
|
item = ptr->data;
|
||||||
|
value = (*item->func)(item->param);
|
||||||
|
if (value == NULL)
|
||||||
|
continue;
|
||||||
|
l = strlen(item->name) + (EmptyString(value) ? 0 : 1 + strlen(value));
|
||||||
|
if (nchars + l + (nparams > 0) >= sizeof buf || nparams + 1 > 12)
|
||||||
|
{
|
||||||
|
sendto_one_numeric(client_p, RPL_ISUPPORT, form_str(RPL_ISUPPORT), buf);
|
||||||
|
nchars = extra_space;
|
||||||
|
nparams = 0;
|
||||||
|
buf[0] = '\0';
|
||||||
|
}
|
||||||
|
if (nparams > 0)
|
||||||
|
{
|
||||||
|
rb_strlcat(buf, " ", sizeof buf);
|
||||||
|
nchars++;
|
||||||
|
}
|
||||||
|
rb_strlcat(buf, item->name, sizeof buf);
|
||||||
|
if (!EmptyString(value))
|
||||||
|
{
|
||||||
|
rb_strlcat(buf, "=", sizeof buf);
|
||||||
|
rb_strlcat(buf, value, sizeof buf);
|
||||||
|
}
|
||||||
|
nchars += l;
|
||||||
|
nparams++;
|
||||||
|
}
|
||||||
|
if (nparams > 0)
|
||||||
|
sendto_one_numeric(client_p, RPL_ISUPPORT, form_str(RPL_ISUPPORT), buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
isupport_intptr(const void *ptr)
|
||||||
|
{
|
||||||
|
static char buf[15];
|
||||||
|
rb_snprintf(buf, sizeof buf, "%d", *(const int *)ptr);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
isupport_boolean(const void *ptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
return *(const int *)ptr ? "" : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
isupport_string(const void *ptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (const char *)ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
isupport_stringptr(const void *ptr)
|
||||||
|
{
|
||||||
|
return *(char * const *)ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
isupport_umode(const void *ptr)
|
||||||
|
{
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
str = ptr;
|
||||||
|
return ConfigFileEntry.oper_only_umodes &
|
||||||
|
user_modes[(unsigned char)*str] ? NULL : str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
isupport_chanmodes(const void *ptr)
|
||||||
|
{
|
||||||
|
static char result[80];
|
||||||
|
|
||||||
|
rb_snprintf(result, sizeof result, "%s%sbq,k,%slj,%s",
|
||||||
|
ConfigChannel.use_except ? "e" : "",
|
||||||
|
ConfigChannel.use_invex ? "I" : "",
|
||||||
|
ConfigChannel.use_forward ? "f" : "",
|
||||||
|
cflagsbuf);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
isupport_chantypes(const void *ptr)
|
||||||
|
{
|
||||||
|
return ConfigChannel.disable_local_channels ? "#" : "&#";
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
isupport_chanlimit(const void *ptr)
|
||||||
|
{
|
||||||
|
static char result[30];
|
||||||
|
|
||||||
|
rb_snprintf(result, sizeof result, "%s:%i",
|
||||||
|
ConfigChannel.disable_local_channels ? "#" : "&#", ConfigChannel.max_chans_per_user);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
isupport_maxlist(const void *ptr)
|
||||||
|
{
|
||||||
|
static char result[30];
|
||||||
|
|
||||||
|
rb_snprintf(result, sizeof result, "bq%s%s:%i",
|
||||||
|
ConfigChannel.use_except ? "e" : "",
|
||||||
|
ConfigChannel.use_invex ? "I" : "",
|
||||||
|
ConfigChannel.max_bans);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
isupport_targmax(const void *ptr)
|
||||||
|
{
|
||||||
|
static char result[200];
|
||||||
|
|
||||||
|
rb_snprintf(result, sizeof result, "NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:%d,NOTICE:%d,ACCEPT:,MONITOR:",
|
||||||
|
ConfigFileEntry.max_targets,
|
||||||
|
ConfigFileEntry.max_targets);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
isupport_extban(const void *ptr)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
static char result[200];
|
||||||
|
|
||||||
|
p = get_extban_string();
|
||||||
|
if (EmptyString(p))
|
||||||
|
return NULL;
|
||||||
|
rb_snprintf(result, sizeof result, "$,%s", p);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
isupport_nicklen(const void *ptr)
|
||||||
|
{
|
||||||
|
static char result[200];
|
||||||
|
|
||||||
|
rb_snprintf(result, sizeof result, "%u", ConfigFileEntry.nicklen - 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init_isupport(void)
|
||||||
|
{
|
||||||
|
static int maxmodes = MAXMODEPARAMS;
|
||||||
|
static int channellen = LOC_CHANNELLEN;
|
||||||
|
static int topiclen = TOPICLEN;
|
||||||
|
static int maxnicklen = NICKLEN - 1;
|
||||||
|
|
||||||
|
add_isupport("CHANTYPES", isupport_chantypes, NULL);
|
||||||
|
add_isupport("EXCEPTS", isupport_boolean, &ConfigChannel.use_except);
|
||||||
|
add_isupport("INVEX", isupport_boolean, &ConfigChannel.use_invex);
|
||||||
|
add_isupport("CHANMODES", isupport_chanmodes, NULL);
|
||||||
|
add_isupport("CHANLIMIT", isupport_chanlimit, NULL);
|
||||||
|
add_isupport("PREFIX", isupport_string, "(ov)@+");
|
||||||
|
add_isupport("MAXLIST", isupport_maxlist, NULL);
|
||||||
|
add_isupport("MODES", isupport_intptr, &maxmodes);
|
||||||
|
add_isupport("NETWORK", isupport_stringptr, &ServerInfo.network_name);
|
||||||
|
add_isupport("STATUSMSG", isupport_string, "@+");
|
||||||
|
add_isupport("CALLERID", isupport_umode, "g");
|
||||||
|
add_isupport("CASEMAPPING", isupport_string, "rfc1459");
|
||||||
|
add_isupport("NICKLEN", isupport_nicklen, NULL);
|
||||||
|
add_isupport("MAXNICKLEN", isupport_intptr, &maxnicklen);
|
||||||
|
add_isupport("CHANNELLEN", isupport_intptr, &channellen);
|
||||||
|
add_isupport("TOPICLEN", isupport_intptr, &topiclen);
|
||||||
|
add_isupport("DEAF", isupport_umode, "D");
|
||||||
|
add_isupport("TARGMAX", isupport_targmax, NULL);
|
||||||
|
add_isupport("EXTBAN", isupport_extban, NULL);
|
||||||
|
add_isupport("CLIENTVER", isupport_string, "3.0");
|
||||||
|
}
|
216
ssld/ssld.c
216
ssld/ssld.c
|
@ -133,8 +133,19 @@ static void conn_plain_read_cb(rb_fde_t *fd, void *data);
|
||||||
static void conn_plain_read_shutdown_cb(rb_fde_t *fd, void *data);
|
static void conn_plain_read_shutdown_cb(rb_fde_t *fd, void *data);
|
||||||
static void mod_cmd_write_queue(mod_ctl_t * ctl, const void *data, size_t len);
|
static void mod_cmd_write_queue(mod_ctl_t * ctl, const void *data, size_t len);
|
||||||
static const char *remote_closed = "Remote host closed the connection";
|
static const char *remote_closed = "Remote host closed the connection";
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
static int ssld_ssl_ok;
|
||||||
|
static int certfp_method = RB_SSL_CERTFP_METH_CERT_SHA1;
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
static int ssld_zlib_ok = 1;
|
||||||
|
#else
|
||||||
|
static int ssld_zlib_ok = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
=======
|
||||||
static bool ssld_ssl_ok;
|
static bool ssld_ssl_ok;
|
||||||
static int certfp_method = RB_SSL_CERTFP_METH_CERT_SHA1;
|
static int certfp_method = RB_SSL_CERTFP_METH_CERT_SHA1;
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
|
|
||||||
|
|
||||||
static conn_t *
|
static conn_t *
|
||||||
|
@ -164,6 +175,18 @@ free_conn(conn_t * conn)
|
||||||
{
|
{
|
||||||
rb_free_rawbuffer(conn->modbuf_out);
|
rb_free_rawbuffer(conn->modbuf_out);
|
||||||
rb_free_rawbuffer(conn->plainbuf_out);
|
rb_free_rawbuffer(conn->plainbuf_out);
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
if(IsZip(conn))
|
||||||
|
{
|
||||||
|
zlib_stream_t *stream = conn->stream;
|
||||||
|
inflateEnd(&stream->instream);
|
||||||
|
deflateEnd(&stream->outstream);
|
||||||
|
rb_free(stream);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
rb_free(conn);
|
rb_free(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,6 +588,8 @@ ssl_send_certfp(conn_t *conn)
|
||||||
uint32_to_buf(&buf[5], certfp_method);
|
uint32_to_buf(&buf[5], certfp_method);
|
||||||
uint32_to_buf(&buf[9], len);
|
uint32_to_buf(&buf[9], len);
|
||||||
mod_cmd_write_queue(conn->ctl, buf, 13 + len);
|
mod_cmd_write_queue(conn->ctl, buf, 13 + len);
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
=======
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -575,6 +600,7 @@ ssl_send_open(conn_t *conn)
|
||||||
buf[0] = 'O';
|
buf[0] = 'O';
|
||||||
uint32_to_buf(&buf[1], conn->id);
|
uint32_to_buf(&buf[1], conn->id);
|
||||||
mod_cmd_write_queue(conn->ctl, buf, 5);
|
mod_cmd_write_queue(conn->ctl, buf, 5);
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -586,7 +612,10 @@ ssl_process_accept_cb(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen
|
||||||
{
|
{
|
||||||
ssl_send_cipher(conn);
|
ssl_send_cipher(conn);
|
||||||
ssl_send_certfp(conn);
|
ssl_send_certfp(conn);
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
=======
|
||||||
ssl_send_open(conn);
|
ssl_send_open(conn);
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
conn_mod_read_cb(conn->mod_fd, conn);
|
conn_mod_read_cb(conn->mod_fd, conn);
|
||||||
conn_plain_read_cb(conn->plain_fd, conn);
|
conn_plain_read_cb(conn->plain_fd, conn);
|
||||||
return;
|
return;
|
||||||
|
@ -605,7 +634,10 @@ ssl_process_connect_cb(rb_fde_t *F, int status, void *data)
|
||||||
{
|
{
|
||||||
ssl_send_cipher(conn);
|
ssl_send_cipher(conn);
|
||||||
ssl_send_certfp(conn);
|
ssl_send_certfp(conn);
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
=======
|
||||||
ssl_send_open(conn);
|
ssl_send_open(conn);
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
conn_mod_read_cb(conn->mod_fd, conn);
|
conn_mod_read_cb(conn->mod_fd, conn);
|
||||||
conn_plain_read_cb(conn->plain_fd, conn);
|
conn_plain_read_cb(conn->plain_fd, conn);
|
||||||
}
|
}
|
||||||
|
@ -692,11 +724,17 @@ process_stats(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
|
||||||
if(conn == NULL)
|
if(conn == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
rb_snprintf(outstat, sizeof(outstat), "S %s %llu %llu %llu %llu", odata,
|
||||||
|
(unsigned long long) conn->plain_out, (unsigned long long) conn->mod_in,
|
||||||
|
(unsigned long long) conn->plain_in, (unsigned long long) conn->mod_out);
|
||||||
|
=======
|
||||||
snprintf(outstat, sizeof(outstat), "S %s %llu %llu %llu %llu", odata,
|
snprintf(outstat, sizeof(outstat), "S %s %llu %llu %llu %llu", odata,
|
||||||
(unsigned long long)conn->plain_out,
|
(unsigned long long)conn->plain_out,
|
||||||
(unsigned long long)conn->mod_in,
|
(unsigned long long)conn->mod_in,
|
||||||
(unsigned long long)conn->plain_in,
|
(unsigned long long)conn->plain_in,
|
||||||
(unsigned long long)conn->mod_out);
|
(unsigned long long)conn->mod_out);
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
conn->plain_out = 0;
|
conn->plain_out = 0;
|
||||||
conn->plain_in = 0;
|
conn->plain_in = 0;
|
||||||
conn->mod_in = 0;
|
conn->mod_in = 0;
|
||||||
|
@ -705,10 +743,109 @@ process_stats(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
change_connid(mod_ctl_t *ctl, mod_ctl_buf_t *ctlb)
|
||||||
|
{
|
||||||
|
uint32_t id = buf_to_uint32(&ctlb->buf[1]);
|
||||||
|
uint32_t newid = buf_to_uint32(&ctlb->buf[5]);
|
||||||
|
conn_t *conn = conn_find_by_id(id);
|
||||||
|
lrb_assert(conn != NULL);
|
||||||
|
if(conn == NULL)
|
||||||
|
{
|
||||||
|
uint8_t buf[256];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
buf[0] = 'D';
|
||||||
|
uint32_to_buf(&buf[1], newid);
|
||||||
|
sprintf((char *) &buf[5], "connid %d does not exist", id);
|
||||||
|
len = (strlen((char *) &buf[5]) + 1) + 5;
|
||||||
|
mod_cmd_write_queue(ctl, buf, len);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rb_dlinkDelete(&conn->node, connid_hash(conn->id));
|
||||||
|
SetZipSSL(conn);
|
||||||
|
conn->id = newid;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
static void
|
||||||
|
zlib_process(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
|
||||||
|
{
|
||||||
|
uint8_t level;
|
||||||
|
size_t recvqlen;
|
||||||
|
size_t hdr = (sizeof(uint8_t) * 2) + sizeof(uint32_t);
|
||||||
|
void *recvq_start;
|
||||||
|
z_stream *instream, *outstream;
|
||||||
|
conn_t *conn;
|
||||||
|
uint32_t id;
|
||||||
|
|
||||||
|
conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
|
||||||
|
if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN)
|
||||||
|
rb_set_type(conn->mod_fd, RB_FD_SOCKET);
|
||||||
|
|
||||||
|
if(rb_get_type(conn->plain_fd) == RB_FD_UNKNOWN)
|
||||||
|
rb_set_type(conn->plain_fd, RB_FD_SOCKET);
|
||||||
|
|
||||||
|
id = buf_to_uint32(&ctlb->buf[1]);
|
||||||
|
conn_add_id_hash(conn, id);
|
||||||
|
|
||||||
|
level = (uint8_t)ctlb->buf[5];
|
||||||
|
|
||||||
|
recvqlen = ctlb->buflen - hdr;
|
||||||
|
recvq_start = &ctlb->buf[6];
|
||||||
|
|
||||||
|
SetZip(conn);
|
||||||
|
conn->stream = rb_malloc(sizeof(zlib_stream_t));
|
||||||
|
instream = &((zlib_stream_t *) conn->stream)->instream;
|
||||||
|
outstream = &((zlib_stream_t *) conn->stream)->outstream;
|
||||||
|
|
||||||
|
instream->total_in = 0;
|
||||||
|
instream->total_out = 0;
|
||||||
|
instream->zalloc = (alloc_func) ssld_alloc;
|
||||||
|
instream->zfree = (free_func) ssld_free;
|
||||||
|
instream->data_type = Z_ASCII;
|
||||||
|
inflateInit(&((zlib_stream_t *) conn->stream)->instream);
|
||||||
|
|
||||||
|
outstream->total_in = 0;
|
||||||
|
outstream->total_out = 0;
|
||||||
|
outstream->zalloc = (alloc_func) ssld_alloc;
|
||||||
|
outstream->zfree = (free_func) ssld_free;
|
||||||
|
outstream->data_type = Z_ASCII;
|
||||||
|
|
||||||
|
if(level > 9)
|
||||||
|
level = (uint8_t) Z_DEFAULT_COMPRESSION;
|
||||||
|
|
||||||
|
deflateInit(&((zlib_stream_t *) conn->stream)->outstream, level);
|
||||||
|
if(recvqlen > 0)
|
||||||
|
common_zlib_inflate(conn, recvq_start, recvqlen);
|
||||||
|
|
||||||
|
conn_mod_read_cb(conn->mod_fd, conn);
|
||||||
|
conn_plain_read_cb(conn->plain_fd, conn);
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_prng(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
|
||||||
|
{
|
||||||
|
char *path;
|
||||||
|
prng_seed_t seed_type;
|
||||||
|
|
||||||
|
seed_type = (prng_seed_t) ctl_buf->buf[1];
|
||||||
|
path = (char *) &ctl_buf->buf[2];
|
||||||
|
rb_init_prng(path, seed_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
|
ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
char *cert, *key, *dhparam, *cipher_list;
|
char *cert, *key, *dhparam, *cipher_list, *hostname;
|
||||||
|
|
||||||
buf = (char *) &ctl_buf->buf[2];
|
buf = (char *) &ctl_buf->buf[2];
|
||||||
cert = buf;
|
cert = buf;
|
||||||
|
@ -718,6 +855,11 @@ ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
|
||||||
dhparam = buf;
|
dhparam = buf;
|
||||||
buf += strlen(dhparam) + 1;
|
buf += strlen(dhparam) + 1;
|
||||||
cipher_list = buf;
|
cipher_list = buf;
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
buf += strlen(cipher_list) + 1;
|
||||||
|
hostname = buf;
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
if(strlen(key) == 0)
|
if(strlen(key) == 0)
|
||||||
key = cert;
|
key = cert;
|
||||||
if(strlen(dhparam) == 0)
|
if(strlen(dhparam) == 0)
|
||||||
|
@ -725,7 +867,15 @@ ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
|
||||||
if(strlen(cipher_list) == 0)
|
if(strlen(cipher_list) == 0)
|
||||||
cipher_list = NULL;
|
cipher_list = NULL;
|
||||||
|
|
||||||
if(!rb_setup_ssl_server(cert, key, dhparam, cipher_list))
|
int ret;
|
||||||
|
if(strlen(hostname) == 0) {
|
||||||
|
ret = rb_setup_ssl_server(cert, key, dhparam, cipher_list, NULL);
|
||||||
|
} else {
|
||||||
|
ret = rb_setup_ssl_server(cert, key, dhparam, cipher_list, hostname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ret)
|
||||||
{
|
{
|
||||||
const char *invalid = "I";
|
const char *invalid = "I";
|
||||||
mod_cmd_write_queue(ctl, invalid, strlen(invalid));
|
mod_cmd_write_queue(ctl, invalid, strlen(invalid));
|
||||||
|
@ -733,6 +883,24 @@ ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ssl_remove_ssl_vhost(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
char *hostname;
|
||||||
|
|
||||||
|
buf = (char *) &ctl_buf->buf[2];
|
||||||
|
hostname = buf;
|
||||||
|
|
||||||
|
if(!rb_remove_ssl_vserver(hostname))
|
||||||
|
{
|
||||||
|
const char *invalid = "I";
|
||||||
|
mod_cmd_write_queue(ctl, invalid, strlen(invalid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
send_nossl_support(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
|
send_nossl_support(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
|
||||||
{
|
{
|
||||||
|
@ -845,6 +1013,22 @@ mod_process_cmd_recv(mod_ctl_t * ctl)
|
||||||
ssl_new_keys(ctl, ctl_buf);
|
ssl_new_keys(ctl, ctl_buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
case 'D':
|
||||||
|
{
|
||||||
|
if(!ssld_ssl_ok)
|
||||||
|
{
|
||||||
|
send_nossl_support(ctl, ctl_buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ssl_remove_ssl_vhost(ctl, ctl_buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'I':
|
||||||
|
init_prng(ctl, ctl_buf);
|
||||||
|
break;
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
case 'S':
|
case 'S':
|
||||||
{
|
{
|
||||||
process_stats(ctl, ctl_buf);
|
process_stats(ctl, ctl_buf);
|
||||||
|
@ -956,7 +1140,11 @@ int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *s_ctlfd, *s_pipe, *s_pid;
|
const char *s_ctlfd, *s_pipe, *s_pid;
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
int ctlfd, pipefd, maxfd;
|
||||||
|
=======
|
||||||
int ctlfd, pipefd, maxfd, x;
|
int ctlfd, pipefd, maxfd, x;
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
maxfd = maxconn();
|
maxfd = maxconn();
|
||||||
|
|
||||||
s_ctlfd = getenv("CTL_FD");
|
s_ctlfd = getenv("CTL_FD");
|
||||||
|
@ -976,6 +1164,12 @@ main(int argc, char **argv)
|
||||||
pipefd = atoi(s_pipe);
|
pipefd = atoi(s_pipe);
|
||||||
ppid = atoi(s_pid);
|
ppid = atoi(s_pid);
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
#ifndef _WIN32
|
||||||
|
int x;
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
for(x = 3; x < maxfd; x++)
|
for(x = 3; x < maxfd; x++)
|
||||||
{
|
{
|
||||||
if(x != ctlfd && x != pipefd)
|
if(x != ctlfd && x != pipefd)
|
||||||
|
@ -995,11 +1189,18 @@ main(int argc, char **argv)
|
||||||
if(x > 2)
|
if(x > 2)
|
||||||
close(x);
|
close(x);
|
||||||
}
|
}
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
#endif
|
||||||
|
=======
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
|
|
||||||
setup_signals();
|
setup_signals();
|
||||||
rb_lib_init(NULL, NULL, NULL, 0, maxfd, 1024, 4096);
|
rb_lib_init(NULL, NULL, NULL, 0, maxfd, 1024, 4096);
|
||||||
rb_init_rawbuffers(1024);
|
rb_init_rawbuffers(1024);
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
=======
|
||||||
rb_init_prng(NULL, RB_PRNG_DEFAULT);
|
rb_init_prng(NULL, RB_PRNG_DEFAULT);
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
ssld_ssl_ok = rb_supports_ssl();
|
ssld_ssl_ok = rb_supports_ssl();
|
||||||
mod_ctl = rb_malloc(sizeof(mod_ctl_t));
|
mod_ctl = rb_malloc(sizeof(mod_ctl_t));
|
||||||
mod_ctl->F = rb_open(ctlfd, RB_FD_SOCKET, "ircd control socket");
|
mod_ctl->F = rb_open(ctlfd, RB_FD_SOCKET, "ircd control socket");
|
||||||
|
@ -1010,8 +1211,12 @@ main(int argc, char **argv)
|
||||||
rb_event_add("check_handshake_flood", check_handshake_flood, NULL, 10);
|
rb_event_add("check_handshake_flood", check_handshake_flood, NULL, 10);
|
||||||
read_pipe_ctl(mod_ctl->F_pipe, NULL);
|
read_pipe_ctl(mod_ctl->F_pipe, NULL);
|
||||||
mod_read_ctl(mod_ctl->F, mod_ctl);
|
mod_read_ctl(mod_ctl->F, mod_ctl);
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
if(!ssld_zlib_ok && !ssld_ssl_ok)
|
||||||
|
=======
|
||||||
send_version(mod_ctl);
|
send_version(mod_ctl);
|
||||||
if(!ssld_ssl_ok)
|
if(!ssld_ssl_ok)
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
{
|
{
|
||||||
/* this is really useless... */
|
/* this is really useless... */
|
||||||
send_i_am_useless(mod_ctl);
|
send_i_am_useless(mod_ctl);
|
||||||
|
@ -1020,11 +1225,16 @@ main(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< .merge_file_7dGMbH
|
||||||
|
if(!ssld_zlib_ok)
|
||||||
|
send_nozlib_support(mod_ctl, NULL);
|
||||||
|
=======
|
||||||
send_nozlib_support(mod_ctl, NULL);
|
send_nozlib_support(mod_ctl, NULL);
|
||||||
|
>>>>>>> .merge_file_Ch5lvI
|
||||||
if(!ssld_ssl_ok)
|
if(!ssld_ssl_ok)
|
||||||
send_nossl_support(mod_ctl, NULL);
|
send_nossl_support(mod_ctl, NULL);
|
||||||
rb_lib_loop(0);
|
rb_lib_loop(0);
|
||||||
return 0;
|
/* UNREACHABLE */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -96,11 +96,9 @@ main(int argc, char *argv[])
|
||||||
case 'h':
|
case 'h':
|
||||||
full_usage();
|
full_usage();
|
||||||
/* NOT REACHED */
|
/* NOT REACHED */
|
||||||
break;
|
|
||||||
case '?':
|
case '?':
|
||||||
brief_usage();
|
brief_usage();
|
||||||
/* NOT REACHED */
|
/* NOT REACHED */
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
printf("Invalid Option: -%c\n", c);
|
printf("Invalid Option: -%c\n", c);
|
||||||
break;
|
break;
|
||||||
|
@ -371,7 +369,7 @@ generate_random_salt(char *salt, int length)
|
||||||
return (salt);
|
return (salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
full_usage()
|
full_usage()
|
||||||
{
|
{
|
||||||
printf("mkpasswd [-m|-b|-x|-y] [-l saltlength] [-r rounds] [-s salt] [-p plaintext]\n");
|
printf("mkpasswd [-m|-b|-x|-y] [-l saltlength] [-r rounds] [-s salt] [-p plaintext]\n");
|
||||||
|
@ -389,7 +387,7 @@ full_usage()
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
brief_usage()
|
brief_usage()
|
||||||
{
|
{
|
||||||
printf("mkpasswd - password hash generator\n");
|
printf("mkpasswd - password hash generator\n");
|
||||||
|
|
Loading…
Reference in a new issue