roamctl |
---|
startup/shutdown script for GRIC's aims_roam_svd (note the LD_PRELOAD value). |
#!/bin/sh cd /etc/gricrad/executables case "$1" in start) # DL: Override IP address LD_PRELOAD=/etc/gricrad/executables/bind_override.so export LD_PRELOAD # #Start roaming with no debug #/etc/gricrad/executables/aims_roam_svd -d /etc/gricrad/config_files/ -a /var/adm/gricacct -R 1645 -A 1646 -U -e -c -l -t 10 & # #Start roaming with terminal debug /etc/gricrad/executables/aims_roam_svd -d /etc/gricrad/config_files/ -a /var/adm/gricacct -R 1645 -A 1646 -U -x -e -c -l -t 10 & # #Start roaming with debug.log debug #/etc/gricrad/executables/aims_roam_svd -d /etc/gricrad/config_files/ -a /var/adm/gricacct -R 1645 -A 1646 -U -x -e -c -l -t 10 > /etc/gricrad/debug.log & ;; stop) # DL: Kill GRIC processes /usr/bin/ps -u root | egrep 'aims_roa|Relog' | awk '{print $1}' | xargs kill -9 ;; *) echo 'This script only supports "start" or "stop"' ;; esac |
bind_override.c |
Note: This code isn't pretty - it doesn't even check sin_family to make sure the bind is a TCP/IP bind. But it works for the GRIC aims_roam_svd.
Compile the following (bind_override.c) with gcc -c -shared bind_override.c -o bind_override.so after changing the IP in it (note: tested on Solaris, should also work on Linux). |
#ifdef __linux__ #include <asm/unistd.h> #include <linux/net.h> static int errno; static __inline__ _syscall2(int,socketcall,int,a1,unsigned long *,args) #endif struct in_addr { unsigned int s_addr; }; struct sockaddr_in { unsigned short sin_family; unsigned short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; int bind(int fd, struct sockaddr_in *s, int len) { #ifdef __linux__ unsigned long sargs[3] = { fd, (long)s, len }; #endif if (len >= 8 && s->sin_addr.s_addr == 0) { printf("DL: Re-writing bind() syscall\n"); s->sin_addr.s_addr = inet_addr("192.168.0.2"); #ifdef __linux__ return socketcall(SYS_BIND, &sargs[0]); #else return _bind(fd, s, len); #endif } else { printf("DL: bind() syscall already has explicit addr (%s)\n", inet_ntoa(s->sin_addr)); #ifdef __linux__ return socketcall(SYS_BIND, &sargs[0]); #else return _bind(fd, s, len); #endif } } |
make-so |
---|
This script compiles and links as required. |
#!/bin/sh # Verbose gcc -c -shared -o virtual.so virtual.c ld -r -dy -G virtual.so /usr/lib/libnsl.so /usr/lib/libsocket.so -o virtual_linked.so # Quiet gcc -c -shared -o virtual_quiet.so virtual_quiet.c ld -r -dy -G virtual_quiet.so /usr/lib/libnsl.so /usr/lib/libsocket.so -o virtual_quiet_linked.so |
virtual.c |
The preload, similar to bind_override but with more test cases. |
#include <sys/select.h> #define VIP "192.168.0.3" #define AF_INET 2 #define SIN(x) ((struct sockaddr_in *)(x)) struct in_addr { unsigned int s_addr; }; struct sockaddr_in { unsigned short sin_family; unsigned short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; fd_set __v_bound; int __v_init = 0; struct sockaddr_in __v_addr; int __v_len = sizeof(__v_addr); static void __v_maybe_init(void) { if (!__v_init) { __v_init = 1; FD_ZERO(&__v_bound); } bzero(__v_addr, __v_len); __v_addr.sin_family = AF_INET; __v_addr.sin_addr.s_addr = inet_addr(VIP); } int bind(int fd, void *s, size_t len) { __v_maybe_init(); FD_SET(fd, &__v_bound); if (len >= 8 && SIN(s)->sin_family == AF_INET && SIN(s)->sin_addr.s_addr == 0) { printf("FD %d: Re-writing bind() syscall\n", fd); SIN(s)->sin_addr.s_addr = __v_addr.sin_addr.s_addr; return _bind(fd, s, len); } else { printf("FD %d: bind() syscall already has explicit addr (%s)\n", fd, inet_ntoa(SIN(s)->sin_addr)); return _bind(fd, s, len); } } int close(int fd) { __v_maybe_init(); if (fd > 0) { FD_CLR(fd, &__v_bound); } return _close(fd); } int connect(int fd, void *s, int len) { __v_maybe_init(); if (!FD_ISSET(fd, &__v_bound) && (len >= 8) && SIN(s)->sin_family == AF_INET) { printf("FD %d: connect() without bind, binding\n", fd); __v_addr.sin_port = 0; _bind(fd, &__v_addr, __v_len); } FD_SET(fd, &__v_bound); return _connect(fd, s, len); } |
virtual_quiet.c |
A quiet version of the virtual preload, since vnas runs from inetd so we can't output anything. |
#include <sys/select.h> #define VIP "192.168.0.3" #define AF_INET 2 #define SIN(x) ((struct sockaddr_in *)(x)) struct in_addr { unsigned int s_addr; }; struct sockaddr_in { unsigned short sin_family; unsigned short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; fd_set __v_bound; int __v_init = 0; struct sockaddr_in __v_addr; int __v_len = sizeof(__v_addr); static void __v_maybe_init(void) { if (!__v_init) { __v_init = 1; FD_ZERO(&__v_bound); } bzero(__v_addr, __v_len); __v_addr.sin_family = AF_INET; __v_addr.sin_addr.s_addr = inet_addr(VIP); } int bind(int fd, void *s, size_t len) { __v_maybe_init(); FD_SET(fd, &__v_bound); if (len >= 8 && SIN(s)->sin_family == AF_INET && SIN(s)->sin_addr.s_addr == 0) { SIN(s)->sin_addr.s_addr = __v_addr.sin_addr.s_addr; return _bind(fd, s, len); } else { return _bind(fd, s, len); } } int close(int fd) { __v_maybe_init(); if (fd > 0) { FD_CLR(fd, &__v_bound); } return _close(fd); } int connect(int fd, void *s, int len) { __v_maybe_init(); if (!FD_ISSET(fd, &__v_bound) && (len >= 8) && SIN(s)->sin_family == AF_INET) { __v_addr.sin_port = 0; _bind(fd, &__v_addr, __v_len); } FD_SET(fd, &__v_bound); return _connect(fd, s, len); } |
vnas |
vnas is moved to vnas.real, and this script put in it's place. |
#!/bin/sh LD_PRELOAD=/usr/ipass/bin/virtual_quiet_linked.so export LD_PRELOAD exec /usr/ipass/bin/vnas.real $* |
rc.netserverd |
The rc.netserverd needs these lines added just above the line starting netserver. |
LD_PRELOAD=/usr/ipass/bin/virtual_linked.so export LD_PRELOAD |
--