#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/vfs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <time.h>
#include <zlib.h>
#include <errno.h>
#include <sys/reg.h>
#include <sys/user.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include "sysdefs.h"
#include "webtool.h"
#include "tools.h"



void main(int argc, char **argv){
	int pid;	
	int retval;
	int status;
	int signo;
	int ip,sp;
	int ipoffs, spoffs;
	long orig_eax;
	struct user_regs_struct regs;
	struct interface_config *interfaces;
	int i,cnt;
	struct sockaddr *sockaddr;
	int sock_family;
	int sock_addr_len;
	char printable[1024];







	cnt = get_interfaces(&interfaces);

	printf("Found: %d interfaces\n",cnt);
	for ( i = 0; i < cnt; i++ ){
		char type[16];
		if ( interfaces[i].addrtype == AF_INET6  ) strcpy(type,"IPv6");
		if ( interfaces[i].addrtype == AF_INET  ) strcpy(type,"IPv4");
		if ( interfaces[i].addrtype == AF_PACKET  ) strcpy(type,"MAC");
		printf("[%d] [%s] %s:[%s]\n",i,interfaces[i].ethname,type,interfaces[i].addr);
	}


	if ( argc != 3 ){
		printf("Usage: %s <hostname> <port>\n",argv[0]);
		exit(2);
	}

	ftp_list(argv[1],"/tftpboot", "/tmp/dirlist");

	ftp_get(argv[1],"/tmp/data.bin",argv[2]);

	exit(0);

	retval = get_sockaddr(AF_UNSPEC,SOCK_STREAM,argv[1],atoi(argv[2]),&sockaddr,&sock_family,&sock_addr_len,printable,1024);
	printf("retval of get_sockaddr(AF_UNSPEC): %d\n",retval);
	if ( retval == 0 ){
		struct sockaddr_in *socky4;
		struct sockaddr_in6 *socky6;
		char buf[1024];
		FILE *ss;
		int sock;
		printf("Addr-Len:    %d\n",sock_addr_len);
		printf("Addr-Family: %d\n",sock_family);
		socky4 = (struct sockaddr_in *)sockaddr;
		socky6 = (struct sockaddr_in6 *)sockaddr;
		printf("ADDR: [%s]\n",printable);
		sock = socket(sock_family,SOCK_STREAM,0);
		if ( sock < 0 ){
			printf("Cannot create socket (%s)!\n",strerror(errno));
		} else {
			if ( connect(sock,sockaddr,sock_addr_len) < 0 ){
				printf("Cannot connect socket (%s)!\n",strerror(errno));
			} else {
				ss = fdopen(sock,"rw");
				fgets(buf,1024,ss);
				printf("Received: [%s]\n",buf);
			}	
			close(sock);
		}
		
	}
	retval = get_sockaddr(AF_INET,SOCK_STREAM,argv[1],atoi(argv[2]),&sockaddr,&sock_family,&sock_addr_len,printable,1024);
	printf("retval of get_sockaddr(AF_INET): %d\n",retval);
	if ( retval == 0 ){
		struct sockaddr_in *socky4;
		struct sockaddr_in6 *socky6;
		char buf[1024];
		FILE *ss;
		int sock;
		printf("Addr-Len:    %d\n",sock_addr_len);
		printf("Addr-Family: %d\n",sock_family);
		socky4 = (struct sockaddr_in *)sockaddr;
		socky6 = (struct sockaddr_in6 *)sockaddr;
		printf("ADDR: [%s]\n",printable);
		sock = socket(sock_family,SOCK_STREAM,0);
		if ( sock < 0 ){
			printf("Cannot create socket (%s)!\n",strerror(errno));
		} else {
			if ( connect(sock,sockaddr,sock_addr_len) < 0 ){
				printf("Cannot connect socket (%s)!\n",strerror(errno));
			} else {
				ss = fdopen(sock,"rw");
				fgets(buf,1024,ss);
				printf("Received: [%s]\n",buf);
			}	
			close(sock);
		}
	}
	retval = get_sockaddr(AF_INET6,SOCK_STREAM,argv[1],atoi(argv[2]),&sockaddr,&sock_family,&sock_addr_len,printable,1024);
	printf("retval of get_sockaddr(AF_INET6): %d\n",retval);
	if ( retval == 0 ){
		struct sockaddr_in *socky4;
		struct sockaddr_in6 *socky6;
		char buf[1024];
		FILE *ss;
		int sock;
		printf("Addr-Len:    %d\n",sock_addr_len);
		printf("Addr-Family: %d\n",sock_family);
		socky4 = (struct sockaddr_in *)sockaddr;
		socky6 = (struct sockaddr_in6 *)sockaddr;
		printf("ADDR: [%s]\n",printable);
		sock = socket(sock_family,SOCK_STREAM,0);
		if ( sock < 0 ){
			printf("Cannot create socket (%s)!\n",strerror(errno));
		} else {
			if ( connect(sock,sockaddr,sock_addr_len) < 0 ){
				printf("Cannot connect socket (%s)!\n",strerror(errno));
			} else {
				ss = fdopen(sock,"rw");
				fgets(buf,1024,ss);
				printf("Received: [%s]\n",buf);
			}	
			close(sock);
		}
	}
	exit(0);

	pid = atoi(argv[1]);
	retval = ptrace(PTRACE_ATTACH, pid, NULL, NULL);
	if ( retval != 0 ){
		printf("Cannot trace %d\n",pid);
		exit(0);
	}
	retval = waitpid(pid,&status,WUNTRACED);
	if ( retval != pid || !(WIFSTOPPED(status)) ){
		printf("Cannot trace %d WAITPID failed!\n",pid);
		exit(0);
	}
	printf("P-Tracing START: %d, RETVAL: %ld\n",pid,retval);

	// Wait now for next syscall
	while(1){
		signo = 0;
		retval = ptrace(PTRACE_SYSCALL,pid,0,signo);
		printf("Waiting for next syscall: %d\n",retval);
			if ( retval < 0 ){
			printf("PTRACE_SYSCALL failed\n");
			exit(0);
		}
		retval = wait(&status);
		signo = WSTOPSIG(status);
		if ( signo == SIGTRAP ) signo = 0;
		if ( signo != SIGHUP && signo != SIGINT){
#if !defined __x86_64__
			long syscall;
			retval = ptrace(PTRACE_GETREGS,pid,NULL,&regs);
			syscall = regs.eax;
			printf("SYSCALL: %08lX [%s]\n",syscall,get_syscall(syscall));
			syscall = regs.orig_eax;
			if ( syscall > 0x80 ) syscall -= 0x80;
			printf("SYSCALL(ORIG): %08lX [%s]\n",syscall,get_syscall(syscall));
#else
			long syscall;
			retval = ptrace(PTRACE_GETREGS,pid,0, &regs);
			syscall = regs.orig_rax;
			printf("RAX: %d, RETVAL: %d, SYSCALL: %ld %s(%08lX,%08lX,%08lX,%08lX,%08lX,%08lX)\n",regs.rax,retval,syscall,get_syscall(syscall), (long)regs.rdi, (long)regs.rsi, (long)regs.rdx, (long)regs.r10,(long)regs.r8,(long)regs.r9);
#endif
			// ptrace(PTRACE_CONT,pid,0,signo);
		} else {
			ptrace(PTRACE_CONT,pid,0,signo);
		}
	}



	retval = ptrace(PTRACE_DETACH, pid, NULL, NULL);
	printf("P-Tracing   END: %d, RETVAL: %ld\n",pid,retval);
}
