aboutsummaryrefslogtreecommitdiff
path: root/src/op
diff options
context:
space:
mode:
Diffstat (limited to 'src/op')
-rw-r--r--src/op/Makefile285
-rw-r--r--src/op/args.c121
-rw-r--r--src/op/args.h41
-rw-r--r--src/op/auth.c85
-rw-r--r--src/op/auth.h23
-rw-r--r--src/op/buffers.c146
-rw-r--r--src/op/buffers.h25
-rw-r--r--src/op/config.c49
-rw-r--r--src/op/config.h30
-rw-r--r--src/op/crypto.c104
-rw-r--r--src/op/crypto.h23
-rw-r--r--src/op/op.c916
-rw-r--r--src/op/op.h54
-rw-r--r--src/op/routers.c364
-rw-r--r--src/op/routers.h66
-rw-r--r--src/op/ss.c194
-rw-r--r--src/op/ss.h22
17 files changed, 2548 insertions, 0 deletions
diff --git a/src/op/Makefile b/src/op/Makefile
new file mode 100644
index 000000000..d1732f99e
--- /dev/null
+++ b/src/op/Makefile
@@ -0,0 +1,285 @@
+SRC=args.c config.c op.c routers.c auth.c ss.c buffers.c crypto.c
+OBJ=${SRC:.c=.o}
+PROGS=op
+LIB=-L/usr/local/ssl/lib
+LIBS=-lcrypto
+INCLUDE = -I/usr/local/ssl/include
+
+CFLAGS= $(INCLUDE) -Wall -Wpointer-arith -O2 -ggdb
+LDFLAGS = $(LIB) $(LIBS)
+
+all: ${PROGS}
+
+clean:
+ rm -f *.o ${PROGS}
+
+depend:
+ makedepend -- ${CFLAGS} -- ${SRC}
+
+${PROGS}: ${OBJ}
+ $(LINK.c) -o $@ $(OBJ) ../common/log.o ../common/config.o ../common/onion.o ../common/utils.o ../common/cell.o ../common/scheduler.o
+
+# DO NOT DELETE
+
+
+args.o: args.h ../common/log.h /usr/include/alloca.h
+args.o: /usr/include/bits/confname.h /usr/include/bits/endian.h
+args.o: /usr/include/bits/environments.h /usr/include/bits/posix_opt.h
+args.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h
+args.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+args.o: /usr/include/bits/stdio_lim.h /usr/include/bits/time.h
+args.o: /usr/include/bits/types.h /usr/include/bits/waitflags.h
+args.o: /usr/include/bits/waitstatus.h /usr/include/bits/wchar.h
+args.o: /usr/include/bits/wordsize.h /usr/include/ctype.h
+args.o: /usr/include/endian.h /usr/include/features.h /usr/include/_G_config.h
+args.o: /usr/include/gconv.h /usr/include/getopt.h /usr/include/gnu/stubs.h
+args.o: /usr/include/libio.h /usr/include/stdio.h /usr/include/stdlib.h
+args.o: /usr/include/sys/cdefs.h /usr/include/syslog.h
+args.o: /usr/include/sys/select.h /usr/include/sys/syslog.h
+args.o: /usr/include/sys/sysmacros.h /usr/include/sys/types.h
+args.o: /usr/include/time.h /usr/include/unistd.h /usr/include/wchar.h
+args.o: /usr/include/xlocale.h
+args.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h
+args.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h
+auth.o: auth.h ../common/log.h /usr/include/alloca.h /usr/include/asm/socket.h
+auth.o: /usr/include/asm/sockios.h /usr/include/bits/byteswap.h
+auth.o: /usr/include/bits/confname.h /usr/include/bits/endian.h
+auth.o: /usr/include/bits/environments.h /usr/include/bits/in.h
+auth.o: /usr/include/bits/local_lim.h /usr/include/bits/posix1_lim.h
+auth.o: /usr/include/bits/posix2_lim.h /usr/include/bits/posix_opt.h
+auth.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h
+auth.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+auth.o: /usr/include/bits/sockaddr.h /usr/include/bits/socket.h
+auth.o: /usr/include/bits/stdio_lim.h /usr/include/bits/time.h
+auth.o: /usr/include/bits/types.h /usr/include/bits/uio.h
+auth.o: /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h
+auth.o: /usr/include/bits/wchar.h /usr/include/bits/wordsize.h
+auth.o: /usr/include/bits/xopen_lim.h /usr/include/endian.h
+auth.o: /usr/include/features.h /usr/include/_G_config.h /usr/include/gconv.h
+auth.o: /usr/include/getopt.h /usr/include/gnu/stubs.h /usr/include/libio.h
+auth.o: /usr/include/limits.h /usr/include/linux/limits.h
+auth.o: /usr/include/netinet/in.h /usr/include/openssl/bio.h
+auth.o: /usr/include/openssl/bn.h /usr/include/openssl/crypto.h
+auth.o: /usr/include/openssl/opensslconf.h /usr/include/openssl/opensslv.h
+auth.o: /usr/include/openssl/rand.h /usr/include/openssl/rsa.h
+auth.o: /usr/include/openssl/safestack.h /usr/include/openssl/stack.h
+auth.o: /usr/include/openssl/symhacks.h /usr/include/stdint.h
+auth.o: /usr/include/stdio.h /usr/include/stdlib.h /usr/include/string.h
+auth.o: /usr/include/sys/cdefs.h /usr/include/syslog.h
+auth.o: /usr/include/sys/select.h /usr/include/sys/socket.h
+auth.o: /usr/include/sys/syslog.h /usr/include/sys/sysmacros.h
+auth.o: /usr/include/sys/types.h /usr/include/sys/uio.h /usr/include/time.h
+auth.o: /usr/include/unistd.h /usr/include/wchar.h /usr/include/xlocale.h
+auth.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/limits.h
+auth.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h
+auth.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h
+auth.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/syslimits.h
+buffers.o: buffers.h ../common/cell.h ../common/log.h ../common/onion.h
+buffers.o: ../common/routent.h ../common/version.h crypto.h op.h
+buffers.o: /usr/include/alloca.h /usr/include/bits/confname.h
+buffers.o: /usr/include/bits/endian.h /usr/include/bits/environments.h
+buffers.o: /usr/include/bits/posix_opt.h /usr/include/bits/pthreadtypes.h
+buffers.o: /usr/include/bits/sched.h /usr/include/bits/select.h
+buffers.o: /usr/include/bits/sigset.h /usr/include/bits/stdio_lim.h
+buffers.o: /usr/include/bits/time.h /usr/include/bits/types.h
+buffers.o: /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h
+buffers.o: /usr/include/bits/wchar.h /usr/include/bits/wordsize.h
+buffers.o: /usr/include/endian.h /usr/include/features.h
+buffers.o: /usr/include/_G_config.h /usr/include/gconv.h /usr/include/getopt.h
+buffers.o: /usr/include/gnu/stubs.h /usr/include/libio.h
+buffers.o: /usr/include/openssl/asn1.h /usr/include/openssl/bio.h
+buffers.o: /usr/include/openssl/blowfish.h /usr/include/openssl/bn.h
+buffers.o: /usr/include/openssl/cast.h /usr/include/openssl/crypto.h
+buffers.o: /usr/include/openssl/des.h /usr/include/openssl/dh.h
+buffers.o: /usr/include/openssl/dsa.h /usr/include/openssl/e_os2.h
+buffers.o: /usr/include/openssl/evp.h /usr/include/openssl/md2.h
+buffers.o: /usr/include/openssl/md4.h /usr/include/openssl/md5.h
+buffers.o: /usr/include/openssl/objects.h /usr/include/openssl/obj_mac.h
+buffers.o: /usr/include/openssl/opensslconf.h /usr/include/openssl/opensslv.h
+buffers.o: /usr/include/openssl/rc2.h /usr/include/openssl/rc4.h
+buffers.o: /usr/include/openssl/ripemd.h /usr/include/openssl/rsa.h
+buffers.o: /usr/include/openssl/safestack.h /usr/include/openssl/sha.h
+buffers.o: /usr/include/openssl/stack.h /usr/include/openssl/symhacks.h
+buffers.o: /usr/include/stdint.h /usr/include/stdio.h /usr/include/stdlib.h
+buffers.o: /usr/include/sys/cdefs.h /usr/include/syslog.h
+buffers.o: /usr/include/sys/select.h /usr/include/sys/syslog.h
+buffers.o: /usr/include/sys/sysmacros.h /usr/include/sys/timeb.h
+buffers.o: /usr/include/sys/time.h /usr/include/sys/types.h
+buffers.o: /usr/include/time.h /usr/include/unistd.h /usr/include/wchar.h
+buffers.o: /usr/include/xlocale.h
+buffers.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h
+buffers.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h
+config.o: ../common/config.h ../common/log.h config.h
+config.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h
+config.o: /usr/include/bits/stdio_lim.h /usr/include/bits/types.h
+config.o: /usr/include/bits/wchar.h /usr/include/features.h
+config.o: /usr/include/_G_config.h /usr/include/gconv.h
+config.o: /usr/include/gnu/stubs.h /usr/include/libio.h /usr/include/stdio.h
+config.o: /usr/include/sys/cdefs.h /usr/include/syslog.h
+config.o: /usr/include/sys/syslog.h /usr/include/wchar.h
+config.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h
+config.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h
+crypto.o: ../common/cell.h ../common/log.h ../common/onion.h
+crypto.o: ../common/routent.h ../common/version.h crypto.h
+crypto.o: /usr/include/alloca.h /usr/include/asm/errno.h
+crypto.o: /usr/include/bits/confname.h /usr/include/bits/endian.h
+crypto.o: /usr/include/bits/environments.h /usr/include/bits/errno.h
+crypto.o: /usr/include/bits/posix_opt.h /usr/include/bits/pthreadtypes.h
+crypto.o: /usr/include/bits/sched.h /usr/include/bits/select.h
+crypto.o: /usr/include/bits/sigset.h /usr/include/bits/stdio_lim.h
+crypto.o: /usr/include/bits/time.h /usr/include/bits/types.h
+crypto.o: /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h
+crypto.o: /usr/include/bits/wchar.h /usr/include/bits/wordsize.h
+crypto.o: /usr/include/endian.h /usr/include/errno.h /usr/include/features.h
+crypto.o: /usr/include/_G_config.h /usr/include/gconv.h /usr/include/getopt.h
+crypto.o: /usr/include/gnu/stubs.h /usr/include/libio.h
+crypto.o: /usr/include/linux/errno.h /usr/include/malloc.h
+crypto.o: /usr/include/openssl/asn1.h /usr/include/openssl/bio.h
+crypto.o: /usr/include/openssl/blowfish.h /usr/include/openssl/bn.h
+crypto.o: /usr/include/openssl/cast.h /usr/include/openssl/crypto.h
+crypto.o: /usr/include/openssl/des.h /usr/include/openssl/dh.h
+crypto.o: /usr/include/openssl/dsa.h /usr/include/openssl/e_os2.h
+crypto.o: /usr/include/openssl/err.h /usr/include/openssl/evp.h
+crypto.o: /usr/include/openssl/lhash.h /usr/include/openssl/md2.h
+crypto.o: /usr/include/openssl/md4.h /usr/include/openssl/md5.h
+crypto.o: /usr/include/openssl/objects.h /usr/include/openssl/obj_mac.h
+crypto.o: /usr/include/openssl/opensslconf.h /usr/include/openssl/opensslv.h
+crypto.o: /usr/include/openssl/rc2.h /usr/include/openssl/rc4.h
+crypto.o: /usr/include/openssl/ripemd.h /usr/include/openssl/rsa.h
+crypto.o: /usr/include/openssl/safestack.h /usr/include/openssl/sha.h
+crypto.o: /usr/include/openssl/stack.h /usr/include/openssl/symhacks.h
+crypto.o: /usr/include/stdint.h /usr/include/stdio.h /usr/include/stdlib.h
+crypto.o: /usr/include/sys/cdefs.h /usr/include/syslog.h
+crypto.o: /usr/include/sys/select.h /usr/include/sys/syslog.h
+crypto.o: /usr/include/sys/sysmacros.h /usr/include/sys/timeb.h
+crypto.o: /usr/include/sys/time.h /usr/include/sys/types.h /usr/include/time.h
+crypto.o: /usr/include/unistd.h /usr/include/wchar.h /usr/include/xlocale.h
+crypto.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h
+crypto.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h
+op.o: args.h auth.h buffers.h ../common/cell.h ../common/config.h
+op.o: ../common/log.h ../common/onion.h ../common/routent.h
+op.o: ../common/scheduler.h ../common/ss.h ../common/utils.h
+op.o: ../common/version.h config.h crypto.h op.h routers.h ss.h
+op.o: /usr/include/alloca.h /usr/include/arpa/inet.h /usr/include/asm/errno.h
+op.o: /usr/include/asm/sigcontext.h /usr/include/asm/socket.h
+op.o: /usr/include/asm/sockios.h /usr/include/bits/byteswap.h
+op.o: /usr/include/bits/confname.h /usr/include/bits/endian.h
+op.o: /usr/include/bits/environments.h /usr/include/bits/errno.h
+op.o: /usr/include/bits/in.h /usr/include/bits/local_lim.h
+op.o: /usr/include/bits/netdb.h /usr/include/bits/posix1_lim.h
+op.o: /usr/include/bits/posix2_lim.h /usr/include/bits/posix_opt.h
+op.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/resource.h
+op.o: /usr/include/bits/sched.h /usr/include/bits/select.h
+op.o: /usr/include/bits/sigaction.h /usr/include/bits/sigcontext.h
+op.o: /usr/include/bits/siginfo.h /usr/include/bits/signum.h
+op.o: /usr/include/bits/sigset.h /usr/include/bits/sigstack.h
+op.o: /usr/include/bits/sigthread.h /usr/include/bits/sockaddr.h
+op.o: /usr/include/bits/socket.h /usr/include/bits/stdio_lim.h
+op.o: /usr/include/bits/time.h /usr/include/bits/types.h
+op.o: /usr/include/bits/uio.h /usr/include/bits/waitflags.h
+op.o: /usr/include/bits/waitstatus.h /usr/include/bits/wchar.h
+op.o: /usr/include/bits/wordsize.h /usr/include/bits/xopen_lim.h
+op.o: /usr/include/ctype.h /usr/include/endian.h /usr/include/errno.h
+op.o: /usr/include/features.h /usr/include/_G_config.h /usr/include/gconv.h
+op.o: /usr/include/getopt.h /usr/include/gnu/stubs.h /usr/include/libio.h
+op.o: /usr/include/limits.h /usr/include/linux/errno.h
+op.o: /usr/include/linux/limits.h /usr/include/netdb.h
+op.o: /usr/include/netinet/in.h /usr/include/openssl/asn1.h
+op.o: /usr/include/openssl/bio.h /usr/include/openssl/blowfish.h
+op.o: /usr/include/openssl/bn.h /usr/include/openssl/buffer.h
+op.o: /usr/include/openssl/cast.h /usr/include/openssl/crypto.h
+op.o: /usr/include/openssl/des.h /usr/include/openssl/dh.h
+op.o: /usr/include/openssl/dsa.h /usr/include/openssl/e_os2.h
+op.o: /usr/include/openssl/err.h /usr/include/openssl/evp.h
+op.o: /usr/include/openssl/lhash.h /usr/include/openssl/md2.h
+op.o: /usr/include/openssl/md4.h /usr/include/openssl/md5.h
+op.o: /usr/include/openssl/objects.h /usr/include/openssl/obj_mac.h
+op.o: /usr/include/openssl/opensslconf.h /usr/include/openssl/opensslv.h
+op.o: /usr/include/openssl/pem2.h /usr/include/openssl/pem.h
+op.o: /usr/include/openssl/pkcs7.h /usr/include/openssl/rand.h
+op.o: /usr/include/openssl/rc2.h /usr/include/openssl/rc4.h
+op.o: /usr/include/openssl/ripemd.h /usr/include/openssl/rsa.h
+op.o: /usr/include/openssl/safestack.h /usr/include/openssl/sha.h
+op.o: /usr/include/openssl/stack.h /usr/include/openssl/symhacks.h
+op.o: /usr/include/openssl/x509.h /usr/include/openssl/x509_vfy.h
+op.o: /usr/include/rpc/netdb.h /usr/include/signal.h /usr/include/stdint.h
+op.o: /usr/include/stdio.h /usr/include/stdlib.h /usr/include/string.h
+op.o: /usr/include/sys/cdefs.h /usr/include/syslog.h
+op.o: /usr/include/sys/resource.h /usr/include/sys/select.h
+op.o: /usr/include/sys/socket.h /usr/include/sys/syslog.h
+op.o: /usr/include/sys/sysmacros.h /usr/include/sys/timeb.h
+op.o: /usr/include/sys/time.h /usr/include/sys/types.h
+op.o: /usr/include/sys/ucontext.h /usr/include/sys/uio.h /usr/include/sys/un.h
+op.o: /usr/include/sys/wait.h /usr/include/time.h /usr/include/ucontext.h
+op.o: /usr/include/unistd.h /usr/include/wait.h /usr/include/wchar.h
+op.o: /usr/include/xlocale.h
+op.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/limits.h
+op.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h
+op.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h
+op.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/syslimits.h
+routers.o: ../common/cell.h ../common/config.h ../common/log.h
+routers.o: ../common/routent.h ../common/utils.h routers.h
+routers.o: /usr/include/alloca.h /usr/include/asm/errno.h
+routers.o: /usr/include/asm/socket.h /usr/include/asm/sockios.h
+routers.o: /usr/include/bits/byteswap.h /usr/include/bits/confname.h
+routers.o: /usr/include/bits/endian.h /usr/include/bits/environments.h
+routers.o: /usr/include/bits/errno.h /usr/include/bits/in.h
+routers.o: /usr/include/bits/local_lim.h /usr/include/bits/netdb.h
+routers.o: /usr/include/bits/posix1_lim.h /usr/include/bits/posix2_lim.h
+routers.o: /usr/include/bits/posix_opt.h /usr/include/bits/pthreadtypes.h
+routers.o: /usr/include/bits/sched.h /usr/include/bits/select.h
+routers.o: /usr/include/bits/siginfo.h /usr/include/bits/sigset.h
+routers.o: /usr/include/bits/sockaddr.h /usr/include/bits/socket.h
+routers.o: /usr/include/bits/stdio_lim.h /usr/include/bits/time.h
+routers.o: /usr/include/bits/types.h /usr/include/bits/waitflags.h
+routers.o: /usr/include/bits/waitstatus.h /usr/include/bits/wchar.h
+routers.o: /usr/include/bits/wordsize.h /usr/include/bits/xopen_lim.h
+routers.o: /usr/include/endian.h /usr/include/errno.h /usr/include/features.h
+routers.o: /usr/include/_G_config.h /usr/include/gconv.h /usr/include/getopt.h
+routers.o: /usr/include/gnu/stubs.h /usr/include/libio.h /usr/include/limits.h
+routers.o: /usr/include/linux/errno.h /usr/include/linux/limits.h
+routers.o: /usr/include/netdb.h /usr/include/netinet/in.h
+routers.o: /usr/include/openssl/asn1.h /usr/include/openssl/bio.h
+routers.o: /usr/include/openssl/blowfish.h /usr/include/openssl/bn.h
+routers.o: /usr/include/openssl/buffer.h /usr/include/openssl/cast.h
+routers.o: /usr/include/openssl/crypto.h /usr/include/openssl/des.h
+routers.o: /usr/include/openssl/dh.h /usr/include/openssl/dsa.h
+routers.o: /usr/include/openssl/e_os2.h /usr/include/openssl/err.h
+routers.o: /usr/include/openssl/evp.h /usr/include/openssl/lhash.h
+routers.o: /usr/include/openssl/md2.h /usr/include/openssl/md4.h
+routers.o: /usr/include/openssl/md5.h /usr/include/openssl/objects.h
+routers.o: /usr/include/openssl/obj_mac.h /usr/include/openssl/opensslconf.h
+routers.o: /usr/include/openssl/opensslv.h /usr/include/openssl/pem2.h
+routers.o: /usr/include/openssl/pem.h /usr/include/openssl/pkcs7.h
+routers.o: /usr/include/openssl/rc2.h /usr/include/openssl/rc4.h
+routers.o: /usr/include/openssl/ripemd.h /usr/include/openssl/rsa.h
+routers.o: /usr/include/openssl/safestack.h /usr/include/openssl/sha.h
+routers.o: /usr/include/openssl/stack.h /usr/include/openssl/symhacks.h
+routers.o: /usr/include/openssl/x509.h /usr/include/openssl/x509_vfy.h
+routers.o: /usr/include/rpc/netdb.h /usr/include/stdint.h /usr/include/stdio.h
+routers.o: /usr/include/stdlib.h /usr/include/string.h
+routers.o: /usr/include/sys/cdefs.h /usr/include/syslog.h
+routers.o: /usr/include/sys/select.h /usr/include/sys/syslog.h
+routers.o: /usr/include/sys/sysmacros.h /usr/include/sys/timeb.h
+routers.o: /usr/include/sys/time.h /usr/include/sys/types.h
+routers.o: /usr/include/sys/un.h /usr/include/time.h /usr/include/unistd.h
+routers.o: /usr/include/wchar.h /usr/include/xlocale.h
+routers.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/limits.h
+routers.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h
+routers.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h
+routers.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/syslimits.h
+ss.o: ../common/log.h ../common/ss.h ../common/utils.h ../common/version.h
+ss.o: ss.h /usr/include/bits/confname.h /usr/include/bits/endian.h
+ss.o: /usr/include/bits/environments.h /usr/include/bits/posix_opt.h
+ss.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h
+ss.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+ss.o: /usr/include/bits/sockaddr.h /usr/include/bits/time.h
+ss.o: /usr/include/bits/types.h /usr/include/bits/wordsize.h
+ss.o: /usr/include/endian.h /usr/include/features.h /usr/include/getopt.h
+ss.o: /usr/include/gnu/stubs.h /usr/include/malloc.h /usr/include/string.h
+ss.o: /usr/include/sys/cdefs.h /usr/include/syslog.h /usr/include/sys/select.h
+ss.o: /usr/include/sys/syslog.h /usr/include/sys/sysmacros.h
+ss.o: /usr/include/sys/time.h /usr/include/sys/types.h /usr/include/sys/un.h
+ss.o: /usr/include/time.h /usr/include/unistd.h /usr/include/xlocale.h
+ss.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h
+ss.o: /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h
diff --git a/src/op/args.c b/src/op/args.c
new file mode 100644
index 000000000..6e3a4600f
--- /dev/null
+++ b/src/op/args.c
@@ -0,0 +1,121 @@
+/**
+ * args.c
+ * Routines for processing command-line arguments.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.3 2002/01/26 22:08:40 mp292
+ * Reviewed according to Secure-Programs-HOWTO.
+ *
+ * Revision 1.2 2001/12/14 11:26:23 badbytes
+ * Tested
+ *
+ * Revision 1.1 2001/12/13 15:15:10 badbytes
+ * Started coding the onion proxy.
+ *
+ */
+
+#include <unistd.h>
+#include <ctype.h>
+
+#include "../common/log.h"
+#include "args.h"
+
+/* prints help on using op */
+void print_usage()
+{
+ char *program = "op";
+
+ printf("\n%s - Onion Proxy for Onion Routing.\nUsage : %s -f config -p port [-l loglevel -h]\n-h : display this help\n-f config : config file\n-p port : port number which %s should bind to\n-l loglevel : logging threshold; one of alert|crit|err|warning|notice|info|debug\n\n", program,program,program);
+}
+
+/* get command-line arguments */
+int getargs(int argc, char *argv[], char *args, unsigned short *p, char **conf_filename, int *loglevel)
+{
+ char c; /* next option character */
+ char *errtest = NULL; /* for detecting strtoul() errors */
+ int gotf=0; int gotp=0;
+
+ if ((!args) || (!conf_filename) || (!loglevel)) /* invalid parameters */
+ return -1;
+
+ while ((c = getopt(argc,argv,args)) != -1)
+ {
+ switch(c)
+ {
+ case 'f': /* config file */
+ *conf_filename = optarg;
+ gotf=1;
+ break;
+ case 'p':
+ *p = (u_short)strtoul(optarg,&errtest,0);
+ if (errtest == optarg) /* error */
+ {
+ log(LOG_ERR,"Error : -p must be followed by an unsigned positive integer value. See help (-h).");
+ return -1;
+ }
+ gotp=1;
+ break;
+ case 'h':
+ print_usage();
+ exit(0);
+ case 'l':
+ if (!strcmp(optarg,"emerg"))
+ *loglevel = LOG_EMERG;
+ else if (!strcmp(optarg,"alert"))
+ *loglevel = LOG_ALERT;
+ else if (!strcmp(optarg,"crit"))
+ *loglevel = LOG_CRIT;
+ else if (!strcmp(optarg,"err"))
+ *loglevel = LOG_ERR;
+ else if (!strcmp(optarg,"warning"))
+ *loglevel = LOG_WARNING;
+ else if (!strcmp(optarg,"notice"))
+ *loglevel = LOG_NOTICE;
+ else if (!strcmp(optarg,"info"))
+ *loglevel = LOG_INFO;
+ else if (!strcmp(optarg,"debug"))
+ *loglevel = LOG_DEBUG;
+ else
+ {
+ log(LOG_ERR,"Error : argument to -l must be one of alert|crit|err|warning|notice|info|debug.");
+ print_usage();
+ return -1;
+ }
+ break;
+ case '?':
+ if (isprint(c))
+ log(LOG_ERR,"Missing argument or unknown option '-%c'. See help (-h).",optopt);
+ else
+ log(LOG_ERR,"Unknown option character 'x%x'. See help (-h).",optopt);
+ print_usage();
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ /* the -f option is mandatory */
+ if (!gotf)
+ {
+ log(LOG_ERR,"You must specify a config file with the -f option. See help (-h).");
+ return -1;
+ }
+
+ /* the -p option is mandatory */
+ if (!gotp)
+ {
+ log(LOG_ERR,"You must specify a port with the -p option. See help (-h).");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/op/args.h b/src/op/args.h
new file mode 100644
index 000000000..0d693efab
--- /dev/null
+++ b/src/op/args.h
@@ -0,0 +1,41 @@
+/**
+ * args.h
+ * Routines for processing command-line arguments.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.4 2002/01/26 22:22:09 mp292
+ * Prevented duplicate definitions.
+ *
+ * Revision 1.3 2002/01/26 22:08:40 mp292
+ * Reviewed according to Secure-Programs-HOWTO.
+ *
+ * Revision 1.2 2001/12/14 11:26:23 badbytes
+ * Tested
+ *
+ * Revision 1.1 2001/12/13 15:15:10 badbytes
+ * Started coding the onion proxy.
+ *
+ */
+
+#ifndef __ARGS_H
+
+#define __ARGS_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/* print help */
+void print_usage();
+
+/* get command-line arguments */
+int getargs(int argc,char *argv[], char *args, unsigned short *p, char **conf_filename, int *loglevel);
+
+#endif
diff --git a/src/op/auth.c b/src/op/auth.c
new file mode 100644
index 000000000..3a3f40ce8
--- /dev/null
+++ b/src/op/auth.c
@@ -0,0 +1,85 @@
+/**
+ * auth.h
+ * Key exchange with an onion router.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.1 2002/03/28 11:00:57 badbytes
+ * Key exchange with an onion router.
+ *
+ */
+#include <openssl/rand.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "../common/log.h"
+
+#include "auth.h"
+
+/* send session keys and bandwidth info to the router */
+int send_auth(int or_sock, uint32_t bandwidth, RSA *pkey, unsigned char *f_session_key, unsigned char *b_session_key)
+{
+ int retval;
+ int x;
+ unsigned char message[20]; /* bandwidth(32bits), forward key(64bits), backward key(64bits) */
+ unsigned char cipher[128];
+ if ((or_sock <= 0) || (bandwidth <= 0) || !pkey || !f_session_key || !b_session_key) /* invalid parameters */
+ return -1;
+
+ bandwidth = htonl(bandwidth); /* convert to network order */
+
+ /* generate the session keys */
+ retval = RAND_bytes(f_session_key, 8);
+ if (!retval)
+ {
+ log(LOG_ERR,"Not enough randomness to generate a session key.");
+ return -1;
+ }
+ retval = RAND_bytes(b_session_key, 8);
+ if (!retval)
+ {
+ log(LOG_ERR,"Not enough randomness to generate a session key.");
+ return -1;
+ }
+
+ /* compose the message */
+ memcpy((void *)message, (void *)&bandwidth, 4);
+ memcpy((void *)(message + 4), (void *)f_session_key, 8);
+ memcpy((void *)(message + 12), (void *)b_session_key, 8);
+ printf("f_session_key: ");
+ for(x=0;x<8;x++) {
+ printf("%d ",f_session_key[x]);
+ }
+ printf("\nb_session_key: ");
+ for(x=0;x<8;x++) {
+ printf("%d ",b_session_key[x]);
+ }
+ printf("\n");
+
+ /* encrypt with RSA */
+ retval = RSA_public_encrypt(20, message, cipher, pkey, RSA_PKCS1_PADDING);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Public key encryption failed.");
+ return -1;
+ }
+
+ /* send the ciphertext */
+ retval = send(or_sock, cipher, 128, 0);
+ if (retval < 128)
+ {
+ log(LOG_ERR,"Connection to router lost while exchanging session keys.");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/op/auth.h b/src/op/auth.h
new file mode 100644
index 000000000..97be419bf
--- /dev/null
+++ b/src/op/auth.h
@@ -0,0 +1,23 @@
+/**
+ * auth.h
+ * Key exchange with an onion router.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.1 2002/03/28 11:00:57 badbytes
+ * Key exchange with an onion router.
+ *
+ */
+
+#include <openssl/rsa.h>
+#include <stdint.h>
+
+/* send session keys and bandwidth info to the router */
+int send_auth(int or_sock, uint32_t bandwidth, RSA *pkey, unsigned char *f_session_key, unsigned char *b_session_key);
diff --git a/src/op/buffers.c b/src/op/buffers.c
new file mode 100644
index 000000000..39a4e442d
--- /dev/null
+++ b/src/op/buffers.c
@@ -0,0 +1,146 @@
+/**
+ * buffers.c
+ * Buffers.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.1 2002/04/02 14:28:01 badbytes
+ * Final finishes.
+ *
+ */
+
+
+#include <unistd.h>
+#include <openssl/evp.h>
+
+#include "../common/cell.h"
+#include "../common/log.h"
+
+#include "buffers.h"
+#include "crypto.h"
+#include "op.h"
+
+int buffer_data(uint16_t aci, unsigned char *buf, size_t buflen, unsigned char **outbuf, size_t *outbuflen, size_t *outbuf_dataoffset, size_t *outbuf_datalen, crypt_path_t **cpath, size_t cpathlen)
+{
+ int retval;
+ int i;
+ cell_t *cellbuf;
+ cell_t *c;
+ size_t cellbuflen;
+ size_t cells;
+ unsigned char *tmpbuf; /* temporary buffer for realloc() operations */
+
+ if (!buf || !outbuf || !outbuflen) /* invalid parameters */
+ return -1;
+
+ /* split the plaintext into DATA cells */
+ retval = pack_data(aci,buf, buflen, (unsigned char **)&cellbuf, &cellbuflen);
+ if (retval == -1)
+ {
+ log(LOG_DEBUG,"buffer_data() : Could not pack data into cells.");
+ return -1;
+ }
+ log(LOG_DEBUG,"buffer_data() : DATA cells created.");
+
+ cells = cellbuflen/(sizeof(cell_t));
+ /* encrypt the cells */
+ for (i=0; i<cells; i++)
+ {
+ c = cellbuf+i;
+ /* encrypt the payload length */
+ retval = crypt_f((unsigned char *)&c->length, 1, cpath, cpathlen);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Could not encrypt the payload length of a DATA cell.");
+ free((void *)cellbuf);
+ return -1;
+ }
+ /* encrypt the payload */
+ retval = crypt_f((unsigned char *)c->payload, CELL_PAYLOAD_SIZE, cpath, cpathlen);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Could not encrypt the payload of a DATA cell.");
+ free((void *)cellbuf);
+ return -1;
+ }
+ }
+
+ /* now copy the cells into the output buffer */
+ if (*outbuflen-*outbuf_dataoffset-*outbuf_datalen < cellbuflen) /* increase the buffer size if necessary */
+ {
+ /* allocate a new buffer (in OP_DEFAULT_BUFSIZE chunks)*/
+ tmpbuf = (unsigned char *)malloc(((cellbuflen+*outbuf_datalen)/OP_DEFAULT_BUFSIZE+1)*OP_DEFAULT_BUFSIZE);
+ if (!tmpbuf)
+ {
+ log(LOG_ERR,"Error allocating memory.");
+ free((void *)cellbuf);
+ return -1;
+ }
+ /* copy old data to the new buffer */
+ memcpy((void *)tmpbuf,(void *)(*outbuf+*outbuf_dataoffset),*outbuf_datalen);
+ /* replace the old buffer with the new one */
+ if (*outbuf)
+ free((void *)*outbuf);
+ *outbuf = tmpbuf;
+ *outbuflen = ((cellbuflen+*outbuf_datalen)/OP_DEFAULT_BUFSIZE+1) * OP_DEFAULT_BUFSIZE;
+ *outbuf_dataoffset = 0;
+ }
+ memcpy((void *)(*outbuf + *outbuf_dataoffset + *outbuf_datalen), (void *)cellbuf, cellbuflen);
+ *outbuf_datalen += cellbuflen;
+
+ return 0;
+}
+
+int buffer_create(uint16_t aci, unsigned char *onion, size_t onionlen, unsigned char **outbuf, size_t *outbuflen, size_t *outbuf_dataoffset, size_t *outbuf_datalen, crypt_path_t **cpath, size_t cpathlen)
+{
+ int retval;
+ cell_t *cellbuf;
+ size_t cells;
+ size_t cellbuflen;
+ unsigned char *tmpbuf; /* temporary buffer for realloc() operations */
+
+ if (!onion || !outbuf || !outbuflen || !outbuf_dataoffset || !outbuf_datalen) /* invalid parameters */
+ return -1;
+
+ retval = pack_create(aci,onion, onionlen, (unsigned char **)&cellbuf, &cellbuflen);
+ if (retval == -1)
+ {
+ log(LOG_DEBUG,"buffer_create() : Could not pack the onion into cells.");
+ return -1;
+ }
+ log(LOG_DEBUG,"buffer_create() : CREATE cells created.");
+
+ cells = cellbuflen/(sizeof(cell_t));
+
+ /* now copy the cells into the output buffer */
+ if (*outbuflen-*outbuf_dataoffset-*outbuf_datalen < cellbuflen) /* increase the buffer size if necessary */
+ {
+ /* allocate a new buffer (in OP_DEFAULT_BUFSIZE chunks)*/
+ tmpbuf = (unsigned char *)malloc(((cellbuflen+*outbuf_datalen)/OP_DEFAULT_BUFSIZE+1)*OP_DEFAULT_BUFSIZE);
+ if (!tmpbuf)
+ {
+ log(LOG_ERR,"Error allocating memory.");
+ free((void *)cellbuf);
+ return -1;
+ }
+ /* copy old data to the new buffer */
+ memcpy((void *)tmpbuf,(void *)(*outbuf+*outbuf_dataoffset),*outbuf_datalen);
+ /* replace the old buffer with the new one */
+ if (*outbuf)
+ free((void *)*outbuf);
+ *outbuf = tmpbuf;
+ *outbuflen = ((cellbuflen+*outbuf_datalen)/OP_DEFAULT_BUFSIZE+1) * OP_DEFAULT_BUFSIZE;
+ *outbuf_dataoffset = 0;
+ }
+ memcpy((void *)(*outbuf + *outbuf_dataoffset + *outbuf_datalen), (void *)cellbuf, cellbuflen);
+ *outbuf_datalen += cellbuflen;
+
+ return 0;
+}
diff --git a/src/op/buffers.h b/src/op/buffers.h
new file mode 100644
index 000000000..a161e0810
--- /dev/null
+++ b/src/op/buffers.h
@@ -0,0 +1,25 @@
+/**
+ * buffers.h
+ * Buffers.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.1 2002/04/02 14:28:01 badbytes
+ * Final finishes.
+ *
+ */
+
+
+#include <stdint.h>
+
+#include "../common/onion.h"
+
+int buffer_data(uint16_t aci, unsigned char *buf, size_t buflen, unsigned char **outbuf, size_t *outbuflen, size_t *outbuf_dataoffset, size_t *outbuf_datalen, crypt_path_t **cpath, size_t cpathlen);
+int buffer_create(uint16_t aci, unsigned char *onion, size_t onionlen, unsigned char **outbuf, size_t *outbuflen, size_t *outbuf_dataoffset, size_t *outbuf_datalen, crypt_path_t **cpath, size_t cpathlen);
diff --git a/src/op/config.c b/src/op/config.c
new file mode 100644
index 000000000..33e5a394a
--- /dev/null
+++ b/src/op/config.c
@@ -0,0 +1,49 @@
+/**
+ * config.c
+ * Routines for loading the configuration file.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.3 2002/04/02 14:28:01 badbytes
+ * Final finishes.
+ *
+ * Revision 1.2 2002/01/26 22:09:53 mp292
+ * Reviewed according to Secure-Programs-HOWTO.
+ *
+ * Revision 1.1 2001/12/13 15:15:10 badbytes
+ * Started coding the onion proxy.
+ *
+ */
+
+#include "config.h"
+#include "../common/log.h"
+
+/* loads the configuration file */
+int getconfig(char *conf_filename, config_opt_t *options)
+{
+ FILE *cf = NULL;
+ int retval = 0;
+
+ if ((!conf_filename) || (!options))
+ return -1;
+
+ /* load config file */
+ cf = open_config(conf_filename);
+ if (!cf)
+ {
+ log(LOG_ERR,"Could not open configuration file %s.",conf_filename);
+ return -1;
+ }
+ retval = parse_config(cf,options);
+ if (retval)
+ return -1;
+
+ return 0;
+}
diff --git a/src/op/config.h b/src/op/config.h
new file mode 100644
index 000000000..190296e76
--- /dev/null
+++ b/src/op/config.h
@@ -0,0 +1,30 @@
+/**
+ * config.h
+ * Routines for loading the configuration file.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.4 2002/04/02 14:28:01 badbytes
+ * Final finishes.
+ *
+ * Revision 1.3 2002/01/26 22:55:11 mp292
+ * *** empty log message ***
+ *
+ * Revision 1.2 2002/01/26 22:22:09 mp292
+ * Prevented duplicate definitions.
+ *
+ * Revision 1.1 2001/12/13 15:15:10 badbytes
+ * Started coding the onion proxy.
+ *
+ */
+#include "../common/config.h"
+
+/* loads the configuration file */
+int getconfig(char *filename, config_opt_t *options);
diff --git a/src/op/crypto.c b/src/op/crypto.c
new file mode 100644
index 000000000..effa768b8
--- /dev/null
+++ b/src/op/crypto.c
@@ -0,0 +1,104 @@
+/**
+ * crypto.c
+ * Crypto calls.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.1 2002/04/02 14:28:01 badbytes
+ * Final finishes.
+ *
+ */
+
+#include <malloc.h>
+#include <unistd.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+#include "../common/log.h"
+
+#include "crypto.h"
+
+int crypt_f(unsigned char *buf, size_t buflen, crypt_path_t **cpath, size_t cpathlen)
+{
+ int i=0;
+ int retval = 0;
+ unsigned char *ciphertext = NULL;
+ crypt_path_t *thishop;
+
+ /* allocate the ciphertext buffer */
+ ciphertext = (unsigned char *)malloc(buflen);
+ if (!ciphertext)
+ {
+ log(LOG_ERR,"Error allocating memory.");
+ return -1;
+ }
+
+ for (i=0; i < cpathlen; i++) /* moving from last to first hop
+ * Remember : cpath is in reverse order, i.e. last hop first
+ */
+ {
+ log(LOG_DEBUG,"crypt_f() : Processing hop %u",cpathlen-i);
+ thishop = cpath[i];
+
+ /* encrypt */
+ retval = EVP_EncryptUpdate(&thishop->f_ctx,ciphertext, &buflen, buf, buflen);
+ if (!retval) /* error */
+ {
+ log(LOG_ERR,"Error performing encryption:%s",ERR_reason_error_string(ERR_get_error()));
+ free(ciphertext);
+ return -1;
+ }
+
+ /* copy ciphertext back to buf */
+ memcpy((void *)buf,(void *)ciphertext,buflen);
+ }
+ free((void *)ciphertext);
+
+ return 0;
+}
+
+int crypt_b(unsigned char *buf, size_t buflen, crypt_path_t **cpath, size_t cpathlen)
+{
+ int i=0;
+ int retval=0;
+ unsigned char *plaintext=NULL;
+ crypt_path_t *thishop;
+
+ /* allocate the plaintext buffer */
+ plaintext = (unsigned char *)malloc(buflen);
+ if (!plaintext)
+ {
+ log(LOG_ERR,"Error allocating memory.");
+ return -1;
+ }
+
+ for (i=cpathlen-1; i >= 0; i--) /* moving from first to last hop
+ * Remember : cpath is in reverse order, i.e. last hop first
+ */
+ {
+ thishop = cpath[i];
+
+ /* encrypt */
+ retval = EVP_DecryptUpdate(&thishop->b_ctx,plaintext, &buflen, buf, buflen);
+ if (!retval) /* error */
+ {
+ log(LOG_ERR,"Error performing decryption:%s",ERR_reason_error_string(ERR_get_error()));
+ free(plaintext);
+ return -1;
+ }
+
+ /* copy plaintext back to buf */
+ memcpy((void *)buf,(void *)plaintext,buflen);
+ }
+
+ free(plaintext);
+
+ return 0;
+}
diff --git a/src/op/crypto.h b/src/op/crypto.h
new file mode 100644
index 000000000..17c61e669
--- /dev/null
+++ b/src/op/crypto.h
@@ -0,0 +1,23 @@
+/**
+ * crypto.h
+ * Crypto calls.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.1 2002/04/02 14:28:01 badbytes
+ * Final finishes.
+ *
+ */
+
+#include "../common/onion.h"
+
+int crypt_f(unsigned char *buf, size_t buflen, crypt_path_t **cpath, size_t cpathlen);
+
+int crypt_b(unsigned char *buf, size_t buflen, crypt_path_t **cpath, size_t cpathlen);
diff --git a/src/op/op.c b/src/op/op.c
new file mode 100644
index 000000000..06ae99950
--- /dev/null
+++ b/src/op/op.c
@@ -0,0 +1,916 @@
+/**
+ * op.c
+ * Onion Proxy
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.37 2002/06/14 20:45:56 mp292
+ * *** empty log message ***
+ *
+ * Revision 1.36 2002/04/02 14:28:01 badbytes
+ * Final finishes.
+ *
+ * Revision 1.35 2002/04/02 10:21:07 badbytes
+ * *** empty log message ***
+ *
+ * Revision 1.34 2002/03/29 08:35:12 badbytes
+ * Link encryption is now done on the entire cell header for simplicity.
+ *
+ * Revision 1.33 2002/03/28 17:57:59 badbytes
+ * Bug fix.
+ *
+ * Revision 1.32 2002/03/28 11:01:43 badbytes
+ * Now does link-encryption and link-padding.
+ *
+ * Revision 1.31 2002/03/12 23:40:32 mp292
+ * Started on op<->router connection padding.
+ *
+ * Revision 1.30 2002/01/29 02:22:58 mp292
+ * Put a timeout on all network I/O.
+ *
+ * Revision 1.29 2002/01/26 23:01:55 mp292
+ * Reviewed according to Secure-Programs-HOWTO.
+ *
+ * Revision 1.28 2002/01/18 20:42:06 mp292
+ * Reflects changes to common/onion.c:new_route()
+ *
+ * Revision 1.27 2002/01/17 23:49:15 mp292
+ * Added size of public key to one of the debugging messages.
+ *
+ * Revision 1.26 2002/01/16 23:01:58 mp292
+ * First phase of system testing completed (main functionality).
+ *
+ * Revision 1.25 2002/01/16 17:01:56 mp292
+ * There was a bug in checking whether the incoming connection is local or not.
+ *
+ * Revision 1.24 2002/01/16 16:09:32 mp292
+ * A pointer cast was missing. Fixed.
+ *
+ * Revision 1.23 2002/01/14 13:05:39 badbytes
+ * System testing in progress.
+ *
+ * Revision 1.22 2002/01/11 15:47:25 badbytes
+ * *** empty log message ***
+ *
+ * Revision 1.21 2002/01/09 09:18:35 badbytes
+ * Now handles EINTR error from accept().
+ *
+ * Revision 1.20 2002/01/09 07:57:18 badbytes
+ * Ciphers got out of sync, hopefully fixed.
+ *
+ * Revision 1.19 2001/12/19 11:15:41 badbytes
+ * Corrected AF_INET to PF_INET in socket() calls.
+ *
+ * Revision 1.18 2001/12/19 08:38:38 badbytes
+ * Zombie problems hopefully fixed.
+ *
+ * Revision 1.17 2001/12/19 08:29:29 badbytes
+ * Tested. Still some problems with zombies in both op and smtpap.
+ *
+ * Revision 1.16 2001/12/18 15:51:58 badbytes
+ * Connection with onion router established. Will continue testing tomorrow.
+ *
+ * Revision 1.15 2001/12/18 14:12:05 badbytes
+ * Tested up to connect() to onion router.
+ *
+ * Revision 1.14 2001/12/18 12:21:11 badbytes
+ * Forgot to convert port to network order :-)
+ *
+ * Revision 1.13 2001/12/18 11:52:27 badbytes
+ * Coding completed. Proceeding to test.
+ *
+ * Revision 1.12 2001/12/17 13:36:15 badbytes
+ * Writing handle_connection()
+ *
+ * Revision 1.11 2001/12/17 08:42:44 badbytes
+ * getrouters() now returns an array of routers and also writes the length of the array to an int*.
+ *
+ * Revision 1.10 2001/12/14 14:45:13 badbytes
+ * Added range checking for CoinWeight.
+ *
+ * Revision 1.9 2001/12/14 14:08:50 badbytes
+ * getrouters() now returns an array of pointers rather than a linked list
+ *
+ * Revision 1.8 2001/12/14 13:31:20 badbytes
+ * *** empty log message ***
+ *
+ * Revision 1.7 2001/12/14 13:17:12 badbytes
+ * Corrected references to types.h
+ *
+ * Revision 1.6 2001/12/14 13:00:30 badbytes
+ * Changed my mind, routers.c and routers.h stay where they are :-)
+ *
+ * Revision 1.5 2001/12/14 12:56:55 badbytes
+ * Moved routers* to common/
+ *
+ * Revision 1.4 2001/12/14 12:42:50 badbytes
+ * References to onion.h and onion.o now point to the common/ directory.
+ *
+ * Revision 1.3 2001/12/14 12:40:26 badbytes
+ * Was being stupid - op doesn't need a private key!! Have removed ...
+ *
+ * Revision 1.2 2001/12/14 11:27:16 badbytes
+ * Configuration and server setup completed.
+ *
+ * Revision 1.1 2001/12/13 15:15:11 badbytes
+ * Started coding the onion proxy.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <wait.h>
+
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+#include "../common/log.h"
+#include "../common/version.h"
+#include "../common/onion.h"
+#include "../common/utils.h"
+#include "../common/cell.h"
+#include "../common/scheduler.h"
+
+#include "config.h"
+#include "routers.h"
+#include "args.h"
+#include "auth.h"
+#include "op.h"
+#include "ss.h"
+#include "crypto.h"
+#include "buffers.h"
+
+/* global variables */
+
+/* default logging threshold */
+int loglevel = LOG_ERR;
+struct timeval conn_tout;
+struct timeval *conn_toutp = &conn_tout;
+
+/* valid command-line options */
+static char *args = "hf:p:l:";
+
+/* valid config file options */
+static config_opt_t options[] =
+{
+ {"RouterFile", CONFIG_TYPE_STRING, {0}, 0},
+ {"CoinWeight", CONFIG_TYPE_DOUBLE, {0}, 0},
+ {"MaxConn", CONFIG_TYPE_INT, {0}, 0},
+ {"ConnTimeout", CONFIG_TYPE_INT, {0}, 0},
+ {"Bandwidth", CONFIG_TYPE_INT, {0}, 0},
+ {0}
+};
+enum opts {
+ RouterFile=0, CoinWeight, MaxConn, ConnTimeout, Bandwidth
+};
+
+int connections = 0; /* number of active connections */
+
+/* local host info */
+struct hostent *local_host;
+char local_hostname[512];
+
+struct sockaddr_in local, remote; /* local and remote address info */
+struct sockaddr_in or_addr; /* onion router address */
+
+int request_sock; /* where we listen for connections */
+int new_sock; /* for accepted connections */
+int or_sock; /* for connecting to the first onion router */
+
+/* router array */
+routent_t **routerarray = NULL;
+int rarray_len = 0;
+
+/* end of global variables */
+
+void send_to_router(int s,unsigned char **outbuf, size_t *outbuflen, size_t *outbuf_dataoffset, size_t *outbuf_datalen, struct timeval *lastsend, struct timeval *interval, sched_t *scheduler, EVP_CIPHER_CTX *ctx)
+{
+ int retval;
+ int cells;
+ int datacells;
+ int paddingcells;
+ int i;
+ int x;
+ char *px;
+ struct timeval now;
+ cell_t cipher;
+ cell_t *padding;
+ int cipherlen;
+ unsigned long elapsed;
+
+ /* calculate the number of cells that need to be sent */
+ retval = gettimeofday(&now,NULL);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Could not get current time!");
+ return;
+ }
+
+ elapsed = 1000000*(now.tv_sec-lastsend->tv_sec) + now.tv_usec-lastsend->tv_usec;
+
+ if (elapsed < 1000000)
+ {
+ cells = ((options[Bandwidth].r.i) * 512) / /* number of bytes per second, divided by two */
+ (1000000/elapsed); /* fractions of second since last send */
+ }
+ else
+ {
+ cells = ((options[Bandwidth].r.i) * 512) * /* number of bytes per second, divided by two */
+ (elapsed/1000000); /* 1/fractions of second since last send */
+ }
+ cells /= sizeof(cell_t);
+
+ datacells = (*outbuf_datalen)/sizeof(cell_t); /* number of data cells available */
+ if (datacells > cells)
+ datacells = cells;
+ paddingcells = cells - datacells;
+
+ /* send the data cells first */
+ for (i=0; i<datacells; i++)
+ {
+ /* link-encrypt the cell header */
+ printf("Cell header plaintext: ");
+ for(x=0;x<8;x++) {
+ printf("%u ",*(char *)(*outbuf+*outbuf_dataoffset+x));
+ }
+ printf("\n");
+ retval = EVP_EncryptUpdate(ctx, (unsigned char *)&cipher, &cipherlen, *outbuf+*outbuf_dataoffset, 8);
+ if (!retval)
+ {
+ log(LOG_ERR,"Link encryption failed. Exiting.");
+ exit(-1);
+ }
+ printf("Cell header crypttext: ");
+ px = (char *)&cipher;
+ for(x=0;x<8;x++) {
+ printf("%u ",px[x]);
+ }
+ printf("\n");
+
+ /* copy the payload */
+ memcpy((void *)cipher.payload, (void *)(*outbuf+*outbuf_dataoffset+8), CELL_PAYLOAD_SIZE);
+
+ /* send the cell */
+ log(LOG_DEBUG,"send_to_router(): Trying to send a data/create cell to router.");
+ retval = write_tout(s,(unsigned char *)&cipher, sizeof(cell_t), conn_toutp);
+ if (retval < sizeof(cell_t))
+ {
+ log(LOG_ERR,"Connection to the router seems to be lost. Exiting.");
+ exit(-1);
+ }
+ *outbuf_dataoffset += sizeof(cell_t);
+ *outbuf_datalen -= sizeof(cell_t);
+
+ }
+
+ /* send padding */
+ for (i=0; i<cells-datacells; i++)
+ {
+ padding = new_padding_cell();
+ if (!padding)
+ {
+ log(LOG_ERR,"Memory allocation error. Exiting.");
+ exit(-1);
+ }
+
+ /* link encrypt the cell header */
+ retval = EVP_EncryptUpdate(ctx, (unsigned char *)&cipher, &cipherlen, (unsigned char *)padding, 8);
+ if (!retval)
+ {
+ log(LOG_ERR,"Link encryption failed. Exiting.");
+ exit(-1);
+ }
+
+ /* copy the payload */
+ memcpy((void *)cipher.payload, (void *)((unsigned char *)padding+8), CELL_PAYLOAD_SIZE);
+
+ /* send the cell */
+ log(LOG_DEBUG,"send_to_router(): Trying to send a padding cell to router.");
+ retval = write_tout(s, (unsigned char *)&cipher, sizeof(cell_t), conn_toutp);
+ if (retval < sizeof(cell_t))
+ {
+ log(LOG_ERR,"Connection to the router seems to be lost. Exiting.");
+ exit(-1);
+ }
+
+ free((void *)padding);
+ }
+
+ /* update scheduler state, if we've sent anything to the router */
+ if (cells)
+ {
+ retval = update_sched_entry(scheduler, *lastsend, *interval, now, *interval);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Scheduler error. Exiting.");
+ exit(-1);
+ }
+ memcpy((void *)lastsend,(void *)&now, sizeof(struct timeval));
+ }
+
+}
+
+/* deal with a client */
+int handle_connection()
+{
+ int retval = 0;
+ int routelen = 0; /* length of the route */
+ unsigned int *route = NULL; /* hops in the route as an array of indexes into rarray */
+ routent_t *firsthop = NULL;
+
+ uint32_t aci; /* ACI for this connection */
+
+ unsigned char *onion = NULL; /* holds the onion */
+ int onionlen = 0; /* onion length in host order */
+
+ crypt_path_t **cpath = NULL; /* defines the crypt operations that need to be performed on incoming/outgoing data */
+ char *dest_addr = NULL; /* destination address in ASCII format */
+
+ int dest_addrlen = 0;
+ char *dest_port = NULL; /* destination port in ASCII format */
+ int dest_portlen = 0;
+ ss_t *ss; /* standard structure */
+
+ uint32_t router_addr_net; /* address of the first onion router in network order */
+
+ unsigned char inbuf[1024]; /* buffer for forwarding data between ap and or */
+
+ unsigned char *outbuf = NULL; /* buffer for cells which are to be transmitted to the first core onion router in the route */
+ size_t outbuflen = 0;
+ size_t outbuf_dataoffset = 0; /* offset to the beginning of the data */
+ size_t outbuf_datalen = 0; /* length of the data stored in the buffer */
+
+ cell_t cellbuf;
+ int cellbuflen = 0;
+
+ struct timeval lastsend; /* time of last transmission to the onion router */
+ struct timeval interval; /* transmission interval */
+
+ /* link encryption */
+ unsigned char f_session_key[8];
+ unsigned char f_session_iv[8] = {0,0,0,0,0,0,0,0};
+ unsigned char b_session_key[8];
+ unsigned char b_session_iv[8] = {0,0,0,0,0,0,0,0};
+ EVP_CIPHER_CTX f_ctx;
+ EVP_CIPHER_CTX b_ctx;
+
+ /* scheduler */
+ sched_t *scheduler;
+
+ /* for use with select() */
+ fd_set rmask, mask;
+ int maxfd;
+ struct timeval *timeout;
+
+ /* get the standard structure */
+ retval = process_ss(new_sock, conn_toutp, &ss,&dest_addr, &dest_addrlen, &dest_port, &dest_portlen);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Error processing the standard structure.");
+ return -1;
+ }
+ log(LOG_DEBUG,"handle_connection() : Destination = %s:%s",dest_addr,dest_port);
+
+ /* choose a route */
+ route = (unsigned int *)new_route(options[CoinWeight].r.d, routerarray,rarray_len, &routelen);
+ if (!route)
+ {
+ log(LOG_ERR,"Error choosing a route through the OR network.");
+ return -1;
+ }
+ log(LOG_DEBUG,"handle_connection() : Chosen a route of length %u : ",routelen);
+ for (retval=routelen-1;retval>=0;retval--)
+ {
+ log(LOG_DEBUG,"handle_connection() : %u : %s:%u, %u",routelen-retval,(routerarray[route[retval]])->address,ntohs((routerarray[route[retval]])->port),RSA_size((routerarray[route[retval]])->pkey));
+ }
+
+ /* allocate memory for the crypt path */
+ cpath = malloc(routelen * sizeof(crypt_path_t *));
+ if (!cpath)
+ {
+ log(LOG_ERR,"Error allocating memory.");
+ free(route);
+ return -1;
+ }
+ /* create an onion and calculate crypto keys */
+ onion = create_onion(routerarray,rarray_len,route,routelen,&onionlen,cpath);
+ if (!onion)
+ {
+ log(LOG_ERR,"Error creating an onion.");
+ free(route);
+ return -1;
+ }
+ log(LOG_DEBUG,"handle_connection() : Created an onion of size %u bytes.",onionlen);
+ log(LOG_DEBUG,"handle_connection() : Crypt path :");
+ for (retval=0;retval<routelen;retval++)
+ {
+ log(LOG_DEBUG,"handle_connection() : %u/%u",(cpath[retval])->forwf, (cpath[retval])->backf);
+ }
+
+ /* connect to first onion router */
+ or_sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
+ if (or_sock < 0)
+ {
+ free(route);
+ free(onion);
+ free(cpath);
+ close(new_sock);
+ log(LOG_ERR,"Error creating socket.");
+ return -1;
+ }
+ log(LOG_DEBUG,"handle_connection() : Socket created.");
+
+ firsthop = routerarray[route[routelen-1]];
+ memset((void *)&or_addr,0,sizeof(or_addr));
+ or_addr.sin_family=AF_INET;
+ or_addr.sin_port=firsthop->entry_port;
+ router_addr_net = firsthop->addr;
+ memcpy(&or_addr.sin_addr,&router_addr_net,sizeof(struct sockaddr_in));
+ log(LOG_DEBUG,"handle_connection() : Trying to connect to %s:%u",inet_ntoa(or_addr.sin_addr), ntohs(or_addr.sin_port));
+ retval = connect(or_sock,(struct sockaddr *)&or_addr, sizeof(or_addr));
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Could not connect to onion router.");
+ free(route);
+ free(onion);
+ free(cpath);
+ close(or_sock);
+ close(new_sock);
+ return -1;
+ }
+ log(LOG_DEBUG,"handle_connection() : Connected to first onion router.");
+
+ /* send session key and bandwidth info */
+ retval = send_auth(or_sock, options[Bandwidth].r.i, firsthop->pkey, f_session_key, b_session_key);
+ if (retval == -1)
+ {
+ close(or_sock);
+ close(new_sock);
+ log(LOG_ERR,"Lost connection to an onion router. Exiting.");
+ return -1;
+ }
+ /* initialize crypto engines */
+ EVP_CIPHER_CTX_init(&f_ctx);
+ EVP_CIPHER_CTX_init(&b_ctx);
+ EVP_EncryptInit(&f_ctx, EVP_des_ofb(), f_session_key, f_session_iv);
+ EVP_DecryptInit(&b_ctx, EVP_des_ofb(), b_session_key, b_session_iv);
+
+ /* chose an ACI */
+ do
+ {
+ retval = RAND_pseudo_bytes((unsigned char *)&aci, 2);
+ if (retval==-1)
+ {
+ log(LOG_ERR,"Random data generator doesn't seem to work. Exiting.");
+ return -1;
+ }
+ } while(!aci); /* don't allow zero ACIs */
+ log(LOG_DEBUG,"handle_connection() : ACI %u chosen.",aci);
+
+ /* initialize last time of transmission to now */
+ retval = gettimeofday(&lastsend, NULL);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Could not get current time.");
+ return -1;
+ }
+ /* calculate the transmission interval */
+ interval.tv_sec = 0;
+ interval.tv_usec = 250000/options[Bandwidth].r.i;
+ /* initialize the scheduler */
+ scheduler = new_sched();
+ if (!scheduler)
+ {
+ log(LOG_ERR,"Could not initialize scheduler.");
+ return -1;
+ }
+ retval = add_sched_entry(scheduler, lastsend, interval);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Could not initialize scheduler.");
+ return -1;
+ }
+ timeout = NULL;
+
+ /* write the onion into the output buffer */
+ retval = buffer_create(aci, (unsigned char *)onion, onionlen, &outbuf, &outbuflen, &outbuf_dataoffset, &outbuf_datalen, cpath, routelen);
+ if (retval == -1)
+ {
+ log(LOG_DEBUG,"handle_connection() : Could not buffer the onion.");
+ close(or_sock);
+ return -1;
+ }
+ log(LOG_DEBUG,"handle_connection() : Onion buffered for output.");
+
+ /* send standard structure */
+ log(LOG_DEBUG,"handle_connection() : Calling send_crypt ... routelen=%u, sizeof(SS) = %u",routelen,sizeof(ss_t));
+ retval = buffer_data(aci, (unsigned char *)ss, sizeof(ss_t), &outbuf, &outbuflen, &outbuf_dataoffset, &outbuf_datalen, cpath, routelen);
+ if (retval == -1)
+ {
+ log(LOG_DEBUG,"handle_connection() : Could not buffer the standard structure for output.");
+ close(or_sock);
+ return -1;
+ }
+ log(LOG_DEBUG,"handle_connection() : Buffered the standard structure header.");
+ retval = buffer_data(aci, dest_addr,dest_addrlen, &outbuf, &outbuflen, &outbuf_dataoffset, &outbuf_datalen, cpath, routelen);
+ if (retval == -1)
+ {
+ log(LOG_DEBUG,"handle_connection() : Could not buffer the standard structure (dest. address) for output.");
+ close(or_sock);
+ return -1;
+ }
+ log(LOG_DEBUG,"handle_connection() : Buffered the destination address.");
+ retval = buffer_data(aci, dest_port, dest_portlen, &outbuf, &outbuflen, &outbuf_dataoffset, &outbuf_datalen, cpath, routelen);
+ if (retval == -1)
+ {
+ log(LOG_DEBUG,"handle_connection() : Could not buffer the standard structure (dest. port) for output.");
+ close(or_sock);
+ return -1;
+ }
+ log(LOG_DEBUG,"handle_connection() : Buffered the destination port.");
+
+
+ /* forward data in both directions, crypt as necessary */
+ /* use select() */
+
+ FD_ZERO(&mask);
+ FD_SET(new_sock, &mask);
+ FD_SET(or_sock, &mask);
+ if (new_sock > or_sock)
+ maxfd = new_sock;
+ else
+ maxfd = or_sock;
+
+ while(1)
+ {
+ rmask = mask;
+
+ /* delete old timeout */
+ if (timeout)
+ free((void *)timeout);
+ /* get the new one */
+ retval = sched_trigger(scheduler, &timeout);
+ if (retval == -1)
+ {
+ log(LOG_DEBUG,"Scheduler error.");
+ break;
+ }
+ retval = select(maxfd+1,&rmask,NULL,NULL,timeout);
+ if (retval < 0)
+ {
+ log(LOG_DEBUG,"handle_connection() : select() returned negative integer");
+ break;
+ }
+
+ if (FD_ISSET(new_sock,&rmask))
+ {
+ log(LOG_DEBUG,"handle_connection() : FD_ISSET(new_sock)");
+ retval = read_tout(new_sock, inbuf, 1024, 0, conn_toutp);
+ if (retval <= 0)
+ {
+ log(LOG_DEBUG,"handle_connection() : Received EOF on new_sock.");
+ break;
+ }
+ log(LOG_DEBUG,"handle_connection() : Received %u bytes from client.",retval);
+ retval = buffer_data(aci, inbuf, retval, &outbuf, &outbuflen, &outbuf_dataoffset, &outbuf_datalen, cpath, routelen);
+
+ if (retval < 0)
+ {
+ log(LOG_DEBUG,"handle_connection() : Could not buffer data for output to OR.");
+ break;
+ }
+ log(LOG_DEBUG,"handle_connection() : Buffered %u bytes for output to the OR.",retval);
+ }
+
+ if (FD_ISSET(or_sock, &rmask))
+ {
+ log(LOG_DEBUG,"handle_connection() : FD_ISSET(or_sock)");
+ /* read the remainder of the cell (or whatever we can get) */
+ retval = read_tout(or_sock, ((unsigned char *)&cellbuf)+cellbuflen, sizeof(cell_t) - cellbuflen, 0, conn_toutp);
+ if (retval <= 0)
+ {
+ log(LOG_DEBUG,"handle_connection() : Received EOF on or_sock.");
+ break;
+ }
+ log(LOG_DEBUG,"handle_connection() : Received %u bytes from router.",retval);
+ cellbuflen += retval;
+
+ if (cellbuflen == sizeof(cell_t)) /* received an entire cell */
+ {
+ /* link decrypt the cell header */
+ retval = EVP_DecryptUpdate(&b_ctx, (unsigned char *)inbuf, &cellbuflen, (unsigned char *)&cellbuf, 8);
+ if (!retval)
+ {
+ log(LOG_ERR,"Decryption error. Closing the connection and exiting.");
+ break;
+ }
+
+ if (((cell_t *)inbuf)->command == CELL_PADDING) /* padding, discard */
+ {
+ log(LOG_DEBUG,"Received a PADDING cell. Discarding.");
+ ; /* discard */
+ }
+ else if (((cell_t *)inbuf)->command == CELL_DATA) /* only process DATA cells , discard otherwise */
+ {
+ /* decrypt the payload length */
+ retval = crypt_b((unsigned char *)&((cell_t *)inbuf)->length, 1, cpath, routelen);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Decryption error. Closing the connection and exiting.");
+ break;
+ }
+
+ /* decrypt the payload */
+ retval = crypt_b((unsigned char *)cellbuf.payload, CELL_PAYLOAD_SIZE, cpath, routelen);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Decryption error. Closing the connection and exiting.");
+ break;
+ }
+
+ /* send the payload to the application proxy */
+ retval = write_tout(new_sock, (unsigned char *)cellbuf.payload, ((cell_t *)inbuf)->length, conn_toutp);
+ if (retval < ((cell_t *)inbuf)->length)
+ {
+ log(LOG_ERR,"Connection to the application proxy seems to be lost.");
+ break;
+ }
+ log(LOG_DEBUG,"handle_connection() : Sent %u bytes to client.",retval);
+ }
+ else
+ log(LOG_DEBUG,"handle_connection() : Recived cell has incorrect command or ACI. Discarding.");
+
+ cellbuflen = 0; /* get ready for the next cell */
+ }
+ }
+
+ /* send cells to the router */
+ send_to_router(or_sock,&outbuf, &outbuflen, &outbuf_dataoffset, &outbuf_datalen, &lastsend, &interval, scheduler, &f_ctx);
+ }
+
+ /* clean up */
+ log(LOG_DEBUG,"handle_connection() : handle_connection() exiting.");
+ close(or_sock);
+
+ return 0;
+}
+
+/* used for reaping zombie processes */
+void sigchld_handler(int s)
+{
+ while (wait(NULL) > 0);
+ connections--;
+}
+
+int main(int argc, char *argv[])
+{
+ int one = 1;
+ int retval = 0;
+
+ char *cp; /* temporary storage */
+ int i=0; /* iteration counter */
+
+ char *conf_filename = NULL; /* configuration file */
+
+ size_t sin_size; /* for accept() calls */
+
+ u_short p; /* onion proxy port */
+
+ /* used for reaping zombie processes */
+ struct sigaction sa;
+
+ int islocal = 0; /* is the incoming connection local? */
+
+ struct rlimit cd_limit; /* resource limit to prevent core dumps */
+
+ /* prevent core dump */
+ retval = getrlimit(RLIMIT_CORE, &cd_limit);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Could not tell the OS to prevent core dumps for the process.");
+ return -1;
+ }
+ cd_limit.rlim_cur = 0;
+ retval = setrlimit(RLIMIT_CORE, &cd_limit);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Could not tell the OS to prevent core dumps for the process.");
+ return -1;
+ }
+
+ /* get command-line arguments */
+ retval = getargs(argc,argv,args,&p,&conf_filename,&loglevel);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Error processing command-line arguments.");
+ exit(1);
+ }
+
+ /* load config file */
+ retval = getconfig(conf_filename,options);
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Error loading configuration file.");
+ exit(1);
+ }
+
+ if (options[RouterFile].err != 1)
+ {
+ log(LOG_ERR,"RouterFile option required, but not found.");
+ exit(1);
+ }
+
+ if (options[CoinWeight].err == -1)
+ {
+ log(LOG_ERR,"Error reading the CoinWeight option.");
+ exit(1);
+ }
+
+ if (options[CoinWeight].err == 0)
+ {
+ /* this is optional, so if not found, set default value */
+ options[CoinWeight].r.d = OP_DEFAULT_COIN_WEIGHT;
+ }
+ else if ((options[CoinWeight].r.d < 0) || (options[CoinWeight].r.d >= 1))
+ {
+ /* must be a value in [0,1) */
+ log(LOG_ERR,"CoinWeight option must be >= 0 and < 1.");
+ exit(1);
+ }
+
+ if (options[Bandwidth].err == 0)
+ {
+ /* optional, set to default */
+ options[Bandwidth].r.i = OP_DEFAULT_BANDWIDTH;
+ }
+ else if (options[Bandwidth].r.i <= 0)
+ {
+ log(LOG_ERR,"The Bandwidth option must be an integer greater than zero.");
+ exit(1);
+ }
+
+ if (options[ConnTimeout].err != 1)
+ {
+ conn_tout.tv_sec = OP_DEFAULT_CONN_TIMEOUT;
+ conn_tout.tv_usec = 0;
+ }
+ else
+ {
+ if (!options[ConnTimeout].r.i)
+ conn_toutp = NULL;
+ else
+ conn_tout.tv_sec = options[ConnTimeout].r.i;
+ conn_tout.tv_usec = 0;
+ }
+
+ /* load the routers file */
+ routerarray = getrouters(options[RouterFile].r.str,&rarray_len);
+ if (!routerarray)
+ {
+ log(LOG_ERR,"Error loading router list.");
+ exit(1);
+ }
+
+ /* get local address so that we know where to allow connections from*/
+ retval = gethostname(local_hostname, (size_t)512);
+ if (retval < 0)
+ {
+ log(LOG_ERR,"Error getting local hostname.");
+ return -1;
+ }
+ local_host = gethostbyname(local_hostname);
+ if (!local_host)
+ {
+ log(LOG_ERR,"Error getting local address.");
+ return -1;
+ }
+ log(LOG_DEBUG,"main() : Got local address : %s.",local_hostname);
+
+ /* get the server up and running */
+ request_sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
+ if (request_sock < 0)
+ {
+ log(LOG_ERR,"Error opening socket.");
+ return -1;
+ }
+ setsockopt(request_sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ log(LOG_DEBUG,"main() : Socket opened.");
+
+ memset((void *)&local,0,sizeof(local)); /* clear the structure first */
+ /* set up the sockaddr_in structure */
+ local.sin_family=AF_INET;
+ local.sin_addr.s_addr = INADDR_ANY;
+ local.sin_port=htons(p);
+ /* bind it to the socket */
+ retval = bind(request_sock,(struct sockaddr *)&local, sizeof(local));
+ if (retval < 0)
+ {
+ log(LOG_ERR,"Error binding socket to local port %d.",p);
+ return retval;
+ }
+ log(LOG_DEBUG,"main() : Socket bound to port %d.",p);
+ /* listen for connections */
+ retval = listen(request_sock,SOMAXCONN);
+ if (retval < 0)
+ {
+ log(LOG_ERR,"Could not listen for connections.");
+ return retval;
+ }
+ log(LOG_DEBUG,"main() : Listening for connections.");
+ /* server should now be up and running */
+
+ /* install the signal handler for making sure zombie processes are killed */
+ sa.sa_handler = sigchld_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ retval = sigaction(SIGCHLD,&sa,NULL);
+ if (retval < 0)
+ {
+ log(LOG_ERR,"Could not install a signal handler.");
+ return -1;
+ }
+
+ /* main server loop */
+ /* I use a forking server technique - this isn't the most efficient way to do it,
+ * but it is simpler. */
+ while(1)
+ {
+ sin_size = sizeof(struct sockaddr_in);
+ new_sock = accept(request_sock,(struct sockaddr *)&remote,&sin_size);
+ if (new_sock == -1)
+ {
+ if (errno != EINTR)
+ log(LOG_ERR,"Could not accept socket connection.");
+ else
+ log(LOG_DEBUG,"main() : Interrupt received.");
+ continue;
+ }
+
+ if (connections == options[MaxConn].r.i)
+ {
+ close(new_sock);
+ log(LOG_NOTICE,"Maximum connection limit exceeded. Rejecting incoming request.");
+ }
+ connections++;
+ log(LOG_DEBUG,"main() : Accepted a connection from %s.",inet_ntoa(remote.sin_addr));
+
+ /* see if the connection is local, otherwise reject */
+ /* first check that the connection is from the local host, otherwise reject */
+ if (*(uint32_t *)&remote.sin_addr == inet_addr("127.0.0.1"))
+ islocal=1;
+ for (i=0; (local_host->h_addr_list[i] != NULL) && (!islocal); i++)
+ {
+ cp = local_host->h_addr_list[i];
+ if (!memcmp(&remote.sin_addr, cp,sizeof(struct in_addr)))
+ islocal = 1;
+ }
+
+ if (!islocal)
+ {
+ log(LOG_DEBUG,"main() : Incoming connection is not local. Will reject.");
+ close(new_sock);
+ }
+ else
+ {
+ log(LOG_DEBUG,"main() : Incoming connection seems to be local. Will accept.");
+ /* fork a process to deal with the customer */
+ if (!fork()) /* this is the child process */
+ {
+ close(request_sock); /* the child doesn't need the request socket anymore */
+
+ /* Main logic of op. */
+ retval = handle_connection();
+ log(LOG_DEBUG,"main() : Handle connection returned %d.",retval);
+ /* End main logic */
+
+ exit(retval); /* done, exit */
+ }
+
+ close(new_sock); /* don't need this anymore */
+ }
+ }
+
+ return retval;
+
+}
+
diff --git a/src/op/op.h b/src/op/op.h
new file mode 100644
index 000000000..f45d387dd
--- /dev/null
+++ b/src/op/op.h
@@ -0,0 +1,54 @@
+/**
+ * op.h
+ * Onion Proxy
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.7 2002/03/28 11:01:43 badbytes
+ * Now does link-encryption and link-padding.
+ *
+ * Revision 1.6 2002/03/12 23:40:32 mp292
+ * Started on op<->router connection padding.
+ *
+ * Revision 1.5 2002/01/29 02:22:58 mp292
+ * Put a timeout on all network I/O.
+ *
+ * Revision 1.4 2002/01/26 23:01:55 mp292
+ * Reviewed according to Secure-Programs-HOWTO.
+ *
+ * Revision 1.3 2001/12/18 11:52:27 badbytes
+ * Coding completed. Proceeding to test.
+ *
+ * Revision 1.2 2001/12/17 13:36:15 badbytes
+ * Writing handle_connection()
+ *
+ * Revision 1.1 2001/12/13 15:15:11 badbytes
+ * Started coding the onion proxy.
+ *
+ */
+
+#ifndef __OP_H
+
+#define __OP_H
+
+/* choosing the length of a route uses a weighted coin
+ * this is the default value for it */
+#define OP_DEFAULT_COIN_WEIGHT 0.8
+
+/* default connection timeout */
+#define OP_DEFAULT_CONN_TIMEOUT 120 /* 120s */
+
+/* default connection bandwidth */
+#define OP_DEFAULT_BANDWIDTH 1 /* 1kb/s */
+
+/* default buffer size per connection */
+#define OP_DEFAULT_BUFSIZE 4096 /* 4kb */
+
+#endif
diff --git a/src/op/routers.c b/src/op/routers.c
new file mode 100644
index 000000000..943b08cf9
--- /dev/null
+++ b/src/op/routers.c
@@ -0,0 +1,364 @@
+/**
+ * routers.c
+ * Routines for loading the list of routers and their public RSA keys.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.16 2002/04/02 14:28:01 badbytes
+ * Final finishes.
+ *
+ * Revision 1.15 2002/03/25 10:48:48 badbytes
+ * Added explicit dependency on <netinet/in.h>.
+ *
+ * Revision 1.14 2002/01/27 19:24:33 mp292
+ * Fixed a bug in parameter checking.
+ *
+ * Revision 1.13 2002/01/26 22:19:15 mp292
+ * Reviewed according to Secure-Programs-HOWTO.
+ *
+ * Revision 1.12 2002/01/18 20:42:25 mp292
+ * Slight modification to the way keys are read from the route file.
+ *
+ * Revision 1.11 2002/01/14 13:05:39 badbytes
+ * System testing in progress.
+ *
+ * Revision 1.10 2002/01/11 15:47:25 badbytes
+ * *** empty log message ***
+ *
+ * Revision 1.9 2001/12/18 15:51:58 badbytes
+ * Connection with onion router established. Will continue testing tomorrow.
+ *
+ * Revision 1.8 2001/12/17 13:36:15 badbytes
+ * Writing handle_connection()
+ *
+ * Revision 1.7 2001/12/17 08:42:45 badbytes
+ * getrouters() now returns an array of routers and also writes the length of the array to an int*.
+ *
+ * Revision 1.6 2001/12/14 14:08:50 badbytes
+ * getrouters() now returns an array of pointers rather than a linked list
+ *
+ * Revision 1.5 2001/12/14 14:05:56 badbytes
+ * Added routent_t** make_rarray(routent_t* list);
+ *
+ * Revision 1.4 2001/12/14 13:25:17 badbytes
+ * Moved back from common/
+ *
+ * Revision 1.2 2001/12/14 11:24:57 badbytes
+ * Tested.
+ *
+ * Revision 1.1 2001/12/13 15:15:11 badbytes
+ * Started coding the onion proxy.
+ *
+ */
+
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <netdb.h>
+#include <string.h>
+#include <netinet/in.h>
+
+#include "routers.h"
+#include "../common/log.h"
+#include "../common/utils.h"
+#include "../common/config.h"
+
+/* delete a list of routers from memory */
+void delete_routerlist(routent_t *list)
+{
+ routent_t *tmp = NULL;
+
+ if (!list)
+ return;
+
+ do
+ {
+ tmp=list->next;
+ free(list->address);
+ RSA_free(list->pkey);
+ free(list);
+ list = tmp;
+ }
+ while (list != NULL);
+
+ return;
+}
+
+/* create an NULL-terminated array of pointers pointing to elements of a router list */
+/* this is done in two passes through the list - inefficient but irrelevant as this is
+ * only done once when op/or start up */
+routent_t **make_rarray(routent_t* list, size_t *len)
+{
+ routent_t *tmp=NULL;
+ int listlen = 0;
+ routent_t **array=NULL;
+ routent_t **p=NULL;
+
+ if ((!list) || (!len))
+ return NULL;
+
+ /* get the length of the list */
+ tmp = list;
+ do
+ {
+ listlen++;
+ tmp = tmp->next;
+ }
+ while (tmp != NULL);
+
+ array = malloc((listlen+1)*sizeof(routent_t *));
+ if (!array)
+ {
+ log(LOG_ERR,"Error allocating memory.");
+ return NULL;
+ }
+
+ tmp=list;
+ p = array;
+ do
+ {
+ *p = tmp;
+ p++;
+ tmp = tmp->next;
+ }
+ while(tmp != NULL);
+ *p=NULL;
+
+ *len = listlen;
+ return array;
+}
+
+/* load the router list */
+routent_t **getrouters(char *routerfile, size_t *lenp)
+{
+ int retval = 0;
+ char *retp = NULL;
+ routent_t *router=NULL, *routerlist=NULL, *lastrouter=NULL;
+ FILE *rf; /* router file */
+ fpos_t fpos;
+ char line[512];
+ char *token;
+ char *errtest; /* detecting errors in strtoul() calls */
+ struct hostent *rent;
+
+ if ((!routerfile) || (!lenp)) /* invalid parameters */
+ return NULL;
+
+ if (strspn(routerfile,CONFIG_LEGAL_FILENAME_CHARACTERS) != strlen(routerfile)) /* invalid filename */
+ {
+ log(LOG_ERR,"Could not open %s because it contains illegal characters.",routerfile);
+ return NULL;
+ }
+
+ /* open the router list */
+ rf = fopen(routerfile,"r");
+ if (!rf)
+ {
+ log(LOG_ERR,"Could not open %s.",routerfile);
+ return NULL;
+ }
+
+ retp= fgets(line,512,rf);
+ while (retp)
+ {
+ log(LOG_DEBUG,"getrouters() : Line :%s",line);
+ token = (char *)strtok(line,OP_ROUTERLIST_SEPCHARS);
+ if (token)
+ {
+ log(LOG_DEBUG,"getrouters() : Token : %s",token);
+ if (token[0] != '#') /* ignore comment lines */
+ {
+ router = malloc(sizeof(routent_t));
+ if (!router)
+ {
+ log(LOG_ERR,"Could not allocate memory.");
+ fclose(rf);
+ delete_routerlist(routerlist);
+ return NULL;
+ }
+
+ /* read the address */
+ router->address = malloc(strlen(token)+1);
+ if (!router->address)
+ {
+ log(LOG_ERR,"Could not allocate memory.");
+ fclose(rf);
+ free(router);
+ delete_routerlist(routerlist);
+ return NULL;
+ }
+ strcpy(router->address,token);
+
+ rent = (struct hostent *)gethostbyname(router->address);
+ if (!rent)
+ {
+ log(LOG_ERR,"Could not get address for router %s.",router->address);
+ fclose(rf);
+ free(router->address);
+ free(router);
+ delete_routerlist(routerlist);
+ return NULL;
+ }
+
+ memcpy(&router->addr, rent->h_addr,rent->h_length);
+
+ /* read the network port */
+ token = (char *)strtok(NULL,OP_ROUTERLIST_SEPCHARS);
+ if (token) /* network port */
+ {
+ log(LOG_DEBUG,"getrouters() : Token :%s",token);
+ router->port = (uint16_t)strtoul(token,&errtest,0);
+ if ((*token != '\0') && (*errtest == '\0')) /* network port conversion was successful */
+ {
+ router->port = htons(router->port);
+ /* read the entry port */
+ token = (char *)strtok(NULL,OP_ROUTERLIST_SEPCHARS);
+ if (token) /* entry port */
+ {
+ log(LOG_DEBUG,"getrouters() : Token :%s",token);
+ router->entry_port = (uint16_t)strtoul(token,&errtest,0);
+ if ((*token != '\0') && (*errtest == '\0')) /* entry port number conversion was successful */
+ {
+ router->entry_port = htons(router->entry_port);
+ /* check that there is a public key entry for that router */
+ retval = fgetpos(rf, &fpos); /* save the current file position
+ * we wil return to it later if we find a public key */
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Could not save position in %s.",routerfile);
+ free(router->address);
+ free(router);
+ fclose(rf);
+ delete_routerlist(routerlist);
+ return NULL;
+ }
+ do /* read through to the next non-empty line */
+ {
+ retp=fgets(line,512,rf);
+ if (!retp)
+ {
+ log(LOG_ERR,"Could not find a public key entry for router %s:%u.",router->address,router->port);
+ free(router->address);
+ free(router);
+ fclose(rf);
+ delete_routerlist(routerlist);
+ return NULL;
+ }
+ log(LOG_DEBUG,"getrouters() : Line:%s",line);
+ if ((*line != '#') && (strspn(line,OP_ROUTERLIST_SEPCHARS) != strlen(line) ))
+ {
+ break;
+ }
+ } while (1);
+
+ if (!strcmp(line,OP_PUBLICKEY_BEGIN_TAG)) /* we've got the public key */
+ {
+ retval = fsetpos(rf,&fpos); /* get us back to where we were otherwise crypto lib won't find the key */
+ if (retval == -1)
+ {
+ log(LOG_ERR,"Could not set position in %s.",routerfile);
+ free(router->address);
+ free(router);
+ fclose(rf);
+ delete_routerlist(routerlist);
+ return NULL;
+ }
+ }
+ else /* we found something else; this isn't right */
+ {
+ log(LOG_ERR,"Could not find a public key entry for router %s:%u.",router->address,router->port);
+ free(router->address);
+ free(router);
+ fclose(rf);
+ delete_routerlist(routerlist);
+ return NULL;
+ }
+
+ log(LOG_DEBUG,"getrouters() : Reading the key ...");
+ /* read the public key into router->pkey */
+ router->pkey=NULL;
+ router->pkey = PEM_read_RSAPublicKey(rf,NULL,NULL,NULL);
+ if (!router->pkey) /* something went wrong */
+ {
+ log(LOG_ERR,"Could not read public key for router %s:%u.",router->address,router->port);
+ free(router->address);
+ free(router);
+ fclose(rf);
+ delete_routerlist(routerlist);
+ return NULL;
+ }
+ else /* read the key */
+ {
+ log(LOG_DEBUG,"getrouters() : Public key size = %u.", RSA_size(router->pkey));
+ if (RSA_size(router->pkey) != 128) /* keys MUST be 1024 bits in size */
+ {
+ log(LOG_ERR,"Key for router %s:%u is not 1024 bits. All keys must be exactly 1024 bits long.",router->address,router->port);
+ free(router->address);
+ RSA_free(router->pkey);
+ free(router);
+ fclose(rf);
+ delete_routerlist(routerlist);
+ return NULL;
+ }
+ router->next = NULL;
+ /* save the entry into the routerlist linked list */
+ if (!routerlist) /* this is the first entry */
+ routerlist = router;
+ else
+ lastrouter->next = (void *)router;
+ lastrouter = router;
+ }
+ }
+ else
+ {
+ log(LOG_ERR,"Entry for router %s doesn't seem to contain a valid entry funnel port.",router->address);
+ free(router->address);
+ free(router);
+ fclose(rf);
+ delete_routerlist(routerlist);
+ return NULL;
+ }
+ }
+ else
+ {
+ log(LOG_ERR,"Entry for router %s doesn't seem to contain an entry funnel port.",router->address);
+ free(router->address);
+ free(router);
+ fclose(rf);
+ delete_routerlist(routerlist);
+ return NULL;
+ }
+ }
+ else
+ {
+ log(LOG_ERR,"Entry for router %s doesn't seem to contain a valid network funnel port.",router->address);
+ free(router->address);
+ free(router);
+ fclose(rf);
+ delete_routerlist(routerlist);
+ return NULL;
+ }
+ }
+ else
+ {
+ log(LOG_ERR,"Entry for router %s doesn't seem to contain a network funnel port.",router->address);
+ free(router->address);
+ free(router);
+ fclose(rf);
+ delete_routerlist(routerlist);
+ return NULL;
+ }
+ }
+ }
+ retp=fgets(line,512,rf);
+ }
+
+ fclose(rf);
+ return make_rarray(routerlist, lenp);
+}
diff --git a/src/op/routers.h b/src/op/routers.h
new file mode 100644
index 000000000..7cacb4daf
--- /dev/null
+++ b/src/op/routers.h
@@ -0,0 +1,66 @@
+/**
+ * routers.h
+ * Routines for loading the list of routers and their public RSA keys.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.11 2002/04/02 14:28:01 badbytes
+ * Final finishes.
+ *
+ * Revision 1.10 2002/01/26 22:22:09 mp292
+ * Prevented duplicate definitions.
+ *
+ * Revision 1.9 2002/01/26 22:19:15 mp292
+ * Reviewed according to Secure-Programs-HOWTO.
+ *
+ * Revision 1.8 2001/12/17 08:42:45 badbytes
+ * getrouters() now returns an array of routers and also writes the length of the array to an int*.
+ *
+ * Revision 1.7 2001/12/14 14:08:50 badbytes
+ * getrouters() now returns an array of pointers rather than a linked list
+ *
+ * Revision 1.6 2001/12/14 14:05:56 badbytes
+ * Added routent** make_rarray(routent_t* list);
+ *
+ * Revision 1.5 2001/12/14 13:32:18 badbytes
+ * No longer contains the definition of routent_t. This is now in common/routent_t.h
+ *
+ * Revision 1.4 2001/12/14 13:25:17 badbytes
+ * Moved back from common/
+ *
+ * Revision 1.2 2001/12/14 11:24:57 badbytes
+ * Tested.
+ *
+ * Revision 1.1 2001/12/13 15:15:11 badbytes
+ * Started coding the onion proxy.
+ *
+ */
+
+#ifndef __ROUTERS_H
+
+#define __ROUTERS_H
+
+#include <openssl/rsa.h>
+#include "../common/routent.h"
+
+#define OP_ROUTERLIST_SEPCHARS " \t\n"
+
+#define OP_PUBLICKEY_BEGIN_TAG "-----BEGIN RSA PUBLIC KEY-----\n"
+
+/* load the list of routers into memory */
+routent_t **getrouters(char *routerfile, size_t *listlenp);
+
+/* free the router list pointed to by list */
+void delete_routerlist(routent_t *list);
+
+/* create an NULL-terminated array of pointers pointing to elements of a router list */
+routent_t **make_rarray(routent_t* list, size_t *listlenp);
+
+#endif
diff --git a/src/op/ss.c b/src/op/ss.c
new file mode 100644
index 000000000..3437517e4
--- /dev/null
+++ b/src/op/ss.c
@@ -0,0 +1,194 @@
+/**
+ * ss.c
+ * Standard structure processing.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.1 2002/04/02 14:28:01 badbytes
+ * Final finishes.
+ *
+ */
+
+
+#include <malloc.h>
+#include <unistd.h>
+
+#include "../common/log.h"
+#include "../common/version.h"
+#include "../common/utils.h"
+
+#include "ss.h"
+
+/* read the standard structure, check if it's acceptable and send an appropriate error code
+ * Returns :
+ * -1 processing error
+ * 0 OK
+ * 1 no error, but standard structure rejected
+ */
+int process_ss(int s, struct timeval *conn_toutp, ss_t **ssp, char **addrp, int *addrlenp, char **portp, int *portlenp)
+{
+ int retval = 0;
+ int len = 0; /* number of bytes read */
+ ss_t *ss; /* standard structure */
+ char errcode = SS_ERROR_SUCCESS; /* error code which we send back to the client */
+ char inbuf;
+ char *addr = NULL; /* destination address */
+ int addrlen = 0;
+ char *port = NULL; /* destination port */
+ int portlen = 0;
+ char *tmp = NULL; /* temporary storage */
+
+ if ((!ssp) || (!addrp) || (!addrlenp) || (!portp) || (!portlenp)) /* invalid parameters */
+ return -1;
+
+ /* allocate memory for SS */
+ ss = malloc(sizeof(ss_t));
+ if (!ss)
+ {
+ log(LOG_ERR,"Error allocating memory.");
+ return -1;
+ }
+
+ log(LOG_DEBUG,"Allocated memory for ss.");
+
+ len = 0;
+ while (len < sizeof(ss_t)) /* need to make sure the entire ss is read */
+ {
+ retval = read_tout(s,(char *)ss+len,sizeof(ss_t)-len,0, conn_toutp);
+ if (retval <= 0)
+ {
+ free(ss);
+ log(LOG_ERR,"Could not receive standard structure.");
+ return -1;
+ }
+ len +=retval;
+ }
+
+ if ((ss->version == 0) || (ss->version != VERSION)) /* unsupported version */
+ {
+ log(LOG_DEBUG,"Unsupported version.");
+ free(ss);
+ errcode = SS_ERROR_VERSION_UNSUPPORTED;
+ write_tout(s,&errcode,1,conn_toutp);
+ return -1;
+ }
+
+ if (ss->addr_fmt != SS_ADDR_FMT_ASCII_HOST_PORT) /* unrecognized address format */
+ {
+ log(LOG_DEBUG,"Unrecognized address format.");
+ free(ss);
+ errcode = SS_ERROR_ADDR_FMT_UNSUPPORTED;
+ write_tout(s,&errcode,1,conn_toutp);
+ return -1;
+ }
+
+ /* allocate memory for the destination address - 512 bytes maximum */
+ addrlen=512;
+ addr = malloc(addrlen);
+ if (!addr)
+ {
+ free(ss);
+ log(LOG_ERR,"Error allocating memory.");
+ return -1;
+ }
+
+ /* now read the destination address */
+ len = 0;
+ do /* need to keep going until the entire string is read in */
+ {
+ if (len == addrlen) /* we've run out of space, abort */
+ {
+ free(ss);
+ free(addr);
+ log(LOG_ERR,"Client tried to send address > 512 characters.");
+ errcode = SS_ERROR_INVALID_ADDRESS;
+ write_tout(s,&errcode,1,conn_toutp);
+ return -1;
+ }
+ retval = read_tout(s,(void *)&inbuf, 1, 0, conn_toutp);
+ if (retval <= 0)
+ {
+ free(ss);
+ free(addr);
+ log(LOG_ERR,"Error receiving destination address.");
+ return -1;
+ }
+ *(addr+len) = inbuf;
+ len++;
+ } while (inbuf != 0);
+
+
+ /* allocate memory for the destination port - 6 bytes maximum */
+ portlen = 6;
+ port = malloc(portlen);
+ if (!port)
+ {
+ free(ss);
+ log(LOG_ERR,"Error allocating memory.");
+ free(addr);
+ return -1;
+ }
+ /* now read the destination port */
+ len = 0;
+ do /* keep going until the entire string is read in */
+ {
+ if (len == portlen) /* no more space, abort */
+ {
+ free(ss);
+ free(addr);
+ free(port);
+ log(LOG_ERR,"Client tried to send port > 6 characters.");
+ errcode = SS_ERROR_INVALID_PORT;
+ write_tout(s,&errcode,1,conn_toutp);
+ return -1;
+ }
+ retval = read_tout(s,(void *)&inbuf, 1, 0, conn_toutp);
+ if (retval <= 0)
+ {
+ free(ss);
+ free(addr);
+ free(port);
+ log(LOG_ERR,"Error receiving destination port.");
+ return -1;
+ }
+ *(port+len)=inbuf;
+ len++;
+ } while (inbuf != 0);
+
+ /* send a success error code back to the client */
+ errcode = SS_ERROR_SUCCESS;
+ write_tout(s,&errcode,1,conn_toutp);
+
+ /* done, now save */
+ addrlen = strlen(addr)+1;
+ tmp = addr;
+ addr = realloc(addr,addrlen);
+ /* if realloc() fails, we just ignore it and use the previously allocated memory, although this may be wasteful */
+ if (!addr)
+ addr=tmp; /* restore previous state */
+ else
+ addr[addrlen-1]=0;
+
+ portlen = strlen(port)+1;
+ tmp=port;
+ port = realloc(port,portlen);
+ if (!port)
+ port=tmp;
+ else
+ port[portlen-1]=0;
+
+ *ssp = ss;
+ *addrp = addr;
+ *addrlenp = addrlen;
+ *portp = port;
+ *portlenp = portlen;
+
+ return 0;
+}
diff --git a/src/op/ss.h b/src/op/ss.h
new file mode 100644
index 000000000..d6e68240f
--- /dev/null
+++ b/src/op/ss.h
@@ -0,0 +1,22 @@
+/**
+ * ss.h
+ * Standard structure processing.
+ *
+ * Matej Pfajfar <mp292@cam.ac.uk>
+ */
+
+/*
+ * Changes :
+ * $Log$
+ * Revision 1.1 2002/06/26 22:45:50 arma
+ * Initial revision
+ *
+ * Revision 1.1 2002/04/02 14:28:01 badbytes
+ * Final finishes.
+ *
+ */
+
+
+#include "../common/ss.h"
+
+int process_ss(int s, struct timeval *conn_toutp, ss_t **ssp, char **addrp, int *addrlenp, char **portp, int *portlenp);