From 4ab19268268cd96b9706625d42a16d2a629134eb Mon Sep 17 00:00:00 2001 From: Jannis Hoffmann Date: Sat, 28 Sep 2024 17:13:21 +0200 Subject: update to version 25 --- BUILD | 2 +- CHANGELOG | 12 ++ CONTENT | 63 ------- CONTENT.md | 63 +++++++ FILES | 329 +++++++++++++++++----------------- INSTALL.md | 116 ++++++++++++ Makefile | 123 ------------- README.md | 90 ++-------- VERSION | 2 +- alloc.c | 50 ------ base64.c | 124 ------------- buffer.c | 226 ----------------------- byte.c | 99 ---------- case.c | 134 -------------- cdbmake.c | 158 ---------------- cdbread.c | 169 ------------------ conf-build | 2 +- configure | 2 +- constmap.c | 169 ------------------ dnsstub/Makefile | 23 --- dnsstub/README.md | 171 ------------------ dnsstub/TARGETS | 18 -- dnsstub/dns_cname.c | 59 ------ dnsstub/dns_dfd.c | 76 -------- dnsstub/dns_domain.c | 80 --------- dnsstub/dns_dtda.c | 43 ----- dnsstub/dns_ip.c | 198 -------------------- dnsstub/dns_ipq.c | 236 ------------------------ dnsstub/dns_mx.c | 63 ------- dnsstub/dns_name.c | 80 --------- dnsstub/dns_nd.c | 48 ----- dnsstub/dns_packet.c | 85 --------- dnsstub/dns_random.c | 70 -------- dnsstub/dns_rcip.c | 114 ------------ dnsstub/dns_rcrw.c | 141 --------------- dnsstub/dns_resolve.c | 39 ---- dnsstub/dns_sortip.c | 45 ----- dnsstub/dns_transmit.c | 436 --------------------------------------------- dnsstub/dns_txt.c | 64 ------- env.c | 136 -------------- errstr.c | 163 ----------------- fd.c | 30 ---- fmt.c | 85 --------- getln.c | 43 ----- getoptb.c | 100 ----------- include/alloc.h | 6 +- include/base64.h | 6 +- include/byte.h | 23 ++- include/cdbmake.h | 9 +- include/constmap.h | 6 +- include/exit.h | 8 +- include/fifo.h | 8 +- include/fmt.h | 14 +- include/genalloc.h | 4 +- include/getoptb.h | 4 + include/lock.h | 8 +- include/ndelay.h | 8 +- include/open.h | 8 +- include/select.h | 2 +- include/sig.h | 67 +++---- include/str.h | 4 +- include/uint_t.h | 24 +-- include/wait.h | 8 +- install | 6 +- iopause.c | 84 --------- ip4.c | 166 ----------------- ip6.c | 360 ------------------------------------- lock.c | 22 --- logmsg.c | 97 ---------- man/buffer.3 | 10 +- man/getln.3 | 38 ++-- man/getoptb.3 | 2 +- ndelay.c | 24 --- open.c | 25 --- pathexec.c | 121 ------------- prot.c | 31 ---- readclose.c | 43 ----- scan.c | 120 ------------- seek.c | 30 ---- sig.c | 110 ------------ socket_bind.c | 79 -------- socket_connect.c | 66 ------- socket_if.c | 36 ---- socket_info.c | 58 ------ socket_recv.c | 39 ---- socket_send.c | 62 ------- socket_setup.c | 99 ---------- socket_tcp.c | 63 ------- socket_udp.c | 57 ------ src/Makefile | 127 +++++++++++++ src/TARGETS | 79 ++++++++ src/alloc.c | 63 +++++++ src/base64.c | 123 +++++++++++++ src/buffer.c | 226 +++++++++++++++++++++++ src/byte.c | 82 +++++++++ src/case.c | 134 ++++++++++++++ src/cdbmake.c | 158 ++++++++++++++++ src/cdbread.c | 169 ++++++++++++++++++ src/constmap.c | 178 ++++++++++++++++++ src/dnsstub/Makefile | 24 +++ src/dnsstub/README.md | 169 ++++++++++++++++++ src/dnsstub/TARGETS | 18 ++ src/dnsstub/dns_cname.c | 59 ++++++ src/dnsstub/dns_dfd.c | 76 ++++++++ src/dnsstub/dns_domain.c | 80 +++++++++ src/dnsstub/dns_dtda.c | 43 +++++ src/dnsstub/dns_ip.c | 198 ++++++++++++++++++++ src/dnsstub/dns_ipq.c | 235 ++++++++++++++++++++++++ src/dnsstub/dns_mx.c | 63 +++++++ src/dnsstub/dns_name.c | 80 +++++++++ src/dnsstub/dns_nd.c | 48 +++++ src/dnsstub/dns_packet.c | 85 +++++++++ src/dnsstub/dns_random.c | 70 ++++++++ src/dnsstub/dns_rcip.c | 114 ++++++++++++ src/dnsstub/dns_rcrw.c | 141 +++++++++++++++ src/dnsstub/dns_resolve.c | 39 ++++ src/dnsstub/dns_sortip.c | 45 +++++ src/dnsstub/dns_transmit.c | 436 +++++++++++++++++++++++++++++++++++++++++++++ src/dnsstub/dns_txt.c | 71 ++++++++ src/env.c | 141 +++++++++++++++ src/errstr.c | 163 +++++++++++++++++ src/fd.c | 33 ++++ src/fmt.c | 87 +++++++++ src/getln.c | 43 +++++ src/getoptb.c | 100 +++++++++++ src/iopause.c | 84 +++++++++ src/ip4.c | 160 +++++++++++++++++ src/ip6.c | 350 ++++++++++++++++++++++++++++++++++++ src/lock.c | 22 +++ src/logmsg.c | 97 ++++++++++ src/ndelay.c | 24 +++ src/open.c | 25 +++ src/pathexec.c | 121 +++++++++++++ src/prot.c | 31 ++++ src/readclose.c | 43 +++++ src/scan.c | 120 +++++++++++++ src/seek.c | 40 +++++ src/sig.c | 169 ++++++++++++++++++ src/socket_bind.c | 79 ++++++++ src/socket_connect.c | 66 +++++++ src/socket_if.c | 36 ++++ src/socket_info.c | 58 ++++++ src/socket_recv.c | 39 ++++ src/socket_send.c | 62 +++++++ src/socket_setup.c | 99 ++++++++++ src/socket_tcp.c | 63 +++++++ src/socket_udp.c | 57 ++++++ src/str.c | 135 ++++++++++++++ src/stralloc.c | 126 +++++++++++++ src/tai.c | 59 ++++++ src/taia.c | 104 +++++++++++ src/timeout.c | 60 +++++++ src/timeoutconn.c | 112 ++++++++++++ src/uint128p.c | 100 +++++++++++ src/uint16p.c | 40 +++++ src/uint32p.c | 47 +++++ src/uint64p.c | 62 +++++++ src/uint8p.c | 39 ++++ src/wait.c | 25 +++ str.c | 135 -------------- stralloc.c | 126 ------------- tai.c | 59 ------ taia.c | 104 ----------- timeout.c | 59 ------ timeoutconn.c | 112 ------------ uint128p.c | 100 ----------- uint16p.c | 40 ----- uint32p.c | 47 ----- uint64p.c | 62 ------- uint8p.c | 39 ---- wait.c | 25 --- 171 files changed, 7273 insertions(+), 7033 deletions(-) delete mode 100755 CONTENT create mode 100755 CONTENT.md create mode 100644 INSTALL.md delete mode 100644 Makefile delete mode 100644 alloc.c delete mode 100644 base64.c delete mode 100644 buffer.c delete mode 100644 byte.c delete mode 100644 case.c delete mode 100644 cdbmake.c delete mode 100644 cdbread.c delete mode 100644 constmap.c delete mode 100644 dnsstub/Makefile delete mode 100644 dnsstub/README.md delete mode 100644 dnsstub/TARGETS delete mode 100644 dnsstub/dns_cname.c delete mode 100644 dnsstub/dns_dfd.c delete mode 100644 dnsstub/dns_domain.c delete mode 100644 dnsstub/dns_dtda.c delete mode 100644 dnsstub/dns_ip.c delete mode 100644 dnsstub/dns_ipq.c delete mode 100644 dnsstub/dns_mx.c delete mode 100644 dnsstub/dns_name.c delete mode 100644 dnsstub/dns_nd.c delete mode 100644 dnsstub/dns_packet.c delete mode 100644 dnsstub/dns_random.c delete mode 100644 dnsstub/dns_rcip.c delete mode 100644 dnsstub/dns_rcrw.c delete mode 100644 dnsstub/dns_resolve.c delete mode 100644 dnsstub/dns_sortip.c delete mode 100644 dnsstub/dns_transmit.c delete mode 100644 dnsstub/dns_txt.c delete mode 100644 env.c delete mode 100644 errstr.c delete mode 100644 fd.c delete mode 100644 fmt.c delete mode 100644 getln.c delete mode 100644 getoptb.c delete mode 100644 iopause.c delete mode 100644 ip4.c delete mode 100644 ip6.c delete mode 100644 lock.c delete mode 100644 logmsg.c delete mode 100644 ndelay.c delete mode 100644 open.c delete mode 100644 pathexec.c delete mode 100644 prot.c delete mode 100644 readclose.c delete mode 100644 scan.c delete mode 100644 seek.c delete mode 100644 sig.c delete mode 100644 socket_bind.c delete mode 100644 socket_connect.c delete mode 100644 socket_if.c delete mode 100644 socket_info.c delete mode 100644 socket_recv.c delete mode 100644 socket_send.c delete mode 100644 socket_setup.c delete mode 100644 socket_tcp.c delete mode 100644 socket_udp.c create mode 100644 src/Makefile create mode 100644 src/TARGETS create mode 100644 src/alloc.c create mode 100644 src/base64.c create mode 100644 src/buffer.c create mode 100644 src/byte.c create mode 100644 src/case.c create mode 100644 src/cdbmake.c create mode 100644 src/cdbread.c create mode 100644 src/constmap.c create mode 100644 src/dnsstub/Makefile create mode 100644 src/dnsstub/README.md create mode 100644 src/dnsstub/TARGETS create mode 100644 src/dnsstub/dns_cname.c create mode 100644 src/dnsstub/dns_dfd.c create mode 100644 src/dnsstub/dns_domain.c create mode 100644 src/dnsstub/dns_dtda.c create mode 100644 src/dnsstub/dns_ip.c create mode 100644 src/dnsstub/dns_ipq.c create mode 100644 src/dnsstub/dns_mx.c create mode 100644 src/dnsstub/dns_name.c create mode 100644 src/dnsstub/dns_nd.c create mode 100644 src/dnsstub/dns_packet.c create mode 100644 src/dnsstub/dns_random.c create mode 100644 src/dnsstub/dns_rcip.c create mode 100644 src/dnsstub/dns_rcrw.c create mode 100644 src/dnsstub/dns_resolve.c create mode 100644 src/dnsstub/dns_sortip.c create mode 100644 src/dnsstub/dns_transmit.c create mode 100644 src/dnsstub/dns_txt.c create mode 100644 src/env.c create mode 100644 src/errstr.c create mode 100644 src/fd.c create mode 100644 src/fmt.c create mode 100644 src/getln.c create mode 100644 src/getoptb.c create mode 100644 src/iopause.c create mode 100644 src/ip4.c create mode 100644 src/ip6.c create mode 100644 src/lock.c create mode 100644 src/logmsg.c create mode 100644 src/ndelay.c create mode 100644 src/open.c create mode 100644 src/pathexec.c create mode 100644 src/prot.c create mode 100644 src/readclose.c create mode 100644 src/scan.c create mode 100644 src/seek.c create mode 100644 src/sig.c create mode 100644 src/socket_bind.c create mode 100644 src/socket_connect.c create mode 100644 src/socket_if.c create mode 100644 src/socket_info.c create mode 100644 src/socket_recv.c create mode 100644 src/socket_send.c create mode 100644 src/socket_setup.c create mode 100644 src/socket_tcp.c create mode 100644 src/socket_udp.c create mode 100644 src/str.c create mode 100644 src/stralloc.c create mode 100644 src/tai.c create mode 100644 src/taia.c create mode 100644 src/timeout.c create mode 100644 src/timeoutconn.c create mode 100644 src/uint128p.c create mode 100644 src/uint16p.c create mode 100644 src/uint32p.c create mode 100644 src/uint64p.c create mode 100644 src/uint8p.c create mode 100644 src/wait.c delete mode 100644 str.c delete mode 100644 stralloc.c delete mode 100644 tai.c delete mode 100644 taia.c delete mode 100644 timeout.c delete mode 100644 timeoutconn.c delete mode 100644 uint128p.c delete mode 100644 uint16p.c delete mode 100644 uint32p.c delete mode 100644 uint64p.c delete mode 100644 uint8p.c delete mode 100644 wait.c diff --git a/BUILD b/BUILD index da0237c..481bc43 100644 --- a/BUILD +++ b/BUILD @@ -1 +1 @@ -20230916182859 +20240921102900 diff --git a/CHANGELOG b/CHANGELOG index 229e41e..80814d6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -67,3 +67,15 @@ fehQlibs-22a fehQlibs-23 More documentation for dns resolver routines. Added function stralloc_free() which was alreday in the header. +fehQlibs-24 Removed 'register' in functions. Added 'const' for input strings. +fehQlibs-25 Compatibility with current gcc and clang compilers: + (Internal) Unrolling for() loops removed. Internal functions are static now. + (Internal) buffer_init uses now 'buffer_unixread' and 'buffer_unixwrite' with matching signatures. + (External) Added getopb() as external and thus removing getop() compatibility. + (Installation) Moved C source files to ./src. Added INSTALL.md to describe changes. + (Compilation) Added -fwrapv flag to the compiler (correctly handling two's complement). + Open issues: + 'constmap' is struct and function name! + (Internal) alloc_re()'s first argument is now a void pointer to a list [gcc 14.2]. +fehQlibs-25(b) + (Make) conf-build was not called due to move to ./src. Missing dot in ./configure. diff --git a/CONTENT b/CONTENT deleted file mode 100755 index 25fa27d..0000000 --- a/CONTENT +++ /dev/null @@ -1,63 +0,0 @@ -Content of fehQlibs -------------------- - -This list contains the generated archive and supplementary -object files together with their main header files (to be -found under ./include) and man pages (located at ./man). -The list is incomplete. - -Archive/Object | Headers | Description ------------------------------------------------ -alloc.a alloc.h alloc.3 -buffer.a buffer.h buffer.3 - byte.h byte.3 -case.a case.h case.3 -cdb.a cdbmake.h cdbmake.3 - cdbread.h cdbread.3 -constmap.a constmap.h constmap.3 -dnsresolv.a dnsresolv.h dns.3, dnsstub.3 -env.a env.h env.3 -fd.a fd.h fd.3 -fs.a fmt.h fmt.3 - scan.h scan.3 -getln.a getln.h getln.3 -getopt.a getoptb.h getoptb.3 -ip.a ip.h ip4.3, ip6.3 -lock.a lock.h -logmsg.a logmsg.h logmsg.3 - error.h error.3 -ndelay.a ndelay.h -open.a open.h -seek.a seek.h -sig.a sig.h -socket.a socket_if.h socket_bind.3, socket_connect.3 - ip.h socket_if.3, socket_info.3 - socket_recv.3, socket_send.3 - socket_setup.3, socket_tcp.3 - socket_udp.3 -str.a str.h -stralloc.a stralloc.h stralloc.3 -time.a tai.h, taia.3 - timeout.h timeout.3 - timeoutconn.h timeoutconn.3 - iopause.h iopause.3 - select.h -wait.a wait.h wait.3 - -pathexec.o pathexec.h pathexec.3 -prot.o prot.h -byte.o byte.h byte.3 - base64.h -readclose.o readclose.h -uint8p.o uint_t.h -uint16p.o uint_t.h -uint32p.o uint_t.h -uint64p.o uint_t.h -uint128p.o uint_t.h - - -Two main archives are generated: - -- (lib)qlibs.a -- including all above, except for -- (lib)dnsresolv.a -- routines located at ./dnsstub. - diff --git a/CONTENT.md b/CONTENT.md new file mode 100755 index 0000000..ef42b84 --- /dev/null +++ b/CONTENT.md @@ -0,0 +1,63 @@ +Content of fehQlibs +=================== + +This list contains the generated archive and supplementary +object files together with their main header files (to be +found under ./include) and man pages (located at ./man). +The list is incomplete. + + Archive/Object | Headers | Description + ----------------------------------------------- + alloc.a alloc.h alloc.3 + buffer.a buffer.h buffer.3 + byte.h byte.3 + case.a case.h case.3 + cdb.a cdbmake.h cdbmake.3 + cdbread.h cdbread.3 + constmap.a constmap.h constmap.3 + dnsresolv.a dnsresolv.h dns.3, dnsstub.3 + env.a env.h env.3 + fd.a fd.h fd.3 + fs.a fmt.h fmt.3 + scan.h scan.3 + getln.a getln.h getln.3 + getopt.a getoptb.h getoptb.3 + ip.a ip.h ip4.3, ip6.3 + lock.a lock.h + logmsg.a logmsg.h logmsg.3 + error.h error.3 + ndelay.a ndelay.h + open.a open.h + seek.a seek.h + sig.a sig.h + socket.a socket_if.h socket_bind.3, socket_connect.3 + ip.h socket_if.3, socket_info.3 + socket_recv.3, socket_send.3 + socket_setup.3, socket_tcp.3 + socket_udp.3 + str.a str.h + stralloc.a stralloc.h stralloc.3 + time.a tai.h, taia.3 + timeout.h timeout.3 + timeoutconn.h timeoutconn.3 + iopause.h iopause.3 + select.h + wait.a wait.h wait.3 + + pathexec.o pathexec.h pathexec.3 + prot.o prot.h + byte.o byte.h byte.3 + base64.h + readclose.o readclose.h + uint8p.o uint_t.h + uint16p.o uint_t.h + uint32p.o uint_t.h + uint64p.o uint_t.h + uint128p.o uint_t.h + + +Two main archives are generated: + +- (lib)qlibs.a -- including all above, except for +- (lib)dnsresolv.a -- routines located at ./dnsstub. + diff --git a/FILES b/FILES index 85b59ef..465217b 100644 --- a/FILES +++ b/FILES @@ -1,162 +1,167 @@ -./BUILD = 3119c820453717278177af253188e95c -./CHANGELOG = ba424a3dd1cdb12d4c345a11de0a0817 -./CONTENT = 3478f3a562d003b32aa0762e93a75b26 -./LICENSE = 43df073a04022f63913c379646905da6 -./Makefile = abba48d9d52ca48f050208231de5c783 -./README.md = 60875952ce23f26102f84757329b9b31 -./TARGETS = a3800d82d6b95a77536b9c719b519b73 -./VERSION = 6cfc8c14f10d3a39524fed09959cdffa -./alloc.c = 514e44b39a3c964d0e17efda78e9b8c7 -./base64.c = 3a2830988bc99a672f09557b288dfd81 -./buffer.c = 04489d0d0961e69081381983bbe26f56 -./byte.c = 67806bc236105f085b46ae4327e437ae -./case.c = f03a5e250d1aff49d1304670f5b7254a -./cdbmake.c = b038d803422618d1f7eaade9716a858e -./cdbread.c = 5eeb568fb122813c7ac0a3d273b98591 -./conf-build = 52f94f184b80b29aa7800265da87de55 -./configure = 145494889bebdcc519320472d84566b6 -./constmap.c = e49f40971441ca0187a19a1feba012f1 -./dnsstub/Makefile = 8dcd8f647b1f8d7ec755cea81ed57a37 -./dnsstub/README.md = d50e01dbf9223e49ec52f131fa5916d8 -./dnsstub/TARGETS = 723bd9a97f59f9091fbe2fba10ef8e5e -./dnsstub/dns_cname.c = f70db88df864eab7694b747fd77dbb6d -./dnsstub/dns_dfd.c = 149da24f7b57761d9c0eec3278b63fb0 -./dnsstub/dns_domain.c = e79ee91862f5d06ec892a228489aca3f -./dnsstub/dns_dtda.c = f9fc0ba7ea3cdaad5e85c0d0edd479a7 -./dnsstub/dns_ip.c = 811eec1cfe97536d6ea9a1d5e48801ce -./dnsstub/dns_ipq.c = 273479eeae125ffbddaf4e95fbcfe0f0 -./dnsstub/dns_mx.c = 01c29dde656fbaf7ab19c4c3a28664ac -./dnsstub/dns_name.c = 31cb8e08404ab22dca6c6098a2fc9317 -./dnsstub/dns_nd.c = 8d1c5bf17f2242d22d64903393a73768 -./dnsstub/dns_packet.c = d6e4035938817a47f10578265d52b0ab -./dnsstub/dns_random.c = 7429f11a2181d0771046ffd85f4acb38 -./dnsstub/dns_rcip.c = 2762d62ad3fffe4caaadbafd3c007211 -./dnsstub/dns_rcrw.c = c57be390844bb9f26fb44dbce2837136 -./dnsstub/dns_resolve.c = 8ec11fea2c0bb173b73230e0f41b055b -./dnsstub/dns_sortip.c = aa8effa053c3d6899a17242d3eebae40 -./dnsstub/dns_transmit.c = 8c2b07aa13b0abcc7697cb37d9fef821 -./dnsstub/dns_txt.c = 4a8d105d506ec11ac3c307f405393e42 -./env.c = 2aabee824c86ed685a17cc8b6eb6e1cf -./errstr.c = e89bde5dd0320f24a399967ef64c4a27 -./fd.c = e1643064b0f9571c92cb17f5e6c2c3c9 -./fmt.c = b2627c34a39b7a492ec07969931c6bc9 -./getln.c = bb694220f8bedb7f7f8a8dd8a6d91347 -./getoptb.c = 92c4305401f59359b8dac69e1df84647 -./include/alloc.h = fc20a6d23d60eeaa84a913b19cea2a6f -./include/base64.h = 518e08181673aff5e497eb526a427b1d -./include/buffer.h = 4ff0a37e7b614e0d80123782f706f54a -./include/byte.h = 6a7dc0cca790d6cbac23731e71c665fb -./include/case.h = b0f7e31bd1e121850c3d1c3dc4c38d5c -./include/cdbmake.h = 44c1444111c3fabd59ed63258b5d54ad -./include/cdbread.h = d40f94c976c1cadb575044a3ef965978 -./include/close.h = a1a84cfde83c8cef39c5ca5f52796aee -./include/constmap.h = f217b422c4d74890b6675e72dca753bf -./include/direntry.h = ed9e2af8fed1975b017883488b0db2f7 -./include/dnsresolv.h = 717941c00c4e369241000ef70cf848f6 -./include/env.h = 70f96abf159cedaad9bbbfa4c27bc8a7 -./include/error.h = 7886039fc72d57919c1c6db56b5fc324 -./include/exit.h = 45e2e3e56314e2332837a61e1c866423 -./include/fd.h = d76deb5c0ed33bf690e25f4e5fc94359 -./include/fifo.h = 4aac02038e14acac8c2b6e28ec992406 -./include/fmt.h = 71b6a242a848044e65e407a5647d21eb -./include/genalloc.h = 7d88ca8ee9f933f1cbb9ed0597dddf60 -./include/getln.h = 040da2a02c37a8aa50ea614410f2ed0c -./include/getoptb.h = 988a7314fca7dff960dcffc134cc404c -./include/iopause.h = b7680ea87e84b568b8f1f7c281ae739a -./include/ip.h = a66be1788f98dc795cceeb4b0f0c9bb2 -./include/lock.h = 224879d2b1671dad51f8bbcd6f7c2426 -./include/logmsg.h = d90310844d3fa6cfbab0b37b54170d92 -./include/ndelay.h = cc914c481a7652e9aef10acdf69de7ff -./include/open.h = 4f4d7371bbefccf2cec365f7811e874e -./include/pathexec.h = 37af5ae960eb91892744c7a3802737d1 -./include/prot.h = 0f6816695dc713f927e09270696835a2 -./include/readclose.h = cfe01c7d37be0a17a492534faf2717b2 -./include/readwrite.h = 58ab91bb5433b835e97fe78fd6780633 -./include/rename.h = 3d13ce7562cd4f87578b94adaa5857f0 -./include/scan.h = 49a8521c05e6c06436637af85e3f7234 -./include/seek.h = be3607921c13b338365ecbf1e9e24f38 -./include/select.h = 019f9aadad2f1a5d14aa5ec8cdee6065 -./include/sig.h = 3012ce2f2f452e3b822aeb7c9765640a -./include/socket_if.h = ba79b96dcdcd50983e7328ee28b209ec -./include/str.h = 9b010e0767b85c44804424ad9436ab5a -./include/stralloc.h = c9a7b068f19c896891c30fd12bd078bb -./include/tai.h = ca3390aa0aa229108a4864c0f4a40e6f -./include/taia.h = 4e9a6bd8f7f6884932d72a48d34301ef -./include/timeout.h = be7d9294fe124d22abdd20204abcaa2f -./include/timeoutconn.h = 3bc13384d2d2355d7327a73428027822 -./include/uint_t.h = 2bdc1c29b1a66a792dc41004b1e4d2fe -./include/wait.h = fc9c628f22a862bb9af69fdd7a6b61a8 -./install = f6468f1ce0a61e581df2d3278d4f9d24 -./iopause.c = 7cbd896fbcca2c26b218a3299543c905 -./ip4.c = 8cf7ae24e43da943e4695f5cb4a50f6c -./ip6.c = 16192261767a3056adc84c10bbcaf8ce -./lock.c = 50aa9fca4611c86f943c49256b7a001a -./logmsg.c = 7335546b87caf29a8fbf41a8ac89169c -./man/INSTALL = c83cc4663e122994ea65d269982df554 -./man/alloc.3 = 2f666bfc6cb2d755e4047be92853c4c9 -./man/buffer.3 = 14df7a93cc6131f83e84ee438ec29f05 -./man/byte.3 = 3927c67098f880846b6d71c8d69d63af -./man/case.3 = 6ee29d92e49bb6f91b2e8029c7a5ad04 -./man/cdbmake.3 = 54e604b19d139b0c5b451b86c58802d5 -./man/cdbread.3 = 81a48e1258f4919861b7537a7759c0a5 -./man/constmap.3 = 3308860b3c8b2032dff86d64aab332d0 -./man/dns.3 = 3a3834e729315537509ddfd06d76ecd7 -./man/dnsstub.3 = 63081eeab017fbf754f854010d8b1dc4 -./man/env.3 = 27c3a784e43a5ec37c2918014bcac3f8 -./man/error.3 = 2d2b4e9800b73983848581814065b074 -./man/fd.3 = c6115dbec98169a66af436ea929cc0bb -./man/fmt.3 = 419b2e143438a3351f6a21828823a367 -./man/getln.3 = 5c4930df89e1132257de8cfa7dbbac3a -./man/getoptb.3 = eb4ff31f223bcf561043fd96e8bf7fcd -./man/iopause.3 = 4705db96ec459124a7cac08c75621b43 -./man/ip4.3 = 0ffc1d509fec9b8432638ba2e244599e -./man/ip6.3 = 480b6a5f03a5a07c122c0dd427b5f671 -./man/logmsg.3 = 1aac69f1603735534b831b062a982b96 -./man/pathexec.3 = 0f320b89031f14099389f245ff0082c4 -./man/scan.3 = f838564ca05d7eb75e0f94601da0e247 -./man/socket_bind.3 = 603252820735a0586d2473d60b5368ba -./man/socket_connect.3 = 7ede000da47f9d050b4a8b4a548c3fba -./man/socket_if.3 = 939ee90dbc06e46530bdebb76f7868b7 -./man/socket_info.3 = 25bb53af29cacae415052b795bc9dbbf -./man/socket_recv.3 = c7fbce83d73180901bacfd42329a1961 -./man/socket_send.3 = 559b6ca0e4e488c961adfec91298cb57 -./man/socket_setup.3 = 06509120a17c0fdc1e74183e4fdeec6e -./man/socket_tcp.3 = 88a7db7c3f87f6e55676a8bbea04bebb -./man/socket_udp.3 = 83ef36e87a0616a1f89c62ee10443d20 -./man/str.3 = 8aada587fbeaa6642b92f8259253e864 -./man/stralloc.3 = 62f213c041e32f3b9c807e69b9c2b0a4 -./man/taia.3 = ca40e8e64a68b1452629067f7f5ba82e -./man/timeout.3 = c70003889aeb948b0083d6ecaf9a78fa -./man/timeoutconn.3 = 2fa5bc7c6c042bb7c80c431bf5eac5b2 -./man/wait.3 = 13f3301b18e333666659b8e49864d389 -./man/x.html = 4eda1f156fe2348daebfbddf7a33c022 -./ndelay.c = 15de43ad20cb35ec2c80df851f606bd9 -./open.c = 1a793911a2e57e01ffa7bda1d08db8f4 -./pathexec.c = 23c0c5d5013a19eb4f6b4b03c87db8ec -./prot.c = e1568767fcfb5fc119da935d9d3cf27f -./readclose.c = deabaa3b8b50201d560bfc3c584ca1c3 -./scan.c = 6792e3f60344e4cf5fcee4fad55fae38 -./seek.c = 5c2ee16ea4ec99584d702ff55d9c9d19 -./sharedlib = bde12e503174244d57ad35135b5d25e9 -./sig.c = a8a98f1c8c27eece5f341ec05f46e80e -./socket_bind.c = b463068c7160e01d6fb8c3fb903d5c8e -./socket_connect.c = 96c784f10d7ea96720b10b5844fd4cd0 -./socket_if.c = c841f0681878e90fbac87dc4ce7ab6fe -./socket_info.c = 623a97efe396c56ac31e0964b4b8025a -./socket_recv.c = 66914af66c9bda8c2239f5308648cbac -./socket_send.c = 80647ec33d769a5f5a7ead0b7e881015 -./socket_setup.c = 229bca06ab2f68f483b525b8e8e13886 -./socket_tcp.c = 5c8565ee6668341730d3b9eac7de0a7b -./socket_udp.c = 50a0bb63dcea40f7c146e17b1aa1050b -./str.c = ff3952e9e6bf49cd34a2bcafaf168208 -./stralloc.c = 85b65c1193b0d93039530edad5e1cab5 -./tai.c = 823b0274b23207ebade293fd14a1ab31 -./taia.c = 63de9eb6672c1c43296b383224fccc74 -./timeout.c = 35e6965f54a50838b6d3ae61ee8fd962 -./timeoutconn.c = 6acef79e4c36a795da73f2c0eb010d39 -./uint128p.c = 83da4a537b781df80316da49e54735e8 -./uint16p.c = 61e6fed3598e3ceaa41a75d91657bef0 -./uint32p.c = 5a1965fbf0e288aebbae066f341a442b -./uint64p.c = b95d3d869c5ecc6fe65f65c04dcceeb2 -./uint8p.c = 4db811c33b483cd9fe08ca72c254bb0c -./wait.c = 4048ebc18bc71a91e21da7ccab205558 +43df073a04022f63913c379646905da6 ./LICENSE +e38263cd3556a47a617820b7f8075dfc ./CHANGELOG +1a9639e5b692ae6ebff22db582b91ac1 ./README.md +e0b1107a83a700404d8380732356aec7 ./configure +a3800d82d6b95a77536b9c719b519b73 ./TARGETS +d989cf4be5e835163431de86a545402f ./src/env.c +8d5cc64913677cd3f1510b0ec0769043 ./src/uint32p.c +d8d9e945e324297597b42bddfaef0d70 ./src/cdbread.c +d9a5e47d22fe94c109c2f3b63681e635 ./src/constmap.c +ac2d821c67a800fb672405f0618aa41b ./src/Makefile +797ef1bf2cc8d5627dd0fa964bd62368 ./src/buffer.c +a3800d82d6b95a77536b9c719b519b73 ./src/TARGETS +718b152686cd951419cd86a909eb1122 ./src/seek.c +6f905994cb9ffa51ae782e879850e514 ./src/timeout.c +5c060f1e0cd9a9e1e49e3946210e84d1 ./src/socket_connect.c +8ff07687bf2bb08faec098d8acdcff56 ./src/ip6.c +43967af6fecc4d4eef2deffe6999047d ./src/socket_send.c +90c44be0ab10cbdbd9991507a6de21a3 ./src/alloc.c +d6c261182d92b78d6f66adec00432883 ./src/getoptb.c +5857af130514a0fc66d3601d09c911f9 ./src/wait.c +40abd7766051a4749a82408bbb0669cc ./src/lock.c +73e7b95f53095e1f645142c9e9f978cf ./src/tai.c +1c55e79cc713ef604a629a13380ceaf7 ./src/stralloc.c +eb72075acf926ba92a41456125106084 ./src/sig.c +fd72b318c3d8ddeff24fff13814f9dcc ./src/logmsg.c +bf646d47b08d9ccf64d1d172f6837de1 ./src/uint128p.c +223c843c280503ad709da9870a1c97ec ./src/ip4.c +84d5eb8c8a9f888b4299c01c8095f497 ./src/ndelay.c +f3ef026d760a2190c0bec465ff2c17bb ./src/socket_recv.c +f2958020b5246f89fe75558a71fc81d4 ./src/iopause.c +e63f1cd6aaa020b9e6a9c67a420e5d5f ./src/case.c +7b82d7356bbd9d508ccd44dc499ed743 ./src/errstr.c +a1219f1f6b55799f7c6ef58d59e5d64f ./src/timeoutconn.c +fcafd37414abb6958ef616f28fc26b66 ./src/uint8p.c +ff7113c7eca77d7b9f3dd01804fa5034 ./src/str.c +8a9bbad7985ce1814e9dc54c3bb46ad4 ./src/open.c +cbbdc60716ddc11f6da2eb60e8adfe4d ./src/socket_if.c +0501d152c7db44915670eb434f01ee11 ./src/socket_bind.c +2fb041cdd1a4dc31ba41bf3bf92c5a13 ./src/fd.c +7632593882141efee3f7d7b506f93098 ./src/fmt.c +274126672025f879a1d50c1783b7429a ./src/byte.c +bde12e503174244d57ad35135b5d25e9 ./src/sharedlib +107d7309a35369b25cc7ed6f18c326ca ./src/socket_setup.c +be8c207d881800aec4e3c9e7e712ebb4 ./src/uint16p.c +f4882c3c1eaacc0992ae5e1cf72b5dc6 ./src/getln.c +79a815a0b0fcb9eeade48c1839cd0641 ./src/scan.c +b8ba1fc87deb7b01b717c247fbf20405 ./src/pathexec.c +6682f956fb3fcce1f3412055a376e859 ./src/cdbmake.c +217540391d2e3b1a73cd4e70816450ac ./src/base64.c +bde99f617768166384afa5d60a051f3c ./src/dnsstub/dns_random.c +fc8786efefecaec49a974df18c0dc25c ./src/dnsstub/dns_name.c +5752db80e5986db3464e2553347854d6 ./src/dnsstub/Makefile +6f078428d499401d75f8c7540718c380 ./src/dnsstub/dns_dfd.c +3c25a1b6c439ccd46ebd127ad922ff0f ./src/dnsstub/dns_sortip.c +723bd9a97f59f9091fbe2fba10ef8e5e ./src/dnsstub/TARGETS +63a27823692bc54740442a5637934be5 ./src/dnsstub/dns_packet.c +08f0ddac37d01f2fbc07530d4354f9cb ./src/dnsstub/dns_rcip.c +46674a28ed8a0d90401825a2ceb38441 ./src/dnsstub/dns_domain.c +ea71564a2bf072b23640b64a9ca79a4c ./src/dnsstub/dns_ipq.c +60542241eaa1d1c0a8a2e982b2dc5494 ./src/dnsstub/dns_rcrw.c +8362746004516897de5ec255d22fec5d ./src/dnsstub/dns_nd.c +2a9bd072394c358def231153427a9b40 ./src/dnsstub/dns_ip.c +8a892c7008a6e2a597741dcc5bea5a68 ./src/dnsstub/dns_resolve.c +2560b5fbd9afd63dc51080b80165ef8c ./src/dnsstub/dns_mx.c +455925dc93c0fcd7909a4657f8c8b4ee ./src/dnsstub/dns_dtda.c +b4aba3a8db9cdc9612bac2fc1763c5b8 ./src/dnsstub/dns_cname.c +2a61cbf664d7e95eed7700e582d897c2 ./src/dnsstub/README.md +8c6695a1cbccf974631a4c9f7ddb04f7 ./src/dnsstub/dns_txt.c +8aa54782818fab29a600a1e40689c876 ./src/dnsstub/dns_transmit.c +b8246d1439a1c5efddcc881e4eda18f0 ./src/socket_info.c +79103dcf6fad6658f4d97cc5973c07b4 ./src/readclose.c +63731f2aa9d0b655c43e7ea7fe9a9e7f ./src/taia.c +6bac00628cb7bad4f12c43d186403c8b ./src/socket_tcp.c +094b1417caa52c065b58e7139ae17403 ./src/prot.c +063f6d9e54e228a4b628b083199edb59 ./src/uint64p.c +3ab098524713f39c3a01bc0b9860d277 ./src/socket_udp.c +facf6a7d37be70e3fe44b33c66ac2570 ./makelib +bde12e503174244d57ad35135b5d25e9 ./sharedlib +e36cfa8aec6df377caee4467d8b96a7f ./VERSION +fe0f9caaa44877d38b6f73dd60710426 ./INSTALL.md +8effeb247b1f5ea6609d9484099880f3 ./install +19b16ec85a6f278d498522cce0fa8f92 ./BUILD +58ab91bb5433b835e97fe78fd6780633 ./include/readwrite.h +040da2a02c37a8aa50ea614410f2ed0c ./include/getln.h +a1a84cfde83c8cef39c5ca5f52796aee ./include/close.h +be3607921c13b338365ecbf1e9e24f38 ./include/seek.h +70f96abf159cedaad9bbbfa4c27bc8a7 ./include/env.h +3bc13384d2d2355d7327a73428027822 ./include/timeoutconn.h +3d13ce7562cd4f87578b94adaa5857f0 ./include/rename.h +954ca9f32023b2dec94c862d02fe7ca4 ./include/cdbmake.h +ed9e2af8fed1975b017883488b0db2f7 ./include/direntry.h +f3849b25c884d49c364c19320cdfad23 ./include/base64.h +b0f7e31bd1e121850c3d1c3dc4c38d5c ./include/case.h +0715579527de757b10176d399404b2b3 ./include/exit.h +a7766f44651eedea6928f4e9ac5f2013 ./include/fifo.h +d76deb5c0ed33bf690e25f4e5fc94359 ./include/fd.h +0e053d8b527a93c843d7eae773bd7444 ./include/sig.h +37af5ae960eb91892744c7a3802737d1 ./include/pathexec.h +ca3390aa0aa229108a4864c0f4a40e6f ./include/tai.h +b43784368cbeb191e78d1b7f9ee3d5ae ./include/wait.h +d4c037d864067145fe97bb34154bf26b ./include/genalloc.h +b536326f7ecfe3ef229a3d3ca3a0a554 ./include/lock.h +1075e89ff1290cf522fb67794e096833 ./include/select.h +e4a27a49c5dd49d19b1fa34af5bab197 ./include/byte.h +7886039fc72d57919c1c6db56b5fc324 ./include/error.h +b7680ea87e84b568b8f1f7c281ae739a ./include/iopause.h +d6f6e984d583bd6d3eec14eeb52d5534 ./include/fmt.h +5b98c40f0a89ca109a1e638a8fe33506 ./include/uint_t.h +83614b78d8a937590fe905d3de9b4911 ./include/open.h +717941c00c4e369241000ef70cf848f6 ./include/dnsresolv.h +4ff0a37e7b614e0d80123782f706f54a ./include/buffer.h +ecc1f8b2b13b77a8c016590618d73cc3 ./include/constmap.h +58473a2f78e6e64cd1a67dd06ace92d9 ./include/str.h +cfe01c7d37be0a17a492534faf2717b2 ./include/readclose.h +d90310844d3fa6cfbab0b37b54170d92 ./include/logmsg.h +4e9a6bd8f7f6884932d72a48d34301ef ./include/taia.h +0f6816695dc713f927e09270696835a2 ./include/prot.h +a66be1788f98dc795cceeb4b0f0c9bb2 ./include/ip.h +9394aa5e8def374935aca019b9718a0a ./include/getoptb.h +84583ba30e2ef88cfe8c53c7e13711ca ./include/ndelay.h +ba79b96dcdcd50983e7328ee28b209ec ./include/socket_if.h +be7d9294fe124d22abdd20204abcaa2f ./include/timeout.h +4faf0a343fc405da9ccc93dd10b96d99 ./include/alloc.h +c9a7b068f19c896891c30fd12bd078bb ./include/stralloc.h +49a8521c05e6c06436637af85e3f7234 ./include/scan.h +d40f94c976c1cadb575044a3ef965978 ./include/cdbread.h +447646285c4a9d3d613307becac0f660 ./CONTENT.md +ed9d85e6db765219dbed38de71d442a5 ./conf-build +ceaf6033abb811be3a4e00c0abc725b7 ./compile +25bb53af29cacae415052b795bc9dbbf ./man/socket_info.3 +13f3301b18e333666659b8e49864d389 ./man/wait.3 +2d2b4e9800b73983848581814065b074 ./man/error.3 +c83cc4663e122994ea65d269982df554 ./man/INSTALL +6ee29d92e49bb6f91b2e8029c7a5ad04 ./man/case.3 +939ee90dbc06e46530bdebb76f7868b7 ./man/socket_if.3 +54e604b19d139b0c5b451b86c58802d5 ./man/cdbmake.3 +0f320b89031f14099389f245ff0082c4 ./man/pathexec.3 +419b2e143438a3351f6a21828823a367 ./man/fmt.3 +2f666bfc6cb2d755e4047be92853c4c9 ./man/alloc.3 +83ef36e87a0616a1f89c62ee10443d20 ./man/socket_udp.3 +88a7db7c3f87f6e55676a8bbea04bebb ./man/socket_tcp.3 +603252820735a0586d2473d60b5368ba ./man/socket_bind.3 +3a3834e729315537509ddfd06d76ecd7 ./man/dns.3 +06509120a17c0fdc1e74183e4fdeec6e ./man/socket_setup.3 +4eda1f156fe2348daebfbddf7a33c022 ./man/x.html +2fa5bc7c6c042bb7c80c431bf5eac5b2 ./man/timeoutconn.3 +8aada587fbeaa6642b92f8259253e864 ./man/str.3 +63081eeab017fbf754f854010d8b1dc4 ./man/dnsstub.3 +c7fbce83d73180901bacfd42329a1961 ./man/socket_recv.3 +4705db96ec459124a7cac08c75621b43 ./man/iopause.3 +f838564ca05d7eb75e0f94601da0e247 ./man/scan.3 +0ffc1d509fec9b8432638ba2e244599e ./man/ip4.3 +ca40e8e64a68b1452629067f7f5ba82e ./man/taia.3 +d119ca0b17775f764fc4d0543c02255e ./man/buffer.3 +98b1a4adc93f98fa412a712e7d803e76 ./man/getln.3 +62f213c041e32f3b9c807e69b9c2b0a4 ./man/stralloc.3 +031965d5c617e7296b90f117b62db294 ./man/getoptb.3 +559b6ca0e4e488c961adfec91298cb57 ./man/socket_send.3 +480b6a5f03a5a07c122c0dd427b5f671 ./man/ip6.3 +c70003889aeb948b0083d6ecaf9a78fa ./man/timeout.3 +1aac69f1603735534b831b062a982b96 ./man/logmsg.3 +3927c67098f880846b6d71c8d69d63af ./man/byte.3 +c6115dbec98169a66af436ea929cc0bb ./man/fd.3 +7ede000da47f9d050b4a8b4a548c3fba ./man/socket_connect.3 +27c3a784e43a5ec37c2918014bcac3f8 ./man/env.3 +3308860b3c8b2032dff86d64aab332d0 ./man/constmap.3 +81a48e1258f4919861b7537a7759c0a5 ./man/cdbread.3 diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..a372829 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,116 @@ +fehQlibs installation +===================== + +Configuration +------------- + +Some build options can be configured through 'conf-build'. +Read the comments in this file for more information. + + +Building +-------- + +a) Static libs: + +Execute + + $ make -C src + +which does the steps of './configure && make'. +Don't forget to make sure that libs and headers will be found by the compiler/linker. + +In fehQlibs main directory you will find now + +- libdnsresolv.a +- libqlibs.a + +ready for use. + +b) Shared objects libs: + +You can also build dynamic libaries for qlibs and dnsresolv. After + + $ make -C src + +call + + $ make -C src shared + +Additionally, the files + +- libdnsresolv.so +- libqlibs.so + +are created. + + +Deployment +---------- + +In case 'conf-build' has been customized to include the location of + +- HDRDIR +- LIBDIR + +issue + + $ make -C src install + +to deploy the include files and libs at the given location. +By default, for the libs the parent directory is used. + + +Cleaning +-------- + +Calling + + $ make -C src clean + +will remove the object files in the src directories, but will +leave the generated libraries as they are in the main directory. +They will be overwritten on the next call of make. + + +Verification +------------ + +Check the ELFCLASS of the generated binaries in the src directory while calling + + $ file open.o + +They need to comply with your OS. See 'conf-build' for options. + +* Resulting libraries: + +The following libraries are generated: + +- qlibs.a - static basic [w/o DNS] lib (linked to libqlibs.a) +- dnsresolv.a - static DNS resolver lib (linked to libdnsresolv.a) + +and perhaps + +- libqlibs.so - dynamic, position independent (PIC) 'shared object' lib +- libdnsresolv.so - dynamic, position independent (PIC) 'shared object' lib + +These libs are of type ELF64 or ELF32 depending on the system. + +Use 'ar -t' to get the included members of the static libs. +Use 'nm' to view the members and symbols of the libs. + +The shared object libs are known NOT not work on MacOS. +You might need additional parameters in 'conf-build'. + + +Man pages +--------- + +In the ./man directory the current man pages for the basic qlibs routines are included. +Determine the current $mandir and (as root) install the man pages: + + $ cp *.3 $mandir/man3/ + +----- + +Updated: 20240920, Erwin Hoffmann diff --git a/Makefile b/Makefile deleted file mode 100644 index 8426968..0000000 --- a/Makefile +++ /dev/null @@ -1,123 +0,0 @@ -# Makefile for qlibs - -SHELL=/bin/sh - -# static flags - DO NOT EDIT! -CCFLAGS=-Iinclude - -SRCS=*.c -OBJS=*.o -COMPILE=./compile -MAKELIB=./makelib -SHAREDLIB=./sharedlib - -default: clean check libs - -check: - @[ -f $(COMPILE) ] && [ -f $(MAKELIB) ] || ./configure - -clean: - @echo -n Cleaning up libs ... - @rm -f `cat TARGETS` - @cd dnsstub ; make -s clean ; cd .. - @echo " done!" - -core: alloc.a buffer.a case.a cdb.a constmap.a env.a \ -fd.a fs.a getln.a getopt.a lock.a logmsg.a ndelay.a open.a \ -seek.a sig.a str.a stralloc.a time.a wait.a \ -ip.a socket.a dnsresolv.a - -libs: obj core qlibs.a dnsresolv.a - -obj: - @echo Making all in qlibs ... - $(COMPILE) $(CCFLAGS) $(CFLAGS) $(SRCS) - -install: setup - -setup: - @./install - -shared: $(COMPILE) $(SHAREDLIB) $(OBJS) ./dnsstub/$(OBJS) - @echo Building shared qlibs ... - $(SHAREDLIB) $(LDFLAGS) $(OBJS) -o libqlibs.so - $(SHAREDLIB) $(LDFLAGS) ./dnsstub/$(OBJS) -o libdnsresolv.so - -qlibs.a: obj socket.a - $(MAKELIB) $(LDFLAGS) qlibs.a *.o - ln -sf qlibs.a libqlibs.a - -dnsresolv.a: - @echo "Building @dnsresolv lib ..." - @cd dnsstub ; make - @cp dnsstub/dnsresolv.a dnsresolv.a - ln -sf dnsresolv.a libdnsresolv.a - -socket.a: ip.a - @echo "Building socket lib ..." - $(MAKELIB) $(LDFLAGS) socket.a socket_if.o socket_bind.o socket_connect.o \ - socket_info.o socket_setup.o socket_tcp.o socket_udp.o ip.a - -# build each file separately (backwards compat) - better use recipe qlibs.a -alloc.a: alloc.o - $(MAKELIB) $(LDFLAGS) alloc.a alloc.o - -buffer.a: buffer.o - $(MAKELIB) $(LDFLAGS) buffer.a buffer.o - -case.a: case.o - $(MAKELIB) $(LDFLAGS) case.a case.o - -cdb.a: cdbread.o cdbmake.o uint32p.o seek.o buffer.o - $(MAKELIB) $(LDFLAGS) cdb.a cdbread.o cdbmake.o uint32p.o seek.o buffer.o - -constmap.a: constmap.o alloc.o buffer.o scan.o - $(MAKELIB) $(LDFLAGS) constmap.a constmap.o alloc.o buffer.o scan.o - -env.a: env.o - $(MAKELIB) $(LDFLAGS) env.a env.o - -fd.a: fd.o - $(MAKELIB) $(LDFLAGS) fd.a fd.o - -fs.a: fmt.o scan.o - $(MAKELIB) $(LDFLAGS) fs.a fmt.o scan.o - -getln.a: getln.o - $(MAKELIB) $(LDFLAGS) getln.a getln.o - -getopt.a: getoptb.o - $(MAKELIB) $(LDFLAGS) getopt.a getoptb.o - -ip.a: ip4.o ip6.o socket_if.o - $(MAKELIB) $(LDFLAGS) ip.a ip4.o ip6.o socket_if.o - -lock.a: lock.o - $(MAKELIB) $(LDFLAGS) lock.a lock.o - -ndelay.a: ndelay.o - $(MAKELIB) $(LDFLAGS) ndelay.a ndelay.o - -open.a: open.o - $(MAKELIB) $(LDFLAGS) open.a open.o - -seek.a: seek.o - $(MAKELIB) $(LDFLAGS) seek.a seek.o - -sig.a: sig.o - $(MAKELIB) $(LDFLAGS) sig.a sig.o - -str.a: str.o byte.o stralloc.o alloc.o - $(MAKELIB) $(LDFLAGS) str.a str.o byte.o stralloc.o alloc.o - -stralloc.a: stralloc.o alloc.o - $(MAKELIB) $(LDFLAGS) stralloc.a stralloc.o alloc.o - -logmsg.a: errstr.o logmsg.o - $(MAKELIB) $(LDFLAGS) logmsg.a errstr.o logmsg.o - -time.a: iopause.o tai.o taia.o timeout.o timeoutconn.o - $(MAKELIB) $(LDFLAGS) time.a iopause.o tai.o taia.o timeout.o timeoutconn.o - -wait.a: wait.o - $(MAKELIB) $(LDFLAGS) wait.a wait.o diff --git a/README.md b/README.md index 0498792..a62eb90 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ /*! \mainpage - qlibs - C library and headers based on "djb's libs" and libowfat ================================================================ @@ -30,82 +29,7 @@ See the README in the ./dnsstub directory for details. Installation ------------ -Some build options can be configured through 'conf-build'. -Read the comments in this file for more information. - -* Building: - -a) Static libs: - -Execute - - $ make - -which does the steps of './configure && make'. -Don't forget to make sure that libs and headers will be found by the compiler/linker. -For convenience, link the current version of fehQlibs to qlibs - - $ ln -s fehQlibs-XY qlibs - -b) Shared objects libs: - -You can also build dynamic libaries for qlibs and dnsresolv. After - - $ make - -call - - $ make shared - -* Deployment: - -In case conf-build has been customized to include the location of - -- HDRDIR -- LIBDIR - -issue - - $ make install - -to deploy the include files and libs at the given location. -By default, for the libs the parent directory is used. - -* Verification: - -Check the ELFCLASS of the generated binaries in the source directory while calling - - $ file open.o - -They need to comply with your OS. See 'conf-build' for options. - -* Resulting libraries: - -The following libraries are generated: - -- qlibs.a - static basic [w/o DNS] lib (linked to libqlibs.a) -- dnsresolv.a - static DNS resolver lib (linked to libdnsresolv.a) - -and perhaps - -- libqlibs.so - dynamic, position independent (PIC) 'shared object' lib -- libdnsresolv.so - dynamic, position independent (PIC) 'shared object' lib - -These libs are of type ELF64 or ELF32 depending on the system. - -Use 'ar -t' to get the included members of the static libs. -Use 'nm' to view the members and symbols of the libs. - -The shared object libs are known NOT not work on MacOS. - - -Man pages ---------- - -In the ./man directory the current man pages for the basic qlibs routines are included. -Determine the current $mandir and (as root) install the man pages: - - $ cp *.3 $mandir/man3/ +Check the INSTALL.md document. Packaging @@ -114,8 +38,8 @@ Packaging The fehQlibs are incompatible with Gentoo's parallel compilation flag '-jN' for N > 1. -Compilation ------------ +Compatibility +------------- Starting with version fehQlibs-15b, GCC 10 and Clang compatibility is provided, which means ISO C conformance. @@ -124,9 +48,15 @@ by the global (external) 'ipv4socket' variable are avoided. stralloc.h is decoupled from genalloc.h (to be included separately). This respects the GCC 10 compilation unit behavior. +fehQlibs-25 provide compatibility with GCC 14 and Clang 18. Under the hood, +the prototypes include now the correct types of arguments (signatures) required +for function pointers. Some warning still exits; some are silly, others need to +be tackled in forthcoming releases. This depends however on the development +of the 'C' standard and the respective 'C' compilers. + ----- Updated: 20170329, Kai Peter -Updated: 20220706, Erwin Hoffmann +Updated: 20240804, Erwin Hoffmann diff --git a/VERSION b/VERSION index cf310ee..1aee5c2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -fehQlibs-21 +fehQlibs-25 diff --git a/alloc.c b/alloc.c deleted file mode 100644 index 8ec0a7e..0000000 --- a/alloc.c +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include -#include -#include "byte.h" -#include "alloc.h" - -#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */ -#define SPACE 4096 /* must be multiple of ALIGNMENT */ - -typedef union { char irrelevant[ALIGNMENT]; double d; } aligned; -static aligned realspace[SPACE / ALIGNMENT]; -#define space ((char *) realspace) -static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */ - -/*@null@*//*@out@*/char *alloc(unsigned int n) { - char *x; - -/* Guninski exploit + patch from Qualys (CVE-2005-1513) */ - - if (n >= (INT_MAX >> 3)) { - errno = ENOMEM; - return 0; - } - - n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ - if (n <= avail) { avail -= n; return space + avail; } - x = malloc(n); - if (!x) errno = ENOMEM; - return x; -} - -void alloc_free(char *x) -{ - if (x >= space) - if (x < space + SPACE) - return; /* XXX: assuming that pointers are flat */ - free(x); -} - -int alloc_re(char **x,unsigned int m,unsigned int n) -{ - char *y; - - y = alloc(n); - if (!y) return 0; - byte_copy(y,m,*x); - qfree(*x); - *x = y; - return 1; -} diff --git a/base64.c b/base64.c deleted file mode 100644 index 986201e..0000000 --- a/base64.c +++ /dev/null @@ -1,124 +0,0 @@ -#include "base64.h" -#include "stralloc.h" -#include "str.h" - -/** - @file base64.c - @author unkown - @source unknown - @brief base64 en+decoding of strings -*/ - -static char *b64alpha = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -#define B64PAD '=' - -/* returns 0 ok, 1 illegal, -1 problem */ - -int b64decode(const unsigned char *in,int l,stralloc *out) /* not null terminated */ -{ - int p = 0; - int n; - unsigned int x; - int i, j; - char *s; - unsigned char b[3]; - - if (l == 0) { - if (!stralloc_copys(out,"")) return -1; - return 0; - } - - while (in[l-1] == B64PAD) { - p ++; - l--; - } - - n = (l + p) / 4; - i = (n * 3) - p; - if (!stralloc_ready(out,i)) return -1; - out->len = i; - s = out->s; - - for (i = 0; i < n - 1 ; i++) { - x = 0; - for (j = 0; j < 4; j++) { - if(in[j] >= 'A' && in[j] <= 'Z') - x = (x << 6) + (unsigned int)(in[j] - 'A' + 0); - else if(in[j] >= 'a' && in[j] <= 'z') - x = (x << 6) + (unsigned int)(in[j] - 'a' + 26); - else if(in[j] >= '0' && in[j] <= '9') - x = (x << 6) + (unsigned int)(in[j] - '0' + 52); - else if(in[j] == '+') - x = (x << 6) + 62; - else if(in[j] == '/') - x = (x << 6) + 63; - else if(in[j] == '=') - x = (x << 6); - } - - s[2] = (unsigned char)(x & 255); x >>= 8; - s[1] = (unsigned char)(x & 255); x >>= 8; - s[0] = (unsigned char)(x & 255); x >>= 8; - s += 3; in += 4; - } - - x = 0; - for (j = 0; j < 4; j++) { - if(in[j] >= 'A' && in[j] <= 'Z') - x = (x << 6) + (unsigned int)(in[j] - 'A' + 0); - else if(in[j] >= 'a' && in[j] <= 'z') - x = (x << 6) + (unsigned int)(in[j] - 'a' + 26); - else if(in[j] >= '0' && in[j] <= '9') - x = (x << 6) + (unsigned int)(in[j] - '0' + 52); - else if(in[j] == '+') - x = (x << 6) + 62; - else if(in[j] == '/') - x = (x << 6) + 63; - else if(in[j] == '=') - x = (x << 6); - } - - b[2] = (unsigned char)(x & 255); x >>= 8; - b[1] = (unsigned char)(x & 255); x >>= 8; - b[0] = (unsigned char)(x & 255); x >>= 8; - - for (i = 0; i < 3 - p; i++) - s[i] = b[i]; - - return 0; -} - -int b64encode(stralloc *in,stralloc *out) /* not null terminated */ -{ - unsigned char a, b, c; - int i; - char *s; - - if (in->len == 0) { - if (!stralloc_copys(out,"")) return -1; - return 0; - } - - i = in->len / 3 * 4 + 4; - if (!stralloc_ready(out,i)) return -1; - s = out->s; - - for (i = 0; i < in->len; i += 3) { - a = in->s[i]; - b = i + 1 < in->len ? in->s[i + 1] : 0; - c = i + 2 < in->len ? in->s[i + 2] : 0; - - *s++ = b64alpha[a >> 2]; - *s++ = b64alpha[((a & 3 ) << 4) | (b >> 4)]; - - if (i + 1 >= in->len) *s++ = B64PAD; - else *s++ = b64alpha[((b & 15) << 2) | (c >> 6)]; - - if (i + 2 >= in->len) *s++ = B64PAD; - else *s++ = b64alpha[c & 63]; - } - out->len = s - out->s; - - return 0; -} diff --git a/buffer.c b/buffer.c deleted file mode 100644 index 92d72b1..0000000 --- a/buffer.c +++ /dev/null @@ -1,226 +0,0 @@ -#include -#include "buffer.h" -#include "str.h" -#include "byte.h" -#include "error.h" - -/** - @file buffer.c - @author djb - @brief input/output routines -*/ - -void buffer_init(buffer *s,ssize_t (*op)(),int fd,char *buf,size_t len) -{ - s->x = buf; - s->fd = fd; - s->op = op; - s->p = 0; - s->n = len; -} - -ssize_t buffer_0_read(int fd,char *buf,size_t len) -{ - if (buffer_flush(buffer_1) == -1) return -1; - return read(fd,buf,len); -} - -char buffer_0_space[BUFFER_INSIZE]; -static buffer it0 = BUFFER_INIT(buffer_0_read,0,buffer_0_space,sizeof(buffer_0_space)); -buffer *buffer_0 = &it0; - -char buffer_1_space[BUFFER_OUTSIZE]; -static buffer it1 = BUFFER_INIT(write,1,buffer_1_space,sizeof(buffer_1_space)); -buffer *buffer_1 = &it1; - -char buffer_2_space[BUFFER_OUTSIZE]; -static buffer it2 = BUFFER_INIT(write,2,buffer_2_space,sizeof(buffer_2_space)); -buffer *buffer_2 = &it2; - -char buffer_0_small[BUFFER_SMALL]; -static buffer is0 = BUFFER_INIT(buffer_0_read,0,buffer_0_small,sizeof(buffer_0_small)); -buffer *buffer_0small = &is0; - -char buffer_1_small[BUFFER_SMALL]; -static buffer is1 = BUFFER_INIT(write,1,buffer_1_small,sizeof(buffer_1_small)); -buffer *buffer_1small = &is1; - -char buffer_2_small[BUFFER_SMALL]; -static buffer is2 = BUFFER_INIT(write,2,buffer_2_small,sizeof(buffer_2_small)); -buffer *buffer_2small = &is2; - -ssize_t buffer_unixread(int fd,char *buf,size_t len) -{ - return read(fd,buf,len); -} - -ssize_t buffer_unixwrite(int fd,char *buf,size_t len) -{ - return write(fd,buf,len); -} - -int buffer_copy(buffer *bout,buffer *bin) -{ - int n; - char *x; - - for (;;) { - n = buffer_feed(bin); - if (n < 0) return -2; - if (!n) return 0; - x = buffer_PEEK(bin); - if (buffer_put(bout,x,n) == -1) return -3; - buffer_SEEK(bin,n); - } -} - -static int oneread(ssize_t (*op)(),int fd,char *buf,size_t len) -{ - int r; - - for (;;) { - r = op(fd,buf,len); - if (r == -1) if (errno == EINTR) continue; - return r; - } -} - -static int getthis(buffer *s,char *buf,size_t len) -{ - if (len > s->p) len = s->p; - s->p -= len; - byte_copy(buf,len,s->x + s->n); - s->n += len; - return len; -} - -int buffer_feed(buffer *s) -{ - int r; - - if (s->p) return s->p; - r = oneread(s->op,s->fd,s->x,s->n); - if (r <= 0) return r; - s->p = r; - s->n -= r; - if (s->n > 0) byte_copyr(s->x + s->n,r,s->x); - return r; -} - -int buffer_bget(buffer *s,char *buf,size_t len) -{ - int r; - - if (s->p > 0) return getthis(s,buf,len); - if (s->n <= len) return oneread(s->op,s->fd,buf,s->n); - r = buffer_feed(s); - if (r <= 0) return r; - return getthis(s,buf,len); -} - -int buffer_get(buffer *s,char *buf,size_t len) -{ - int r; - - if (s->p > 0) return getthis(s,buf,len); - if (s->n <= len) return oneread(s->op,s->fd,buf,len); - r = buffer_feed(s); - if (r <= 0) return r; - return getthis(s,buf,len); -} - -char *buffer_peek(buffer *s) -{ - return s->x + s->n; -} - -void buffer_seek(buffer *s,size_t len) -{ - s->n += len; - s->p -= len; -} - -static int allwrite(ssize_t (*op)(),int fd,const char *buf,size_t len) -{ - int w; - - while (len) { - w = op(fd,buf,len); - if (w == -1) { - if (errno == EINTR) continue; - return -1; /* note that some data may have been written */ - } - if (w == 0) /* luser's fault */ - ; - buf += w; - len -= w; - } - return 0; -} - -int buffer_flush(buffer *s) -{ - int p; - - p = s->p; - if (!p) return 0; - s->p = 0; - return allwrite(s->op,s->fd,s->x,p); -} - -int buffer_putalign(buffer *s,const char *buf,size_t len) -{ - unsigned int n; - - while (len > (n = s->n - s->p)) { - byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n; - if (buffer_flush(s) == -1) return -1; - } - /* now len <= s->n - s->p */ - byte_copy(s->x + s->p,len,buf); - s->p += len; - return 0; -} - -int buffer_put(buffer *s,const char *buf,size_t len) -{ - unsigned int n; - - n = s->n; - if (len > n - s->p) { - if (buffer_flush(s) == -1) return -1; - /* now s->p == 0 */ - if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE; - while (len > s->n) { - if (n > len) n = len; - if (allwrite(s->op,s->fd,buf,n) == -1) return -1; - buf += n; - len -= n; - } - } - /* now len <= s->n - s->p */ - byte_copy(s->x + s->p,len,buf); - s->p += len; - return 0; -} - -int buffer_putflush(buffer *s,const char *buf,size_t len) -{ - if (buffer_flush(s) == -1) return -1; - return allwrite(s->op,s->fd,buf,len); -} - -int buffer_putsalign(buffer *s,const char *buf) -{ - return buffer_putalign(s,buf,str_len(buf)); -} - -int buffer_puts(buffer *s,const char *buf) -{ - return buffer_put(s,buf,str_len(buf)); -} - -int buffer_putsflush(buffer *s,const char *buf) -{ - return buffer_putflush(s,buf,str_len(buf)); -} diff --git a/byte.c b/byte.c deleted file mode 100644 index c9d6d23..0000000 --- a/byte.c +++ /dev/null @@ -1,99 +0,0 @@ -#include "byte.h" - -/** - @file byte.c - @author djb - @brief byte manipulation functions -*/ - -unsigned int byte_chr(char *s,register unsigned int n,int c) -{ - register char ch; - register char *t; - - ch = c; - t = s; - for (;;) { - if (!n) { break; } if (*t == ch) { break; } ++t; --n; - if (!n) { break; } if (*t == ch) { break; } ++t; --n; - if (!n) { break; } if (*t == ch) { break; } ++t; --n; - if (!n) { break; } if (*t == ch) { break; } ++t; --n; - } - return t - s; -} - -void byte_copy(register char *to,register unsigned int n,register char *from) -{ - for (;;) { - if (!n) { return; } *to++ = *from++; --n; - if (!n) { return; } *to++ = *from++; --n; - if (!n) { return; } *to++ = *from++; --n; - if (!n) { return; } *to++ = *from++; --n; - } -} - -void byte_copyr(register char *to,register unsigned int n,register char *from) -{ - to += n; - from += n; - for (;;) { - if (!n) { return; } *--to = *--from; --n; - if (!n) { return; } *--to = *--from; --n; - if (!n) { return; } *--to = *--from; --n; - if (!n) { return; } *--to = *--from; --n; - } -} - -int byte_diff(register char *s,register unsigned int n,register char *t) -{ - for (;;) { - if (!n) { return 0; } if (*s != *t) { break; } ++s; ++t; --n; - if (!n) { return 0; } if (*s != *t) { break; } ++s; ++t; --n; - if (!n) { return 0; } if (*s != *t) { break; } ++s; ++t; --n; - if (!n) { return 0; } if (*s != *t) { break; } ++s; ++t; --n; - } - return ((int)(unsigned int)(unsigned char) *s) - - ((int)(unsigned int)(unsigned char) *t); -} - -unsigned int byte_rchr(char *s,register unsigned int n,int c) -{ - register char ch; - register char *t; - register char *u; - - ch = c; - t = s; - u = 0; - for (;;) { - if (!n) { break; } if (*t == ch) { u = t; } ++t; --n; - if (!n) { break; } if (*t == ch) { u = t; } ++t; --n; - if (!n) { break; } if (*t == ch) { u = t; } ++t; --n; - if (!n) { break; } if (*t == ch) { u = t; } ++t; --n; - } - if (!u) { u = t; } - return u - s; -} - -void byte_zero(char *s,register unsigned int n) -{ - for (;;) { - if (!n) { break; } *s++ = 0; --n; - if (!n) { break; } *s++ = 0; --n; - if (!n) { break; } *s++ = 0; --n; - if (!n) { break; } *s++ = 0; --n; - } -} - -void byte_fill(char *s,register unsigned int n,const int c) -{ - register char ch; - - ch = c; - for (;;) { - if (!n) { break; } *s++ = ch; --n; - if (!n) { break; } *s++ = ch; --n; - if (!n) { break; } *s++ = ch; --n; - if (!n) { break; } *s++ = ch; --n; - } -} diff --git a/case.c b/case.c deleted file mode 100644 index 47eb8ed..0000000 --- a/case.c +++ /dev/null @@ -1,134 +0,0 @@ -#include "case.h" -#include "str.h" - -/** - @file case.c - @author djb - @brief string comparison and helper functions; case insensitive -*/ - -int case_diffb(register char *s,unsigned int len,register char *t) -{ - register unsigned char x; - register unsigned char y; - - while (len > 0) { - --len; - x = *s++ - 'A'; - if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; - y = *t++ - 'A'; - if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; - if (x != y) - return ((int)(unsigned int) x) - ((int)(unsigned int) y); - } - return 0; -} - -int case_diffs(register char *s,register char *t) -{ - register unsigned char x; - register unsigned char y; - - for (;;) { - x = *s++ - 'A'; - if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; - y = *t++ - 'A'; - if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; - if (x != y) break; - if (!x) break; - } - return ((int)(unsigned int) x) - ((int)(unsigned int) y); -} - -int case_diffrs(register char *s,register char *t) -{ - register unsigned char x = 0; - register unsigned char y = 0; - unsigned int lens = str_len(s); - unsigned int lent = str_len(t); - - while (lens > 0 && lent > 0) { - x = s[--lens] - 'A'; - if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; - y = t[--lent] - 'A'; - if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; - if (x != y) break; - if (!x) break; - if (!y) break; - } - return ((int)(unsigned int) x) - ((int)(unsigned int) y); -} - -void case_lowerb(char *s,unsigned int len) -{ - unsigned char x; - while (len > 0) { - --len; - x = *s - 'A'; - if (x <= 'Z' - 'A') *s = x + 'a'; - ++s; - } -} - -void case_lowers(char *s) -{ - unsigned char x; - while ((x = *s)) { - x -= 'A'; - if (x <= 'Z' - 'A') *s = x + 'a'; - ++s; - } -} - -void case_upperb(char *s,unsigned int len) -{ - unsigned char x; - while (len > 0) { - --len; - x = *s - 'a'; - if (x <= 'z' - 'a') *s = x + 'A'; - ++s; - } -} - -void case_uppers(char *s) -{ - unsigned char x; - while ((x = *s)) { - x -= 'a'; - if (x <= 'z' - 'a') *s = x + 'A'; - ++s; - } -} - -int case_startb(register char *s,unsigned int len,register char *t) -{ - register unsigned char x; - register unsigned char y; - - for (;;) { - y = *t++ - 'A'; - if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; - if (!y) return 1; - if (!len) return 0; - --len; - x = *s++ - 'A'; - if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; - if (x != y) return 0; - } -} - -int case_starts(register char *s,register char *t) -{ - register unsigned char x; - register unsigned char y; - - for (;;) { - x = *s++ - 'A'; - if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; - y = *t++ - 'A'; - if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; - if (!y) return 1; - if (x != y) return 0; - } -} diff --git a/cdbmake.c b/cdbmake.c deleted file mode 100644 index 28e170c..0000000 --- a/cdbmake.c +++ /dev/null @@ -1,158 +0,0 @@ -#include -#include "seek.h" -#include "error.h" -#include "alloc.h" -#include "cdbread.h" -#include "cdbmake.h" - -/** - @file cdbmake.c - @author djb - @source ucspi-tcp - @brief constant data base (cdb) generation -*/ - -int cdb_make_start(struct cdb_make *c,int fd) -{ - c->head = 0; - c->split = 0; - c->hash = 0; - c->numentries = 0; - c->fd = fd; - c->pos = sizeof(c->final); - buffer_init(&c->b,write,fd,c->bspace,sizeof(c->bspace)); - return seek_set(fd,c->pos); -} - -static int posplus(struct cdb_make *c,uint32 len) -{ - uint32 newpos = c->pos + len; - if (newpos < len) { errno = ENOMEM; return -1; } - c->pos = newpos; - return 0; -} - -int cdb_make_addend(struct cdb_make *c,unsigned int keylen,unsigned int datalen,uint32 h) -{ - struct cdb_hplist *head; - - head = c->head; - if (!head || (head->num >= CDB_HPLIST)) { - head = (struct cdb_hplist *) alloc(sizeof(struct cdb_hplist)); - if (!head) return -1; - head->num = 0; - head->next = c->head; - c->head = head; - } - head->hp[head->num].h = h; - head->hp[head->num].p = c->pos; - ++head->num; - ++c->numentries; - if (posplus(c,8) == -1) return -1; - if (posplus(c,keylen) == -1) return -1; - if (posplus(c,datalen) == -1) return -1; - return 0; -} - -int cdb_make_addbegin(struct cdb_make *c,unsigned int keylen,unsigned int datalen) -{ - char buf[8]; - - if (keylen > 0xffffffff) { errno = ENOMEM; return -1; } - if (datalen > 0xffffffff) { errno = ENOMEM; return -1; } - - uint32_pack(buf,keylen); - uint32_pack(buf + 4,datalen); - if (buffer_putalign(&c->b,buf,8) == -1) return -1; - return 0; -} - -int cdb_make_add(struct cdb_make *c,char *key,unsigned int keylen,char *data,unsigned int datalen) -{ - if (cdb_make_addbegin(c,keylen,datalen) == -1) return -1; - if (buffer_putalign(&c->b,key,keylen) == -1) return -1; - if (buffer_putalign(&c->b,data,datalen) == -1) return -1; - return cdb_make_addend(c,keylen,datalen,cdb_hash(key,keylen)); -} - -int cdb_make_finish(struct cdb_make *c) -{ - char buf[8]; - int i; - uint32 len; - uint32 u; - uint32 memsize; - uint32 count; - uint32 where; - struct cdb_hplist *x; - struct cdb_hp *hp; - - for (i = 0; i < 256; ++i) - c->count[i] = 0; - - for (x = c->head; x; x = x->next) { - i = x->num; - while (i--) - ++c->count[255 & x->hp[i].h]; - } - - memsize = 1; - for (i = 0; i < 256; ++i) { - u = c->count[i] * 2; - if (u > memsize) - memsize = u; - } - - memsize += c->numentries; /* no overflow possible up to now */ - u = (uint32) 0 - (uint32) 1; - u /= sizeof(struct cdb_hp); - if (memsize > u) { errno = ENOMEM; return -1; } - - c->split = (struct cdb_hp *) alloc(memsize * sizeof(struct cdb_hp)); - if (!c->split) return -1; - - c->hash = c->split + c->numentries; - - u = 0; - for (i = 0; i < 256; ++i) { - u += c->count[i]; /* bounded by numentries, so no overflow */ - c->start[i] = u; - } - - for (x = c->head; x; x = x->next) { - i = x->num; - while (i--) - c->split[--c->start[255 & x->hp[i].h]] = x->hp[i]; - } - - for (i = 0; i < 256; ++i) { - count = c->count[i]; - - len = count + count; /* no overflow possible */ - uint32_pack(c->final + 8 * i,c->pos); - uint32_pack(c->final + 8 * i + 4,len); - - for (u = 0; u < len; ++u) - c->hash[u].h = c->hash[u].p = 0; - - hp = c->split + c->start[i]; - for (u = 0; u < count; ++u) { - where = (hp->h >> 8) % len; - while (c->hash[where].p) - if (++where == len) - where = 0; - c->hash[where] = *hp++; - } - - for (u = 0; u < len; ++u) { - uint32_pack(buf,c->hash[u].h); - uint32_pack(buf + 4,c->hash[u].p); - if (buffer_putalign(&c->b,buf,8) == -1) return -1; - if (posplus(c,8) == -1) return -1; - } - } - - if (buffer_flush(&c->b) == -1) return -1; - if (seek_begin(c->fd) == -1) return -1; - return buffer_putflush(&c->b,c->final,sizeof(c->final)); -} diff --git a/cdbread.c b/cdbread.c deleted file mode 100644 index c8ffa42..0000000 --- a/cdbread.c +++ /dev/null @@ -1,169 +0,0 @@ -#include -#include -#include -#include -#include "error.h" -#include "seek.h" -#include "byte.h" -#include "cdbread.h" - -/** - @file cdbread.c - @author djb - @source ucspi-tcp, fastforward - @brief read entries from a cdb -*/ - -uint32 cdb_unpack(unsigned char *buf) -{ - uint32 num; - num = buf[3]; num <<= 8; - num += buf[2]; num <<= 8; - num += buf[1]; num <<= 8; - num += buf[0]; - return num; -} - -void cdb_free(struct cdb *c) -{ - if (c->map) { - munmap(c->map,c->size); - c->map = 0; - } -} - -void cdb_findstart(struct cdb *c) -{ - c->loop = 0; -} - -void cdb_init(struct cdb *c,int fd) -{ - struct stat st; - char *x; - - cdb_free(c); - cdb_findstart(c); - c->fd = fd; - - if (fstat(fd,&st) == 0) - if (st.st_size <= 0xffffffff) { - x = mmap(0,st.st_size,PROT_READ,MAP_SHARED,fd,0); - if (x + 1) { - c->size = st.st_size; - c->map = x; - } - } -} - -int cdb_read(struct cdb *c,char *buf,unsigned int len,uint32 pos) -{ - if (c->map) { - if ((pos > c->size) || (c->size - pos < len)) goto FORMAT; - byte_copy(buf,len,c->map + pos); - } - else { - if (seek_set(c->fd,pos) == -1) return -1; - while (len > 0) { - int r; - do - r = read(c->fd,buf,len); - while ((r == -1) && (errno == EINTR)); - if (r == -1) return -1; - if (r == 0) goto FORMAT; - buf += r; - len -= r; - } - } - return 0; - - FORMAT: - errno = EPROTO; - return -1; -} - -static int match(struct cdb *c,char *key,unsigned int len,uint32 pos) -{ - char buf[32]; - int n; - - while (len > 0) { - n = sizeof(buf); - if (n > len) n = len; - if (cdb_read(c,buf,n,pos) == -1) return -1; - if (byte_diff(buf,n,key)) return 0; - pos += n; - key += n; - len -= n; - } - return 1; -} - -int cdb_findnext(struct cdb *c,char *key,unsigned int len) -{ - char buf[8]; - uint32 pos; - uint32 u; - - if (!c->loop) { - u = cdb_hash(key,len); - if (cdb_read(c,buf,8,(u << 3) & 2047) == -1) return -1; - uint32_unpack(buf + 4,&c->hslots); - if (!c->hslots) return 0; - uint32_unpack(buf,&c->hpos); - c->khash = u; - u >>= 8; - u %= c->hslots; - u <<= 3; - c->kpos = c->hpos + u; - } - - while (c->loop < c->hslots) { - if (cdb_read(c,buf,8,c->kpos) == -1) return -1; - uint32_unpack(buf + 4,&pos); - if (!pos) return 0; - c->loop += 1; - c->kpos += 8; - if (c->kpos == c->hpos + (c->hslots << 3)) c->kpos = c->hpos; - uint32_unpack(buf,&u); - if (u == c->khash) { - if (cdb_read(c,buf,8,pos) == -1) return -1; - uint32_unpack(buf,&u); - if (u == len) - switch(match(c,key,len,pos + 8)) { - case -1: - return -1; - case 1: - uint32_unpack(buf + 4,&c->dlen); - c->dpos = pos + 8 + len; - return 1; - } - } - } - - return 0; -} - -int cdb_find(struct cdb *c,char *key,unsigned int len) -{ - cdb_findstart(c); - return cdb_findnext(c,key,len); -} - -uint32 cdb_hashadd(uint32 h,unsigned char c) -{ - h += (h << 5); - return h ^ c; -} - -uint32 cdb_hash(char *buf,unsigned int len) -{ - uint32 h; - - h = CDB_HASHSTART; - while (len) { - h = cdb_hashadd(h,*buf++); - --len; - } - return h; -} diff --git a/conf-build b/conf-build index a2428c4..66258c2 100644 --- a/conf-build +++ b/conf-build @@ -3,7 +3,7 @@ # #******************************************************************************** # default compiler flags - usually this shouldn't be changed -CFLAGS='-O2 -Iinclude -fPIC -Wall' +CFLAGS='-O2 -Iinclude -fPIC -fwrapv -Wall' # under OmniOS the binaries are build as 32 bit version; except enabling this: #CFLAGS='-O2 -Iinclude -Wall -fPIC -m64' diff --git a/configure b/configure index 34785ac..47b0f08 100755 --- a/configure +++ b/configure @@ -2,7 +2,7 @@ #******************************************************************************** # Very simple configure script for qlibs -. ./conf-build +. ../conf-build # Add $HDRDIR as include option to default $CFLAGS [ "$HDRDIR" ] && CFLAGS="$CFLAGS -I$HDRDIR" diff --git a/constmap.c b/constmap.c deleted file mode 100644 index ecd5a92..0000000 --- a/constmap.c +++ /dev/null @@ -1,169 +0,0 @@ -#include "constmap.h" -#include "alloc.h" -#include "case.h" - -static constmap_hash hash(char *s,int len) -{ - unsigned char ch; - constmap_hash h; - h = 5381; - while (len > 0) { - ch = *s++ - 'A'; - if (ch <= 'Z' - 'A') ch += 'a' - 'A'; - h = ((h << 5) + h) ^ ch; - --len; - } - return h; -} - -char *constmap(struct constmap *cm,char *s,int len) -{ - constmap_hash h; - int pos; - h = hash(s,len); - pos = cm->first[h & cm->mask]; - while (pos != -1) { - if (h == cm->hash[pos]) - if (len == cm->inputlen[pos]) - if (!case_diffb(cm->input[pos],len,s)) - return cm->input[pos] + cm->inputlen[pos] + 1; - pos = cm->next[pos]; - } - return 0; -} - -int constmap_init(struct constmap *cm,char *s,int len,int flagcolon) -{ - int i; - int j; - int k; - int pos; - constmap_hash h; - - cm->num = 0; - for (j = 0; j < len; ++j) if (!s[j]) ++cm->num; - - h = 64; - while (h && (h < cm->num)) h += h; - cm->mask = h - 1; - - cm->first = (int *) alloc(sizeof(int) * h); - if (cm->first) { - cm->input = (char **) alloc(sizeof(char *) * cm->num); - if (cm->input) { - cm->inputlen = (int *) alloc(sizeof(int) * cm->num); - if (cm->inputlen) { - cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num); - if (cm->hash) { - cm->next = (int *) alloc(sizeof(int) * cm->num); - if (cm->next) { - for (h = 0; h <= cm->mask; ++h) - cm->first[h] = -1; - pos = 0; - i = 0; - for (j = 0; j < len; ++j) - if (!s[j]) { - k = j - i; - if (flagcolon) { - for (k = i; k < j; ++k) - if (s[k] == ':') break; - if (k >= j) { i = j + 1; continue; } - k -= i; - } - cm->input[pos] = s + i; - cm->inputlen[pos] = k; - h = hash(s + i,k); - cm->hash[pos] = h; - h &= cm->mask; - cm->next[pos] = cm->first[h]; - cm->first[h] = pos; - ++pos; - i = j + 1; - } - return 1; - } - alloc_free(cm->hash); - } - alloc_free(cm->inputlen); - } - alloc_free(cm->input); - } - alloc_free(cm->first); - } - return 0; -} - -int constmap_init_char(struct constmap *cm,char *s,int len,int flagcolon,char flagchar) -{ - int i; - int j; - int k; - int pos; - constmap_hash h; - - if (!flagchar || flagchar == 0 || flagchar == '\0') { - flagchar = ':'; - } - - cm->num = 0; - for (j = 0; j < len; ++j) if (!s[j]) ++cm->num; - - h = 64; - while (h && (h < cm->num)) h += h; - cm->mask = h - 1; - - cm->first = (int *) alloc(sizeof(int) * h); - if (cm->first) { - cm->input = (char **) alloc(sizeof(char *) * cm->num); - if (cm->input) { - cm->inputlen = (int *) alloc(sizeof(int) * cm->num); - if (cm->inputlen) { - cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num); - if (cm->hash) { - cm->next = (int *) alloc(sizeof(int) * cm->num); - if (cm->next) { - for (h = 0; h <= cm->mask; ++h) - cm->first[h] = -1; - pos = 0; - i = 0; - for (j = 0; j < len; ++j) { - if (!s[j]) { - k = j - i; - if (flagcolon) { - for (k = i; k < j; ++k) - if (s[k] == flagchar) break; - if (k >= j) { i = j + 1; continue; } - k -= i; - } - cm->input[pos] = s + i; - cm->inputlen[pos] = k; - h = hash(s + i,k); - cm->hash[pos] = h; - h &= cm->mask; - cm->next[pos] = cm->first[h]; - cm->first[h] = pos; - ++pos; - i = j + 1; - } - } - return 1; - } - alloc_free(cm->hash); - } - alloc_free(cm->inputlen); - } - alloc_free(cm->input); - } - alloc_free(cm->first); - } - return 0; -} - -void constmap_free(struct constmap *cm) -{ - alloc_free(cm->next); - alloc_free(cm->hash); - alloc_free(cm->inputlen); - alloc_free(cm->input); - alloc_free(cm->first); -} diff --git a/dnsstub/Makefile b/dnsstub/Makefile deleted file mode 100644 index 6c3bab3..0000000 --- a/dnsstub/Makefile +++ /dev/null @@ -1,23 +0,0 @@ - -COMPILE=../compile -MAKELIB=../makelib -CCFLAGS=-I../include - -default: clean check dnsresolv.a - -check: - @[ -f $(COMPILE) ] && [ -f $(MAKELIB) ] || ( cd .. ; ./configure ; ) - -clean: - rm -f `cat TARGETS` - -dnsresolv.a: \ -dns_domain.c dns_dtda.c dns_ip.c dns_ipq.c dns_name.c \ -dns_nd.c dns_packet.c dns_random.c dns_rcip.c dns_rcrw.c dns_resolve.c \ -dns_sortip.c dns_transmit.c dns_txt.c - $(COMPILE) $(CCFLAGS) dns_domain.c dns_dfd.c dns_dtda.c dns_ip.c dns_ipq.c \ - dns_mx.c dns_name.c dns_nd.c dns_packet.c dns_random.c dns_rcip.c \ - dns_rcrw.c dns_resolve.c dns_sortip.c dns_transmit.c dns_txt.c dns_cname.c - $(MAKELIB) dnsresolv.a dns_domain.o dns_dfd.o dns_dtda.o dns_ip.o dns_ipq.o \ - dns_mx.o dns_name.o dns_nd.o dns_packet.o dns_random.o dns_rcip.o \ - dns_rcrw.o dns_resolve.o dns_sortip.o dns_transmit.o dns_txt.o dns_cname.o diff --git a/dnsstub/README.md b/dnsstub/README.md deleted file mode 100644 index 95cd11c..0000000 --- a/dnsstub/README.md +++ /dev/null @@ -1,171 +0,0 @@ -/*! \mainpage - -Stub Resolver -============= - -Simple DJBDNS stub-resolver based on 'djbdns-1.05(IPv6)' allowing for each -calling application individually to include up to 16 DNSCACHEIP(s) -as DNS forwarding/resolving servers to be tried sequentially. - -IP Addresses ------------- - -Here, - - global IPv6, - - IPv6 ULA, and - - IPv6 LLU addresses with a given Interface-Id -can be specified. The IPv4 format could be either a - - legacy dotted-decimal or a - - IPv4-mapped IPv6 address. - -In any case, compactified IPv6 addresses are understood. -IPv4/IPv6 addresses in brackets are understood by dns_ip. - -Resolver Call -------------- - -If $DNSCACHEIP is not provided as environment variable, the stub-resolver -will use the system-wide - - /etc/resolv.conf -file; however now without the capability for IPv6 LLU addresses. -While IPv4-mapped IPv6 addresses are supported here by default as well, -care has to taken not to jeopardize other client's usage. - -Name Qualification ------------------- - -If provided, the stub-resolver uses either a system-wide configuration file - - /etc/dnsrewritefile or assumes this file to available as given in - - $DNSREWRITEFILE -in order to define persistent mapping-rules of local domain names to public -ones (for lookup) or IP addresses (for direct matching). - -Well-known domain names 'localhost', 'ip4-loopback' and 'ip6-loopback' -are handled locally, thus no DNS query is used (RFC 6761). -'localhost' is advertised as '::1' and '::ff:127.0.0.1' in it's native -IPv6 format. It is up to the caller to convert the IPv6-mapped IPv4 -address to the IPv4 format. - -Local domain names can be alternatively specified (per application) using -the environment variable - - $LOCALDOMAIN -to be appended to unqualified hostnames dynamically. This is roughly equivalent -with the 'search' string in /etc/resolv. Several domains names may be -specified within $LOCALDOMAIN separated by blanks. - -See: https://cr.yp.to/djbdns/qualify.html - - -Specific DNS Record type lookup -------------------------------- - -* dns_ip (A, AAAAA) -* dns_name (PTR) -* dns_cname (CNAME) -* dns_txt (TXT) -- now considering several 'labels' -* dns_mx (MX) - - -Internals ---------- - -* UDP message size: -Unlike other implementations, this DNS stub-resolver supports UDP packet -sizes up to 1028 byte without the need for (E)DNS0 packet enhancements. - -* DNS UDP query retrials: -In case the NS is not able to initally reply to the query, -it is retried again at the intervalls {1, 2, 4, 8, 16} secs. - -* DNS name qualification (dns_ip_qualify): -Well-known domain names are qualified locally without invoking a DNS query -while handling IPv4 and IPv6 addresses separately. - -* NS qualification/sorting for NS replies: -NS qualification is not supported (yet), thus we use a randomly sorted -list of NS IP addresses. - -* Query/Reply to/from DNS Cache servers/forwarders: -Neither message (CurveDNS) nor transport layer (TLS) encryption is provided; -the sub-resolver 'trusts' it's upstream caches/forwarders. We recommend to -setup communication on private IPv4/IPv6 addresses; if applicable. - -* DNS TXT Records: -The label substructure is now recognized in the RDATA section; -each label may have the size of 255 byte. -The length information is excluded from the output. -Only printable characters are recognized in the output. - -* Return Codes: -Different from DJB's initial routines, the DNS front-end routines - dns_cname*, dns_ip*, dns_mx*, dns_name*, dns dns_txt* -return now the number of replies received (not bytes!). -Thus, three cases need to be considered: - - - rc < 0: Problem occured (SOFTFAIL, HARDFAIL) - - rc = 0: No answer obtained (but query was successful) = NXDOMAIN - - rc > 0: rc answers received; positive reply - -For return codes < 0, the following conventions have been applied: - - include/dnsresolv.h - -\#define DNS_NXD 0 -\#define DNS_MEM -1 -\#define DNS_ERR -2 /* parsing errors and others */ -\#define DNS_COM -3 /* (socket) communication errors */ -\#define DNS_INT -4 /* internal errors */ -\#define DNS_SOFT -5 /* either -2 or -3 */ -\#define DNS_HARD -6 /* CNAME loop problem */ - -The modification of the return code is typically not problematic, -since mostly just rc = -1 is checked. - -In the future, these return codes are subject of change. -Thus, instead of - - if (dns_XX(...) == -1) - -one shoud use the more general syntax - - if (dns_XX(...) < 0) - -to check for 'negative' results, allowing further actions -and refinements given the calling sequence. - - - -Environment Variables Read --------------------------- - -$DNSCACHEPIP The upstream resolver's IP[v4|v6] addresses (up to 32). - IPv6 LLU addresses may be suffixed with the interface name. -$DNSREWRITEFILE Alternate location for the system-wide - /etc/dnsrewrite -file -$LOCALDOMAIN Additional local domain name appended to unqualified - hostnames dynamically. - -Sample for the file /etc/dnsrewrite: - -\#annything.local -> me -\-.example.com:me -\# me -> 127.0.0.1 -\=me:127.0.0.1 -\# any.name.a -> any.name.af.mil -\*.a:.af.mil -\# any-name-without-dots -> any-name-without-dots.heaven.af.mil -\?:.heaven.af.mil -\# remove trailing dot -\*.: - -and DJB's explanations are given here: - -Instructions are followed in order, each at most once. There are four types of instructions: - -\=post:new means that the host name post is replaced by new. -\*post:new means that any name of the form prepost is replaced by prenew. -\?post:new means that any name of the form prepost, where pre does not contain dots or brackets, is replaced by prenew. -\-post:new means that any name of the form prepost is replaced by new. - -Erwin Hoffmann, June 2023. diff --git a/dnsstub/TARGETS b/dnsstub/TARGETS deleted file mode 100644 index 62f40be..0000000 --- a/dnsstub/TARGETS +++ /dev/null @@ -1,18 +0,0 @@ -dns_cname.o -dns_dfd.o -dns_domain.o -dns_dtda.o -dns_ip.o -dns_ipq.o -dns_mx.o -dns_name.o -dns_nd.o -dns_packet.o -dns_random.o -dns_rcip.o -dns_rcrw.o -dns_resolve.o -dns_sortip.o -dns_transmit.o -dns_txt.o -dnsresolv.a diff --git a/dnsstub/dns_cname.c b/dnsstub/dns_cname.c deleted file mode 100644 index 408949a..0000000 --- a/dnsstub/dns_cname.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "stralloc.h" -#include "uint_t.h" -#include "byte.h" -#include "ip.h" -#include "case.h" -#include "dnsresolv.h" - -/** - @file dns_cname.c - @author feh - @brief DNS cname lookup -*/ - -static char *q = 0; - -int dns_cname_packet(stralloc *out,const char *buf,unsigned int len) -{ - unsigned int pos; - char header[12]; - uint16 numanswers; - uint16 datalen; - int ranswers = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - - pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 6,&numanswers); - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos += 4; - - while (numanswers--) { - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 8,&datalen); - if (byte_equal(header,2,DNS_T_CNAME)) - if (byte_equal(header + 2,2,DNS_C_IN)) { - if (!dns_packet_getname(buf,len,pos,&q)) return DNS_ERR; - if (dns_domain_todot_cat(out,q) <= 0) return DNS_ERR; - } - pos += datalen; - ++ranswers; - } - - return ranswers; -} - -int dns_cname(stralloc *out,stralloc *fqdn) -{ - int rc; - - if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; - if (dns_resolve(q,DNS_T_CNAME) < 0) return DNS_ERR; - if ((rc = dns_cname_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - if (case_equals(out->s,fqdn->s)) rc = -6; // loop DNS_HARD - - return rc; -} diff --git a/dnsstub/dns_dfd.c b/dnsstub/dns_dfd.c deleted file mode 100644 index 756a1f8..0000000 --- a/dnsstub/dns_dfd.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "error.h" -#include "alloc.h" -#include "byte.h" -#include "dnsresolv.h" - -/** - @file dns_dfd.c - @author djb - @source ucspi-tcp - @brief domain name qualification (domain from dot) -*/ - -int dns_domain_fromdot(char **out,const char *buf,unsigned int n) -{ - char label[63]; - unsigned int labellen = 0; /* <= sizeof label */ - char name[255]; - unsigned int namelen = 0; /* <= sizeof name */ - char ch; - char *x; - - errno = EPROTO; - - for (;;) { - if (!n) break; - ch = *buf++; --n; - if (ch == '.') { - if (labellen) { - if (namelen + labellen + 1 > sizeof(name)) return 0; - name[namelen++] = labellen; - byte_copy(name + namelen,labellen,label); - namelen += labellen; - labellen = 0; - } - continue; - } - if (ch == '\\') { // octal -> decimal - if (!n) break; - ch = *buf++; --n; - if ((ch >= '0') && (ch <= '7')) { - ch -= '0'; - if (n && (*buf >= '0') && (*buf <= '7')) { - ch <<= 3; - ch += *buf - '0'; - ++buf; --n; - if (n && (*buf >= '0') && (*buf <= '7')) { - ch <<= 3; - ch += *buf - '0'; - ++buf; --n; - } - } - } - } - if (labellen >= sizeof(label)) return 0; - label[labellen++] = ch; - } - - if (labellen) { - if (namelen + labellen + 1 > sizeof(name)) return 0; - name[namelen++] = labellen; - byte_copy(name + namelen,labellen,label); - namelen += labellen; - labellen = 0; - } - - if (namelen + 1 > sizeof(name)) return 0; - name[namelen++] = 0; - - x = alloc(namelen); - if (!x) return DNS_MEM; - byte_copy(x,namelen,name); - - if (*out) alloc_free(*out); - *out = x; - return 1; -} diff --git a/dnsstub/dns_domain.c b/dnsstub/dns_domain.c deleted file mode 100644 index 654a827..0000000 --- a/dnsstub/dns_domain.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "alloc.h" -#include "case.h" -#include "byte.h" -#include "dnsresolv.h" - -/** - @file dns_domain.c - @author djb - @source ucspi-tcp - @brief domain qualification -*/ - -unsigned int dns_domain_length(const char *dn) -{ - const char *x; - unsigned char c; - - x = dn; - while ((c = *x++)) - x += (unsigned int) c; - return x - dn; -} - -void dns_domain_free(char **out) -{ - if (*out) { - alloc_free(*out); - *out = 0; - } -} - -int dns_domain_copy(char **out,const char *in) -{ - unsigned int len; - char *x; - - len = dns_domain_length(in); - x = alloc(len); - if (!x) return 0; - byte_copy(x,len,in); - if (*out) alloc_free(*out); - *out = x; - return 1; -} - -int dns_domain_equal(const char *dn1,const char *dn2) -{ - unsigned int len; - - len = dns_domain_length(dn1); - if (len != dns_domain_length(dn2)) return 0; - - if (case_diffb((char *)dn1,len,(char *)dn2)) return 0; /* safe since 63 < 'A' */ - return 1; -} - -int dns_domain_suffix(const char *big,const char *little) -{ - unsigned char c; - - for (;;) { - if (dns_domain_equal(big,little)) return 1; - c = *big++; - if (!c) return 0; - big += c; - } -} - -unsigned int dns_domain_suffixpos(const char *big,const char *little) -{ - const char *orig = big; - unsigned char c; - - for (;;) { - if (dns_domain_equal(big,little)) return big - orig; - c = *big++; - if (!c) return 0; - big += c; - } -} diff --git a/dnsstub/dns_dtda.c b/dnsstub/dns_dtda.c deleted file mode 100644 index 38358a2..0000000 --- a/dnsstub/dns_dtda.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "stralloc.h" -#include "dnsresolv.h" - -/** - @file dns_dtda.c - @author djb - @source ucspi-tcp - @brief domain to dot append -*/ - -int dns_domain_todot_cat(stralloc *out,const char *d) -{ - char ch; - char ch2; - unsigned char ch3; - char buf[4]; - - if (!*d) - return stralloc_append(out,"."); - - for (;;) { - ch = *d++; - while (ch--) { - ch2 = *d++; - if ((ch2 >= 'A') && (ch2 <= 'Z')) ch2 += 32; // FQDN -> lowercase - if (((ch2 >= 'a') && (ch2 <= 'z')) || - ((ch2 >= '0') && (ch2 <= '9')) || - (ch2 == '-') || (ch2 == '_')) { - if (!stralloc_append(out,&ch2)) return DNS_MEM; - } - else { // decimal -> octal - ch3 = ch2; - buf[3] = '0' + (ch3 & 7); ch3 >>= 3; - buf[2] = '0' + (ch3 & 7); ch3 >>= 3; - buf[1] = '0' + (ch3 & 7); - buf[0] = '\\'; - if (!stralloc_catb(out,buf,4)) return DNS_MEM; - } - } - if (!*d) return 1; - if (!stralloc_append(out,".")) return DNS_MEM; - } -} diff --git a/dnsstub/dns_ip.c b/dnsstub/dns_ip.c deleted file mode 100644 index f89728c..0000000 --- a/dnsstub/dns_ip.c +++ /dev/null @@ -1,198 +0,0 @@ -#include "stralloc.h" -#include "uint_t.h" -#include "byte.h" -#include "ip.h" -#include "dnsresolv.h" - -/** - @file dns_ip.c - @author djb, fefe, feh - @source ucspi-tcp6 - @brief DNS IP query -*/ - -static char *q = 0; - -int dns_ip4_packet(stralloc *out,const char *buf,unsigned int len) -{ - unsigned int pos; - char header[12]; - uint16 numanswers; - uint16 datalen; - int ranswers = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - - pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 6,&numanswers); - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos += 4; - - while (numanswers--) { - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 8,&datalen); - if (byte_equal(header,2,DNS_T_A)) - if (byte_equal(header + 2,2,DNS_C_IN)) - if (datalen == 4) { - if (!dns_packet_copy(buf,len,pos,header,4)) return DNS_ERR; - if (!stralloc_catb(out,header,4)) return DNS_MEM; - } - pos += datalen; - ++ranswers; - } - - dns_sortip4(out->s,out->len); - return ranswers; -} - -int dns_ip4(stralloc *out,stralloc *fqdn) -{ - unsigned int i; - char code = 0; - int dot = 0; - char ch; - char ip[4]; - int r; - int rc = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - if (!stralloc_readyplus(fqdn,1)) return DNS_MEM; - - fqdn->s[fqdn->len] = 0; /* test FQDN string */ - for (i = 1; i < fqdn->len; i++) { - if (fqdn->s[i] >= '_') { code = 127; break; } - if (fqdn->s[i] == '.') dot++; - } - - if (code != 127 && dot == 3) /* if FQDN is just IPv4 */ - if (ip4_scan(fqdn->s,ip) || ip4_scanbracket(fqdn->s,ip)) { - if (!stralloc_copyb(out,ip,4)) return DNS_MEM; - return 1; - } - - code = 0; - for (i = 0; i <= fqdn->len; ++i) { - if (i < fqdn->len) - ch = fqdn->s[i]; - else - ch = '.'; - - if ((ch == '[') || (ch == ']')) continue; - if (ch == '.') { - if (!stralloc_append(out,&code)) return DNS_MEM; - code = 0; - continue; - } - if ((ch >= '0') && (ch <= '9')) { - code *= 10; - code += ch - '0'; - continue; - } - - if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; // fdqn -> A query -> response - if (dns_resolve(q,DNS_T_A) >= 0) { - if ((r = dns_ip4_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - rc += r; - } - - return rc; - } - - out->len &= ~3; - return 0; -} - -int dns_ip6_packet(stralloc *out,const char *buf,unsigned int len) -{ - unsigned int pos; - char header[16]; - uint16 numanswers; - uint16 datalen; - int ranswers = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - - pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 6,&numanswers); - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos += 4; - - while (numanswers--) { - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 8,&datalen); - if (byte_equal(header,2,DNS_T_AAAA)) { - if (byte_equal(header + 2,2,DNS_C_IN)) - if (datalen == 16) { - if (!dns_packet_copy(buf,len,pos,header,16)) return DNS_ERR; - if (!stralloc_catb(out,header,16)) return DNS_MEM; - } - } else if (byte_equal(header,2,DNS_T_A)) - if (byte_equal(header + 2,2,DNS_C_IN)) - if (datalen == 4) { - byte_copy(header,12,V4mappedprefix); - if (!dns_packet_copy(buf,len,pos,header + 12,4)) return DNS_ERR; - if (!stralloc_catb(out,header,16)) return DNS_MEM; - } - pos += datalen; - ++ranswers; - } - - dns_sortip6(out->s,out->len); - return ranswers; -} - -int dns_ip6(stralloc *out,stralloc *fqdn) -{ - unsigned int i; - char code; - char ch; - char ip[16]; - int r; - int rc = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - if (!stralloc_readyplus(fqdn,1)) return DNS_MEM; - - fqdn->s[fqdn->len] = 0; /* if FQDN is just IPv6 */ - if (ip6_scan(fqdn->s,ip) || ip6_scanbracket(fqdn->s,ip)) { - if (!stralloc_copyb(out,ip,16)) return DNS_MEM; - return 1; - } - - code = 0; - for (i = 0; i <= fqdn->len; ++i) { - if (i < fqdn->len) - ch = fqdn->s[i]; - else - ch = '.'; - - if ((ch == '[') || (ch == ']')) continue; - if (ch == '.') { - if (!stralloc_append(out,&code)) return DNS_MEM; - code = 0; - continue; - } - if ((ch >= '0') && (ch <= '9')) { - code *= 10; - code += ch - '0'; - continue; - } - - if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; // fqdn -> AAAA query -> response - if (dns_resolve(q,DNS_T_AAAA) >= 0) { - if ((r = dns_ip6_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - rc += r; - } - - return rc; - } - - out->len &= ~3; - return 0; -} diff --git a/dnsstub/dns_ipq.c b/dnsstub/dns_ipq.c deleted file mode 100644 index 26c3818..0000000 --- a/dnsstub/dns_ipq.c +++ /dev/null @@ -1,236 +0,0 @@ -#include "case.h" -#include "byte.h" -#include "str.h" -#include "stralloc.h" -#include "dnsresolv.h" -#include "socket_if.h" -#include "ip.h" - -/** - @file dns_ipq.c - @author djb, feh - @source ucspi-tcp - @brief DNS hostname qualification for ipv4 and ipv6 -*/ - -/** - @fn int doit -> @return number of added chars to name -*/ -static int doit(stralloc *work,const char *rule) -{ - char ch; - unsigned int colon; - unsigned int prefixlen; - - ch = *rule++; - if ((ch != '?') && (ch != '=') && (ch != '*') && (ch != '-')) return 1; - colon = str_chr((char *)rule,':'); - if (!rule[colon]) return 1; - - if (work->len < colon) return 1; - prefixlen = work->len - colon; - if ((ch == '=') && prefixlen) return 1; - if (case_diffb((char *)rule,colon,work->s + prefixlen)) return 1; - if (ch == '?') { - if (byte_chr(work->s,prefixlen,'.') < prefixlen) return 1; - if (byte_chr(work->s,prefixlen,'[') < prefixlen) return 1; - if (byte_chr(work->s,prefixlen,']') < prefixlen) return 1; - } - - work->len = prefixlen; - if (ch == '-') work->len = 0; - return stralloc_cats(work,rule + colon + 1); -} - -/** @fn int dns_ip4_qualify_rules -> @return number of IPv4 addresss with rules */ - -int dns_ip4_qualify_rules(stralloc *ipout,stralloc *fqdn,const stralloc *in,const stralloc *rules) -{ - unsigned int i; - unsigned int j; - unsigned int plus; - unsigned int fqdnlen; - int rc = 0; - - if (!stralloc_copy(fqdn,(stralloc *)in)) return DNS_MEM; - - for (j = i = 0; j < rules->len; ++j) - if (!rules->s[j]) { - if (!doit(fqdn,rules->s + i)) return DNS_INT; - i = j + 1; - } - - fqdnlen = fqdn->len; - plus = byte_chr(fqdn->s,fqdnlen,'+'); - if (plus >= fqdnlen) - return dns_ip4(ipout,fqdn); - - i = plus + 1; - for (;;) { - j = byte_chr(fqdn->s + i,fqdnlen - i,'+'); - byte_copy(fqdn->s + plus,j,fqdn->s + i); - fqdn->len = plus + j; - if (rc += dns_ip4(ipout,fqdn) < 0) return DNS_ERR; - i += j; - if (i >= fqdnlen) return rc; - ++i; - } - return 0; -} - -/** @fn int dns_ip4_qualify -> @return number of IPv4 addresss qualified */ - -int dns_ip4_qualify(stralloc *ipout,stralloc *fqdn,const stralloc *in) -{ - int r; - static stralloc rules; - - if ((r = dns_ip_qualify_localhost(ipout,fqdn,in)) > 0 ) return r; - if (dns_resolvconfrewrite(&rules) < 0) return DNS_INT; - return dns_ip4_qualify_rules(ipout,fqdn,in,&rules); -} - -/** @fn int dns_ip4_qualify_rules -> @return number of IPv6 addresss with rules */ - -int dns_ip6_qualify_rules(stralloc *ipout,stralloc *fqdn,const stralloc *in,const stralloc *rules) -{ - unsigned int i; - unsigned int j; - unsigned int plus; - unsigned int fqdnlen; - int rc = 0; - - if (!stralloc_copy(fqdn,(stralloc *)in)) return DNS_MEM; - - for (j = i = 0; j < rules->len; ++j) - if (!rules->s[j]) { - if (!doit(fqdn,rules->s + i)) return DNS_INT; - i = j + 1; - } - - fqdnlen = fqdn->len; - plus = byte_chr(fqdn->s,fqdnlen,'+'); - if (plus >= fqdnlen) - return dns_ip6(ipout,fqdn); - - i = plus + 1; - for (;;) { - j = byte_chr(fqdn->s + i,fqdnlen - i,'+'); - byte_copy(fqdn->s + plus,j,fqdn->s + i); - fqdn->len = plus + j; - if ((rc += dns_ip6(ipout,fqdn)) < 0) return DNS_ERR; - i += j; - if (i >= fqdnlen) return rc; - ++i; - } - return 0; -} - -/** @fn int dns_ip6_qualify -> @return number of IPv6 addresss qualified */ - -int dns_ip6_qualify(stralloc *ipout,stralloc *fqdn,const stralloc *in) -{ - int r; - static stralloc rules; - - if ((r = dns_ip_qualify_localhost(ipout,fqdn,in)) > 0) return r; - if (dns_resolvconfrewrite(&rules) < 0) return DNS_INT; - return dns_ip6_qualify_rules(ipout,fqdn,in,&rules); -} - -/** @fn int dns_ip_qualify_rules -> @return number of IPv6+IPv4 addresss with rules */ - -int dns_ip_qualify_rules(stralloc *ipout,stralloc *fqdn,const stralloc *in,const stralloc *rules) -{ - unsigned int i; - unsigned int j; - unsigned int k; - unsigned int plus; - unsigned int fqdnlen; - stralloc tmp = {0}; - int rc = 0; - - if (!stralloc_copy(fqdn,(stralloc *)in)) return DNS_MEM; - if (!stralloc_copys(ipout,"")) return DNS_MEM; - - for (j = i = 0; j < rules->len; ++j) - if (!rules->s[j]) { - if (!doit(fqdn,rules->s + i)) return DNS_INT; - i = j + 1; - } - - fqdnlen = fqdn->len; - plus = byte_chr(fqdn->s,fqdnlen,'+'); - if (plus >= fqdnlen) { - rc = dns_ip6(ipout,fqdn); - if (dns_ip4(&tmp,fqdn) > 0) { - for (k = 0; k < tmp.len; k += 4) { - if (!stralloc_catb(ipout,(const char *) V4mappedprefix,12)) return DNS_MEM; - if (!stralloc_catb(ipout,tmp.s + k,4)) return DNS_MEM; - rc++; - } - } - return rc; - } - - i = plus + 1; - for (;;) { - j = byte_chr(fqdn->s + i,fqdnlen - i,'+'); - byte_copy(fqdn->s + plus,j,fqdn->s + i); - fqdn->len = plus + j; - if (!stralloc_copys(ipout,"")) return DNS_MEM; - rc = dns_ip6(&tmp,fqdn); - if (rc) if (!stralloc_cat(ipout,&tmp)) return DNS_MEM; - if (dns_ip4(&tmp,fqdn) > 0) { - for (k = 0; k < tmp.len; k += 4) { - if (!stralloc_catb(ipout,(const char *) V4mappedprefix,12)) return DNS_MEM; - if (!stralloc_catb(ipout,tmp.s + k,4)) return DNS_MEM; - rc++; - } - } - - if (rc < 0) return DNS_ERR; - i += j; - if (i >= fqdnlen) return rc; - ++i; - } - return 0; -} - -/** @fn int dns_ip_qualify_localhost -> @return number of IP addresss */ - -int dns_ip_qualify_localhost(stralloc *ipout,stralloc *fqdn,const stralloc *in) -{ - if (!stralloc_copys(ipout,"")) return DNS_MEM; - if (!stralloc_copys(fqdn,"")) return DNS_MEM; - ipout->len = 0; - - if (byte_equal(in->s,9,LOCALHOST)) { - if (!stralloc_copyb(ipout,(const char *) V6loopback,16)) return DNS_MEM; - if (!stralloc_catb(ipout,(const char *) V46loopback,16)) return DNS_MEM; - if (!stralloc_copys(fqdn,"localhost.localhost.")) return DNS_MEM; - } - if (byte_equal(in->s,13,IP4_LOOPBACK)) { - if (!stralloc_copyb(ipout,(const char *) V46loopback,16)) return DNS_MEM; - if (!stralloc_copys(fqdn,"ip4-loopback.localhost.")) return DNS_MEM; - } - if (byte_equal(in->s,13,IP6_LOOPBACK)) { - if (!stralloc_copyb(ipout,(const char *) V6loopback,16)) return DNS_MEM; - if (!stralloc_copys(fqdn,"ip6-loopback.localhost.")) return DNS_MEM; - } -// if (!stralloc_0(fqdn)) return DNS_MEM; // don't do it - - return ipout->len ? ipout->len % 15 : 0; -} - -/** @fn int dns_ip_qualify -> @return number of IP addresss */ - -int dns_ip_qualify(stralloc *ipout,stralloc *fqdn,const stralloc *in) -{ - int r; - static stralloc rules; - - if ((r = dns_ip_qualify_localhost(ipout,fqdn,in)) > 0 ) return r; - if (dns_resolvconfrewrite(&rules) < 0) return DNS_INT; - return dns_ip_qualify_rules(ipout,fqdn,in,&rules); -} diff --git a/dnsstub/dns_mx.c b/dnsstub/dns_mx.c deleted file mode 100644 index c0845ef..0000000 --- a/dnsstub/dns_mx.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "stralloc.h" -#include "byte.h" -#include "uint_t.h" -#include "dnsresolv.h" - -/** - @file dns_mx.c - @author djb - @source qmail - @brief dns MX query - @param (on output) stralloc out -*/ - -static char *q = 0; - -int dns_mx_packet(stralloc *out,const char *buf,unsigned int len) -{ - unsigned int pos; - char header[12]; - char pref[2]; - uint16 numanswers; - uint16 datalen; - int ranswers = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - - pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 6,&numanswers); - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos += 4; - - while (numanswers--) { - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 8,&datalen); - if (byte_equal(header,2,DNS_T_MX)) - if (byte_equal(header + 2,2,DNS_C_IN)) { - if (!dns_packet_copy(buf,len,pos,pref,2)) return DNS_ERR; - if (!dns_packet_getname(buf,len,pos + 2,&q)) return DNS_ERR; - if (!stralloc_catb(out,pref,2)) return DNS_MEM; - if (dns_domain_todot_cat(out,q) <= 0) return DNS_ERR; - if (!stralloc_0(out)) return DNS_MEM; - } - pos += datalen; - ++ranswers; - } - - return ranswers; -} - -int dns_mx(stralloc *out,const stralloc *fqdn) -{ - int rc = 0; - - if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; - if (dns_resolve(q,DNS_T_MX) >= 0) { - if ((rc = dns_mx_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - } - - return rc; -} diff --git a/dnsstub/dns_name.c b/dnsstub/dns_name.c deleted file mode 100644 index 0723a8f..0000000 --- a/dnsstub/dns_name.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "stralloc.h" -#include "uint_t.h" -#include "byte.h" -#include "ip.h" -#include "dnsresolv.h" - -/** - @file dns_name.c - @author djb, fefe, feh - @source ucspi-tcp - @brief DNS name query (ptr) -*/ - -static char *q = 0; - -int dns_name_packet(stralloc *out,const char *buf,unsigned int len) -{ - unsigned int pos; - char header[12]; - uint16 numanswers; - uint16 datalen; - - if (!stralloc_copys(out,"")) return DNS_MEM; - - pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 6,&numanswers); - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos += 4; - - while (numanswers--) { - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 8,&datalen); - if (byte_equal(header,2,DNS_T_PTR)) - if (byte_equal(header + 2,2,DNS_C_IN)) { - if (!dns_packet_getname(buf,len,pos,&q)) return DNS_ERR; - if (dns_domain_todot_cat(out,q) <= 0) return DNS_ERR; - return 1; - } - pos += datalen; - } - - return 0; -} - -int dns_name4(stralloc *out,const char ip[4]) -{ - int rc; - char name[DNS_NAME4_DOMAIN]; - - dns_name4_domain(name,ip); - if (dns_resolve(name,DNS_T_PTR) < 0) return DNS_ERR; - if ((rc = dns_name_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - - return rc; -} - -int dns_name6(stralloc *out,const char ip[16]) -{ - int rc; - char name[DNS_NAME6_DOMAIN]; - - dns_name6_domain(name,ip); - if (dns_resolve(name,DNS_T_PTR) < 0) return DNS_ERR; - if ((rc = dns_name_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - - return rc; -} - -int dns_name(stralloc *out,const char ip[16]) -{ - if (ip6_isv4mapped(ip)) - return dns_name4(out,ip+12); - else - return dns_name6(out,ip); -} diff --git a/dnsstub/dns_nd.c b/dnsstub/dns_nd.c deleted file mode 100644 index 6ce8ed9..0000000 --- a/dnsstub/dns_nd.c +++ /dev/null @@ -1,48 +0,0 @@ -#include "byte.h" -#include "fmt.h" -#include "ip.h" -#include "dnsresolv.h" - -/** - @file dns_nd.c - @autor djb, fefe - @source ucspi-tcp - @brief DNS domain name for ip (wire format) -*/ - -int dns_name4_domain(char name[DNS_NAME4_DOMAIN],const char ip[4]) -{ - unsigned int namelen; - unsigned int i; - - namelen = 0; - i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[3]); - name[namelen++] = i; - namelen += i; - i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[2]); - name[namelen++] = i; - namelen += i; - i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[1]); - name[namelen++] = i; - namelen += i; - i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[0]); - name[namelen++] = i; - namelen += i; - byte_copy(name + namelen,14,"\7in-addr\4arpa\0"); - return namelen+14; -} - -int dns_name6_domain(char name[DNS_NAME6_DOMAIN],const char ip[16]) -{ - unsigned int j; - - for (j = 0; j < 16; j++) { - name[j * 4] = 1; - name[j * 4 + 1] = tohex(ip[15 - j] & 15); - name[j * 4 + 2] = 1; - name[j * 4 + 3] = tohex((unsigned char)ip[15 - j] >> 4); - } - byte_copy(name + 4 * 16,10,"\3ip6\4arpa\0"); - return 4 * 16 + 10; -} - diff --git a/dnsstub/dns_packet.c b/dnsstub/dns_packet.c deleted file mode 100644 index ce322ea..0000000 --- a/dnsstub/dns_packet.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "error.h" -#include "dnsresolv.h" - -/** - @file dns_packet.c - @author djb - @source ucspi-tcp - @brief DNS low level packet routine - @brief DNS should have used LZ77 instead of its own sophomoric compression algorithm. -*/ - -unsigned int dns_packet_copy(const char *buf,unsigned int len,unsigned int pos,char *out,unsigned int outlen) -{ - while (outlen) { - if (pos >= len) { errno = EPROTO; return 0; } - *out = buf[pos++]; - ++out; --outlen; - } - return pos; -} - -unsigned int dns_packet_skipname(const char *buf,unsigned int len,unsigned int pos) -{ - unsigned char ch; - - for (;;) { - if (pos >= len) break; - ch = buf[pos++]; - if (ch >= 192) return pos + 1; - if (ch >= 64) break; - if (!ch) return pos; - pos += ch; - } - - errno = EPROTO; - return 0; -} - -unsigned int dns_packet_getname(const char *buf,unsigned int len,unsigned int pos,char **d) -{ - unsigned int loop = 0; - unsigned int state = 0; - unsigned int firstcompress = 0; - unsigned int where; - unsigned char ch; - char name[255]; - unsigned int namelen = 0; - - for (;;) { - if (pos >= len) goto PROTO; - ch = buf[pos++]; - if (++loop >= 1000) goto PROTO; - - if (state) { - if (namelen + 1 > sizeof(name)) goto PROTO; - name[namelen++] = ch; - --state; - } else { - while (ch >= 192) { - where = ch; where -= 192; where <<= 8; - if (pos >= len) goto PROTO; - ch = buf[pos++]; - if (!firstcompress) firstcompress = pos; - pos = where + ch; - if (pos >= len) goto PROTO; - ch = buf[pos++]; - if (++loop >= 1000) goto PROTO; - } - if (ch >= 64) goto PROTO; - if (namelen + 1 > sizeof(name)) goto PROTO; - name[namelen++] = ch; - if (!ch) break; - state = ch; - } - } - - if (!dns_domain_copy(d,name)) return 0; - - if (firstcompress) return firstcompress; - return pos; - - PROTO: - errno = EPROTO; - return 0; -} diff --git a/dnsstub/dns_random.c b/dnsstub/dns_random.c deleted file mode 100644 index 200cd6c..0000000 --- a/dnsstub/dns_random.c +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include "taia.h" -#include "uint_t.h" -#include "dnsresolv.h" - -/** - @file dns_random.c - @author djb - @source ucspi-tcp - @brief random use of DNS resolvers given their IP -*/ - -static uint32 seed[32]; -static uint32 in[12]; -static uint32 out[8]; -static int outleft = 0; - -#define ROTATE(x,b) (((x) << (b)) | ((x) >> (32 - (b)))) -#define MUSH(i,b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x,b)); - -static void surf(void) -{ - uint32 t[12]; uint32 x; uint32 sum = 0; - int r; int i; int loop; - - for (i = 0; i < 12; ++i) t[i] = in[i] ^ seed[12 + i]; - for (i = 0; i < 8; ++i) out[i] = seed[24 + i]; - x = t[11]; - for (loop = 0; loop < 2; ++loop) { - for (r = 0; r < 16; ++r) { - sum += 0x9e3779b9; - MUSH(0,5) MUSH(1,7) MUSH(2,9) MUSH(3,13) - MUSH(4,5) MUSH(5,7) MUSH(6,9) MUSH(7,13) - MUSH(8,5) MUSH(9,7) MUSH(10,9) MUSH(11,13) - } - for (i = 0; i < 8; ++i) out[i] ^= t[i + 4]; - } -} - -void dns_random_init(const char data[128]) -{ - int i; - struct taia t; - char tpack[16]; - - for (i = 0; i < 32; ++i) - uint32_unpack((char *)data + 4 * i,seed + i); - - taia_now(&t); - taia_pack(tpack,&t); - for (i = 0; i < 4; ++i) - uint32_unpack(tpack + 4 * i,in + 4 + i); - - in[8] = getpid(); - in[9] = getppid(); - /* more space in 10 and 11, but this is probably enough */ -} - -unsigned int dns_random(unsigned int n) -{ - if (!n) return 0; - - if (!outleft) { - if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3]; - surf(); - outleft = 8; - } - - return out[--outleft] % n; -} diff --git a/dnsstub/dns_rcip.c b/dnsstub/dns_rcip.c deleted file mode 100644 index 93b0daa..0000000 --- a/dnsstub/dns_rcip.c +++ /dev/null @@ -1,114 +0,0 @@ -#include "taia.h" -#include "readclose.h" -#include "byte.h" -#include "ip.h" -#include "env.h" -#include "dnsresolv.h" -#include "socket_if.h" - -/** - @file dns_rcip.c - @author djb, fefe, feh - @source ucspi-tcp - @brief DNS receive for query -*/ - -static stralloc data = {0}; -static stralloc ifname = {0}; - -static int init(char ip[QUERY_MAXIPLEN],uint32 sid[QUERY_MAXNS]) -{ - int i; - int j; - int k = 0; - int iplen = 0; - char *x; - char ip4[4]; - -/* Read (compactified) IPv4|v6 addresses of resolvers - Store them in array IP with fixed length : - ip(64) -> 16 IPv4 addresses (not used anymore) - ip(512) -> 16*2 IPv6 addresses (we use IPv4 mapped IPv6 addresses) - sid(32) -> the scope for the respective IPv6 or 0 -*/ - for (i = 0; i < QUERY_MAXNS; ++i) sid[i] = 0; - - x = env_get("DNSCACHEIP"); - if (x) - while (iplen <= 240 && *x != '\0') { - if (*x == ' ') - ++x; - else - if ((i = ip6_ifscan(x,ip + iplen,&ifname))) { - if (ifname.len > 2) sid[k] = socket_getifidx(ifname.s); - iplen += 16; k++; - if (*(x += i) == '\0') break; - } - } - - if (!iplen) { - i = openreadclose("/etc/resolv.conf",&data,64); - if (i == -1) return DNS_INT; - if (i) { - if (!stralloc_append(&data,"\n")) return DNS_MEM; - i = 0; - for (j = 0; j < data.len; ++j) - if (data.s[j] == '\n') { - if (byte_equal("nameserver ",11,data.s + i) || byte_equal("nameserver\t",11,data.s + i)) { - i += 10; - while ((data.s[i] == ' ') || (data.s[i] == '\t')) - i++; - if (iplen <= 240) { - data.s[j] = '\0'; /* ip6_ifscan needs terminated string on input */ - if (ip4_scan(data.s + i,ip4)) { - if (byte_equal(ip4,4,"\0\0\0\0")) - byte_copy(ip4,4,"\177\0\0\1"); - byte_copy(ip + iplen,12,V4mappedprefix); - byte_copy(ip + iplen + 12,4,ip4); - sid[k] = 0; iplen += 16; k++; - } else if (ip6_ifscan(data.s + i,ip + iplen,&ifname)) { - if (ifname.len > 2) sid[k] = socket_getifidx(ifname.s); - iplen += 16; k++; - } - } - } - i = j + 1; - } - } - } - - if (!iplen) { - byte_copy(ip,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"); - iplen = 16; - } - byte_zero(ip + iplen,QUERY_MAXIPLEN - iplen); - return 0; -} - -static int ok = 0; -static unsigned int uses; -static struct taia deadline; -static char ip[QUERY_MAXIPLEN]; /* defined if ok */ -static uint32 scopes[QUERY_MAXNS]; - -int dns_resolvconfip(char s[QUERY_MAXIPLEN],uint32 scope[QUERY_MAXNS]) -{ - struct taia now; - - taia_now(&now); - if (taia_less(&deadline,&now)) ok = 0; - if (!uses) ok = 0; - - if (!ok) { - if (init(ip,scopes) < 0) return DNS_INT; - taia_uint(&deadline,600); - taia_add(&deadline,&now,&deadline); - uses = 10000; - ok = 1; - } - - --uses; - byte_copy(s,QUERY_MAXIPLEN,ip); - byte_copy(scope,128,scopes); - return 0; -} diff --git a/dnsstub/dns_rcrw.c b/dnsstub/dns_rcrw.c deleted file mode 100644 index 4633fed..0000000 --- a/dnsstub/dns_rcrw.c +++ /dev/null @@ -1,141 +0,0 @@ -#include -#include "taia.h" -#include "env.h" -#include "byte.h" -#include "str.h" -#include "readclose.h" -#include "dnsresolv.h" - -/** - @file dns_rcrw.c - @author djb - @source ucspi-tcp - @brief DNS receive rewrite -*/ - -static stralloc data = {0}; - -static int init(stralloc *rules) -{ - char host[256]; - const char *x; - int i; - int j; - int k; - - if (!stralloc_copys(rules,"")) return DNS_MEM; - - x = env_get("DNSREWRITEFILE"); - if (!x) x = "/etc/dnsrewrite"; - - i = openreadclose(x,&data,64); - if (i == -1) return DNS_INT; - - if (i) { - if (!stralloc_append(&data,"\n")) return DNS_MEM; - i = 0; - for (j = 0; j < data.len; ++j) - if (data.s[j] == '\n') { - if (!stralloc_catb(rules,data.s + i,j - i)) return DNS_MEM; - while (rules->len) { - if (rules->s[rules->len - 1] != ' ') - if (rules->s[rules->len - 1] != '\t') - if (rules->s[rules->len - 1] != '\r') - break; - --rules->len; - } - if (!stralloc_0(rules)) return DNS_MEM; - i = j + 1; - } - return 0; - } - - x = env_get("LOCALDOMAIN"); - if (x) { - if (!stralloc_copys(&data,x)) return DNS_MEM; - if (!stralloc_append(&data," ")) return DNS_MEM; - if (!stralloc_copys(rules,"?:")) return DNS_MEM; - i = 0; - for (j = 0; j < data.len; ++j) - if (data.s[j] == ' ') { - if (!stralloc_cats(rules,"+.")) return DNS_MEM; - if (!stralloc_catb(rules,data.s + i,j - i)) return DNS_MEM; - i = j + 1; - } - if (!stralloc_0(rules)) return DNS_MEM; - if (!stralloc_cats(rules,"*.:")) return DNS_MEM; - if (!stralloc_0(rules)) return DNS_MEM; - return 0; - } - - i = openreadclose("/etc/resolv.conf",&data,64); - if (i == -1) return DNS_INT; - - if (i) { - if (!stralloc_append(&data,"\n")) return DNS_MEM; - i = 0; - for (j = 0; j < data.len; ++j) - if (data.s[j] == '\n') { - if (byte_equal("search ",7,data.s + i) || - byte_equal("search\t",7,data.s + i) || - byte_equal("domain ",7,data.s + i) || - byte_equal("domain\t",7,data.s + i)) { - if (!stralloc_copys(rules,"?:")) return DNS_MEM; - i += 7; - while (i < j) { - k = byte_chr(data.s + i,j - i,' '); - k = byte_chr(data.s + i,k,'\t'); - if (!k) { ++i; continue; } - if (!stralloc_cats(rules,"+.")) return DNS_MEM; - if (!stralloc_catb(rules,data.s + i,k)) return DNS_MEM; - i += k; - } - if (!stralloc_0(rules)) return DNS_MEM; - if (!stralloc_cats(rules,"*.:")) return DNS_MEM; - if (!stralloc_0(rules)) return DNS_MEM; - return 0; - } - i = j + 1; - } - } - - host[0] = 0; - if (gethostname(host,sizeof(host)) == -1) return DNS_ERR; - host[(sizeof(host)) - 1] = 0; - i = str_chr(host,'.'); - if (host[i]) { - if (!stralloc_copys(rules,"?:")) return DNS_MEM; - if (!stralloc_cats(rules,host + i)) return DNS_MEM; - if (!stralloc_0(rules)) return DNS_MEM; - } - if (!stralloc_cats(rules,"*.:")) return DNS_MEM; - if (!stralloc_0(rules)) return DNS_MEM; - - return 0; -} - -static int ok = 0; -static unsigned int uses; -static struct taia deadline; -static stralloc rules = {0}; /* defined if ok */ - -int dns_resolvconfrewrite(stralloc *out) -{ - struct taia now; - - taia_now(&now); - if (taia_less(&deadline,&now)) ok = 0; - if (!uses) ok = 0; - - if (!ok) { - if (init(&rules) < 0) return DNS_INT; - taia_uint(&deadline,600); - taia_add(&deadline,&now,&deadline); - uses = 10000; - ok = 1; - } - - --uses; - if (!stralloc_copy(out,&rules)) return DNS_MEM; - return 0; -} diff --git a/dnsstub/dns_resolve.c b/dnsstub/dns_resolve.c deleted file mode 100644 index bcc4308..0000000 --- a/dnsstub/dns_resolve.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "iopause.h" -#include "taia.h" -#include "byte.h" -#include "ip.h" -#include "dnsresolv.h" - -/** - @file dns_resolve.c - @author djb, fefe, feh - @source ucspi-tcp - @brief high-level DNS resolve function -*/ - -struct dns_transmit dns_resolve_tx = {0}; - -int dns_resolve(const char *q,const char qtype[2]) -{ - struct taia stamp; - struct taia deadline; - char servers[QUERY_MAXIPLEN]; - uint32 scopes[QUERY_MAXNS]; - iopause_fd x[1]; - int r; - - if (dns_resolvconfip(servers,scopes) < 0) return DNS_INT; - - if (dns_transmit_start6(&dns_resolve_tx,servers,1,q,qtype,(const char *)V6localnet,scopes) < 0) return DNS_COM; - - for (;;) { - taia_now(&stamp); - taia_uint(&deadline,120); - taia_add(&deadline,&deadline,&stamp); - dns_transmit_io(&dns_resolve_tx,x,&deadline); - iopause(x,1,&deadline,&stamp); - r = dns_transmit_get(&dns_resolve_tx,x,&stamp); - if (r < 0) return DNS_COM; - if (r == 1) return 0; - } -} diff --git a/dnsstub/dns_sortip.c b/dnsstub/dns_sortip.c deleted file mode 100644 index 56742e0..0000000 --- a/dnsstub/dns_sortip.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "byte.h" -#include "ip.h" -#include "dnsresolv.h" - -/** - @file dns_sortip.c - @authors djb, fefe, feh - @source ucspi-tcp6 - @brief random sort of DNS servers per IP -*/ - -/* XXX: sort servers by configurable notion of closeness? */ -/* XXX: pay attention to competence of each server? */ -/* XXX: pay attention to qualification (DNSSec, DNSCurve) of each server? */ -/* YYY: we use a randomly sorted list of NS; not depending on answer */ - -void dns_sortip4(char *s,unsigned int n) -{ - unsigned int i; - char tmp[4]; - - n >>= 2; /* 4 byte per IPv4 address */ - while (n > 1) { - i = dns_random(n); - --n; - byte_copy(tmp,4,s + (i << 2)); - byte_copy(s + (i << 2),4,s + (n << 2)); - byte_copy(s + (n << 2),4,tmp); - } -} - -void dns_sortip6(char *s,unsigned int n) -{ - unsigned int i; - char tmp[16]; - - n >>= 4; /* 16 byte per IPv4 address */ - while (n > 1) { - i = dns_random(n); - --n; - byte_copy(tmp,16,s + (i << 4)); - byte_copy(s + (i << 4),16,s + (n << 4)); - byte_copy(s + (n << 4),16,tmp); - } -} diff --git a/dnsstub/dns_transmit.c b/dnsstub/dns_transmit.c deleted file mode 100644 index 2513565..0000000 --- a/dnsstub/dns_transmit.c +++ /dev/null @@ -1,436 +0,0 @@ -#include -#include -#include -#include "socket_if.h" -#include "alloc.h" -#include "error.h" -#include "byte.h" -#include "uint_t.h" -#include "ip.h" -#include "dnsresolv.h" - -/** - @file dns_transmit.c - @authors djb, fefe, feh - @source qlibs - @brief DNS query function - @brief scope_ids[32] -> 32 LLU root servers supported -*/ - -#define DNSPORT 53 - -uint32 scope_ids[QUERY_MAXNS]; - -static const int timeouts[5] = { 1, 2, 4, 8, 16 }; /* quadratic, not exponentially */ - -int getscopeid(const struct dns_transmit *d,const char *ip) -{ - int i; - - if (byte_diff(ip,2,V6linklocal)) return 0; - for (i = 0; i < QUERY_MAXNS; ++i) - if (byte_equal(d->servers + 16 * i,16,ip)) - return scope_ids[i]; - - return 0; -} - -int serverwantstcp(const char *buf,unsigned int len) -{ - char out[12]; - - if (!dns_packet_copy(buf,len,0,out,12)) return 1; - if (out[2] & 2) return 1; - - return 0; -} - -int serverfailed(const char *buf,unsigned int len) -{ - char out[12]; - unsigned int rcode; - - if (!dns_packet_copy(buf,len,0,out,12)) return 1; - rcode = out[3]; - rcode &= 15; - if (rcode && (rcode != 3)) { errno = EAGAIN; return 1; } - - return 0; -} - -int irrelevant(const struct dns_transmit *d,const char *buf,unsigned int len) -{ - char out[12]; - char *dn; - unsigned int pos; - - pos = dns_packet_copy(buf,len,0,out,12); if (!pos) return 1; - if (byte_diff(out,2,d->query + 2)) return 1; - if (out[4] != 0) return 1; - if (out[5] != 1) return 1; - - dn = 0; - pos = dns_packet_getname(buf,len,pos,&dn); if (!pos) return 1; - if (!dns_domain_equal(dn,d->query + 14)) { alloc_free(dn); return 1; } - alloc_free(dn); - - pos = dns_packet_copy(buf,len,pos,out,4); if (!pos) return 1; - if (byte_diff(out,2,d->qtype)) return 1; - if (byte_diff(out + 2,2,DNS_C_IN)) return 1; - - return 0; -} - -void packetfree(struct dns_transmit *d) -{ - if (!d->packet) return; - alloc_free(d->packet); - d->packet = 0; -} - -void queryfree(struct dns_transmit *d) -{ - if (!d->query) return; - alloc_free(d->query); - d->query = 0; -} - -void socketfree(struct dns_transmit *d) -{ - if (!d->s1) return; - close(d->s1 - 1); - d->s1 = 0; -} - -void dns_transmit_free(struct dns_transmit *d) -{ - queryfree(d); - socketfree(d); - packetfree(d); -} - -int randombind6(struct dns_transmit *d) -{ - int j; - - for (j = 0; j < 10; ++j) { - if (socket_bind6(d->s1 - 1,d->localip,1025 + dns_random(64510),d->scope_id) == 0) - return 0; - } - if (socket_bind6(d->s1 - 1,d->localip,0,d->scope_id) == 0) - return 0; - - return DNS_COM; -} - -int randombind4(struct dns_transmit *d) -{ - int j; - - for (j = 0; j < 10; ++j) { - if (socket_bind4(d->s1 - 1,d->localip + 12,1025 + dns_random(64510)) == 0) - return 0; - } - if (socket_bind4(d->s1 - 1,d->localip + 12,0) == 0) - return 0; - - return DNS_COM; -} - -int thisudp(struct dns_transmit *d) -{ - const char *ip; - - socketfree(d); - - while (d->udploop < 5) { - for (; d->curserver < QUERY_MAXNS; ++d->curserver) { - ip = d->servers + 16 * d->curserver; - if (byte_diff(ip,16,V6localnet)) { - d->query[2] = dns_random(256); - d->query[3] = dns_random(256); - - if (ip6_isv4mapped(ip)) { - d->s1 = 1 + socket_udp4(); - if (!d->s1) { dns_transmit_free(d); return DNS_COM; } - if (randombind4(d) < 0) { dns_transmit_free(d); return DNS_COM; } - } else { - d->s1 = 1 + socket_udp6(); - if (!d->s1) { dns_transmit_free(d); return DNS_COM; } - if (randombind6(d) < 0) { dns_transmit_free(d); return DNS_COM; } - } - - if (byte_equal(ip,2,V6linklocal) && !d->scope_id) - d->scope_id = getscopeid(d,ip); - if (socket_connect(d->s1 - 1,ip,DNSPORT,d->scope_id) == 0) - if (send(d->s1 - 1,d->query + 2,d->querylen - 2,0) == d->querylen - 2) { - struct taia now; - taia_now(&now); - taia_uint(&d->deadline,timeouts[d->udploop]); - taia_add(&d->deadline,&d->deadline,&now); - d->tcpstate = 0; - return 0; - } - socketfree(d); - } - } - ++d->udploop; - d->curserver = 0; - } - - dns_transmit_free(d); return DNS_COM; -} - -int firstudp(struct dns_transmit *d) -{ - d->curserver = 0; - return thisudp(d); -} - -int nextudp(struct dns_transmit *d) -{ - ++d->curserver; - return thisudp(d); -} - -int thistcp(struct dns_transmit *d) -{ - struct taia now; - const char *ip; - - socketfree(d); - packetfree(d); - - for (; d->curserver < QUERY_MAXNS; ++d->curserver) { - ip = d->servers + 16 * d->curserver; - if (byte_diff(ip,16,V6localnet)) { - d->query[2] = dns_random(256); - d->query[3] = dns_random(256); - - if (ip6_isv4mapped(ip)) { - d->s1 = 1 + socket_tcp4(); - if (!d->s1) { dns_transmit_free(d); return DNS_COM; } - if (randombind4(d) < 0) { dns_transmit_free(d); return DNS_COM; } - } else { - d->s1 = 1 + socket_tcp6(); - if (!d->s1) { dns_transmit_free(d); return DNS_COM; } - if (randombind6(d) < 0) { dns_transmit_free(d); return DNS_COM; } - } - - taia_now(&now); - taia_uint(&d->deadline,10); - taia_add(&d->deadline,&d->deadline,&now); - - if (byte_equal(ip,2,V6linklocal) && !d->scope_id) - d->scope_id = getscopeid(d,ip); - if (socket_connect(d->s1 - 1,ip,DNSPORT,d->scope_id) == 0) { - d->tcpstate = 2; - return 0; - } - if ((errno == EINPROGRESS) || (errno == EWOULDBLOCK)) { - d->tcpstate = 1; - return 0; - } - - socketfree(d); - } - } - - dns_transmit_free(d); - return DNS_COM; -} - -int firsttcp(struct dns_transmit *d) -{ - d->curserver = 0; - return thistcp(d); -} - -int nexttcp(struct dns_transmit *d) -{ - ++d->curserver; - return thistcp(d); -} - -int dns_transmit_start(struct dns_transmit *d,const char servers[QUERY_MAXIPLEN], \ - int flagrecursive,const char *q,const char qtype[2],const char localip[16]) -{ - unsigned int len; - - dns_transmit_free(d); - errno = EIO; - - len = dns_domain_length(q); - d->querylen = len + 18; - d->query = alloc(d->querylen); - if (!d->query) return DNS_COM; - - uint16_pack_big(d->query,len + 16); - byte_copy(d->query + 2,12,flagrecursive ? "\0\0\1\0\0\1\0\0\0\0\0\0" : \ - "\0\0\0\0\0\1\0\0\0\0\0\0gcc-bug-workaround"); - byte_copy(d->query + 14,len,q); - byte_copy(d->query + 14 + len,2,qtype); - byte_copy(d->query + 16 + len,2,DNS_C_IN); - - byte_copy(d->qtype,2,(char *) qtype); - d->servers = servers; - byte_copy(d->localip,16,(char *) localip); - - d->udploop = flagrecursive ? 1 : 0; - - if (len + 16 > MSGSIZE) return firsttcp(d); - return firstudp(d); -} - -int dns_transmit_start6(struct dns_transmit *d,const char servers[QUERY_MAXIPLEN], \ - int flagrecursive,const char *q,const char qtype[2], \ - const char localip[16],const uint32 scopes[QUERY_MAXNS]) -{ - byte_copy(scope_ids,128,(char *) scopes); - - return dns_transmit_start(d,servers,flagrecursive,q,qtype,localip); -} - -void dns_transmit_io(struct dns_transmit *d,iopause_fd *x,struct taia *deadline) -{ - x->fd = d->s1 - 1; - - switch (d->tcpstate) { - case 0: case 3: case 4: case 5: - x->events = IOPAUSE_READ; - break; - case 1: case 2: - x->events = IOPAUSE_WRITE; - break; - } - - if (taia_less(&d->deadline,deadline)) - *deadline = d->deadline; -} - -int dns_transmit_get(struct dns_transmit *d,const iopause_fd *x,const struct taia *when) -{ - char udpbuf[MSGSIZE + 1]; - unsigned char ch; - int r; - int fd; - - errno = EIO; - fd = d->s1 - 1; - - if (!x->revents) { - if (taia_less((struct taia *)when,&d->deadline)) return 0; - errno = ETIMEDOUT; - if (d->tcpstate == 0) return nextudp(d); - return nexttcp(d); - } - -/* -have attempted to send UDP query to each server udploop times -have sent query to curserver on UDP socket s -*/ - if (d->tcpstate == 0) { - r = recv(fd,udpbuf,sizeof(udpbuf),0); - if (r <= 0) { - if (errno == ECONNREFUSED) if (d->udploop == 2) return 0; - return nextudp(d); - } - if (r + 1 > sizeof(udpbuf)) return 0; - - if (irrelevant(d,udpbuf,r)) return 0; - if (serverwantstcp(udpbuf,r)) return firsttcp(d); - if (serverfailed(udpbuf,r)) { - if (d->udploop == 2) return 0; - return nextudp(d); - } - socketfree(d); - - d->packetlen = r; - d->packet = alloc(d->packetlen); - if (!d->packet) { dns_transmit_free(d); return DNS_COM; } - byte_copy(d->packet,d->packetlen,udpbuf); - queryfree(d); - return 1; - } - -/* -have sent connection attempt to curserver on TCP socket s -pos not defined -*/ - if (d->tcpstate == 1) { - if (!socket_connected(fd)) return nexttcp(d); - d->pos = 0; - d->tcpstate = 2; - return 0; - } - -/* -have connection to curserver on TCP socket s -have sent pos bytes of query -*/ - if (d->tcpstate == 2) { - r = write(fd,d->query + d->pos,d->querylen - d->pos); - if (r <= 0) return nexttcp(d); - d->pos += r; - if (d->pos == d->querylen) { - struct taia now; - taia_now(&now); - taia_uint(&d->deadline,10); - taia_add(&d->deadline,&d->deadline,&now); - d->tcpstate = 3; - } - return 0; - } - -/* -have sent entire query to curserver on TCP socket s -pos not defined -*/ - if (d->tcpstate == 3) { - r = read(fd,&ch,1); - if (r <= 0) return nexttcp(d); - d->packetlen = ch; - d->tcpstate = 4; - return 0; - } - -/* -have sent entire query to curserver on TCP socket s -pos not defined -have received one byte of packet length into packetlen -*/ - if (d->tcpstate == 4) { - r = read(fd,&ch,1); - if (r <= 0) return nexttcp(d); - d->packetlen <<= 8; - d->packetlen += ch; - d->tcpstate = 5; - d->pos = 0; - d->packet = alloc(d->packetlen); - if (!d->packet) { dns_transmit_free(d); return DNS_COM; } - return 0; - } - -/* -have sent entire query to curserver on TCP socket s -have received entire packet length into packetlen -packet is allocated -have received pos bytes of packet -*/ - if (d->tcpstate == 5) { - r = read(fd,d->packet + d->pos,d->packetlen - d->pos); - if (r <= 0) return nexttcp(d); - d->pos += r; - if (d->pos < d->packetlen) return 0; - - socketfree(d); - if (irrelevant(d,d->packet,d->packetlen)) return nexttcp(d); - if (serverwantstcp(d->packet,d->packetlen)) return nexttcp(d); - if (serverfailed(d->packet,d->packetlen)) return nexttcp(d); - - queryfree(d); - return 1; - } - - return 0; -} diff --git a/dnsstub/dns_txt.c b/dnsstub/dns_txt.c deleted file mode 100644 index 9a1b56a..0000000 --- a/dnsstub/dns_txt.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "stralloc.h" -#include "uint_t.h" -#include "byte.h" -#include "dnsresolv.h" - -int dns_txt_packet(stralloc *out,const char *buf,unsigned int len) -{ - unsigned int pos; - char header[12]; - uint16 numanswers; - uint16 datalen; - char ch; - unsigned int txtlen; - int i; - int ranswers = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - - pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 6,&numanswers); - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos += 4; - - while (numanswers--) { - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 8,&datalen); - if (byte_equal(header,2,DNS_T_TXT)) - if (byte_equal(header + 2,2,DNS_C_IN)) { - if (pos + datalen > len) return DNS_ERR; - txtlen = (unsigned char) buf[pos]; - for (i = 1; i < datalen; ++i) { - ch = buf[pos + i]; - if (i == txtlen + 1) // next label - txtlen += (unsigned char) ch + 1; - else { - if (ch < 32) ch = '?'; - if (ch > 126) ch = '?'; - if (!stralloc_append(out,&ch)) return DNS_MEM; - } - } - } - pos += datalen; - ++ranswers; - if (numanswers) if (!stralloc_append(out,"\n")) return DNS_MEM; - } - - return ranswers; -} - -static char *q = 0; - -int dns_txt(stralloc *out,const stralloc *fqdn) -{ - int rc; - - if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; - if (dns_resolve(q,DNS_T_TXT) < 0) return DNS_ERR; - if ((rc = dns_txt_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - - return rc; -} diff --git a/env.c b/env.c deleted file mode 100644 index 2ecaa83..0000000 --- a/env.c +++ /dev/null @@ -1,136 +0,0 @@ -#include "str.h" -#include "alloc.h" -#include "env.h" - -/** - @file env.c - @author djb - @source ucspi-tcp - @brief setting up environment after fork -*/ - -extern /*@null@*/char *env_get(char *s) -{ - int i; - unsigned int len; - - if (!s) return 0; - len = str_len(s); - for (i = 0; environ[i]; ++i) - if (str_start(environ[i],s) && (environ[i][len] == '=')) - return environ[i] + len + 1; - return 0; -} - -extern char *env_findeq(char *s) -{ - for (; *s; ++s) - if (*s == '=') return s; - return 0; -} - -int env_isinit = 0; /* if env_isinit: */ -static int ea; /* environ is a pointer to ea+1 char*'s. */ -static int en; /* the first en of those are ALLOCATED. environ[en] is 0. */ - -static void env_del(int i) { - alloc_free(environ[i]); - environ[i] = environ[--en]; - environ[en] = 0; -} - -static void env_unsetlen(char *s,int len) -{ - int i; - - for (i = en - 1; i >= 0; --i) - if (!str_diffn(s,environ[i],len)) - if (environ[i][len] == '=') - env_del(i); -} - -int env_unset(char *s) -{ - if (!env_isinit) - if (!env_init()) return 0; - env_unsetlen(s,str_len(s)); - return 1; -} - -int env_set(char *s) { - char *t; - - t = env_findeq(s); - if (t) env_unsetlen(s,t - s); - if (en == ea) { - ea += 30; - if (!alloc_re(&environ,(en + 1) * sizeof(char *),(ea + 1) * sizeof(char *))) - { ea = en; return 0; } - } - environ[en++] = s; - environ[en] = 0; - return 1; -} - -int env_puts(char *s) { - char *u; - - if (!env_isinit) - if (!env_init()) return 0; - u = alloc(str_len(s) + 1); - if (!u) return 0; - str_copy(u,s); - if (!env_set(u)) { alloc_free(u); return 0; } - return 1; -} - -int env_put(char *name,char *value) { - char *ln; - int len; - - if (!env_isinit) - if (!env_init()) return 0; - len = str_len(name); - ln = alloc(len + str_len(value) + 2); - if (!ln) return 0; - str_copy(ln,name); - ln[len] = '='; - str_copy(ln + len + 1,value); - if (!env_set(ln)) { alloc_free(ln); return 0; } - return 1; -} - -int env_init() { - char **newenviron; - int i; - - for (en = 0; environ[en]; ++en) - ; - ea = en + 10; - newenviron = (char **) alloc((ea + 1) * sizeof(char *)); - if (!newenviron) return 0; - - for (en = 0; environ[en]; ++en) { - newenviron[en] = alloc(str_len(environ[en]) + 1); - if (!newenviron[en]) { - for (i = 0; i < en; ++i) alloc_free(newenviron[i]); - alloc_free(newenviron); - return 0; - } - str_copy(newenviron[en],environ[en]); - } - - newenviron[en] = 0; - environ = newenviron; - env_isinit = 1; - return 1; -} - -static char *null = 0; - -void env_clear() { - if (env_isinit) - while (en) env_del(0); - else environ = &null; -} -extern char *env_pick() { return environ[0]; } diff --git a/errstr.c b/errstr.c deleted file mode 100644 index e2290fb..0000000 --- a/errstr.c +++ /dev/null @@ -1,163 +0,0 @@ -#include "error.h" - -/** - @file errstr.c - @author kp - @source qlibs - @brief error output to log for different conditions and OS -*/ - -#define X(e,s) if (code == e) return s; - -extern char *error_str(int); - -char *errstr(int code) -{ - X(0,"") // NOERROR - X(error_intr,"interrupted system call") // EINTR - X(EINTR, "interrupted system call") - X(error_nomem,"out of memory") // ENOMEM - X(ENOMEM, "out of memory") - X(error_noent,"file does not exist") // ENOENT - X(ENOENT, "file does not exist") - X(error_txtbsy,"text busy") // ETXTBSY - X(ETXTBSY, "text busy") - X(error_io,"input/output error") // EIO - X(EIO, "input/output error") - X(error_exist,"file already exists") // EEXISTS - X(EEXIST, "file already exists") - X(error_timeout,"timed out") // ETIMEDOUT - X(ETIMEDOUT, "timed out") - X(error_inprogress,"operation in progress") // EINPROGRESS - X(EINPROGRESS, "operation in progress") - X(error_again,"temporary failure") // EAGAIN - X(EAGAIN, "temporary failure") - X(error_wouldblock,"input/output would block") // EWOULDBLOCK (intern EAGAIN) - X(EWOULDBLOCK, "input/output would block") - X(error_pipe,"broken pipe") // EPIPE - X(EPIPE, "broken pipe") - X(error_perm,"permission denied") // EPERM - X(EPERM, "permission denied") - X(error_acces,"access denied") // EACCES - X(EACCES, "access denied") - - X(ESRCH, "no such process") - -// X(error_nodevice,"device not configured") // ENXIO - X(ENXIO, "device not configured") - - X(E2BIG, "argument list too long") - X(ENOEXEC, "exec format error") - X(EBADF, "file descriptor not open") - X(ECHILD, "no child processes") - X(EDEADLK, "operation would cause deadlock") - X(EFAULT, "bad address") - X(ENOTBLK, "not a block device") - X(EBUSY, "device busy") - X(EXDEV, "cross-device link") - X(ENODEV, "device does not support operation") -// X(error_notdir,"not a directory") // ENOTDIR - X(ENOTDIR, "not a directory") - X(error_isdir,"is a directory") // EISDIR - X(EISDIR, "is a directory") - X(EINVAL, "invalid argument") - X(ENFILE, "system cannot open more files") - X(EMFILE, "process cannot open more files") - X(ENOTTY, "not a tty") - X(EFBIG, "file too big") - X(ENOSPC, "out of disk space") - X(ESPIPE, "unseekable descriptor") -// X(error_rofs,"read-only file system") // EROFS - X(EROFS, "read-only file system") - X(EMLINK, "too many links") - X(EDOM, "input out of range") - X(ERANGE, "output out of range") - X(EALREADY, "operation already in progress") - X(ENOTSOCK, "not a socket") - X(EDESTADDRREQ, "destination address required") - X(EMSGSIZE, "message too long") - X(EPROTOTYPE, "incorrect protocol type") - X(ENOPROTOOPT, "protocol not available") - X(EPROTONOSUPPORT, "protocol not supported") - X(ESOCKTNOSUPPORT, "socket type not supported") - X(EOPNOTSUPP, "operation not supported") - X(EPFNOSUPPORT, "protocol family not supported") - X(EAFNOSUPPORT, "address family not supported") - X(EADDRINUSE, "address already used") - X(EADDRNOTAVAIL, "address not available") - X(ENETDOWN, "network down") - X(ENETUNREACH, "network unreachable") - X(ENETRESET, "network reset") - X(ECONNABORTED, "connection aborted") - X(error_connreset, "connection reset") // ECONNRESET - X(ECONNRESET, "connection reset") - X(ENOBUFS, "out of buffer space") - X(EISCONN, "already connected") - X(ENOTCONN, "not connected") - X(ESHUTDOWN, "socket shut down") - X(ETOOMANYREFS, "too many references") - X(error_connrefused,"connection refused") // ECONNREFUSED - X(ECONNREFUSED, "connection refused") - X(ELOOP, "symbolic link loop") - X(ENAMETOOLONG, "file name too long") - X(EHOSTDOWN, "host down") - X(EHOSTUNREACH, "host unreachable") - X(ENOTEMPTY, "directory not empty") - X(EUSERS, "too many users") - X(EDQUOT, "disk quota exceeded") - X(ESTALE, "stale NFS file handle") - - /* BSD only (all BSD's, NOT on Linux) */ -// X(EPROCLIM, "too many processes") // -L +FB +OB +NB -// X(EBADRPC, "RPC structure is bad") // -L +FB +OB +NB - -// X(ERPCMISMATCH, "RPC version mismatch") // -L +FB +OB +NB -// X(EPROGUNAVAIL, "RPC program unavailable") // -L +FB +OB +NB -// X(EPROGMISMATCH, "program version mismatch") // -L +FB +OB +NB -// X(EPROCUNAVAIL, "bad procedure for program") // -L +FB +OB +NB -// X(EFTYPE, "bad file type") // -L +FB +OB +NB - - X(ENOLCK, "no locks available") - X(ENOSYS, "system call not available") - X(ENOMSG, "no message of desired type") - X(EIDRM, "identifier removed") - -// X(ERREMOTE, "object not local") // -L -FB -OB -NB - X(EREMOTE, "object not local") // Linux: "Object is remote" -// X(EREMOTE, "too many levels of remote in path") - - /* Linux only */ -// X(ENONET, "machine not on network") // +L -FB -OB -NB -// X(EADV, "advertise error") // +L -FB -OB -NB -// X(ESRMNT, "srmount error") // +L -FB -OB -NB -// X(ECOMM, "communication error") // +L -FB -OB -NB -// X(EREMCHG, "remote address changed") // +L -FB -OB -NB - - X(error_proto,"protocol error") // EPROTO - /* EPROTO: see 'error.h' for OpenBSD compat */ - X(EPROTO, "protocol error") // +L +FB -OB +NB - - /* Linux and NetBSD */ -// X(ENOSTR, "not a stream device") // +L -FB -OB +NB -// X(ETIME, "timer expired") // +L -FB -OB +NB -// X(ENOSR, "out of stream resources") // +L -FB -OB +NB - - /* FreeBSD and NetBSD */ -// X(EAUTH, "authentication error") // -L +FB -OB +NB -// X(ENEEDAUTH, "not authenticated") // -L +FB -OB +NB - - /* NOT on OpenBSD */ -// X(EBADMSG, "bad message type") // +L +FB -OB +NB -// X(ENOLINK, "link severed") // +L +FB -OB +NB -// X(EMULTIHOP, "multihop attempted") // +L +FB -OB +NB - - /* Application/DJB specific */ - X(EHARD, " ") - X(ESOFT, " ") - X(USAGE, "usage error") // qmail; explicit - X(SYNTAX, "syntax error") // djbdns, qmail; explicit - X(DROP, "connection dropped") // ucspi-tcp - X(FATAL, "unable to continue") // all - - return "unknown error"; /* worst case */ -} diff --git a/fd.c b/fd.c deleted file mode 100644 index 776575c..0000000 --- a/fd.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include "fd.h" - -/** - @file fd.c - @autor djb - @source qmail - @brief file descriptor manipulation -*/ - -int close(int __fd); /* we won't use unistd.h here */ - -int fd_copy(int to,int from) -{ - if (to == from) return 0; - if (fcntl(from,F_GETFL,0) == -1) return -1; - close(to); - if (fcntl(from,F_DUPFD,to) == -1) return -1; - return 0; -} - -int fd_move(int to,int from) -{ - if (to == from) return 0; - if (fd_copy(to,from) == -1) return -1; - close(from); - return 0; -} - -int fd_coe(int fd) {return fcntl(fd,F_SETFD,1); } diff --git a/fmt.c b/fmt.c deleted file mode 100644 index 52ab5dc..0000000 --- a/fmt.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "fmt.h" - -/** - @file fmt.c - @author djb - @source qmail - @brief formating differnt inputs format for output printing -*/ - -unsigned int fmt_str(register char *s,register char *t) -{ - register unsigned int len; - char ch; - len = 0; - if (s) { while ((ch = t[len])) s[len++] = ch; } - else while (t[len]) len++; - return len; -} - -unsigned int fmt_strn(register char *s,register char *t,register unsigned int n) -{ - register unsigned int len; - char ch; - len = 0; - if (s) { while (n-- && (ch = t[len])) s[len++] = ch; } - else while (n-- && t[len]) len++; - return len; -} - -unsigned int fmt_uint(register char *s,register unsigned int u) -{ - register unsigned long l; l = u; return fmt_ulong(s,l); -} - -unsigned int fmt_uint0(char *s,unsigned int u,unsigned int n) -{ - unsigned int len; - len = fmt_uint(FMT_LEN,u); - while (len < n) { if (s) *s++ = '0'; ++len; } - if (s) fmt_uint(s,u); - return len; -} - -unsigned int fmt_ulong(register char *s,register unsigned long u) -{ - register unsigned int len; register unsigned long q; - len = 1; q = u; - while (q > 9) { ++len; q /= 10; } - if (s) { - s += len; - do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */ - } - return len; -} - -unsigned int fmt_xlong(register char *s,register unsigned long u) -{ - register unsigned int len; register unsigned long q; - len = 1; q = u; - while (q > 15) { ++len; q /= 16; } - if (s) { - s += len; - do { *--s = tohex(u % 16); u /= 16; } while(u); /* handles u == 0 */ - } - return len; -} - -char tohex(char num) { - if (num < 10) - return num + '0'; - else if (num < 16) - return num - 10 + 'a'; - else - return -1; -} - -int fromhex(unsigned char c) { - if (c >= '0' && c <= '9') - return c-'0'; - else if (c >= 'A' && c <= 'F') - return c -'A' + 10; - else if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - return -1; -} diff --git a/getln.c b/getln.c deleted file mode 100644 index f83d3c2..0000000 --- a/getln.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "byte.h" -#include "getln.h" - -/** - @file getln.c - @author djb - @source qmail - @brief evaluting tokenized input arguments -*/ - -int getln(buffer *b,stralloc *sa,int *match,int sep) -{ - char *cont; - unsigned int clen; - - if (sgetln(b,sa,&cont,&clen,sep) == -1) return -1; - if (!clen) { *match = 0; return 0; } - if (!stralloc_catb(sa,cont,clen)) return -1; - *match = 1; - return 0; -} - -int sgetln(buffer *b,stralloc *sa,char **cont,unsigned int *clen,int sep) -{ - register char *x; - register unsigned int i; - int n; - - if (!stralloc_ready(sa,0)) return -1; - sa->len = 0; - - for (;;) { - n = buffer_feed(b); - if (n < 0) return -1; - if (n == 0) { *clen = 0; return 0; } - x = buffer_PEEK(b); - i = byte_chr(x,n,sep); - if (i < n) { buffer_SEEK(b,*clen = i + 1); *cont = x; return 0; } - if (!stralloc_readyplus(sa,n)) return -1; - i = sa->len; - sa->len = i + buffer_get(b,sa->s + i,n); - } -} diff --git a/getoptb.c b/getoptb.c deleted file mode 100644 index edee6b8..0000000 --- a/getoptb.c +++ /dev/null @@ -1,100 +0,0 @@ -#include "buffer.h" -#include "getoptb.h" - -/** - @file getoptb.c - @author djb - @source ucspi-tcp - @brief 'getopt' version w/o stdlib -*/ - -#define optind subgetoptind -#define optproblem subgetoptproblem - -int opterr = 1; -char *optprogname = 0; - -int getopt(int argc,char **argv,char *opts) -{ - int c; - char *s; - - if (!optprogname) { - optprogname = *argv; - if (!optprogname) optprogname = ""; - for (s = optprogname;*s;++s) if (*s == '/') optprogname = s + 1; - } - c = subgetopt(argc,argv,opts); - if (opterr) - if (c == '?') { - char chp[2]; chp[0] = optproblem; chp[1] = '\n'; - buffer_puts(buffer_2,optprogname); - if (argv[optind] && (optind < argc)) - buffer_puts(buffer_2,": illegal option -- "); - else - buffer_puts(buffer_2,": option requires an argument -- "); - buffer_put(buffer_2,chp,2); - buffer_flush(buffer_2); - } - return c; -} - -#define optpos subgetoptpos -#define optarg subgetoptarg -#define optdone subgetoptdone - -int optind = 1; -int optpos = 0; -char *optarg = 0; -int optproblem = 0; -int optdone = SUBGETOPTDONE; - -int subgetopt(int argc,char **argv,char *opts) -{ - int c; - char *s; - - optarg = 0; - if (!argv || (optind >= argc) || !argv[optind]) return optdone; - if (optpos && !argv[optind][optpos]) { - ++optind; - optpos = 0; - if ((optind >= argc) || !argv[optind]) return optdone; - } - if (!optpos) { - if (argv[optind][0] != '-') return optdone; - ++optpos; - c = argv[optind][1]; - if ((c == '-') || (c == 0)) { - if (c) ++optind; - optpos = 0; - return optdone; - } - /* otherwise c is reassigned below */ - } - c = argv[optind][optpos]; - ++optpos; - s = opts; - while (*s) { - if (c == *s) { - if (s[1] == ':') { - optarg = argv[optind] + optpos; - ++optind; - optpos = 0; - if (!*optarg) { - optarg = argv[optind]; - if ((optind >= argc) || !optarg) { /* argument past end */ - optproblem = c; - return '?'; - } - ++optind; - } - } - return c; - } - ++s; - if (*s == ':') ++s; - } - optproblem = c; - return '?'; -} diff --git a/include/alloc.h b/include/alloc.h index 56a4a52..daac8a5 100644 --- a/include/alloc.h +++ b/include/alloc.h @@ -1,9 +1,9 @@ #ifndef ALLOC_H #define ALLOC_H -extern /*@null@*//*@out@*/char *alloc(); -extern void alloc_free(); -extern int alloc_re(); +extern void *alloc(unsigned int); +extern void alloc_free(void *); +extern int alloc_re(void **, unsigned int, unsigned int); /* use these names in the future */ #define qfree alloc_free diff --git a/include/base64.h b/include/base64.h index a9164c0..0f318c4 100644 --- a/include/base64.h +++ b/include/base64.h @@ -1,7 +1,9 @@ #ifndef BASE64_H #define BASE64_H -extern int b64decode(); -extern int b64encode(); +#include "stralloc.h" + +extern int b64decode(const unsigned char *in, int l, stralloc *out); +extern int b64encode(stralloc *in, stralloc *out); #endif diff --git a/include/byte.h b/include/byte.h index f437341..3ce3b31 100644 --- a/include/byte.h +++ b/include/byte.h @@ -2,19 +2,18 @@ #define BYTE_H /** - @file byte.h - @author djb, feh - @source s/qmail - @comment no declaration of argument types; too many compiler errors -*/ + * @file byte.h + * @authors djb, feh, jmh + * @ref s/qmail + */ -extern unsigned int byte_chr(); -extern unsigned int byte_rchr(); -extern void byte_copy(); -extern void byte_copyr(); -extern int byte_diff(); -extern void byte_zero(); -extern void byte_fill(); +extern unsigned int byte_chr(char *, unsigned int, int); +extern unsigned int byte_rchr(char *, unsigned int, int); +extern void byte_copy(void *, unsigned int, const void *); +extern void byte_copyr(void *, unsigned int, const void *); +extern int byte_diff(const void *, unsigned int, const void *); +extern void byte_zero(void *, unsigned int); +extern void byte_fill(void *, unsigned int, int); #define byte_equal(s,n,t) (!byte_diff((s),(n),(t))) diff --git a/include/cdbmake.h b/include/cdbmake.h index 9c20d2d..565e7ef 100644 --- a/include/cdbmake.h +++ b/include/cdbmake.h @@ -8,13 +8,16 @@ #define CDB_HPLIST 1000 -struct cdb_hp { uint32 h; uint32 p; } ; +struct cdb_hp { + uint32 h; + uint32 p; +}; struct cdb_hplist { struct cdb_hp hp[CDB_HPLIST]; struct cdb_hplist *next; int num; -} ; +}; struct cdb_make { char bspace[8192]; @@ -28,7 +31,7 @@ struct cdb_make { buffer b; uint32 pos; int fd; -} ; +}; extern int cdb_make_start(struct cdb_make *,int); extern int cdb_make_addbegin(struct cdb_make *,unsigned int,unsigned int); diff --git a/include/constmap.h b/include/constmap.h index 750702e..26d945d 100644 --- a/include/constmap.h +++ b/include/constmap.h @@ -11,11 +11,11 @@ struct constmap { int *next; char **input; int *inputlen; -} ; +}; int constmap_init(struct constmap *,char *,int,int); int constmap_init_char(struct constmap *,char *,int,int,char); -void constmap_free(); -char *constmap(); +void constmap_free(struct constmap *); +char *constmap(struct constmap *,char *,int); #endif diff --git a/include/exit.h b/include/exit.h index f74b741..e41b993 100644 --- a/include/exit.h +++ b/include/exit.h @@ -2,10 +2,10 @@ #define EXIT_H /** - @file exit.h - @author djb, feh - @source qmail - @brief convenience header + * @file exit.h + * @author djb + * @ref qmail + * @brief convenience header */ extern void _exit(int); diff --git a/include/fifo.h b/include/fifo.h index 3c1bf68..d9a1b95 100644 --- a/include/fifo.h +++ b/include/fifo.h @@ -2,10 +2,10 @@ #define FIFO_H /** - @file fifo.h - @author djb, feh - @source s/qmail -*/ + * @file fifo.h + * @author djb + * @ref s/qmail + */ int fifo_make(char *,int); diff --git a/include/fmt.h b/include/fmt.h index 6e68d60..62eeefb 100644 --- a/include/fmt.h +++ b/include/fmt.h @@ -2,17 +2,17 @@ #define FMT_H /** - @file fmt.h - @author djb, kp, feh - @source qmail - @brief conversion function declarations - */ + * @file fmt.h + * @authors djb, kp, feh + * @ref qmail + * @brief conversion function declarations + */ #define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */ #define FMT_LEN ((char *) 0) /* convenient abbreviation */ -extern unsigned int fmt_str(char *,char *); -extern unsigned int fmt_strn(char *,char *,unsigned int); +extern unsigned int fmt_str(char *,const char *); +extern unsigned int fmt_strn(char *,const char *,unsigned int); extern unsigned int fmt_uint(char *,unsigned int); extern unsigned int fmt_uint0(char *,unsigned int,unsigned int); extern unsigned int fmt_ulong(char *,unsigned long); diff --git a/include/genalloc.h b/include/genalloc.h index ee489af..aaa17f3 100644 --- a/include/genalloc.h +++ b/include/genalloc.h @@ -48,7 +48,7 @@ int ta_ready(x,n) register ta *x; register unsigned int n; \ i = x->a; \ if (n > i) { \ x->a = base + n + (n >> 3); \ - if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + if (alloc_re((void **)&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ x->a = i; return 0; } \ return 1; } \ x->len = 0; \ @@ -61,7 +61,7 @@ int ta_rplus(x,n) register ta *x; register unsigned int n; \ i = x->a; n += x->len; \ if (n > i) { \ x->a = base + n + (n >> 3); \ - if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + if (alloc_re((void **)&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ x->a = i; return 0; } \ return 1; } \ x->len = 0; \ diff --git a/include/getoptb.h b/include/getoptb.h index 0338a15..33e7cc4 100644 --- a/include/getoptb.h +++ b/include/getoptb.h @@ -2,6 +2,8 @@ #define BGETOPT_H /* + * Revision 20240731, Erwin Hoffmann + * - added getoptb() prototype * Revision 20160714, Kai Peter * - consolidated 'sgetopt.h' and 'subgetopt.h' into '(b)getopt.h' */ @@ -15,6 +17,8 @@ #define SUBGETOPTDONE -1 +extern int getoptb(int,char **,char *); + extern int subgetopt(int,char **,char *); extern char *subgetoptarg; extern int subgetoptind; diff --git a/include/lock.h b/include/lock.h index 74df4c9..71c01fa 100644 --- a/include/lock.h +++ b/include/lock.h @@ -2,10 +2,10 @@ #define LOCK_H /** - @file lock.h - @author djb, feh - @source s/qmail -*/ + * @file lock.h + * @author djb + * @ref s/qmail + */ int lock_ex(int); int lock_un(int); diff --git a/include/ndelay.h b/include/ndelay.h index 7a03a8d..4ef04c1 100644 --- a/include/ndelay.h +++ b/include/ndelay.h @@ -2,10 +2,10 @@ #define NDELAY_H /** - @brief ndelay.h - @author djb, feh - @source s/qmail -*/ + * @file ndelay.h + * @author djb + * @ref s/qmail + */ int ndelay_on(int); int ndelay_off(int); diff --git a/include/open.h b/include/open.h index 428ebfb..2629a4d 100644 --- a/include/open.h +++ b/include/open.h @@ -2,10 +2,10 @@ #define OPEN_H /** - @file open.h - @author djb, feh - @source s/qmail -*/ + * @file open.h + * @authors djb, feh + * @ref s/qmail + */ int open_read(const char *); int open_excl(const char *); diff --git a/include/select.h b/include/select.h index 646dd50..b2fe69e 100644 --- a/include/select.h +++ b/include/select.h @@ -8,6 +8,6 @@ #include #endif -extern int select(); +extern int select(int,fd_set *,fd_set *,fd_set *,struct timeval *); #endif diff --git a/include/sig.h b/include/sig.h index 3efdd32..b4879b8 100644 --- a/include/sig.h +++ b/include/sig.h @@ -2,6 +2,7 @@ #define SIG_H /* + * Revision 20240720, Erwin Hoffmann, jmh * Revision 20160714, Kai Peter * - updated some declarations no new(er) one's from ucspi-tcp-0.88 */ @@ -14,10 +15,10 @@ extern int sig_hangup; extern int sig_pipe; extern int sig_term; -extern void (*sig_defaulthandler)(); -extern void (*sig_ignorehandler)(); +extern void (*sig_defaulthandler)(int); +extern void (*sig_ignorehandler)(int); -extern void sig_catch(int,void (*)()); +extern void sig_catch(int,void (*)(int)); #define sig_ignore(s) (sig_catch((s),sig_ignorehandler)) #define sig_uncatch(s) (sig_catch((s),sig_defaulthandler)) @@ -29,35 +30,35 @@ extern void sig_pause(void); extern void sig_dfl(int); /* declaration of (net)qmail package (untouched) */ -extern void sig_miscignore(); -extern void sig_bugcatch(); - -extern void sig_pipeignore(); -extern void sig_pipedefault(); - -extern void sig_contblock(); -extern void sig_contunblock(); -extern void sig_contcatch(); -extern void sig_contdefault(); - -extern void sig_termblock(); -extern void sig_termunblock(); -extern void sig_termcatch(); -extern void sig_termdefault(); - -extern void sig_alarmblock(); -extern void sig_alarmunblock(); -extern void sig_alarmcatch(); -extern void sig_alarmdefault(); - -extern void sig_childblock(); -extern void sig_childunblock(); -extern void sig_childcatch(); -extern void sig_childdefault(); - -extern void sig_hangupblock(); -extern void sig_hangupunblock(); -extern void sig_hangupcatch(); -extern void sig_hangupdefault(); +extern void sig_miscignore(void); +extern void sig_bugcatch(void (*)(int)); + +extern void sig_pipeignore(void); +extern void sig_pipedefault(void); + +extern void sig_contblock(void); +extern void sig_contunblock(void); +extern void sig_contcatch(void (*)(int)); +extern void sig_contdefault(void); + +extern void sig_termblock(void); +extern void sig_termunblock(void); +extern void sig_termcatch(void (*)(int)); +extern void sig_termdefault(void); + +extern void sig_alarmblock(void); +extern void sig_alarmunblock(void); +extern void sig_alarmcatch(void (*)(int)); +extern void sig_alarmdefault(void); + +extern void sig_childblock(void); +extern void sig_childunblock(void); +extern void sig_childcatch(void (*)(int)); +extern void sig_childdefault(void); + +extern void sig_hangupblock(void); +extern void sig_hangupunblock(void); +extern void sig_hangupcatch(void (*)(int)); +extern void sig_hangupdefault(void); #endif diff --git a/include/str.h b/include/str.h index fe36d0b..4e3fc49 100644 --- a/include/str.h +++ b/include/str.h @@ -12,8 +12,8 @@ extern unsigned int str_copy(char *,const char *); extern unsigned int str_copyb(char *,const char *,unsigned int); extern int str_diff(const char *,const char *); extern int str_diffn(const char *,const char *,unsigned int); -//extern unsigned int str_len(char *); // --> this produces lot of warnings !!! -extern unsigned int str_len(); +extern unsigned int str_len(const char *); // --> this produces lot of warnings !!! +//extern unsigned int str_len(); extern unsigned int str_chr(const char *,int); extern unsigned int str_rchr(const char *,int); extern int str_start(const char *,const char *); diff --git a/include/uint_t.h b/include/uint_t.h index 84eb06e..aec9ed5 100644 --- a/include/uint_t.h +++ b/include/uint_t.h @@ -1,12 +1,12 @@ #include /** - @file uint_t.h - @author djb, kp, feh - @source qmail, djbdns6 - @brief additional types and pack routines - @brief define basic integer types and size through -*/ + * @file uint_t.h + * @authors djb, kp, feh + * @ref qmail, djbdns6 + * @brief additional types and pack routines + * @brief define basic integer types and size through + */ #ifndef UINT8_H #define UINT8_H @@ -17,6 +17,10 @@ typedef uint8_t uint8; typedef unsigned char uint8; #endif +extern void uint8_pack(char *,uint8); +extern void uint8_pack_big(char *,uint8); +extern void uint8_unpack(char *,uint8 *); +extern void uint8_unpack_big(char *,uint8 *); #endif #ifndef UINT16_H @@ -24,10 +28,10 @@ typedef unsigned char uint8; typedef uint16_t uint16; -extern void uint16_pack(char *,uint16); -extern void uint16_pack_big(char *,uint16); -extern void uint16_unpack(char *,uint16 *); -extern void uint16_unpack_big(char *,uint16 *); +extern void uint16_pack(char [16],uint16); +extern void uint16_pack_big(char [16],uint16); +extern void uint16_unpack(char [16],uint16 *); +extern void uint16_unpack_big(char [16],uint16 *); #endif #ifndef UINT32_H diff --git a/include/wait.h b/include/wait.h index f7cfc60..846b838 100644 --- a/include/wait.h +++ b/include/wait.h @@ -2,10 +2,10 @@ #define WAIT_H /** - @file wait.h - @author djb - @source s/qmail -*/ + * @file wait.h + * @author djb + * @ref s/qmail + */ int wait_pid(int *,int); int wait_nohang(int *); diff --git a/install b/install index ef58eaa..5401000 100755 --- a/install +++ b/install @@ -1,9 +1,11 @@ #!/bin/sh -. ./conf-build +# We are in ./src: + +. ../conf-build install_libs() { cp *.a $OFILES "$LIBDIR" ; } -install_hdrs() { cp include/*.h "$HDRDIR" ; } +install_hdrs() { cp ../include/*.h "$HDRDIR" ; } echo -n "Installing qlibs ..." mkdir -p "$LIBDIR" "$HDRDIR" 2>/dev/null diff --git a/iopause.c b/iopause.c deleted file mode 100644 index 94a6fea..0000000 --- a/iopause.c +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include "taia.h" -#include "select.h" -#include "iopause.h" - -/** - @file iopause.c - @author djb - @source qmail - @brief stateful reading from net - @return > 0 if successful -*/ - -int iopause(iopause_fd *x,unsigned int len,struct taia *deadline,struct taia *stamp) -{ - struct taia t; - int millisecs; - double d; - int i, r; - - if (taia_less(deadline,stamp)) - millisecs = 0; - else { - t = *stamp; - taia_sub(&t,deadline,&t); - d = taia_approx(&t); - if (d > 1000.0) d = 1000.0; - millisecs = d * 1000.0 + 20.0; - if (millisecs < 0) millisecs = 20.0; - } - - for (i = 0; i < len; ++i) - x[i].revents = 0; - -#ifdef IOPAUSE_POLL - r = poll(x,len,millisecs); - - /* XXX: some kernels apparently need x[0] even if len is 0 */ - /* XXX: how to handle EAGAIN? are kernels really this dumb? */ - /* XXX: how to handle EINVAL? when exactly can this happen? */ - -#else - struct timeval tv; - fd_set rfds; - fd_set wfds; - int nfds; - int fd; - - FD_ZERO(&rfds); - FD_ZERO(&wfds); - - nfds = 1; - for (i = 0; i < len; ++i) { - fd = x[i].fd; - if (fd < 0) continue; - if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/ - - if (fd >= nfds) nfds = fd + 1; - if (x[i].events & IOPAUSE_READ) FD_SET(fd,&rfds); - if (x[i].events & IOPAUSE_WRITE) FD_SET(fd,&wfds); - } - - tv.tv_sec = millisecs / 1000; - tv.tv_usec = 1000 * (millisecs % 1000); - - r = select(nfds,&rfds,&wfds,(fd_set *) 0,&tv); - if (r <= 0) return r; - - /* XXX: for EBADF, could seek out and destroy the bad descriptor */ - - for (i = 0; i < len; ++i) { - fd = x[i].fd; - if (fd < 0) continue; - if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/ - - if (x[i].events & IOPAUSE_READ) - if (FD_ISSET(fd,&rfds)) x[i].revents |= IOPAUSE_READ; - if (x[i].events & IOPAUSE_WRITE) - if (FD_ISSET(fd,&wfds)) x[i].revents |= IOPAUSE_WRITE; - } - -#endif - return r; -} diff --git a/ip4.c b/ip4.c deleted file mode 100644 index e77cfb6..0000000 --- a/ip4.c +++ /dev/null @@ -1,166 +0,0 @@ -#include "fmt.h" -#include "scan.h" -#include "str.h" -#include "ip.h" - -/** - @file ip4.c - @author djb, fefe, feh, kp - @source ucspi-tcp, ucspi-tcp6 - @brief handling of IPv4 addresses -*/ - -/** - @brief ip4_fmt - converts IPv4 address to dotted decimal string format - @param input: IPv4 char array - output: IPv4 address string - @return int length of address (ok > 0) - */ - -unsigned int ip4_fmt(char *s,char ip[4]) -{ - unsigned int len; - unsigned int i; - - len = 0; - i = fmt_ulong(s,(unsigned long) (unsigned char) ip[0]); len += i; if (s) s += i; - if (s) { *s++ = '.'; } ++len; - i = fmt_ulong(s,(unsigned long) (unsigned char) ip[1]); len += i; if (s) s += i; - if (s) { *s++ = '.'; } ++len; - i = fmt_ulong(s,(unsigned long) (unsigned char) ip[2]); len += i; if (s) s += i; - if (s) { *s++ = '.'; } ++len; - i = fmt_ulong(s,(unsigned long) (unsigned char) ip[3]); len += i; if (s) s += i; - return len; -} - -/** - @brief ia4_fmt - converts IPv4 address into DNS inverse nibble format - @param input: IPv4 char array - output: IPv4 address string - @return int length of address (ok > 0) - */ - -unsigned int ia4_fmt(char *s,char ip[4]) -{ - unsigned int i; - unsigned int len; - - len = 0; - i = fmt_ulong(s,(unsigned long) ip[3]); len += i; if (s) s += i; - i = fmt_str(s,"."); len += i; if (s) s += i; - i = fmt_ulong(s,(unsigned long) ip[2]); len += i; if (s) s += i; - i = fmt_str(s,"."); len += i; if (s) s += i; - i = fmt_ulong(s,(unsigned long) ip[1]); len += i; if (s) s += i; - i = fmt_str(s,"."); len += i; if (s) s += i; - i = fmt_ulong(s,(unsigned long) ip[0]); len += i; if (s) s += i; - i = fmt_str(s,".in-addr.arpa."); len += i; if (s) s += i; - return len; -} - -/** - @brief ip4_scan - parse IPv4 address string and convert to IP address array - @param input: IPv4 address string - output: IPv4 char array - @return int length of ip_address (ok > 0) - */ - -unsigned int ip4_scan(const char *s,char ip[4]) -{ - unsigned int i; - unsigned int len; - unsigned long u; - - byte_zero(ip,4); - len = 0; - i = scan_ulong((char *)s,&u); if (!i) { return 0; } ip[0] = u; s += i; len += i; - if (*s != '.') { return 0; } ++s; ++len; - i = scan_ulong((char *)s,&u); if (!i) { return 0; } ip[1] = u; s += i; len += i; - if (*s != '.') { return 0; } ++s; ++len; - i = scan_ulong((char *)s,&u); if (!i) { return 0; } ip[2] = u; s += i; len += i; - if (*s != '.') { return 0; } ++s; ++len; - i = scan_ulong((char *)s,&u); if (!i) { return 0; } ip[3] = u; s += i; len += i; - return len; -} - -/** - @brief ip4_scanbracket - parse IPv4 address string enclosed in brackets and convert to IP address array - @param input: IPv4 char array - output: IPv4 char array - @return int length of ip_address (ok > 0) - */ - -unsigned int ip4_scanbracket(const char *s,char ip[4]) -{ - unsigned int len; - - if (*s != '[') return 0; - len = ip4_scan(s + 1,ip); - if (!len) return 0; - if (s[len + 1] != ']') return 0; - return len + 2; -} - -/** - @brief ip4_cidr - parse IPv4 address string - concatinated with the prefix length: 192.168.1/24 - @param input: IPv6 char array - output: IPv6 char array, long plen - @return int length of ip6_address/ip - */ - -unsigned int ip4_cidr(char *s,char ip[4],unsigned long *plen) -{ - unsigned int j = 0; - *plen = 32UL; - - j = str_chr(s,'/'); - if (s[j] == '/') { - s[j] = 0; - j = scan_ulong(s + j + 1,plen); - } - return ip4_scan((const char *)s,ip); -} - -/** - @brief ip4_bytestring - parse IPv4 address and represent as char string with length prefix - @param input: IPv4 char array, prefix length - output: pointer to stralloc bytestring - @return n: number of bytes, if ok; -1: memory shortage; -2: input error - */ - -unsigned int ip4_bytestring(stralloc *ipstring,char ip[4],int prefix) -{ - int i, j, n = 0; - unsigned char number; - - if (!stralloc_readyplus(ipstring,32)) return -1; - if (!stralloc_copys(ipstring,"")) return -1; - - for (i = 0; i < 4; i++) { - number = (unsigned char) ip[i]; - if (number > 255) return -2; - - for (j = 7; j >= 0; j--) { - if (number & (1 << j)) { - n++; - if (!stralloc_cats(ipstring,"1")) return -1; - } else { - n++; - if (!stralloc_cats(ipstring,"0")) return -1; - } - prefix--; - if (!prefix) goto DONE; - } - } - -DONE: - if (!stralloc_0(ipstring)) return 1; - - return n; -} diff --git a/ip6.c b/ip6.c deleted file mode 100644 index cf8d85b..0000000 --- a/ip6.c +++ /dev/null @@ -1,360 +0,0 @@ -#include "fmt.h" -#include "byte.h" -#include "scan.h" -#include "ip.h" -#include "str.h" - -/** - @file ip6.c - @author djb, fefe, feh - @source ucspi-tcp, ucspi-tcp6 - @brief handling of IPv6 addresses -*/ - -/*** - @brief ip6_fmt - convert IPv6 address to compactified IPv6 address string - @param input: IPv6 char array - output: pointer to IPv6 address string - @return int length of address (ok > 0) - */ - -unsigned int ip6_fmt(char *s,char ip[16]) -{ - unsigned int len; - unsigned int i; - unsigned int temp, temp0; - unsigned int compressing; - unsigned int compressed; - int j; - - len = 0; - compressing = 0; - compressed = 0; - - for (j = 0; j < 16; j += 2) { - if (j == 12 && ip6_isv4mapped(ip)) { - len += ip4_fmt(s,ip+12); - break; - } - - temp = ((unsigned long) (unsigned char) ip[j] << 8) + - (unsigned long) (unsigned char) ip[j+1]; - - temp0 = 0; - if (!compressing && j < 16) - temp0 = ((unsigned long) (unsigned char) ip[j+2] << 8) + - (unsigned long) (unsigned char) ip[j+3]; - - if (temp == 0 && temp0 == 0 && !compressed) { - if (!compressing) { - compressing = 1; - if (j == 0) { - if (s) *s++ = ':'; - ++len; - } - } - } else { - if (compressing) { - compressing = 0; - ++compressed; - if (s) *s++ = ':'; - ++len; - } - i = fmt_xlong(s,temp); - len += i; - if (s) s += i; - if (j < 14) { - if (s) *s++ = ':'; - ++len; - } - } - } - if (compressing) { *s++ = ':'; ++len; } - - return len; -} - -/*** - @brief ip6_fmt_flat - convert IPv6 address to IPv6 address string - @param input: IPv6 char array - output: pointer to IPv6 address string - @return int length of address (ok > 0) - */ - -unsigned int ip6_fmt_flat(char *s,char ip[16]) -{ - int i; - for (i = 0; i < 16; i++) { - *s++ = tohex((unsigned char)ip[i] >> 4); - *s++ = tohex((unsigned char)ip[i] & 15); - } - return 32; -} - -/*** - @brief ia6_fmt - convert IPv6 address to inverse DNS nibble format - 1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.arpa - @param input: IPv6 char array - output: pointer to IPv6 address string - @return int length of address - */ - -unsigned int ia6_fmt(char *s,char ip[16]) -{ - unsigned int i; - unsigned int len; - int j; - - static char data[] = "0123456789abcdef"; - len = 0; - - for (j = 15; j >= 0; j--) { - i = fmt_str(s,&data[ip[j] & 0x0f]); len += i; if (s) s += i; - i = fmt_str(s,"."); len += i; if (s) s += i; - i = fmt_str(s,&data[ip[j] >> 4 & 0x0f]); len += i; if (s) s += i; - i = fmt_str(s,"."); len += i; if (s) s += i; - } - i = fmt_str(s,"ip6.arpa."); len += i; if (s) s += i; - - return len; -} - - -/*** - @brief ip6_scan_flat - convert IPv6 address string to IPv6 address array - @param input: pointer to IPv6 address string - output: IPv6 char array - @return int length of address (ok > 0) - */ - -unsigned int ip6_scan_flat(const char *s,char ip[16]) -{ - int i, tmp; - - for (i = 0; i < 16; i++) { - tmp = fromhex(*s++); - if (tmp < 0) return 0; - ip[i] = tmp << 4; - tmp = fromhex(*s++); - if (tmp < 0) return 0; - ip[i] += tmp; - } - return 32; -} - -/*** - @brief ip6_scan - parse compactified IPv6 address string and convert to IPv6 address array - @param input: pointer to IPv6 address string - output: IPv6 char array - @return int length of ip6_address/ip - */ - -unsigned int ip6_scan(const char *s,char ip[16]) -{ - unsigned int i, j; - unsigned int len = 0; - unsigned long u; - - char suffix[16]; - int prefixlen = 0; - int suffixlen = 0; - - /* Always return IPv4 as IPv4-mapped IPv6 address */ - if ((i = ip4_scan(s,ip+12))) { - for (len = 0; len < 12; ++len) - ip[len] = V4mappedprefix[len]; - return i; - if (byte_equal(ip+12,4,V4localnet)) { - byte_copy(ip,16,V6localnet); - return 16; - } - } - byte_zero(ip,16); - - for (;;) { - if (*s == ':') { - len++; - if (s[1] == ':') { /* Found "::", skip to part 2 */ - s += 2; len++; - break; - } - s++; - } - i = scan_xlong((char *)s,&u); - if (!i) return 0; - - if (prefixlen == 12 && s[i] == '.') { - /* the last 4 bytes may be written as IPv4 address */ - i = ip4_scan(s,ip+12); - if (i) - return i+len; - else - return 0; - } - - ip[prefixlen++] = (u >> 8); - ip[prefixlen++] = (u & 255); - s += i; len += i; - if (prefixlen == 16) return len; - } - -/* part 2, after "::" */ - for (;;) { - if (*s == ':') { - if (suffixlen == 0) break; - s++; - len++; - } else if (suffixlen != 0) break; - - i = scan_xlong((char *)s,&u); - if (!i) { - len--; - break; - } - - if (suffixlen + prefixlen <= 12 && s[i] == '.') { - j = ip4_scan(s,suffix+suffixlen); - if (j) { - suffixlen += 4; - len += j; - break; - } else - prefixlen = 12 - suffixlen; /* make end-of-loop test true */ - } - - suffix[suffixlen++] = (u >> 8); - suffix[suffixlen++] = (u & 255); - s += i; len += i; - if (prefixlen + suffixlen == 16) break; - } - - for (i = 0; i < suffixlen; i++) - ip[16 - suffixlen + i] = suffix[i]; - - return len; -} - -/*** - @brief ip6_scanbracket - parse IPv6 string address enclosed in brackets - @param input: pointer to IPv6 address string - output: IPv6 char array - @return int length of ip_address (ok > 0) - */ - -unsigned int ip6_scanbracket(const char *s,char ip[16]) -{ - unsigned int len; - - if (*s != '[') return 0; - len = ip6_scan(s + 1,ip); - if (!len) return 0; - if (s[len + 1] != ']') return 0; - return len + 2; -} - -/** - @brief ip6_ifscan - parse compactified IPv6 address string - concatinated with the interface name: fe80::1%eth0 - @param input: pointer to IPv6 address string - output: IPv6 char array, stralloc interface_name - @return int length of ip6_address/ip - */ - -unsigned int ip6_ifscan(char *s,char ip[16],stralloc *ifname) -{ - int i; - int j = 0; - int k = 0; - if (!stralloc_copys(ifname,"0")) return 0; - - if ((j = str_chr(s,'%'))) { - if ((i = str_chr(s+j+1,' '))) k = i; - else if ((i = str_chr(s+j+1,'\n'))) k = i; - else if ((i = str_chr(s+j+1,'\t'))) k = i; - if (k) s[j+k+1] = '\0'; /* input might contain trailing chars */ - if (!stralloc_copys(ifname,s+j+1)) return 0; - s[j] = 0; - } - if (!stralloc_0(ifname)) return 0; - - return ip6_scan(s,ip); -} - -/** - @brief ip6_cidr - parse compactified IPv6 address string - concatinated with the prefix length: fe80::1/64 - @param input: pointer to IPv6 address string - output: IPv6 char array, long plen - @return int length of ip6_address/ip - */ - -unsigned int ip6_cidr(char *s,char ip[16],unsigned long *plen) -{ - unsigned int j = 0; - *plen = 128UL; - - j = str_chr(s,'/'); - if (s[j] == '/') { - s[j] = 0; - j = scan_ulong(s+j+1,plen); - } - return ip6_scan((const char *)s,ip); -} - -/** - @brief ip6_bytestring - parse IPv6 address and represent as char string with length prefix - @param input: IPv6 char array, prefix length - output: pointer to stralloc bit string; - @return n: number of bytes, if ok; -1: memory shortage - */ - -unsigned int ip6_bytestring(stralloc *ipstring,char ip[16],int prefix) -{ - int i, j, n = 0; - unsigned char lowbyte, highbyte; - - if (!stralloc_readyplus(ipstring,128)) return -1; - if (!stralloc_copys(ipstring,"")) return -1; - - for (i = 0; i < 16; i++) { - lowbyte = (unsigned char) (ip[i]) & 0x0f; - highbyte = (unsigned char) (ip[i] >> 4) & 0x0f; - - for (j = 3; j >= 0; j--) { - if (highbyte & (1 << j)) { - n++; - if (!stralloc_cats(ipstring,"1")) return -1; - } else { - n++; - if (!stralloc_cats(ipstring,"0")) return -1; - } - prefix--; - if (!prefix) goto DONE; - } - for (j = 3; j >= 0; j--) { - if (lowbyte & (1 << j)) { - n++; - if (!stralloc_cats(ipstring,"1")) return -1; - } else { - n++; - if (!stralloc_cats(ipstring,"0")) return -1; - } - prefix--; - if (!prefix) goto DONE; - } - } - -DONE: - if (!stralloc_0(ipstring)) return -1; - - return n; -} diff --git a/lock.c b/lock.c deleted file mode 100644 index 4ac6b40..0000000 --- a/lock.c +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include -#include -#include "lock.h" - -/** - @file lock.c - @author djb - @source qmail - @brief locking of resources -*/ - -#ifdef HASFLOCK -int lock_ex(int fd) { return flock(fd,LOCK_EX); } -int lock_exnb(int fd) { return flock(fd,LOCK_EX | LOCK_NB); } -int lock_un(int fd) { return flock(fd,LOCK_UN); } -#else -int lock_ex(int fd) { return lockf(fd,1,0); } -int lock_exnb(int fd) { return lockf(fd,2,0); } -int lock_un(int fd) { return lockf(fd,0,0); } -#endif diff --git a/logmsg.c b/logmsg.c deleted file mode 100644 index 3f079f4..0000000 --- a/logmsg.c +++ /dev/null @@ -1,97 +0,0 @@ -#include -#include -#include -#include "buffer.h" -#include "fmt.h" -#include "str.h" -#include "stralloc.h" -#include "logmsg.h" - -/** - @file logmsg.c - @author kp, feh - @source qlibs - @brief unified system and error message handling -*/ - -#define WHO "logmsg" - -char *build_log_msg(const char *x[]) -{ - stralloc sa = {0}; - stralloc_copys(&sa,""); - - while(*x) { if (!stralloc_cats(&sa,*x++)) err_sys(WHO,errno); } /* concatenate *x */ - - if (!stralloc_0(&sa)) err_sys(WHO,errno); - return(sa.s); -} - -void logmsg(const char *who,int ecode,unsigned int class,const char *msg) -{ - char strnum[FMT_ULONG]; - char *codestr = ""; - char *classstr = ""; - char *errmsg = ""; - - errno = 0; /* re-initialize errno, value is in 'code' now */ - -/* Part 1: obtain the (error) code -- perhaps received from OS */ - - if (ecode != 0) { - codestr = ""; - if (ecode < 0) { // check for negative error codes - ecode = (ecode^-1) + 1; - codestr = "-"; - } - strnum[fmt_ulong(strnum,ecode)] = 0; /* format for output */ - char *temp = strnum; - codestr = str_cat(codestr,temp); - } - -/* Part 2: behavioral on error */ - - switch (class) { - case ERROR: classstr = "error: "; break; // info + exit - case FATAL: classstr = "fatal: "; break; // info + exit - case DROP: classstr = "drop: "; break; // info + next call/iteration - case ALERT: classstr = "alert: "; break; // info + next statement - case WARN: classstr = "warning: "; break; // info + next statement - case INFO: classstr = "info: "; break; // info + continue - case SYNTAX: classstr = "syntax: "; break; // info + exit - case USAGE: classstr = "usage: "; break; // info + exit - case TEMP: classstr = "temp: "; break; // info + exit - case CAT: classstr = ""; break; // info w/o \n - default: - class = LOG; classstr = ""; break; // custom info + continue - } - -/* Part 3: get system error message */ - - if (class == FATAL || class == DROP) - errmsg = error_str(errno); - -/* Part 4: construct log message: Source: Class (Ecode) Message: Errmsg */ - - buffer_puts(buffer_2,who); - buffer_puts(buffer_2,": "); - buffer_puts(buffer_2,classstr); - if (class == FATAL || class == DROP || class == ERROR) { - buffer_puts(buffer_2,"("); - buffer_puts(buffer_2,codestr); - buffer_puts(buffer_2,") "); - } - buffer_puts(buffer_2,msg); - if (errno) { - buffer_puts(buffer_2,": "); - buffer_puts(buffer_2,errmsg); - } - if (class != CAT) { - buffer_puts(buffer_2,"\n"); - buffer_flush(buffer_2); - } - - if (class == USAGE) _exit(USAGE); - if (class == SYNTAX) _exit(SYNTAX); - if (class == FATAL || class == DROP || class == ERROR) _exit(ecode); -} diff --git a/man/buffer.3 b/man/buffer.3 index 2d4d0d2..331c32e 100644 --- a/man/buffer.3 +++ b/man/buffer.3 @@ -31,9 +31,9 @@ int \fBbuffer_flush\fP(buffer *\fIb\fR); .br int \fBbuffer_copy\fP(buffer *\fIbo\fR,buffer *\fIbi\fR); -int \fBbuffer_unixread\fP(int \fIfd\fR,char *\fIbuf\fR,size_t \fIlen\fR); +ssize_t \fBbuffer_unixread\fP(int \fIfd\fR,char *\fIbuf\fR,size_t \fIlen\fR); .br -int \fBbuffer_unixwrite\fP(int \fIfd\fR,char *\fIbuf\fR,size_t \fIlen\fR); +ssize_t \fBbuffer_unixwrite\fP(int \fIfd\fR,char *\fIbuf\fR,size_t \fIlen\fR); .SH DESCRIPTION .B buffer.h describes a generic buffer interface that can be used for @@ -111,13 +111,17 @@ fills all available space with data before calling copies one buffer to other one. The output buffer needs to have at least the preallocated size of the input buffer. + .B buffer_unixread and .B buffer_unixwrite perform the same operation like standard Unix .B read or -.BR write. +.B write +however provide the function return signature +.IR ssize_t +required to be used with the buffer interface. .SH MACROS Apart from this basic usage, some helpful macro definitions are provided: diff --git a/man/getln.3 b/man/getln.3 index bb4ae7c..01f8b89 100644 --- a/man/getln.3 +++ b/man/getln.3 @@ -4,11 +4,11 @@ getln \ - read one line of data .SH SYNTAX .B #include \(dqgetln.h\(dq -int \fBgetln\fP(&buffer_0,&sa,&match,sep); +int \fBgetln\fP(&buf,&sa,&match,sep); .br -int \fBgetln2\fP(&buffer_0,&sa,&cont,&clen,sep); +int \fBgetln2\fP(&buf,&sa,&cont,&clen,sep); -buffer \fIbuffer_0\fR; +buffer \fIbuf\fR; .br stralloc \fIsa\fR; .br @@ -22,7 +22,7 @@ unsigned int \fIclen\fR; .SH DESCRIPTION .B getln reads a line of characters, terminated by a sep character, from -.IR buffer_0 . +.IR buf . It returns the line in .I sa and sets match to @@ -39,18 +39,18 @@ and sets match to .B getln2 reads a line of characters, terminated by a .I sep -character, from -.IR buffer_0 . +character from +.IR buf . The line is returned in two pieces. The first piece is stored in .IR sa . The second piece is .IR cont , a pointer to .I clen -characters inside the -.I buffer_0 -buffer. The second piece must be copied somewhere else before -.I ss +characters inside +.IR buf . +The second piece must be copied somewhere else before +.I sa is used again. If .B getln2 @@ -64,12 +64,19 @@ and does not set .IR cont . It puts the partial line into .IR sa. +.SH "BUFFER" +.I buf +can be a pre-allocated buffer like +.I buffer_0 +reading from +.I STDIN +or any other explicitly generated buffer on a given file descriptor. .SH "RETURN CODES" .B getln normally returns .IR 0 . If it runs out of memory, or encounters an error from -.IR ss , +.IR sa , it returns .IR -1 , setting @@ -80,17 +87,12 @@ appropriately. normally returns .IR 0 . If it runs out of memory, or encounters an error from -.IR ss , +.IR sa , it returns .IR -1 , setting .I errno appropriately. -.SH NOTE -The input buffer -.I buffer_0 -is already pre-allocated. -It can be used without initialization as synonym for STDIN. .SH CREDITS The .B getln @@ -99,4 +101,4 @@ and man page were taken from Bruce Guenther and originally published by Dan Bernstein for qmail-1.03. .SH SEE ALSO -stralloc(3) +stralloc(3), buffer(3). diff --git a/man/getoptb.3 b/man/getoptb.3 index f3e329b..1c5522a 100644 --- a/man/getoptb.3 +++ b/man/getoptb.3 @@ -5,7 +5,7 @@ getoptb \- get option character from command line .B #include \(dqgetoptb.h\(dq .SH DESCRIPTION Qlib's -.B getopt +.B getoptb is a replacement for the standard Unix .B getopt library, based on diff --git a/ndelay.c b/ndelay.c deleted file mode 100644 index f4b5eb8..0000000 --- a/ndelay.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include "ndelay.h" - -/** - @file ndelay.c - @author djb - @soure qmail - @brief delaying of IO operations -*/ - -#ifndef O_NONBLOCK -#define O_NONBLOCK O_NDELAY -#endif - -int ndelay_on(int fd) -{ - return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK); -} - -int ndelay_off(int fd) -{ - return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK); -} diff --git a/open.c b/open.c deleted file mode 100644 index c430698..0000000 --- a/open.c +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include "open.h" - -/** - @file open.c - @author djb - @source qmail - @brief open a file -*/ - -int open_append(const char *fn) -{ return open(fn,O_WRONLY | O_NDELAY | O_APPEND | O_CREAT,0600); } - -int open_excl(const char *fn) -{ return open(fn,O_WRONLY | O_EXCL | O_CREAT,0644); } - -int open_read(const char *fn) -{ return open(fn,O_RDONLY | O_NDELAY); } - -int open_trunc(const char *fn) -{ return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); } - -int open_write(const char *fn) -{ return open(fn,O_WRONLY | O_NDELAY); } diff --git a/pathexec.c b/pathexec.c deleted file mode 100644 index 2c1e7d1..0000000 --- a/pathexec.c +++ /dev/null @@ -1,121 +0,0 @@ -#include -#include "alloc.h" -#include "error.h" -#include "stralloc.h" -#include "str.h" -#include "byte.h" -#include "env.h" -#include "pathexec.h" - -/** - @file pathexec.c - @author djb - @source ucspi-tcp, ucspi-ssl - @brief populate environment after fork -*/ - -static stralloc plus; -static stralloc tmp; - -int pathexec_env(const char *s,const char *t) -{ - if (!s) return 1; - if (!stralloc_copys(&tmp,s)) return 0; - if (t) { - if (!stralloc_cats(&tmp,"=")) return 0; - if (!stralloc_cats(&tmp,t)) return 0; - } - if (!stralloc_0(&tmp)) return 0; - return stralloc_cat(&plus,&tmp); -} - -int pathexec_multienv(stralloc *sa) -{ - if (!sa) return 1; - return stralloc_cat(&plus,sa); -} - -void pathexec(char * const *argv) -{ - char **e; - unsigned int elen; - unsigned int i; - unsigned int j; - unsigned int split; - unsigned int t; - - if (!stralloc_cats(&plus,"")) return; - - elen = 0; - for (i = 0; environ[i]; ++i) - ++elen; - for (i = 0; i < plus.len; ++i) - if (!plus.s[i]) - ++elen; - - e = (char **) alloc((elen + 1) * sizeof(char *)); - if (!e) return; - - elen = 0; - for (i = 0; environ[i]; ++i) - e[elen++] = environ[i]; - - j = 0; - for (i = 0; i < plus.len; ++i) - if (!plus.s[i]) { - split = str_chr(plus.s + j,'='); - for (t = 0; t < elen; ++t) - if (byte_equal(plus.s + j,split,e[t])) - if (e[t][split] == '=') { - --elen; - e[t] = e[elen]; - break; - } - if (plus.s[j + split]) - e[elen++] = plus.s + j; - j = i + 1; - } - e[elen] = 0; - - pathexec_run(*argv,argv,e); - alloc_free(e); -} - -void pathexec_run(const char *file,char *const *argv,char *const *envp) -{ - char *path; - unsigned int split; - int savederrno; - - if (file[str_chr(file,'/')]) { - execve(file,argv,envp); - return; - } - - path = env_get("PATH"); - if (!path) path = "/bin:/usr/bin"; - - savederrno = 0; - for (;;) { - split = str_chr(path,':'); - if (!stralloc_copyb(&tmp,path,split)) return; - if (!split) - if (!stralloc_cats(&tmp,".")) return; - if (!stralloc_cats(&tmp,"/")) return; - if (!stralloc_cats(&tmp,file)) return; - if (!stralloc_0(&tmp)) return; - - execve(tmp.s,argv,envp); - if (errno != ENOENT) { - savederrno = errno; - if ((errno != EACCES) && (errno != EPERM) && (errno != EISDIR)) return; - } - - if (!path[split]) { - if (savederrno) errno = savederrno; - return; - } - path += split; - path += 1; - } -} diff --git a/prot.c b/prot.c deleted file mode 100644 index 907de52..0000000 --- a/prot.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include -//#include "hasshsgr.h" -#include "prot.h" - -/** - @file prot.c - @author djb - @source qmail - @brief setting up uid an gid for OS (short group was for ancient solaris) -*/ - -/* XXX: there are more portability problems here waiting to leap out at me */ - -int prot_gid(int gid) -{ -//#ifdef HASSHORTSETGROUPS -// short x[2]; -// x[0] = gid; x[1] = 73; /* catch errors */ -// if (setgroups(1,x) == -1) return -1; -//#else - if (setgroups(1,(gid_t *)&gid) == -1) return -1; -//#endif - return setgid(gid); /* _should_ be redundant, but on some systems it isn't */ -} - -int prot_uid(int uid) -{ - return setuid(uid); -} diff --git a/readclose.c b/readclose.c deleted file mode 100644 index b0bce7e..0000000 --- a/readclose.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include "open.h" -#include "error.h" -#include "readclose.h" - -/** - @file readclose.c - @author kp - @source qlibs - @brief This is the successor of the older 'slurpclose.c' file. The function - 'slurpclose' is now called 'readclose_append'. The other function - 'readclose' was introduced here initial. -*/ - -int readclose_append(int fd,stralloc *sa,unsigned int bufsize) -{ - int r; - for (;;) { - if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; } - r = read(fd,sa->s + sa->len,bufsize); - if (r == -1) if (errno == EINTR) continue; - if (r <= 0) { close(fd); return r; } - sa->len += r; - } -} - -int readclose(int fd,stralloc *sa,unsigned int bufsize) -{ - if (!stralloc_copys(sa,"")) { close(fd); return -1; } - return readclose_append(fd,sa,bufsize); -} - -int openreadclose(const char *fn,stralloc *sa,unsigned int bufsize) -{ - int fd; - fd = open_read((char *) fn); - if (fd == -1) { - if (errno == ENOENT) return 0; - return -1; - } - if (readclose(fd,sa,bufsize) == -1) return -1; - return 1; -} diff --git a/scan.c b/scan.c deleted file mode 100644 index da3d8ad..0000000 --- a/scan.c +++ /dev/null @@ -1,120 +0,0 @@ -#include "scan.h" - -/** - @file scan.c - @author djb - @source qmail, ucspi-tcp - @brief scanning/conversion of strings to different variable types -*/ - -static long int fromhex(unsigned char c) -{ - if (c>='0' && c<='9') - return c-'0'; - else if (c>='A' && c<='F') - return c-'A'+10; - else if (c>='a' && c<='f') - return c-'a'+10; - return -1; -} - -unsigned int scan_0x(register const char *s,register unsigned int *u) -{ - register unsigned int pos = 0; - register unsigned long result = 0; - register long int c; - - while ((c = fromhex((unsigned char) (s[pos]))) >= 0) { - result = (result << 4) + c; - ++pos; - } - *u = result; - return pos; -} - -unsigned int scan_8long(register const char *s,register unsigned long *u) -{ - register unsigned int pos = 0; - register unsigned long result = 0; - register unsigned long c; - - while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 8) { - result = result * 8 + c; - ++pos; - } - *u = result; - return pos; -} - -unsigned int scan_uint(register const char *s,register unsigned int *u) -{ - register unsigned int pos; - unsigned long result; - - pos = scan_ulong(s,&result); - *u = result; - return pos; -} - -unsigned int scan_plusminus(register const char *s,register int *sign) -{ - if (*s == '+') { *sign = 1; return 1; } - if (*s == '-') { *sign = -1; return 1; } - *sign = 1; return 0; -} - -unsigned int scan_long(register const char *s,register long *i) -{ - int sign; - unsigned long u; - register unsigned int len; - - len = scan_plusminus(s,&sign); s += len; - len += scan_ulong(s,&u); - if (sign < 0) *i = -u; else *i = u; - return len; -} - - -unsigned int scan_ulong(register const char *s,register unsigned long *u) -{ - register unsigned int pos = 0; - register unsigned long result = 0; - register unsigned long c; - - while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) { - result = result * 10 + c; - ++pos; - } - *u = result; - return pos; -} - -unsigned int scan_xlong(const char *s,unsigned long *u) -{ - register const char *t = s; - register int l = 0; - register unsigned char c; - - while ((c = fromhex(*t)) < 16) { - l = (l<<4)+c; - ++t; - } - *u=l; - return t-s; -} - -unsigned int scan_xint(const char *s,unsigned int *i) -{ - register const char *t = s; - register unsigned int l = 0; - register unsigned char c; - - while ((l >> (sizeof(l)*8 - 4)) == 0 - && (c = (unsigned char)fromhex((unsigned char)*t))<16) { - l= (l << 4) + c; - ++t; - } - *i = l; - return (unsigned int)(t-s); -} diff --git a/seek.c b/seek.c deleted file mode 100644 index ac761a9..0000000 --- a/seek.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include "seek.h" - -/** - @file seek.c - @author djb - @source qmail - @brief seek in an open file descritor -*/ - -off_t lseek(int fd,off_t offset,int whence); -int ftruncate(int fd, off_t length); - -#define CUR 1 /* sigh */ - -seek_pos seek_cur(int fd) -{ return lseek(fd,(off_t) 0,CUR); } - -#define END 2 /* sigh */ - -int seek_end(int fd) -{ if (lseek(fd,(off_t) 0,END) == -1) return -1; return 0; } - -#define SET 0 /* sigh */ - -int seek_set(int fd,seek_pos pos) -{ if (lseek(fd,(off_t) pos,SET) == -1) return -1; return 0; } - -int seek_trunc(int fd,seek_pos pos) -{ return ftruncate(fd,(off_t) pos); } diff --git a/sig.c b/sig.c deleted file mode 100644 index 0963948..0000000 --- a/sig.c +++ /dev/null @@ -1,110 +0,0 @@ -#include -#include "sig.h" - -/** - @file sig.c - @author djb - @source qmail - @brief signal handling functions -*/ - -void sig_alarmblock() { sig_block(SIGALRM); } -void sig_alarmunblock() { sig_unblock(SIGALRM); } -void sig_alarmcatch(f) void (*f)(); { sig_catch(SIGALRM,f); } -void sig_alarmdefault() { sig_catch(SIGALRM,SIG_DFL); } -int sig_alarm = SIGALRM; - -void sig_block(int sig) -{ - sigset_t ss; - sigemptyset(&ss); - sigaddset(&ss,sig); - sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0); -} - -void sig_unblock(int sig) -{ - sigset_t ss; - sigemptyset(&ss); - sigaddset(&ss,sig); - sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0); -} - -void sig_blocknone() -{ - sigset_t ss; - sigemptyset(&ss); - sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); -} - -void sig_catch(int sig,void (*f)()) -{ - struct sigaction sa; - sa.sa_handler = f; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sigaction(sig,&sa,(struct sigaction *) 0); -} - -void sig_pause() -{ - sigset_t ss; - sigemptyset(&ss); - sigsuspend(&ss); -} - -void sig_pipeignore() { sig_catch(SIGPIPE,SIG_IGN); } -void sig_pipedefault() { sig_catch(SIGPIPE,SIG_DFL); } -int sig_pipe = SIGPIPE; - -void sig_childblock() { sig_block(SIGCHLD); } -void sig_childunblock() { sig_unblock(SIGCHLD); } -void sig_childcatch(f) void (*f)(); { sig_catch(SIGCHLD,f); } -void sig_childdefault() { sig_catch(SIGCHLD,SIG_DFL); } -int sig_child = SIGCHLD; - -void sig_hangupblock() { sig_block(SIGHUP); } -void sig_hangupunblock() { sig_unblock(SIGHUP); } -void sig_hangupcatch(f) void (*f)(); { sig_catch(SIGHUP,f); } -void sig_hangupdefault() { sig_catch(SIGHUP,SIG_DFL); } -int sig_hangup = SIGHUP; - -void sig_termblock() { sig_block(SIGTERM); } -void sig_termunblock() { sig_unblock(SIGTERM); } -void sig_termcatch(f) void (*f)(); { sig_catch(SIGTERM,f); } -void sig_termdefault() { sig_catch(SIGTERM,SIG_DFL); } -int sig_term = SIGTERM; - -void sig_bugcatch(void (*f)()) -{ - sig_catch(SIGILL,f); - sig_catch(SIGABRT,f); - sig_catch(SIGFPE,f); - sig_catch(SIGBUS,f); - sig_catch(SIGSEGV,f); -#ifdef SIGSYS - sig_catch(SIGSYS,f); -#endif -#ifdef SIGEMT - sig_catch(SIGEMT,f); -#endif -} -void (*sig_defaulthandler)() = SIG_DFL; - -void sig_miscignore() -{ - sig_catch(SIGVTALRM,SIG_IGN); - sig_catch(SIGPROF,SIG_IGN); - sig_catch(SIGQUIT,SIG_IGN); - sig_catch(SIGINT,SIG_IGN); - sig_catch(SIGHUP,SIG_IGN); -#ifdef SIGXCPU - sig_catch(SIGXCPU,SIG_IGN); -#endif -#ifdef SIGXFSZ - sig_catch(SIGXFSZ,SIG_IGN); -#endif -} -void (*sig_ignorehandler)() = SIG_IGN; - -int sig_cont = SIGCONT; diff --git a/socket_bind.c b/socket_bind.c deleted file mode 100644 index b942e20..0000000 --- a/socket_bind.c +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include -#include -#include -#include "byte.h" -#include "socket_if.h" -#include "ip.h" - -/** - @file socket_bind.c - @author djb, fefe, feh - @source qmail, djbdns, ucspi-tcp6 - @brief binding a socket to a local resource -*/ - -int socket_bind4(int s,const char ip[4],uint16 port) -{ - struct sockaddr_in sa; - - byte_zero(&sa,sizeof(sa)); - sa.sin_family = AF_INET; - uint16_pack_big((char *)&sa.sin_port,port); - byte_copy((char *)&sa.sin_addr,4,ip); - - return bind(s,(struct sockaddr *)&sa,sizeof(sa)); -} - -int socket_bind4_reuse(int s,const char ip[4],uint16 port) -{ - int opt = 1; - setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); - return socket_bind4(s,ip,port); -} - -/* seems not to be used here -- djbdns requires it */ -void socket_tryreservein(int s,int size) -{ - while (size >= 1024) { - if (setsockopt(s,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size)) == 0) return; - size -= (size >> 5); - } -} - -int socket_bind6(int s,const char ip[16],uint16 port,uint32 scope_id) -{ - struct sockaddr_in6 sa; - - byte_zero(&sa,sizeof(sa)); - sa.sin6_family = AF_INET6; - uint16_pack_big((char *)&sa.sin6_port,port); -/* implicit: sa.sin6_flowinfo = 0; */ - byte_copy((char *)&sa.sin6_addr,16,ip); - sa.sin6_scope_id = scope_id; - - return bind(s,(struct sockaddr *)&sa,sizeof(sa)); -} - -int socket_bind6_reuse(int s,const char ip[16],uint16 port,uint32 scope_id) -{ - int opt = 1; - setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); - return socket_bind6(s,ip,port,scope_id); -} - -int socket_bind(int s,const char ip[16],uint16 port,uint32 scope_id) -{ - if (ip6_isv4mapped(ip)) - return socket_bind4(s,ip + 12,port); - - return socket_bind6(s,ip,port,scope_id); -} - -int socket_bind_reuse(int s,const char ip[16],uint16 port,uint32 scope_id) -{ - if (ip6_isv4mapped(ip)) - return socket_bind4_reuse(s,ip + 12,port); - - return socket_bind6_reuse(s,ip,port,scope_id); -} diff --git a/socket_connect.c b/socket_connect.c deleted file mode 100644 index 7b20659..0000000 --- a/socket_connect.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include -#include -#include -#include "byte.h" -#include "socket_if.h" -#include "ip.h" - -/** - @file socket_connect.c - @author djb, fefe, feh, kp - @source qmail, ucscpi-tcp6 - @brief connection to remote IP host -*/ - -int socket_connect6(int s,const char ip[16],uint16 port,uint32 scope_id) -{ - struct sockaddr_in6 sa; - - byte_zero(&sa,sizeof(sa)); - sa.sin6_family = AF_INET6; - uint16_pack_big((char *)&sa.sin6_port,port); - sa.sin6_flowinfo = 0; - sa.sin6_scope_id = scope_id; - byte_copy((char *)&sa.sin6_addr,16,ip); - - return connect(s,(struct sockaddr *)&sa,sizeof(sa)); -} - -/* this explizit declaration is needed to prevent compiler warnings */ -int read(int _str, void *_buf, int _b); - -int socket_connect4(int s,const char ip[4],uint16 port) -{ - struct sockaddr_in sa; - - byte_zero(&sa,sizeof(sa)); - sa.sin_family = AF_INET; - uint16_pack_big((char *)&sa.sin_port,port); - byte_copy((char *)&sa.sin_addr,4,ip); - - return connect(s,(struct sockaddr *)&sa,sizeof(sa)); -} - -int socket_connect(int s,const char ip[16],uint16 port,uint32 scope_id) -{ - if (ip6_isv4mapped(ip)) - return socket_connect4(s,ip + 12,port); - - return socket_connect6(s,ip,port,scope_id); -} - -int socket_connected(int s) -{ - struct sockaddr_in6 sa; - int dummy; - char ch; - - dummy = sizeof(sa); - if (getpeername(s,(struct sockaddr *)&sa,(socklen_t *)&dummy) == -1) { - read(s,&ch,1); /* sets errno */ - return 0; - } - return 1; -} diff --git a/socket_if.c b/socket_if.c deleted file mode 100644 index f55af4e..0000000 --- a/socket_if.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include -#include -#include -#include "socket_if.h" - -/** - @file socket_if.c - @author fefe, feh - @source ucspi-tcp6 - @brief interface handling for LLU -*/ - -const unsigned char V4loopback[4] = {127,0,0,1}; -const unsigned char V4localnet[4] = {0,0,0,0}; -/* the 'V4mappedprefix' constant is needed by 'ip.a' too */ -const unsigned char V4mappedprefix[12] = {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff}; -const unsigned char V6localnet[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; -const unsigned char V6loopback[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1}; - -uint32 socket_getifidx(const char *ifname) -{ - return if_nametoindex(ifname); -} - -static char ifname[IFNAMSIZ]; - -const char* socket_getifname(uint32 scope_id) -{ - char *tmp = if_indextoname(scope_id,ifname); - if (tmp) - return tmp; - else - return "[unknown]"; -} diff --git a/socket_info.c b/socket_info.c deleted file mode 100644 index e644798..0000000 --- a/socket_info.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include -#include -#include "byte.h" -#include "socket_if.h" -#include "ip.h" - -/** - @file socket_info.c - @author djb, fefe, feh - @source ucspi-tcp6 - @brief querying local and remote info for socket -*/ - -int socket_local(int s,char ip[16],uint16 *port,uint32 *scope_id) -{ - struct sockaddr_in6 sa; - unsigned int dummy = sizeof(sa); - - if (getsockname(s,(struct sockaddr *)&sa,&dummy) == -1) return -1; - - if (sa.sin6_family == AF_INET) { - struct sockaddr_in *sa4 = (struct sockaddr_in*)&sa; - byte_copy(ip,12,V4mappedprefix); - byte_copy(ip+12,4,(char *)&sa4->sin_addr); - uint16_unpack_big((char *)&sa4->sin_port,port); - if (scope_id) *scope_id = 0; - } else { - byte_copy(ip,16,(char *)&sa.sin6_addr); - uint16_unpack_big((char *)&sa.sin6_port,port); - if (scope_id) *scope_id = sa.sin6_scope_id; - } - - return 0; -} - -int socket_remote(int s,char ip[16],uint16 *port,uint32 *scope_id) -{ - struct sockaddr_in6 sa; - unsigned int dummy = sizeof(sa); - - if (getpeername(s,(struct sockaddr *)&sa,&dummy) == -1) return -1; - - if (sa.sin6_family == AF_INET) { - struct sockaddr_in *sa4 = (struct sockaddr_in*)&sa; - byte_copy(ip,12,V4mappedprefix); - byte_copy(ip+12,4,(char *)&sa4->sin_addr); - uint16_unpack_big((char *)&sa4->sin_port,port); - *scope_id = 0; - } else { - byte_copy(ip,16,(char *)&sa.sin6_addr); - uint16_unpack_big((char *)&sa.sin6_port,port); - *scope_id = sa.sin6_scope_id; - } - - return 0; -} diff --git a/socket_recv.c b/socket_recv.c deleted file mode 100644 index de8c856..0000000 --- a/socket_recv.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include -#include -#include "byte.h" -#include "ip.h" -#include "socket_if.h" - -/** - @file socket_recv.c - @author djb, fefe - @source ucspi-tcp6 - @brief setup receiving socket -*/ - -int socket_recv(int s,char *buf,unsigned int len,char ip[16],uint16 *port,uint32 *scope_id) -{ - struct sockaddr_in6 sa; - unsigned int dummy = sizeof(sa); - int r; - - byte_zero(&sa,dummy); - r = recvfrom(s,buf,len,0,(struct sockaddr *)&sa,&dummy); - if (r == -1) return -1; - - if (sa.sin6_family == AF_INET) { - struct sockaddr_in *sa4 = (struct sockaddr_in *)&sa; - byte_copy(ip,12,V4mappedprefix); - byte_copy(ip+12,4,(char *)&sa4->sin_addr); - uint16_unpack_big((char *)&sa4->sin_port,port); - if (scope_id) *scope_id = 0; - } else { - byte_copy(ip,16,(char *)&sa.sin6_addr); - uint16_unpack_big((char *)&sa.sin6_port,port); - if (scope_id) *scope_id = sa.sin6_scope_id; - } - - return r; -} diff --git a/socket_send.c b/socket_send.c deleted file mode 100644 index 9f09520..0000000 --- a/socket_send.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include -#include -#include "byte.h" -#include "ip.h" -#include "socket_if.h" - -/** - @file socket_send.c - @author djb, fefe, feh - @source ucspi-tcp6 - @brief setup sending socket -*/ - -int socket_send4(int s,const char *buf,unsigned int len,const char ip[4],uint16 port) -{ - struct sockaddr_in sa; - - byte_zero(&sa,sizeof(sa)); - - sa.sin_family = AF_INET; - uint16_pack_big((char *)&sa.sin_port,port); - byte_copy((char *)&sa.sin_addr,4,ip); - - return sendto(s,buf,len,0,(struct sockaddr *)&sa,sizeof(sa)); -} - -int socket_send6(int s,const char *buf,unsigned int len,const char ip[16],uint16 port,uint32 scope_id) -{ - struct sockaddr_in6 sa; - - byte_zero(&sa,sizeof(sa)); - - sa.sin6_family = AF_INET6; - sa.sin6_scope_id = scope_id; - uint16_pack_big((char *)&sa.sin6_port,port); - byte_copy((char *)&sa.sin6_addr,16,ip); - - return sendto(s,buf,len,0,(struct sockaddr *)&sa,sizeof(sa)); -} - -int socket_send(int s,const char *buf,unsigned int len,const char ip[16],uint16 port,uint32 scope_id) -{ - if (ip6_isv4mapped(ip)) - return socket_send4(s,buf,len,ip + 12,port); - else - return socket_send6(s,buf,len,ip,port,scope_id); -} - -int socket_broadcast4(int s,const char *buf,unsigned int len,uint16 port) -{ - struct sockaddr_in sa; - - byte_zero(&sa,sizeof(sa)); - - sa.sin_family = AF_INET; - uint16_pack_big((char *)&sa.sin_port,port); - byte_copy((char *)&sa.sin_addr,4,V4broadcast); - - return sendto(s,buf,len,0,(struct sockaddr *)&sa,sizeof(sa)); -} diff --git a/socket_setup.c b/socket_setup.c deleted file mode 100644 index fb65fa2..0000000 --- a/socket_setup.c +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include -#include -#include -#include "byte.h" -#include "socket_if.h" -#include "ip.h" - -/** - @file socket_setup.c - @author djb, feh - @source ucspi-tcp6 - @brief setup listening socket -*/ - -int socket_accept(int s,char ip[16],uint16 *port,uint32 *scope_id) -{ - struct sockaddr_in6 sa; - unsigned int dummy = sizeof(sa); - int fd; - - fd = accept(s,(struct sockaddr *)&sa,&dummy); - if (fd == -1) return -1; - - if (sa.sin6_family == AF_INET) { - struct sockaddr_in *sa4 = (struct sockaddr_in*)&sa; - byte_copy(ip,12,V4mappedprefix); - byte_copy(ip+12,4,(char *)&sa4->sin_addr); - uint16_unpack_big((char *)&sa4->sin_port,port); - if (scope_id) *scope_id = 0; - } else { - byte_copy(ip,16,(char *)&sa.sin6_addr); - uint16_unpack_big((char *)&sa.sin6_port,port); - if (scope_id) *scope_id = sa.sin6_scope_id; - } - - return fd; -} - -int socket_accept4(int s,char ip[4],uint16 *port) -{ - struct sockaddr_in sa; - unsigned int dummy = sizeof(sa); - int fd; - - fd = accept(s,(struct sockaddr *) &sa,&dummy); - if (fd == -1) return -1; - - byte_copy(ip,4,(char *) &sa.sin_addr); - uint16_unpack_big((char *) &sa.sin_port,port); - - return fd; -} - -int socket_listen(int s,int backlog) -{ - return listen(s,backlog); -} - -int socket_ipoptionskill(int s) -{ - int r; - - r = setsockopt(s,IPPROTO_IP,1,(char *) 0,0); /* 1 == IP_OPTIONS */ - r = setsockopt(s,IPPROTO_IPV6,1,(char *) 0,0); - - return r; -} - -int socket_ip6anycast(int s) -{ - int opt = 1; - int r; - -#ifdef GEN_IP_PKTINFO /* Linux */ - r = setsockopt(s,IPPROTO_IP,GEN_IP_PKTINFO,&opt,sizeof(opt)); -#elif IP_PKTINFO /* Solaris */ - r = setsockopt(s,IPPROTO_IP,IP_PKTINFO,&opt,sizeof(opt)); -#elif IP_RECVDSTADDR /* BSD */ - r = setsockopt(s,IPPROTO_IP,IP_RECVDSTADDR,&opt,sizeof(opt)); -#elif IPV6_RECVDSTADDR - r = setsockopt(s,IPPROTO_IPV6,IP_RECVDSTADDR,&opt,sizeof(opt)); -#endif - return r; -} - -int socket_dualstack(int s) -{ - int opt = 0; - - return setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,&opt,sizeof(opt)); -} - -int socket_nodualstack(int s) -{ - int opt = 1; - - return setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,&opt,sizeof(opt)); -} diff --git a/socket_tcp.c b/socket_tcp.c deleted file mode 100644 index 1ff050e..0000000 --- a/socket_tcp.c +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include -#include -#include -#include -#include "close.h" /* better use unistd.h ? */ -#include "ndelay.h" -#include "socket_if.h" -#include "error.h" - -#ifndef EAFNOSUPPORT -#define EAFNOSUPPORT EINVAL -#endif - -/** - @file socket_tcp.c - @author djb, fefe, feh - @source ucspi-tcp6 - @brief setup TCP stream socket -*/ - -int socket_tcp4(void) -{ - int s; - - s = socket(AF_INET,SOCK_STREAM,0); - if (s != -1) - if (ndelay_on(s) == -1) { close(s); return -1; } - - return s; -} - -int socket_tcp6(void) -{ - int s; - - s = socket(AF_INET6,SOCK_STREAM,0); - if (s != -1) - if (ndelay_on(s) == -1) { close(s); return -1; } - - return s; -} - -int socket_tcp(void) -{ - int s; - - s = socket(AF_INET6,SOCK_STREAM,0); - if (s == -1) - if (errno == EINVAL || errno == EAFNOSUPPORT || errno == EPROTO || errno == EPROTONOSUPPORT) - s = socket(AF_INET,SOCK_STREAM,0); - - if (s != -1) - if (ndelay_on(s) == -1) { close(s); return -1; } - - return s; -} - -int socket_tcpnodelay(int s) -{ - int opt = 1; - return setsockopt(s,IPPROTO_TCP,1,&opt,sizeof(opt)); /* 1 == TCP_NODELAY */ -} diff --git a/socket_udp.c b/socket_udp.c deleted file mode 100644 index 743cdf1..0000000 --- a/socket_udp.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include -#include -#include -#include "close.h" /* better use unistd.h ? */ -#include "ndelay.h" -#include "socket_if.h" -#include "error.h" - -#ifndef EAFNOSUPPORT -#define EAFNOSUPPORT EINVAL -#endif - -/** - @file socket_udp.c - @author djb, fefe, feh - @source ucspi-tcp6 - @brief setup a UDP message socket -*/ - -int socket_udp6(void) -{ - int s; - - s = socket(AF_INET6,SOCK_DGRAM,0); - if (s != -1) - if (ndelay_on(s) == -1) { close(s); return -1; } - - return s; -} - -int socket_udp4(void) -{ - int s; - - s = socket(AF_INET,SOCK_DGRAM,0); - if (s != -1) - if (ndelay_on(s) == -1) { close(s); return -1; } - - return s; -} - -int socket_udp(void) -{ - int s; - - s = socket(AF_INET6,SOCK_DGRAM,0); - if (s == -1) - if (errno == EINVAL || errno == EAFNOSUPPORT || errno == EPROTO || errno == EPROTONOSUPPORT) - s = socket(AF_INET,SOCK_DGRAM,0); - - if (s != -1) - if (ndelay_on(s) == -1) { close(s); return -1; } - - return s; -} diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..8ca5d6e --- /dev/null +++ b/src/Makefile @@ -0,0 +1,127 @@ +# Makefile for qlibs + +SHELL=/bin/sh + +# static flags - DO NOT EDIT! +CCFLAGS=-I../include + +SRCS=*.c +OBJS=*.o +COMPILE=../compile +MAKELIB=../makelib +SHAREDLIB=../sharedlib + +default: clean check libs + +check: + @[ -f $(COMPILE) ] && [ -f $(MAKELIB) ] || ../configure + +clean: + @echo "Cleaning up libs ..." + @rm -f `cat TARGETS` + @cd dnsstub ; make -s clean ; cd .. + @echo " done!" + +core: alloc.a buffer.a case.a cdb.a constmap.a env.a \ +fd.a fs.a getln.a getopt.a lock.a logmsg.a ndelay.a open.a \ +seek.a sig.a str.a stralloc.a time.a wait.a \ +ip.a socket.a dnsresolv.a + +libs: obj core qlibs.a dnsresolv.a + +obj: + @echo Making all in qlibs ... + $(COMPILE) $(CCFLAGS) $(CFLAGS) $(SRCS) + +install: setup + +setup: + @../install + +shared: $(COMPILE) $(SHAREDLIB) $(OBJS) ./dnsstub/$(OBJS) + @echo "Building shared qlibs ..." + $(SHAREDLIB) $(LDFLAGS) $(OBJS) -o libqlibs.so + $(SHAREDLIB) $(LDFLAGS) ./dnsstub/$(OBJS) -o libdnsresolv.so + @ln -f libqlibs.so ../libqlibs.so + @ln -f libdnsresolv.so ../libdnsresolv.so + + +qlibs.a: obj socket.a + $(MAKELIB) $(LDFLAGS) qlibs.a *.o + @echo "Creating libqlibs ... " + @ln -f qlibs.a ../libqlibs.a + +dnsresolv.a: + @echo "Building @dnsresolv lib ..." + @cd dnsstub ; make + @cp dnsstub/dnsresolv.a dnsresolv.a + @ln -f dnsresolv.a ../libdnsresolv.a + +socket.a: ip.a + @echo "Building socket lib ..." + $(MAKELIB) $(LDFLAGS) socket.a socket_if.o socket_bind.o socket_connect.o \ + socket_info.o socket_setup.o socket_tcp.o socket_udp.o ip.a + +# build each file separately (backwards compat) - better use recipe qlibs.a +alloc.a: alloc.o + $(MAKELIB) $(LDFLAGS) alloc.a alloc.o + +buffer.a: buffer.o + $(MAKELIB) $(LDFLAGS) buffer.a buffer.o + +case.a: case.o + $(MAKELIB) $(LDFLAGS) case.a case.o + +cdb.a: cdbread.o cdbmake.o uint32p.o seek.o buffer.o + $(MAKELIB) $(LDFLAGS) cdb.a cdbread.o cdbmake.o uint32p.o seek.o buffer.o + +constmap.a: constmap.o alloc.o buffer.o scan.o + $(MAKELIB) $(LDFLAGS) constmap.a constmap.o alloc.o buffer.o scan.o + +env.a: env.o + $(MAKELIB) $(LDFLAGS) env.a env.o + +fd.a: fd.o + $(MAKELIB) $(LDFLAGS) fd.a fd.o + +fs.a: fmt.o scan.o + $(MAKELIB) $(LDFLAGS) fs.a fmt.o scan.o + +getln.a: getln.o + $(MAKELIB) $(LDFLAGS) getln.a getln.o + +getopt.a: getoptb.o + $(MAKELIB) $(LDFLAGS) getopt.a getoptb.o + +ip.a: ip4.o ip6.o socket_if.o + $(MAKELIB) $(LDFLAGS) ip.a ip4.o ip6.o socket_if.o + +lock.a: lock.o + $(MAKELIB) $(LDFLAGS) lock.a lock.o + +ndelay.a: ndelay.o + $(MAKELIB) $(LDFLAGS) ndelay.a ndelay.o + +open.a: open.o + $(MAKELIB) $(LDFLAGS) open.a open.o + +seek.a: seek.o + $(MAKELIB) $(LDFLAGS) seek.a seek.o + +sig.a: sig.o + $(MAKELIB) $(LDFLAGS) sig.a sig.o + +str.a: str.o byte.o stralloc.o alloc.o + $(MAKELIB) $(LDFLAGS) str.a str.o byte.o stralloc.o alloc.o + +stralloc.a: stralloc.o alloc.o + $(MAKELIB) $(LDFLAGS) stralloc.a stralloc.o alloc.o + +logmsg.a: errstr.o logmsg.o + $(MAKELIB) $(LDFLAGS) logmsg.a errstr.o logmsg.o + +time.a: iopause.o tai.o taia.o timeout.o timeoutconn.o + $(MAKELIB) $(LDFLAGS) time.a iopause.o tai.o taia.o timeout.o timeoutconn.o + +wait.a: wait.o + $(MAKELIB) $(LDFLAGS) wait.a wait.o diff --git a/src/TARGETS b/src/TARGETS new file mode 100644 index 0000000..df6d6ee --- /dev/null +++ b/src/TARGETS @@ -0,0 +1,79 @@ +alloc.a +alloc.o +base64.o +buffer.a +buffer.o +byte.o +case.a +case.o +cdb.a +cdbmake.o +cdbread.o +constmap.a +constmap.o +compile +dnsresolv.a +env.a +env.o +errstr.o +fd.a +fd.o +fmt.o +fs.a +getln.a +getln.o +getopt.a +getoptb.o +iopause.o +ip.a +ip4.o +ip6.o +libdnsresolv.a +libqlibs.a +lock.a +lock.o +logmsg.a +logmsg.o +makelib +ndelay.a +ndelay.o +open.a +open.o +pathexec.o +prot.o +qlibs.a +readclose.o +scan.o +seek.a +seek.o +sig.a +sig.o +socket.a +socket_bind.o +socket_connect.o +socket_if.o +socket_info.o +socket_recv.o +socket_send.o +socket_setup.o +socket_tcp.o +socket_udp.o +str.a +str.o +stralloc.a +stralloc.o +sysmsg.o +tai.o +taia.o +time.a +timeout.o +timeoutconn.o +uint128p.o +uint16p.o +uint32p.o +uint64p.o +uint8p.o +wait.a +wait.o +libdnsresolv.so +libqlibs.so diff --git a/src/alloc.c b/src/alloc.c new file mode 100644 index 0000000..d6151ec --- /dev/null +++ b/src/alloc.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include "byte.h" +#include "alloc.h" + +#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */ +#define SPACE 4096 /* must be multiple of ALIGNMENT */ +#define space ((char *)realspace) + +/** + * @file alloc.c + * @authors djb, feh, jmh + * @ref qmail + * @brief Generic allocation of heap memory + */ + +typedef union { + char irrelevant[ALIGNMENT]; + double d; +} aligned; + +static aligned realspace[SPACE / ALIGNMENT]; +static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */ + +// /*@null@*//*@out@*/char *alloc(unsigned int n) -- old style +void *alloc(unsigned int n) +{ + char *x; + +/* Guninski exploit + patch from Qualys (CVE-2005-1513) */ + + if (n >= (INT_MAX >> 3)) { + errno = ENOMEM; + return 0; + } + + n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ + if (n <= avail) { avail -= n; return space + avail; } + x = malloc(n); + if (!x) errno = ENOMEM; + return x; +} + +void alloc_free(void *x) +{ + if (x >= space) + if (x < space + SPACE) + return; /* XXX: assuming that pointers are flat */ + free(x); +} + +int alloc_re(void **x,unsigned int m,unsigned int n) +{ + char *y; + + y = alloc(n); + if (!y) return 0; + byte_copy(y,m,*x); + qfree(*x); + *x = y; + return 1; +} diff --git a/src/base64.c b/src/base64.c new file mode 100644 index 0000000..d82ecdf --- /dev/null +++ b/src/base64.c @@ -0,0 +1,123 @@ +#include "base64.h" +#include "stralloc.h" +#include "str.h" + +/** + * @file base64.c + * @author unkown + * @brief base64 en+decoding of strings + */ + +static const char *b64alpha = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +#define B64PAD '=' + +/* returns 0 ok, 1 illegal, -1 problem */ + +int b64decode(const unsigned char *in,int l,stralloc *out) /* not null terminated */ +{ + int p = 0; + int n; + unsigned int x; + int i, j; + char *s; + unsigned char b[3]; + + if (l == 0) { + if (!stralloc_copys(out,"")) return -1; + return 0; + } + + while (in[l-1] == B64PAD) { + p ++; + l--; + } + + n = (l + p) / 4; + i = (n * 3) - p; + if (!stralloc_ready(out,i)) return -1; + out->len = i; + s = out->s; + + for (i = 0; i < n - 1 ; i++) { + x = 0; + for (j = 0; j < 4; j++) { + if(in[j] >= 'A' && in[j] <= 'Z') + x = (x << 6) + (unsigned int)(in[j] - 'A' + 0); + else if(in[j] >= 'a' && in[j] <= 'z') + x = (x << 6) + (unsigned int)(in[j] - 'a' + 26); + else if(in[j] >= '0' && in[j] <= '9') + x = (x << 6) + (unsigned int)(in[j] - '0' + 52); + else if(in[j] == '+') + x = (x << 6) + 62; + else if(in[j] == '/') + x = (x << 6) + 63; + else if(in[j] == '=') + x = (x << 6); + } + + s[2] = (unsigned char)(x & 255); x >>= 8; + s[1] = (unsigned char)(x & 255); x >>= 8; + s[0] = (unsigned char)(x & 255); x >>= 8; + s += 3; in += 4; + } + + x = 0; + for (j = 0; j < 4; j++) { + if(in[j] >= 'A' && in[j] <= 'Z') + x = (x << 6) + (unsigned int)(in[j] - 'A' + 0); + else if(in[j] >= 'a' && in[j] <= 'z') + x = (x << 6) + (unsigned int)(in[j] - 'a' + 26); + else if(in[j] >= '0' && in[j] <= '9') + x = (x << 6) + (unsigned int)(in[j] - '0' + 52); + else if(in[j] == '+') + x = (x << 6) + 62; + else if(in[j] == '/') + x = (x << 6) + 63; + else if(in[j] == '=') + x = (x << 6); + } + + b[2] = (unsigned char)(x & 255); x >>= 8; + b[1] = (unsigned char)(x & 255); x >>= 8; + b[0] = (unsigned char)(x & 255); x >>= 8; + + for (i = 0; i < 3 - p; i++) + s[i] = b[i]; + + return 0; +} + +int b64encode(stralloc *in,stralloc *out) /* not null terminated */ +{ + unsigned char a, b, c; + int i; + char *s; + + if (in->len == 0) { + if (!stralloc_copys(out,"")) return -1; + return 0; + } + + i = in->len / 3 * 4 + 4; + if (!stralloc_ready(out,i)) return -1; + s = out->s; + + for (i = 0; i < in->len; i += 3) { + a = in->s[i]; + b = i + 1 < in->len ? in->s[i + 1] : 0; + c = i + 2 < in->len ? in->s[i + 2] : 0; + + *s++ = b64alpha[a >> 2]; + *s++ = b64alpha[((a & 3 ) << 4) | (b >> 4)]; + + if (i + 1 >= in->len) *s++ = B64PAD; + else *s++ = b64alpha[((b & 15) << 2) | (c >> 6)]; + + if (i + 2 >= in->len) *s++ = B64PAD; + else *s++ = b64alpha[c & 63]; + } + out->len = s - out->s; + + return 0; +} diff --git a/src/buffer.c b/src/buffer.c new file mode 100644 index 0000000..06e3857 --- /dev/null +++ b/src/buffer.c @@ -0,0 +1,226 @@ +#include +#include "buffer.h" +#include "str.h" +#include "byte.h" +#include "error.h" + +/** + * @file buffer.c + * @author djb + * @brief input/output routines + */ + +void buffer_init(buffer *s,ssize_t (*op)(),int fd,char *buf,size_t len) +{ + s->x = buf; + s->fd = fd; + s->op = op; + s->p = 0; + s->n = len; +} + +static ssize_t buffer_0_read(int fd,char *buf,size_t len) +{ + if (buffer_flush(buffer_1) == -1) return -1; + return read(fd,buf,len); +} + +ssize_t buffer_unixread(int fd,char *buf,size_t len) +{ + return (ssize_t) read(fd,buf,len); +} + +ssize_t buffer_unixwrite(int fd,char *buf,size_t len) +{ + return (ssize_t) write(fd,buf,len); +} + +char buffer_0_space[BUFFER_INSIZE]; +static buffer it0 = BUFFER_INIT(buffer_0_read,0,buffer_0_space,sizeof(buffer_0_space)); +buffer *buffer_0 = &it0; + +char buffer_1_space[BUFFER_OUTSIZE]; +static buffer it1 = BUFFER_INIT(buffer_unixwrite,1,buffer_1_space,sizeof(buffer_1_space)); +buffer *buffer_1 = &it1; + +char buffer_2_space[BUFFER_OUTSIZE]; +static buffer it2 = BUFFER_INIT(buffer_unixwrite,2,buffer_2_space,sizeof(buffer_2_space)); +buffer *buffer_2 = &it2; + +char buffer_0_small[BUFFER_SMALL]; +static buffer is0 = BUFFER_INIT(buffer_0_read,0,buffer_0_small,sizeof(buffer_0_small)); +buffer *buffer_0small = &is0; + +char buffer_1_small[BUFFER_SMALL]; +static buffer is1 = BUFFER_INIT(buffer_unixwrite,1,buffer_1_small,sizeof(buffer_1_small)); +buffer *buffer_1small = &is1; + +char buffer_2_small[BUFFER_SMALL]; +static buffer is2 = BUFFER_INIT(buffer_unixwrite,2,buffer_2_small,sizeof(buffer_2_small)); +buffer *buffer_2small = &is2; + +int buffer_copy(buffer *bout,buffer *bin) +{ + int n; + char *x; + + for (;;) { + n = buffer_feed(bin); + if (n < 0) return -2; + if (!n) return 0; + x = buffer_PEEK(bin); + if (buffer_put(bout,x,n) == -1) return -3; + buffer_SEEK(bin,n); + } +} + +static int oneread(ssize_t (*op)(),int fd,char *buf,size_t len) +{ + int r; + + for (;;) { + r = op(fd,buf,len); + if (r == -1) if (errno == EINTR) continue; + return r; + } +} + +static int getthis(buffer *s,char *buf,size_t len) +{ + if (len > s->p) len = s->p; + s->p -= len; + byte_copy(buf,len,s->x + s->n); + s->n += len; + return len; +} + +int buffer_feed(buffer *s) +{ + int r; + + if (s->p) return s->p; + r = oneread(s->op,s->fd,s->x,s->n); + if (r <= 0) return r; + s->p = r; + s->n -= r; + if (s->n > 0) byte_copyr(s->x + s->n,r,s->x); + return r; +} + +int buffer_bget(buffer *s,char *buf,size_t len) +{ + int r; + + if (s->p > 0) return getthis(s,buf,len); + if (s->n <= len) return oneread(s->op,s->fd,buf,s->n); + r = buffer_feed(s); + if (r <= 0) return r; + return getthis(s,buf,len); +} + +int buffer_get(buffer *s,char *buf,size_t len) +{ + int r; + + if (s->p > 0) return getthis(s,buf,len); + if (s->n <= len) return oneread(s->op,s->fd,buf,len); + r = buffer_feed(s); + if (r <= 0) return r; + return getthis(s,buf,len); +} + +char *buffer_peek(buffer *s) +{ + return s->x + s->n; +} + +void buffer_seek(buffer *s,size_t len) +{ + s->n += len; + s->p -= len; +} + +static int allwrite(ssize_t (*op)(),int fd,const char *buf,size_t len) +{ + int w; + + while (len) { + w = op(fd,buf,len); + if (w == -1) { + if (errno == EINTR) continue; + return -1; /* note that some data may have been written */ + } + if (w == 0) /* luser's fault */ + ; + buf += w; + len -= w; + } + return 0; +} + +int buffer_flush(buffer *s) +{ + int p; + + p = s->p; + if (!p) return 0; + s->p = 0; + return allwrite(s->op,s->fd,s->x,p); +} + +int buffer_putalign(buffer *s,const char *buf,size_t len) +{ + unsigned int n; + + while (len > (n = s->n - s->p)) { + byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n; + if (buffer_flush(s) == -1) return -1; + } + /* now len <= s->n - s->p */ + byte_copy(s->x + s->p,len,buf); + s->p += len; + return 0; +} + +int buffer_put(buffer *s,const char *buf,size_t len) +{ + unsigned int n; + + n = s->n; + if (len > n - s->p) { + if (buffer_flush(s) == -1) return -1; + /* now s->p == 0 */ + if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE; + while (len > s->n) { + if (n > len) n = len; + if (allwrite(s->op,s->fd,buf,n) == -1) return -1; + buf += n; + len -= n; + } + } + /* now len <= s->n - s->p */ + byte_copy(s->x + s->p,len,buf); + s->p += len; + return 0; +} + +int buffer_putflush(buffer *s,const char *buf,size_t len) +{ + if (buffer_flush(s) == -1) return -1; + return allwrite(s->op,s->fd,buf,len); +} + +int buffer_putsalign(buffer *s,const char *buf) +{ + return buffer_putalign(s,buf,str_len(buf)); +} + +int buffer_puts(buffer *s,const char *buf) +{ + return buffer_put(s,buf,str_len(buf)); +} + +int buffer_putsflush(buffer *s,const char *buf) +{ + return buffer_putflush(s,buf,str_len(buf)); +} diff --git a/src/byte.c b/src/byte.c new file mode 100644 index 0000000..c6ac6b0 --- /dev/null +++ b/src/byte.c @@ -0,0 +1,82 @@ +#include "byte.h" + +/** + * @file byte.c + * @author djb + * @brief byte manipulation functions + */ + +unsigned int byte_chr(char *s,unsigned int n,int c) +{ + char ch = c; + char *t = s; + + for (;;) { + if (!n) { break; } if (*t == ch) { break; } ++t; --n; + } + return t - s; +} + +void byte_copy(void *to,unsigned int n,const void *from) +{ + char *out = to; // share same address + const char *in = from; // one byte + + for (;;) { + if (!n) { return; } *out++ = *in++; --n; + } +} + +void byte_copyr(void *to,unsigned int n,const void *from) +{ + char *out = to + n; + const char *in = from + n; + + for (;;) { + if (!n) { return; } *--out = *--in; --n; + } +} + +int byte_diff(const void *s,unsigned int n,const void *t) +{ + const char *a = s; + const char *b = t; + + for (;;) { + if (!n) { return 0; } if (*a != *b) { break; } ++a; ++b; --n; + } + return ((int)(unsigned int)(unsigned char) *a) + - ((int)(unsigned int)(unsigned char) *b); +} + +unsigned int byte_rchr(char *s,unsigned int n,int c) +{ + char ch = c; + char *t = s; + char *u = 0; + + for (;;) { + if (!n) { break; } if (*t == ch) { u = t; } ++t; --n; + } + if (!u) { u = t; } + return u - s; +} + +void byte_zero(void *s,unsigned int n) +{ + char *out = s; + + for (;;) { + if (!n) { break; } *out++ = 0; --n; + } +} + +void byte_fill(void *to,unsigned int n,int c) +{ + char *s = to; + char ch = c; + + for (;;) { + if (!n) { break; } *s++ = ch; --n; + } +} diff --git a/src/case.c b/src/case.c new file mode 100644 index 0000000..b3aba2f --- /dev/null +++ b/src/case.c @@ -0,0 +1,134 @@ +#include "case.h" +#include "str.h" + +/** + * @file case.c + * @author djb + * @brief string comparison and helper functions; case insensitive + */ + +int case_diffb(char *s,unsigned int len,char *t) +{ + unsigned char x; + unsigned char y; + + while (len > 0) { + --len; + x = *s++ - 'A'; + if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; + y = *t++ - 'A'; + if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; + if (x != y) + return ((int)(unsigned int) x) - ((int)(unsigned int) y); + } + return 0; +} + +int case_diffs(char *s,char *t) +{ + unsigned char x; + unsigned char y; + + for (;;) { + x = *s++ - 'A'; + if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; + y = *t++ - 'A'; + if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; + if (x != y) break; + if (!x) break; + } + return ((int)(unsigned int) x) - ((int)(unsigned int) y); +} + +int case_diffrs(char *s,char *t) +{ + unsigned char x = 0; + unsigned char y = 0; + unsigned int lens = str_len(s); + unsigned int lent = str_len(t); + + while (lens > 0 && lent > 0) { + x = s[--lens] - 'A'; + if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; + y = t[--lent] - 'A'; + if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; + if (x != y) break; + if (!x) break; + if (!y) break; + } + return ((int)(unsigned int) x) - ((int)(unsigned int) y); +} + +void case_lowerb(char *s,unsigned int len) +{ + unsigned char x; + while (len > 0) { + --len; + x = *s - 'A'; + if (x <= 'Z' - 'A') *s = x + 'a'; + ++s; + } +} + +void case_lowers(char *s) +{ + unsigned char x; + while ((x = *s)) { + x -= 'A'; + if (x <= 'Z' - 'A') *s = x + 'a'; + ++s; + } +} + +void case_upperb(char *s,unsigned int len) +{ + unsigned char x; + while (len > 0) { + --len; + x = *s - 'a'; + if (x <= 'z' - 'a') *s = x + 'A'; + ++s; + } +} + +void case_uppers(char *s) +{ + unsigned char x; + while ((x = *s)) { + x -= 'a'; + if (x <= 'z' - 'a') *s = x + 'A'; + ++s; + } +} + +int case_startb(char *s,unsigned int len,char *t) +{ + unsigned char x; + unsigned char y; + + for (;;) { + y = *t++ - 'A'; + if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; + if (!y) return 1; + if (!len) return 0; + --len; + x = *s++ - 'A'; + if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; + if (x != y) return 0; + } +} + +int case_starts(char *s,char *t) +{ + unsigned char x; + unsigned char y; + + for (;;) { + x = *s++ - 'A'; + if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; + y = *t++ - 'A'; + if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; + if (!y) return 1; + if (x != y) return 0; + } +} diff --git a/src/cdbmake.c b/src/cdbmake.c new file mode 100644 index 0000000..54372c1 --- /dev/null +++ b/src/cdbmake.c @@ -0,0 +1,158 @@ +#include +#include "seek.h" +#include "error.h" +#include "alloc.h" +#include "cdbread.h" +#include "cdbmake.h" + +/** + * @file cdbmake.c + * @author djb + * @ref ucspi-tcp + * @brief constant data base (cdb) generation + */ + +int cdb_make_start(struct cdb_make *c,int fd) +{ + c->head = 0; + c->split = 0; + c->hash = 0; + c->numentries = 0; + c->fd = fd; + c->pos = sizeof(c->final); + buffer_init(&c->b,write,fd,c->bspace,sizeof(c->bspace)); + return seek_set(fd,c->pos); +} + +static int posplus(struct cdb_make *c,uint32 len) +{ + uint32 newpos = c->pos + len; + if (newpos < len) { errno = ENOMEM; return -1; } + c->pos = newpos; + return 0; +} + +int cdb_make_addend(struct cdb_make *c,unsigned int keylen,unsigned int datalen,uint32 h) +{ + struct cdb_hplist *head; + + head = c->head; + if (!head || (head->num >= CDB_HPLIST)) { + head = (struct cdb_hplist *) alloc(sizeof(struct cdb_hplist)); + if (!head) return -1; + head->num = 0; + head->next = c->head; + c->head = head; + } + head->hp[head->num].h = h; + head->hp[head->num].p = c->pos; + ++head->num; + ++c->numentries; + if (posplus(c,8) == -1) return -1; + if (posplus(c,keylen) == -1) return -1; + if (posplus(c,datalen) == -1) return -1; + return 0; +} + +int cdb_make_addbegin(struct cdb_make *c,unsigned int keylen,unsigned int datalen) +{ + char buf[8]; + + if (keylen > 0xffffffff) { errno = ENOMEM; return -1; } + if (datalen > 0xffffffff) { errno = ENOMEM; return -1; } + + uint32_pack(buf,keylen); + uint32_pack(buf + 4,datalen); + if (buffer_putalign(&c->b,buf,8) == -1) return -1; + return 0; +} + +int cdb_make_add(struct cdb_make *c,char *key,unsigned int keylen,char *data,unsigned int datalen) +{ + if (cdb_make_addbegin(c,keylen,datalen) == -1) return -1; + if (buffer_putalign(&c->b,key,keylen) == -1) return -1; + if (buffer_putalign(&c->b,data,datalen) == -1) return -1; + return cdb_make_addend(c,keylen,datalen,cdb_hash(key,keylen)); +} + +int cdb_make_finish(struct cdb_make *c) +{ + char buf[8]; + int i; + uint32 len; + uint32 u; + uint32 memsize; + uint32 count; + uint32 where; + struct cdb_hplist *x; + struct cdb_hp *hp; + + for (i = 0; i < 256; ++i) + c->count[i] = 0; + + for (x = c->head; x; x = x->next) { + i = x->num; + while (i--) + ++c->count[255 & x->hp[i].h]; + } + + memsize = 1; + for (i = 0; i < 256; ++i) { + u = c->count[i] * 2; + if (u > memsize) + memsize = u; + } + + memsize += c->numentries; /* no overflow possible up to now */ + u = (uint32) 0 - (uint32) 1; + u /= sizeof(struct cdb_hp); + if (memsize > u) { errno = ENOMEM; return -1; } + + c->split = (struct cdb_hp *) alloc(memsize * sizeof(struct cdb_hp)); + if (!c->split) return -1; + + c->hash = c->split + c->numentries; + + u = 0; + for (i = 0; i < 256; ++i) { + u += c->count[i]; /* bounded by numentries, so no overflow */ + c->start[i] = u; + } + + for (x = c->head; x; x = x->next) { + i = x->num; + while (i--) + c->split[--c->start[255 & x->hp[i].h]] = x->hp[i]; + } + + for (i = 0; i < 256; ++i) { + count = c->count[i]; + + len = count + count; /* no overflow possible */ + uint32_pack(c->final + 8 * i,c->pos); + uint32_pack(c->final + 8 * i + 4,len); + + for (u = 0; u < len; ++u) + c->hash[u].h = c->hash[u].p = 0; + + hp = c->split + c->start[i]; + for (u = 0; u < count; ++u) { + where = (hp->h >> 8) % len; + while (c->hash[where].p) + if (++where == len) + where = 0; + c->hash[where] = *hp++; + } + + for (u = 0; u < len; ++u) { + uint32_pack(buf,c->hash[u].h); + uint32_pack(buf + 4,c->hash[u].p); + if (buffer_putalign(&c->b,buf,8) == -1) return -1; + if (posplus(c,8) == -1) return -1; + } + } + + if (buffer_flush(&c->b) == -1) return -1; + if (seek_begin(c->fd) == -1) return -1; + return buffer_putflush(&c->b,c->final,sizeof(c->final)); +} diff --git a/src/cdbread.c b/src/cdbread.c new file mode 100644 index 0000000..8387591 --- /dev/null +++ b/src/cdbread.c @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include "error.h" +#include "seek.h" +#include "byte.h" +#include "cdbread.h" + +/** + * @file cdbread.c + * @author djb + * @ref ucspi-tcp, fastforward + * @brief read entries from a cdb + */ + +uint32 cdb_unpack(unsigned char *buf) +{ + uint32 num; + num = buf[3]; num <<= 8; + num += buf[2]; num <<= 8; + num += buf[1]; num <<= 8; + num += buf[0]; + return num; +} + +void cdb_free(struct cdb *c) +{ + if (c->map) { + munmap(c->map,c->size); + c->map = 0; + } +} + +void cdb_findstart(struct cdb *c) +{ + c->loop = 0; +} + +void cdb_init(struct cdb *c,int fd) +{ + struct stat st; + char *x; + + cdb_free(c); + cdb_findstart(c); + c->fd = fd; + + if (fstat(fd,&st) == 0) + if (st.st_size <= 0xffffffff) { + x = mmap(0,st.st_size,PROT_READ,MAP_SHARED,fd,0); + if (x + 1) { + c->size = st.st_size; + c->map = x; + } + } +} + +int cdb_read(struct cdb *c,char *buf,unsigned int len,uint32 pos) +{ + if (c->map) { + if ((pos > c->size) || (c->size - pos < len)) goto FORMAT; + byte_copy(buf,len,c->map + pos); + } + else { + if (seek_set(c->fd,pos) == -1) return -1; + while (len > 0) { + int r; + do + r = read(c->fd,buf,len); + while ((r == -1) && (errno == EINTR)); + if (r == -1) return -1; + if (r == 0) goto FORMAT; + buf += r; + len -= r; + } + } + return 0; + + FORMAT: + errno = EPROTO; + return -1; +} + +static int match(struct cdb *c,char *key,unsigned int len,uint32 pos) +{ + char buf[32]; + int n; + + while (len > 0) { + n = sizeof(buf); + if (n > len) n = len; + if (cdb_read(c,buf,n,pos) == -1) return -1; + if (byte_diff(buf,n,key)) return 0; + pos += n; + key += n; + len -= n; + } + return 1; +} + +int cdb_findnext(struct cdb *c,char *key,unsigned int len) +{ + char buf[8]; + uint32 pos; + uint32 u; + + if (!c->loop) { + u = cdb_hash(key,len); + if (cdb_read(c,buf,8,(u << 3) & 2047) == -1) return -1; + uint32_unpack(buf + 4,&c->hslots); + if (!c->hslots) return 0; + uint32_unpack(buf,&c->hpos); + c->khash = u; + u >>= 8; + u %= c->hslots; + u <<= 3; + c->kpos = c->hpos + u; + } + + while (c->loop < c->hslots) { + if (cdb_read(c,buf,8,c->kpos) == -1) return -1; + uint32_unpack(buf + 4,&pos); + if (!pos) return 0; + c->loop += 1; + c->kpos += 8; + if (c->kpos == c->hpos + (c->hslots << 3)) c->kpos = c->hpos; + uint32_unpack(buf,&u); + if (u == c->khash) { + if (cdb_read(c,buf,8,pos) == -1) return -1; + uint32_unpack(buf,&u); + if (u == len) + switch(match(c,key,len,pos + 8)) { + case -1: + return -1; + case 1: + uint32_unpack(buf + 4,&c->dlen); + c->dpos = pos + 8 + len; + return 1; + } + } + } + + return 0; +} + +int cdb_find(struct cdb *c,char *key,unsigned int len) +{ + cdb_findstart(c); + return cdb_findnext(c,key,len); +} + +uint32 cdb_hashadd(uint32 h,unsigned char c) +{ + h += (h << 5); + return h ^ c; +} + +uint32 cdb_hash(char *buf,unsigned int len) +{ + uint32 h; + + h = CDB_HASHSTART; + while (len) { + h = cdb_hashadd(h,*buf++); + --len; + } + return h; +} diff --git a/src/constmap.c b/src/constmap.c new file mode 100644 index 0000000..4b2eb87 --- /dev/null +++ b/src/constmap.c @@ -0,0 +1,178 @@ +#include "constmap.h" +#include "alloc.h" +#include "case.h" + +/** + * @file constmap.c + * @author djb + * @ref qmail + * @brief constant hash table + * @brief Attention! constmap is both function and struct + */ + + +static constmap_hash hash(char *s,int len) +{ + unsigned char ch; + constmap_hash h; + h = 5381; + while (len > 0) { + ch = *s++ - 'A'; + if (ch <= 'Z' - 'A') ch += 'a' - 'A'; + h = ((h << 5) + h) ^ ch; + --len; + } + return h; +} + +char *constmap(struct constmap *cm,char *s,int len) +{ + constmap_hash h; + int pos; + h = hash(s,len); + pos = cm->first[h & cm->mask]; + while (pos != -1) { + if (h == cm->hash[pos]) + if (len == cm->inputlen[pos]) + if (!case_diffb(cm->input[pos],len,s)) + return cm->input[pos] + cm->inputlen[pos] + 1; + pos = cm->next[pos]; + } + return 0; +} + +int constmap_init(struct constmap *cm,char *s,int len,int flagcolon) +{ + int i; + int j; + int k; + int pos; + constmap_hash h; + + cm->num = 0; + for (j = 0; j < len; ++j) if (!s[j]) ++cm->num; + + h = 64; + while (h && (h < cm->num)) h += h; + cm->mask = h - 1; + + cm->first = (int *) alloc(sizeof(int) * h); + if (cm->first) { + cm->input = (char **) alloc(sizeof(char *) * cm->num); + if (cm->input) { + cm->inputlen = (int *) alloc(sizeof(int) * cm->num); + if (cm->inputlen) { + cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num); + if (cm->hash) { + cm->next = (int *) alloc(sizeof(int) * cm->num); + if (cm->next) { + for (h = 0; h <= cm->mask; ++h) + cm->first[h] = -1; + pos = 0; + i = 0; + for (j = 0; j < len; ++j) + if (!s[j]) { + k = j - i; + if (flagcolon) { + for (k = i; k < j; ++k) + if (s[k] == ':') break; + if (k >= j) { i = j + 1; continue; } + k -= i; + } + cm->input[pos] = s + i; + cm->inputlen[pos] = k; + h = hash(s + i,k); + cm->hash[pos] = h; + h &= cm->mask; + cm->next[pos] = cm->first[h]; + cm->first[h] = pos; + ++pos; + i = j + 1; + } + return 1; + } + alloc_free(cm->hash); + } + alloc_free(cm->inputlen); + } + alloc_free(cm->input); + } + alloc_free(cm->first); + } + return 0; +} + +int constmap_init_char(struct constmap *cm,char *s,int len,int flagcolon,char flagchar) +{ + int i; + int j; + int k; + int pos; + constmap_hash h; + + if (!flagchar || flagchar == 0 || flagchar == '\0') { + flagchar = ':'; + } + + cm->num = 0; + for (j = 0; j < len; ++j) if (!s[j]) ++cm->num; + + h = 64; + while (h && (h < cm->num)) h += h; + cm->mask = h - 1; + + cm->first = (int *) alloc(sizeof(int) * h); + if (cm->first) { + cm->input = (char **) alloc(sizeof(char *) * cm->num); + if (cm->input) { + cm->inputlen = (int *) alloc(sizeof(int) * cm->num); + if (cm->inputlen) { + cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num); + if (cm->hash) { + cm->next = (int *) alloc(sizeof(int) * cm->num); + if (cm->next) { + for (h = 0; h <= cm->mask; ++h) + cm->first[h] = -1; + pos = 0; + i = 0; + for (j = 0; j < len; ++j) { + if (!s[j]) { + k = j - i; + if (flagcolon) { + for (k = i; k < j; ++k) + if (s[k] == flagchar) break; + if (k >= j) { i = j + 1; continue; } + k -= i; + } + cm->input[pos] = s + i; + cm->inputlen[pos] = k; + h = hash(s + i,k); + cm->hash[pos] = h; + h &= cm->mask; + cm->next[pos] = cm->first[h]; + cm->first[h] = pos; + ++pos; + i = j + 1; + } + } + return 1; + } + alloc_free(cm->hash); + } + alloc_free(cm->inputlen); + } + alloc_free(cm->input); + } + alloc_free(cm->first); + } + return 0; +} + +void constmap_free(struct constmap *cm) +{ + alloc_free(cm->next); + alloc_free(cm->hash); + alloc_free(cm->inputlen); + alloc_free(cm->input); + alloc_free(cm->first); +} diff --git a/src/dnsstub/Makefile b/src/dnsstub/Makefile new file mode 100644 index 0000000..c4ca883 --- /dev/null +++ b/src/dnsstub/Makefile @@ -0,0 +1,24 @@ +# dnsstub Makefile + +COMPILE=../../compile +MAKELIB=../../makelib +CCFLAGS=-I../../include + +default: clean check dnsresolv.a + +check: + @[ -f $(COMPILE) ] && [ -f $(MAKELIB) ] || ( cd ../../ ; ./configure ; ) + +clean: + rm -f `cat TARGETS` + +dnsresolv.a: \ +dns_domain.c dns_dtda.c dns_ip.c dns_ipq.c dns_name.c \ +dns_nd.c dns_packet.c dns_random.c dns_rcip.c dns_rcrw.c dns_resolve.c \ +dns_sortip.c dns_transmit.c dns_txt.c + $(COMPILE) $(CCFLAGS) dns_domain.c dns_dfd.c dns_dtda.c dns_ip.c dns_ipq.c \ + dns_mx.c dns_name.c dns_nd.c dns_packet.c dns_random.c dns_rcip.c \ + dns_rcrw.c dns_resolve.c dns_sortip.c dns_transmit.c dns_txt.c dns_cname.c + $(MAKELIB) dnsresolv.a dns_domain.o dns_dfd.o dns_dtda.o dns_ip.o dns_ipq.o \ + dns_mx.o dns_name.o dns_nd.o dns_packet.o dns_random.o dns_rcip.o \ + dns_rcrw.o dns_resolve.o dns_sortip.o dns_transmit.o dns_txt.o dns_cname.o diff --git a/src/dnsstub/README.md b/src/dnsstub/README.md new file mode 100644 index 0000000..f2543f3 --- /dev/null +++ b/src/dnsstub/README.md @@ -0,0 +1,169 @@ +DJBDNS Stub Resolver +==================== + +Simple DJBDNS stub-resolver based on 'djbdns-1.05(IPv6)' allowing for each +calling application individually to include up to 16 DNSCACHEIP(s) +as DNS forwarding/resolving servers to be tried sequentially. + +IP Addresses +------------ + +Here, + - global IPv6, + - IPv6 ULA, and + - IPv6 LLU addresses with a given Interface-Id +can be specified. The IPv4 format could be either a + - legacy dotted-decimal or a + - IPv4-mapped IPv6 address. + +In any case, compactified IPv6 addresses are understood. +IPv4/IPv6 addresses in brackets are understood by dns_ip. + +Resolver Call +------------- + +If $DNSCACHEIP is not provided as environment variable, the stub-resolver +will use the system-wide + - /etc/resolv.conf +file; however now without the capability for IPv6 LLU addresses. +While IPv4-mapped IPv6 addresses are supported here by default as well, +care has to taken not to jeopardize other client's usage. + +Name Qualification +------------------ + +If provided, the stub-resolver uses either a system-wide configuration file + - /etc/dnsrewritefile or assumes this file to available as given in + - $DNSREWRITEFILE +in order to define persistent mapping-rules of local domain names to public +ones (for lookup) or IP addresses (for direct matching). + +Well-known domain names 'localhost', 'ip4-loopback' and 'ip6-loopback' +are handled locally, thus no DNS query is used (RFC 6761). +'localhost' is advertised as '::1' and '::ff:127.0.0.1' in it's native +IPv6 format. It is up to the caller to convert the IPv6-mapped IPv4 +address to the IPv4 format. + +Local domain names can be alternatively specified (per application) using +the environment variable + - $LOCALDOMAIN +to be appended to unqualified hostnames dynamically. This is roughly equivalent +with the 'search' string in /etc/resolv. Several domains names may be +specified within $LOCALDOMAIN separated by blanks. + +See: https://cr.yp.to/djbdns/qualify.html + + +Specific DNS Record type lookup +------------------------------- + +* dns_ip (A, AAAAA) +* dns_name (PTR) +* dns_cname (CNAME) +* dns_txt (TXT) -- now considering several 'labels' +* dns_mx (MX) + + +Internals +--------- + +* UDP message size: +Unlike other implementations, this DNS stub-resolver supports UDP packet +sizes up to 1028 byte without the need for (E)DNS0 packet enhancements. + +* DNS UDP query retrials: +In case the NS is not able to initally reply to the query, +it is retried again at the intervalls {1, 2, 4, 8, 16} secs. + +* DNS name qualification (dns_ip_qualify): +Well-known domain names are qualified locally without invoking a DNS query +while handling IPv4 and IPv6 addresses separately. + +* NS qualification/sorting for NS replies: +NS qualification is not supported (yet), thus we use a randomly sorted +list of NS IP addresses. + +* Query/Reply to/from DNS Cache servers/forwarders: +Neither message (CurveDNS) nor transport layer (TLS) encryption is provided; +the sub-resolver 'trusts' it's upstream caches/forwarders. We recommend to +setup communication on private IPv4/IPv6 addresses; if applicable. + +* DNS TXT Records: +The label substructure is now recognized in the RDATA section; +each label may have the size of 255 byte. +The length information is excluded from the output. +Only printable characters are recognized in the output. + +* Return Codes: +Different from DJB's initial routines, the DNS front-end routines + dns_cname*, dns_ip*, dns_mx*, dns_name*, dns dns_txt* +return now the number of replies received (not bytes!). +Thus, three cases need to be considered: + + - rc < 0: Problem occured (SOFTFAIL, HARDFAIL) + - rc = 0: No answer obtained (but query was successful) = NXDOMAIN + - rc > 0: rc answers received; positive reply + +For return codes < 0, the following conventions have been applied: + + include/dnsresolv.h + +\#define DNS_NXD 0 +\#define DNS_MEM -1 +\#define DNS_ERR -2 /* parsing errors and others */ +\#define DNS_COM -3 /* (socket) communication errors */ +\#define DNS_INT -4 /* internal errors */ +\#define DNS_SOFT -5 /* either -2 or -3 */ +\#define DNS_HARD -6 /* CNAME loop problem */ + +The modification of the return code is typically not problematic, +since mostly just rc = -1 is checked. + +In the future, these return codes are subject of change. +Thus, instead of + + if (dns_XX(...) == -1) + +one shoud use the more general syntax + + if (dns_XX(...) < 0) + +to check for 'negative' results, allowing further actions +and refinements given the calling sequence. + + + +Environment Variables Read +-------------------------- + +$DNSCACHEPIP The upstream resolver's IP[v4|v6] addresses (up to 32). + IPv6 LLU addresses may be suffixed with the interface name. +$DNSREWRITEFILE Alternate location for the system-wide + /etc/dnsrewrite +file +$LOCALDOMAIN Additional local domain name appended to unqualified + hostnames dynamically. + +Sample for the file /etc/dnsrewrite: + +\#annything.local -> me +\-.example.com:me +\# me -> 127.0.0.1 +\=me:127.0.0.1 +\# any.name.a -> any.name.af.mil +\*.a:.af.mil +\# any-name-without-dots -> any-name-without-dots.heaven.af.mil +\?:.heaven.af.mil +\# remove trailing dot +\*.: + +and DJB's explanations are given here: + +Instructions are followed in order, each at most once. There are four types of instructions: + +\=post:new means that the host name post is replaced by new. +\*post:new means that any name of the form prepost is replaced by prenew. +\?post:new means that any name of the form prepost, where pre does not contain dots or brackets, is replaced by prenew. +\-post:new means that any name of the form prepost is replaced by new. + +Erwin Hoffmann, June 2023. diff --git a/src/dnsstub/TARGETS b/src/dnsstub/TARGETS new file mode 100644 index 0000000..62f40be --- /dev/null +++ b/src/dnsstub/TARGETS @@ -0,0 +1,18 @@ +dns_cname.o +dns_dfd.o +dns_domain.o +dns_dtda.o +dns_ip.o +dns_ipq.o +dns_mx.o +dns_name.o +dns_nd.o +dns_packet.o +dns_random.o +dns_rcip.o +dns_rcrw.o +dns_resolve.o +dns_sortip.o +dns_transmit.o +dns_txt.o +dnsresolv.a diff --git a/src/dnsstub/dns_cname.c b/src/dnsstub/dns_cname.c new file mode 100644 index 0000000..3694bb0 --- /dev/null +++ b/src/dnsstub/dns_cname.c @@ -0,0 +1,59 @@ +#include "stralloc.h" +#include "uint_t.h" +#include "byte.h" +#include "ip.h" +#include "case.h" +#include "dnsresolv.h" + +/** + * @file dns_cname.c + * @author feh + * @brief DNS cname lookup +*/ + +static char *q = 0; + +int dns_cname_packet(stralloc *out,const char *buf,unsigned int len) +{ + unsigned int pos; + char header[12]; + uint16 numanswers; + uint16 datalen; + int ranswers = 0; + + if (!stralloc_copys(out,"")) return DNS_MEM; + + pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; + uint16_unpack_big(header + 6,&numanswers); + pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; + pos += 4; + + while (numanswers--) { + pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; + pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; + uint16_unpack_big(header + 8,&datalen); + if (byte_equal(header,2,DNS_T_CNAME)) + if (byte_equal(header + 2,2,DNS_C_IN)) { + if (!dns_packet_getname(buf,len,pos,&q)) return DNS_ERR; + if (dns_domain_todot_cat(out,q) <= 0) return DNS_ERR; + } + pos += datalen; + ++ranswers; + } + + return ranswers; +} + +int dns_cname(stralloc *out,stralloc *fqdn) +{ + int rc; + + if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; + if (dns_resolve(q,DNS_T_CNAME) < 0) return DNS_ERR; + if ((rc = dns_cname_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; + dns_transmit_free(&dns_resolve_tx); + dns_domain_free(&q); + if (case_equals(out->s,fqdn->s)) rc = -6; // loop DNS_HARD + + return rc; +} diff --git a/src/dnsstub/dns_dfd.c b/src/dnsstub/dns_dfd.c new file mode 100644 index 0000000..cf3ca61 --- /dev/null +++ b/src/dnsstub/dns_dfd.c @@ -0,0 +1,76 @@ +#include "error.h" +#include "alloc.h" +#include "byte.h" +#include "dnsresolv.h" + +/** + * @file dns_dfd.c + * @author djb + * @ref ucspi-tcp + * @brief domain name qualification (domain from dot) + */ + +int dns_domain_fromdot(char **out,const char *buf,unsigned int n) +{ + char label[63]; + unsigned int labellen = 0; /* <= sizeof label */ + char name[255]; + unsigned int namelen = 0; /* <= sizeof name */ + char ch; + char *x; + + errno = EPROTO; + + for (;;) { + if (!n) break; + ch = *buf++; --n; + if (ch == '.') { + if (labellen) { + if (namelen + labellen + 1 > sizeof(name)) return 0; + name[namelen++] = labellen; + byte_copy(name + namelen,labellen,label); + namelen += labellen; + labellen = 0; + } + continue; + } + if (ch == '\\') { // octal -> decimal + if (!n) break; + ch = *buf++; --n; + if ((ch >= '0') && (ch <= '7')) { + ch -= '0'; + if (n && (*buf >= '0') && (*buf <= '7')) { + ch <<= 3; + ch += *buf - '0'; + ++buf; --n; + if (n && (*buf >= '0') && (*buf <= '7')) { + ch <<= 3; + ch += *buf - '0'; + ++buf; --n; + } + } + } + } + if (labellen >= sizeof(label)) return 0; + label[labellen++] = ch; + } + + if (labellen) { + if (namelen + labellen + 1 > sizeof(name)) return 0; + name[namelen++] = labellen; + byte_copy(name + namelen,labellen,label); + namelen += labellen; + labellen = 0; + } + + if (namelen + 1 > sizeof(name)) return 0; + name[namelen++] = 0; + + x = alloc(namelen); + if (!x) return DNS_MEM; + byte_copy(x,namelen,name); + + if (*out) alloc_free(*out); + *out = x; + return 1; +} diff --git a/src/dnsstub/dns_domain.c b/src/dnsstub/dns_domain.c new file mode 100644 index 0000000..44de835 --- /dev/null +++ b/src/dnsstub/dns_domain.c @@ -0,0 +1,80 @@ +#include "alloc.h" +#include "case.h" +#include "byte.h" +#include "dnsresolv.h" + +/** + * @file dns_domain.c + * @author djb + * @ref ucspi-tcp + * @brief domain qualification + */ + +unsigned int dns_domain_length(const char *dn) +{ + const char *x; + unsigned char c; + + x = dn; + while ((c = *x++)) + x += (unsigned int) c; + return x - dn; +} + +void dns_domain_free(char **out) +{ + if (*out) { + alloc_free(*out); + *out = 0; + } +} + +int dns_domain_copy(char **out,const char *in) +{ + unsigned int len; + char *x; + + len = dns_domain_length(in); + x = alloc(len); + if (!x) return 0; + byte_copy(x,len,in); + if (*out) alloc_free(*out); + *out = x; + return 1; +} + +int dns_domain_equal(const char *dn1,const char *dn2) +{ + unsigned int len; + + len = dns_domain_length(dn1); + if (len != dns_domain_length(dn2)) return 0; + + if (case_diffb((char *)dn1,len,(char *)dn2)) return 0; /* safe since 63 < 'A' */ + return 1; +} + +int dns_domain_suffix(const char *big,const char *little) +{ + unsigned char c; + + for (;;) { + if (dns_domain_equal(big,little)) return 1; + c = *big++; + if (!c) return 0; + big += c; + } +} + +unsigned int dns_domain_suffixpos(const char *big,const char *little) +{ + const char *orig = big; + unsigned char c; + + for (;;) { + if (dns_domain_equal(big,little)) return big - orig; + c = *big++; + if (!c) return 0; + big += c; + } +} diff --git a/src/dnsstub/dns_dtda.c b/src/dnsstub/dns_dtda.c new file mode 100644 index 0000000..f20ace2 --- /dev/null +++ b/src/dnsstub/dns_dtda.c @@ -0,0 +1,43 @@ +#include "stralloc.h" +#include "dnsresolv.h" + +/** + * @file dns_dtda.c + * @author djb + * @ref ucspi-tcp + * @brief domain to dot append + */ + +int dns_domain_todot_cat(stralloc *out,const char *d) +{ + char ch; + char ch2; + unsigned char ch3; + char buf[4]; + + if (!*d) + return stralloc_append(out,"."); + + for (;;) { + ch = *d++; + while (ch--) { + ch2 = *d++; + if ((ch2 >= 'A') && (ch2 <= 'Z')) ch2 += 32; // FQDN -> lowercase + if (((ch2 >= 'a') && (ch2 <= 'z')) || + ((ch2 >= '0') && (ch2 <= '9')) || + (ch2 == '-') || (ch2 == '_')) { + if (!stralloc_append(out,&ch2)) return DNS_MEM; + } + else { // decimal -> octal + ch3 = ch2; + buf[3] = '0' + (ch3 & 7); ch3 >>= 3; + buf[2] = '0' + (ch3 & 7); ch3 >>= 3; + buf[1] = '0' + (ch3 & 7); + buf[0] = '\\'; + if (!stralloc_catb(out,buf,4)) return DNS_MEM; + } + } + if (!*d) return 1; + if (!stralloc_append(out,".")) return DNS_MEM; + } +} diff --git a/src/dnsstub/dns_ip.c b/src/dnsstub/dns_ip.c new file mode 100644 index 0000000..74bc24f --- /dev/null +++ b/src/dnsstub/dns_ip.c @@ -0,0 +1,198 @@ +#include "stralloc.h" +#include "uint_t.h" +#include "byte.h" +#include "ip.h" +#include "dnsresolv.h" + +/** + * @file dns_ip.c + * @authors djb, fefe, feh + * @ref ucspi-tcp6 + * @brief DNS IP query + */ + +static char *q = 0; + +int dns_ip4_packet(stralloc *out,const char *buf,unsigned int len) +{ + unsigned int pos; + char header[12]; + uint16 numanswers; + uint16 datalen; + int ranswers = 0; + + if (!stralloc_copys(out,"")) return DNS_MEM; + + pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; + uint16_unpack_big(header + 6,&numanswers); + pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; + pos += 4; + + while (numanswers--) { + pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; + pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; + uint16_unpack_big(header + 8,&datalen); + if (byte_equal(header,2,DNS_T_A)) + if (byte_equal(header + 2,2,DNS_C_IN)) + if (datalen == 4) { + if (!dns_packet_copy(buf,len,pos,header,4)) return DNS_ERR; + if (!stralloc_catb(out,header,4)) return DNS_MEM; + } + pos += datalen; + ++ranswers; + } + + dns_sortip4(out->s,out->len); + return ranswers; +} + +int dns_ip4(stralloc *out,stralloc *fqdn) +{ + unsigned int i; + char code = 0; + int dot = 0; + char ch; + char ip[4]; + int r; + int rc = 0; + + if (!stralloc_copys(out,"")) return DNS_MEM; + if (!stralloc_readyplus(fqdn,1)) return DNS_MEM; + + fqdn->s[fqdn->len] = 0; /* test FQDN string */ + for (i = 1; i < fqdn->len; i++) { + if (fqdn->s[i] >= '_') { code = 127; break; } + if (fqdn->s[i] == '.') dot++; + } + + if (code != 127 && dot == 3) /* if FQDN is just IPv4 */ + if (ip4_scan(fqdn->s,ip) || ip4_scanbracket(fqdn->s,ip)) { + if (!stralloc_copyb(out,ip,4)) return DNS_MEM; + return 1; + } + + code = 0; + for (i = 0; i <= fqdn->len; ++i) { + if (i < fqdn->len) + ch = fqdn->s[i]; + else + ch = '.'; + + if ((ch == '[') || (ch == ']')) continue; + if (ch == '.') { + if (!stralloc_append(out,&code)) return DNS_MEM; + code = 0; + continue; + } + if ((ch >= '0') && (ch <= '9')) { + code *= 10; + code += ch - '0'; + continue; + } + + if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; // fdqn -> A query -> response + if (dns_resolve(q,DNS_T_A) >= 0) { + if ((r = dns_ip4_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; + dns_transmit_free(&dns_resolve_tx); + dns_domain_free(&q); + rc += r; + } + + return rc; + } + + out->len &= ~3; + return 0; +} + +int dns_ip6_packet(stralloc *out,const char *buf,unsigned int len) +{ + unsigned int pos; + char header[16]; + uint16 numanswers; + uint16 datalen; + int ranswers = 0; + + if (!stralloc_copys(out,"")) return DNS_MEM; + + pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; + uint16_unpack_big(header + 6,&numanswers); + pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; + pos += 4; + + while (numanswers--) { + pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; + pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; + uint16_unpack_big(header + 8,&datalen); + if (byte_equal(header,2,DNS_T_AAAA)) { + if (byte_equal(header + 2,2,DNS_C_IN)) + if (datalen == 16) { + if (!dns_packet_copy(buf,len,pos,header,16)) return DNS_ERR; + if (!stralloc_catb(out,header,16)) return DNS_MEM; + } + } else if (byte_equal(header,2,DNS_T_A)) + if (byte_equal(header + 2,2,DNS_C_IN)) + if (datalen == 4) { + byte_copy(header,12,V4mappedprefix); + if (!dns_packet_copy(buf,len,pos,header + 12,4)) return DNS_ERR; + if (!stralloc_catb(out,header,16)) return DNS_MEM; + } + pos += datalen; + ++ranswers; + } + + dns_sortip6(out->s,out->len); + return ranswers; +} + +int dns_ip6(stralloc *out,stralloc *fqdn) +{ + unsigned int i; + char code; + char ch; + char ip[16]; + int r; + int rc = 0; + + if (!stralloc_copys(out,"")) return DNS_MEM; + if (!stralloc_readyplus(fqdn,1)) return DNS_MEM; + + fqdn->s[fqdn->len] = 0; /* if FQDN is just IPv6 */ + if (ip6_scan(fqdn->s,ip) || ip6_scanbracket(fqdn->s,ip)) { + if (!stralloc_copyb(out,ip,16)) return DNS_MEM; + return 1; + } + + code = 0; + for (i = 0; i <= fqdn->len; ++i) { + if (i < fqdn->len) + ch = fqdn->s[i]; + else + ch = '.'; + + if ((ch == '[') || (ch == ']')) continue; + if (ch == '.') { + if (!stralloc_append(out,&code)) return DNS_MEM; + code = 0; + continue; + } + if ((ch >= '0') && (ch <= '9')) { + code *= 10; + code += ch - '0'; + continue; + } + + if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; // fqdn -> AAAA query -> response + if (dns_resolve(q,DNS_T_AAAA) >= 0) { + if ((r = dns_ip6_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; + dns_transmit_free(&dns_resolve_tx); + dns_domain_free(&q); + rc += r; + } + + return rc; + } + + out->len &= ~3; + return 0; +} diff --git a/src/dnsstub/dns_ipq.c b/src/dnsstub/dns_ipq.c new file mode 100644 index 0000000..f298128 --- /dev/null +++ b/src/dnsstub/dns_ipq.c @@ -0,0 +1,235 @@ +#include "case.h" +#include "byte.h" +#include "str.h" +#include "stralloc.h" +#include "dnsresolv.h" +#include "socket_if.h" +#include "ip.h" + +/** + * @file dns_ipq.c + * @authors djb, feh + * @ref ucspi-tcp + * @brief DNS hostname qualification for ipv4 and ipv6 + */ + +/** @fn int doit -> @return number of added chars to name */ + +static int doit(stralloc *work,const char *rule) +{ + char ch; + unsigned int colon; + unsigned int prefixlen; + + ch = *rule++; + if ((ch != '?') && (ch != '=') && (ch != '*') && (ch != '-')) return 1; + colon = str_chr((char *)rule,':'); + if (!rule[colon]) return 1; + + if (work->len < colon) return 1; + prefixlen = work->len - colon; + if ((ch == '=') && prefixlen) return 1; + if (case_diffb((char *)rule,colon,work->s + prefixlen)) return 1; + if (ch == '?') { + if (byte_chr(work->s,prefixlen,'.') < prefixlen) return 1; + if (byte_chr(work->s,prefixlen,'[') < prefixlen) return 1; + if (byte_chr(work->s,prefixlen,']') < prefixlen) return 1; + } + + work->len = prefixlen; + if (ch == '-') work->len = 0; + return stralloc_cats(work,rule + colon + 1); +} + +/** @fn int dns_ip4_qualify_rules -> @return number of IPv4 addresss with rules */ + +int dns_ip4_qualify_rules(stralloc *ipout,stralloc *fqdn,const stralloc *in,const stralloc *rules) +{ + unsigned int i; + unsigned int j; + unsigned int plus; + unsigned int fqdnlen; + int rc = 0; + + if (!stralloc_copy(fqdn,(stralloc *)in)) return DNS_MEM; + + for (j = i = 0; j < rules->len; ++j) + if (!rules->s[j]) { + if (!doit(fqdn,rules->s + i)) return DNS_INT; + i = j + 1; + } + + fqdnlen = fqdn->len; + plus = byte_chr(fqdn->s,fqdnlen,'+'); + if (plus >= fqdnlen) + return dns_ip4(ipout,fqdn); + + i = plus + 1; + for (;;) { + j = byte_chr(fqdn->s + i,fqdnlen - i,'+'); + byte_copy(fqdn->s + plus,j,fqdn->s + i); + fqdn->len = plus + j; + if (rc += dns_ip4(ipout,fqdn) < 0) return DNS_ERR; + i += j; + if (i >= fqdnlen) return rc; + ++i; + } + return 0; +} + +/** @fn int dns_ip4_qualify -> @return number of IPv4 addresss qualified */ + +int dns_ip4_qualify(stralloc *ipout,stralloc *fqdn,const stralloc *in) +{ + int r; + static stralloc rules; + + if ((r = dns_ip_qualify_localhost(ipout,fqdn,in)) > 0 ) return r; + if (dns_resolvconfrewrite(&rules) < 0) return DNS_INT; + return dns_ip4_qualify_rules(ipout,fqdn,in,&rules); +} + +/** @fn int dns_ip4_qualify_rules -> @return number of IPv6 addresss with rules */ + +int dns_ip6_qualify_rules(stralloc *ipout,stralloc *fqdn,const stralloc *in,const stralloc *rules) +{ + unsigned int i; + unsigned int j; + unsigned int plus; + unsigned int fqdnlen; + int rc = 0; + + if (!stralloc_copy(fqdn,(stralloc *)in)) return DNS_MEM; + + for (j = i = 0; j < rules->len; ++j) + if (!rules->s[j]) { + if (!doit(fqdn,rules->s + i)) return DNS_INT; + i = j + 1; + } + + fqdnlen = fqdn->len; + plus = byte_chr(fqdn->s,fqdnlen,'+'); + if (plus >= fqdnlen) + return dns_ip6(ipout,fqdn); + + i = plus + 1; + for (;;) { + j = byte_chr(fqdn->s + i,fqdnlen - i,'+'); + byte_copy(fqdn->s + plus,j,fqdn->s + i); + fqdn->len = plus + j; + if ((rc += dns_ip6(ipout,fqdn)) < 0) return DNS_ERR; + i += j; + if (i >= fqdnlen) return rc; + ++i; + } + return 0; +} + +/** @fn int dns_ip6_qualify -> @return number of IPv6 addresss qualified */ + +int dns_ip6_qualify(stralloc *ipout,stralloc *fqdn,const stralloc *in) +{ + int r; + static stralloc rules; + + if ((r = dns_ip_qualify_localhost(ipout,fqdn,in)) > 0) return r; + if (dns_resolvconfrewrite(&rules) < 0) return DNS_INT; + return dns_ip6_qualify_rules(ipout,fqdn,in,&rules); +} + +/** @fn int dns_ip_qualify_rules -> @return number of IPv6+IPv4 addresss with rules */ + +int dns_ip_qualify_rules(stralloc *ipout,stralloc *fqdn,const stralloc *in,const stralloc *rules) +{ + unsigned int i; + unsigned int j; + unsigned int k; + unsigned int plus; + unsigned int fqdnlen; + stralloc tmp = {0}; + int rc = 0; + + if (!stralloc_copy(fqdn,(stralloc *)in)) return DNS_MEM; + if (!stralloc_copys(ipout,"")) return DNS_MEM; + + for (j = i = 0; j < rules->len; ++j) + if (!rules->s[j]) { + if (!doit(fqdn,rules->s + i)) return DNS_INT; + i = j + 1; + } + + fqdnlen = fqdn->len; + plus = byte_chr(fqdn->s,fqdnlen,'+'); + if (plus >= fqdnlen) { + rc = dns_ip6(ipout,fqdn); + if (dns_ip4(&tmp,fqdn) > 0) { + for (k = 0; k < tmp.len; k += 4) { + if (!stralloc_catb(ipout,(const char *) V4mappedprefix,12)) return DNS_MEM; + if (!stralloc_catb(ipout,tmp.s + k,4)) return DNS_MEM; + rc++; + } + } + return rc; + } + + i = plus + 1; + for (;;) { + j = byte_chr(fqdn->s + i,fqdnlen - i,'+'); + byte_copy(fqdn->s + plus,j,fqdn->s + i); + fqdn->len = plus + j; + if (!stralloc_copys(ipout,"")) return DNS_MEM; + rc = dns_ip6(&tmp,fqdn); + if (rc) if (!stralloc_cat(ipout,&tmp)) return DNS_MEM; + if (dns_ip4(&tmp,fqdn) > 0) { + for (k = 0; k < tmp.len; k += 4) { + if (!stralloc_catb(ipout,(const char *) V4mappedprefix,12)) return DNS_MEM; + if (!stralloc_catb(ipout,tmp.s + k,4)) return DNS_MEM; + rc++; + } + } + + if (rc < 0) return DNS_ERR; + i += j; + if (i >= fqdnlen) return rc; + ++i; + } + return 0; +} + +/** @fn int dns_ip_qualify_localhost -> @return number of IP addresss */ + +int dns_ip_qualify_localhost(stralloc *ipout,stralloc *fqdn,const stralloc *in) +{ + if (!stralloc_copys(ipout,"")) return DNS_MEM; + if (!stralloc_copys(fqdn,"")) return DNS_MEM; + ipout->len = 0; + + if (byte_equal(in->s,9,LOCALHOST)) { + if (!stralloc_copyb(ipout,(const char *) V6loopback,16)) return DNS_MEM; + if (!stralloc_catb(ipout,(const char *) V46loopback,16)) return DNS_MEM; + if (!stralloc_copys(fqdn,"localhost.localhost.")) return DNS_MEM; + } + if (byte_equal(in->s,13,IP4_LOOPBACK)) { + if (!stralloc_copyb(ipout,(const char *) V46loopback,16)) return DNS_MEM; + if (!stralloc_copys(fqdn,"ip4-loopback.localhost.")) return DNS_MEM; + } + if (byte_equal(in->s,13,IP6_LOOPBACK)) { + if (!stralloc_copyb(ipout,(const char *) V6loopback,16)) return DNS_MEM; + if (!stralloc_copys(fqdn,"ip6-loopback.localhost.")) return DNS_MEM; + } +// if (!stralloc_0(fqdn)) return DNS_MEM; // don't do it + + return ipout->len ? ipout->len % 15 : 0; +} + +/** @fn int dns_ip_qualify -> @return number of IP addresss */ + +int dns_ip_qualify(stralloc *ipout,stralloc *fqdn,const stralloc *in) +{ + int r; + static stralloc rules; + + if ((r = dns_ip_qualify_localhost(ipout,fqdn,in)) > 0 ) return r; + if (dns_resolvconfrewrite(&rules) < 0) return DNS_INT; + return dns_ip_qualify_rules(ipout,fqdn,in,&rules); +} diff --git a/src/dnsstub/dns_mx.c b/src/dnsstub/dns_mx.c new file mode 100644 index 0000000..ab321ec --- /dev/null +++ b/src/dnsstub/dns_mx.c @@ -0,0 +1,63 @@ +#include "stralloc.h" +#include "byte.h" +#include "uint_t.h" +#include "dnsresolv.h" + +/** + * @file dns_mx.c + * @author djb + * @ref qmail + * @brief dns MX query + * @param (on output) stralloc out + */ + +static char *q = 0; + +int dns_mx_packet(stralloc *out,const char *buf,unsigned int len) +{ + unsigned int pos; + char header[12]; + char pref[2]; + uint16 numanswers; + uint16 datalen; + int ranswers = 0; + + if (!stralloc_copys(out,"")) return DNS_MEM; + + pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; + uint16_unpack_big(header + 6,&numanswers); + pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; + pos += 4; + + while (numanswers--) { + pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; + pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; + uint16_unpack_big(header + 8,&datalen); + if (byte_equal(header,2,DNS_T_MX)) + if (byte_equal(header + 2,2,DNS_C_IN)) { + if (!dns_packet_copy(buf,len,pos,pref,2)) return DNS_ERR; + if (!dns_packet_getname(buf,len,pos + 2,&q)) return DNS_ERR; + if (!stralloc_catb(out,pref,2)) return DNS_MEM; + if (dns_domain_todot_cat(out,q) <= 0) return DNS_ERR; + if (!stralloc_0(out)) return DNS_MEM; + } + pos += datalen; + ++ranswers; + } + + return ranswers; +} + +int dns_mx(stralloc *out,const stralloc *fqdn) +{ + int rc = 0; + + if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; + if (dns_resolve(q,DNS_T_MX) >= 0) { + if ((rc = dns_mx_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; + dns_transmit_free(&dns_resolve_tx); + dns_domain_free(&q); + } + + return rc; +} diff --git a/src/dnsstub/dns_name.c b/src/dnsstub/dns_name.c new file mode 100644 index 0000000..a53b5a5 --- /dev/null +++ b/src/dnsstub/dns_name.c @@ -0,0 +1,80 @@ +#include "stralloc.h" +#include "uint_t.h" +#include "byte.h" +#include "ip.h" +#include "dnsresolv.h" + +/** + * @file dns_name.c + * @authors djb, fefe, feh + * @ref ucspi-tcp + * @brief DNS name query (ptr) + */ + +static char *q = 0; + +int dns_name_packet(stralloc *out,const char *buf,unsigned int len) +{ + unsigned int pos; + char header[12]; + uint16 numanswers; + uint16 datalen; + + if (!stralloc_copys(out,"")) return DNS_MEM; + + pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; + uint16_unpack_big(header + 6,&numanswers); + pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; + pos += 4; + + while (numanswers--) { + pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; + pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; + uint16_unpack_big(header + 8,&datalen); + if (byte_equal(header,2,DNS_T_PTR)) + if (byte_equal(header + 2,2,DNS_C_IN)) { + if (!dns_packet_getname(buf,len,pos,&q)) return DNS_ERR; + if (dns_domain_todot_cat(out,q) <= 0) return DNS_ERR; + return 1; + } + pos += datalen; + } + + return 0; +} + +int dns_name4(stralloc *out,const char ip[4]) +{ + int rc; + char name[DNS_NAME4_DOMAIN]; + + dns_name4_domain(name,ip); + if (dns_resolve(name,DNS_T_PTR) < 0) return DNS_ERR; + if ((rc = dns_name_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; + dns_transmit_free(&dns_resolve_tx); + dns_domain_free(&q); + + return rc; +} + +int dns_name6(stralloc *out,const char ip[16]) +{ + int rc; + char name[DNS_NAME6_DOMAIN]; + + dns_name6_domain(name,ip); + if (dns_resolve(name,DNS_T_PTR) < 0) return DNS_ERR; + if ((rc = dns_name_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; + dns_transmit_free(&dns_resolve_tx); + dns_domain_free(&q); + + return rc; +} + +int dns_name(stralloc *out,const char ip[16]) +{ + if (ip6_isv4mapped(ip)) + return dns_name4(out,ip+12); + else + return dns_name6(out,ip); +} diff --git a/src/dnsstub/dns_nd.c b/src/dnsstub/dns_nd.c new file mode 100644 index 0000000..bdef42b --- /dev/null +++ b/src/dnsstub/dns_nd.c @@ -0,0 +1,48 @@ +#include "byte.h" +#include "fmt.h" +#include "ip.h" +#include "dnsresolv.h" + +/** + * @file dns_nd.c + * @authors djb, fefe + * @ref ucspi-tcp + * @brief DNS domain name for ip (wire format) + */ + +int dns_name4_domain(char name[DNS_NAME4_DOMAIN],const char ip[4]) +{ + unsigned int namelen; + unsigned int i; + + namelen = 0; + i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[3]); + name[namelen++] = i; + namelen += i; + i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[2]); + name[namelen++] = i; + namelen += i; + i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[1]); + name[namelen++] = i; + namelen += i; + i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[0]); + name[namelen++] = i; + namelen += i; + byte_copy(name + namelen,14,"\7in-addr\4arpa\0"); + return namelen+14; +} + +int dns_name6_domain(char name[DNS_NAME6_DOMAIN],const char ip[16]) +{ + unsigned int j; + + for (j = 0; j < 16; j++) { + name[j * 4] = 1; + name[j * 4 + 1] = tohex(ip[15 - j] & 15); + name[j * 4 + 2] = 1; + name[j * 4 + 3] = tohex((unsigned char)ip[15 - j] >> 4); + } + byte_copy(name + 4 * 16,10,"\3ip6\4arpa\0"); + return 4 * 16 + 10; +} + diff --git a/src/dnsstub/dns_packet.c b/src/dnsstub/dns_packet.c new file mode 100644 index 0000000..b131635 --- /dev/null +++ b/src/dnsstub/dns_packet.c @@ -0,0 +1,85 @@ +#include "error.h" +#include "dnsresolv.h" + +/** + * @file dns_packet.c + * @author djb + * @ref ucspi-tcp + * @brief DNS low level packet routine + * @brief DNS should have used LZ77 instead of its own sophomoric compression algorithm. + */ + +unsigned int dns_packet_copy(const char *buf,unsigned int len,unsigned int pos,char *out,unsigned int outlen) +{ + while (outlen) { + if (pos >= len) { errno = EPROTO; return 0; } + *out = buf[pos++]; + ++out; --outlen; + } + return pos; +} + +unsigned int dns_packet_skipname(const char *buf,unsigned int len,unsigned int pos) +{ + unsigned char ch; + + for (;;) { + if (pos >= len) break; + ch = buf[pos++]; + if (ch >= 192) return pos + 1; + if (ch >= 64) break; + if (!ch) return pos; + pos += ch; + } + + errno = EPROTO; + return 0; +} + +unsigned int dns_packet_getname(const char *buf,unsigned int len,unsigned int pos,char **d) +{ + unsigned int loop = 0; + unsigned int state = 0; + unsigned int firstcompress = 0; + unsigned int where; + unsigned char ch; + char name[255]; + unsigned int namelen = 0; + + for (;;) { + if (pos >= len) goto PROTO; + ch = buf[pos++]; + if (++loop >= 1000) goto PROTO; + + if (state) { + if (namelen + 1 > sizeof(name)) goto PROTO; + name[namelen++] = ch; + --state; + } else { + while (ch >= 192) { + where = ch; where -= 192; where <<= 8; + if (pos >= len) goto PROTO; + ch = buf[pos++]; + if (!firstcompress) firstcompress = pos; + pos = where + ch; + if (pos >= len) goto PROTO; + ch = buf[pos++]; + if (++loop >= 1000) goto PROTO; + } + if (ch >= 64) goto PROTO; + if (namelen + 1 > sizeof(name)) goto PROTO; + name[namelen++] = ch; + if (!ch) break; + state = ch; + } + } + + if (!dns_domain_copy(d,name)) return 0; + + if (firstcompress) return firstcompress; + return pos; + + PROTO: + errno = EPROTO; + return 0; +} diff --git a/src/dnsstub/dns_random.c b/src/dnsstub/dns_random.c new file mode 100644 index 0000000..c300f6a --- /dev/null +++ b/src/dnsstub/dns_random.c @@ -0,0 +1,70 @@ +#include +#include "taia.h" +#include "uint_t.h" +#include "dnsresolv.h" + +/** + * @file dns_random.c + * @author djb + * @ref ucspi-tcp + * @brief random use of DNS resolvers given their IP + */ + +static uint32 seed[32]; +static uint32 in[12]; +static uint32 out[8]; +static int outleft = 0; + +#define ROTATE(x,b) (((x) << (b)) | ((x) >> (32 - (b)))) +#define MUSH(i,b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x,b)); + +static void surf(void) +{ + uint32 t[12]; uint32 x; uint32 sum = 0; + int r; int i; int loop; + + for (i = 0; i < 12; ++i) t[i] = in[i] ^ seed[12 + i]; + for (i = 0; i < 8; ++i) out[i] = seed[24 + i]; + x = t[11]; + for (loop = 0; loop < 2; ++loop) { + for (r = 0; r < 16; ++r) { + sum += 0x9e3779b9; + MUSH(0,5) MUSH(1,7) MUSH(2,9) MUSH(3,13) + MUSH(4,5) MUSH(5,7) MUSH(6,9) MUSH(7,13) + MUSH(8,5) MUSH(9,7) MUSH(10,9) MUSH(11,13) + } + for (i = 0; i < 8; ++i) out[i] ^= t[i + 4]; + } +} + +void dns_random_init(const char data[128]) +{ + int i; + struct taia t; + char tpack[16]; + + for (i = 0; i < 32; ++i) + uint32_unpack((char *)data + 4 * i,seed + i); + + taia_now(&t); + taia_pack(tpack,&t); + for (i = 0; i < 4; ++i) + uint32_unpack(tpack + 4 * i,in + 4 + i); + + in[8] = getpid(); + in[9] = getppid(); + /* more space in 10 and 11, but this is probably enough */ +} + +unsigned int dns_random(unsigned int n) +{ + if (!n) return 0; + + if (!outleft) { + if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3]; + surf(); + outleft = 8; + } + + return out[--outleft] % n; +} diff --git a/src/dnsstub/dns_rcip.c b/src/dnsstub/dns_rcip.c new file mode 100644 index 0000000..97a1a6b --- /dev/null +++ b/src/dnsstub/dns_rcip.c @@ -0,0 +1,114 @@ +#include "taia.h" +#include "readclose.h" +#include "byte.h" +#include "ip.h" +#include "env.h" +#include "dnsresolv.h" +#include "socket_if.h" + +/** + * @file dns_rcip.c + * @author djb, fefe, feh + * @ref ucspi-tcp + * @brief DNS receive for query + */ + +static stralloc data = {0}; +static stralloc ifname = {0}; + +static int init(char ip[QUERY_MAXIPLEN],uint32 sid[QUERY_MAXNS]) +{ + int i; + int j; + int k = 0; + int iplen = 0; + char *x; + char ip4[4]; + +/* Read (compactified) IPv4|v6 addresses of resolvers + Store them in array IP with fixed length : + ip(64) -> 16 IPv4 addresses (not used anymore) + ip(512) -> 16*2 IPv6 addresses (we use IPv4 mapped IPv6 addresses) + sid(32) -> the scope for the respective IPv6 or 0 +*/ + for (i = 0; i < QUERY_MAXNS; ++i) sid[i] = 0; + + x = env_get("DNSCACHEIP"); + if (x) + while (iplen <= 240 && *x != '\0') { + if (*x == ' ') + ++x; + else + if ((i = ip6_ifscan(x,ip + iplen,&ifname))) { + if (ifname.len > 2) sid[k] = socket_getifidx(ifname.s); + iplen += 16; k++; + if (*(x += i) == '\0') break; + } + } + + if (!iplen) { + i = openreadclose("/etc/resolv.conf",&data,64); + if (i == -1) return DNS_INT; + if (i) { + if (!stralloc_append(&data,"\n")) return DNS_MEM; + i = 0; + for (j = 0; j < data.len; ++j) + if (data.s[j] == '\n') { + if (byte_equal("nameserver ",11,data.s + i) || byte_equal("nameserver\t",11,data.s + i)) { + i += 10; + while ((data.s[i] == ' ') || (data.s[i] == '\t')) + i++; + if (iplen <= 240) { + data.s[j] = '\0'; /* ip6_ifscan needs terminated string on input */ + if (ip4_scan(data.s + i,ip4)) { + if (byte_equal(ip4,4,"\0\0\0\0")) + byte_copy(ip4,4,"\177\0\0\1"); + byte_copy(ip + iplen,12,V4mappedprefix); + byte_copy(ip + iplen + 12,4,ip4); + sid[k] = 0; iplen += 16; k++; + } else if (ip6_ifscan(data.s + i,ip + iplen,&ifname)) { + if (ifname.len > 2) sid[k] = socket_getifidx(ifname.s); + iplen += 16; k++; + } + } + } + i = j + 1; + } + } + } + + if (!iplen) { + byte_copy(ip,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"); + iplen = 16; + } + byte_zero(ip + iplen,QUERY_MAXIPLEN - iplen); + return 0; +} + +static int ok = 0; +static unsigned int uses; +static struct taia deadline; +static char ip[QUERY_MAXIPLEN]; /* defined if ok */ +static uint32 scopes[QUERY_MAXNS]; + +int dns_resolvconfip(char s[QUERY_MAXIPLEN],uint32 scope[QUERY_MAXNS]) +{ + struct taia now; + + taia_now(&now); + if (taia_less(&deadline,&now)) ok = 0; + if (!uses) ok = 0; + + if (!ok) { + if (init(ip,scopes) < 0) return DNS_INT; + taia_uint(&deadline,600); + taia_add(&deadline,&now,&deadline); + uses = 10000; + ok = 1; + } + + --uses; + byte_copy(s,QUERY_MAXIPLEN,ip); + byte_copy(scope,128,scopes); + return 0; +} diff --git a/src/dnsstub/dns_rcrw.c b/src/dnsstub/dns_rcrw.c new file mode 100644 index 0000000..c0cad86 --- /dev/null +++ b/src/dnsstub/dns_rcrw.c @@ -0,0 +1,141 @@ +#include +#include "taia.h" +#include "env.h" +#include "byte.h" +#include "str.h" +#include "readclose.h" +#include "dnsresolv.h" + +/** + * @file dns_rcrw.c + * @author djb + * @ref ucspi-tcp + * @brief DNS receive rewrite + */ + +static stralloc data = {0}; + +static int init(stralloc *rules) +{ + char host[256]; + const char *x; + int i; + int j; + int k; + + if (!stralloc_copys(rules,"")) return DNS_MEM; + + x = env_get("DNSREWRITEFILE"); + if (!x) x = "/etc/dnsrewrite"; + + i = openreadclose(x,&data,64); + if (i == -1) return DNS_INT; + + if (i) { + if (!stralloc_append(&data,"\n")) return DNS_MEM; + i = 0; + for (j = 0; j < data.len; ++j) + if (data.s[j] == '\n') { + if (!stralloc_catb(rules,data.s + i,j - i)) return DNS_MEM; + while (rules->len) { + if (rules->s[rules->len - 1] != ' ') + if (rules->s[rules->len - 1] != '\t') + if (rules->s[rules->len - 1] != '\r') + break; + --rules->len; + } + if (!stralloc_0(rules)) return DNS_MEM; + i = j + 1; + } + return 0; + } + + x = env_get("LOCALDOMAIN"); + if (x) { + if (!stralloc_copys(&data,x)) return DNS_MEM; + if (!stralloc_append(&data," ")) return DNS_MEM; + if (!stralloc_copys(rules,"?:")) return DNS_MEM; + i = 0; + for (j = 0; j < data.len; ++j) + if (data.s[j] == ' ') { + if (!stralloc_cats(rules,"+.")) return DNS_MEM; + if (!stralloc_catb(rules,data.s + i,j - i)) return DNS_MEM; + i = j + 1; + } + if (!stralloc_0(rules)) return DNS_MEM; + if (!stralloc_cats(rules,"*.:")) return DNS_MEM; + if (!stralloc_0(rules)) return DNS_MEM; + return 0; + } + + i = openreadclose("/etc/resolv.conf",&data,64); + if (i == -1) return DNS_INT; + + if (i) { + if (!stralloc_append(&data,"\n")) return DNS_MEM; + i = 0; + for (j = 0; j < data.len; ++j) + if (data.s[j] == '\n') { + if (byte_equal("search ",7,data.s + i) || + byte_equal("search\t",7,data.s + i) || + byte_equal("domain ",7,data.s + i) || + byte_equal("domain\t",7,data.s + i)) { + if (!stralloc_copys(rules,"?:")) return DNS_MEM; + i += 7; + while (i < j) { + k = byte_chr(data.s + i,j - i,' '); + k = byte_chr(data.s + i,k,'\t'); + if (!k) { ++i; continue; } + if (!stralloc_cats(rules,"+.")) return DNS_MEM; + if (!stralloc_catb(rules,data.s + i,k)) return DNS_MEM; + i += k; + } + if (!stralloc_0(rules)) return DNS_MEM; + if (!stralloc_cats(rules,"*.:")) return DNS_MEM; + if (!stralloc_0(rules)) return DNS_MEM; + return 0; + } + i = j + 1; + } + } + + host[0] = 0; + if (gethostname(host,sizeof(host)) == -1) return DNS_ERR; + host[(sizeof(host)) - 1] = 0; + i = str_chr(host,'.'); + if (host[i]) { + if (!stralloc_copys(rules,"?:")) return DNS_MEM; + if (!stralloc_cats(rules,host + i)) return DNS_MEM; + if (!stralloc_0(rules)) return DNS_MEM; + } + if (!stralloc_cats(rules,"*.:")) return DNS_MEM; + if (!stralloc_0(rules)) return DNS_MEM; + + return 0; +} + +static int ok = 0; +static unsigned int uses; +static struct taia deadline; +static stralloc rules = {0}; /* defined if ok */ + +int dns_resolvconfrewrite(stralloc *out) +{ + struct taia now; + + taia_now(&now); + if (taia_less(&deadline,&now)) ok = 0; + if (!uses) ok = 0; + + if (!ok) { + if (init(&rules) < 0) return DNS_INT; + taia_uint(&deadline,600); + taia_add(&deadline,&now,&deadline); + uses = 10000; + ok = 1; + } + + --uses; + if (!stralloc_copy(out,&rules)) return DNS_MEM; + return 0; +} diff --git a/src/dnsstub/dns_resolve.c b/src/dnsstub/dns_resolve.c new file mode 100644 index 0000000..f2b845c --- /dev/null +++ b/src/dnsstub/dns_resolve.c @@ -0,0 +1,39 @@ +#include "iopause.h" +#include "taia.h" +#include "byte.h" +#include "ip.h" +#include "dnsresolv.h" + +/** + * @file dns_resolve.c + * @authors djb, fefe, feh + * @ref ucspi-tcp + * @brief high-level DNS resolve function + */ + +struct dns_transmit dns_resolve_tx = {0}; + +int dns_resolve(const char *q,const char qtype[2]) +{ + struct taia stamp; + struct taia deadline; + char servers[QUERY_MAXIPLEN]; + uint32 scopes[QUERY_MAXNS]; + iopause_fd x[1]; + int r; + + if (dns_resolvconfip(servers,scopes) < 0) return DNS_INT; + + if (dns_transmit_start6(&dns_resolve_tx,servers,1,q,qtype,(const char *)V6localnet,scopes) < 0) return DNS_COM; + + for (;;) { + taia_now(&stamp); + taia_uint(&deadline,120); + taia_add(&deadline,&deadline,&stamp); + dns_transmit_io(&dns_resolve_tx,x,&deadline); + iopause(x,1,&deadline,&stamp); + r = dns_transmit_get(&dns_resolve_tx,x,&stamp); + if (r < 0) return DNS_COM; + if (r == 1) return 0; + } +} diff --git a/src/dnsstub/dns_sortip.c b/src/dnsstub/dns_sortip.c new file mode 100644 index 0000000..38f5df2 --- /dev/null +++ b/src/dnsstub/dns_sortip.c @@ -0,0 +1,45 @@ +#include "byte.h" +#include "ip.h" +#include "dnsresolv.h" + +/** + * @file dns_sortip.c + * @authors djb, fefe, feh + * @ref ucspi-tcp6 + * @brief random sort of DNS servers per IP + */ + +/* XXX: sort servers by configurable notion of closeness? */ +/* XXX: pay attention to competence of each server? */ +/* XXX: pay attention to qualification (DNSSec, DNSCurve) of each server? */ +/* YYY: we use a randomly sorted list of NS; not depending on answer */ + +void dns_sortip4(char *s,unsigned int n) +{ + unsigned int i; + char tmp[4]; + + n >>= 2; /* 4 byte per IPv4 address */ + while (n > 1) { + i = dns_random(n); + --n; + byte_copy(tmp,4,s + (i << 2)); + byte_copy(s + (i << 2),4,s + (n << 2)); + byte_copy(s + (n << 2),4,tmp); + } +} + +void dns_sortip6(char *s,unsigned int n) +{ + unsigned int i; + char tmp[16]; + + n >>= 4; /* 16 byte per IPv4 address */ + while (n > 1) { + i = dns_random(n); + --n; + byte_copy(tmp,16,s + (i << 4)); + byte_copy(s + (i << 4),16,s + (n << 4)); + byte_copy(s + (n << 4),16,tmp); + } +} diff --git a/src/dnsstub/dns_transmit.c b/src/dnsstub/dns_transmit.c new file mode 100644 index 0000000..93cc896 --- /dev/null +++ b/src/dnsstub/dns_transmit.c @@ -0,0 +1,436 @@ +#include +#include +#include +#include "socket_if.h" +#include "alloc.h" +#include "error.h" +#include "byte.h" +#include "uint_t.h" +#include "ip.h" +#include "dnsresolv.h" + +/** + * @file dns_transmit.c + * @authors djb, fefe, feh + * @ref qlibs + * @brief DNS query function + * @brief scope_ids[32] -> 32 LLU root servers supported + */ + +#define DNSPORT 53 + +uint32 scope_ids[QUERY_MAXNS]; + +static const int timeouts[5] = { 1, 2, 4, 8, 16 }; /* quadratic, not exponentially */ + +int getscopeid(const struct dns_transmit *d,const char *ip) +{ + int i; + + if (byte_diff(ip,2,V6linklocal)) return 0; + for (i = 0; i < QUERY_MAXNS; ++i) + if (byte_equal(d->servers + 16 * i,16,ip)) + return scope_ids[i]; + + return 0; +} + +int serverwantstcp(const char *buf,unsigned int len) +{ + char out[12]; + + if (!dns_packet_copy(buf,len,0,out,12)) return 1; + if (out[2] & 2) return 1; + + return 0; +} + +int serverfailed(const char *buf,unsigned int len) +{ + char out[12]; + unsigned int rcode; + + if (!dns_packet_copy(buf,len,0,out,12)) return 1; + rcode = out[3]; + rcode &= 15; + if (rcode && (rcode != 3)) { errno = EAGAIN; return 1; } + + return 0; +} + +static int irrelevant(const struct dns_transmit *d,const char *buf,unsigned int len) +{ + char out[12]; + char *dn; + unsigned int pos; + + pos = dns_packet_copy(buf,len,0,out,12); if (!pos) return 1; + if (byte_diff(out,2,d->query + 2)) return 1; + if (out[4] != 0) return 1; + if (out[5] != 1) return 1; + + dn = 0; + pos = dns_packet_getname(buf,len,pos,&dn); if (!pos) return 1; + if (!dns_domain_equal(dn,d->query + 14)) { alloc_free(dn); return 1; } + alloc_free(dn); + + pos = dns_packet_copy(buf,len,pos,out,4); if (!pos) return 1; + if (byte_diff(out,2,d->qtype)) return 1; + if (byte_diff(out + 2,2,DNS_C_IN)) return 1; + + return 0; +} + +void packetfree(struct dns_transmit *d) +{ + if (!d->packet) return; + alloc_free(d->packet); + d->packet = 0; +} + +void queryfree(struct dns_transmit *d) +{ + if (!d->query) return; + alloc_free(d->query); + d->query = 0; +} + +void socketfree(struct dns_transmit *d) +{ + if (!d->s1) return; + close(d->s1 - 1); + d->s1 = 0; +} + +void dns_transmit_free(struct dns_transmit *d) +{ + queryfree(d); + socketfree(d); + packetfree(d); +} + +int randombind6(struct dns_transmit *d) +{ + int j; + + for (j = 0; j < 10; ++j) { + if (socket_bind6(d->s1 - 1,d->localip,1025 + dns_random(64510),d->scope_id) == 0) + return 0; + } + if (socket_bind6(d->s1 - 1,d->localip,0,d->scope_id) == 0) + return 0; + + return DNS_COM; +} + +int randombind4(struct dns_transmit *d) +{ + int j; + + for (j = 0; j < 10; ++j) { + if (socket_bind4(d->s1 - 1,d->localip + 12,1025 + dns_random(64510)) == 0) + return 0; + } + if (socket_bind4(d->s1 - 1,d->localip + 12,0) == 0) + return 0; + + return DNS_COM; +} + +static int thisudp(struct dns_transmit *d) +{ + const char *ip; + + socketfree(d); + + while (d->udploop < 5) { + for (; d->curserver < QUERY_MAXNS; ++d->curserver) { + ip = d->servers + 16 * d->curserver; + if (byte_diff(ip,16,V6localnet)) { + d->query[2] = dns_random(256); + d->query[3] = dns_random(256); + + if (ip6_isv4mapped(ip)) { + d->s1 = 1 + socket_udp4(); + if (!d->s1) { dns_transmit_free(d); return DNS_COM; } + if (randombind4(d) < 0) { dns_transmit_free(d); return DNS_COM; } + } else { + d->s1 = 1 + socket_udp6(); + if (!d->s1) { dns_transmit_free(d); return DNS_COM; } + if (randombind6(d) < 0) { dns_transmit_free(d); return DNS_COM; } + } + + if (byte_equal(ip,2,V6linklocal) && !d->scope_id) + d->scope_id = getscopeid(d,ip); + if (socket_connect(d->s1 - 1,ip,DNSPORT,d->scope_id) == 0) + if (send(d->s1 - 1,d->query + 2,d->querylen - 2,0) == d->querylen - 2) { + struct taia now; + taia_now(&now); + taia_uint(&d->deadline,timeouts[d->udploop]); + taia_add(&d->deadline,&d->deadline,&now); + d->tcpstate = 0; + return 0; + } + socketfree(d); + } + } + ++d->udploop; + d->curserver = 0; + } + + dns_transmit_free(d); return DNS_COM; +} + +int firstudp(struct dns_transmit *d) +{ + d->curserver = 0; + return thisudp(d); +} + +int nextudp(struct dns_transmit *d) +{ + ++d->curserver; + return thisudp(d); +} + +static int thistcp(struct dns_transmit *d) +{ + struct taia now; + const char *ip; + + socketfree(d); + packetfree(d); + + for (; d->curserver < QUERY_MAXNS; ++d->curserver) { + ip = d->servers + 16 * d->curserver; + if (byte_diff(ip,16,V6localnet)) { + d->query[2] = dns_random(256); + d->query[3] = dns_random(256); + + if (ip6_isv4mapped(ip)) { + d->s1 = 1 + socket_tcp4(); + if (!d->s1) { dns_transmit_free(d); return DNS_COM; } + if (randombind4(d) < 0) { dns_transmit_free(d); return DNS_COM; } + } else { + d->s1 = 1 + socket_tcp6(); + if (!d->s1) { dns_transmit_free(d); return DNS_COM; } + if (randombind6(d) < 0) { dns_transmit_free(d); return DNS_COM; } + } + + taia_now(&now); + taia_uint(&d->deadline,10); + taia_add(&d->deadline,&d->deadline,&now); + + if (byte_equal(ip,2,V6linklocal) && !d->scope_id) + d->scope_id = getscopeid(d,ip); + if (socket_connect(d->s1 - 1,ip,DNSPORT,d->scope_id) == 0) { + d->tcpstate = 2; + return 0; + } + if ((errno == EINPROGRESS) || (errno == EWOULDBLOCK)) { + d->tcpstate = 1; + return 0; + } + + socketfree(d); + } + } + + dns_transmit_free(d); + return DNS_COM; +} + +int firsttcp(struct dns_transmit *d) +{ + d->curserver = 0; + return thistcp(d); +} + +int nexttcp(struct dns_transmit *d) +{ + ++d->curserver; + return thistcp(d); +} + +int dns_transmit_start(struct dns_transmit *d,const char servers[QUERY_MAXIPLEN], \ + int flagrecursive,const char *q,const char qtype[2],const char localip[16]) +{ + unsigned int len; + + dns_transmit_free(d); + errno = EIO; + + len = dns_domain_length(q); + d->querylen = len + 18; + d->query = alloc(d->querylen); + if (!d->query) return DNS_COM; + + uint16_pack_big(d->query,len + 16); + byte_copy(d->query + 2,12,flagrecursive ? "\0\0\1\0\0\1\0\0\0\0\0\0" : \ + "\0\0\0\0\0\1\0\0\0\0\0\0gcc-bug-workaround"); + byte_copy(d->query + 14,len,q); + byte_copy(d->query + 14 + len,2,qtype); + byte_copy(d->query + 16 + len,2,DNS_C_IN); + + byte_copy(d->qtype,2,(char *) qtype); + d->servers = servers; + byte_copy(d->localip,16,(char *) localip); + + d->udploop = flagrecursive ? 1 : 0; + + if (len + 16 > MSGSIZE) return firsttcp(d); + return firstudp(d); +} + +int dns_transmit_start6(struct dns_transmit *d,const char servers[QUERY_MAXIPLEN], \ + int flagrecursive,const char *q,const char qtype[2], \ + const char localip[16],const uint32 scopes[QUERY_MAXNS]) +{ + byte_copy(scope_ids,128,(char *) scopes); + + return dns_transmit_start(d,servers,flagrecursive,q,qtype,localip); +} + +void dns_transmit_io(struct dns_transmit *d,iopause_fd *x,struct taia *deadline) +{ + x->fd = d->s1 - 1; + + switch (d->tcpstate) { + case 0: case 3: case 4: case 5: + x->events = IOPAUSE_READ; + break; + case 1: case 2: + x->events = IOPAUSE_WRITE; + break; + } + + if (taia_less(&d->deadline,deadline)) + *deadline = d->deadline; +} + +int dns_transmit_get(struct dns_transmit *d,const iopause_fd *x,const struct taia *when) +{ + char udpbuf[MSGSIZE + 1]; + unsigned char ch; + int r; + int fd; + + errno = EIO; + fd = d->s1 - 1; + + if (!x->revents) { + if (taia_less((struct taia *)when,&d->deadline)) return 0; + errno = ETIMEDOUT; + if (d->tcpstate == 0) return nextudp(d); + return nexttcp(d); + } + +/* +have attempted to send UDP query to each server udploop times +have sent query to curserver on UDP socket s +*/ + if (d->tcpstate == 0) { + r = recv(fd,udpbuf,sizeof(udpbuf),0); + if (r <= 0) { + if (errno == ECONNREFUSED) if (d->udploop == 2) return 0; + return nextudp(d); + } + if (r + 1 > sizeof(udpbuf)) return 0; + + if (irrelevant(d,udpbuf,r)) return 0; + if (serverwantstcp(udpbuf,r)) return firsttcp(d); + if (serverfailed(udpbuf,r)) { + if (d->udploop == 2) return 0; + return nextudp(d); + } + socketfree(d); + + d->packetlen = r; + d->packet = alloc(d->packetlen); + if (!d->packet) { dns_transmit_free(d); return DNS_COM; } + byte_copy(d->packet,d->packetlen,udpbuf); + queryfree(d); + return 1; + } + +/* +have sent connection attempt to curserver on TCP socket s +pos not defined +*/ + if (d->tcpstate == 1) { + if (!socket_connected(fd)) return nexttcp(d); + d->pos = 0; + d->tcpstate = 2; + return 0; + } + +/* +have connection to curserver on TCP socket s +have sent pos bytes of query +*/ + if (d->tcpstate == 2) { + r = write(fd,d->query + d->pos,d->querylen - d->pos); + if (r <= 0) return nexttcp(d); + d->pos += r; + if (d->pos == d->querylen) { + struct taia now; + taia_now(&now); + taia_uint(&d->deadline,10); + taia_add(&d->deadline,&d->deadline,&now); + d->tcpstate = 3; + } + return 0; + } + +/* +have sent entire query to curserver on TCP socket s +pos not defined +*/ + if (d->tcpstate == 3) { + r = read(fd,&ch,1); + if (r <= 0) return nexttcp(d); + d->packetlen = ch; + d->tcpstate = 4; + return 0; + } + +/* +have sent entire query to curserver on TCP socket s +pos not defined +have received one byte of packet length into packetlen +*/ + if (d->tcpstate == 4) { + r = read(fd,&ch,1); + if (r <= 0) return nexttcp(d); + d->packetlen <<= 8; + d->packetlen += ch; + d->tcpstate = 5; + d->pos = 0; + d->packet = alloc(d->packetlen); + if (!d->packet) { dns_transmit_free(d); return DNS_COM; } + return 0; + } + +/* +have sent entire query to curserver on TCP socket s +have received entire packet length into packetlen +packet is allocated +have received pos bytes of packet +*/ + if (d->tcpstate == 5) { + r = read(fd,d->packet + d->pos,d->packetlen - d->pos); + if (r <= 0) return nexttcp(d); + d->pos += r; + if (d->pos < d->packetlen) return 0; + + socketfree(d); + if (irrelevant(d,d->packet,d->packetlen)) return nexttcp(d); + if (serverwantstcp(d->packet,d->packetlen)) return nexttcp(d); + if (serverfailed(d->packet,d->packetlen)) return nexttcp(d); + + queryfree(d); + return 1; + } + + return 0; +} diff --git a/src/dnsstub/dns_txt.c b/src/dnsstub/dns_txt.c new file mode 100644 index 0000000..3c54773 --- /dev/null +++ b/src/dnsstub/dns_txt.c @@ -0,0 +1,71 @@ +#include "stralloc.h" +#include "uint_t.h" +#include "byte.h" +#include "dnsresolv.h" + +/** + * @file dns_txt.c + * @authors djb, fefe, feh + * @ref ucspi-tcp + * @brief DNS text query (txt) + */ + +int dns_txt_packet(stralloc *out,const char *buf,unsigned int len) +{ + unsigned int pos; + char header[12]; + uint16 numanswers; + uint16 datalen; + char ch; + unsigned int txtlen; + int i; + int ranswers = 0; + + if (!stralloc_copys(out,"")) return DNS_MEM; + + pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; + uint16_unpack_big(header + 6,&numanswers); + pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; + pos += 4; + + while (numanswers--) { + pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; + pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; + uint16_unpack_big(header + 8,&datalen); + if (byte_equal(header,2,DNS_T_TXT)) + if (byte_equal(header + 2,2,DNS_C_IN)) { + if (pos + datalen > len) return DNS_ERR; + txtlen = (unsigned char) buf[pos]; + for (i = 1; i < datalen; ++i) { + ch = buf[pos + i]; + if (i == txtlen + 1) // next label + txtlen += (unsigned char) ch + 1; + else { + if (ch < 32) ch = '?'; + if (ch > 126) ch = '?'; + if (!stralloc_append(out,&ch)) return DNS_MEM; + } + } + } + pos += datalen; + ++ranswers; + if (numanswers) if (!stralloc_append(out,"\n")) return DNS_MEM; + } + + return ranswers; +} + +static char *q = 0; + +int dns_txt(stralloc *out,const stralloc *fqdn) +{ + int rc; + + if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; + if (dns_resolve(q,DNS_T_TXT) < 0) return DNS_ERR; + if ((rc = dns_txt_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; + dns_transmit_free(&dns_resolve_tx); + dns_domain_free(&q); + + return rc; +} diff --git a/src/env.c b/src/env.c new file mode 100644 index 0000000..053357b --- /dev/null +++ b/src/env.c @@ -0,0 +1,141 @@ +#include "str.h" +#include "alloc.h" +#include "env.h" + +/** + * @file env.c + * @author djb + * @ref ucspi-tcp + * @brief setting up environment after fork + */ + +extern /*@null@*/char *env_get(char *s) +{ + int i; + unsigned int len; + + if (!s) return 0; + len = str_len(s); + for (i = 0; environ[i]; ++i) + if (str_start(environ[i],s) && (environ[i][len] == '=')) + return environ[i] + len + 1; + return 0; +} + +extern char *env_findeq(char *s) +{ + for (; *s; ++s) + if (*s == '=') return s; + return 0; +} + +int env_isinit = 0; /* if env_isinit: */ +static int ea; /* environ is a pointer to ea+1 char*'s. */ +static int en; /* the first en of those are ALLOCATED. environ[en] is 0. */ + +static void env_del(int i) { + alloc_free(environ[i]); + environ[i] = environ[--en]; + environ[en] = 0; +} + +static void env_unsetlen(char *s,int len) +{ + int i; + + for (i = en - 1; i >= 0; --i) + if (!str_diffn(s,environ[i],len)) + if (environ[i][len] == '=') + env_del(i); +} + +int env_unset(char *s) +{ + if (!env_isinit) + if (!env_init()) return 0; + env_unsetlen(s,str_len(s)); + return 1; +} + +int env_set(char *s) +{ + char *t; + + t = env_findeq(s); + if (t) env_unsetlen(s,t - s); + if (en == ea) { + ea += 30; + if (!alloc_re((void **)&environ,(en + 1) * sizeof(char *),(ea + 1) * sizeof(char *))) + { ea = en; return 0; } + } + environ[en++] = s; + environ[en] = 0; + return 1; +} + +int env_puts(char *s) +{ + char *u; + + if (!env_isinit) + if (!env_init()) return 0; + u = alloc(str_len(s) + 1); + if (!u) return 0; + str_copy(u,s); + if (!env_set(u)) { alloc_free(u); return 0; } + return 1; +} + +int env_put(char *name,char *value) { + char *ln; + int len; + + if (!env_isinit) + if (!env_init()) return 0; + len = str_len(name); + ln = alloc(len + str_len(value) + 2); + if (!ln) return 0; + str_copy(ln,name); + ln[len] = '='; + str_copy(ln + len + 1,value); + if (!env_set(ln)) { alloc_free(ln); return 0; } + return 1; +} + +int env_init() { + char **newenviron; + int i; + + for (en = 0; environ[en]; ++en) + ; + ea = en + 10; + newenviron = (char **) alloc((ea + 1) * sizeof(char *)); + if (!newenviron) return 0; + + for (en = 0; environ[en]; ++en) { + newenviron[en] = alloc(str_len(environ[en]) + 1); + if (!newenviron[en]) { + for (i = 0; i < en; ++i) alloc_free(newenviron[i]); + alloc_free(newenviron); + return 0; + } + str_copy(newenviron[en],environ[en]); + } + + newenviron[en] = 0; + environ = newenviron; + env_isinit = 1; + return 1; +} + +static char *null = 0; + +void env_clear() { + if (env_isinit) + while (en) env_del(0); + else environ = &null; +} +extern char *env_pick() +{ + return environ[0]; +} diff --git a/src/errstr.c b/src/errstr.c new file mode 100644 index 0000000..e3d854b --- /dev/null +++ b/src/errstr.c @@ -0,0 +1,163 @@ +#include "error.h" + +/** + * @file errstr.c + * @author kp + * @ref qlibs + * @brief error output to log for different conditions and OS + */ + +#define X(e,s) if (code == e) return s; + +extern char *error_str(int); + +char *errstr(int code) +{ + X(0,"") // NOERROR + X(error_intr,"interrupted system call") // EINTR + X(EINTR, "interrupted system call") + X(error_nomem,"out of memory") // ENOMEM + X(ENOMEM, "out of memory") + X(error_noent,"file does not exist") // ENOENT + X(ENOENT, "file does not exist") + X(error_txtbsy,"text busy") // ETXTBSY + X(ETXTBSY, "text busy") + X(error_io,"input/output error") // EIO + X(EIO, "input/output error") + X(error_exist,"file already exists") // EEXISTS + X(EEXIST, "file already exists") + X(error_timeout,"timed out") // ETIMEDOUT + X(ETIMEDOUT, "timed out") + X(error_inprogress,"operation in progress") // EINPROGRESS + X(EINPROGRESS, "operation in progress") + X(error_again,"temporary failure") // EAGAIN + X(EAGAIN, "temporary failure") + X(error_wouldblock,"input/output would block") // EWOULDBLOCK (intern EAGAIN) + X(EWOULDBLOCK, "input/output would block") + X(error_pipe,"broken pipe") // EPIPE + X(EPIPE, "broken pipe") + X(error_perm,"permission denied") // EPERM + X(EPERM, "permission denied") + X(error_acces,"access denied") // EACCES + X(EACCES, "access denied") + + X(ESRCH, "no such process") + +// X(error_nodevice,"device not configured") // ENXIO + X(ENXIO, "device not configured") + + X(E2BIG, "argument list too long") + X(ENOEXEC, "exec format error") + X(EBADF, "file descriptor not open") + X(ECHILD, "no child processes") + X(EDEADLK, "operation would cause deadlock") + X(EFAULT, "bad address") + X(ENOTBLK, "not a block device") + X(EBUSY, "device busy") + X(EXDEV, "cross-device link") + X(ENODEV, "device does not support operation") +// X(error_notdir,"not a directory") // ENOTDIR + X(ENOTDIR, "not a directory") + X(error_isdir,"is a directory") // EISDIR + X(EISDIR, "is a directory") + X(EINVAL, "invalid argument") + X(ENFILE, "system cannot open more files") + X(EMFILE, "process cannot open more files") + X(ENOTTY, "not a tty") + X(EFBIG, "file too big") + X(ENOSPC, "out of disk space") + X(ESPIPE, "unseekable descriptor") +// X(error_rofs,"read-only file system") // EROFS + X(EROFS, "read-only file system") + X(EMLINK, "too many links") + X(EDOM, "input out of range") + X(ERANGE, "output out of range") + X(EALREADY, "operation already in progress") + X(ENOTSOCK, "not a socket") + X(EDESTADDRREQ, "destination address required") + X(EMSGSIZE, "message too long") + X(EPROTOTYPE, "incorrect protocol type") + X(ENOPROTOOPT, "protocol not available") + X(EPROTONOSUPPORT, "protocol not supported") + X(ESOCKTNOSUPPORT, "socket type not supported") + X(EOPNOTSUPP, "operation not supported") + X(EPFNOSUPPORT, "protocol family not supported") + X(EAFNOSUPPORT, "address family not supported") + X(EADDRINUSE, "address already used") + X(EADDRNOTAVAIL, "address not available") + X(ENETDOWN, "network down") + X(ENETUNREACH, "network unreachable") + X(ENETRESET, "network reset") + X(ECONNABORTED, "connection aborted") + X(error_connreset, "connection reset") // ECONNRESET + X(ECONNRESET, "connection reset") + X(ENOBUFS, "out of buffer space") + X(EISCONN, "already connected") + X(ENOTCONN, "not connected") + X(ESHUTDOWN, "socket shut down") + X(ETOOMANYREFS, "too many references") + X(error_connrefused,"connection refused") // ECONNREFUSED + X(ECONNREFUSED, "connection refused") + X(ELOOP, "symbolic link loop") + X(ENAMETOOLONG, "file name too long") + X(EHOSTDOWN, "host down") + X(EHOSTUNREACH, "host unreachable") + X(ENOTEMPTY, "directory not empty") + X(EUSERS, "too many users") + X(EDQUOT, "disk quota exceeded") + X(ESTALE, "stale NFS file handle") + + /* BSD only (all BSD's, NOT on Linux) */ +// X(EPROCLIM, "too many processes") // -L +FB +OB +NB +// X(EBADRPC, "RPC structure is bad") // -L +FB +OB +NB + +// X(ERPCMISMATCH, "RPC version mismatch") // -L +FB +OB +NB +// X(EPROGUNAVAIL, "RPC program unavailable") // -L +FB +OB +NB +// X(EPROGMISMATCH, "program version mismatch") // -L +FB +OB +NB +// X(EPROCUNAVAIL, "bad procedure for program") // -L +FB +OB +NB +// X(EFTYPE, "bad file type") // -L +FB +OB +NB + + X(ENOLCK, "no locks available") + X(ENOSYS, "system call not available") + X(ENOMSG, "no message of desired type") + X(EIDRM, "identifier removed") + +// X(ERREMOTE, "object not local") // -L -FB -OB -NB + X(EREMOTE, "object not local") // Linux: "Object is remote" +// X(EREMOTE, "too many levels of remote in path") + + /* Linux only */ +// X(ENONET, "machine not on network") // +L -FB -OB -NB +// X(EADV, "advertise error") // +L -FB -OB -NB +// X(ESRMNT, "srmount error") // +L -FB -OB -NB +// X(ECOMM, "communication error") // +L -FB -OB -NB +// X(EREMCHG, "remote address changed") // +L -FB -OB -NB + + X(error_proto,"protocol error") // EPROTO + /* EPROTO: see 'error.h' for OpenBSD compat */ + X(EPROTO, "protocol error") // +L +FB -OB +NB + + /* Linux and NetBSD */ +// X(ENOSTR, "not a stream device") // +L -FB -OB +NB +// X(ETIME, "timer expired") // +L -FB -OB +NB +// X(ENOSR, "out of stream resources") // +L -FB -OB +NB + + /* FreeBSD and NetBSD */ +// X(EAUTH, "authentication error") // -L +FB -OB +NB +// X(ENEEDAUTH, "not authenticated") // -L +FB -OB +NB + + /* NOT on OpenBSD */ +// X(EBADMSG, "bad message type") // +L +FB -OB +NB +// X(ENOLINK, "link severed") // +L +FB -OB +NB +// X(EMULTIHOP, "multihop attempted") // +L +FB -OB +NB + + /* Application/DJB specific */ + X(EHARD, " ") + X(ESOFT, " ") + X(USAGE, "usage error") // qmail; explicit + X(SYNTAX, "syntax error") // djbdns, qmail; explicit + X(DROP, "connection dropped") // ucspi-tcp + X(FATAL, "unable to continue") // all + + return "unknown error"; /* worst case */ +} diff --git a/src/fd.c b/src/fd.c new file mode 100644 index 0000000..c3cc0f7 --- /dev/null +++ b/src/fd.c @@ -0,0 +1,33 @@ +#include +#include "fd.h" + +/** + * @file fd.c + * @autor djb + * @ref qmail + * @brief file descriptor manipulation + */ + +int close(int __fd); /* we won't use unistd.h here */ + +int fd_copy(int to,int from) +{ + if (to == from) return 0; + if (fcntl(from,F_GETFL,0) == -1) return -1; + close(to); + if (fcntl(from,F_DUPFD,to) == -1) return -1; + return 0; +} + +int fd_move(int to,int from) +{ + if (to == from) return 0; + if (fd_copy(to,from) == -1) return -1; + close(from); + return 0; +} + +int fd_coe(int fd) +{ + return fcntl(fd,F_SETFD,1); +} diff --git a/src/fmt.c b/src/fmt.c new file mode 100644 index 0000000..ff838be --- /dev/null +++ b/src/fmt.c @@ -0,0 +1,87 @@ +#include "fmt.h" + +/** + * @file fmt.c + * @authors djb, feh + * @ref qmail + * @brief formating differnt inputs format for output printing + */ + +unsigned int fmt_str(char *s,const char *t) +{ + unsigned int len; + char ch; + len = 0; + if (s) { while ((ch = t[len])) s[len++] = ch; } + else while (t[len]) len++; + return len; +} + +unsigned int fmt_strn(char *s,const char *t,unsigned int n) +{ + unsigned int len; + char ch; + len = 0; + if (s) { while (n-- && (ch = t[len])) s[len++] = ch; } + else while (n-- && t[len]) len++; + return len; +} + +unsigned int fmt_uint(char *s,unsigned int u) +{ + unsigned long l; l = u; return fmt_ulong(s,l); +} + +unsigned int fmt_uint0(char *s,unsigned int u,unsigned int n) +{ + unsigned int len; + len = fmt_uint(FMT_LEN,u); + while (len < n) { if (s) *s++ = '0'; ++len; } + if (s) fmt_uint(s,u); + return len; +} + +unsigned int fmt_ulong(char *s,unsigned long u) +{ + unsigned int len; + unsigned long q; + len = 1; q = u; + while (q > 9) { ++len; q /= 10; } + if (s) { + s += len; + do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */ + } + return len; +} + +unsigned int fmt_xlong(char *s,unsigned long u) +{ + unsigned int len; + unsigned long q; + len = 1; q = u; + while (q > 15) { ++len; q /= 16; } + if (s) { + s += len; + do { *--s = tohex(u % 16); u /= 16; } while(u); /* handles u == 0 */ + } + return len; +} + +char tohex(char num) { + if (num < 10) + return num + '0'; + else if (num < 16) + return num - 10 + 'a'; + else + return -1; +} + +int fromhex(unsigned char c) { + if (c >= '0' && c <= '9') + return c-'0'; + else if (c >= 'A' && c <= 'F') + return c -'A' + 10; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return -1; +} diff --git a/src/getln.c b/src/getln.c new file mode 100644 index 0000000..84c875c --- /dev/null +++ b/src/getln.c @@ -0,0 +1,43 @@ +#include "byte.h" +#include "getln.h" + +/** + * @file getln.c + * @author djb + * @ref qmail + * @brief evaluating tokenized input arguments + */ + +int getln(buffer *b,stralloc *sa,int *match,int sep) +{ + char *cont; + unsigned int clen; + + if (sgetln(b,sa,&cont,&clen,sep) == -1) return -1; + if (!clen) { *match = 0; return 0; } + if (!stralloc_catb(sa,cont,clen)) return -1; + *match = 1; + return 0; +} + +int sgetln(buffer *b,stralloc *sa,char **cont,unsigned int *clen,int sep) +{ + char *x; + unsigned int i; + int n; + + if (!stralloc_ready(sa,0)) return -1; + sa->len = 0; + + for (;;) { + n = buffer_feed(b); + if (n < 0) return -1; + if (n == 0) { *clen = 0; return 0; } + x = buffer_PEEK(b); + i = byte_chr(x,n,sep); + if (i < n) { buffer_SEEK(b,*clen = i + 1); *cont = x; return 0; } + if (!stralloc_readyplus(sa,n)) return -1; + i = sa->len; + sa->len = i + buffer_get(b,sa->s + i,n); + } +} diff --git a/src/getoptb.c b/src/getoptb.c new file mode 100644 index 0000000..af7ffc2 --- /dev/null +++ b/src/getoptb.c @@ -0,0 +1,100 @@ +#include "buffer.h" +#include "getoptb.h" + +/** + * @file getoptb.c + * @author djb + * @ref ucspi-tcp + * @brief 'getopt' version w/o stdlib + */ + +#define optind subgetoptind +#define optproblem subgetoptproblem + +int opterr = 1; +char *optprogname = 0; + +int getoptb(int argc,char **argv,char *opts) +{ + int c; + char *s; + + if (!optprogname) { + optprogname = *argv; + if (!optprogname) optprogname = ""; + for (s = optprogname;*s;++s) if (*s == '/') optprogname = s + 1; + } + c = subgetopt(argc,argv,opts); + if (opterr) + if (c == '?') { + char chp[2]; chp[0] = optproblem; chp[1] = '\n'; + buffer_puts(buffer_2,optprogname); + if (argv[optind] && (optind < argc)) + buffer_puts(buffer_2,": illegal option -- "); + else + buffer_puts(buffer_2,": option requires an argument -- "); + buffer_put(buffer_2,chp,2); + buffer_flush(buffer_2); + } + return c; +} + +#define optpos subgetoptpos +#define optarg subgetoptarg +#define optdone subgetoptdone + +int optind = 1; +int optpos = 0; +char *optarg = 0; +int optproblem = 0; +int optdone = SUBGETOPTDONE; + +int subgetopt(int argc,char **argv,char *opts) +{ + int c; + char *s; + + optarg = 0; + if (!argv || (optind >= argc) || !argv[optind]) return optdone; + if (optpos && !argv[optind][optpos]) { + ++optind; + optpos = 0; + if ((optind >= argc) || !argv[optind]) return optdone; + } + if (!optpos) { + if (argv[optind][0] != '-') return optdone; + ++optpos; + c = argv[optind][1]; + if ((c == '-') || (c == 0)) { + if (c) ++optind; + optpos = 0; + return optdone; + } + /* otherwise c is reassigned below */ + } + c = argv[optind][optpos]; + ++optpos; + s = opts; + while (*s) { + if (c == *s) { + if (s[1] == ':') { + optarg = argv[optind] + optpos; + ++optind; + optpos = 0; + if (!*optarg) { + optarg = argv[optind]; + if ((optind >= argc) || !optarg) { /* argument past end */ + optproblem = c; + return '?'; + } + ++optind; + } + } + return c; + } + ++s; + if (*s == ':') ++s; + } + optproblem = c; + return '?'; +} diff --git a/src/iopause.c b/src/iopause.c new file mode 100644 index 0000000..2e24d45 --- /dev/null +++ b/src/iopause.c @@ -0,0 +1,84 @@ +#include +#include "taia.h" +#include "select.h" +#include "iopause.h" + +/** + * @file iopause.c + * @author djb + * @ref qmail + * @brief stateful reading from net + * @return > 0 if successful + */ + +int iopause(iopause_fd *x,unsigned int len,struct taia *deadline,struct taia *stamp) +{ + struct taia t; + int millisecs; + double d; + int i, r; + + if (taia_less(deadline,stamp)) + millisecs = 0; + else { + t = *stamp; + taia_sub(&t,deadline,&t); + d = taia_approx(&t); + if (d > 1000.0) d = 1000.0; + millisecs = d * 1000.0 + 20.0; + if (millisecs < 0) millisecs = 20.0; + } + + for (i = 0; i < len; ++i) + x[i].revents = 0; + +#ifdef IOPAUSE_POLL + r = poll(x,len,millisecs); + + /* XXX: some kernels apparently need x[0] even if len is 0 */ + /* XXX: how to handle EAGAIN? are kernels really this dumb? */ + /* XXX: how to handle EINVAL? when exactly can this happen? */ + +#else + struct timeval tv; + fd_set rfds; + fd_set wfds; + int nfds; + int fd; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + nfds = 1; + for (i = 0; i < len; ++i) { + fd = x[i].fd; + if (fd < 0) continue; + if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/ + + if (fd >= nfds) nfds = fd + 1; + if (x[i].events & IOPAUSE_READ) FD_SET(fd,&rfds); + if (x[i].events & IOPAUSE_WRITE) FD_SET(fd,&wfds); + } + + tv.tv_sec = millisecs / 1000; + tv.tv_usec = 1000 * (millisecs % 1000); + + r = select(nfds,&rfds,&wfds,(fd_set *) 0,&tv); + if (r <= 0) return r; + + /* XXX: for EBADF, could seek out and destroy the bad descriptor */ + + for (i = 0; i < len; ++i) { + fd = x[i].fd; + if (fd < 0) continue; + if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/ + + if (x[i].events & IOPAUSE_READ) + if (FD_ISSET(fd,&rfds)) x[i].revents |= IOPAUSE_READ; + if (x[i].events & IOPAUSE_WRITE) + if (FD_ISSET(fd,&wfds)) x[i].revents |= IOPAUSE_WRITE; + } + +#endif + return r; +} diff --git a/src/ip4.c b/src/ip4.c new file mode 100644 index 0000000..9b2047c --- /dev/null +++ b/src/ip4.c @@ -0,0 +1,160 @@ +#include "fmt.h" +#include "scan.h" +#include "str.h" +#include "ip.h" + +/** + * @file ip4.c + * @authors djb, fefe, feh, kp + * @ref ucspi-tcp, ucspi-tcp6 + * @brief handling of IPv4 addresses + */ + +/** + * @brief ip4_fmt + * converts IPv4 address to dotted decimal string format + * @param input: IPv4 char array + * output: IPv4 address string + * @return int length of address (ok > 0) + */ +unsigned int ip4_fmt(char *s,char ip[4]) +{ + unsigned int len; + unsigned int i; + + len = 0; + i = fmt_ulong(s,(unsigned long) (unsigned char) ip[0]); len += i; if (s) s += i; + if (s) { *s++ = '.'; } ++len; + i = fmt_ulong(s,(unsigned long) (unsigned char) ip[1]); len += i; if (s) s += i; + if (s) { *s++ = '.'; } ++len; + i = fmt_ulong(s,(unsigned long) (unsigned char) ip[2]); len += i; if (s) s += i; + if (s) { *s++ = '.'; } ++len; + i = fmt_ulong(s,(unsigned long) (unsigned char) ip[3]); len += i; if (s) s += i; + return len; +} + +/** + * @brief ia4_fmt + * converts IPv4 address into DNS inverse nibble format + * @param input: IPv4 char array + * output: IPv4 address string + * @return int length of address (ok > 0) + */ +unsigned int ia4_fmt(char *s,char ip[4]) +{ + unsigned int i; + unsigned int len; + + len = 0; + i = fmt_ulong(s,(unsigned long) ip[3]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; + i = fmt_ulong(s,(unsigned long) ip[2]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; + i = fmt_ulong(s,(unsigned long) ip[1]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; + i = fmt_ulong(s,(unsigned long) ip[0]); len += i; if (s) s += i; + i = fmt_str(s,".in-addr.arpa."); len += i; if (s) s += i; + return len; +} + +/** + * @brief ip4_scan + * parse IPv4 address string and convert to IP address array + * @param input: IPv4 address string + * output: IPv4 char array + * @return int length of ip_address (ok > 0) + */ +unsigned int ip4_scan(const char *s,char ip[4]) +{ + unsigned int i; + unsigned int len; + unsigned long u; + + byte_zero(ip,4); + len = 0; + i = scan_ulong((char *)s,&u); if (!i) { return 0; } ip[0] = u; s += i; len += i; + if (*s != '.') { return 0; } ++s; ++len; + i = scan_ulong((char *)s,&u); if (!i) { return 0; } ip[1] = u; s += i; len += i; + if (*s != '.') { return 0; } ++s; ++len; + i = scan_ulong((char *)s,&u); if (!i) { return 0; } ip[2] = u; s += i; len += i; + if (*s != '.') { return 0; } ++s; ++len; + i = scan_ulong((char *)s,&u); if (!i) { return 0; } ip[3] = u; s += i; len += i; + return len; +} + +/** + * @brief ip4_scanbracket + * parse IPv4 address string enclosed in brackets and convert to IP address array + * @param input: IPv4 char array + * output: IPv4 char array + * @return int length of ip_address (ok > 0) + */ +unsigned int ip4_scanbracket(const char *s,char ip[4]) +{ + unsigned int len; + + if (*s != '[') return 0; + len = ip4_scan(s + 1,ip); + if (!len) return 0; + if (s[len + 1] != ']') return 0; + return len + 2; +} + +/** + * @brief ip4_cidr + * parse IPv4 address string + * concatinated with the prefix length: 192.168.1/24 + * @param input: IPv6 char array + * output: IPv6 char array, long plen + * @return int length of ip6_address/ip + */ +unsigned int ip4_cidr(char *s,char ip[4],unsigned long *plen) +{ + unsigned int j = 0; + *plen = 32UL; + + j = str_chr(s,'/'); + if (s[j] == '/') { + s[j] = 0; + j = scan_ulong(s + j + 1,plen); + } + return ip4_scan((const char *)s,ip); +} + +/** + * @brief ip4_bytestring + * parse IPv4 address and represent as char string with length prefix + * @param input: IPv4 char array, prefix length + * output: pointer to stralloc bytestring + * @return n: number of bytes, if ok; -1: memory shortage; -2: input error + */ +unsigned int ip4_bytestring(stralloc *ipstring,char ip[4],int prefix) +{ + int i, j, n = 0; + unsigned char number; + + if (!stralloc_readyplus(ipstring,32)) return -1; + if (!stralloc_copys(ipstring,"")) return -1; + + for (i = 0; i < 4; i++) { + number = (unsigned char) ip[i]; + if (number > 255) return -2; + + for (j = 7; j >= 0; j--) { + if (number & (1 << j)) { + n++; + if (!stralloc_cats(ipstring,"1")) return -1; + } else { + n++; + if (!stralloc_cats(ipstring,"0")) return -1; + } + prefix--; + if (!prefix) goto DONE; + } + } + +DONE: + if (!stralloc_0(ipstring)) return 1; + + return n; +} diff --git a/src/ip6.c b/src/ip6.c new file mode 100644 index 0000000..a5a60fd --- /dev/null +++ b/src/ip6.c @@ -0,0 +1,350 @@ +#include "fmt.h" +#include "byte.h" +#include "scan.h" +#include "ip.h" +#include "str.h" + +/** + * @file ip6.c + * @authors djb, fefe, feh + * @ref ucspi-tcp, ucspi-tcp6 + * @brief handling of IPv6 addresses + */ + +/** + * @brief ip6_fmt + * convert IPv6 address to compactified IPv6 address string + * @param input: IPv6 char array + * output: pointer to IPv6 address string + * @return int length of address (ok > 0) + */ +unsigned int ip6_fmt(char *s,char ip[16]) +{ + unsigned int len; + unsigned int i; + unsigned int temp, temp0; + unsigned int compressing; + unsigned int compressed; + int j; + + len = 0; + compressing = 0; + compressed = 0; + + for (j = 0; j < 16; j += 2) { + if (j == 12 && ip6_isv4mapped(ip)) { + len += ip4_fmt(s,ip+12); + break; + } + + temp = ((unsigned long) (unsigned char) ip[j] << 8) + + (unsigned long) (unsigned char) ip[j+1]; + + temp0 = 0; + if (!compressing && j < 16) + temp0 = ((unsigned long) (unsigned char) ip[j+2] << 8) + + (unsigned long) (unsigned char) ip[j+3]; + + if (temp == 0 && temp0 == 0 && !compressed) { + if (!compressing) { + compressing = 1; + if (j == 0) { + if (s) *s++ = ':'; + ++len; + } + } + } else { + if (compressing) { + compressing = 0; + ++compressed; + if (s) *s++ = ':'; + ++len; + } + i = fmt_xlong(s,temp); + len += i; + if (s) s += i; + if (j < 14) { + if (s) *s++ = ':'; + ++len; + } + } + } + if (compressing) { *s++ = ':'; ++len; } + + return len; +} + +/** + * @brief ip6_fmt_flat + * convert IPv6 address to IPv6 address string + * @param input: IPv6 char array + * output: pointer to IPv6 address string + * @return int length of address (ok > 0) + */ +unsigned int ip6_fmt_flat(char *s,char ip[16]) +{ + int i; + for (i = 0; i < 16; i++) { + *s++ = tohex((unsigned char)ip[i] >> 4); + *s++ = tohex((unsigned char)ip[i] & 15); + } + return 32; +} + +/** + * @brief ia6_fmt + * convert IPv6 address to inverse DNS nibble format + * 1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.arpa + * @param input: IPv6 char array + * output: pointer to IPv6 address string + * @return int length of address + */ +unsigned int ia6_fmt(char *s,char ip[16]) +{ + unsigned int i; + unsigned int len; + int j; + + static char data[] = "0123456789abcdef"; + len = 0; + + for (j = 15; j >= 0; j--) { + i = fmt_str(s,&data[ip[j] & 0x0f]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; + i = fmt_str(s,&data[ip[j] >> 4 & 0x0f]); len += i; if (s) s += i; + i = fmt_str(s,"."); len += i; if (s) s += i; + } + i = fmt_str(s,"ip6.arpa."); len += i; if (s) s += i; + + return len; +} + +/** + * @brief ip6_scan_flat + * convert IPv6 address string to IPv6 address array + * @param input: pointer to IPv6 address string + * output: IPv6 char array + * @return int length of address (ok > 0) + */ +unsigned int ip6_scan_flat(const char *s,char ip[16]) +{ + int i, tmp; + + for (i = 0; i < 16; i++) { + tmp = fromhex(*s++); + if (tmp < 0) return 0; + ip[i] = tmp << 4; + tmp = fromhex(*s++); + if (tmp < 0) return 0; + ip[i] += tmp; + } + return 32; +} + +/** + * @brief ip6_scan + * parse compactified IPv6 address string and convert to IPv6 address array + * @param input: pointer to IPv6 address string + * output: IPv6 char array + * @return int length of ip6_address/ip + */ +unsigned int ip6_scan(const char *s,char ip[16]) +{ + unsigned int i, j; + unsigned int len = 0; + unsigned long u; + + char suffix[16]; + int prefixlen = 0; + int suffixlen = 0; + + /* Always return IPv4 as IPv4-mapped IPv6 address */ + if ((i = ip4_scan(s,ip+12))) { + for (len = 0; len < 12; ++len) + ip[len] = V4mappedprefix[len]; + return i; + if (byte_equal(ip+12,4,V4localnet)) { + byte_copy(ip,16,V6localnet); + return 16; + } + } + byte_zero(ip,16); + + for (;;) { + if (*s == ':') { + len++; + if (s[1] == ':') { /* Found "::", skip to part 2 */ + s += 2; len++; + break; + } + s++; + } + i = scan_xlong((char *)s,&u); + if (!i) return 0; + + if (prefixlen == 12 && s[i] == '.') { + /* the last 4 bytes may be written as IPv4 address */ + i = ip4_scan(s,ip+12); + if (i) + return i+len; + else + return 0; + } + + ip[prefixlen++] = (u >> 8); + ip[prefixlen++] = (u & 255); + s += i; len += i; + if (prefixlen == 16) return len; + } + +/* part 2, after "::" */ + for (;;) { + if (*s == ':') { + if (suffixlen == 0) break; + s++; + len++; + } else if (suffixlen != 0) break; + + i = scan_xlong((char *)s,&u); + if (!i) { + len--; + break; + } + + if (suffixlen + prefixlen <= 12 && s[i] == '.') { + j = ip4_scan(s,suffix+suffixlen); + if (j) { + suffixlen += 4; + len += j; + break; + } else + prefixlen = 12 - suffixlen; /* make end-of-loop test true */ + } + + suffix[suffixlen++] = (u >> 8); + suffix[suffixlen++] = (u & 255); + s += i; len += i; + if (prefixlen + suffixlen == 16) break; + } + + for (i = 0; i < suffixlen; i++) + ip[16 - suffixlen + i] = suffix[i]; + + return len; +} + +/** + * @brief ip6_scanbracket + * parse IPv6 string address enclosed in brackets + * @param input: pointer to IPv6 address string + * output: IPv6 char array + * @return int length of ip_address (ok > 0) + */ +unsigned int ip6_scanbracket(const char *s,char ip[16]) +{ + unsigned int len; + + if (*s != '[') return 0; + len = ip6_scan(s + 1,ip); + if (!len) return 0; + if (s[len + 1] != ']') return 0; + return len + 2; +} + +/** + * @brief ip6_ifscan + * parse compactified IPv6 address string + * concatinated with the interface name: fe80::1%eth0 + * @param input: pointer to IPv6 address string + * output: IPv6 char array, stralloc interface_name + * @return int length of ip6_address/ip + */ +unsigned int ip6_ifscan(char *s,char ip[16],stralloc *ifname) +{ + int i; + int j = 0; + int k = 0; + if (!stralloc_copys(ifname,"0")) return 0; + + if ((j = str_chr(s,'%'))) { + if ((i = str_chr(s+j+1,' '))) k = i; + else if ((i = str_chr(s+j+1,'\n'))) k = i; + else if ((i = str_chr(s+j+1,'\t'))) k = i; + if (k) s[j+k+1] = '\0'; /* input might contain trailing chars */ + if (!stralloc_copys(ifname,s+j+1)) return 0; + s[j] = 0; + } + if (!stralloc_0(ifname)) return 0; + + return ip6_scan(s,ip); +} + +/** + * @brief ip6_cidr + * parse compactified IPv6 address string + * concatinated with the prefix length: fe80::1/64 + * @param input: pointer to IPv6 address string + * output: IPv6 char array, long plen + * @return int length of ip6_address/ip + */ +unsigned int ip6_cidr(char *s,char ip[16],unsigned long *plen) +{ + unsigned int j = 0; + *plen = 128UL; + + j = str_chr(s,'/'); + if (s[j] == '/') { + s[j] = 0; + j = scan_ulong(s+j+1,plen); + } + return ip6_scan((const char *)s,ip); +} + +/** + * @brief ip6_bytestring + * parse IPv6 address and represent as char string with length prefix + * @param input: IPv6 char array, prefix length + * output: pointer to stralloc bit string; + * @return n: number of bytes, if ok; -1: memory shortage + */ +unsigned int ip6_bytestring(stralloc *ipstring,char ip[16],int prefix) +{ + int i, j, n = 0; + unsigned char lowbyte, highbyte; + + if (!stralloc_readyplus(ipstring,128)) return -1; + if (!stralloc_copys(ipstring,"")) return -1; + + for (i = 0; i < 16; i++) { + lowbyte = (unsigned char) (ip[i]) & 0x0f; + highbyte = (unsigned char) (ip[i] >> 4) & 0x0f; + + for (j = 3; j >= 0; j--) { + if (highbyte & (1 << j)) { + n++; + if (!stralloc_cats(ipstring,"1")) return -1; + } else { + n++; + if (!stralloc_cats(ipstring,"0")) return -1; + } + prefix--; + if (!prefix) goto DONE; + } + for (j = 3; j >= 0; j--) { + if (lowbyte & (1 << j)) { + n++; + if (!stralloc_cats(ipstring,"1")) return -1; + } else { + n++; + if (!stralloc_cats(ipstring,"0")) return -1; + } + prefix--; + if (!prefix) goto DONE; + } + } + +DONE: + if (!stralloc_0(ipstring)) return -1; + + return n; +} diff --git a/src/lock.c b/src/lock.c new file mode 100644 index 0000000..5285210 --- /dev/null +++ b/src/lock.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include "lock.h" + +/** + * @file lock.c + * @author djb + * @ref qmail + * @brief locking of resources + */ + +#ifdef HASFLOCK +int lock_ex(int fd) { return flock(fd,LOCK_EX); } +int lock_exnb(int fd) { return flock(fd,LOCK_EX | LOCK_NB); } +int lock_un(int fd) { return flock(fd,LOCK_UN); } +#else +int lock_ex(int fd) { return lockf(fd,1,0); } +int lock_exnb(int fd) { return lockf(fd,2,0); } +int lock_un(int fd) { return lockf(fd,0,0); } +#endif diff --git a/src/logmsg.c b/src/logmsg.c new file mode 100644 index 0000000..97d832e --- /dev/null +++ b/src/logmsg.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include "buffer.h" +#include "fmt.h" +#include "str.h" +#include "stralloc.h" +#include "logmsg.h" + +/** + * @file logmsg.c + * @author kp, feh + * @ref qlibs + * @brief unified system and error message handling + */ + +#define WHO "logmsg" + +char *build_log_msg(const char *x[]) +{ + stralloc sa = {0}; + stralloc_copys(&sa,""); + + while(*x) { if (!stralloc_cats(&sa,*x++)) err_sys(WHO,errno); } /* concatenate *x */ + + if (!stralloc_0(&sa)) err_sys(WHO,errno); + return(sa.s); +} + +void logmsg(const char *who,int ecode,unsigned int class,const char *msg) +{ + char strnum[FMT_ULONG]; + char *codestr = ""; + char *classstr = ""; + char *errmsg = ""; + + errno = 0; /* re-initialize errno, value is in 'code' now */ + +/* Part 1: obtain the (error) code -- perhaps received from OS */ + + if (ecode != 0) { + codestr = ""; + if (ecode < 0) { // check for negative error codes + ecode = (ecode^-1) + 1; + codestr = "-"; + } + strnum[fmt_ulong(strnum,ecode)] = 0; /* format for output */ + char *temp = strnum; + codestr = str_cat(codestr,temp); + } + +/* Part 2: behavioral on error */ + + switch (class) { + case ERROR: classstr = "error: "; break; // info + exit + case FATAL: classstr = "fatal: "; break; // info + exit + case DROP: classstr = "drop: "; break; // info + next call/iteration + case ALERT: classstr = "alert: "; break; // info + next statement + case WARN: classstr = "warning: "; break; // info + next statement + case INFO: classstr = "info: "; break; // info + continue + case SYNTAX: classstr = "syntax: "; break; // info + exit + case USAGE: classstr = "usage: "; break; // info + exit + case TEMP: classstr = "temp: "; break; // info + exit + case CAT: classstr = ""; break; // info w/o \n + default: + class = LOG; classstr = ""; break; // custom info + continue + } + +/* Part 3: get system error message */ + + if (class == FATAL || class == DROP) + errmsg = error_str(errno); + +/* Part 4: construct log message: Source: Class (Ecode) Message: Errmsg */ + + buffer_puts(buffer_2,who); + buffer_puts(buffer_2,": "); + buffer_puts(buffer_2,classstr); + if (class == FATAL || class == DROP || class == ERROR) { + buffer_puts(buffer_2,"("); + buffer_puts(buffer_2,codestr); + buffer_puts(buffer_2,") "); + } + buffer_puts(buffer_2,msg); + if (errno) { + buffer_puts(buffer_2,": "); + buffer_puts(buffer_2,errmsg); + } + if (class != CAT) { + buffer_puts(buffer_2,"\n"); + buffer_flush(buffer_2); + } + + if (class == USAGE) _exit(USAGE); + if (class == SYNTAX) _exit(SYNTAX); + if (class == FATAL || class == DROP || class == ERROR) _exit(ecode); +} diff --git a/src/ndelay.c b/src/ndelay.c new file mode 100644 index 0000000..d6769c7 --- /dev/null +++ b/src/ndelay.c @@ -0,0 +1,24 @@ +#include +#include +#include "ndelay.h" + +/** + * @file ndelay.c + * @author djb + * @ref qmail + * @brief delaying of IO operations + */ + +#ifndef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif + +int ndelay_on(int fd) +{ + return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK); +} + +int ndelay_off(int fd) +{ + return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK); +} diff --git a/src/open.c b/src/open.c new file mode 100644 index 0000000..842955a --- /dev/null +++ b/src/open.c @@ -0,0 +1,25 @@ +#include +#include +#include "open.h" + +/** + * @file open.c + * @author djb + * @ref qmail + * @brief open a file + */ + +int open_append(const char *fn) +{ return open(fn,O_WRONLY | O_NDELAY | O_APPEND | O_CREAT,0600); } + +int open_excl(const char *fn) +{ return open(fn,O_WRONLY | O_EXCL | O_CREAT,0644); } + +int open_read(const char *fn) +{ return open(fn,O_RDONLY | O_NDELAY); } + +int open_trunc(const char *fn) +{ return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); } + +int open_write(const char *fn) +{ return open(fn,O_WRONLY | O_NDELAY); } diff --git a/src/pathexec.c b/src/pathexec.c new file mode 100644 index 0000000..564d65d --- /dev/null +++ b/src/pathexec.c @@ -0,0 +1,121 @@ +#include +#include "alloc.h" +#include "error.h" +#include "stralloc.h" +#include "str.h" +#include "byte.h" +#include "env.h" +#include "pathexec.h" + +/** + * @file pathexec.c + * @author djb + * @ref ucspi-tcp, ucspi-ssl + * @brief populate environment after fork + */ + +static stralloc plus; +static stralloc tmp; + +int pathexec_env(const char *s,const char *t) +{ + if (!s) return 1; + if (!stralloc_copys(&tmp,s)) return 0; + if (t) { + if (!stralloc_cats(&tmp,"=")) return 0; + if (!stralloc_cats(&tmp,t)) return 0; + } + if (!stralloc_0(&tmp)) return 0; + return stralloc_cat(&plus,&tmp); +} + +int pathexec_multienv(stralloc *sa) +{ + if (!sa) return 1; + return stralloc_cat(&plus,sa); +} + +void pathexec(char * const *argv) +{ + char **e; + unsigned int elen; + unsigned int i; + unsigned int j; + unsigned int split; + unsigned int t; + + if (!stralloc_cats(&plus,"")) return; + + elen = 0; + for (i = 0; environ[i]; ++i) + ++elen; + for (i = 0; i < plus.len; ++i) + if (!plus.s[i]) + ++elen; + + e = (char **) alloc((elen + 1) * sizeof(char *)); + if (!e) return; + + elen = 0; + for (i = 0; environ[i]; ++i) + e[elen++] = environ[i]; + + j = 0; + for (i = 0; i < plus.len; ++i) + if (!plus.s[i]) { + split = str_chr(plus.s + j,'='); + for (t = 0; t < elen; ++t) + if (byte_equal(plus.s + j,split,e[t])) + if (e[t][split] == '=') { + --elen; + e[t] = e[elen]; + break; + } + if (plus.s[j + split]) + e[elen++] = plus.s + j; + j = i + 1; + } + e[elen] = 0; + + pathexec_run(*argv,argv,e); + alloc_free(e); +} + +void pathexec_run(const char *file,char *const *argv,char *const *envp) +{ + char *path; + unsigned int split; + int savederrno; + + if (file[str_chr(file,'/')]) { + execve(file,argv,envp); + return; + } + + path = env_get("PATH"); + if (!path) path = "/bin:/usr/bin"; + + savederrno = 0; + for (;;) { + split = str_chr(path,':'); + if (!stralloc_copyb(&tmp,path,split)) return; + if (!split) + if (!stralloc_cats(&tmp,".")) return; + if (!stralloc_cats(&tmp,"/")) return; + if (!stralloc_cats(&tmp,file)) return; + if (!stralloc_0(&tmp)) return; + + execve(tmp.s,argv,envp); + if (errno != ENOENT) { + savederrno = errno; + if ((errno != EACCES) && (errno != EPERM) && (errno != EISDIR)) return; + } + + if (!path[split]) { + if (savederrno) errno = savederrno; + return; + } + path += split; + path += 1; + } +} diff --git a/src/prot.c b/src/prot.c new file mode 100644 index 0000000..078c4b5 --- /dev/null +++ b/src/prot.c @@ -0,0 +1,31 @@ +#include +#include +#include +//#include "hasshsgr.h" +#include "prot.h" + +/** + * @file prot.c + * @author djb + * @ref qmail + * @brief setting up uid an gid for OS (short group was for ancient solaris) + */ + +/* XXX: there are more portability problems here waiting to leap out at me */ + +int prot_gid(int gid) +{ +//#ifdef HASSHORTSETGROUPS +// short x[2]; +// x[0] = gid; x[1] = 73; /* catch errors */ +// if (setgroups(1,x) == -1) return -1; +//#else + if (setgroups(1,(gid_t *)&gid) == -1) return -1; +//#endif + return setgid(gid); /* _should_ be redundant, but on some systems it isn't */ +} + +int prot_uid(int uid) +{ + return setuid(uid); +} diff --git a/src/readclose.c b/src/readclose.c new file mode 100644 index 0000000..7f06b06 --- /dev/null +++ b/src/readclose.c @@ -0,0 +1,43 @@ +#include +#include "open.h" +#include "error.h" +#include "readclose.h" + +/** + * @file readclose.c + * @author kp + * @ref qlibs + * @brief This is the successor of the older 'slurpclose.c' file. + * @brief The function * 'slurpclose' is now called 'readclose_append'. + * @brief The other function 'readclose' was introduced here initial. + */ + +int readclose_append(int fd,stralloc *sa,unsigned int bufsize) +{ + int r; + for (;;) { + if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; } + r = read(fd,sa->s + sa->len,bufsize); + if (r == -1) if (errno == EINTR) continue; + if (r <= 0) { close(fd); return r; } + sa->len += r; + } +} + +int readclose(int fd,stralloc *sa,unsigned int bufsize) +{ + if (!stralloc_copys(sa,"")) { close(fd); return -1; } + return readclose_append(fd,sa,bufsize); +} + +int openreadclose(const char *fn,stralloc *sa,unsigned int bufsize) +{ + int fd; + fd = open_read((char *) fn); + if (fd == -1) { + if (errno == ENOENT) return 0; + return -1; + } + if (readclose(fd,sa,bufsize) == -1) return -1; + return 1; +} diff --git a/src/scan.c b/src/scan.c new file mode 100644 index 0000000..597e76c --- /dev/null +++ b/src/scan.c @@ -0,0 +1,120 @@ +#include "scan.h" + +/** + * @file scan.c + * @author djb + * @ref qmail, ucspi-tcp + * @brief scanning/conversion of strings to different variable types + */ + +static long int fromhex(unsigned char c) +{ + if (c>='0' && c<='9') + return c-'0'; + else if (c>='A' && c<='F') + return c-'A'+10; + else if (c>='a' && c<='f') + return c-'a'+10; + return -1; +} + +unsigned int scan_0x(const char *s,unsigned int *u) +{ + unsigned int pos = 0; + unsigned long result = 0; + long int c; + + while ((c = fromhex((unsigned char) (s[pos]))) >= 0) { + result = (result << 4) + c; + ++pos; + } + *u = result; + return pos; +} + +unsigned int scan_8long(const char *s,unsigned long *u) +{ + unsigned int pos = 0; + unsigned long result = 0; + unsigned long c; + + while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 8) { + result = result * 8 + c; + ++pos; + } + *u = result; + return pos; +} + +unsigned int scan_uint(const char *s,unsigned int *u) +{ + unsigned int pos; + unsigned long result; + + pos = scan_ulong(s,&result); + *u = result; + return pos; +} + +unsigned int scan_plusminus(const char *s,register int *sign) +{ + if (*s == '+') { *sign = 1; return 1; } + if (*s == '-') { *sign = -1; return 1; } + *sign = 1; return 0; +} + +unsigned int scan_long(const char *s,register long *i) +{ + int sign; + unsigned long u; + unsigned int len; + + len = scan_plusminus(s,&sign); s += len; + len += scan_ulong(s,&u); + if (sign < 0) *i = -u; else *i = u; + return len; +} + + +unsigned int scan_ulong(const char *s,unsigned long *u) +{ + unsigned int pos = 0; + unsigned long result = 0; + unsigned long c; + + while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) { + result = result * 10 + c; + ++pos; + } + *u = result; + return pos; +} + +unsigned int scan_xlong(const char *s,unsigned long *u) +{ + const char *t = s; + int l = 0; + unsigned char c; + + while ((c = fromhex(*t)) < 16) { + l = (l<<4)+c; + ++t; + } + *u=l; + return t-s; +} + +unsigned int scan_xint(const char *s,unsigned int *i) +{ + const char *t = s; + unsigned int l = 0; + unsigned char c; + + while ((l >> (sizeof(l)*8 - 4)) == 0 + && (c = (unsigned char)fromhex((unsigned char)*t))<16) { + l= (l << 4) + c; + ++t; + } + *i = l; + return (unsigned int)(t-s); +} diff --git a/src/seek.c b/src/seek.c new file mode 100644 index 0000000..a7b0cac --- /dev/null +++ b/src/seek.c @@ -0,0 +1,40 @@ +#include +#include "seek.h" + +/** + * @file seek.c + * @author djb + * @ref qmail + * @brief seek in an open file descritor + */ + +off_t lseek(int fd,off_t offset,int whence); +int ftruncate(int fd, off_t length); + +#define CUR 1 /* sigh */ + +seek_pos seek_cur(int fd) +{ + return lseek(fd,(off_t) 0,CUR); +} + +#define END 2 /* sigh */ + +int seek_end(int fd) +{ + if (lseek(fd,(off_t) 0,END) == -1) return -1; + return 0; +} + +#define SET 0 /* sigh */ + +int seek_set(int fd,seek_pos pos) +{ + if (lseek(fd,(off_t) pos,SET) == -1) return -1; + return 0; +} + +int seek_trunc(int fd,seek_pos pos) +{ + return ftruncate(fd,(off_t) pos); +} diff --git a/src/sig.c b/src/sig.c new file mode 100644 index 0000000..e4d2bf0 --- /dev/null +++ b/src/sig.c @@ -0,0 +1,169 @@ +#include +#include "sig.h" + +/** + * @file sig.c + * @authors djb, jmh + * @ref qmail + * @brief signal handling functions + */ + +void sig_alarmblock() +{ + sig_block(SIGALRM); +} +void sig_alarmunblock() +{ + sig_unblock(SIGALRM); +} +void sig_alarmcatch(void (*f)(int)) +{ + sig_catch(SIGALRM,f); +} +void sig_alarmdefault() +{ + sig_catch(SIGALRM,SIG_DFL); +} + +int sig_alarm = SIGALRM; + +void sig_block(int sig) +{ + sigset_t ss; + sigemptyset(&ss); + sigaddset(&ss,sig); + sigprocmask(SIG_BLOCK,&ss,(sigset_t *)0); +} + +void sig_unblock(int sig) +{ + sigset_t ss; + sigemptyset(&ss); + sigaddset(&ss,sig); + sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *)0); +} + +void sig_blocknone() +{ + sigset_t ss; + sigemptyset(&ss); + sigprocmask(SIG_SETMASK,&ss,(sigset_t *)0); +} + +void sig_catch(int sig,void (*f)(int)) +{ + struct sigaction sa; + sa.sa_handler = f; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(sig,&sa,(struct sigaction *)0); +} + +void sig_pause() +{ + sigset_t ss; + sigemptyset(&ss); + sigsuspend(&ss); +} + +void sig_pipeignore() +{ + sig_catch(SIGPIPE,SIG_IGN); +} +void sig_pipedefault() +{ + sig_catch(SIGPIPE,SIG_DFL); +} + +int sig_pipe = SIGPIPE; + +void sig_childblock() +{ + sig_block(SIGCHLD); +} +void sig_childunblock() +{ + sig_unblock(SIGCHLD); +} +void sig_childcatch(void (*f)(int)) +{ + sig_catch(SIGCHLD,f); +} +void sig_childdefault() +{ + sig_catch(SIGCHLD,SIG_DFL); +} + +int sig_child = SIGCHLD; + +void sig_hangupblock() +{ + sig_block(SIGHUP); +} +void sig_hangupunblock() +{ + sig_unblock(SIGHUP); +} +void sig_hangupcatch(void (*f)(int)) +{ + sig_catch(SIGHUP,f); +} +void sig_hangupdefault() +{ + sig_catch(SIGHUP,SIG_DFL); +} + +int sig_hangup = SIGHUP; + +void sig_termblock() +{ + sig_block(SIGTERM); +} +void sig_termunblock() +{ + sig_unblock(SIGTERM); +} +void sig_termcatch( void (*f)(int)) +{ + sig_catch(SIGTERM,f); +} +void sig_termdefault() +{ + sig_catch(SIGTERM,SIG_DFL); +} + +int sig_term = SIGTERM; + +void sig_bugcatch(void (*f)(int)) +{ + sig_catch(SIGILL,f); + sig_catch(SIGABRT,f); + sig_catch(SIGFPE,f); + sig_catch(SIGBUS,f); + sig_catch(SIGSEGV,f); +#ifdef SIGSYS + sig_catch(SIGSYS,f); +#endif +#ifdef SIGEMT + sig_catch(SIGEMT,f); +#endif +} +void (*sig_defaulthandler)(int) = SIG_DFL; + +void sig_miscignore() +{ + sig_catch(SIGVTALRM,SIG_IGN); + sig_catch(SIGPROF,SIG_IGN); + sig_catch(SIGQUIT,SIG_IGN); + sig_catch(SIGINT,SIG_IGN); + sig_catch(SIGHUP,SIG_IGN); +#ifdef SIGXCPU + sig_catch(SIGXCPU,SIG_IGN); +#endif +#ifdef SIGXFSZ + sig_catch(SIGXFSZ,SIG_IGN); +#endif +} +void (*sig_ignorehandler)() = SIG_IGN; + +int sig_cont = SIGCONT; diff --git a/src/socket_bind.c b/src/socket_bind.c new file mode 100644 index 0000000..261f386 --- /dev/null +++ b/src/socket_bind.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include "byte.h" +#include "socket_if.h" +#include "ip.h" + +/** + * @file socket_bind.c + * @author djb, fefe, feh + * @ref qmail, djbdns, ucspi-tcp6 + * @brief binding a socket to a local resource + */ + +int socket_bind4(int s,const char ip[4],uint16 port) +{ + struct sockaddr_in sa; + + byte_zero(&sa,sizeof(sa)); + sa.sin_family = AF_INET; + uint16_pack_big((char *)&sa.sin_port,port); + byte_copy((char *)&sa.sin_addr,4,ip); + + return bind(s,(struct sockaddr *)&sa,sizeof(sa)); +} + +int socket_bind4_reuse(int s,const char ip[4],uint16 port) +{ + int opt = 1; + setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); + return socket_bind4(s,ip,port); +} + +/* seems not to be used here -- djbdns requires it */ +void socket_tryreservein(int s,int size) +{ + while (size >= 1024) { + if (setsockopt(s,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size)) == 0) return; + size -= (size >> 5); + } +} + +int socket_bind6(int s,const char ip[16],uint16 port,uint32 scope_id) +{ + struct sockaddr_in6 sa; + + byte_zero(&sa,sizeof(sa)); + sa.sin6_family = AF_INET6; + uint16_pack_big((char *)&sa.sin6_port,port); +/* implicit: sa.sin6_flowinfo = 0; */ + byte_copy((char *)&sa.sin6_addr,16,ip); + sa.sin6_scope_id = scope_id; + + return bind(s,(struct sockaddr *)&sa,sizeof(sa)); +} + +int socket_bind6_reuse(int s,const char ip[16],uint16 port,uint32 scope_id) +{ + int opt = 1; + setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); + return socket_bind6(s,ip,port,scope_id); +} + +int socket_bind(int s,const char ip[16],uint16 port,uint32 scope_id) +{ + if (ip6_isv4mapped(ip)) + return socket_bind4(s,ip + 12,port); + + return socket_bind6(s,ip,port,scope_id); +} + +int socket_bind_reuse(int s,const char ip[16],uint16 port,uint32 scope_id) +{ + if (ip6_isv4mapped(ip)) + return socket_bind4_reuse(s,ip + 12,port); + + return socket_bind6_reuse(s,ip,port,scope_id); +} diff --git a/src/socket_connect.c b/src/socket_connect.c new file mode 100644 index 0000000..4e0dbf0 --- /dev/null +++ b/src/socket_connect.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +#include "byte.h" +#include "socket_if.h" +#include "ip.h" + +/** + * @file socket_connect.c + * @authors djb, fefe, feh, kp + * @ref qmail, ucscpi-tcp6 + * @brief connection to remote IP host + */ + +int socket_connect6(int s,const char ip[16],uint16 port,uint32 scope_id) +{ + struct sockaddr_in6 sa; + + byte_zero(&sa,sizeof(sa)); + sa.sin6_family = AF_INET6; + uint16_pack_big((char *)&sa.sin6_port,port); + sa.sin6_flowinfo = 0; + sa.sin6_scope_id = scope_id; + byte_copy((char *)&sa.sin6_addr,16,ip); + + return connect(s,(struct sockaddr *)&sa,sizeof(sa)); +} + +/* this explizit declaration is needed to prevent compiler warnings */ +int read(int _str, void *_buf, int _b); + +int socket_connect4(int s,const char ip[4],uint16 port) +{ + struct sockaddr_in sa; + + byte_zero(&sa,sizeof(sa)); + sa.sin_family = AF_INET; + uint16_pack_big((char *)&sa.sin_port,port); + byte_copy((char *)&sa.sin_addr,4,ip); + + return connect(s,(struct sockaddr *)&sa,sizeof(sa)); +} + +int socket_connect(int s,const char ip[16],uint16 port,uint32 scope_id) +{ + if (ip6_isv4mapped(ip)) + return socket_connect4(s,ip + 12,port); + + return socket_connect6(s,ip,port,scope_id); +} + +int socket_connected(int s) +{ + struct sockaddr_in6 sa; + int dummy; + char ch; + + dummy = sizeof(sa); + if (getpeername(s,(struct sockaddr *)&sa,(socklen_t *)&dummy) == -1) { + read(s,&ch,1); /* sets errno */ + return 0; + } + return 1; +} diff --git a/src/socket_if.c b/src/socket_if.c new file mode 100644 index 0000000..a7b423a --- /dev/null +++ b/src/socket_if.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include +#include "socket_if.h" + +/** + * @file socket_if.c + * @authors fefe, feh + * @ref ucspi-tcp6 + * @brief interface handling for LLU + */ + +const unsigned char V4loopback[4] = {127,0,0,1}; +const unsigned char V4localnet[4] = {0,0,0,0}; +/* the 'V4mappedprefix' constant is needed by 'ip.a' too */ +const unsigned char V4mappedprefix[12] = {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff}; +const unsigned char V6localnet[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; +const unsigned char V6loopback[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1}; + +uint32 socket_getifidx(const char *ifname) +{ + return if_nametoindex(ifname); +} + +static char ifname[IFNAMSIZ]; + +const char* socket_getifname(uint32 scope_id) +{ + char *tmp = if_indextoname(scope_id,ifname); + if (tmp) + return tmp; + else + return "[unknown]"; +} diff --git a/src/socket_info.c b/src/socket_info.c new file mode 100644 index 0000000..6401cc2 --- /dev/null +++ b/src/socket_info.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include "byte.h" +#include "socket_if.h" +#include "ip.h" + +/** + * @file socket_info.c + * @authors djb, fefe, feh + * @ref ucspi-tcp6 + * @brief querying local and remote info for socket + */ + +int socket_local(int s,char ip[16],uint16 *port,uint32 *scope_id) +{ + struct sockaddr_in6 sa; + unsigned int dummy = sizeof(sa); + + if (getsockname(s,(struct sockaddr *)&sa,&dummy) == -1) return -1; + + if (sa.sin6_family == AF_INET) { + struct sockaddr_in *sa4 = (struct sockaddr_in*)&sa; + byte_copy(ip,12,V4mappedprefix); + byte_copy(ip + 12,4,(char *)&sa4->sin_addr); + uint16_unpack_big((char *)&sa4->sin_port,port); + if (scope_id) *scope_id = 0; + } else { + byte_copy(ip,16,(char *)&sa.sin6_addr); + uint16_unpack_big((char *)&sa.sin6_port,port); + if (scope_id) *scope_id = sa.sin6_scope_id; + } + + return 0; +} + +int socket_remote(int s,char ip[16],uint16 *port,uint32 *scope_id) +{ + struct sockaddr_in6 sa; + unsigned int dummy = sizeof(sa); + + if (getpeername(s,(struct sockaddr *)&sa,&dummy) == -1) return -1; + + if (sa.sin6_family == AF_INET) { + struct sockaddr_in *sa4 = (struct sockaddr_in*)&sa; + byte_copy(ip,12,V4mappedprefix); + byte_copy(ip + 12,4,(char *)&sa4->sin_addr); + uint16_unpack_big((char *)&sa4->sin_port,port); + *scope_id = 0; + } else { + byte_copy(ip,16,(char *)&sa.sin6_addr); + uint16_unpack_big((char *)&sa.sin6_port,port); + *scope_id = sa.sin6_scope_id; + } + + return 0; +} diff --git a/src/socket_recv.c b/src/socket_recv.c new file mode 100644 index 0000000..7e0d8f9 --- /dev/null +++ b/src/socket_recv.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include "byte.h" +#include "ip.h" +#include "socket_if.h" + +/** + * @file socket_recv.c + * @authors djb, fefe + * @ref ucspi-tcp6 + * @brief setup receiving socket + */ + +int socket_recv(int s,char *buf,unsigned int len,char ip[16],uint16 *port,uint32 *scope_id) +{ + struct sockaddr_in6 sa; + unsigned int dummy = sizeof(sa); + int r; + + byte_zero(&sa,dummy); + r = recvfrom(s,buf,len,0,(struct sockaddr *)&sa,&dummy); + if (r == -1) return -1; + + if (sa.sin6_family == AF_INET) { + struct sockaddr_in *sa4 = (struct sockaddr_in *)&sa; + byte_copy(ip,12,V4mappedprefix); + byte_copy(ip + 12,4,(char *)&sa4->sin_addr); + uint16_unpack_big((char *)&sa4->sin_port,port); + if (scope_id) *scope_id = 0; + } else { + byte_copy(ip,16,(char *)&sa.sin6_addr); + uint16_unpack_big((char *)&sa.sin6_port,port); + if (scope_id) *scope_id = sa.sin6_scope_id; + } + + return r; +} diff --git a/src/socket_send.c b/src/socket_send.c new file mode 100644 index 0000000..73b15a2 --- /dev/null +++ b/src/socket_send.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include "byte.h" +#include "ip.h" +#include "socket_if.h" + +/** + * @file socket_send.c + * @authors djb, fefe, feh + * @ref ucspi-tcp6 + * @brief setup sending socket + */ + +int socket_send4(int s,const char *buf,unsigned int len,const char ip[4],uint16 port) +{ + struct sockaddr_in sa; + + byte_zero(&sa,sizeof(sa)); + + sa.sin_family = AF_INET; + uint16_pack_big((char *)&sa.sin_port,port); + byte_copy((char *)&sa.sin_addr,4,ip); + + return sendto(s,buf,len,0,(struct sockaddr *)&sa,sizeof(sa)); +} + +int socket_send6(int s,const char *buf,unsigned int len,const char ip[16],uint16 port,uint32 scope_id) +{ + struct sockaddr_in6 sa; + + byte_zero(&sa,sizeof(sa)); + + sa.sin6_family = AF_INET6; + sa.sin6_scope_id = scope_id; + uint16_pack_big((char *)&sa.sin6_port,port); + byte_copy((char *)&sa.sin6_addr,16,ip); + + return sendto(s,buf,len,0,(struct sockaddr *)&sa,sizeof(sa)); +} + +int socket_send(int s,const char *buf,unsigned int len,const char ip[16],uint16 port,uint32 scope_id) +{ + if (ip6_isv4mapped(ip)) + return socket_send4(s,buf,len,ip + 12,port); + else + return socket_send6(s,buf,len,ip,port,scope_id); +} + +int socket_broadcast4(int s,const char *buf,unsigned int len,uint16 port) +{ + struct sockaddr_in sa; + + byte_zero(&sa,sizeof(sa)); + + sa.sin_family = AF_INET; + uint16_pack_big((char *)&sa.sin_port,port); + byte_copy((char *)&sa.sin_addr,4,V4broadcast); + + return sendto(s,buf,len,0,(struct sockaddr *)&sa,sizeof(sa)); +} diff --git a/src/socket_setup.c b/src/socket_setup.c new file mode 100644 index 0000000..9f6cd00 --- /dev/null +++ b/src/socket_setup.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include "byte.h" +#include "socket_if.h" +#include "ip.h" + +/** + * @file socket_setup.c + * @authors djb, feh + * @ref ucspi-tcp6 + * @brief setup listening socket + */ + +int socket_accept(int s,char ip[16],uint16 *port,uint32 *scope_id) +{ + struct sockaddr_in6 sa; + unsigned int dummy = sizeof(sa); + int fd; + + fd = accept(s,(struct sockaddr *)&sa,&dummy); + if (fd == -1) return -1; + + if (sa.sin6_family == AF_INET) { + struct sockaddr_in *sa4 = (struct sockaddr_in*)&sa; + byte_copy(ip,12,V4mappedprefix); + byte_copy(ip + 12,4,(char *)&sa4->sin_addr); + uint16_unpack_big((char *)&sa4->sin_port,port); + if (scope_id) *scope_id = 0; + } else { + byte_copy(ip,16,(char *)&sa.sin6_addr); + uint16_unpack_big((char *)&sa.sin6_port,port); + if (scope_id) *scope_id = sa.sin6_scope_id; + } + + return fd; +} + +int socket_accept4(int s,char ip[4],uint16 *port) +{ + struct sockaddr_in sa; + unsigned int dummy = sizeof(sa); + int fd; + + fd = accept(s,(struct sockaddr *) &sa,&dummy); + if (fd == -1) return -1; + + byte_copy(ip,4,(char *) &sa.sin_addr); + uint16_unpack_big((char *) &sa.sin_port,port); + + return fd; +} + +int socket_listen(int s,int backlog) +{ + return listen(s,backlog); +} + +int socket_ipoptionskill(int s) +{ + int r; + + r = setsockopt(s,IPPROTO_IP,1,(char *) 0,0); /* 1 == IP_OPTIONS */ + r = setsockopt(s,IPPROTO_IPV6,1,(char *) 0,0); + + return r; +} + +int socket_ip6anycast(int s) +{ + int opt = 1; + int r; + +#ifdef GEN_IP_PKTINFO /* Linux */ + r = setsockopt(s,IPPROTO_IP,GEN_IP_PKTINFO,&opt,sizeof(opt)); +#elif IP_PKTINFO /* Solaris */ + r = setsockopt(s,IPPROTO_IP,IP_PKTINFO,&opt,sizeof(opt)); +#elif IP_RECVDSTADDR /* BSD */ + r = setsockopt(s,IPPROTO_IP,IP_RECVDSTADDR,&opt,sizeof(opt)); +#elif IPV6_RECVDSTADDR + r = setsockopt(s,IPPROTO_IPV6,IP_RECVDSTADDR,&opt,sizeof(opt)); +#endif + return r; +} + +int socket_dualstack(int s) +{ + int opt = 0; + + return setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,&opt,sizeof(opt)); +} + +int socket_nodualstack(int s) +{ + int opt = 1; + + return setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,&opt,sizeof(opt)); +} diff --git a/src/socket_tcp.c b/src/socket_tcp.c new file mode 100644 index 0000000..44667a4 --- /dev/null +++ b/src/socket_tcp.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include "close.h" /* better use unistd.h ? */ +#include "ndelay.h" +#include "socket_if.h" +#include "error.h" + +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT EINVAL +#endif + +/** + * @file socket_tcp.c + * @authors djb, fefe, feh + * @ref ucspi-tcp6 + * @brief setup TCP stream socket + */ + +int socket_tcp4(void) +{ + int s; + + s = socket(AF_INET,SOCK_STREAM,0); + if (s != -1) + if (ndelay_on(s) == -1) { close(s); return -1; } + + return s; +} + +int socket_tcp6(void) +{ + int s; + + s = socket(AF_INET6,SOCK_STREAM,0); + if (s != -1) + if (ndelay_on(s) == -1) { close(s); return -1; } + + return s; +} + +int socket_tcp(void) +{ + int s; + + s = socket(AF_INET6,SOCK_STREAM,0); + if (s == -1) + if (errno == EINVAL || errno == EAFNOSUPPORT || errno == EPROTO || errno == EPROTONOSUPPORT) + s = socket(AF_INET,SOCK_STREAM,0); + + if (s != -1) + if (ndelay_on(s) == -1) { close(s); return -1; } + + return s; +} + +int socket_tcpnodelay(int s) +{ + int opt = 1; + return setsockopt(s,IPPROTO_TCP,1,&opt,sizeof(opt)); /* 1 == TCP_NODELAY */ +} diff --git a/src/socket_udp.c b/src/socket_udp.c new file mode 100644 index 0000000..2fe2ffc --- /dev/null +++ b/src/socket_udp.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include "close.h" /* better use unistd.h ? */ +#include "ndelay.h" +#include "socket_if.h" +#include "error.h" + +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT EINVAL +#endif + +/** + * @file socket_udp.c + * @authors djb, fefe, feh + * @ref ucspi-tcp6 + * @brief setup a UDP message socket + */ + +int socket_udp6(void) +{ + int s; + + s = socket(AF_INET6,SOCK_DGRAM,0); + if (s != -1) + if (ndelay_on(s) == -1) { close(s); return -1; } + + return s; +} + +int socket_udp4(void) +{ + int s; + + s = socket(AF_INET,SOCK_DGRAM,0); + if (s != -1) + if (ndelay_on(s) == -1) { close(s); return -1; } + + return s; +} + +int socket_udp(void) +{ + int s; + + s = socket(AF_INET6,SOCK_DGRAM,0); + if (s == -1) + if (errno == EINVAL || errno == EAFNOSUPPORT || errno == EPROTO || errno == EPROTONOSUPPORT) + s = socket(AF_INET,SOCK_DGRAM,0); + + if (s != -1) + if (ndelay_on(s) == -1) { close(s); return -1; } + + return s; +} diff --git a/src/str.c b/src/str.c new file mode 100644 index 0000000..b632878 --- /dev/null +++ b/src/str.c @@ -0,0 +1,135 @@ +#include "str.h" +#include "stralloc.h" + +/** + * @file str.c + * @authors djb, feh + * @ref qmail + * @brief string handling functions + */ + +unsigned int str_copy(char *s,const char *t) +{ + int len; + + len = 0; + for (;;) { + if (!(*s = *t)) { return len; } ++s; ++t; ++len; + if (!(*s = *t)) { return len; } ++s; ++t; ++len; + if (!(*s = *t)) { return len; } ++s; ++t; ++len; + if (!(*s = *t)) { return len; } ++s; ++t; ++len; + } +} + +unsigned int str_copyb(char *s,const char *t,unsigned int max) +{ + int len; + + len = 0; + + while (max-- > 0) { + if (!(*s = *t)) { return len; } ++s; ++t; ++len; + if (!(*s = *t)) { return len; } ++s; ++t; ++len; + if (!(*s = *t)) { return len; } ++s; ++t; ++len; + if (!(*s = *t)) { return len; } ++s; ++t; ++len; + } + + return len; +} + +int str_diff(const char *s,const char *t) +{ + char x; + + for (;;) { + x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; + x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; + x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; + x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; + } + return ((int)(unsigned int)(unsigned char) x) + - ((int)(unsigned int)(unsigned char) *t); +} + +int str_diffn(const char *s,const char *t,unsigned int len) +{ + char x; + + for (;;) { + if (!len--) { return 0; } x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; + if (!len--) { return 0; } x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; + if (!len--) { return 0; } x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; + if (!len--) { return 0; } x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; + } + return ((int)(unsigned int)(unsigned char) x) + - ((int)(unsigned int)(unsigned char) *t); +} + +unsigned int str_len(const char *s) +{ + const char *t; + + t = s; + for (;;) { + if (!*t) { return t - s; } ++t; + if (!*t) { return t - s; } ++t; + if (!*t) { return t - s; } ++t; + if (!*t) { return t - s; } ++t; + } +} + +unsigned int str_chr(const char *s,int c) +{ + char ch; + const char *t; + + ch = c; + t = s; + for (;;) { + if (!*t) { break; } if (*t == ch) { break; } ++t; + if (!*t) { break; } if (*t == ch) { break; } ++t; + if (!*t) { break; } if (*t == ch) { break; } ++t; + if (!*t) { break; } if (*t == ch) { break; } ++t; + } + return t - s; +} + +unsigned int str_rchr(const char *s,int c) +{ + char ch; + const char *t; + const char *u; + + ch = c; + t = s; + u = 0; + for (;;) { + if (!*t) { break; } if (*t == ch) { u = t; } ++t; + if (!*t) { break; } if (*t == ch) { u = t; } ++t; + if (!*t) { break; } if (*t == ch) { u = t; } ++t; + if (!*t) { break; } if (*t == ch) { u = t; } ++t; + } + if (!u) u = t; + return u - s; +} + +int str_start(const char *s,const char *t) +{ + char x; + + for (;;) { + x = *t++; if (!x) return 1; if (x != *s++) return 0; + x = *t++; if (!x) return 1; if (x != *s++) return 0; + x = *t++; if (!x) return 1; if (x != *s++) return 0; + x = *t++; if (!x) return 1; if (x != *s++) return 0; + } +} + +char *str_append(char *dest, char const *s) +{ + static stralloc sa = {0}; + + stralloc_copys(&sa,dest); + stralloc_catb(&sa,s,sizeof(s)); + return sa.s; +} diff --git a/src/stralloc.c b/src/stralloc.c new file mode 100644 index 0000000..24bd068 --- /dev/null +++ b/src/stralloc.c @@ -0,0 +1,126 @@ +#include +#include "byte.h" +#include "str.h" +#include "stralloc.h" +#include "alloc.h" + +/** + * @file stralloc.c + * @author djb + * @ref qmail, ucspi-tcp + * @brief genious dynamic string handling + */ + +int stralloc_starts(stralloc *sa,const char *s) +{ + int len; + len = str_len(s); + return (sa->len >= len) && byte_equal(s,len,sa->s); +} + +int stralloc_cat(stralloc *sato,stralloc *safrom) +{ + return stralloc_catb(sato,safrom->s,safrom->len); +} + +int stralloc_catb(stralloc *sa,const char *s,unsigned int n) +{ + if (!sa->s) return stralloc_copyb(sa,s,n); + if (!stralloc_readyplus(sa,n + 1)) return 0; + byte_copy(sa->s + sa->len,n,s); + sa->len += n; + sa->s[sa->len] = 'Z'; /* ``offensive programming'' */ + return 1; +} + +int stralloc_cats(stralloc *sa,const char *s) +{ + return stralloc_catb(sa,s,str_len(s)); +} + +int stralloc_copy(stralloc *sato,stralloc *safrom) +{ + return stralloc_copyb(sato,safrom->s,safrom->len); +} + + +int stralloc_ready(stralloc *sa,size_t len) +{ + register size_t wanted = len+(len>>3)+30; /* heuristic from djb */ + if (wanteds || sa->as,wanted))) // !!! needs stdlib (realloc) + return 0; + sa->a = wanted; + sa->s = tmp; + } + return 1; +} + +int stralloc_readyplus(stralloc *sa,size_t len) +{ + if (sa->s) { + if (sa->len + len < len) return 0; /* catch integer overflow */ + return stralloc_ready(sa,sa->len+len); + } else + return stralloc_ready(sa,len); +} + +int stralloc_copyb(stralloc *sa,const char *s,unsigned int n) +{ + if (!stralloc_ready(sa,n + 1)) return 0; + byte_copy(sa->s,n,s); + sa->len = n; + sa->s[n] = 'Z'; /* ``offensive programming'' */ + return 1; +} + +int stralloc_copys(stralloc *sa,const char *s) +{ + return stralloc_copyb(sa,s,str_len(s)); +} + +int stralloc_catulong0(stralloc *sa,unsigned long u,unsigned int n) +{ + unsigned int len; + unsigned long q; + char *s; + + len = 1; + q = u; + while (q > 9) { ++len; q /= 10; } + if (len < n) len = n; + + if (!stralloc_readyplus(sa,len)) return 0; + s = sa->s + sa->len; + sa->len += len; + while (len) { s[--len] = '0' + (u % 10); u /= 10; } + + return 1; +} + +int stralloc_catlong0(stralloc *sa,long l,unsigned int n) +{ + if (l < 0) { + if (!stralloc_append(sa,"-")) return 0; + l = -l; + } + return stralloc_catulong0(sa,l,n); +} + +int stralloc_append(stralloc *sa,const char *in) +{ + if (stralloc_readyplus(sa,1)) { + sa->s[sa->len] = *in; + ++sa->len; + return 1; + } + return 0; +} + +void stralloc_free(stralloc *sa) { + if (sa->s) free(sa->s); + sa->s = 0; + sa->a = sa->len = 0; +} diff --git a/src/tai.c b/src/tai.c new file mode 100644 index 0000000..5ec7652 --- /dev/null +++ b/src/tai.c @@ -0,0 +1,59 @@ +#include +#include "tai.h" + +/** + * @file tai.c + * @author djb + * @ref qmail + * @brief 'temps atomic' time handling + */ + +void tai_add(struct tai *t,const struct tai *u,const struct tai *v) +{ + t->x = u->x + v->x; +} + +void tai_now(struct tai *t) +{ + tai_unix(t,time((time_t *) 0)); +} + +void tai_pack(char *s,const struct tai *t) +{ + uint64 x; + + x = t->x; + s[7] = (char)x; x >>= 8; + s[6] = (char)x; x >>= 8; + s[5] = (char)x; x >>= 8; + s[4] = (char)x; x >>= 8; + s[3] = (char)x; x >>= 8; + s[2] = (char)x; x >>= 8; + s[1] = (char)x; x >>= 8; + s[0] = (char)x; +} + +void tai_sub(struct tai *t,const struct tai *u,const struct tai *v) +{ + t->x = u->x - v->x; +} + +void tai_uint(struct tai *t,unsigned int u) +{ + t->x = u; +} + +void tai_unpack(const char *s,struct tai *t) +{ + uint64 x; + + x = (unsigned char) s[0]; + x <<= 8; x += (unsigned char) s[1]; + x <<= 8; x += (unsigned char) s[2]; + x <<= 8; x += (unsigned char) s[3]; + x <<= 8; x += (unsigned char) s[4]; + x <<= 8; x += (unsigned char) s[5]; + x <<= 8; x += (unsigned char) s[6]; + x <<= 8; x += (unsigned char) s[7]; + t->x = x; +} diff --git a/src/taia.c b/src/taia.c new file mode 100644 index 0000000..92e5255 --- /dev/null +++ b/src/taia.c @@ -0,0 +1,104 @@ +#include +#include +#include "taia.h" + +/** + * @file taia.c + * @author djb + * @ref qmail + * @brief 'tai' attosecond time handling + */ + +/* XXX: breaks tai encapsulation */ + +void taia_add(struct taia *t,struct taia *u,struct taia *v) +{ + t->sec.x = u->sec.x + v->sec.x; + t->nano = u->nano + v->nano; + t->atto = u->atto + v->atto; + if (t->atto > 999999999UL) { + t->atto -= 1000000000UL; + ++t->nano; + } + if (t->nano > 999999999UL) { + t->nano -= 1000000000UL; + ++t->sec.x; + } +} + +double taia_approx(struct taia *t) +{ + return tai_approx(&t->sec) + taia_frac(t); +} + +double taia_frac(struct taia *t) +{ + return (t->atto * 0.000000001 + t->nano) * 0.000000001; +} + +int taia_less(struct taia *t,struct taia *u) +{ + if (t->sec.x < u->sec.x) return 1; + if (t->sec.x > u->sec.x) return 0; + if (t->nano < u->nano) return 1; + if (t->nano > u->nano) return 0; + return t->atto < u->atto; +} + +int taia_now(struct taia *t) +{ + struct timeval now; + if (gettimeofday(&now,(struct timezone *) 0) == 0) { + tai_unix(&t->sec,now.tv_sec); + t->nano = 1000 * now.tv_usec + 500; + t->atto = 0; + return 0; + } + t->nano = 0; + t->atto = 0; + return -1; +} + +void taia_pack(char *s,struct taia *t) +{ + unsigned long x; + + tai_pack(s,&t->sec); + s += 8; + + x = t->atto; + s[7] = x & 255; x >>= 8; + s[6] = x & 255; x >>= 8; + s[5] = x & 255; x >>= 8; + s[4] = x; + x = t->nano; + s[3] = x & 255; x >>= 8; + s[2] = x & 255; x >>= 8; + s[1] = x & 255; x >>= 8; + s[0] = x; +} + +void taia_sub(struct taia *t,struct taia *u,struct taia *v) +{ + unsigned long unano = u->nano; + unsigned long uatto = u->atto; + + t->sec.x = u->sec.x - v->sec.x; + t->nano = unano - v->nano; + t->atto = uatto - v->atto; + if (t->atto > uatto) { + t->atto += 1000000000UL; + --t->nano; + } + if (t->nano > unano) { + t->nano += 1000000000UL; + --t->sec.x; + } +} + +void taia_uint(struct taia *t,unsigned int s) +{ + t->sec.x = s; + t->nano = 0; + t->atto = 0; +} diff --git a/src/timeout.c b/src/timeout.c new file mode 100644 index 0000000..7d3f0b2 --- /dev/null +++ b/src/timeout.c @@ -0,0 +1,60 @@ +#include +#include "error.h" +#include "iopause.h" +#include "timeout.h" + +/** + * @file timeout.c + * @author djb + * @ref qmail + * @brief read/write timeout handling + * @return same as read(2) or write(2); -1 on error + */ + +int timeoutread(int t,int fd,char *buf,int len) +{ + struct taia now; + struct taia deadline; + iopause_fd x; + + taia_now(&now); + taia_uint(&deadline,t); + taia_add(&deadline,&now,&deadline); + + x.fd = fd; + x.events = IOPAUSE_READ; + for (;;) { + taia_now(&now); + iopause(&x,1,&deadline,&now); + if (x.revents) break; + if (taia_less(&deadline,&now)) { + errno = ETIMEDOUT; + return -1; + } + } + return read(fd,buf,len); +} + +int timeoutwrite(int t,int fd,char *buf,int len) +{ + struct taia now; + struct taia deadline; + iopause_fd x; + + taia_now(&now); + taia_uint(&deadline,t); + taia_add(&deadline,&now,&deadline); + + x.fd = fd; + x.events = IOPAUSE_WRITE; + for (;;) { + taia_now(&now); + iopause(&x,1,&deadline,&now); + if (x.revents) break; + if (taia_less(&deadline,&now)) { + errno = ETIMEDOUT; + return -1; + } + } + return write(fd,buf,len); +} diff --git a/src/timeoutconn.c b/src/timeoutconn.c new file mode 100644 index 0000000..0702743 --- /dev/null +++ b/src/timeoutconn.c @@ -0,0 +1,112 @@ +#include "ndelay.h" +#include "socket_if.h" +#include "iopause.h" +#include "error.h" +#include "timeoutconn.h" +#include "ip.h" + +/** + * @file timeoutconn.c + * @authors djb, fefe, feh + * @ref qmail + * @brief socket read/write timeout handling; return code of iopause considered + */ + +int timeoutconn4(int s,char ip[4],uint16 port,unsigned int timeout) +{ + struct taia now; + struct taia deadline; + iopause_fd x; + unsigned int p = 0; + + if (socket_connect4(s,ip,port) == -1) { + if ((errno != EWOULDBLOCK) && (errno != EINPROGRESS)) return -1; + x.fd = s; + x.events = IOPAUSE_WRITE; + taia_now(&now); + taia_uint(&deadline,timeout); + taia_add(&deadline,&now,&deadline); + for (;;) { + taia_now(&now); + iopause(&x,1,&deadline,&now); + if (x.revents) break; /* 's' available */ + if (taia_less(&deadline,&now)) { + errno = ETIMEDOUT; /* note that connect attempt is continuing */ + return -1; + } + p++; + } + if (!socket_connected(s)) return -1; + } + + if (ndelay_off(s) == -1) return -1; + return 0; +} + +int timeoutconn6(int s,char ip[16],uint16 port,unsigned int timeout,uint32 netif) +{ + struct taia now; + struct taia deadline; + iopause_fd x; + unsigned int p = 0; + + if (socket_connect6(s,ip,port,netif) == -1) { + if ((errno != EWOULDBLOCK) && (errno != EINPROGRESS)) return -1; + x.fd = s; + x.events = IOPAUSE_WRITE; + taia_now(&now); + taia_uint(&deadline,timeout); + taia_add(&deadline,&now,&deadline); + for (;;) { + taia_now(&now); + iopause(&x,1,&deadline,&now); + if (x.revents) break; /* 's' available */ + if (taia_less(&deadline,&now)) { + errno = ETIMEDOUT; /* note that connect attempt is continuing */ + return -1; + } + p++; + } + if (!socket_connected(s)) return -1; + } + + if (ndelay_off(s) == -1) return -1; + return 0; +} + +int timeoutconn(int s,char ip[16],uint16 port,unsigned int timeout,uint32 netif) +{ + struct taia now; + struct taia deadline; + iopause_fd x; + unsigned int p = 0; + int r; + + if (ip6_isv4mapped(ip)) + r = socket_connect4(s,ip + 12,port); + else + r = socket_connect6(s,ip,port,netif); + + if (r == -1) { + if ((errno != EWOULDBLOCK) && (errno != EINPROGRESS)) return -1; + x.fd = s; + x.events = IOPAUSE_WRITE; + taia_now(&now); + taia_uint(&deadline,timeout); + taia_add(&deadline,&now,&deadline); + for (;;) { + taia_now(&now); + iopause(&x,1,&deadline,&now); + if (x.revents) break; /* 's' available */ + if (taia_less(&deadline,&now)) { + errno = ETIMEDOUT; /* note that connect attempt is continuing */ + return -1; + } + p++; + } + if (!socket_connected(s)) return -1; + } + + if (ndelay_off(s) == -1) return -1; + return 0; +} diff --git a/src/uint128p.c b/src/uint128p.c new file mode 100644 index 0000000..e109f94 --- /dev/null +++ b/src/uint128p.c @@ -0,0 +1,100 @@ +#include "uint_t.h" + +/** + * @file uint128p.c + * @authors feh, jmh + * @ref djbdns6 + * @brief packing/unpacking 128 bit integer to/from char string + */ + +void uint128_pack(char s[16],uint128 u) +{ + s[0] = u.lo & 255; u.lo >>= 8; + s[1] = u.lo & 255; u.lo >>= 8; + s[2] = u.lo & 255; u.lo >>= 8; + s[3] = u.lo & 255; u.lo >>= 8; + s[4] = u.lo & 255; u.lo >>= 8; + s[5] = u.lo & 255; u.lo >>= 8; + s[6] = u.lo & 255; u.lo >>= 8; + s[7] = u.lo & 255; u.lo >>= 8; + + s[8] = u.hi & 255; u.hi >>= 8; + s[9] = u.hi & 255; u.hi >>= 8; + s[10] = u.hi & 255; u.hi >>= 8; + s[11] = u.hi & 255; u.hi >>= 8; + s[12] = u.hi & 255; u.hi >>= 8; + s[13] = u.hi & 255; u.hi >>= 8; + s[14] = u.hi & 255; u.hi >>= 8; + s[15] = u.hi & 255; +} +void uint128_pack_big(char s[16],uint128 u) +{ + s[15] = u.lo & 255; u.lo >>= 8; + s[14] = u.lo & 255; u.lo >>= 8; + s[13] = u.lo & 255; u.lo >>= 8; + s[12] = u.lo & 255; u.lo >>= 8; + s[11] = u.lo & 255; u.lo >>= 8; + s[10] = u.lo & 255; u.lo >>= 8; + s[9] = u.lo & 255; u.lo >>= 8; + s[8] = u.lo & 255; u.lo >>= 8; + + s[7] = u.hi & 255; u.hi >>= 8; + s[6] = u.hi & 255; u.hi >>= 8; + s[5] = u.hi & 255; u.hi >>= 8; + s[4] = u.hi & 255; u.hi >>= 8; + s[3] = u.hi & 255; u.hi >>= 8; + s[2] = u.hi & 255; u.hi >>= 8; + s[1] = u.hi & 255; u.hi >>= 8; + s[0] = u.hi & 255; +} + +void uint128_unpack(char s[16],uint128 *u) +{ + uint128 result; + result.hi = result.lo = 0ULL; + + result.hi = (unsigned char) s[15]; result.hi <<= 8; + result.hi += (unsigned char) s[14]; result.hi <<= 8; + result.hi += (unsigned char) s[13]; result.hi <<= 8; + result.hi += (unsigned char) s[12]; result.hi <<= 8; + result.hi += (unsigned char) s[11]; result.hi <<= 8; + result.hi += (unsigned char) s[10]; result.hi <<= 8; + result.hi += (unsigned char) s[9]; result.hi <<= 8; + result.hi += (unsigned char) s[8]; //correct + + result.lo += (unsigned char) s[7]; result.lo <<= 8; + result.lo += (unsigned char) s[6]; result.lo <<= 8; + result.lo += (unsigned char) s[5]; result.lo <<= 8; + result.lo += (unsigned char) s[4]; result.lo <<= 8; + result.lo += (unsigned char) s[3]; result.lo <<= 8; + result.lo += (unsigned char) s[2]; result.lo <<= 8; + result.lo += (unsigned char) s[1]; result.lo <<= 8; + result.lo += (unsigned char) s[0]; + + *u = result; +} +void uint128_unpack_big(char s[16],uint128 *u) +{ + uint128 result; + result.hi = result.lo = 0ULL; + + result.hi = (unsigned char) s[0]; result.hi <<= 8; + result.hi += (unsigned char) s[1]; result.hi <<= 8; + result.hi += (unsigned char) s[2]; result.hi <<= 8; + result.hi += (unsigned char) s[3]; result.hi <<= 8; + result.hi += (unsigned char) s[4]; result.hi <<= 8; + result.hi += (unsigned char) s[5]; result.hi <<= 8; + result.hi += (unsigned char) s[6]; result.hi <<= 8; + result.hi += (unsigned char) s[7]; + + result.lo += (unsigned char) s[8]; result.lo <<= 8; + result.lo += (unsigned char) s[9]; result.lo <<= 8; + result.lo += (unsigned char) s[10]; result.lo <<= 8; + result.lo += (unsigned char) s[11]; result.lo <<= 8; + result.lo += (unsigned char) s[12]; result.lo <<= 8; + result.lo += (unsigned char) s[13]; result.lo <<= 8; + result.lo += (unsigned char) s[14]; result.lo <<= 8; + result.lo += (unsigned char) s[15]; + + *u = result; +} diff --git a/src/uint16p.c b/src/uint16p.c new file mode 100644 index 0000000..8d1d481 --- /dev/null +++ b/src/uint16p.c @@ -0,0 +1,40 @@ +#include "uint_t.h" + +/** + * @file uint16p.c + * @author djb + * @ref qmail + * @brief packing/unpacking 16 bit integer to/from char string + */ + +void uint16_pack(char s[2],uint16 u) +{ + s[0] = u & 255; + s[1] = u >> 8; +} + +void uint16_pack_big(char s[2],uint16 u) +{ + s[1] = u & 255; + s[0] = u >> 8; +} + +void uint16_unpack(char s[2],uint16 *u) +{ + uint16 result; + + result = (unsigned char) s[1]; result <<= 8; + result += (unsigned char) s[0]; + + *u = result; +} + +void uint16_unpack_big(char s[2],uint16 *u) +{ + uint16 result; + + result = (unsigned char) s[0]; result <<= 8; + result += (unsigned char) s[1]; + + *u = result; +} diff --git a/src/uint32p.c b/src/uint32p.c new file mode 100644 index 0000000..94327de --- /dev/null +++ b/src/uint32p.c @@ -0,0 +1,47 @@ +#include "uint_t.h" + +/** + * @file uint32p.c + * @author djb + * @ref qmail + * @brief packing/unpacking 32 bit integer to/from char string + */ + +void uint32_pack(char s[4],uint32 u) +{ + s[0] = u & 255; u >>= 8; + s[1] = u & 255; u >>= 8; + s[2] = u & 255; + s[3] = u >> 8; +} +void uint32_pack_big(char s[4],uint32 u) +{ + s[3] = u & 255; u >>= 8; + s[2] = u & 255; u >>= 8; + s[1] = u & 255; + s[0] = u >> 8; +} + +void uint32_unpack(char s[4],uint32 *u) +{ + uint32 result; + + result = (unsigned char) s[3]; result <<= 8; + result += (unsigned char) s[2]; result <<= 8; + result += (unsigned char) s[1]; result <<= 8; + result += (unsigned char) s[0]; + + *u = result; +} + +void uint32_unpack_big(char s[4],uint32 *u) +{ + uint32 result; + + result = (unsigned char) s[0]; result <<= 8; + result += (unsigned char) s[1]; result <<= 8; + result += (unsigned char) s[2]; result <<= 8; + result += (unsigned char) s[3]; + + *u = result; +} diff --git a/src/uint64p.c b/src/uint64p.c new file mode 100644 index 0000000..b6f1988 --- /dev/null +++ b/src/uint64p.c @@ -0,0 +1,62 @@ +#include "uint_t.h" + +/** + * @file uint64p.c + * @authors feh, jmh + * @ref djbdns6 + * @brief packing/unpacking 64 bit integer to/from char string + */ + +void uint64_pack(char s[8],uint64 u) +{ + s[0] = u & 255; u >>= 8; + s[1] = u & 255; u >>= 8; + s[2] = u & 255; u >>= 8; + s[3] = u & 255; u >>= 8; + s[4] = u & 255; u >>= 8; + s[5] = u & 255; u >>= 8; + s[6] = u & 255; u >>= 8; + s[7] = u & 255; +} +void uint64_pack_big(char s[8],uint64 u) +{ + s[7] = u & 255; u >>= 8; + s[6] = u & 255; u >>= 8; + s[5] = u & 255; u >>= 8; + s[4] = u & 255; u >>= 8; + s[3] = u & 255; u >>= 8; + s[2] = u & 255; u >>= 8; + s[1] = u & 255; u >>= 8; + s[0] = u & 255; +} + +void uint64_unpack(char s[8],uint64 *u) +{ + uint64 result; + + result = (unsigned char) s[7]; result <<= 8; + result += (unsigned char) s[6]; result <<= 8; + result += (unsigned char) s[5]; result <<= 8; + result += (unsigned char) s[4]; result <<= 8; + result += (unsigned char) s[3]; result <<= 8; + result += (unsigned char) s[2]; result <<= 8; + result += (unsigned char) s[1]; result <<= 8; + result += (unsigned char) s[0]; + + *u = result; +} +void uint64_unpack_big(char s[8],uint64 *u) +{ + uint64 result; + + result = (unsigned char) s[0]; result <<= 8; + result += (unsigned char) s[1]; result <<= 8; + result += (unsigned char) s[2]; result <<= 8; + result += (unsigned char) s[3]; result <<= 8; + result += (unsigned char) s[4]; result <<= 8; + result += (unsigned char) s[5]; result <<= 8; + result += (unsigned char) s[6]; result <<= 8; + result += (unsigned char) s[7]; + + *u = result; +} diff --git a/src/uint8p.c b/src/uint8p.c new file mode 100644 index 0000000..3a41560 --- /dev/null +++ b/src/uint8p.c @@ -0,0 +1,39 @@ +#include "uint_t.h" + +/** + * @file uint8p.c + * @author feh + * @brief packing/unpacking 8 bit int to/from char string + */ + +void uint8_pack(char s[2],uint8 u) +{ + s[0] = u & 255; + s[1] = u >> 4; +} + +void uint8_pack_big(char s[2],uint8 u) +{ + s[1] = u & 255; + s[0] = u >> 4; +} + +void uint8_unpack(char s[2],uint8 *u) +{ + uint8 result; + + result = (unsigned char) s[1]; result <<= 4; + result += (unsigned char) s[0]; + + *u = result; +} + +void uint8_unpack_big(char s[2],uint8 *u) +{ + uint8 result; + + result = (unsigned char) s[0]; result <<= 4; + result += (unsigned char) s[1]; + + *u = result; +} diff --git a/src/wait.c b/src/wait.c new file mode 100644 index 0000000..4043a4f --- /dev/null +++ b/src/wait.c @@ -0,0 +1,25 @@ +#include +#include +#include "logmsg.h" + +/** + * @file wait.c + * @author djb + * @ref qmail + * @brief wait for forked processes + */ + +int wait_nohang(int *wstat) +{ + return waitpid(-1,wstat,WNOHANG); +} + +int wait_pid(int *wstat,int pid) +{ + int r; + + do + r = waitpid(pid,wstat,0); + while ((r == -1) && (errno == EINTR)); + return r; +} diff --git a/str.c b/str.c deleted file mode 100644 index 7d5ab5e..0000000 --- a/str.c +++ /dev/null @@ -1,135 +0,0 @@ -#include "str.h" -#include "stralloc.h" - -/** - @file str.c - @author djb - @source qmail - @brief string handling functions -*/ - -unsigned int str_copy(register char *s,register const char *t) -{ - register int len; - - len = 0; - for (;;) { - if (!(*s = *t)) { return len; } ++s; ++t; ++len; - if (!(*s = *t)) { return len; } ++s; ++t; ++len; - if (!(*s = *t)) { return len; } ++s; ++t; ++len; - if (!(*s = *t)) { return len; } ++s; ++t; ++len; - } -} - -unsigned int str_copyb(register char *s,register const char *t,unsigned int max) -{ - register int len; - - len = 0; - - while (max-- > 0) { - if (!(*s = *t)) { return len; } ++s; ++t; ++len; - if (!(*s = *t)) { return len; } ++s; ++t; ++len; - if (!(*s = *t)) { return len; } ++s; ++t; ++len; - if (!(*s = *t)) { return len; } ++s; ++t; ++len; - } - - return len; -} - -int str_diff(register const char *s,register const char *t) -{ - register char x; - - for (;;) { - x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; - x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; - x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; - x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; - } - return ((int)(unsigned int)(unsigned char) x) - - ((int)(unsigned int)(unsigned char) *t); -} - -int str_diffn(register const char *s,register const char *t,unsigned int len) -{ - register char x; - - for (;;) { - if (!len--) { return 0; } x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; - if (!len--) { return 0; } x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; - if (!len--) { return 0; } x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; - if (!len--) { return 0; } x = *s; if (x != *t) { break; } if (!x) { break; } ++s; ++t; - } - return ((int)(unsigned int)(unsigned char) x) - - ((int)(unsigned int)(unsigned char) *t); -} - -unsigned int str_len(register const char *s) -{ - register const char *t; - - t = s; - for (;;) { - if (!*t) { return t - s; } ++t; - if (!*t) { return t - s; } ++t; - if (!*t) { return t - s; } ++t; - if (!*t) { return t - s; } ++t; - } -} - -unsigned int str_chr(register const char *s,int c) -{ - register char ch; - register const char *t; - - ch = c; - t = s; - for (;;) { - if (!*t) { break; } if (*t == ch) { break; } ++t; - if (!*t) { break; } if (*t == ch) { break; } ++t; - if (!*t) { break; } if (*t == ch) { break; } ++t; - if (!*t) { break; } if (*t == ch) { break; } ++t; - } - return t - s; -} - -unsigned int str_rchr(register const char *s,int c) -{ - register char ch; - register const char *t; - register const char *u; - - ch = c; - t = s; - u = 0; - for (;;) { - if (!*t) { break; } if (*t == ch) { u = t; } ++t; - if (!*t) { break; } if (*t == ch) { u = t; } ++t; - if (!*t) { break; } if (*t == ch) { u = t; } ++t; - if (!*t) { break; } if (*t == ch) { u = t; } ++t; - } - if (!u) u = t; - return u - s; -} - -int str_start(register const char *s,register const char *t) -{ - register char x; - - for (;;) { - x = *t++; if (!x) return 1; if (x != *s++) return 0; - x = *t++; if (!x) return 1; if (x != *s++) return 0; - x = *t++; if (!x) return 1; if (x != *s++) return 0; - x = *t++; if (!x) return 1; if (x != *s++) return 0; - } -} - -char *str_append(char *dest, char const *s) -{ - static stralloc sa = {0}; - - stralloc_copys(&sa,dest); - stralloc_catb(&sa,s,sizeof(s)); - return sa.s; -} diff --git a/stralloc.c b/stralloc.c deleted file mode 100644 index 8c0335e..0000000 --- a/stralloc.c +++ /dev/null @@ -1,126 +0,0 @@ -#include -#include "byte.h" -#include "str.h" -#include "stralloc.h" -#include "alloc.h" - -/** - @file stralloc.c - @author djb - @source qmail, ucspi-tcp - @brief genious dynamic string handling -*/ - -int stralloc_starts(stralloc *sa,const char *s) -{ - int len; - len = str_len(s); - return (sa->len >= len) && byte_equal(s,len,sa->s); -} - -int stralloc_cat(stralloc *sato,stralloc *safrom) -{ - return stralloc_catb(sato,safrom->s,safrom->len); -} - -int stralloc_catb(stralloc *sa,const char *s,unsigned int n) -{ - if (!sa->s) return stralloc_copyb(sa,s,n); - if (!stralloc_readyplus(sa,n + 1)) return 0; - byte_copy(sa->s + sa->len,n,s); - sa->len += n; - sa->s[sa->len] = 'Z'; /* ``offensive programming'' */ - return 1; -} - -int stralloc_cats(stralloc *sa,const char *s) -{ - return stralloc_catb(sa,s,str_len(s)); -} - -int stralloc_copy(stralloc *sato,stralloc *safrom) -{ - return stralloc_copyb(sato,safrom->s,safrom->len); -} - - -int stralloc_ready(stralloc *sa,size_t len) -{ - register size_t wanted = len+(len>>3)+30; /* heuristic from djb */ - if (wanteds || sa->as,wanted))) // !!! needs stdlib (realloc) - return 0; - sa->a = wanted; - sa->s = tmp; - } - return 1; -} - -int stralloc_readyplus(stralloc *sa,size_t len) -{ - if (sa->s) { - if (sa->len + len < len) return 0; /* catch integer overflow */ - return stralloc_ready(sa,sa->len+len); - } else - return stralloc_ready(sa,len); -} - -int stralloc_copyb(stralloc *sa,const char *s,unsigned int n) -{ - if (!stralloc_ready(sa,n + 1)) return 0; - byte_copy(sa->s,n,s); - sa->len = n; - sa->s[n] = 'Z'; /* ``offensive programming'' */ - return 1; -} - -int stralloc_copys(stralloc *sa,const char *s) -{ - return stralloc_copyb(sa,s,str_len(s)); -} - -int stralloc_catulong0(stralloc *sa,unsigned long u,unsigned int n) -{ - unsigned int len; - unsigned long q; - char *s; - - len = 1; - q = u; - while (q > 9) { ++len; q /= 10; } - if (len < n) len = n; - - if (!stralloc_readyplus(sa,len)) return 0; - s = sa->s + sa->len; - sa->len += len; - while (len) { s[--len] = '0' + (u % 10); u /= 10; } - - return 1; -} - -int stralloc_catlong0(stralloc *sa,long l,unsigned int n) -{ - if (l < 0) { - if (!stralloc_append(sa,"-")) return 0; - l = -l; - } - return stralloc_catulong0(sa,l,n); -} - -int stralloc_append(stralloc *sa,const char *in) -{ - if (stralloc_readyplus(sa,1)) { - sa->s[sa->len] = *in; - ++sa->len; - return 1; - } - return 0; -} - -void stralloc_free(stralloc *sa) { - if (sa->s) free(sa->s); - sa->s = 0; - sa->a = sa->len = 0; -} diff --git a/tai.c b/tai.c deleted file mode 100644 index 65a8225..0000000 --- a/tai.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include "tai.h" - -/** - @file tai.c - @author djb - @source qmail - @brief 'temps atomic' time handling -*/ - -void tai_add(struct tai *t,const struct tai *u,const struct tai *v) -{ - t->x = u->x + v->x; -} - -void tai_now(struct tai *t) -{ - tai_unix(t,time((time_t *) 0)); -} - -void tai_pack(char *s,const struct tai *t) -{ - uint64 x; - - x = t->x; - s[7] = (char)x; x >>= 8; - s[6] = (char)x; x >>= 8; - s[5] = (char)x; x >>= 8; - s[4] = (char)x; x >>= 8; - s[3] = (char)x; x >>= 8; - s[2] = (char)x; x >>= 8; - s[1] = (char)x; x >>= 8; - s[0] = (char)x; -} - -void tai_sub(struct tai *t,const struct tai *u,const struct tai *v) -{ - t->x = u->x - v->x; -} - -void tai_uint(struct tai *t,unsigned int u) -{ - t->x = u; -} - -void tai_unpack(const char *s,struct tai *t) -{ - uint64 x; - - x = (unsigned char) s[0]; - x <<= 8; x += (unsigned char) s[1]; - x <<= 8; x += (unsigned char) s[2]; - x <<= 8; x += (unsigned char) s[3]; - x <<= 8; x += (unsigned char) s[4]; - x <<= 8; x += (unsigned char) s[5]; - x <<= 8; x += (unsigned char) s[6]; - x <<= 8; x += (unsigned char) s[7]; - t->x = x; -} diff --git a/taia.c b/taia.c deleted file mode 100644 index 22bd816..0000000 --- a/taia.c +++ /dev/null @@ -1,104 +0,0 @@ -#include -#include -#include "taia.h" - -/** - @file taia.c - @author djb - @source qmail - @brief 'tai' attosecond time handling -*/ - -/* XXX: breaks tai encapsulation */ - -void taia_add(struct taia *t,struct taia *u,struct taia *v) -{ - t->sec.x = u->sec.x + v->sec.x; - t->nano = u->nano + v->nano; - t->atto = u->atto + v->atto; - if (t->atto > 999999999UL) { - t->atto -= 1000000000UL; - ++t->nano; - } - if (t->nano > 999999999UL) { - t->nano -= 1000000000UL; - ++t->sec.x; - } -} - -double taia_approx(struct taia *t) -{ - return tai_approx(&t->sec) + taia_frac(t); -} - -double taia_frac(struct taia *t) -{ - return (t->atto * 0.000000001 + t->nano) * 0.000000001; -} - -int taia_less(struct taia *t,struct taia *u) -{ - if (t->sec.x < u->sec.x) return 1; - if (t->sec.x > u->sec.x) return 0; - if (t->nano < u->nano) return 1; - if (t->nano > u->nano) return 0; - return t->atto < u->atto; -} - -int taia_now(struct taia *t) -{ - struct timeval now; - if (gettimeofday(&now,(struct timezone *) 0) == 0) { - tai_unix(&t->sec,now.tv_sec); - t->nano = 1000 * now.tv_usec + 500; - t->atto = 0; - return 0; - } - t->nano = 0; - t->atto = 0; - return -1; -} - -void taia_pack(char *s,struct taia *t) -{ - unsigned long x; - - tai_pack(s,&t->sec); - s += 8; - - x = t->atto; - s[7] = x & 255; x >>= 8; - s[6] = x & 255; x >>= 8; - s[5] = x & 255; x >>= 8; - s[4] = x; - x = t->nano; - s[3] = x & 255; x >>= 8; - s[2] = x & 255; x >>= 8; - s[1] = x & 255; x >>= 8; - s[0] = x; -} - -void taia_sub(struct taia *t,struct taia *u,struct taia *v) -{ - unsigned long unano = u->nano; - unsigned long uatto = u->atto; - - t->sec.x = u->sec.x - v->sec.x; - t->nano = unano - v->nano; - t->atto = uatto - v->atto; - if (t->atto > uatto) { - t->atto += 1000000000UL; - --t->nano; - } - if (t->nano > unano) { - t->nano += 1000000000UL; - --t->sec.x; - } -} - -void taia_uint(struct taia *t,unsigned int s) -{ - t->sec.x = s; - t->nano = 0; - t->atto = 0; -} diff --git a/timeout.c b/timeout.c deleted file mode 100644 index e721b66..0000000 --- a/timeout.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include "error.h" -#include "iopause.h" -#include "timeout.h" - -/** - @file timeout.c - @author djb - @source qmail - @brief read/write timeout handling -*/ - -int timeoutread(int t,int fd,char *buf,int len) -{ - struct taia now; - struct taia deadline; - iopause_fd x; - - taia_now(&now); - taia_uint(&deadline,t); - taia_add(&deadline,&now,&deadline); - - x.fd = fd; - x.events = IOPAUSE_READ; - for (;;) { - taia_now(&now); - iopause(&x,1,&deadline,&now); - if (x.revents) break; - if (taia_less(&deadline,&now)) { - errno = ETIMEDOUT; - return -1; - } - } - return read(fd,buf,len); -} - -int timeoutwrite(int t,int fd,char *buf,int len) -{ - struct taia now; - struct taia deadline; - iopause_fd x; - - taia_now(&now); - taia_uint(&deadline,t); - taia_add(&deadline,&now,&deadline); - - x.fd = fd; - x.events = IOPAUSE_WRITE; - for (;;) { - taia_now(&now); - iopause(&x,1,&deadline,&now); - if (x.revents) break; - if (taia_less(&deadline,&now)) { - errno = ETIMEDOUT; - return -1; - } - } - return write(fd,buf,len); -} diff --git a/timeoutconn.c b/timeoutconn.c deleted file mode 100644 index c94f600..0000000 --- a/timeoutconn.c +++ /dev/null @@ -1,112 +0,0 @@ -#include "ndelay.h" -#include "socket_if.h" -#include "iopause.h" -#include "error.h" -#include "timeoutconn.h" -#include "ip.h" - -/** - @file timeoutconn.c - @author djb, fefe, feh - @source qmail - @brief socket read/write timeout handling; return code of iopause considered -*/ - -int timeoutconn4(int s,char ip[4],uint16 port,unsigned int timeout) -{ - struct taia now; - struct taia deadline; - iopause_fd x; - unsigned int p = 0; - - if (socket_connect4(s,ip,port) == -1) { - if ((errno != EWOULDBLOCK) && (errno != EINPROGRESS)) return -1; - x.fd = s; - x.events = IOPAUSE_WRITE; - taia_now(&now); - taia_uint(&deadline,timeout); - taia_add(&deadline,&now,&deadline); - for (;;) { - taia_now(&now); - iopause(&x,1,&deadline,&now); - if (x.revents) break; /* 's' available */ - if (taia_less(&deadline,&now)) { - errno = ETIMEDOUT; /* note that connect attempt is continuing */ - return -1; - } - p++; - } - if (!socket_connected(s)) return -1; - } - - if (ndelay_off(s) == -1) return -1; - return 0; -} - -int timeoutconn6(int s,char ip[16],uint16 port,unsigned int timeout,uint32 netif) -{ - struct taia now; - struct taia deadline; - iopause_fd x; - unsigned int p = 0; - - if (socket_connect6(s,ip,port,netif) == -1) { - if ((errno != EWOULDBLOCK) && (errno != EINPROGRESS)) return -1; - x.fd = s; - x.events = IOPAUSE_WRITE; - taia_now(&now); - taia_uint(&deadline,timeout); - taia_add(&deadline,&now,&deadline); - for (;;) { - taia_now(&now); - iopause(&x,1,&deadline,&now); - if (x.revents) break; /* 's' available */ - if (taia_less(&deadline,&now)) { - errno = ETIMEDOUT; /* note that connect attempt is continuing */ - return -1; - } - p++; - } - if (!socket_connected(s)) return -1; - } - - if (ndelay_off(s) == -1) return -1; - return 0; -} - -int timeoutconn(int s,char ip[16],uint16 port,unsigned int timeout,uint32 netif) -{ - struct taia now; - struct taia deadline; - iopause_fd x; - unsigned int p = 0; - int r; - - if (ip6_isv4mapped(ip)) - r = socket_connect4(s,ip + 12,port); - else - r = socket_connect6(s,ip,port,netif); - - if (r == -1) { - if ((errno != EWOULDBLOCK) && (errno != EINPROGRESS)) return -1; - x.fd = s; - x.events = IOPAUSE_WRITE; - taia_now(&now); - taia_uint(&deadline,timeout); - taia_add(&deadline,&now,&deadline); - for (;;) { - taia_now(&now); - iopause(&x,1,&deadline,&now); - if (x.revents) break; /* 's' available */ - if (taia_less(&deadline,&now)) { - errno = ETIMEDOUT; /* note that connect attempt is continuing */ - return -1; - } - p++; - } - if (!socket_connected(s)) return -1; - } - - if (ndelay_off(s) == -1) return -1; - return 0; -} diff --git a/uint128p.c b/uint128p.c deleted file mode 100644 index 57c713e..0000000 --- a/uint128p.c +++ /dev/null @@ -1,100 +0,0 @@ -#include "uint_t.h" - -/** - @file uint128p.c - @author feh, jannis - @source djbdns6 - @brief packing/unpacking 128 bit integer to/from char string -*/ - -void uint128_pack(char s[16],uint128 u) -{ - s[0] = u.lo & 255; u.lo >>= 8; - s[1] = u.lo & 255; u.lo >>= 8; - s[2] = u.lo & 255; u.lo >>= 8; - s[3] = u.lo & 255; u.lo >>= 8; - s[4] = u.lo & 255; u.lo >>= 8; - s[5] = u.lo & 255; u.lo >>= 8; - s[6] = u.lo & 255; u.lo >>= 8; - s[7] = u.lo & 255; u.lo >>= 8; - - s[8] = u.hi & 255; u.hi >>= 8; - s[9] = u.hi & 255; u.hi >>= 8; - s[10] = u.hi & 255; u.hi >>= 8; - s[11] = u.hi & 255; u.hi >>= 8; - s[12] = u.hi & 255; u.hi >>= 8; - s[13] = u.hi & 255; u.hi >>= 8; - s[14] = u.hi & 255; u.hi >>= 8; - s[15] = u.hi & 255; -} -void uint128_pack_big(char s[16],uint128 u) -{ - s[15] = u.lo & 255; u.lo >>= 8; - s[14] = u.lo & 255; u.lo >>= 8; - s[13] = u.lo & 255; u.lo >>= 8; - s[12] = u.lo & 255; u.lo >>= 8; - s[11] = u.lo & 255; u.lo >>= 8; - s[10] = u.lo & 255; u.lo >>= 8; - s[9] = u.lo & 255; u.lo >>= 8; - s[8] = u.lo & 255; u.lo >>= 8; - - s[7] = u.hi & 255; u.hi >>= 8; - s[6] = u.hi & 255; u.hi >>= 8; - s[5] = u.hi & 255; u.hi >>= 8; - s[4] = u.hi & 255; u.hi >>= 8; - s[3] = u.hi & 255; u.hi >>= 8; - s[2] = u.hi & 255; u.hi >>= 8; - s[1] = u.hi & 255; u.hi >>= 8; - s[0] = u.hi & 255; -} - -void uint128_unpack(char s[16],uint128 *u) -{ - uint128 result; - result.hi = result.lo = 0ULL; - - result.hi = (unsigned char) s[15]; result.hi <<= 8; - result.hi += (unsigned char) s[14]; result.hi <<= 8; - result.hi += (unsigned char) s[13]; result.hi <<= 8; - result.hi += (unsigned char) s[12]; result.hi <<= 8; - result.hi += (unsigned char) s[11]; result.hi <<= 8; - result.hi += (unsigned char) s[10]; result.hi <<= 8; - result.hi += (unsigned char) s[9]; result.hi <<= 8; - result.hi += (unsigned char) s[8]; //correct - - result.lo += (unsigned char) s[7]; result.lo <<= 8; - result.lo += (unsigned char) s[6]; result.lo <<= 8; - result.lo += (unsigned char) s[5]; result.lo <<= 8; - result.lo += (unsigned char) s[4]; result.lo <<= 8; - result.lo += (unsigned char) s[3]; result.lo <<= 8; - result.lo += (unsigned char) s[2]; result.lo <<= 8; - result.lo += (unsigned char) s[1]; result.lo <<= 8; - result.lo += (unsigned char) s[0]; - - *u = result; -} -void uint128_unpack_big(char s[16],uint128 *u) -{ - uint128 result; - result.hi = result.lo = 0ULL; - - result.hi = (unsigned char) s[0]; result.hi <<= 8; - result.hi += (unsigned char) s[1]; result.hi <<= 8; - result.hi += (unsigned char) s[2]; result.hi <<= 8; - result.hi += (unsigned char) s[3]; result.hi <<= 8; - result.hi += (unsigned char) s[4]; result.hi <<= 8; - result.hi += (unsigned char) s[5]; result.hi <<= 8; - result.hi += (unsigned char) s[6]; result.hi <<= 8; - result.hi += (unsigned char) s[7]; - - result.lo += (unsigned char) s[8]; result.lo <<= 8; - result.lo += (unsigned char) s[9]; result.lo <<= 8; - result.lo += (unsigned char) s[10]; result.lo <<= 8; - result.lo += (unsigned char) s[11]; result.lo <<= 8; - result.lo += (unsigned char) s[12]; result.lo <<= 8; - result.lo += (unsigned char) s[13]; result.lo <<= 8; - result.lo += (unsigned char) s[14]; result.lo <<= 8; - result.lo += (unsigned char) s[15]; - - *u = result; -} diff --git a/uint16p.c b/uint16p.c deleted file mode 100644 index 5dddf21..0000000 --- a/uint16p.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "uint_t.h" - -/** - @file uint16p.c - @author djb - @source qmail - @brief packing/unpacking 16 bit integer to/from char string -*/ - -void uint16_pack(char s[2],uint16 u) -{ - s[0] = u & 255; - s[1] = u >> 8; -} - -void uint16_pack_big(char s[2],uint16 u) -{ - s[1] = u & 255; - s[0] = u >> 8; -} - -void uint16_unpack(char s[2],uint16 *u) -{ - uint16 result; - - result = (unsigned char) s[1]; result <<= 8; - result += (unsigned char) s[0]; - - *u = result; -} - -void uint16_unpack_big(char s[2],uint16 *u) -{ - uint16 result; - - result = (unsigned char) s[0]; result <<= 8; - result += (unsigned char) s[1]; - - *u = result; -} diff --git a/uint32p.c b/uint32p.c deleted file mode 100644 index f3f04ea..0000000 --- a/uint32p.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "uint_t.h" - -/** - @file uint32p.c - @author djb - @source qmail - @brief packing/unpacking 32 bit integer to/from char string -*/ - -void uint32_pack(char s[4],uint32 u) -{ - s[0] = u & 255; u >>= 8; - s[1] = u & 255; u >>= 8; - s[2] = u & 255; - s[3] = u >> 8; -} -void uint32_pack_big(char s[4],uint32 u) -{ - s[3] = u & 255; u >>= 8; - s[2] = u & 255; u >>= 8; - s[1] = u & 255; - s[0] = u >> 8; -} - -void uint32_unpack(char s[4],uint32 *u) -{ - uint32 result; - - result = (unsigned char) s[3]; result <<= 8; - result += (unsigned char) s[2]; result <<= 8; - result += (unsigned char) s[1]; result <<= 8; - result += (unsigned char) s[0]; - - *u = result; -} - -void uint32_unpack_big(char s[4],uint32 *u) -{ - uint32 result; - - result = (unsigned char) s[0]; result <<= 8; - result += (unsigned char) s[1]; result <<= 8; - result += (unsigned char) s[2]; result <<= 8; - result += (unsigned char) s[3]; - - *u = result; -} diff --git a/uint64p.c b/uint64p.c deleted file mode 100644 index 41b8ceb..0000000 --- a/uint64p.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "uint_t.h" - -/** - @file uint64p.c - @author feh, jannis - @source djbdns6 - @brief packing/unpacking 64 bit integer to/from char string -*/ - -void uint64_pack(char s[8],uint64 u) -{ - s[0] = u & 255; u >>= 8; - s[1] = u & 255; u >>= 8; - s[2] = u & 255; u >>= 8; - s[3] = u & 255; u >>= 8; - s[4] = u & 255; u >>= 8; - s[5] = u & 255; u >>= 8; - s[6] = u & 255; u >>= 8; - s[7] = u & 255; -} -void uint64_pack_big(char s[8],uint64 u) -{ - s[7] = u & 255; u >>= 8; - s[6] = u & 255; u >>= 8; - s[5] = u & 255; u >>= 8; - s[4] = u & 255; u >>= 8; - s[3] = u & 255; u >>= 8; - s[2] = u & 255; u >>= 8; - s[1] = u & 255; u >>= 8; - s[0] = u & 255; -} - -void uint64_unpack(char s[8],uint64 *u) -{ - uint64 result; - - result = (unsigned char) s[7]; result <<= 8; - result += (unsigned char) s[6]; result <<= 8; - result += (unsigned char) s[5]; result <<= 8; - result += (unsigned char) s[4]; result <<= 8; - result += (unsigned char) s[3]; result <<= 8; - result += (unsigned char) s[2]; result <<= 8; - result += (unsigned char) s[1]; result <<= 8; - result += (unsigned char) s[0]; - - *u = result; -} -void uint64_unpack_big(char s[8],uint64 *u) -{ - uint64 result; - - result = (unsigned char) s[0]; result <<= 8; - result += (unsigned char) s[1]; result <<= 8; - result += (unsigned char) s[2]; result <<= 8; - result += (unsigned char) s[3]; result <<= 8; - result += (unsigned char) s[4]; result <<= 8; - result += (unsigned char) s[5]; result <<= 8; - result += (unsigned char) s[6]; result <<= 8; - result += (unsigned char) s[7]; - - *u = result; -} diff --git a/uint8p.c b/uint8p.c deleted file mode 100644 index a7a1460..0000000 --- a/uint8p.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "uint_t.h" - -/** - @file uint8x.c - @author feh - @brief packing/unpacking 8 bit int to/from char string -*/ - -void uint8_pack(char s[2],uint8 u) -{ - s[0] = u & 255; - s[1] = u >> 4; -} - -void uint8_pack_big(char s[2],uint8 u) -{ - s[1] = u & 255; - s[0] = u >> 4; -} - -void uint8_unpack(char s[2],uint8 *u) -{ - uint8 result; - - result = (unsigned char) s[1]; result <<= 4; - result += (unsigned char) s[0]; - - *u = result; -} - -void uint8_unpack_big(char s[2],uint8 *u) -{ - uint8 result; - - result = (unsigned char) s[0]; result <<= 4; - result += (unsigned char) s[1]; - - *u = result; -} diff --git a/wait.c b/wait.c deleted file mode 100644 index 869a120..0000000 --- a/wait.c +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include "logmsg.h" - -/** - @file wait.c - @author djb - @source qmail - @brief wait for forked processes -*/ - -int wait_nohang(int *wstat) -{ - return waitpid(-1,wstat,WNOHANG); -} - -int wait_pid(int *wstat,int pid) -{ - int r; - - do - r = waitpid(pid,wstat,0); - while ((r == -1) && (errno == EINTR)); - return r; -} -- cgit v1.2.3