diff --git a/src/mkinitcpio-netconf/.SRCINFO b/src/mkinitcpio-netconf/.SRCINFO new file mode 100644 index 0000000..274379d --- /dev/null +++ b/src/mkinitcpio-netconf/.SRCINFO @@ -0,0 +1,17 @@ +# Generated by mksrcinfo v8 +# Fri Oct 21 11:22:56 UTC 2016 +pkgbase = mkinitcpio-netconf + pkgdesc = Archlinux mkinitcpio hook for configuring early userspace networking + pkgver = 0.0.4 + pkgrel = 2 + url = https://github.com/grazzolini/mkinitcpio-netconf + changelog = Changelog + arch = any + license = BSD + depends = mkinitcpio-nfs-utils + depends = iproute2 + source = mkinitcpio-netconf-0.0.4.tar.gz::https://github.com/grazzolini/mkinitcpio-netconf/archive/v0.0.4.tar.gz + sha512sums = 06ac202410964740785d2977f7918981276e10568260433436c51a1d540152cc28462e46dae6bfa31acd1fafa9ebe1e4f57ca90d7754a09ccaba142c8d48b228 + +pkgname = mkinitcpio-netconf + diff --git a/src/mkinitcpio-netconf/.gitignore b/src/mkinitcpio-netconf/.gitignore new file mode 100644 index 0000000..56dc8d7 --- /dev/null +++ b/src/mkinitcpio-netconf/.gitignore @@ -0,0 +1,6 @@ +v*.tar.gz +mkinitcpio-netconf-*-any.pkg.tar.xz +mkinitcpio-netconf-*.tar.gz +develop.* +pkg/* +src/* diff --git a/src/mkinitcpio-netconf/Changelog b/src/mkinitcpio-netconf/Changelog new file mode 100644 index 0000000..5ac3d7f --- /dev/null +++ b/src/mkinitcpio-netconf/Changelog @@ -0,0 +1,13 @@ +2015-08-11 Giancarlo Razzolini + + * 0.0.2 : + - Initial support for systemd enabled initrd: + + Check for any files ending in .initramfs in the /etc/systemd/network directory, and copies them to the initrd, and also copy and install systemd-networkd. + + There are some caveats, specially that it won't remove any ip addresses added to the interface: https://github.com/systemd/systemd/issues/780 + - Corrected the help text. + +2015-07-15 Giancarlo Razzolini + + * 0.0.1 : + - Initial release. + - Right now it only support the ip= configuration mode. diff --git a/src/mkinitcpio-netconf/PKGBUILD b/src/mkinitcpio-netconf/PKGBUILD new file mode 100644 index 0000000..0b9a6f8 --- /dev/null +++ b/src/mkinitcpio-netconf/PKGBUILD @@ -0,0 +1,20 @@ +# Maintainer: Giancarlo Razzolini +pkgname=mkinitcpio-netconf +pkgver=0.0.4 +pkgrel=2 +pkgdesc="Archlinux mkinitcpio hook for configuring early userspace networking" +arch=('any') +url="https://github.com/grazzolini/mkinitcpio-netconf" +license=('BSD') +depends=('mkinitcpio-nfs-utils' 'iproute2') +#install=$pkgname.install +source=("${pkgname}-${pkgver}.tar.gz::$url/archive/v$pkgver.tar.gz") +changelog='Changelog' +sha512sums=('06ac202410964740785d2977f7918981276e10568260433436c51a1d540152cc28462e46dae6bfa31acd1fafa9ebe1e4f57ca90d7754a09ccaba142c8d48b228') + +package() { + install -Dm644 "$srcdir/$pkgname-$pkgver/netconf_hook" "$pkgdir/usr/lib/initcpio/hooks/netconf" + install -Dm644 "$srcdir/$pkgname-$pkgver/netconf_install" "$pkgdir/usr/lib/initcpio/install/netconf" + install -Dm644 "$srcdir/$pkgname-$pkgver/LICENSE" "$pkgdir/usr/share/licenses/$pkgname/LICENSE" + +} diff --git a/src/mkinitcpio-netconf/mkinitcpio-netconf.install b/src/mkinitcpio-netconf/mkinitcpio-netconf.install new file mode 100644 index 0000000..cb10542 --- /dev/null +++ b/src/mkinitcpio-netconf/mkinitcpio-netconf.install @@ -0,0 +1,37 @@ +#!/bin/bash + +post_install() { + cat< + * 0.0.3: + - Created a new function to use the tinyssh-convert tool to convert already existing OpenSSH ED25519 keys to the tinyssh format. + - It will continue to create the tinyssh keys if openssh isn't installed and it has no keys available. + - This will only happen if openssh is installed and has run at least once and if there are no keys already created under /etc/tinyssh/sshkeydir. + - This is only valid for ED25519 keys, since the tinyssh-convert tool can only convert those. + +2015-08-11 Giancarlo Razzolini + + * 0.0.2 : + - Initial systemd support. It will add the tinyssh@22.socket unit, create a dependency on cryptsetup.target and enable the unit. + - Changed the root user home dir to /root. + - TMPDIR juggling cleanup. + - Hook help text correction. + +2015-08-03 Giancarlo Razzolini + + * 0.0.1 : + - Initial release. + - Uses the ucspi-tcp tcpserver tool to start the tinysshd daemon on boot. + - Right now only accepts connections on the default ssh port (22). + - There is no customization of the tinysshd parameters yet. diff --git a/src/mkinitcpio-tinyssh/PKGBUILD b/src/mkinitcpio-tinyssh/PKGBUILD new file mode 100644 index 0000000..ca30a5d --- /dev/null +++ b/src/mkinitcpio-tinyssh/PKGBUILD @@ -0,0 +1,24 @@ +# Maintainer: Giancarlo Razzolini +pkgname=mkinitcpio-tinyssh +pkgver=0.0.3 +pkgrel=3 +pkgdesc="Archlinux mkinitcpio hook to install and enable the tinyssh daemon in early userspace" +arch=('any') +url="https://github.com/grazzolini/mkinitcpio-tinyssh" +license=('BSD') +depends=('psmisc' 'tinyssh' 'ucspi-tcp') +optdepends=('mkinitcpio-netconf: Network interface configuration' + 'mkinitcpio-ppp: PPP interface configuration' + 'tinyssh-convert: For converting OpenSSH keys' + 'tinyssh-convert-git: For converting OpenSSH keys') +conflicts=('mkinitcpio-dropbear') +#install=$pkgname.install +source=("${pkgname}-${pkgver}.tar.gz::$url/archive/v$pkgver.tar.gz") +changelog='ChangeLog' +sha512sums=('16f5f2c09bdcf53a7a63011630c6ce03c73db724a3bed52145e53a9d4dc818878af7ad48b7c19927bca9fd8fc9fc230dbcef966b14c40f48468109acd3618f64') + +package() { + install -Dm644 "$srcdir/$pkgname-$pkgver/tinyssh_hook" "$pkgdir/usr/lib/initcpio/hooks/tinyssh" + install -Dm644 "$srcdir/$pkgname-$pkgver/tinyssh_install" "$pkgdir/usr/lib/initcpio/install/tinyssh" + install -Dm644 "$srcdir/$pkgname-$pkgver/LICENSE" "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} diff --git a/src/mkinitcpio-tinyssh/mkinitcpio-tinyssh.install b/src/mkinitcpio-tinyssh/mkinitcpio-tinyssh.install new file mode 100644 index 0000000..1a2195c --- /dev/null +++ b/src/mkinitcpio-tinyssh/mkinitcpio-tinyssh.install @@ -0,0 +1,34 @@ +#!/bin/bash + +post_install() { + touch /etc/tinyssh/root_key + chmod 600 /etc/tinyssh/root_key + + cat< /etc/tinyssh/root_key". + + If you want to use the same host keys as your OpenSSH installation + (only ed25519 for now), install tinyssh-convert or tinyssh-convert-git + BEFORE rebuilding your initramfs. Or, if you already have keys generated, + remove either the /etc/tinyssh/sshkeydir, or the ed25519 public and secret + keys from that dir, in order to use OpenSSH keys. This hook will not overwrite + existing keys either OpenSSH's converted or tinysshd-makekey created. + + Afterwards add the "tinyssh" hook after any networking hook (netconf/ppp) + and before any hook provided with the mkinitcpio-utils package in the + "HOOKS" array in "/etc/mkinitcpio.conf". Finally rebuild the initramsfs + ("mkinitcpio -p linux"). +INSTALLEOF +} + +post_remove() { + cat< + + * 0.0.2 : + - Got rid of TMPDIR juggling by using BUILDROOT directly. + - Changed the root home dir to /root. + +2015-07-22 Giancarlo Razzolini + + * 0.0.1 : + - Initial release. + - Provide the encryptssh hook and the cryptsetup_shell as it is on the original dropbear_initrd_encrypt package. diff --git a/src/mkinitcpio-utils/PKGBUILD b/src/mkinitcpio-utils/PKGBUILD new file mode 100644 index 0000000..8979db4 --- /dev/null +++ b/src/mkinitcpio-utils/PKGBUILD @@ -0,0 +1,23 @@ +# Maintainer: Giancarlo Razzolini +pkgname=mkinitcpio-utils +pkgver=0.0.3 +pkgrel=3 +pkgdesc="Collection of Archlinux mkinitcpio utilities performing various tasks" +arch=('any') +url="https://github.com/grazzolini/mkinitcpio-utils" +license=('BSD') +depends=('cryptsetup') +optdepends=('mkinitcpio-dropbear: Allow the encryptssh hook to unlock a root container remotely using dropbear' + 'mkinitcpio-tinyssh: Allow the encryptssh hook to unlock a root container remotely using tinyssh') +#install=$pkgname.install +changelog='ChangeLog' +source=("${pkgname}-${pkgver}.tar.gz::$url/archive/v$pkgver.tar.gz") +sha512sums=('9d454006978f23abca61be71523454670b94ea6d8e08eeab2e61fc81da3e3f5e8ec2b053fb0a6f986ce673d8521aa2a5b5fe5f37d4dffc4e27fde1b238437470') + +package() { + install -Dm755 "$srcdir/$pkgname-$pkgver/utils/shells/cryptsetup_shell" "$pkgdir/usr/share/$pkgname/utils/shells/cryptsetup_shell" + install -Dm644 "$srcdir/$pkgname-$pkgver/README.md" "$pkgdir/usr/share/$pkgname/README.md" + install -Dm644 "$srcdir/$pkgname-$pkgver/initcpio/hooks/encryptssh" "$pkgdir/usr/lib/initcpio/hooks/encryptssh" + install -Dm644 "$srcdir/$pkgname-$pkgver/initcpio/install/encryptssh" "$pkgdir/usr/lib/initcpio/install/encryptssh" + install -Dm644 "$srcdir/$pkgname-$pkgver/LICENSE" "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} diff --git a/src/mkinitcpio-utils/mkinitcpio-utils.install b/src/mkinitcpio-utils/mkinitcpio-utils.install new file mode 100644 index 0000000..b10b9c4 --- /dev/null +++ b/src/mkinitcpio-utils/mkinitcpio-utils.install @@ -0,0 +1,20 @@ +#!/bin/bash + +post_install() { + cat< +# Co-Maintainer: Giancarlo Razzolini +pkgname='tinyssh' +pkgver='20160812' +pkgrel='1' +pkgdesc='Small SSH server using NaCl / TweetNaCl' +url='http://tinyssh.org' +arch=('x86_64' 'i686' 'arm' 'armv6h') +license=('Public Domain') +makedepends=('gcc' 'make') +install='tinyssh.install' +source=("${pkgname}-${pkgver}.tar.gz::https://mojzis.com/software/${pkgname}/${pkgname}-${pkgver}.tar.gz" + tinyssh@.socket tinyssh@.service tinysshgenkeys.service + "${pkgname}-${pkgver}.tar.gz.asc::https://mojzis.com/software/${pkgname}/${pkgname}-${pkgver}.tar.gz.asc") +sha512sums=('54817e7e0da778eb4e404e165caff321ef3c8b13f1e1840c9fad1e8f6f64fee086019f4222199bf2b47e19754913400bb719443a944c612e987e3d3fdae14147' + '9fbc5ae3b6d1df6d78eedf812fdd8fe115e81fc0811f4799d541e37239d53db22203e691026ed479a38c9f17043e52d43b44054be51ae03c2f12f3f235c5b83a' + '9c9ba78c5b61f64f42f59cfe556519d9ab2c3e4d45f36d6f78c5e7728b050c494673239630dae66398006f3f20fb3a26f22899cd0728ed17e61c655b372236b3' + '415cdfe649eedcbb11a263938c0a66bef42432210baa2e2c9e428d5e8e486fb4dedad53b9fdb9086bf97ca506909d3b3054aaca56f02c063e0b8d5fab4e56198' + 'SKIP') +validpgpkeys=('AADF2EDF5529F1702772C8A2DEC4D246931EF49B') + +build () { + cd "${srcdir}/${pkgname}-${pkgver//./}" + make +} + +package () { + cd "${srcdir}/${pkgname}-${pkgver//./}" + make install DESTDIR="${pkgdir}" + + # Nowadays /usr/sbin is a symlink to /usr/bin + mv "${pkgdir}"/usr/{s,}bin + + install -m 755 -d ${pkgdir}/etc/tinyssh + + install -m 755 -d "${pkgdir}/usr/lib/systemd/system" + install -m 644 -t "${pkgdir}/usr/lib/systemd/system" \ + "${srcdir}/tinysshgenkeys.service" \ + "${srcdir}/tinyssh@.service" \ + "${srcdir}/tinyssh@.socket" +} diff --git a/src/tinyssh/tinyssh.install b/src/tinyssh/tinyssh.install new file mode 100755 index 0000000..ef68eb2 --- /dev/null +++ b/src/tinyssh/tinyssh.install @@ -0,0 +1,31 @@ +#! /bin/bash +# +# tinyssh.install +# Copyright (C) 2014 Adrian Perez +# +# Distributed under terms of the MIT license. +# +set -e + +post_install () { + cat <<-EOF + A generic systemd template unit has been installed, which can be used + to make TinySSH listen on more than one interface/address. To configure + it in the default port (22) on all interfaces, use: + + systemctl enable tinyssh@22.socket + systemctl start tinyssh@22.socket + + Note that you can also specify the interface address, and multiple + address/port combinations can be configured at the same time by writing + the "ipaddress:port" as the unit instance. For example: + + systemctl enable tinyssh@192.168.0.10:22222.socket + systemctl start tinyssh@192.168.0.10:22222.socket + + EOF +} + +post_upgrade () { + post_install +} diff --git a/src/tinyssh/tinyssh@.service b/src/tinyssh/tinyssh@.service new file mode 100644 index 0000000..7f908f9 --- /dev/null +++ b/src/tinyssh/tinyssh@.service @@ -0,0 +1,9 @@ +[Unit] +Description=TinySSH Per-Connection Daemon +Documentation=http://tinyssh.org +After=tinysshgenkeys.service + +[Service] +ExecStart=/usr/bin/tinysshd /etc/tinyssh/sshkeydir +StandardInput=socket +StandardError=journal diff --git a/src/tinyssh/tinyssh@.socket b/src/tinyssh/tinyssh@.socket new file mode 100644 index 0000000..05dab75 --- /dev/null +++ b/src/tinyssh/tinyssh@.socket @@ -0,0 +1,13 @@ +[Unit] +Description=TinySSH service (socket-activated) +Documentation=http://tinyssh.org +Wants=tinysshgenkeys.service + +[Socket] +ListenStream=%i +Accept=true +KeepAlive=true +IPTOS=low-delay + +[Install] +WantedBy=sockets.target diff --git a/src/tinyssh/tinysshgenkeys.service b/src/tinyssh/tinysshgenkeys.service new file mode 100644 index 0000000..00f3c0b --- /dev/null +++ b/src/tinyssh/tinysshgenkeys.service @@ -0,0 +1,8 @@ +[Unit] +Description=TinySSH Key Generation +ConditionPathIsDirectory=!/etc/tinyssh/sshkeydir + +[Service] +ExecStart=/usr/bin/tinysshd-makekey /etc/tinyssh/sshkeydir +Type=oneshot +RemainAfterExit=true diff --git a/src/ucspi-tcp/.SRCINFO b/src/ucspi-tcp/.SRCINFO new file mode 100644 index 0000000..c4792ca --- /dev/null +++ b/src/ucspi-tcp/.SRCINFO @@ -0,0 +1,19 @@ +# Generated by mksrcinfo v8 +# Fri Oct 21 10:55:49 UTC 2016 +pkgbase = ucspi-tcp + pkgdesc = Easy-to-use command-line tools for building TCP client-server applications. + pkgver = 0.88 + pkgrel = 8 + url = http://cr.yp.to/ucspi-tcp.html + arch = i686 + arch = x86_64 + license = public-domain + source = http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz + source = ucspi-tcp-0.88-ipv6.patch + source = head-1.patch + sha512sums = 44efbd477dacf31d39fc970e2d2f74526dc815b905742f6127f0d5c80928ecc7e743089eaab0492386a58d5b97905113fbe8bbc7214ae179b7be27966b7566c7 + sha512sums = 4180f2e8e0bd23bc345d363b5cfeab321293360203386fc93672bcb5c6fd8145d82c4eedb261abd0faacbce15bcd3180d7b02f2604039db735def7cdcd30abbc + sha512sums = 815b4caa3d9a294e3fe69a464f37d1f50ebd83e25d608955dff4b78da1d3ddd9fb4f2586ab41552f006a117f2bd7a937a6ee485dd7897d2d63a9f9e2e12a1d8d + +pkgname = ucspi-tcp + diff --git a/src/ucspi-tcp/.gitignore b/src/ucspi-tcp/.gitignore new file mode 100644 index 0000000..d4bfacc --- /dev/null +++ b/src/ucspi-tcp/.gitignore @@ -0,0 +1,2 @@ +ucspi-tcp-*.tar.gz +ucspi-tcp-*.tar.xz diff --git a/src/ucspi-tcp/PKGBUILD b/src/ucspi-tcp/PKGBUILD new file mode 100644 index 0000000..b27d1c8 --- /dev/null +++ b/src/ucspi-tcp/PKGBUILD @@ -0,0 +1,39 @@ +# Maintainer: Giancarlo Razzolini +# Contributor: eric +# Contributor: Manolis Tzanidakis +pkgname=ucspi-tcp +pkgver=0.88 +pkgrel=8 +pkgdesc="Easy-to-use command-line tools for building TCP client-server applications." +arch=('i686' 'x86_64') +url="http://cr.yp.to/ucspi-tcp.html" +license=('public-domain') +source=("http://cr.yp.to/$pkgname/$pkgname-$pkgver.tar.gz" + "ucspi-tcp-$pkgver-ipv6.patch" + "head-1.patch") +sha512sums=('44efbd477dacf31d39fc970e2d2f74526dc815b905742f6127f0d5c80928ecc7e743089eaab0492386a58d5b97905113fbe8bbc7214ae179b7be27966b7566c7' + '4180f2e8e0bd23bc345d363b5cfeab321293360203386fc93672bcb5c6fd8145d82c4eedb261abd0faacbce15bcd3180d7b02f2604039db735def7cdcd30abbc' + '815b4caa3d9a294e3fe69a464f37d1f50ebd83e25d608955dff4b78da1d3ddd9fb4f2586ab41552f006a117f2bd7a937a6ee485dd7897d2d63a9f9e2e12a1d8d') + +prepare() { + cd "$srcdir/$pkgname-$pkgver" + patch -p0 < "$srcdir/head-1.patch" + patch -p1 < "$srcdir/ucspi-tcp-$pkgver-ipv6.patch" + echo "gcc ${CFLAGS}" > conf-cc + echo "/usr" > conf-home +} + +build() { + cd "$srcdir/$pkgname-$pkgver" + make +} + +package() { + cd "$srcdir/$pkgname-$pkgver" + for bin in tcpserver tcprules tcprulescheck argv0 recordio \ + tcpclient *\@ tcpcat mconnect mconnect-io addcr \ + delcr fixcrio rblsmtpd; do + install -m 755 -D $bin "$pkgdir/usr/bin/$bin" + done +} diff --git a/src/ucspi-tcp/head-1.patch b/src/ucspi-tcp/head-1.patch new file mode 100644 index 0000000..b8b0fd9 --- /dev/null +++ b/src/ucspi-tcp/head-1.patch @@ -0,0 +1,40 @@ +--- Makefile.orig 2003-09-03 10:42:49.624475128 -0400 ++++ Makefile 2003-09-03 10:43:04.950145272 -0400 +@@ -41 +41 @@ +- ./auto-str auto_home `head -1 conf-home` > auto_home.c ++ ./auto-str auto_home `head -n 1 conf-home` > auto_home.c +@@ -152 +152 @@ +- | sed s}HOME}"`head -1 conf-home`"}g \ ++ | sed s}HOME}"`head -n 1 conf-home`"}g \ +@@ -164 +164 @@ +- echo exec "`head -1 conf-cc`" '-c $${1+"$$@"}' \ ++ echo exec "`head -n 1 conf-cc`" '-c $${1+"$$@"}' \ +@@ -171 +171 @@ +- | sed s}HOME}"`head -1 conf-home`"}g \ ++ | sed s}HOME}"`head -n 1 conf-home`"}g \ +@@ -295 +295 @@ +- | sed s}HOME}"`head -1 conf-home`"}g \ ++ | sed s}HOME}"`head -n 1 conf-home`"}g \ +@@ -349 +349 @@ +- | sed s}HOME}"`head -1 conf-home`"}g \ ++ | sed s}HOME}"`head -n 1 conf-home`"}g \ +@@ -392 +392 @@ +- echo exec "`head -1 conf-ld`" \ ++ echo exec "`head -n 1 conf-ld`" \ +@@ -419 +419 @@ +- | sed s}HOME}"`head -1 conf-home`"}g \ ++ | sed s}HOME}"`head -n 1 conf-home`"}g \ +@@ -517 +517 @@ +- | sed s}HOME}"`head -1 conf-home`"}g \ ++ | sed s}HOME}"`head -n 1 conf-home`"}g \ +@@ -674,2 +674,2 @@ +- echo CC=\'`head -1 conf-cc`\'; \ +- echo LD=\'`head -1 conf-ld`\'; \ ++ echo CC=\'`head -n 1 conf-cc`\'; \ ++ echo LD=\'`head -n 1 conf-ld`\'; \ +@@ -718 +718 @@ +- | sed s}HOME}"`head -1 conf-home`"}g \ ++ | sed s}HOME}"`head -n 1 conf-home`"}g \ +@@ -860 +860 @@ +- | sed s}HOME}"`head -1 conf-home`"}g \ ++ | sed s}HOME}"`head -n 1 conf-home`"}g \ diff --git a/src/ucspi-tcp/ucspi-tcp-0.88-ipv6.patch b/src/ucspi-tcp/ucspi-tcp-0.88-ipv6.patch new file mode 100644 index 0000000..d83be6a --- /dev/null +++ b/src/ucspi-tcp/ucspi-tcp-0.88-ipv6.patch @@ -0,0 +1,4976 @@ +diff -uNr ucspi-tcp-0.88.orig/FILES ucspi-tcp-0.88/FILES +--- ucspi-tcp-0.88.orig/FILES 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/FILES 2009-08-04 17:45:59.000000000 -0500 +@@ -216,3 +216,40 @@ + warn-auto.sh + warn-shsgr + x86cpuid.c ++dns_ip6.c ++dns_ipq6.c ++dns_nd6.c ++dns_sortip6.c ++fmt_xlong.c ++ip6_fmt.c ++ip6_scan.c ++scan_0x.c ++socket_accept6.c ++socket_bind6.c ++socket_conn6.c ++socket_local6.c ++socket_recv6.c ++socket_remote6.c ++socket_send6.c ++socket_tcp6.c ++timeoutconn6.c ++tryip6.c ++haveip6.h2 ++haveip6.h1 ++remoteinfo6.c ++addcr.1 ++argv0.1 ++date@.1 ++delcr.1 ++finger@.1 ++fixcr.1 ++http@.1 ++mconnect.1 ++recordio.1 ++tcp-environ.5 ++tcpcat.1 ++tcpclient.1 ++tcprules.1 ++tcprulescheck.1 ++tcpserver.1 ++who@.1 +diff -uNr ucspi-tcp-0.88.orig/Makefile ucspi-tcp-0.88/Makefile +--- ucspi-tcp-0.88.orig/Makefile 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/Makefile 2009-08-04 17:45:59.000000000 -0500 +@@ -76,12 +76,14 @@ + makelib byte_chr.o byte_copy.o byte_cr.o byte_diff.o byte_rchr.o \ + byte_zero.o case_diffb.o case_diffs.o fmt_ulong.o ip4_fmt.o \ + ip4_scan.o scan_ulong.o str_chr.o str_diff.o str_len.o str_start.o \ +-uint16_pack.o uint16_unpack.o uint32_pack.o uint32_unpack.o ++uint16_pack.o uint16_unpack.o uint32_pack.o uint32_unpack.o \ ++ip6_fmt.o scan_ip6.o scan_xlong.o fmt_xlong.o + ./makelib byte.a byte_chr.o byte_copy.o byte_cr.o \ + byte_diff.o byte_rchr.o byte_zero.o case_diffb.o \ + case_diffs.o fmt_ulong.o ip4_fmt.o ip4_scan.o scan_ulong.o \ + str_chr.o str_diff.o str_len.o str_start.o uint16_pack.o \ +- uint16_unpack.o uint32_pack.o uint32_unpack.o ++ uint16_unpack.o uint32_pack.o uint32_unpack.o ip6_fmt.o \ ++ scan_ip6.o scan_xlong.o fmt_xlong.o + + byte_chr.o: \ + compile byte_chr.c byte.h +@@ -181,11 +183,13 @@ + dns.a: \ + makelib dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o dns_ipq.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_resolve.o dns_sortip.o dns_transmit.o dns_txt.o dns_ip6.o \ ++dns_sortip6.o dns_nd6.o dns_ipq6.o + ./makelib dns.a dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o \ + dns_ipq.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_transmit.o dns_txt.o dns_ip6.o dns_sortip6.o dns_nd6.o \ ++ dns_ipq6.o + + dns_dfd.o: \ + compile dns_dfd.c error.h alloc.h byte.h dns.h stralloc.h gen_alloc.h \ +@@ -257,7 +261,7 @@ + dns_transmit.o: \ + compile dns_transmit.c socket.h uint16.h alloc.h error.h byte.h \ + readwrite.h uint16.h dns.h stralloc.h gen_alloc.h iopause.h taia.h \ +-tai.h uint64.h taia.h ++tai.h uint64.h taia.h uint32.h + ./compile dns_transmit.c + + dns_txt.o: \ +@@ -498,9 +502,15 @@ + remoteinfo.o: \ + compile remoteinfo.c fmt.h buffer.h socket.h uint16.h error.h \ + iopause.h taia.h tai.h uint64.h timeoutconn.h uint16.h remoteinfo.h \ +-stralloc.h gen_alloc.h uint16.h ++stralloc.h gen_alloc.h uint16.h uint32.h + ./compile remoteinfo.c + ++remoteinfo6.o: \ ++compile remoteinfo6.c fmt.h buffer.h socket.h uint16.h error.h \ ++iopause.h taia.h tai.h uint64.h timeoutconn.h uint16.h remoteinfo.h \ ++stralloc.h gen_alloc.h uint16.h uint32.h ++ ./compile remoteinfo6.c ++ + rts: \ + warn-auto.sh rts.sh conf-home + cat warn-auto.sh rts.sh \ +@@ -557,43 +567,43 @@ + rm -f trylsock.o trylsock + + socket_accept.o: \ +-compile socket_accept.c byte.h socket.h uint16.h ++compile socket_accept.c byte.h socket.h uint16.h uint32.h + ./compile socket_accept.c + + socket_bind.o: \ +-compile socket_bind.c byte.h socket.h uint16.h ++compile socket_bind.c byte.h socket.h uint16.h uint32.h + ./compile socket_bind.c + + socket_conn.o: \ +-compile socket_conn.c readwrite.h byte.h socket.h uint16.h ++compile socket_conn.c readwrite.h byte.h socket.h uint16.h uint32.h + ./compile socket_conn.c + + socket_delay.o: \ +-compile socket_delay.c socket.h uint16.h ++compile socket_delay.c socket.h uint16.h uint32.h + ./compile socket_delay.c + + socket_listen.o: \ +-compile socket_listen.c socket.h uint16.h ++compile socket_listen.c socket.h uint16.h uint32.h + ./compile socket_listen.c + + socket_local.o: \ +-compile socket_local.c byte.h socket.h uint16.h ++compile socket_local.c byte.h socket.h uint16.h uint32.h + ./compile socket_local.c + + socket_opts.o: \ +-compile socket_opts.c socket.h uint16.h ++compile socket_opts.c socket.h uint16.h uint32.h + ./compile socket_opts.c + + socket_remote.o: \ +-compile socket_remote.c byte.h socket.h uint16.h ++compile socket_remote.c byte.h socket.h uint16.h uint32.h + ./compile socket_remote.c + + socket_tcp.o: \ +-compile socket_tcp.c ndelay.h socket.h uint16.h ++compile socket_tcp.c ndelay.h socket.h uint16.h uint32.h + ./compile socket_tcp.c + + socket_udp.o: \ +-compile socket_udp.c ndelay.h socket.h uint16.h ++compile socket_udp.c ndelay.h socket.h uint16.h uint32.h + ./compile socket_udp.c + + str_chr.o: \ +@@ -710,9 +720,9 @@ + chmod 755 tcpcat + + tcpclient: \ +-load tcpclient.o remoteinfo.o timeoutconn.o dns.a time.a unix.a \ +-byte.a socket.lib +- ./load tcpclient remoteinfo.o timeoutconn.o dns.a time.a \ ++load tcpclient.o remoteinfo6.o dns.a time.a unix.a \ ++byte.a socket.lib byte.h timeoutconn6.o ++ ./load tcpclient remoteinfo6.o timeoutconn6.o dns.a time.a \ + unix.a byte.a `cat socket.lib` + + tcpclient.o: \ +@@ -720,7 +730,7 @@ + scan.h str.h ip4.h uint16.h socket.h uint16.h fd.h stralloc.h \ + gen_alloc.h buffer.h error.h strerr.h pathexec.h timeoutconn.h \ + uint16.h remoteinfo.h stralloc.h uint16.h dns.h stralloc.h iopause.h \ +-taia.h tai.h uint64.h taia.h ++taia.h tai.h uint64.h taia.h uint32.h + ./compile tcpclient.c + + tcprules: \ +@@ -742,9 +752,9 @@ + ./compile tcprulescheck.c + + tcpserver: \ +-load tcpserver.o rules.o remoteinfo.o timeoutconn.o cdb.a dns.a \ ++load tcpserver.o rules.o remoteinfo6.o timeoutconn6.o cdb.a dns.a \ + time.a unix.a byte.a socket.lib +- ./load tcpserver rules.o remoteinfo.o timeoutconn.o cdb.a \ ++ ./load tcpserver rules.o remoteinfo6.o timeoutconn6.o cdb.a \ + dns.a time.a unix.a byte.a `cat socket.lib` + + tcpserver.o: \ +@@ -753,7 +763,7 @@ + alloc.h buffer.h error.h strerr.h sgetopt.h subgetopt.h pathexec.h \ + socket.h uint16.h ndelay.h remoteinfo.h stralloc.h uint16.h rules.h \ + stralloc.h sig.h dns.h stralloc.h iopause.h taia.h tai.h uint64.h \ +-taia.h ++taia.h uint32.h + ./compile tcpserver.c + + time.a: \ +@@ -765,9 +775,14 @@ + + timeoutconn.o: \ + compile timeoutconn.c ndelay.h socket.h uint16.h iopause.h taia.h \ +-tai.h uint64.h error.h timeoutconn.h uint16.h ++tai.h uint64.h error.h timeoutconn.h uint16.h uint32.h + ./compile timeoutconn.c + ++timeoutconn6.o: \ ++compile timeoutconn6.c ndelay.h socket.h uint16.h iopause.h taia.h \ ++tai.h uint64.h error.h timeoutconn.h uint16.h uint32.h ++ ./compile timeoutconn6.c ++ + uint16_pack.o: \ + compile uint16_pack.c uint16.h + ./compile uint16_pack.c +@@ -806,7 +821,12 @@ + socket_opts.o socket_remote.o socket_tcp.o socket_udp.o \ + stralloc_cat.o stralloc_catb.o stralloc_cats.o stralloc_copy.o \ + stralloc_eady.o stralloc_opyb.o stralloc_opys.o stralloc_pend.o \ +-strerr_die.o strerr_sys.o subgetopt.o wait_nohang.o wait_pid.o ++strerr_die.o strerr_sys.o subgetopt.o wait_nohang.o wait_pid.o \ ++socket_conn6.o socket_bind6.o socket_accept6.o socket_recv6.o \ ++socket_send6.o socket_local6.o socket_remote6.o socket_tcp6.o \ ++socket_getifname.o socket_getifidx.o socket_v4mappedprefix.o \ ++socket_ip4loopback.o socket_v6any.o socket_v6loopback.o \ ++socket_udp6.o + ./makelib unix.a alloc.o alloc_re.o buffer.o buffer_0.o \ + buffer_1.o buffer_2.o buffer_copy.o buffer_get.o \ + buffer_put.o env.o error.o error_str.o fd_copy.o fd_move.o \ +@@ -819,7 +839,12 @@ + socket_udp.o stralloc_cat.o stralloc_catb.o stralloc_cats.o \ + stralloc_copy.o stralloc_eady.o stralloc_opyb.o \ + stralloc_opys.o stralloc_pend.o strerr_die.o strerr_sys.o \ +- subgetopt.o wait_nohang.o wait_pid.o ++ subgetopt.o wait_nohang.o wait_pid.o socket_conn6.o \ ++ socket_bind6.o socket_accept6.o socket_recv6.o socket_send6.o \ ++ socket_local6.o socket_remote6.o socket_tcp6.o \ ++ socket_getifname.o socket_getifidx.o socket_v4mappedprefix.o \ ++ socket_ip4loopback.o socket_v6any.o socket_v6loopback.o \ ++ socket_udp6.o + + wait_nohang.o: \ + compile wait_nohang.c haswaitp.h +@@ -835,3 +860,110 @@ + | sed s}HOME}"`head -1 conf-home`"}g \ + > who@ + chmod 755 who@ ++ ++socket_conn6.o: \ ++compile socket_conn6.c socket.h uint16.h haveip6.h error.h ip6.h \ ++uint32.h ++ ./compile socket_conn6.c ++ ++socket_bind6.o: \ ++compile socket_bind6.c socket.h uint16.h haveip6.h error.h ip6.h \ ++uint32.h ++ ./compile socket_bind6.c ++ ++socket_accept6.o: \ ++compile socket_accept6.c socket.h uint16.h haveip6.h error.h ip6.h \ ++uint32.h ++ ./compile socket_accept6.c ++ ++socket_recv6.o: \ ++compile socket_recv6.c socket.h uint16.h haveip6.h error.h ip6.h \ ++uint32.h ++ ./compile socket_recv6.c ++ ++socket_send6.o: \ ++compile socket_send6.c socket.h uint16.h haveip6.h error.h uint32.h ++ ./compile socket_send6.c ++ ++socket_local6.o: \ ++compile socket_local6.c socket.h uint16.h haveip6.h error.h uint32.h ++ ./compile socket_local6.c ++ ++socket_remote6.o: \ ++compile socket_remote6.c socket.h uint16.h haveip6.h error.h uint32.h ++ ./compile socket_remote6.c ++ ++dns_sortip6.o: \ ++compile dns_sortip6.c byte.h dns.h stralloc.h gen_alloc.h iopause.h \ ++taia.h tai.h uint64.h taia.h ++ ./compile dns_sortip6.c ++ ++dns_nd6.o: \ ++compile dns_nd6.c byte.h fmt.h dns.h stralloc.h gen_alloc.h iopause.h \ ++taia.h tai.h uint64.h taia.h ++ ./compile dns_nd6.c ++ ++dns_ipq6.o: \ ++compile dns_ipq6.c stralloc.h gen_alloc.h case.h byte.h str.h dns.h \ ++stralloc.h iopause.h taia.h tai.h uint64.h taia.h ip6.h ++ ./compile dns_ipq6.c ++ ++dns_ip6.o: \ ++compile dns_ip6.c stralloc.h gen_alloc.h uint16.h byte.h dns.h \ ++stralloc.h iopause.h taia.h tai.h uint64.h taia.h ++ ./compile dns_ip6.c ++ ++fmt_xlong.o: \ ++compile fmt_xlong.c scan.h ++ ./compile fmt_xlong.c ++ ++scan_xlong.o: \ ++compile scan_xlong.c scan.h ++ ./compile scan_xlong.c ++ ++ip6_fmt.o: \ ++compile ip6_fmt.c fmt.h ip6.h ++ ./compile ip6_fmt.c ++ ++scan_ip6.o: \ ++compile scan_ip6.c scan.h ip6.h ++ ./compile scan_ip6.c ++ ++socket_tcp6.o: \ ++compile socket_tcp6.c ndelay.h socket.h uint16.h haveip6.h uint32.h ++ ./compile socket_tcp6.c ++ ++socket_udp6.o: \ ++compile socket_udp6.c ndelay.h socket.h uint16.h haveip6.h uint32.h ++ ./compile socket_udp6.c ++ ++haveip6.h: \ ++tryip6.c choose compile haveip6.h1 haveip6.h2 ++ ./choose c tryip6 haveip6.h1 haveip6.h2 > haveip6.h ++ ++socket_getifname.o: \ ++compile socket_getifname.c socket.h uint16.h uint32.h ++ ./compile socket_getifname.c ++ ++socket_getifidx.o: \ ++compile socket_getifidx.c socket.h uint16.h uint32.h ++ ./compile socket_getifidx.c ++ ++socket_ip4loopback.o: \ ++compile socket_ip4loopback.c ++ ./compile socket_ip4loopback.c ++ ++socket_v4mappedprefix.o: \ ++compile socket_v4mappedprefix.c ++ ./compile socket_v4mappedprefix.c ++ ++socket_v6any.o: \ ++compile socket_v6any.c ++ ./compile socket_v6any.c ++ ++socket_v6loopback.o: \ ++compile socket_v6loopback.c ++ ./compile socket_v6loopback.c ++ ++clean: ++ rm -f `cat TARGETS` +diff -uNr ucspi-tcp-0.88.orig/TARGETS ucspi-tcp-0.88/TARGETS +--- ucspi-tcp-0.88.orig/TARGETS 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/TARGETS 2009-08-04 17:45:59.000000000 -0500 +@@ -169,3 +169,31 @@ + it + setup + check ++dns_ip6.o ++dns_ipq6.o ++dns_nd6.o ++dns_sortip6.o ++fmt_xlong.o ++ip6_fmt.o ++ip6_scan.o ++scan_0x.o ++socket_accept6.o ++socket_bind6.o ++socket_conn6.o ++socket_local6.o ++socket_recv6.o ++socket_remote6.o ++socket_send6.o ++socket_tcp6.o ++timeoutconn6.o ++haveip6.h ++remoteinfo6.o ++socket_getifidx.o ++socket_getifname.o ++scan_ip6.o ++scan_xlong.o ++socket_ip4loopback.o ++socket_udp6.o ++socket_v4mappedprefix.o ++socket_v6any.o ++socket_v6loopback.o +diff -uNr ucspi-tcp-0.88.orig/addcr.1 ucspi-tcp-0.88/addcr.1 +--- ucspi-tcp-0.88.orig/addcr.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/addcr.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,22 @@ ++.TH addcr 1 ++.SH NAME ++addcr \- add a CR before each LF ++.SH SYNOPSIS ++.B addcr ++.SH DESCRIPTION ++.B addcr ++inserts CR at the end of each line of input. ++It does not insert CR at the end of a partial final line. ++.SH COMPATIBILITY ++Some vendors ship ++.B unix2dos ++or ++.B bsd2dos ++tools similar to ++.BR addcr . ++Those tools often blow up on long lines and nulls. ++.B addcr ++has no trouble with long lines and nulls. ++.SH "SEE ALSO" ++delcr(1), ++fixcr(1) +diff -uNr ucspi-tcp-0.88.orig/argv0.1 ucspi-tcp-0.88/argv0.1 +--- ucspi-tcp-0.88.orig/argv0.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/argv0.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,47 @@ ++.TH argv0 1 ++.SH NAME ++argv0 \- run a program with a specified 0th argument ++.SH SYNOPSIS ++.B argv0 ++.I realname ++.I zero ++[ ++.I arg ... ++] ++.SH DESCRIPTION ++.B argv0 ++runs ++the program stored as ++.I realname ++on disk, ++with the given ++arguments. ++It sets the 0th argument of ++the program to ++.IR zero . ++ ++For example, ++ ++.EX ++ argv0 /bin/csh -bin/csh ++.EE ++ ++runs ++.B /bin/csh ++with a 0th argument of ++.BR -bin/csh . ++.B csh ++will think it is a login shell ++and behave accordingly. ++ ++.B argv0 ++can be used to run some ++.B inetd ++wrappers under ++.BR tcpserver . ++.SH "SEE ALSO" ++csh(1), ++tcpserver(1), ++execve(2), ++execvp(3), ++inetd(8) +diff -uNr ucspi-tcp-0.88.orig/date@.1 ucspi-tcp-0.88/date@.1 +--- ucspi-tcp-0.88.orig/date@.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/date@.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,32 @@ ++.TH date@ 1 ++.SH NAME ++date@ \- print the date on a host ++.SH SYNTAX ++.B date@ ++[ ++.I host ++] ++.SH DESCRIPTION ++.B date@ ++connects to TCP port 13 (Daytime) on ++.I host ++and prints any data it receives. ++It removes CR and converts unprintable characters to a visible format. ++ ++If ++.I host ++is not supplied, ++.B date@ ++connects to the local host. ++ ++Some computers respond to port 13 with a human-readable date. ++For example, they may be running ++ ++.EX ++ tcpserver 0 13 date & ++.EE ++.SH "SEE ALSO" ++cat(1), ++delcr(1), ++tcpclient(1), ++tcpserver(1) +diff -uNr ucspi-tcp-0.88.orig/delcr.1 ucspi-tcp-0.88/delcr.1 +--- ucspi-tcp-0.88.orig/delcr.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/delcr.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,30 @@ ++.TH delcr 1 ++.SH NAME ++delcr \- remove a CR before each LF ++.SH SYNOPSIS ++.B delcr ++.SH DESCRIPTION ++.B delcr ++removes a CR at the end of each line of input, ++if a CR is present. ++It also removes a CR at the end of a partial final line. ++ ++The pipeline ++ ++.EX ++ addcr | delcr ++.EE ++ ++prints an exact copy of its input. ++.SH COMPATIBILITY ++Some vendors ship ++.B dos2unix ++or ++.B dos2bsd ++tools similar to ++.BR delcr . ++Those tools often blow up on long lines and nulls. ++.B delcr ++has no trouble with long lines and nulls. ++.SH "SEE ALSO" ++addcr(1) +diff -uNr ucspi-tcp-0.88.orig/dns.h ucspi-tcp-0.88/dns.h +--- ucspi-tcp-0.88.orig/dns.h 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns.h 2009-08-04 17:45:59.000000000 -0500 +@@ -34,51 +34,60 @@ + unsigned int curserver; + struct taia deadline; + unsigned int pos; +- char *servers; +- char localip[4]; ++ const char *servers; ++ char localip[16]; ++ unsigned int scope_id; + char qtype[2]; + } ; + +-extern void dns_random_init(char *); ++extern void dns_random_init(const char *); + extern unsigned int dns_random(unsigned int); + + extern void dns_sortip(char *,unsigned int); ++extern void dns_sortip6(char *,unsigned int); + + extern void dns_domain_free(char **); +-extern int dns_domain_copy(char **,char *); +-extern unsigned int dns_domain_length(char *); +-extern int dns_domain_equal(char *,char *); +-extern char *dns_domain_suffix(char *,char *); +-extern int dns_domain_fromdot(char **,char *,unsigned int); +-extern int dns_domain_todot_cat(stralloc *,char *); +- +-extern unsigned int dns_packet_copy(char *,unsigned int,unsigned int,char *,unsigned int); +-extern unsigned int dns_packet_getname(char *,unsigned int,unsigned int,char **); +-extern unsigned int dns_packet_skipname(char *,unsigned int,unsigned int); +-extern int dns_packet_nameequal(char *,unsigned int,unsigned int,char *,unsigned int,unsigned int); ++extern int dns_domain_copy(char **,const char *); ++extern unsigned int dns_domain_length(const char *); ++extern int dns_domain_equal(const char *,const char *); ++extern int dns_domain_suffix(const char *,const char *); ++extern unsigned int dns_domain_suffixpos(const char *,const char *); ++extern int dns_domain_fromdot(char **,const char *,unsigned int); ++extern int dns_domain_todot_cat(stralloc *,const char *); ++ ++extern unsigned int dns_packet_copy(const char *,unsigned int,unsigned int,char *,unsigned int); ++extern unsigned int dns_packet_getname(const char *,unsigned int,unsigned int,char **); ++extern unsigned int dns_packet_skipname(const char *,unsigned int,unsigned int); + +-extern int dns_transmit_start(struct dns_transmit *,char *,int,char *,char *,char *); ++extern int dns_transmit_start(struct dns_transmit *,const char *,int,const char *,const char *,const char *); + extern void dns_transmit_free(struct dns_transmit *); + extern void dns_transmit_io(struct dns_transmit *,iopause_fd *,struct taia *); +-extern int dns_transmit_get(struct dns_transmit *,iopause_fd *,struct taia *); ++extern int dns_transmit_get(struct dns_transmit *,const iopause_fd *,const struct taia *); + + extern int dns_resolvconfip(char *); +-extern int dns_resolve(char *,char *); ++extern int dns_resolve(const char *,const char *); + extern struct dns_transmit dns_resolve_tx; + +-extern int dns_ip4_packet(stralloc *,char *,unsigned int); +-extern int dns_ip4(stralloc *,stralloc *); +-extern int dns_name_packet(stralloc *,char *,unsigned int); +-extern void dns_name4_domain(char *,char *); ++extern int dns_ip4_packet(stralloc *,const char *,unsigned int); ++extern int dns_ip4(stralloc *,const stralloc *); ++extern int dns_ip6_packet(stralloc *,const char *,unsigned int); ++extern int dns_ip6(stralloc *,stralloc *); ++extern int dns_name_packet(stralloc *,const char *,unsigned int); ++extern void dns_name4_domain(char *,const char *); + #define DNS_NAME4_DOMAIN 31 +-extern int dns_name4(stralloc *,char *); +-extern int dns_txt_packet(stralloc *,char *,unsigned int); +-extern int dns_txt(stralloc *,stralloc *); +-extern int dns_mx_packet(stralloc *,char *,unsigned int); +-extern int dns_mx(stralloc *,stralloc *); ++extern int dns_name4(stralloc *,const char *); ++extern int dns_txt_packet(stralloc *,const char *,unsigned int); ++extern int dns_txt(stralloc *,const stralloc *); ++extern int dns_mx_packet(stralloc *,const char *,unsigned int); ++extern int dns_mx(stralloc *,const stralloc *); + + extern int dns_resolvconfrewrite(stralloc *); +-extern int dns_ip4_qualify_rules(stralloc *,stralloc *,stralloc *,stralloc *); +-extern int dns_ip4_qualify(stralloc *,stralloc *,stralloc *); ++extern int dns_ip4_qualify_rules(stralloc *,stralloc *,const stralloc *,const stralloc *); ++extern int dns_ip4_qualify(stralloc *,stralloc *,const stralloc *); ++extern int dns_ip6_qualify_rules(stralloc *,stralloc *,const stralloc *,const stralloc *); ++extern int dns_ip6_qualify(stralloc *,stralloc *,const stralloc *); ++ ++extern int dns_name6_domain(char *,char *); ++#define DNS_NAME6_DOMAIN (4*16+11) + + #endif +diff -uNr ucspi-tcp-0.88.orig/dns_dfd.c ucspi-tcp-0.88/dns_dfd.c +--- ucspi-tcp-0.88.orig/dns_dfd.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_dfd.c 2009-08-04 17:45:59.000000000 -0500 +@@ -1,9 +1,10 @@ +-#include "error.h" +-#include "alloc.h" ++#include ++#include + #include "byte.h" + #include "dns.h" ++#include "error.h" + +-int dns_domain_fromdot(char **out,char *buf,unsigned int n) ++int dns_domain_fromdot(char **out,const char *buf,unsigned int n) + { + char label[63]; + unsigned int labellen = 0; /* <= sizeof label */ +@@ -59,11 +60,11 @@ + if (namelen + 1 > sizeof name) return 0; + name[namelen++] = 0; + +- x = alloc(namelen); ++ x = malloc(namelen); + if (!x) return 0; + byte_copy(x,namelen,name); + +- if (*out) alloc_free(*out); ++ if (*out) free(*out); + *out = x; + return 1; + } +diff -uNr ucspi-tcp-0.88.orig/dns_domain.c ucspi-tcp-0.88/dns_domain.c +--- ucspi-tcp-0.88.orig/dns_domain.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_domain.c 2009-08-04 17:45:59.000000000 -0500 +@@ -1,16 +1,15 @@ +-#include "error.h" +-#include "alloc.h" ++#include + #include "case.h" + #include "byte.h" + #include "dns.h" + +-unsigned int dns_domain_length(char *dn) ++unsigned int dns_domain_length(const char *dn) + { +- char *x; ++ const char *x; + unsigned char c; + + x = dn; +- while (c = *x++) ++ while ((c = *x++)) + x += (unsigned int) c; + return x - dn; + } +@@ -18,26 +17,26 @@ + void dns_domain_free(char **out) + { + if (*out) { +- alloc_free(*out); ++ free(*out); + *out = 0; + } + } + +-int dns_domain_copy(char **out,char *in) ++int dns_domain_copy(char **out,const char *in) + { + unsigned int len; + char *x; + + len = dns_domain_length(in); +- x = alloc(len); ++ x = malloc(len); + if (!x) return 0; + byte_copy(x,len,in); +- if (*out) alloc_free(*out); ++ if (*out) free(*out); + *out = x; + return 1; + } + +-int dns_domain_equal(char *dn1,char *dn2) ++int dns_domain_equal(const char *dn1,const char *dn2) + { + unsigned int len; + +@@ -48,12 +47,25 @@ + return 1; + } + +-char *dns_domain_suffix(char *big,char *little) ++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; ++ if (dns_domain_equal(big,little)) return big - orig; + c = *big++; + if (!c) return 0; + big += c; +diff -uNr ucspi-tcp-0.88.orig/dns_dtda.c ucspi-tcp-0.88/dns_dtda.c +--- ucspi-tcp-0.88.orig/dns_dtda.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_dtda.c 2009-08-04 17:45:59.000000000 -0500 +@@ -1,7 +1,7 @@ + #include "stralloc.h" + #include "dns.h" + +-int dns_domain_todot_cat(stralloc *out,char *d) ++int dns_domain_todot_cat(stralloc *out,const char *d) + { + char ch; + char ch2; +diff -uNr ucspi-tcp-0.88.orig/dns_ip.c ucspi-tcp-0.88/dns_ip.c +--- ucspi-tcp-0.88.orig/dns_ip.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_ip.c 2009-08-04 17:45:59.000000000 -0500 +@@ -3,7 +3,7 @@ + #include "byte.h" + #include "dns.h" + +-int dns_ip4_packet(stralloc *out,char *buf,unsigned int len) ++int dns_ip4_packet(stralloc *out,const char *buf,unsigned int len) + { + unsigned int pos; + char header[12]; +@@ -36,7 +36,7 @@ + + static char *q = 0; + +-int dns_ip4(stralloc *out,stralloc *fqdn) ++int dns_ip4(stralloc *out,const stralloc *fqdn) + { + unsigned int i; + char code; +diff -uNr ucspi-tcp-0.88.orig/dns_ip6.c ucspi-tcp-0.88/dns_ip6.c +--- ucspi-tcp-0.88.orig/dns_ip6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/dns_ip6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,103 @@ ++#include "stralloc.h" ++#include "uint16.h" ++#include "byte.h" ++#include "dns.h" ++#include "ip4.h" ++#include "ip6.h" ++ ++static int dns_ip6_packet_add(stralloc *out,const char *buf,unsigned int len) ++{ ++ unsigned int pos; ++ char header[16]; ++ uint16 numanswers; ++ uint16 datalen; ++ ++ pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1; ++ uint16_unpack_big(header + 6,&numanswers); ++ pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1; ++ pos += 4; ++ ++ while (numanswers--) { ++ pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1; ++ pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1; ++ 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 -1; ++ if (!stralloc_catb(out,header,16)) return -1; ++ } ++ } 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 -1; ++ if (!stralloc_catb(out,header,16)) return -1; ++ } ++ pos += datalen; ++ } ++ ++ dns_sortip6(out->s,out->len); ++ return 0; ++} ++ ++int dns_ip6_packet(stralloc *out,const char *buf,unsigned int len) { ++ if (!stralloc_copys(out,"")) return -1; ++ return dns_ip6_packet_add(out,buf,len); ++} ++ ++static char *q = 0; ++ ++int dns_ip6(stralloc *out,stralloc *fqdn) ++{ ++ unsigned int i; ++ char code; ++ char ch; ++ char ip[16]; ++ ++ if (!stralloc_copys(out,"")) return -1; ++ if (!stralloc_readyplus(fqdn,1)) return -1; ++ fqdn->s[fqdn->len]=0; ++ if ((i=scan_ip6(fqdn->s,ip))) { ++ if (fqdn->s[i]) return -1; ++ stralloc_copyb(out,ip,16); ++ return 0; ++ } ++ 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 -1; ++ code = 0; ++ continue; ++ } ++ if ((ch >= '0') && (ch <= '9')) { ++ code *= 10; ++ code += ch - '0'; ++ continue; ++ } ++ ++ if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1; ++ if (!stralloc_copys(out,"")) return -1; ++ if (dns_resolve(q,DNS_T_AAAA) != -1) ++ if (dns_ip6_packet_add(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) != -1) { ++ dns_transmit_free(&dns_resolve_tx); ++ dns_domain_free(&q); ++ } ++ if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1; ++ if (dns_resolve(q,DNS_T_A) != -1) ++ if (dns_ip6_packet_add(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) != -1) { ++ dns_transmit_free(&dns_resolve_tx); ++ dns_domain_free(&q); ++ } ++ return out->a>0?0:-1; ++ } ++ ++ out->len &= ~3; ++ return 0; ++} +diff -uNr ucspi-tcp-0.88.orig/dns_ipq.c ucspi-tcp-0.88/dns_ipq.c +--- ucspi-tcp-0.88.orig/dns_ipq.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_ipq.c 2009-08-04 17:45:59.000000000 -0500 +@@ -4,7 +4,7 @@ + #include "str.h" + #include "dns.h" + +-static int doit(stralloc *work,char *rule) ++static int doit(stralloc *work,const char *rule) + { + char ch; + unsigned int colon; +@@ -30,7 +30,7 @@ + return stralloc_cats(work,rule + colon + 1); + } + +-int dns_ip4_qualify_rules(stralloc *out,stralloc *fqdn,stralloc *in,stralloc *rules) ++int dns_ip4_qualify_rules(stralloc *out,stralloc *fqdn,const stralloc *in,const stralloc *rules) + { + unsigned int i; + unsigned int j; +@@ -63,7 +63,7 @@ + } + } + +-int dns_ip4_qualify(stralloc *out,stralloc *fqdn,stralloc *in) ++int dns_ip4_qualify(stralloc *out,stralloc *fqdn,const stralloc *in) + { + static stralloc rules; + if (dns_resolvconfrewrite(&rules) == -1) return -1; +diff -uNr ucspi-tcp-0.88.orig/dns_ipq6.c ucspi-tcp-0.88/dns_ipq6.c +--- ucspi-tcp-0.88.orig/dns_ipq6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/dns_ipq6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,72 @@ ++#include "stralloc.h" ++#include "case.h" ++#include "byte.h" ++#include "str.h" ++#include "dns.h" ++ ++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(rule,':'); ++ if (!rule[colon]) return 1; ++ ++ if (work->len < colon) return 1; ++ prefixlen = work->len - colon; ++ if ((ch == '=') && prefixlen) return 1; ++ if (case_diffb(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; ++ if (byte_chr(work->s,prefixlen,']') < prefixlen) return 1; ++ } ++ ++ work->len = prefixlen; ++ if (ch == '-') work->len = 0; ++ return stralloc_cats(work,rule + colon + 1); ++} ++ ++int dns_ip6_qualify_rules(stralloc *out,stralloc *fqdn,const stralloc *in,const stralloc *rules) ++{ ++ unsigned int i; ++ unsigned int j; ++ unsigned int plus; ++ unsigned int fqdnlen; ++ ++ if (!stralloc_copy(fqdn,in)) return -1; ++ ++ for (j = i = 0;j < rules->len;++j) ++ if (!rules->s[j]) { ++ if (!doit(fqdn,rules->s + i)) return -1; ++ i = j + 1; ++ } ++ ++ fqdnlen = fqdn->len; ++ plus = byte_chr(fqdn->s,fqdnlen,'+'); ++ if (plus >= fqdnlen) ++ return dns_ip6(out,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 (dns_ip6(out,fqdn) == -1) return -1; ++ if (out->len) return 0; ++ i += j; ++ if (i >= fqdnlen) return 0; ++ ++i; ++ } ++} ++ ++int dns_ip6_qualify(stralloc *out,stralloc *fqdn,const stralloc *in) ++{ ++ static stralloc rules; ++ if (dns_resolvconfrewrite(&rules) == -1) return -1; ++ return dns_ip6_qualify_rules(out,fqdn,in,&rules); ++} +diff -uNr ucspi-tcp-0.88.orig/dns_name.c ucspi-tcp-0.88/dns_name.c +--- ucspi-tcp-0.88.orig/dns_name.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_name.c 2009-08-04 17:45:59.000000000 -0500 +@@ -2,10 +2,11 @@ + #include "uint16.h" + #include "byte.h" + #include "dns.h" ++#include "ip6.h" + + static char *q = 0; + +-int dns_name_packet(stralloc *out,char *buf,unsigned int len) ++int dns_name_packet(stralloc *out,const char *buf,unsigned int len) + { + unsigned int pos; + char header[12]; +@@ -35,7 +36,7 @@ + return 0; + } + +-int dns_name4(stralloc *out,char ip[4]) ++int dns_name4(stralloc *out,const char ip[4]) + { + char name[DNS_NAME4_DOMAIN]; + +@@ -46,3 +47,17 @@ + dns_domain_free(&q); + return 0; + } ++ ++int dns_name6(stralloc *out,char ip[16]) ++{ ++ char name[DNS_NAME6_DOMAIN]; ++ ++ if (ip6_isv4mapped(ip)) ++ return dns_name4(out,ip+12); ++ dns_name6_domain(name,ip); ++ if (dns_resolve(name,DNS_T_PTR) == -1) return -1; ++ if (dns_name_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1; ++ dns_transmit_free(&dns_resolve_tx); ++ dns_domain_free(&q); ++ return 0; ++} +diff -uNr ucspi-tcp-0.88.orig/dns_nd.c ucspi-tcp-0.88/dns_nd.c +--- ucspi-tcp-0.88.orig/dns_nd.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_nd.c 2009-08-04 17:45:59.000000000 -0500 +@@ -2,7 +2,7 @@ + #include "fmt.h" + #include "dns.h" + +-void dns_name4_domain(char name[DNS_NAME4_DOMAIN],char ip[4]) ++void dns_name4_domain(char name[DNS_NAME4_DOMAIN],const char ip[4]) + { + unsigned int namelen; + unsigned int i; +diff -uNr ucspi-tcp-0.88.orig/dns_nd6.c ucspi-tcp-0.88/dns_nd6.c +--- ucspi-tcp-0.88.orig/dns_nd6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/dns_nd6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,28 @@ ++#include "byte.h" ++#include "fmt.h" ++#include "dns.h" ++ ++/* RFC1886: ++ * 4321:0:1:2:3:4:567:89ab ++ * -> ++ * b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.IP6.INT. ++ */ ++ ++static inline char tohex(char c) { ++ return c>=10?c-10+'a':c+'0'; ++} ++ ++int dns_name6_domain(char name[DNS_NAME6_DOMAIN],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 -uNr ucspi-tcp-0.88.orig/dns_packet.c ucspi-tcp-0.88/dns_packet.c +--- ucspi-tcp-0.88.orig/dns_packet.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_packet.c 2009-08-04 17:45:59.000000000 -0500 +@@ -2,10 +2,11 @@ + DNS should have used LZ77 instead of its own sophomoric compression algorithm. + */ + +-#include "error.h" ++#include + #include "dns.h" ++#include "error.h" + +-unsigned int dns_packet_copy(char *buf,unsigned int len,unsigned int pos,char *out,unsigned int outlen) ++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 = error_proto; return 0; } +@@ -15,7 +16,7 @@ + return pos; + } + +-unsigned int dns_packet_skipname(char *buf,unsigned int len,unsigned int pos) ++unsigned int dns_packet_skipname(const char *buf,unsigned int len,unsigned int pos) + { + unsigned char ch; + +@@ -32,7 +33,7 @@ + return 0; + } + +-unsigned int dns_packet_getname(char *buf,unsigned int len,unsigned int pos,char **d) ++unsigned int dns_packet_getname(const char *buf,unsigned int len,unsigned int pos,char **d) + { + unsigned int loop = 0; + unsigned int state = 0; +diff -uNr ucspi-tcp-0.88.orig/dns_random.c ucspi-tcp-0.88/dns_random.c +--- ucspi-tcp-0.88.orig/dns_random.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_random.c 2009-08-04 17:45:59.000000000 -0500 +@@ -1,3 +1,4 @@ ++#include + #include "dns.h" + #include "taia.h" + #include "uint32.h" +@@ -29,7 +30,7 @@ + } + } + +-void dns_random_init(char data[128]) ++void dns_random_init(const char data[128]) + { + int i; + struct taia t; +diff -uNr ucspi-tcp-0.88.orig/dns_rcip.c ucspi-tcp-0.88/dns_rcip.c +--- ucspi-tcp-0.88.orig/dns_rcip.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_rcip.c 2009-08-04 17:45:59.000000000 -0500 +@@ -2,12 +2,13 @@ + #include "openreadclose.h" + #include "byte.h" + #include "ip4.h" +-#include "env.h" ++#include "ip6.h" + #include "dns.h" ++#include "env.h" + + static stralloc data = {0}; + +-static int init(char ip[64]) ++static int init(char ip[256]) + { + int i; + int j; +@@ -16,15 +17,16 @@ + + x = env_get("DNSCACHEIP"); + if (x) +- while (iplen <= 60) ++ while (iplen <= 60) { + if (*x == '.') + ++x; + else { +- i = ip4_scan(x,ip + iplen); ++ i = scan_ip6(x,ip + iplen); + if (!i) break; + x += i; +- iplen += 4; ++ iplen += 16; + } ++ } + + if (!iplen) { + i = openreadclose("/etc/resolv.conf",&data,64); +@@ -39,8 +41,9 @@ + while ((data.s[i] == ' ') || (data.s[i] == '\t')) + ++i; + if (iplen <= 60) +- if (ip4_scan(data.s + i,ip + iplen)) +- iplen += 4; ++ if (scan_ip6(data.s + i,ip + iplen)) { ++ iplen += 16; ++ } + } + i = j + 1; + } +@@ -48,19 +51,19 @@ + } + + if (!iplen) { +- byte_copy(ip,4,"\177\0\0\1"); +- iplen = 4; ++ 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,64 - iplen); ++ byte_zero(ip + iplen,256 - iplen); + return 0; + } + + static int ok = 0; + static unsigned int uses; + static struct taia deadline; +-static char ip[64]; /* defined if ok */ ++static char ip[256]; /* defined if ok */ + +-int dns_resolvconfip(char s[64]) ++int dns_resolvconfip(char s[256]) + { + struct taia now; + +@@ -77,6 +80,6 @@ + } + + --uses; +- byte_copy(s,64,ip); ++ byte_copy(s,256,ip); + return 0; + } +diff -uNr ucspi-tcp-0.88.orig/dns_rcrw.c ucspi-tcp-0.88/dns_rcrw.c +--- ucspi-tcp-0.88.orig/dns_rcrw.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_rcrw.c 2009-08-04 17:45:59.000000000 -0500 +@@ -1,16 +1,17 @@ ++#include + #include "taia.h" +-#include "env.h" + #include "byte.h" + #include "str.h" + #include "openreadclose.h" + #include "dns.h" ++#include "env.h" + + static stralloc data = {0}; + + static int init(stralloc *rules) + { + char host[256]; +- char *x; ++ const char *x; + int i; + int j; + int k; +diff -uNr ucspi-tcp-0.88.orig/dns_resolve.c ucspi-tcp-0.88/dns_resolve.c +--- ucspi-tcp-0.88.orig/dns_resolve.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_resolve.c 2009-08-04 17:45:59.000000000 -0500 +@@ -2,19 +2,20 @@ + #include "taia.h" + #include "byte.h" + #include "dns.h" ++#include "ip6.h" + + struct dns_transmit dns_resolve_tx = {0}; + +-int dns_resolve(char *q,char qtype[2]) ++int dns_resolve(const char *q,const char qtype[2]) + { + struct taia stamp; + struct taia deadline; +- char servers[64]; ++ char servers[256]; + iopause_fd x[1]; + int r; + + if (dns_resolvconfip(servers) == -1) return -1; +- if (dns_transmit_start(&dns_resolve_tx,servers,1,q,qtype,"\0\0\0\0") == -1) return -1; ++ if (dns_transmit_start(&dns_resolve_tx,servers,1,q,qtype,V6any) == -1) return -1; + + for (;;) { + taia_now(&stamp); +diff -uNr ucspi-tcp-0.88.orig/dns_sortip6.c ucspi-tcp-0.88/dns_sortip6.c +--- ucspi-tcp-0.88.orig/dns_sortip6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/dns_sortip6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,20 @@ ++#include "byte.h" ++#include "dns.h" ++ ++/* XXX: sort servers by configurable notion of closeness? */ ++/* XXX: pay attention to competence of each server? */ ++ ++void dns_sortip6(char *s,unsigned int n) ++{ ++ unsigned int i; ++ char tmp[16]; ++ ++ n >>= 4; ++ 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 -uNr ucspi-tcp-0.88.orig/dns_transmit.c ucspi-tcp-0.88/dns_transmit.c +--- ucspi-tcp-0.88.orig/dns_transmit.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_transmit.c 2009-08-04 17:45:59.000000000 -0500 +@@ -1,12 +1,15 @@ ++#include ++#include ++#include ++#include + #include "socket.h" +-#include "alloc.h" +-#include "error.h" ++#include + #include "byte.h" +-#include "readwrite.h" + #include "uint16.h" + #include "dns.h" ++#include "ip6.h" + +-static int serverwantstcp(char *buf,unsigned int len) ++static int serverwantstcp(const char *buf,unsigned int len) + { + char out[12]; + +@@ -15,7 +18,7 @@ + return 0; + } + +-static int serverfailed(char *buf,unsigned int len) ++static int serverfailed(const char *buf,unsigned int len) + { + char out[12]; + unsigned int rcode; +@@ -23,11 +26,11 @@ + if (!dns_packet_copy(buf,len,0,out,12)) return 1; + rcode = out[3]; + rcode &= 15; +- if (rcode && (rcode != 3)) { errno = error_again; return 1; } ++ if (rcode && (rcode != 3)) { errno = EAGAIN; return 1; } + return 0; + } + +-static int irrelevant(struct dns_transmit *d,char *buf,unsigned int len) ++static int irrelevant(const struct dns_transmit *d,const char *buf,unsigned int len) + { + char out[12]; + char *dn; +@@ -40,8 +43,8 @@ + + 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); ++ if (!dns_domain_equal(dn,d->query + 14)) { free(dn); return 1; } ++ free(dn); + + pos = dns_packet_copy(buf,len,pos,out,4); if (!pos) return 1; + if (byte_diff(out,2,d->qtype)) return 1; +@@ -53,14 +56,14 @@ + static void packetfree(struct dns_transmit *d) + { + if (!d->packet) return; +- alloc_free(d->packet); ++ free(d->packet); + d->packet = 0; + } + + static void queryfree(struct dns_transmit *d) + { + if (!d->query) return; +- alloc_free(d->query); ++ free(d->query); + d->query = 0; + } + +@@ -83,9 +86,9 @@ + int j; + + for (j = 0;j < 10;++j) +- if (socket_bind4(d->s1 - 1,d->localip,1025 + dns_random(64510)) == 0) ++ if (socket_bind6(d->s1 - 1,d->localip,1025 + dns_random(64510),d->scope_id) == 0) + return 0; +- if (socket_bind4(d->s1 - 1,d->localip,0) == 0) ++ if (socket_bind6(d->s1 - 1,d->localip,0,d->scope_id) == 0) + return 0; + return -1; + } +@@ -94,22 +97,22 @@ + + static int thisudp(struct dns_transmit *d) + { +- char *ip; ++ const char *ip; + + socketfree(d); + + while (d->udploop < 4) { + for (;d->curserver < 16;++d->curserver) { +- ip = d->servers + 4 * d->curserver; +- if (byte_diff(ip,4,"\0\0\0\0")) { ++ ip = d->servers + 16 * d->curserver; ++ if (byte_diff(ip,16,V6any)) { + d->query[2] = dns_random(256); + d->query[3] = dns_random(256); + +- d->s1 = 1 + socket_udp(); ++ d->s1 = 1 + socket_udp6(); + if (!d->s1) { dns_transmit_free(d); return -1; } + if (randombind(d) == -1) { dns_transmit_free(d); return -1; } + +- if (socket_connect4(d->s1 - 1,ip,53) == 0) ++ if (socket_connect6(d->s1 - 1,ip,53,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); +@@ -145,29 +148,29 @@ + static int thistcp(struct dns_transmit *d) + { + struct taia now; +- char *ip; ++ const char *ip; + + socketfree(d); + packetfree(d); + + for (;d->curserver < 16;++d->curserver) { +- ip = d->servers + 4 * d->curserver; +- if (byte_diff(ip,4,"\0\0\0\0")) { ++ ip = d->servers + 16 * d->curserver; ++ if (byte_diff(ip,16,V6any)) { + d->query[2] = dns_random(256); + d->query[3] = dns_random(256); + +- d->s1 = 1 + socket_tcp(); ++ d->s1 = 1 + socket_tcp6(); + if (!d->s1) { dns_transmit_free(d); return -1; } + if (randombind(d) == -1) { dns_transmit_free(d); return -1; } + + taia_now(&now); + taia_uint(&d->deadline,10); + taia_add(&d->deadline,&d->deadline,&now); +- if (socket_connect4(d->s1 - 1,ip,53) == 0) { ++ if (socket_connect6(d->s1 - 1,ip,53,d->scope_id) == 0) { + d->tcpstate = 2; + return 0; + } +- if ((errno == error_inprogress) || (errno == error_wouldblock)) { ++ if ((errno == EINPROGRESS) || (errno == EWOULDBLOCK)) { + d->tcpstate = 1; + return 0; + } +@@ -191,16 +194,16 @@ + return thistcp(d); + } + +-int dns_transmit_start(struct dns_transmit *d,char servers[64],int flagrecursive,char *q,char qtype[2],char localip[4]) ++int dns_transmit_start(struct dns_transmit *d,const char servers[256],int flagrecursive,const char *q,const char qtype[2],const char localip[16]) + { + unsigned int len; + + dns_transmit_free(d); +- errno = error_io; ++ errno = EIO; + + len = dns_domain_length(q); + d->querylen = len + 18; +- d->query = alloc(d->querylen); ++ d->query = malloc(d->querylen); + if (!d->query) return -1; + + uint16_pack_big(d->query,len + 16); +@@ -211,7 +214,7 @@ + + byte_copy(d->qtype,2,qtype); + d->servers = servers; +- byte_copy(d->localip,4,localip); ++ byte_copy(d->localip,16,localip); + + d->udploop = flagrecursive ? 1 : 0; + +@@ -236,19 +239,19 @@ + *deadline = d->deadline; + } + +-int dns_transmit_get(struct dns_transmit *d,iopause_fd *x,struct taia *when) ++int dns_transmit_get(struct dns_transmit *d,const iopause_fd *x,const struct taia *when) + { + char udpbuf[513]; + unsigned char ch; + int r; + int fd; + +- errno = error_io; ++ errno = EIO; + fd = d->s1 - 1; + + if (!x->revents) { + if (taia_less(when,&d->deadline)) return 0; +- errno = error_timeout; ++ errno = ETIMEDOUT; + if (d->tcpstate == 0) return nextudp(d); + return nexttcp(d); + } +@@ -260,7 +263,7 @@ + */ + r = recv(fd,udpbuf,sizeof udpbuf,0); + if (r <= 0) { +- if (d->udploop == 2) return 0; ++ if (errno == ECONNREFUSED) if (d->udploop == 2) return 0; + return nextudp(d); + } + if (r + 1 > sizeof udpbuf) return 0; +@@ -274,7 +277,7 @@ + socketfree(d); + + d->packetlen = r; +- d->packet = alloc(d->packetlen); ++ d->packet = malloc(d->packetlen); + if (!d->packet) { dns_transmit_free(d); return -1; } + byte_copy(d->packet,d->packetlen,udpbuf); + queryfree(d); +@@ -334,7 +337,7 @@ + d->packetlen += ch; + d->tcpstate = 5; + d->pos = 0; +- d->packet = alloc(d->packetlen); ++ d->packet = malloc(d->packetlen); + if (!d->packet) { dns_transmit_free(d); return -1; } + return 0; + } +diff -uNr ucspi-tcp-0.88.orig/dns_txt.c ucspi-tcp-0.88/dns_txt.c +--- ucspi-tcp-0.88.orig/dns_txt.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/dns_txt.c 2009-08-04 17:45:59.000000000 -0500 +@@ -3,7 +3,7 @@ + #include "byte.h" + #include "dns.h" + +-int dns_txt_packet(stralloc *out,char *buf,unsigned int len) ++int dns_txt_packet(stralloc *out,const char *buf,unsigned int len) + { + unsigned int pos; + char header[12]; +@@ -48,7 +48,7 @@ + + static char *q = 0; + +-int dns_txt(stralloc *out,stralloc *fqdn) ++int dns_txt(stralloc *out,const stralloc *fqdn) + { + if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1; + if (dns_resolve(q,DNS_T_TXT) == -1) return -1; +diff -uNr ucspi-tcp-0.88.orig/error.h ucspi-tcp-0.88/error.h +--- ucspi-tcp-0.88.orig/error.h 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/error.h 2009-08-04 17:45:59.000000000 -0500 +@@ -1,7 +1,7 @@ + #ifndef ERROR_H + #define ERROR_H + +-extern int errno; ++#include + + extern int error_intr; + extern int error_nomem; +diff -uNr ucspi-tcp-0.88.orig/finger@.1 ucspi-tcp-0.88/finger@.1 +--- ucspi-tcp-0.88.orig/finger@.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/finger@.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,45 @@ ++.TH finger@ 1 ++.SH NAME ++finger@ \- get user information from a host ++.SH SYNTAX ++.B finger@ ++[ ++.I host ++[ ++.I user ++] ++] ++.SH DESCRIPTION ++.B finger@ ++connects to TCP port 79 (Finger) on ++.IR host , ++sends ++.I user ++(with an extra CR) ++to ++.IR host , ++and prints any data it receives. ++It removes CR and converts unprintable characters to a visible format. ++Some computers respond to port 79 with information about ++.IR user . ++ ++If ++.I user ++is not supplied, ++.B finger@ ++sends a blank line to ++.IR host . ++Some computers respond with information about ++all the users who are logged in. ++ ++If ++.I host ++is not supplied, ++.B finger@ ++connects to the local host. ++.SH "SEE ALSO" ++addcr(1), ++cat(1), ++delcr(1), ++finger(1), ++tcpclient(1) +diff -uNr ucspi-tcp-0.88.orig/fixcr.1 ucspi-tcp-0.88/fixcr.1 +--- ucspi-tcp-0.88.orig/fixcr.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/fixcr.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,11 @@ ++.TH fixcr 1 ++.SH NAME ++fixcr \- make sure that there is a CR before each LF ++.SH SYNOPSIS ++.B fixcr ++.SH DESCRIPTION ++.B fixcr ++inserts CR at the end of each line of input where a CR is not already present. ++It does not insert CR at the end of a partial final line. ++.SH "SEE ALSO" ++addcr(1) +diff -uNr ucspi-tcp-0.88.orig/fmt_xlong.c ucspi-tcp-0.88/fmt_xlong.c +--- ucspi-tcp-0.88.orig/fmt_xlong.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/fmt_xlong.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,22 @@ ++#include "fmt.h" ++ ++char tohex(char num) { ++ if (num<10) ++ return num+'0'; ++ else if (num<16) ++ return num-10+'a'; ++ else ++ return -1; ++} ++ ++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; ++} +diff -uNr ucspi-tcp-0.88.orig/haveip6.h1 ucspi-tcp-0.88/haveip6.h1 +--- ucspi-tcp-0.88.orig/haveip6.h1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/haveip6.h1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1 @@ ++ +diff -uNr ucspi-tcp-0.88.orig/haveip6.h2 ucspi-tcp-0.88/haveip6.h2 +--- ucspi-tcp-0.88.orig/haveip6.h2 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/haveip6.h2 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1 @@ ++#define LIBC_HAS_IP6 1 +diff -uNr ucspi-tcp-0.88.orig/hier.c ucspi-tcp-0.88/hier.c +--- ucspi-tcp-0.88.orig/hier.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/hier.c 2009-08-04 17:45:59.000000000 -0500 +@@ -4,6 +4,9 @@ + { + h(auto_home,-1,-1,02755); + d(auto_home,"bin",-1,-1,02755); ++ d(auto_home,"man",-1,-1,02755); ++ d(auto_home,"man/man1",-1,-1,02755); ++ d(auto_home,"man/man5",-1,-1,02755); + + c(auto_home,"bin","tcpserver",-1,-1,0755); + c(auto_home,"bin","tcprules",-1,-1,0755); +@@ -22,4 +25,20 @@ + c(auto_home,"bin","delcr",-1,-1,0755); + c(auto_home,"bin","fixcrio",-1,-1,0755); + c(auto_home,"bin","rblsmtpd",-1,-1,0755); ++ ++ c(auto_home,"man/man1","tcpclient.1",-1,-1,0644); ++ c(auto_home,"man/man1","tcpserver.1",-1,-1,0644); ++ c(auto_home,"man/man1","tcprules.1",-1,-1,0644); ++ c(auto_home,"man/man1","tcprulescheck.1",-1,-1,0644); ++ c(auto_home,"man/man1","fixcr.1",-1,-1,0644); ++ c(auto_home,"man/man1","addcr.1",-1,-1,0644); ++ c(auto_home,"man/man1","delcr.1",-1,-1,0644); ++ c(auto_home,"man/man1","who@.1",-1,-1,0644); ++ c(auto_home,"man/man1","date@.1",-1,-1,0644); ++ c(auto_home,"man/man1","finger@.1",-1,-1,0644); ++ c(auto_home,"man/man1","http@.1",-1,-1,0644); ++ c(auto_home,"man/man1","mconnect.1",-1,-1,0644); ++ c(auto_home,"man/man1","argv0.1",-1,-1,0644); ++ c(auto_home,"man/man1","recordio.1",-1,-1,0644); ++ c(auto_home,"man/man5","tcp-environ.5",-1,-1,0644); + } +diff -uNr ucspi-tcp-0.88.orig/http@.1 ucspi-tcp-0.88/http@.1 +--- ucspi-tcp-0.88.orig/http@.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/http@.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,52 @@ ++.TH http@ 1 ++.SH NAME ++http@ \- get a web page from a host through HTTP ++.SH SYNTAX ++.B http@ ++[ ++.I host ++[ ++.I page ++[ ++.I port ++] ++] ++] ++.SH DESCRIPTION ++.B http@ ++connects to ++.I port ++on ++.IR host , ++sends ++.B GET /\fIpage ++(with an extra CR) ++to ++.IR host , ++and prints any data it receives, ++removing CR from the end of each line. ++ ++If ++.I port ++is not supplied, ++.B http@ ++uses port 80 (HTTP). ++ ++If ++.I page ++is not supplied, ++.B http@ ++sends ++.B GET / ++to ++.IR host . ++ ++If ++.I host ++is not supplied, ++.B http@ ++connects to the local host. ++.SH "SEE ALSO" ++addcr(1), ++delcr(1), ++tcpclient(1) +diff -uNr ucspi-tcp-0.88.orig/ip4.h ucspi-tcp-0.88/ip4.h +--- ucspi-tcp-0.88.orig/ip4.h 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/ip4.h 2009-08-04 17:45:59.000000000 -0500 +@@ -6,4 +6,6 @@ + + #define IP4_FMT 20 + ++extern const char ip4loopback[4]; /* = {127,0,0,1}; */ ++ + #endif +diff -uNr ucspi-tcp-0.88.orig/ip6.h ucspi-tcp-0.88/ip6.h +--- ucspi-tcp-0.88.orig/ip6.h 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/ip6.h 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,28 @@ ++#ifndef IP6_H ++#define IP6_H ++ ++#include "byte.h" ++ ++extern unsigned int scan_ip6(const char *src,char *ip); ++extern unsigned int fmt_ip6(char *dest,const char *ip); ++ ++extern unsigned int scan_ip6_flat(const char *src,char *); ++extern unsigned int fmt_ip6_flat(char *dest,const char *); ++ ++/* ++ ip6 address syntax: (h = hex digit), no leading '0' required ++ 1. hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh ++ 2. any number of 0000 may be abbreviated as "::", but only once ++ flat ip6 address syntax: ++ hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh ++ */ ++ ++#define IP6_FMT 40 ++ ++extern const unsigned char V4mappedprefix[12]; /*={0,0,0,0,0,0,0,0,0,0,0xff,0xff}; */ ++extern const unsigned char V6loopback[16]; /*={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; */ ++extern const unsigned char V6any[16]; /*={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; */ ++ ++#define ip6_isv4mapped(ip) (byte_equal(ip,12,V4mappedprefix)) ++ ++#endif +diff -uNr ucspi-tcp-0.88.orig/ip6_fmt.c ucspi-tcp-0.88/ip6_fmt.c +--- ucspi-tcp-0.88.orig/ip6_fmt.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/ip6_fmt.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,64 @@ ++#include "fmt.h" ++#include "byte.h" ++#include "ip4.h" ++#include "ip6.h" ++ ++unsigned int ip6_fmt(char *s,char ip[16]) ++{ ++ unsigned long len,temp, k, pos0=0,len0=0, pos1=0, compr=0; ++ ++ for (k=0; k<16; k+=2) { ++ if (ip[k]==0 && ip[k+1]==0) { ++ if (!compr) { ++ compr=1; ++ pos1=k; ++ } ++ if (k==14) { k=16; goto last; } ++ } else if (compr) { ++ last: ++ if ((temp=k-pos1) > len0) { ++ len0=temp; ++ pos0=pos1; ++ } ++ compr=0; ++ } ++ } ++ ++ for (len=0,k=0; k<16; k+=2) { ++ if (k==12 && ip6_isv4mapped(ip)) { ++ len += ip4_fmt(s,ip+12); ++ break; ++ } ++ if (pos0==k && len0) { ++ if (k==0) { ++len; if (s) *s++ = ':'; } ++ ++len; if (s) *s++ = ':'; ++ k += len0-2; ++ continue; ++ } ++ temp = ((unsigned long) (unsigned char) ip[k] << 8) + ++ (unsigned long) (unsigned char) ip[k+1]; ++ temp = fmt_xlong(s,temp); len += temp; if (s) s += temp; ++ if (k<14) { ++len; if (s) *s++ = ':'; } ++ } ++ ++ return len; ++} ++ ++static char tohex(char num) { ++ if (num<10) ++ return num+'0'; ++ else if (num<16) ++ return num-10+'a'; ++ else ++ return -1; ++} ++ ++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; ++} +diff -uNr ucspi-tcp-0.88.orig/mconnect.1 ucspi-tcp-0.88/mconnect.1 +--- ucspi-tcp-0.88.orig/mconnect.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/mconnect.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,36 @@ ++.TH mconnect 1 ++.SH NAME ++mconnect \- connect to the SMTP server on a host ++.SH SYNTAX ++.B mconnect ++[ ++.I host ++[ ++.I port ++] ++] ++.SH DESCRIPTION ++.B mconnect ++connects to ++.I port ++on ++.IR host . ++It sends its input to ++.IR host , ++adding a CR to each line. ++Meanwhile it prints anything it receives from ++.IR host . ++ ++If ++.I port ++is not supplied, ++.B mconnect ++uses port 25 (SMTP). ++ ++If ++.I host ++is not supplied, ++.B mconnect ++connects to the local host. ++.SH "SEE ALSO" ++tcpclient(1) +diff -uNr ucspi-tcp-0.88.orig/old-rules.c ucspi-tcp-0.88/old-rules.c +--- ucspi-tcp-0.88.orig/old-rules.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/old-rules.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,101 @@ ++#include "alloc.h" ++#include "stralloc.h" ++#include "open.h" ++#include "cdb.h" ++#include "rules.h" ++ ++stralloc rules_name = {0}; ++ ++static struct cdb c; ++ ++static int dorule(void (*callback)(char *,unsigned int)) ++{ ++ char *data; ++ unsigned int datalen; ++ ++ switch(cdb_find(&c,rules_name.s,rules_name.len)) { ++ case -1: return -1; ++ case 0: return 0; ++ } ++ ++ datalen = cdb_datalen(&c); ++ data = alloc(datalen); ++ if (!data) return -1; ++ if (cdb_read(&c,data,datalen,cdb_datapos(&c)) == -1) { ++ alloc_free(data); ++ return -1; ++ } ++ ++ callback(data,datalen); ++ alloc_free(data); ++ return 1; ++} ++ ++static int doit(void (*callback)(char *,unsigned int),char *ip,char *host,char *info) ++{ ++ int r; ++ ++ if (info) { ++ if (!stralloc_copys(&rules_name,info)) return -1; ++ if (!stralloc_cats(&rules_name,"@")) return -1; ++ if (!stralloc_cats(&rules_name,ip)) return -1; ++ r = dorule(callback); ++ if (r) return r; ++ ++ if (host) { ++ if (!stralloc_copys(&rules_name,info)) return -1; ++ if (!stralloc_cats(&rules_name,"@=")) return -1; ++ if (!stralloc_cats(&rules_name,host)) return -1; ++ r = dorule(callback); ++ if (r) return r; ++ } ++ } ++ ++ if (!stralloc_copys(&rules_name,ip)) return -1; ++ r = dorule(callback); ++ if (r) return r; ++ ++ if (host) { ++ if (!stralloc_copys(&rules_name,"=")) return -1; ++ if (!stralloc_cats(&rules_name,host)) return -1; ++ r = dorule(callback); ++ if (r) return r; ++ } ++ ++ if (!stralloc_copys(&rules_name,ip)) return -1; ++ while (rules_name.len > 0) { ++ if (ip[rules_name.len - 1] == '.' || ++ (ip[rules_name.len-1]==':' && rules_name.len>1)) { ++ r = dorule(callback); ++ if (r) return r; ++ } ++ --rules_name.len; ++ } ++ ++ if (host) { ++ while (*host) { ++ if (*host == '.') { ++ if (!stralloc_copys(&rules_name,"=")) return -1; ++ if (!stralloc_cats(&rules_name,host)) return -1; ++ r = dorule(callback); ++ if (r) return r; ++ } ++ ++host; ++ } ++ if (!stralloc_copys(&rules_name,"=")) return -1; ++ r = dorule(callback); ++ if (r) return r; ++ } ++ ++ rules_name.len = 0; ++ return dorule(callback); ++} ++ ++int rules(void (*callback)(char *,unsigned int),int fd,char *ip,char *host,char *info) ++{ ++ int r; ++ cdb_init(&c,fd); ++ r = doit(callback,ip,host,info); ++ cdb_free(&c); ++ return r; ++} +diff -uNr ucspi-tcp-0.88.orig/pathexec.h ucspi-tcp-0.88/pathexec.h +--- ucspi-tcp-0.88.orig/pathexec.h 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/pathexec.h 2009-08-04 17:45:59.000000000 -0500 +@@ -2,7 +2,7 @@ + #define PATHEXEC_H + + extern void pathexec_run(char *,char **,char **); +-extern int pathexec_env(char *,char *); ++extern int pathexec_env(const char *,const char *); + extern void pathexec(char **); + + #endif +diff -uNr ucspi-tcp-0.88.orig/pathexec_env.c ucspi-tcp-0.88/pathexec_env.c +--- ucspi-tcp-0.88.orig/pathexec_env.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/pathexec_env.c 2009-08-04 17:45:59.000000000 -0500 +@@ -8,7 +8,7 @@ + static stralloc plus; + static stralloc tmp; + +-int pathexec_env(char *s,char *t) ++int pathexec_env(const char *s,const char *t) + { + if (!s) return 1; + if (!stralloc_copys(&tmp,s)) return 0; +@@ -22,7 +22,6 @@ + + void pathexec(char **argv) + { +- char *path; + char **e; + unsigned int elen; + unsigned int i; +diff -uNr ucspi-tcp-0.88.orig/rblsmtpd.c ucspi-tcp-0.88/rblsmtpd.c +--- ucspi-tcp-0.88.orig/rblsmtpd.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/rblsmtpd.c 2009-08-04 17:51:17.000000000 -0500 +@@ -25,26 +25,58 @@ + strerr_die1x(100,"rblsmtpd: usage: rblsmtpd [ -b ] [ -R ] [ -t timeout ] [ -r base ] [ -a base ] smtpd [ arg ... ]"); + } + ++char *tcp_proto; + char *ip_env; + static stralloc ip_reverse; + ++static inline char tohex(char c) { ++ return c>=10?c-10+'a':c+'0'; ++} ++ + void ip_init(void) + { + unsigned int i; + unsigned int j; ++ unsigned char remoteip[16]; ++ char hexval; + ++ tcp_proto = env_get("PROTO"); ++ if (!tcp_proto) tcp_proto = ""; + ip_env = env_get("TCPREMOTEIP"); + if (!ip_env) ip_env = ""; + + if (!stralloc_copys(&ip_reverse,"")) nomem(); + + i = str_len(ip_env); +- while (i) { +- for (j = i;j > 0;--j) if (ip_env[j - 1] == '.') break; +- if (!stralloc_catb(&ip_reverse,ip_env + j,i - j)) nomem(); +- if (!stralloc_cats(&ip_reverse,".")) nomem(); +- if (!j) break; +- i = j - 1; ++ if (str_diff(tcp_proto, "TCP6") != 0) ++ { ++ // IPv4 ++ while (i) { ++ for (j = i;j > 0;--j) if (ip_env[j - 1] == '.') break; ++ if (!stralloc_catb(&ip_reverse,ip_env + j,i - j)) nomem(); ++ if (!stralloc_cats(&ip_reverse,".")) nomem(); ++ if (!j) break; ++ i = j - 1; ++ } ++ } ++ else ++ { ++ // IPv6 ++ if ((i=scan_ip6(ip_env, remoteip))==0) ++ return; ++ ++ for (j=16; j>0; j--) ++ { ++ hexval=tohex(remoteip[j-1] & 15); ++ if(!stralloc_catb(&ip_reverse, &hexval, 1)) nomem(); ++ if(!stralloc_cats(&ip_reverse, ".")) nomem(); ++ ++ hexval=tohex(remoteip[j-1] >> 4); ++ if(!stralloc_catb(&ip_reverse, &hexval, 1)) nomem(); ++ if(!stralloc_cats(&ip_reverse, ".")) nomem(); ++ } ++ ++ if(!stralloc_cats(&ip_reverse, "ipv6.")) nomem(); + } + } + +@@ -190,7 +222,7 @@ + argv += optind; + if (!*argv) usage(); + +- if (flagwantdefaultrbl) rbl("rbl.maps.vix.com"); ++ if (flagwantdefaultrbl) rbl("zen.spamhaus.org"); + if (decision >= 2) rblsmtpd(); + + pathexec_run(*argv,argv,envp); +diff -uNr ucspi-tcp-0.88.orig/recordio.1 ucspi-tcp-0.88/recordio.1 +--- ucspi-tcp-0.88.orig/recordio.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/recordio.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,75 @@ ++.TH recordio 1 ++.SH NAME ++recordio \- record the input and output of a program ++.SH SYNTAX ++.B recordio ++.I program ++[ ++.I arg ... ++] ++.SH DESCRIPTION ++.B recordio ++runs ++.I program ++with the given arguments. ++It prints lines to stderr ++showing the input and output of ++.IR program . ++ ++At the beginning of each line on stderr, ++.B recordio ++inserts the ++.I program ++process ID, ++along with ++.B < ++for input or ++.B > ++for output. ++At the end of each line it inserts a space, a plus sign, or [EOF]; ++a space indicates that there was a newline in the input or output, ++and [EOF] indicates the end of input or output. ++ ++.B recordio ++prints every packet of input and output immediately. ++It does not attempt to combine packets into coherent stderr lines. ++For example, ++ ++.EX ++ recordio sh -c 'cat /dev/fd/8 2>&1' > /dev/null ++.EE ++ ++could produce ++ ++.EX ++ 5135 > cat: /dev/fd/8: Bad file descriptor ++.br ++ 5135 > [EOF] ++.EE ++ ++or ++ ++.EX ++ 5135 > cat: + ++.br ++ 5135 > /dev/fd/8+ ++.br ++ 5135 > : + ++.br ++ 5135 > Bad file descriptor ++.br ++ 5135 > [EOF] ++.EE ++ ++.B recordio ++uses several lines for long packets ++to guarantee that each line is printed atomically to stderr. ++ ++.B recordio ++runs as a child of ++.IR program . ++It exits when it sees the end of ++.IR program 's ++output. ++.SH "SEE ALSO" ++tcpserver(1) +diff -uNr ucspi-tcp-0.88.orig/remoteinfo.h ucspi-tcp-0.88/remoteinfo.h +--- ucspi-tcp-0.88.orig/remoteinfo.h 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/remoteinfo.h 2009-08-04 17:45:59.000000000 -0500 +@@ -5,5 +5,6 @@ + #include "uint16.h" + + extern int remoteinfo(stralloc *,char *,uint16,char *,uint16,unsigned int); ++extern int remoteinfo6(stralloc *,char *,uint16,char *,uint16,unsigned int,uint32); + + #endif +diff -uNr ucspi-tcp-0.88.orig/remoteinfo6.c ucspi-tcp-0.88/remoteinfo6.c +--- ucspi-tcp-0.88.orig/remoteinfo6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/remoteinfo6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,98 @@ ++#include "fmt.h" ++#include "buffer.h" ++#include "socket.h" ++#include "error.h" ++#include "iopause.h" ++#include "timeoutconn.h" ++#include "remoteinfo.h" ++ ++static struct taia now; ++static struct taia deadline; ++ ++static int mywrite(int fd,char *buf,int len) ++{ ++ iopause_fd x; ++ ++ 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 = error_timeout; ++ return -1; ++ } ++ } ++ return write(fd,buf,len); ++} ++ ++static int myread(int fd,char *buf,int len) ++{ ++ iopause_fd x; ++ ++ 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 = error_timeout; ++ return -1; ++ } ++ } ++ return read(fd,buf,len); ++} ++ ++static int doit(stralloc *out,int s,char ipremote[16],uint16 portremote,char iplocal[16],uint16 portlocal,unsigned int timeout,uint32 netif) ++{ ++ buffer b; ++ char bspace[128]; ++ char strnum[FMT_ULONG]; ++ int numcolons; ++ char ch; ++ ++ if (socket_bind6(s,iplocal,0,netif) == -1) return -1; ++ if (timeoutconn6(s,ipremote,113,timeout,netif) == -1) return -1; ++ ++ buffer_init(&b,mywrite,s,bspace,sizeof bspace); ++ buffer_put(&b,strnum,fmt_ulong(strnum,portremote)); ++ buffer_put(&b," , ",3); ++ buffer_put(&b,strnum,fmt_ulong(strnum,portlocal)); ++ buffer_put(&b,"\r\n",2); ++ if (buffer_flush(&b) == -1) return -1; ++ ++ buffer_init(&b,myread,s,bspace,sizeof bspace); ++ numcolons = 0; ++ for (;;) { ++ if (buffer_get(&b,&ch,1) != 1) return -1; ++ if ((ch == ' ') || (ch == '\t') || (ch == '\r')) continue; ++ if (ch == '\n') return 0; ++ if (numcolons < 3) { ++ if (ch == ':') ++numcolons; ++ } ++ else { ++ if (!stralloc_append(out,&ch)) return -1; ++ if (out->len > 256) return 0; ++ } ++ } ++} ++ ++int remoteinfo6(stralloc *out,char ipremote[16],uint16 portremote,char iplocal[16],uint16 portlocal,unsigned int timeout,uint32 netif) ++{ ++ int s; ++ int r; ++ ++ if (!stralloc_copys(out,"")) return -1; ++ ++ taia_now(&now); ++ taia_uint(&deadline,timeout); ++ taia_add(&deadline,&now,&deadline); ++ ++ s = socket_tcp6(); ++ if (s == -1) return -1; ++ r = doit(out,s,ipremote,portremote,iplocal,portlocal,timeout,netif); ++ close(s); ++ return r; ++} +diff -uNr ucspi-tcp-0.88.orig/rules.c ucspi-tcp-0.88/rules.c +--- ucspi-tcp-0.88.orig/rules.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/rules.c 2009-08-04 17:45:59.000000000 -0500 +@@ -64,7 +64,7 @@ + + if (!stralloc_copys(&rules_name,ip)) return -1; + while (rules_name.len > 0) { +- if (ip[rules_name.len - 1] == '.') { ++ if (ip[rules_name.len - 1] == '.' || ip[rules_name.len - 1] == ':') { + r = dorule(callback); + if (r) return r; + } +diff -uNr ucspi-tcp-0.88.orig/scan_ip6.c ucspi-tcp-0.88/scan_ip6.c +--- ucspi-tcp-0.88.orig/scan_ip6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/scan_ip6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,87 @@ ++#include "scan.h" ++#include "ip4.h" ++#include "ip6.h" ++ ++/* ++ * IPv6 addresses are really ugly to parse. ++ * Syntax: (h = hex digit) ++ * 1. hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh ++ * 2. any number of 0000 may be abbreviated as "::", but only once ++ * 3. The last two words may be written as IPv4 address ++ */ ++ ++unsigned int scan_ip6(const char *s,char ip[16]) ++{ ++ unsigned int i; ++ unsigned int len=0; ++ unsigned long u; ++ ++ char suffix[16]; ++ int prefixlen=0; ++ int suffixlen=0; ++ ++ if ((i=ip4_scan((char*)s,ip+12))) { ++ for (len=0; len<12; ++len) ip[len]=V4mappedprefix[len]; ++ return i; ++ } ++ for (i=0; i<16; i++) ip[i]=0; ++ 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((char*)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]=='.') { ++ int j=ip4_scan((char*)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='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_xlong(char *src,unsigned long *dest) { ++ register const char *tmp=src; ++ register int l=0; ++ register unsigned char c; ++ while ((c=fromhex(*tmp))<16) { ++ l=(l<<4)+c; ++ ++tmp; ++ } ++ *dest=l; ++ return tmp-src; ++} +diff -uNr ucspi-tcp-0.88.orig/socket.h ucspi-tcp-0.88/socket.h +--- ucspi-tcp-0.88.orig/socket.h 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/socket.h 2009-08-04 17:45:59.000000000 -0500 +@@ -2,21 +2,52 @@ + #define SOCKET_H + + #include "uint16.h" ++#include "uint32.h" + + extern int socket_tcp(void); + extern int socket_udp(void); ++extern int socket_tcp6(void); ++extern int socket_udp6(void); + +-extern int socket_connect4(int,char *,uint16); ++extern int socket_connect4(int,const char *,uint16); ++extern int socket_connect6(int s,const char *ip,uint16 port,uint32 scope_id); + extern int socket_connected(int); +-extern int socket_bind4(int,char *,uint16); +-extern int socket_bind4_reuse(int,char *,uint16); ++extern int socket_bind4(int,const char *,uint16); ++extern int socket_bind4_reuse(int,const char *,uint16); ++extern int socket_bind6(int s,const char *ip,uint16 port,uint32 scope_id); ++extern int socket_bind6_reuse(int s,const char *ip,uint16 port,uint32 scope_id); + extern int socket_listen(int,int); + extern int socket_accept4(int,char *,uint16 *); ++extern int socket_accept6(int s,char *ip,uint16 *port,uint32 *scope_id); + extern int socket_recv4(int,char *,int,char *,uint16 *); +-extern int socket_send4(int,char *,int,char *,uint16); ++extern int socket_send4(int,const char *,int,const char *,uint16); ++extern int socket_recv6(int s,char *buf,unsigned int len,char *ip,uint16 *port,uint32 *scope_id); ++extern int socket_send6(int s,const char *buf,unsigned int len,const char *ip,uint16 port,uint32 scope_id); + extern int socket_local4(int,char *,uint16 *); + extern int socket_remote4(int,char *,uint16 *); ++extern int socket_local6(int s,char *ip,uint16 *port,uint32 *scope_id); ++extern int socket_remote6(int s,char *ip,uint16 *port,uint32 *scope_id); ++ ++/* enable sending udp packets to the broadcast address */ ++extern int socket_broadcast(int); ++/* join a multicast group on the given interface */ ++extern int socket_mcjoin4(int,char *,char *); ++extern int socket_mcjoin6(int,char *,int); ++/* leave a multicast group on the given interface */ ++extern int socket_mcleave4(int,char *); ++extern int socket_mcleave6(int,char *); ++/* set multicast TTL/hop count for outgoing packets */ ++extern int socket_mcttl4(int,char); ++extern int socket_mcttl6(int,char); ++/* enable multicast loopback */ ++extern int socket_mcloop4(int,char); ++extern int socket_mcloop6(int,char); ++ ++extern const char* socket_getifname(uint32 interface); ++extern uint32 socket_getifidx(const char *ifname); + + extern void socket_tryreservein(int,int); + ++extern int noipv6; ++ + #endif +diff -uNr ucspi-tcp-0.88.orig/socket_accept6.c ucspi-tcp-0.88/socket_accept6.c +--- ucspi-tcp-0.88.orig/socket_accept6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_accept6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,44 @@ ++#include ++#include ++#include ++#include ++#include "byte.h" ++#include "socket.h" ++#include "ip6.h" ++#include "haveip6.h" ++#include "error.h" ++ ++int socket_accept6(int s,char ip[16],uint16 *port,uint32 *scope_id) ++{ ++#ifdef LIBC_HAS_IP6 ++ struct sockaddr_in6 sa; ++#else ++ struct sockaddr_in sa; ++#endif ++ unsigned int dummy = sizeof sa; ++ int fd; ++ ++ fd = accept(s,(struct sockaddr *) &sa,&dummy); ++ if (fd == -1) return -1; ++ ++#ifdef LIBC_HAS_IP6 ++ 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); ++ return fd; ++ } ++ 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; ++#else ++ byte_copy(ip,12,V4mappedprefix); ++ byte_copy(ip+12,4,(char *) &sa.sin_addr); ++ uint16_unpack_big((char *) &sa.sin_port,port); ++ if (scope_id) *scope_id=0; ++ return fd; ++#endif ++} +diff -uNr ucspi-tcp-0.88.orig/socket_bind.c ucspi-tcp-0.88/socket_bind.c +--- ucspi-tcp-0.88.orig/socket_bind.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/socket_bind.c 2009-08-04 17:45:59.000000000 -0500 +@@ -5,7 +5,7 @@ + #include "byte.h" + #include "socket.h" + +-int socket_bind4(int s,char ip[4],uint16 port) ++int socket_bind4(int s,const char ip[4],uint16 port) + { + struct sockaddr_in sa; + +@@ -17,7 +17,7 @@ + return bind(s,(struct sockaddr *) &sa,sizeof sa); + } + +-int socket_bind4_reuse(int s,char ip[4],uint16 port) ++int socket_bind4_reuse(int s,const char ip[4],uint16 port) + { + int opt = 1; + setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt); +diff -uNr ucspi-tcp-0.88.orig/socket_bind6.c ucspi-tcp-0.88/socket_bind6.c +--- ucspi-tcp-0.88.orig/socket_bind6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_bind6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,45 @@ ++#include ++#include ++#include ++#include ++#include "byte.h" ++#include "socket.h" ++#include "ip6.h" ++#include "haveip6.h" ++#include "error.h" ++ ++int socket_bind6(int s,const char ip[16],uint16 port,uint32 scope_id) ++{ ++#ifdef LIBC_HAS_IP6 ++ struct sockaddr_in6 sa; ++ ++ if (noipv6) { ++#endif ++ int i; ++ for (i=0; i<16; i++) ++ if (ip[i]!=0) break; ++ if (i==16 || ip6_isv4mapped(ip)) ++ return socket_bind4(s,ip+12,port); ++#ifdef LIBC_HAS_IP6 ++ } ++ 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); ++#else ++ errno=error_proto; ++ return -1; ++#endif ++} ++ ++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); ++} ++ +diff -uNr ucspi-tcp-0.88.orig/socket_conn.c ucspi-tcp-0.88/socket_conn.c +--- ucspi-tcp-0.88.orig/socket_conn.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/socket_conn.c 2009-08-04 17:45:59.000000000 -0500 +@@ -6,7 +6,7 @@ + #include "byte.h" + #include "socket.h" + +-int socket_connect4(int s,char ip[4],uint16 port) ++int socket_connect4(int s,const char ip[4],uint16 port) + { + struct sockaddr_in sa; + +diff -uNr ucspi-tcp-0.88.orig/socket_conn6.c ucspi-tcp-0.88/socket_conn6.c +--- ucspi-tcp-0.88.orig/socket_conn6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_conn6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,38 @@ ++#include ++#include ++#include ++#include ++#include ++#include "byte.h" ++#include "socket.h" ++#include "ip6.h" ++#include "haveip6.h" ++#include "uint32.h" ++#include "ip4.h" ++ ++int socket_connect6(int s,const char ip[16],uint16 port,uint32 scope_id) ++{ ++#ifdef LIBC_HAS_IP6 ++ struct sockaddr_in6 sa; ++ ++ if (noipv6) { ++#endif ++ if (ip6_isv4mapped(ip)) ++ return socket_connect4(s,ip+12,port); ++ if (byte_equal(ip,16,V6loopback)) ++ return socket_connect4(s,ip4loopback,port); ++#ifdef LIBC_HAS_IP6 ++ } ++ byte_zero(&sa,sizeof sa); ++ sa.sin6_family = PF_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); ++#else ++ errno=EPROTONOSUPPORT; ++ return -1; ++#endif ++} +diff -uNr ucspi-tcp-0.88.orig/socket_getifidx.c ucspi-tcp-0.88/socket_getifidx.c +--- ucspi-tcp-0.88.orig/socket_getifidx.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_getifidx.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,8 @@ ++#include ++#include ++#include ++#include "socket.h" ++ ++uint32 socket_getifidx(const char* ifname) { ++ return if_nametoindex(ifname); ++} +diff -uNr ucspi-tcp-0.88.orig/socket_getifname.c ucspi-tcp-0.88/socket_getifname.c +--- ucspi-tcp-0.88.orig/socket_getifname.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_getifname.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,14 @@ ++#include ++#include ++#include ++#include "socket.h" ++ ++static char ifname[IFNAMSIZ]; ++ ++const char* socket_getifname(uint32 interface) { ++ char *tmp=if_indextoname(interface,ifname); ++ if (tmp) ++ return tmp; ++ else ++ return "[unknown]"; ++} +diff -uNr ucspi-tcp-0.88.orig/socket_ip4loopback.c ucspi-tcp-0.88/socket_ip4loopback.c +--- ucspi-tcp-0.88.orig/socket_ip4loopback.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_ip4loopback.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,2 @@ ++ ++const char ip4loopback[4] = {127,0,0,1}; +diff -uNr ucspi-tcp-0.88.orig/socket_local6.c ucspi-tcp-0.88/socket_local6.c +--- ucspi-tcp-0.88.orig/socket_local6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_local6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,39 @@ ++#include ++#include ++#include ++#include ++#include "byte.h" ++#include "socket.h" ++#include "ip6.h" ++#include "haveip6.h" ++#include "error.h" ++ ++int socket_local6(int s,char ip[16],uint16 *port,uint32 *scope_id) ++{ ++#ifdef LIBC_HAS_IP6 ++ struct sockaddr_in6 sa; ++#else ++ struct sockaddr_in sa; ++#endif ++ unsigned int dummy = sizeof sa; ++ ++ if (getsockname(s,(struct sockaddr *) &sa,&dummy) == -1) return -1; ++#ifdef LIBC_HAS_IP6 ++ 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); ++ return 0; ++ } ++ 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; ++#else ++ byte_copy(ip,12,V4mappedprefix); ++ byte_copy(ip+12,4,(char *) &sa.sin_addr); ++ uint16_unpack_big((char *) &sa.sin_port,port); ++ if (scope_id) *scope_id=0; ++#endif ++ return 0; ++} +diff -uNr ucspi-tcp-0.88.orig/socket_recv6.c ucspi-tcp-0.88/socket_recv6.c +--- ucspi-tcp-0.88.orig/socket_recv6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_recv6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,44 @@ ++#include ++#include ++#include ++#include ++#include "byte.h" ++#include "socket.h" ++#include "ip6.h" ++#include "haveip6.h" ++#include "error.h" ++ ++int socket_recv6(int s,char *buf,unsigned int len,char ip[16],uint16 *port,uint32 *scope_id) ++{ ++#ifdef LIBC_HAS_IP6 ++ struct sockaddr_in6 sa; ++#else ++ struct sockaddr_in sa; ++#endif ++ 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; ++ ++#ifdef LIBC_HAS_IP6 ++ if (noipv6) { ++ 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); ++ return r; ++ } ++ 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; ++#else ++ byte_copy(ip,12,(char *)V4mappedprefix); ++ byte_copy(ip+12,4,(char *) &sa.sin_addr); ++ uint16_unpack_big((char *) &sa.sin_port,port); ++ if (scope_id) *scope_id=0; ++#endif ++ ++ return r; ++} +diff -uNr ucspi-tcp-0.88.orig/socket_remote6.c ucspi-tcp-0.88/socket_remote6.c +--- ucspi-tcp-0.88.orig/socket_remote6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_remote6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,39 @@ ++#include ++#include ++#include ++#include ++#include "byte.h" ++#include "socket.h" ++#include "ip6.h" ++#include "haveip6.h" ++#include "error.h" ++ ++int socket_remote6(int s,char ip[16],uint16 *port,uint32 *scope_id) ++{ ++#ifdef LIBC_HAS_IP6 ++ struct sockaddr_in6 sa; ++#else ++ struct sockaddr_in sa; ++#endif ++ unsigned int dummy = sizeof sa; ++ ++ if (getpeername(s,(struct sockaddr *) &sa,&dummy) == -1) return -1; ++#ifdef LIBC_HAS_IP6 ++ 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); ++ return 0; ++ } ++ 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; ++#else ++ byte_copy(ip,12,V4mappedprefix); ++ byte_copy(ip+12,4,(char *) &sa.sin_addr); ++ uint16_unpack_big((char *) &sa.sin_port,port); ++ if (scope_id) *scope_id=0; ++#endif ++ return 0; ++} +diff -uNr ucspi-tcp-0.88.orig/socket_send6.c ucspi-tcp-0.88/socket_send6.c +--- ucspi-tcp-0.88.orig/socket_send6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_send6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,40 @@ ++#include ++#include ++#include ++#include ++#include "byte.h" ++#include "socket.h" ++#include "ip4.h" ++#include "ip6.h" ++#include "haveip6.h" ++#include "error.h" ++ ++int socket_send6(int s,const char *buf,unsigned int len,const char ip[16],uint16 port,uint32 scope_id) ++{ ++#ifdef LIBC_HAS_IP6 ++ struct sockaddr_in6 sa; ++#else ++ struct sockaddr_in sa; ++#endif ++ ++ byte_zero(&sa,sizeof sa); ++#ifdef LIBC_HAS_IP6 ++ if (noipv6) { ++#endif ++ if (ip6_isv4mapped(ip)) ++ return socket_send4(s,buf,len,ip+12,port); ++ if (byte_equal(ip,16,V6loopback)) ++ return socket_send4(s,buf,len,ip4loopback,port); ++#ifdef LIBC_HAS_IP6 ++ errno=error_proto; ++ return -1; ++ } ++ sa.sin6_family = AF_INET6; ++ 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); ++#else ++ errno=error_proto; ++ return -1; ++#endif ++} +diff -uNr ucspi-tcp-0.88.orig/socket_tcp6.c ucspi-tcp-0.88/socket_tcp6.c +--- ucspi-tcp-0.88.orig/socket_tcp6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_tcp6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,44 @@ ++#include ++#include ++#include ++#include ++#include ++#include "ndelay.h" ++#include "socket.h" ++#include "haveip6.h" ++#include "error.h" ++ ++#ifdef LIBC_HAS_IP6 ++int noipv6=0; ++#else ++int noipv6=1; ++#endif ++ ++int socket_tcp6(void) ++{ ++#ifdef LIBC_HAS_IP6 ++ int s; ++ ++ if (noipv6) goto compat; ++ s = socket(PF_INET6,SOCK_STREAM,0); ++ if (s == -1) { ++ if (errno == EINVAL || errno == EAFNOSUPPORT) { ++compat: ++ s=socket(AF_INET,SOCK_STREAM,0); ++ noipv6=1; ++ if (s==-1) return -1; ++ } else ++ return -1; ++ } ++ if (ndelay_on(s) == -1) { close(s); return -1; } ++#ifdef IPV6_V6ONLY ++ { ++ int zero=0; ++ setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&zero,sizeof(zero)); ++ } ++#endif ++ return s; ++#else ++ return socket_tcp(); ++#endif ++} +diff -uNr ucspi-tcp-0.88.orig/socket_udp6.c ucspi-tcp-0.88/socket_udp6.c +--- ucspi-tcp-0.88.orig/socket_udp6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_udp6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,38 @@ ++#include ++#include ++#include ++#include ++#include "haveip6.h" ++#include "socket.h" ++ ++#ifndef EAFNOSUPPORT ++#define EAFNOSUPPORT EINVAL ++#endif ++ ++int socket_udp6(void) ++{ ++#ifdef LIBC_HAS_IP6 ++ int s; ++ ++ if (noipv6) goto compat; ++ s = socket(PF_INET6,SOCK_DGRAM,0); ++ if (s == -1) { ++ if (errno == EINVAL || errno == EAFNOSUPPORT) { ++compat: ++ s=socket(AF_INET,SOCK_DGRAM,0); ++ noipv6=1; ++ if (s==-1) return -1; ++ } else ++ return -1; ++ } ++#ifdef IPV6_V6ONLY ++ { ++ int zero=0; ++ setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&zero,sizeof(zero)); ++ } ++#endif ++ return s; ++#else ++ return socket_udp(); ++#endif ++} +diff -uNr ucspi-tcp-0.88.orig/socket_v4mappedprefix.c ucspi-tcp-0.88/socket_v4mappedprefix.c +--- ucspi-tcp-0.88.orig/socket_v4mappedprefix.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_v4mappedprefix.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,2 @@ ++ ++const unsigned char V4mappedprefix[12]={0,0,0,0,0,0,0,0,0,0,0xff,0xff}; +diff -uNr ucspi-tcp-0.88.orig/socket_v6any.c ucspi-tcp-0.88/socket_v6any.c +--- ucspi-tcp-0.88.orig/socket_v6any.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_v6any.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,2 @@ ++ ++const unsigned char V6any[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +diff -uNr ucspi-tcp-0.88.orig/socket_v6loopback.c ucspi-tcp-0.88/socket_v6loopback.c +--- ucspi-tcp-0.88.orig/socket_v6loopback.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/socket_v6loopback.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,2 @@ ++ ++const unsigned char V6loopback[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; +diff -uNr ucspi-tcp-0.88.orig/str.h ucspi-tcp-0.88/str.h +--- ucspi-tcp-0.88.orig/str.h 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/str.h 2009-08-04 17:45:59.000000000 -0500 +@@ -1,13 +1,13 @@ + #ifndef STR_H + #define STR_H + +-extern unsigned int str_copy(char *,char *); +-extern int str_diff(char *,char *); +-extern int str_diffn(char *,char *,unsigned int); +-extern unsigned int str_len(char *); +-extern unsigned int str_chr(char *,int); +-extern unsigned int str_rchr(char *,int); +-extern int str_start(char *,char *); ++extern unsigned int str_copy(char *,const char *); ++extern int str_diff(const char *,const char *); ++extern int str_diffn(const char *,const char *,unsigned int); ++extern unsigned int str_len(const char *); ++extern unsigned int str_chr(const char *,int); ++extern unsigned int str_rchr(const char *,int); ++extern int str_start(const char *,const char *); + + #define str_equal(s,t) (!str_diff((s),(t))) + +diff -uNr ucspi-tcp-0.88.orig/str_chr.c ucspi-tcp-0.88/str_chr.c +--- ucspi-tcp-0.88.orig/str_chr.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/str_chr.c 2009-08-04 17:45:59.000000000 -0500 +@@ -1,9 +1,9 @@ + #include "str.h" + +-unsigned int str_chr(register char *s,int c) ++unsigned int str_chr(register const char *s,int c) + { + register char ch; +- register char *t; ++ register const char *t; + + ch = c; + t = s; +diff -uNr ucspi-tcp-0.88.orig/str_diff.c ucspi-tcp-0.88/str_diff.c +--- ucspi-tcp-0.88.orig/str_diff.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/str_diff.c 2009-08-04 17:45:59.000000000 -0500 +@@ -1,6 +1,6 @@ + #include "str.h" + +-int str_diff(register char *s,register char *t) ++int str_diff(register const char *s,register const char *t) + { + register char x; + +diff -uNr ucspi-tcp-0.88.orig/str_len.c ucspi-tcp-0.88/str_len.c +--- ucspi-tcp-0.88.orig/str_len.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/str_len.c 2009-08-04 17:45:59.000000000 -0500 +@@ -1,8 +1,8 @@ + #include "str.h" + +-unsigned int str_len(char *s) ++unsigned int str_len(const char *s) + { +- register char *t; ++ register const char *t; + + t = s; + for (;;) { +diff -uNr ucspi-tcp-0.88.orig/str_start.c ucspi-tcp-0.88/str_start.c +--- ucspi-tcp-0.88.orig/str_start.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/str_start.c 2009-08-04 17:45:59.000000000 -0500 +@@ -1,6 +1,6 @@ + #include "str.h" + +-int str_start(register char *s,register char *t) ++int str_start(register const char *s,register const char *t) + { + register char x; + +diff -uNr ucspi-tcp-0.88.orig/stralloc.h ucspi-tcp-0.88/stralloc.h +--- ucspi-tcp-0.88.orig/stralloc.h 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/stralloc.h 2009-08-04 17:45:59.000000000 -0500 +@@ -9,18 +9,20 @@ + extern int stralloc_readyplus(stralloc *,unsigned int); + extern int stralloc_copy(stralloc *,stralloc *); + extern int stralloc_cat(stralloc *,stralloc *); +-extern int stralloc_copys(stralloc *,char *); +-extern int stralloc_cats(stralloc *,char *); +-extern int stralloc_copyb(stralloc *,char *,unsigned int); +-extern int stralloc_catb(stralloc *,char *,unsigned int); ++extern int stralloc_copys(stralloc *,const char *); ++extern int stralloc_cats(stralloc *,const char *); ++extern int stralloc_copyb(stralloc *,const char *,unsigned int); ++extern int stralloc_catb(stralloc *,const char *,unsigned int); + extern int stralloc_append(stralloc *,char *); /* beware: this takes a pointer to 1 char */ +-extern int stralloc_starts(stralloc *,char *); ++extern int stralloc_starts(stralloc *,const char *); + + #define stralloc_0(sa) stralloc_append(sa,"") + + extern int stralloc_catulong0(stralloc *,unsigned long,unsigned int); + extern int stralloc_catlong0(stralloc *,long,unsigned int); + ++extern void stralloc_free(stralloc *); ++ + #define stralloc_catlong(sa,l) (stralloc_catlong0((sa),(l),0)) + #define stralloc_catuint0(sa,i,n) (stralloc_catulong0((sa),(i),(n))) + #define stralloc_catint0(sa,i,n) (stralloc_catlong0((sa),(i),(n))) +diff -uNr ucspi-tcp-0.88.orig/stralloc_catb.c ucspi-tcp-0.88/stralloc_catb.c +--- ucspi-tcp-0.88.orig/stralloc_catb.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/stralloc_catb.c 2009-08-04 17:45:59.000000000 -0500 +@@ -1,7 +1,7 @@ + #include "stralloc.h" + #include "byte.h" + +-int stralloc_catb(stralloc *sa,char *s,unsigned int n) ++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; +diff -uNr ucspi-tcp-0.88.orig/stralloc_cats.c ucspi-tcp-0.88/stralloc_cats.c +--- ucspi-tcp-0.88.orig/stralloc_cats.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/stralloc_cats.c 2009-08-04 17:45:59.000000000 -0500 +@@ -2,7 +2,7 @@ + #include "str.h" + #include "stralloc.h" + +-int stralloc_cats(stralloc *sa,char *s) ++int stralloc_cats(stralloc *sa,const char *s) + { + return stralloc_catb(sa,s,str_len(s)); + } +diff -uNr ucspi-tcp-0.88.orig/stralloc_opyb.c ucspi-tcp-0.88/stralloc_opyb.c +--- ucspi-tcp-0.88.orig/stralloc_opyb.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/stralloc_opyb.c 2009-08-04 17:45:59.000000000 -0500 +@@ -1,7 +1,7 @@ + #include "stralloc.h" + #include "byte.h" + +-int stralloc_copyb(stralloc *sa,char *s,unsigned int n) ++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); +diff -uNr ucspi-tcp-0.88.orig/stralloc_opys.c ucspi-tcp-0.88/stralloc_opys.c +--- ucspi-tcp-0.88.orig/stralloc_opys.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/stralloc_opys.c 2009-08-04 17:45:59.000000000 -0500 +@@ -2,7 +2,7 @@ + #include "str.h" + #include "stralloc.h" + +-int stralloc_copys(stralloc *sa,char *s) ++int stralloc_copys(stralloc *sa,const char *s) + { + return stralloc_copyb(sa,s,str_len(s)); + } +diff -uNr ucspi-tcp-0.88.orig/tcp-environ.5 ucspi-tcp-0.88/tcp-environ.5 +--- ucspi-tcp-0.88.orig/tcp-environ.5 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/tcp-environ.5 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,66 @@ ++.TH tcp-environ 5 ++.SH NAME ++tcp-environ \- TCP-related environment variables ++.SH DESCRIPTION ++The following environment variables ++describe a TCP connection. ++They are set up by ++.BR tcp-env , ++.BR tcpclient , ++and ++.BR tcpserver . ++Note that ++.BR TCPLOCALHOST , ++.BR TCPREMOTEHOST , ++and ++.B TCPREMOTEINFO ++can contain arbitrary characters. ++.TP 5 ++PROTO ++The string ++.BR TCP . ++.TP 5 ++TCPLOCALHOST ++The domain name of the local host, ++with uppercase letters converted to lowercase. ++If there is no currently available domain name ++for the local IP address, ++.B TCPLOCALHOST ++is not set. ++.TP 5 ++TCPLOCALIP ++The IP address of the local host, in dotted-decimal form. ++.TP 5 ++TCPLOCALPORT ++The local TCP port number, in decimal. ++.TP 5 ++TCPREMOTEHOST ++The domain name of the remote host, ++with uppercase letters converted to lowercase. ++If there is no currently available domain name ++for the remote IP address, ++.B TCPREMOTEHOST ++is not set. ++.TP 5 ++TCPREMOTEINFO ++A connection-specific string, perhaps a username, ++supplied by the remote host ++via 931/1413/IDENT/TAP. ++If the remote host did not supply connection information, ++.B TCPREMOTEINFO ++is not set. ++.TP 5 ++TCPREMOTEIP ++The IP address of the remote host. ++.TP 5 ++TCPREMOTEPORT ++The remote TCP port number. ++.TP 5 ++TCPINTERFACE ++The interface name ("eth0") for IPv6 connections using link-local ++addresses. ++.SH "SEE ALSO" ++tcpclient(1), ++tcpserver(1), ++tcp-env(1), ++tcp(4) +diff -uNr ucspi-tcp-0.88.orig/tcpcat.1 ucspi-tcp-0.88/tcpcat.1 +--- ucspi-tcp-0.88.orig/tcpcat.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/tcpcat.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,20 @@ ++.TH tcpcat 1 ++.SH NAME ++tcpcat \- print data from a TCP port ++.SH SYNTAX ++.B tcpcat ++.I host ++.I port ++.SH DESCRIPTION ++.B tcpcat ++connects to ++.I port ++on ++.I host ++and prints any data it receives. ++ ++.B tcpcat ++can be used to transfer binary data. ++It does no conversions. ++.SH "SEE ALSO" ++tcpclient(1) +diff -uNr ucspi-tcp-0.88.orig/tcpclient.1 ucspi-tcp-0.88/tcpclient.1 +--- ucspi-tcp-0.88.orig/tcpclient.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/tcpclient.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,173 @@ ++.TH tcpclient 1 ++.SH NAME ++tcpclient \- create an outgoing TCP connection ++.SH SYNOPSIS ++.B tcpclient ++[ ++.B \-46hHrRdDqQv ++] ++[ ++.B \-i\fIlocalip ++] ++[ ++.B \-p\fIlocalport ++] ++[ ++.B \-T\fItimeoutconn ++] ++[ ++.B \-l\fIlocalname ++] ++[ ++.B \-t\fItimeoutinfo ++] ++[ ++.B \-I\fIinterface ++] ++.I host ++.I port ++.I program ++[ ++.I arg ... ++] ++.SH DESCRIPTION ++.B tcpclient ++attempts to connect to a TCP server. ++If it is successful, it runs ++.I program ++with the given arguments, ++with descriptor 6 reading from the network ++and descriptor 7 writing to the network. ++ ++The server's address is given by ++.I host ++and ++.IR port . ++.I host ++may be 0, referring to the local machine, ++or a dotted-decimal IP address, ++or a host name; ++if a host has several IP addresses, ++.B tcpclient ++tries each in turn. ++.I port ++may be a numeric port number ++or a port name. ++ ++.B tcpclient ++sets up several environment variables, ++as described in ++.B tcp-environ(5). ++.SH OPTIONS ++.TP ++.B \-i\fIlocalip ++Use ++.I localip ++as the IP address for the local side of the connection; ++quit if ++.I localip ++is not available. ++.TP ++.B \-p\fIlocalport ++Use ++.I localport ++as the port number for the local side of the connection; ++quit if ++.I localport ++is not available. ++.TP ++.B \-I\fIinterface ++Use ++.I interface ++as the local network interface. This is only defined for IPv6 sockets ++and needed if you use link-local IPv6 addresses. ++.TP ++.B \-T\fItimeoutconn ++Give up on the ++connection attempt ++after ++.I timeoutconn ++seconds. Default: 60. ++This timeout applies to each IP address tried. ++.TP ++.B \-d ++(Default.) ++Delay sending data for a fraction of a second whenever the ++remote host is responding slowly, ++to make better use of the network. ++.TP ++.B \-D ++Never delay sending data; ++enable TCP_NODELAY. ++This is appropriate for interactive connections. ++.TP ++.B \-q ++Quiet. ++Do not print any messages. ++.TP ++.B \-Q ++(Default.) ++Print error messages. ++.TP ++.B \-v ++Verbose. ++Print all available messages. ++.SH "DATA-GATHERING OPTIONS" ++.TP ++.B \-h ++(Default.) ++Look up the remote host name for ++.BR TCPREMOTEHOST . ++.TP ++.B \-H ++Do not look up the remote host name; ++unset ++.BR TCPREMOTEHOST . ++.TP ++.B \-l\fIlocalname ++Do not look up the local host name; ++use ++.I localname ++for ++.BR TCPLOCALHOST . ++.TP ++.B \-r ++(Default.) ++Attempt to obtain ++.B TCPREMOTEINFO ++from the remote host. ++.TP ++.B \-R ++Do not attempt to obtain ++.B TCPREMOTEINFO ++from the remote host. ++.TP ++.B \-t\fItimeoutinfo ++Give up on the ++.B TCPREMOTEINFO ++connection attempt ++after ++.I timeoutinfo ++seconds. Default: 26. ++.TP ++.B \-4 ++Fall back to IPv4 sockets. This is necessary for terminally broken ++systems like OpenBSD which will not let IPv6 sockets connect to ++V4-mapped IPv6 addresses. Please note that this also applies to DNS ++lookups, so you will have to use an DNS resolver with an IPv6 address to ++connect to IPv6 systems. Use \fBDNSCACHEIP\fR to set the DNS resolver ++IP dynamically. ++.TP ++.B \-6 ++Force IPv6 mode in UCSPI environment variables, even for ++IPv4 connections. This will set \fB$PROTO\fR to \fBTCP6\fR and put ++IPv4-mapped IPv6 addresses in \fBTCPLOCALIP\fR and \fBTCPREMOTEIP\fR. ++.SH "SEE ALSO" ++date@(1), ++finger@(1), ++http@(1), ++mconnect(1), ++tcpcat(1), ++tcpserver(1), ++who@(1), ++tcp-environ(5) +diff -uNr ucspi-tcp-0.88.orig/tcpclient.c ucspi-tcp-0.88/tcpclient.c +--- ucspi-tcp-0.88.orig/tcpclient.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/tcpclient.c 2009-08-04 17:45:59.000000000 -0500 +@@ -9,6 +9,7 @@ + #include "scan.h" + #include "str.h" + #include "ip4.h" ++#include "ip6.h" + #include "uint16.h" + #include "socket.h" + #include "fd.h" +@@ -20,6 +21,7 @@ + #include "timeoutconn.h" + #include "remoteinfo.h" + #include "dns.h" ++#include "byte.h" + + #define FATAL "tcpclient: fatal: " + #define CONNECT "tcpclient: unable to connect to " +@@ -31,27 +33,30 @@ + void usage(void) + { + strerr_die1x(100,"tcpclient: usage: tcpclient \ +-[ -hHrRdDqQv ] \ ++[ -46hHrRdDqQv ] \ + [ -i localip ] \ + [ -p localport ] \ + [ -T timeoutconn ] \ + [ -l localname ] \ + [ -t timeoutinfo ] \ ++[ -I interface ] \ + host port program"); + } + ++int forcev6 = 0; + int verbosity = 1; + int flagdelay = 1; + int flagremoteinfo = 1; + int flagremotehost = 1; + unsigned long itimeout = 26; + unsigned long ctimeout[2] = { 2, 58 }; ++uint32 netif = 0; + +-char iplocal[4] = { 0,0,0,0 }; ++char iplocal[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; + uint16 portlocal = 0; + char *forcelocal = 0; + +-char ipremote[4]; ++char ipremote[16]; + uint16 portremote; + + char *hostname; +@@ -61,12 +66,13 @@ + static stralloc tmp; + static stralloc fqdn; + char strnum[FMT_ULONG]; +-char ipstr[IP4_FMT]; ++char ipstr[IP6_FMT]; + + char seed[128]; + + main(int argc,char **argv) + { ++ int fakev4=0; + unsigned long u; + int opt; + char *x; +@@ -80,8 +86,10 @@ + close(7); + sig_ignore(sig_pipe); + +- while ((opt = getopt(argc,argv,"dDvqQhHrRi:p:t:T:l:")) != opteof) ++ while ((opt = getopt(argc,argv,"46dDvqQhHrRi:p:t:T:l:I:")) != opteof) + switch(opt) { ++ case '4': noipv6 = 1; break; ++ case '6': forcev6 = 1; break; + case 'd': flagdelay = 1; break; + case 'D': flagdelay = 0; break; + case 'v': verbosity = 2; break; +@@ -97,7 +105,8 @@ + if (optarg[j] == '+') ++j; + scan_ulong(optarg + j,&ctimeout[1]); + break; +- case 'i': if (!ip4_scan(optarg,iplocal)) usage(); break; ++ case 'i': if (!scan_ip6(optarg,iplocal)) usage(); break; ++ case 'I': netif=socket_getifidx(optarg); break; + case 'p': scan_ulong(optarg,&u); portlocal = u; break; + default: usage(); + } +@@ -108,8 +117,8 @@ + + hostname = *argv; + if (!hostname) usage(); +- if (str_equal(hostname,"")) hostname = "127.0.0.1"; +- if (str_equal(hostname,"0")) hostname = "127.0.0.1"; ++ if (!hostname[0] || str_equal(hostname,"0")) ++ hostname = (noipv6?"127.0.0.1":"::1"); + + x = *++argv; + if (!x) usage(); +@@ -127,33 +136,36 @@ + if (!*++argv) usage(); + + if (!stralloc_copys(&tmp,hostname)) nomem(); +- if (dns_ip4_qualify(&addresses,&fqdn,&tmp) == -1) ++ if (dns_ip6_qualify(&addresses,&fqdn,&tmp) == -1) + strerr_die4sys(111,FATAL,"temporarily unable to figure out IP address for ",hostname,": "); +- if (addresses.len < 4) ++ if (addresses.len < 16) + strerr_die3x(111,FATAL,"no IP address for ",hostname); + +- if (addresses.len == 4) { ++ if (addresses.len == 16) { + ctimeout[0] += ctimeout[1]; + ctimeout[1] = 0; + } + + for (cloop = 0;cloop < 2;++cloop) { + if (!stralloc_copys(&moreaddresses,"")) nomem(); +- for (j = 0;j + 4 <= addresses.len;j += 4) { +- s = socket_tcp(); ++ for (j = 0;j + 16 <= addresses.len;j += 4) { ++ s = socket_tcp6(); + if (s == -1) + strerr_die2sys(111,FATAL,"unable to create socket: "); +- if (socket_bind4(s,iplocal,portlocal) == -1) ++ if (socket_bind6(s,iplocal,portlocal,netif) == -1) + strerr_die2sys(111,FATAL,"unable to bind socket: "); +- if (timeoutconn(s,addresses.s + j,portremote,ctimeout[cloop]) == 0) ++ if (timeoutconn6(s,addresses.s + j,portremote,ctimeout[cloop],netif) == 0) + goto CONNECTED; + close(s); + if (!cloop && ctimeout[1] && (errno == error_timeout)) { +- if (!stralloc_catb(&moreaddresses,addresses.s + j,4)) nomem(); ++ if (!stralloc_catb(&moreaddresses,addresses.s + j,16)) nomem(); + } + else { + strnum[fmt_ulong(strnum,portremote)] = 0; +- ipstr[ip4_fmt(ipstr,addresses.s + j)] = 0; ++ if (ip6_isv4mapped(addresses.s+j)) ++ ipstr[ip4_fmt(ipstr,addresses.s + j + 12)] = 0; ++ else ++ ipstr[ip6_fmt(ipstr,addresses.s + j)] = 0; + strerr_warn5(CONNECT,ipstr," port ",strnum,": ",&strerr_sys); + } + } +@@ -169,37 +181,46 @@ + if (!flagdelay) + socket_tcpnodelay(s); /* if it fails, bummer */ + +- if (!pathexec_env("PROTO","TCP")) nomem(); +- +- if (socket_local4(s,iplocal,&portlocal) == -1) ++ if (socket_local6(s,iplocal,&portlocal,&netif) == -1) + strerr_die2sys(111,FATAL,"unable to get local address: "); + ++ if (!forcev6 && (ip6_isv4mapped(iplocal) || byte_equal(iplocal,16,V6any))) ++ fakev4=1; ++ ++ if (!pathexec_env("PROTO",fakev4?"TCP":"TCP6")) nomem(); ++ + strnum[fmt_ulong(strnum,portlocal)] = 0; + if (!pathexec_env("TCPLOCALPORT",strnum)) nomem(); +- ipstr[ip4_fmt(ipstr,iplocal)] = 0; ++ if (fakev4) ++ ipstr[ip4_fmt(ipstr,iplocal+12)] = 0; ++ else ++ ipstr[ip6_fmt(ipstr,iplocal)] = 0; + if (!pathexec_env("TCPLOCALIP",ipstr)) nomem(); + + x = forcelocal; + if (!x) +- if (dns_name4(&tmp,iplocal) == 0) { ++ if (dns_name6(&tmp,iplocal) == 0) { + if (!stralloc_0(&tmp)) nomem(); + x = tmp.s; + } + if (!pathexec_env("TCPLOCALHOST",x)) nomem(); + +- if (socket_remote4(s,ipremote,&portremote) == -1) ++ if (socket_remote6(s,ipremote,&portremote,&netif) == -1) + strerr_die2sys(111,FATAL,"unable to get remote address: "); + + strnum[fmt_ulong(strnum,portremote)] = 0; + if (!pathexec_env("TCPREMOTEPORT",strnum)) nomem(); +- ipstr[ip4_fmt(ipstr,ipremote)] = 0; ++ if (fakev4) ++ ipstr[ip4_fmt(ipstr,ipremote+12)] = 0; ++ else ++ ipstr[ip6_fmt(ipstr,ipremote)] = 0; + if (!pathexec_env("TCPREMOTEIP",ipstr)) nomem(); + if (verbosity >= 2) + strerr_warn4("tcpclient: connected to ",ipstr," port ",strnum,0); + + x = 0; + if (flagremotehost) +- if (dns_name4(&tmp,ipremote) == 0) { ++ if (dns_name6(&tmp,ipremote) == 0) { + if (!stralloc_0(&tmp)) nomem(); + x = tmp.s; + } +@@ -207,7 +228,7 @@ + + x = 0; + if (flagremoteinfo) +- if (remoteinfo(&tmp,ipremote,portremote,iplocal,portlocal,itimeout) == 0) { ++ if (remoteinfo6(&tmp,ipremote,portremote,iplocal,portlocal,itimeout,netif) == 0) { + if (!stralloc_0(&tmp)) nomem(); + x = tmp.s; + } +diff -uNr ucspi-tcp-0.88.orig/tcprules.1 ucspi-tcp-0.88/tcprules.1 +--- ucspi-tcp-0.88.orig/tcprules.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/tcprules.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,221 @@ ++.TH tcprules 1 ++.SH NAME ++tcprules \- compile rules for tcpserver ++.SH SYNOPSIS ++.B tcprules ++.I rules.cdb ++.I rules.tmp ++.SH OVERVIEW ++.B tcpserver ++optionally follows rules to decide whether a TCP connection is acceptable. ++For example, a rule of ++ ++.EX ++ 18.23.0.32:deny ++.EE ++ ++prohibits connections from IP address 18.23.0.32. ++ ++.B tcprules ++reads rules from its standard input ++and writes them into ++.I rules.cdb ++in a binary format suited ++for quick access by ++.BR tcpserver . ++ ++.B tcprules ++can be used while ++.B tcpserver ++is running: ++it ensures that ++.I rules.cdb ++is updated atomically. ++It does this by first writing the rules to ++.I rules.tmp ++and then moving ++.I rules.tmp ++on top of ++.IR rules.cdb . ++If ++.I rules.tmp ++already exists, it is destroyed. ++The directories containing ++.I rules.cdb ++and ++.I rules.tmp ++must be writable to ++.BR tcprules ; ++they must also be on the same filesystem. ++ ++If there is a problem with the input, ++.B tcprules ++complains and leaves ++.I rules.cdb ++alone. ++ ++The binary ++.I rules.cdb ++format is portable across machines. ++.SH "RULE FORMAT" ++A rule takes up one line. ++A file containing rules ++may also contain comments: lines beginning with # are ignored. ++ ++Each rule contains an ++.BR address , ++a colon, ++and a list of ++.BR instructions , ++with no extra spaces. ++When ++.B tcpserver ++receives a connection from that address, ++it follows the instructions. ++.SH "ADDRESSES" ++.B tcpserver ++starts by looking for a rule with address ++.IR TCPREMOTEINFO\fB@\fITCPREMOTEIP . ++If it doesn't find one, or if ++.I TCPREMOTEINFO ++is not set, it tries the address ++.IR TCPREMOTEIP . ++If that doesn't work, it tries shorter and shorter prefixes of ++.I TCPREMOTEIP ++ending with a dot. ++If none of them work, it tries the empty string. ++ ++For example, here are some rules: ++ ++.EX ++ joe@127.0.0.1:first ++.br ++ 18.23.0.32:second ++.br ++ 127.:third ++.br ++ :fourth ++.br ++ ::1:fifth ++.EE ++ ++If ++.I TCPREMOTEIP ++is ++.BR 10.119.75.38 , ++.B tcpserver ++will follow the ++.B fourth ++instructions. ++ ++If ++.I TCPREMOTEIP ++is ++.BR ::1 , ++.B tcpserver ++will follow the ++.B fifth ++instructions. Note that you cannot detect IPv4 mapped addresses by ++matching "::ffff", as those addresses will be converted to IPv4 before ++looking at the rules. ++ ++If ++.I TCPREMOTEIP ++is ++.BR 18.23.0.32 , ++.B tcpserver ++will follow the ++.B second ++instructions. ++ ++If ++.I TCPREMOTEINFO ++is ++.B bill ++and ++.I TCPREMOTEIP ++is ++.BR 127.0.0.1 , ++.B tcpserver ++will follow the ++.B third ++instructions. ++ ++If ++.I TCPREMOTEINFO ++is ++.B joe ++and ++.I TCPREMOTEIP ++is ++.BR 127.0.0.1 , ++.B tcpserver ++will follow the ++.B first ++instructions. ++.SH "ADDRESS RANGES" ++.B tcprules ++treats ++.B 1.2.3.37-53:ins ++as an abbreviation ++for the rules ++.BR 1.2.3.37:ins , ++.BR 1.2.3.38:ins , ++and so on up through ++.BR 1.2.3.53:ins . ++Similarly, ++.BR 10.2-3.:ins ++is an abbreviation for ++.B 10.2.:ins ++and ++.BR 10.3.:ins . ++.SH "INSTRUCTIONS" ++The instructions in a rule must begin with either ++.B allow ++or ++.BR deny . ++.B deny ++tells ++.B tcpserver ++to drop the connection without running anything. ++For example, the rule ++ ++.EX ++ :deny ++.EE ++ ++tells ++.B tcpserver ++to drop all connections that aren't handled by more specific rules. ++ ++The instructions may continue with some environment variables, ++in the format ++.IR ,VAR="VALUE" . ++.B tcpserver ++adds ++.I VAR=VALUE ++to the current environment. ++For example, ++ ++.EX ++ 10.0.:allow,RELAYCLIENT="@fix.me" ++.EE ++ ++adds ++.B RELAYCLIENT=@fix.me ++to the environment. ++The quotes here may be replaced by any repeated character: ++ ++.EX ++ 10.0.:allow,RELAYCLIENT=/@fix.me/ ++.EE ++ ++Any number of variables may be listed: ++ ++.EX ++ 127.0.0.1:allow,RELAYCLIENT="",TCPLOCALHOST="movie.edu" ++.EE ++.SH "SEE ALSO" ++tcprulescheck(1), ++tcpserver(1), ++tcp-environ(5) +diff -uNr ucspi-tcp-0.88.orig/tcprules.c ucspi-tcp-0.88/tcprules.c +--- ucspi-tcp-0.88.orig/tcprules.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/tcprules.c 2009-08-04 17:45:59.000000000 -0500 +@@ -123,8 +123,15 @@ + } + line.len = len; /* for die_bad() */ + +- colon = byte_chr(x,len,':'); +- if (colon == len) continue; ++ colon = 0; ++ for (;;) { ++ int tmp; ++ tmp = byte_chr(x + colon,len - colon,':'); ++ colon += tmp; ++ if (colon == len) continue; ++ if (byte_equal(x+colon+1,4,"deny") || byte_equal(x+colon+1,5,"allow")) break; ++ ++colon; ++ } + + if (!stralloc_copyb(&address,x,colon)) nomem(); + if (!stralloc_copys(&data,"")) nomem(); +diff -uNr ucspi-tcp-0.88.orig/tcprulescheck.1 ucspi-tcp-0.88/tcprulescheck.1 +--- ucspi-tcp-0.88.orig/tcprulescheck.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/tcprulescheck.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,25 @@ ++.TH tcprulescheck 1 ++.SH NAME ++tcprulescheck \- try out rules for tcpserver ++.SH SYNTAX ++.B tcprulescheck ++.I rules.cdb ++.I tcpremoteip ++[ ++.I tcpremoteinfo ++] ++.SH DESCRIPTION ++.B tcprulescheck ++says what ++.B tcpserver ++will do with a connection from ++IP address ++.IR tcpremoteip , ++following the rules compiled into ++.I rules.cdb ++by ++.BR tcprules . ++.SH "SEE ALSO" ++tcprules(1), ++tcpserver(1), ++tcp-environ(5) +diff -uNr ucspi-tcp-0.88.orig/tcpserver.1 ucspi-tcp-0.88/tcpserver.1 +--- ucspi-tcp-0.88.orig/tcpserver.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/tcpserver.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,266 @@ ++.TH tcpserver 1 ++.SH NAME ++tcpserver \- accept incoming TCP connections ++.SH SYNOPSIS ++.B tcpserver ++[ ++.B \-146jpPhHrRoOdDqQv ++] ++[ ++.B \-c\fIlimit ++] ++[ ++.B \-x\fIrules.cdb ++] ++[ ++.B \-B\fIbanner ++] ++[ ++.B \-g\fIgid ++] ++[ ++.B \-u\fIuid ++] ++[ ++.B \-b\fIbacklog ++] ++[ ++.B \-l\fIlocalname ++] ++[ ++.B \-t\fItimeout ++] ++[ ++.B \-I\fIinterface ++] ++.I host ++.I port ++.I program ++[ ++.I arg ... ++] ++.SH DESCRIPTION ++.B tcpserver ++waits for connections from TCP clients. ++For each connection, it runs ++.I program ++with the given arguments, ++with descriptor 0 reading from the network ++and descriptor 1 writing to the network. ++ ++The server's address is given by ++.I host ++and ++.IR port . ++.I host ++can be 0, allowing connections from any host; ++or a particular IP address, ++allowing connections only to that address; ++or a host name, allowing connections to the first IP address ++for that host. ++.I port ++may be a numeric port number ++or a port name. ++If ++.I port ++is 0, ++.B tcpserver ++will choose a free port. ++ ++.B tcpserver ++sets up several environment variables, ++as described in ++.B tcp-environ(5). ++ ++.B tcpserver ++exits when it receives SIGTERM. ++.SH "OPTIONS" ++.TP ++.B \-c\fIlimit ++Do not handle more than ++.I limit ++simultaneous connections. ++If there are ++.I limit ++simultaneous copies of ++.I program ++running, defer acceptance of a new connection ++until one copy finishes. ++.I limit ++must be a positive integer. ++Default: 40. ++.TP ++.B \-x\fIrules.cdb ++Follow the rules compiled into ++.I rules.cdb ++by ++.BR tcprules . ++These rules may specify setting environment variables ++or rejecting connections from bad sources. ++ ++.B tcpserver ++does not read ++.I rules.cdb ++into memory; ++you can rerun ++.B tcprules ++to change ++.BR tcpserver 's ++behavior on the fly. ++.TP ++.B \-B\fIbanner ++Write ++.I banner ++to the network immediately after each connection is made. ++.B tcpserver ++writes ++.I banner ++before looking up ++.BR TCPREMOTEHOST , ++before looking up ++.BR TCPREMOTEINFO , ++and before checking ++.IR rules.cdb . ++ ++This feature can be used to reduce latency in protocols ++where the client waits for a greeting from the server. ++.TP ++.B \-g\fIgid ++Switch group ID to ++.I gid ++after preparing to receive connections. ++.I gid ++must be a positive integer. ++.TP ++.B \-u\fIuid ++Switch user ID to ++.I uid ++after preparing to receive connections. ++.I uid ++must be a positive integer. ++.TP ++.B \-1 ++After preparing to receive connections, ++print the local port number to standard output. ++.TP ++.B \-4 ++Fall back to IPv4 sockets. This is necessary for terminally broken ++systems like OpenBSD which will not let IPv6 sockets connect to ++V4-mapped IPv6 addresses. Please note that this also applies to DNS ++lookups, so you will have to use an DNS resolver with an IPv6 address to ++accept IPv6 connections. Use \fBDNSCACHEIP\fR to set the DNS resolver ++IP dynamically. ++.TP ++.B \-6 ++Force IPv6 mode in UCSPI environment variables, even for ++IPv4 connections. This will set \fB$PROTO\fR to \fBTCP6\fR and put ++IPv4-mapped IPv6 addresses in \fBTCPLOCALIP\fR and \fBTCPREMOTEIP\fR. ++.TP ++.B \-I\fIinterface ++Bind to the network interface ++.I interface ++("eth0" on Linux, for example). This is only defined and needed for ++IPv6 link-local addresses. ++.TP ++.B \-b\fIbacklog ++Allow up to ++.I backlog ++simultaneous SYN_RECEIVEDs. ++Default: 20. ++On some systems, ++.I backlog ++is silently limited to 5. ++See ++.BR listen (2) ++for more details. ++.TP ++.B \-o ++Leave IP options alone. ++If the client is sending packets along an IP source route, ++send packets back along the same route. ++.TP ++.B \-O ++(Default.) ++Kill IP options. ++A client can still use source routing to connect and to send data, ++but packets will be sent back along the default route. ++.TP ++.B \-d ++(Default.) ++Delay sending data for a fraction of a second whenever the ++remote host is responding slowly, ++to make better use of the network. ++.TP ++.B \-D ++Never delay sending data; ++enable TCP_NODELAY. ++This is appropriate for interactive connections. ++.TP ++.B \-q ++Quiet. ++Do not print any messages. ++.TP ++.B \-Q ++(Default.) ++Print error messages. ++.TP ++.B \-v ++Verbose. ++Print all available messages. ++.SH "DATA-GATHERING OPTIONS" ++.TP ++.B \-p ++Paranoid. ++After looking up the remote host name, ++look up the IP addresses for that name, ++and make sure one of them matches ++.BR TCPREMOTEIP . ++If none of them do, ++unset ++.BR TCPREMOTEHOST . ++.TP ++.B \-P ++(Default.) ++Not paranoid. ++.TP ++.B \-h ++(Default.) ++Look up the remote host name and set ++.BR TCPREMOTEHOST . ++.TP ++.B \-H ++Do not look up the remote host name. ++.TP ++.B \-l\fIlocalname ++Do not look up the local host name; ++use ++.I localname ++for ++.BR TCPLOCALHOST . ++.TP ++.B \-r ++(Default.) ++Attempt to obtain ++.B TCPREMOTEINFO ++from the remote host. ++.TP ++.B \-R ++Do not attempt to obtain ++.B TCPREMOTEINFO ++from the remote host. ++.TP ++.B \-t\fItimeout ++Give up on the ++.B TCPREMOTEINFO ++connection attempt ++after ++.I timeout ++seconds. Default: 26. ++.SH "SEE ALSO" ++argv0(1), ++fixcr(1), ++recordio(1), ++tcpclient(1), ++tcprules(1), ++listen(2), ++tcp-environ(5) +diff -uNr ucspi-tcp-0.88.orig/tcpserver.c ucspi-tcp-0.88/tcpserver.c +--- ucspi-tcp-0.88.orig/tcpserver.c 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/tcpserver.c 2009-08-04 17:45:59.000000000 -0500 +@@ -7,6 +7,7 @@ + #include "fmt.h" + #include "scan.h" + #include "ip4.h" ++#include "ip6.h" + #include "fd.h" + #include "exit.h" + #include "env.h" +@@ -28,6 +29,7 @@ + #include "sig.h" + #include "dns.h" + ++int forcev6 = 0; + int verbosity = 1; + int flagkillopts = 1; + int flagdelay = 1; +@@ -36,20 +38,21 @@ + int flagremotehost = 1; + int flagparanoid = 0; + unsigned long timeout = 26; ++uint32 netif = 0; + + static stralloc tcpremoteinfo; + + uint16 localport; + char localportstr[FMT_ULONG]; +-char localip[4]; +-char localipstr[IP4_FMT]; ++char localip[16]; ++char localipstr[IP6_FMT]; + static stralloc localhostsa; + char *localhost = 0; + + uint16 remoteport; + char remoteportstr[FMT_ULONG]; +-char remoteip[4]; +-char remoteipstr[IP4_FMT]; ++char remoteip[16]; ++char remoteipstr[IP6_FMT]; + static stralloc remotehostsa; + char *remotehost = 0; + +@@ -96,12 +99,12 @@ + if (ch < 33) ch = '?'; + if (ch > 126) ch = '?'; + if (ch == '%') ch = '?'; /* logger stupidity */ +- if (ch == ':') ch = '?'; ++/* if (ch == ':') ch = '?'; */ + append(&ch); + } + cats("..."); + } +-void env(char *s,char *t) ++void env(const char *s,const char *t) + { + if (!pathexec_env(s,t)) drop_nomem(); + } +@@ -135,9 +138,16 @@ + + void doit(int t) + { ++ int fakev4=0; + int j; ++ uint32 scope_id; + +- remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0; ++ if (!forcev6 && ip6_isv4mapped(remoteip)) ++ fakev4=1; ++ if (fakev4) ++ remoteipstr[ip4_fmt(remoteipstr,remoteip+12)] = 0; ++ else ++ remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0; + + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,getpid())] = 0; +@@ -155,30 +165,40 @@ + strerr_die2sys(111,DROP,"unable to print banner: "); + } + +- if (socket_local4(t,localip,&localport) == -1) ++ if (socket_local6(t,localip,&localport,&scope_id) == -1) + strerr_die2sys(111,DROP,"unable to get local address: "); + +- localipstr[ip4_fmt(localipstr,localip)] = 0; ++ if (fakev4) ++ localipstr[ip4_fmt(localipstr,localip+12)] = 0; ++ else ++ localipstr[ip6_fmt(localipstr,localip)] = 0; + remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0; + + if (!localhost) +- if (dns_name4(&localhostsa,localip) == 0) ++ if (dns_name6(&localhostsa,localip) == 0) + if (localhostsa.len) { + if (!stralloc_0(&localhostsa)) drop_nomem(); + localhost = localhostsa.s; + } +- env("PROTO","TCP"); ++ env("PROTO",fakev4?"TCP":"TCP6"); + env("TCPLOCALIP",localipstr); ++ localipstr[ip6_fmt(localipstr,localip)]=0; ++ env("TCP6LOCALIP",localipstr); ++ + env("TCPLOCALPORT",localportstr); ++ env("TCP6LOCALPORT",localportstr); + env("TCPLOCALHOST",localhost); ++ env("TCP6LOCALHOST",localhost); ++ if (!fakev4 && scope_id) ++ env("TCP6INTERFACE",socket_getifname(scope_id)); + + if (flagremotehost) +- if (dns_name4(&remotehostsa,remoteip) == 0) ++ if (dns_name6(&remotehostsa,remoteip) == 0) + if (remotehostsa.len) { + if (flagparanoid) +- if (dns_ip4(&tmp,&remotehostsa) == 0) +- for (j = 0;j + 4 <= tmp.len;j += 4) +- if (byte_equal(remoteip,4,tmp.s + j)) { ++ if (dns_ip6(&tmp,&remotehostsa) == 0) ++ for (j = 0;j + 16 <= tmp.len;j += 16) ++ if (byte_equal(remoteip,16,tmp.s + j)) { + flagparanoid = 0; + break; + } +@@ -188,15 +208,20 @@ + } + } + env("TCPREMOTEIP",remoteipstr); ++ remoteipstr[ip6_fmt(remoteipstr,remoteip)]=0; ++ env("TCP6REMOTEIP",remoteipstr); + env("TCPREMOTEPORT",remoteportstr); ++ env("TCP6REMOTEPORT",remoteportstr); + env("TCPREMOTEHOST",remotehost); ++ env("TCP6REMOTEHOST",remotehost); + + if (flagremoteinfo) { +- if (remoteinfo(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout) == -1) ++ if (remoteinfo6(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout,netif) == -1) + flagremoteinfo = 0; + if (!stralloc_0(&tcpremoteinfo)) drop_nomem(); + } + env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); ++ env("TCP6REMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); + + if (fnrules) { + int fdrules; +@@ -206,7 +231,15 @@ + if (!flagallownorules) drop_rules(); + } + else { +- if (rules(found,fdrules,remoteipstr,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) drop_rules(); ++ int fakev4=0; ++ char* temp; ++ if (!forcev6 && ip6_isv4mapped(remoteip)) ++ fakev4=1; ++ if (fakev4) ++ temp=remoteipstr+7; ++ else ++ temp=remoteipstr; ++ if (rules(found,fdrules,temp,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) drop_rules(); + close(fdrules); + } + } +@@ -240,7 +273,7 @@ + { + strerr_warn1("\ + tcpserver: usage: tcpserver \ +-[ -1UXpPhHrRoOdDqQv ] \ ++[ -461UXpPhHrRoOdDqQv ] \ + [ -c limit ] \ + [ -x rules.cdb ] \ + [ -B banner ] \ +@@ -249,6 +282,7 @@ + [ -b backlog ] \ + [ -l localname ] \ + [ -t timeout ] \ ++[ -I interface ] \ + host port program",0); + _exit(100); + } +@@ -299,8 +333,8 @@ + unsigned long u; + int s; + int t; +- +- while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:pPoO")) != opteof) ++ ++ while ((opt = getopt(argc,argv,"46dDvqQhHrR1UXx:t:u:g:l:b:B:c:I:pPoO")) != opteof) + switch(opt) { + case 'b': scan_ulong(optarg,&backlog); break; + case 'c': scan_ulong(optarg,&limit); break; +@@ -325,7 +359,10 @@ + x = env_get("GID"); if (x) scan_ulong(x,&gid); break; + case 'u': scan_ulong(optarg,&uid); break; + case 'g': scan_ulong(optarg,&gid); break; ++ case 'I': netif=socket_getifidx(optarg); break; + case '1': flag1 = 1; break; ++ case '4': noipv6 = 1; break; ++ case '6': forcev6 = 1; break; + case 'l': localhost = optarg; break; + default: usage(); + } +@@ -337,8 +374,7 @@ + + hostname = *argv++; + if (!hostname) usage(); +- if (str_equal(hostname,"")) hostname = "0.0.0.0"; +- if (str_equal(hostname,"0")) hostname = "0.0.0.0"; ++ if (str_equal(hostname,"")) hostname = "0"; + + x = *argv++; + if (!x) usage(); +@@ -348,7 +384,7 @@ + se = getservbyname(x,"tcp"); + if (!se) + strerr_die3x(111,FATAL,"unable to figure out port number for ",x); +- localport = ntohs(se->s_port); ++ uint16_unpack_big((char*)&se->s_port,&localport); + } + + if (!*argv) usage(); +@@ -358,20 +394,26 @@ + sig_catch(sig_term,sigterm); + sig_ignore(sig_pipe); + +- if (!stralloc_copys(&tmp,hostname)) +- strerr_die2x(111,FATAL,"out of memory"); +- if (dns_ip4_qualify(&addresses,&fqdn,&tmp) == -1) +- strerr_die4sys(111,FATAL,"temporarily unable to figure out IP address for ",hostname,": "); +- if (addresses.len < 4) +- strerr_die3x(111,FATAL,"no IP address for ",hostname); +- byte_copy(localip,4,addresses.s); ++ if (str_equal(hostname,"0")) { ++ byte_zero(localip,sizeof localip); ++ } else { ++ if (!stralloc_copys(&tmp,hostname)) ++ strerr_die2x(111,FATAL,"out of memory"); ++ if (dns_ip6_qualify(&addresses,&fqdn,&tmp) == -1) ++ strerr_die4sys(111,FATAL,"temporarily unable to figure out IP address for ",hostname,": "); ++ if (addresses.len < 16) ++ strerr_die3x(111,FATAL,"no IP address for ",hostname); ++ byte_copy(localip,16,addresses.s); ++ if (ip6_isv4mapped(localip)) ++ noipv6=1; ++ } + +- s = socket_tcp(); ++ s = socket_tcp6(); + if (s == -1) + strerr_die2sys(111,FATAL,"unable to create socket: "); +- if (socket_bind4_reuse(s,localip,localport) == -1) ++ if (socket_bind6_reuse(s,localip,localport,netif) == -1) + strerr_die2sys(111,FATAL,"unable to bind: "); +- if (socket_local4(s,localip,&localport) == -1) ++ if (socket_local6(s,localip,&localport,&netif) == -1) + strerr_die2sys(111,FATAL,"unable to get local address: "); + if (socket_listen(s,backlog) == -1) + strerr_die2sys(111,FATAL,"unable to listen: "); +@@ -399,7 +441,7 @@ + while (numchildren >= limit) sig_pause(); + + sig_unblock(sig_child); +- t = socket_accept4(s,remoteip,&remoteport); ++ t = socket_accept6(s,remoteip,&remoteport,&netif); + sig_block(sig_child); + + if (t == -1) continue; +diff -uNr ucspi-tcp-0.88.orig/timeoutconn.h ucspi-tcp-0.88/timeoutconn.h +--- ucspi-tcp-0.88.orig/timeoutconn.h 2009-08-04 15:19:16.000000000 -0500 ++++ ucspi-tcp-0.88/timeoutconn.h 2009-08-04 17:45:59.000000000 -0500 +@@ -2,7 +2,9 @@ + #define TIMEOUTCONN_H + + #include "uint16.h" ++#include "uint32.h" + + extern int timeoutconn(int,char *,uint16,unsigned int); ++extern int timeoutconn6(int,char *,uint16,unsigned int,uint32); + + #endif +diff -uNr ucspi-tcp-0.88.orig/timeoutconn6.c ucspi-tcp-0.88/timeoutconn6.c +--- ucspi-tcp-0.88.orig/timeoutconn6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/timeoutconn6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,34 @@ ++#include "ndelay.h" ++#include "socket.h" ++#include "iopause.h" ++#include "error.h" ++#include "timeoutconn.h" ++ ++int timeoutconn6(int s,char ip[16],uint16 port,unsigned int timeout,uint32 netif) ++{ ++ struct taia now; ++ struct taia deadline; ++ iopause_fd x; ++ ++ if (socket_connect6(s,ip,port,netif) == -1) { ++ if ((errno != error_wouldblock) && (errno != error_inprogress)) 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; ++ if (taia_less(&deadline,&now)) { ++ errno = error_timeout; /* note that connect attempt is continuing */ ++ return -1; ++ } ++ } ++ if (!socket_connected(s)) return -1; ++ } ++ ++ if (ndelay_off(s) == -1) return -1; ++ return 0; ++} +diff -uNr ucspi-tcp-0.88.orig/tryip6.c ucspi-tcp-0.88/tryip6.c +--- ucspi-tcp-0.88.orig/tryip6.c 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/tryip6.c 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,8 @@ ++#include ++#include ++#include ++ ++main() { ++ struct sockaddr_in6 sa; ++ sa.sin6_family = PF_INET6; ++} +diff -uNr ucspi-tcp-0.88.orig/usr/local/man/man1/tcpclient.1 ucspi-tcp-0.88/usr/local/man/man1/tcpclient.1 +--- ucspi-tcp-0.88.orig/usr/local/man/man1/tcpclient.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/usr/local/man/man1/tcpclient.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,173 @@ ++.TH tcpclient 1 ++.SH NAME ++tcpclient \- create an outgoing TCP connection ++.SH SYNOPSIS ++.B tcpclient ++[ ++.B \-46hHrRdDqQv ++] ++[ ++.B \-i\fIlocalip ++] ++[ ++.B \-p\fIlocalport ++] ++[ ++.B \-T\fItimeoutconn ++] ++[ ++.B \-l\fIlocalname ++] ++[ ++.B \-t\fItimeoutinfo ++] ++[ ++.B \-I\fIinterface ++] ++.I host ++.I port ++.I program ++[ ++.I arg ... ++] ++.SH DESCRIPTION ++.B tcpclient ++attempts to connect to a TCP server. ++If it is successful, it runs ++.I program ++with the given arguments, ++with descriptor 6 reading from the network ++and descriptor 7 writing to the network. ++ ++The server's address is given by ++.I host ++and ++.IR port . ++.I host ++may be 0, referring to the local machine, ++or a dotted-decimal IP address, ++or a host name; ++if a host has several IP addresses, ++.B tcpclient ++tries each in turn. ++.I port ++may be a numeric port number ++or a port name. ++ ++.B tcpclient ++sets up several environment variables, ++as described in ++.B tcp-environ(5). ++.SH OPTIONS ++.TP ++.B \-i\fIlocalip ++Use ++.I localip ++as the IP address for the local side of the connection; ++quit if ++.I localip ++is not available. ++.TP ++.B \-p\fIlocalport ++Use ++.I localport ++as the port number for the local side of the connection; ++quit if ++.I localport ++is not available. ++.TP ++.B \-I\fIinterface ++Use ++.I interface ++as the local network interface. This is only defined for IPv6 sockets ++and needed if you use link-local IPv6 addresses. ++.TP ++.B \-T\fItimeoutconn ++Give up on the ++connection attempt ++after ++.I timeoutconn ++seconds. Default: 60. ++This timeout applies to each IP address tried. ++.TP ++.B \-d ++(Default.) ++Delay sending data for a fraction of a second whenever the ++remote host is responding slowly, ++to make better use of the network. ++.TP ++.B \-D ++Never delay sending data; ++enable TCP_NODELAY. ++This is appropriate for interactive connections. ++.TP ++.B \-q ++Quiet. ++Do not print any messages. ++.TP ++.B \-Q ++(Default.) ++Print error messages. ++.TP ++.B \-v ++Verbose. ++Print all available messages. ++.SH "DATA-GATHERING OPTIONS" ++.TP ++.B \-h ++(Default.) ++Look up the remote host name for ++.BR TCPREMOTEHOST . ++.TP ++.B \-H ++Do not look up the remote host name; ++unset ++.BR TCPREMOTEHOST . ++.TP ++.B \-l\fIlocalname ++Do not look up the local host name; ++use ++.I localname ++for ++.BR TCPLOCALHOST . ++.TP ++.B \-r ++(Default.) ++Attempt to obtain ++.B TCPREMOTEINFO ++from the remote host. ++.TP ++.B \-R ++Do not attempt to obtain ++.B TCPREMOTEINFO ++from the remote host. ++.TP ++.B \-t\fItimeoutinfo ++Give up on the ++.B TCPREMOTEINFO ++connection attempt ++after ++.I timeoutinfo ++seconds. Default: 26. ++.TP ++.B \-4 ++Fall back to IPv4 sockets. This is necessary for terminally broken ++systems like OpenBSD which will not let IPv6 sockets connect to ++V4-mapped IPv6 addresses. Please note that this also applies to DNS ++lookups, so you will have to use an DNS resolver with an IPv6 address to ++connect to IPv6 systems. Use \fBDNSCACHEIP\fR to set the DNS resolver ++IP dynamically. ++.TP ++.B \-6 ++Force IPv6 mode in UCSPI environment variables, even for ++IPv4 connections. This will set \fB$PROTO\fR to \fBTCP6\fR and put ++IPv4-mapped IPv6 addresses in \fBTCPLOCALIP\fR and \fBTCPREMOTEIP\fR. ++.SH "SEE ALSO" ++date@(1), ++finger@(1), ++http@(1), ++mconnect(1), ++tcpcat(1), ++tcpserver(1), ++who@(1), ++tcp-environ(5) +diff -uNr ucspi-tcp-0.88.orig/usr/local/man/man1/tcpserver.1 ucspi-tcp-0.88/usr/local/man/man1/tcpserver.1 +--- ucspi-tcp-0.88.orig/usr/local/man/man1/tcpserver.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/usr/local/man/man1/tcpserver.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,266 @@ ++.TH tcpserver 1 ++.SH NAME ++tcpserver \- accept incoming TCP connections ++.SH SYNOPSIS ++.B tcpserver ++[ ++.B \-146jpPhHrRoOdDqQv ++] ++[ ++.B \-c\fIlimit ++] ++[ ++.B \-x\fIrules.cdb ++] ++[ ++.B \-B\fIbanner ++] ++[ ++.B \-g\fIgid ++] ++[ ++.B \-u\fIuid ++] ++[ ++.B \-b\fIbacklog ++] ++[ ++.B \-l\fIlocalname ++] ++[ ++.B \-t\fItimeout ++] ++[ ++.B \-I\fIinterface ++] ++.I host ++.I port ++.I program ++[ ++.I arg ... ++] ++.SH DESCRIPTION ++.B tcpserver ++waits for connections from TCP clients. ++For each connection, it runs ++.I program ++with the given arguments, ++with descriptor 0 reading from the network ++and descriptor 1 writing to the network. ++ ++The server's address is given by ++.I host ++and ++.IR port . ++.I host ++can be 0, allowing connections from any host; ++or a particular IP address, ++allowing connections only to that address; ++or a host name, allowing connections to the first IP address ++for that host. ++.I port ++may be a numeric port number ++or a port name. ++If ++.I port ++is 0, ++.B tcpserver ++will choose a free port. ++ ++.B tcpserver ++sets up several environment variables, ++as described in ++.B tcp-environ(5). ++ ++.B tcpserver ++exits when it receives SIGTERM. ++.SH "OPTIONS" ++.TP ++.B \-c\fIlimit ++Do not handle more than ++.I limit ++simultaneous connections. ++If there are ++.I limit ++simultaneous copies of ++.I program ++running, defer acceptance of a new connection ++until one copy finishes. ++.I limit ++must be a positive integer. ++Default: 40. ++.TP ++.B \-x\fIrules.cdb ++Follow the rules compiled into ++.I rules.cdb ++by ++.BR tcprules . ++These rules may specify setting environment variables ++or rejecting connections from bad sources. ++ ++.B tcpserver ++does not read ++.I rules.cdb ++into memory; ++you can rerun ++.B tcprules ++to change ++.BR tcpserver 's ++behavior on the fly. ++.TP ++.B \-B\fIbanner ++Write ++.I banner ++to the network immediately after each connection is made. ++.B tcpserver ++writes ++.I banner ++before looking up ++.BR TCPREMOTEHOST , ++before looking up ++.BR TCPREMOTEINFO , ++and before checking ++.IR rules.cdb . ++ ++This feature can be used to reduce latency in protocols ++where the client waits for a greeting from the server. ++.TP ++.B \-g\fIgid ++Switch group ID to ++.I gid ++after preparing to receive connections. ++.I gid ++must be a positive integer. ++.TP ++.B \-u\fIuid ++Switch user ID to ++.I uid ++after preparing to receive connections. ++.I uid ++must be a positive integer. ++.TP ++.B \-1 ++After preparing to receive connections, ++print the local port number to standard output. ++.TP ++.B \-4 ++Fall back to IPv4 sockets. This is necessary for terminally broken ++systems like OpenBSD which will not let IPv6 sockets connect to ++V4-mapped IPv6 addresses. Please note that this also applies to DNS ++lookups, so you will have to use an DNS resolver with an IPv6 address to ++accept IPv6 connections. Use \fBDNSCACHEIP\fR to set the DNS resolver ++IP dynamically. ++.TP ++.B \-6 ++Force IPv6 mode in UCSPI environment variables, even for ++IPv4 connections. This will set \fB$PROTO\fR to \fBTCP6\fR and put ++IPv4-mapped IPv6 addresses in \fBTCPLOCALIP\fR and \fBTCPREMOTEIP\fR. ++.TP ++.B \-I\fIinterface ++Bind to the network interface ++.I interface ++("eth0" on Linux, for example). This is only defined and needed for ++IPv6 link-local addresses. ++.TP ++.B \-b\fIbacklog ++Allow up to ++.I backlog ++simultaneous SYN_RECEIVEDs. ++Default: 20. ++On some systems, ++.I backlog ++is silently limited to 5. ++See ++.BR listen (2) ++for more details. ++.TP ++.B \-o ++Leave IP options alone. ++If the client is sending packets along an IP source route, ++send packets back along the same route. ++.TP ++.B \-O ++(Default.) ++Kill IP options. ++A client can still use source routing to connect and to send data, ++but packets will be sent back along the default route. ++.TP ++.B \-d ++(Default.) ++Delay sending data for a fraction of a second whenever the ++remote host is responding slowly, ++to make better use of the network. ++.TP ++.B \-D ++Never delay sending data; ++enable TCP_NODELAY. ++This is appropriate for interactive connections. ++.TP ++.B \-q ++Quiet. ++Do not print any messages. ++.TP ++.B \-Q ++(Default.) ++Print error messages. ++.TP ++.B \-v ++Verbose. ++Print all available messages. ++.SH "DATA-GATHERING OPTIONS" ++.TP ++.B \-p ++Paranoid. ++After looking up the remote host name, ++look up the IP addresses for that name, ++and make sure one of them matches ++.BR TCPREMOTEIP . ++If none of them do, ++unset ++.BR TCPREMOTEHOST . ++.TP ++.B \-P ++(Default.) ++Not paranoid. ++.TP ++.B \-h ++(Default.) ++Look up the remote host name and set ++.BR TCPREMOTEHOST . ++.TP ++.B \-H ++Do not look up the remote host name. ++.TP ++.B \-l\fIlocalname ++Do not look up the local host name; ++use ++.I localname ++for ++.BR TCPLOCALHOST . ++.TP ++.B \-r ++(Default.) ++Attempt to obtain ++.B TCPREMOTEINFO ++from the remote host. ++.TP ++.B \-R ++Do not attempt to obtain ++.B TCPREMOTEINFO ++from the remote host. ++.TP ++.B \-t\fItimeout ++Give up on the ++.B TCPREMOTEINFO ++connection attempt ++after ++.I timeout ++seconds. Default: 26. ++.SH "SEE ALSO" ++argv0(1), ++fixcr(1), ++recordio(1), ++tcpclient(1), ++tcprules(1), ++listen(2), ++tcp-environ(5) +diff -uNr ucspi-tcp-0.88.orig/who@.1 ucspi-tcp-0.88/who@.1 +--- ucspi-tcp-0.88.orig/who@.1 1969-12-31 18:00:00.000000000 -0600 ++++ ucspi-tcp-0.88/who@.1 2009-08-04 17:45:59.000000000 -0500 +@@ -0,0 +1,32 @@ ++.TH who@ 1 ++.SH NAME ++who@ \- print list of active users on a host ++.SH SYNTAX ++.B who@ ++[ ++.I host ++] ++.SH DESCRIPTION ++.B who@ ++connects to TCP port 11 (Systat) on ++.I host ++and prints any data it receives. ++It removes CR and converts unprintable characters to a visible format. ++ ++If ++.I host ++is not supplied, ++.B who@ ++connects to the local host. ++ ++Some computers respond to port 11 with a list of active users. ++For example, they may be running ++ ++.EX ++ tcpserver 0 11 who & ++.EE ++.SH "SEE ALSO" ++cat(1), ++delcr(1), ++tcpclient(1), ++tcpserver(1)