summaryrefslogtreecommitdiffstats
path: root/cryptot.c
diff options
context:
space:
mode:
authorJérémy Zurcher <jeremy@asynk.ch>2010-07-09 12:32:17 +0200
committerJérémy Zurcher <jeremy@asynk.ch>2010-07-09 12:32:17 +0200
commit6c027b4de25a529908be895e7ff19236f4002a57 (patch)
treef70d3a400bbb9ba8a83e9d4ffcaa4b6e367fc8bb /cryptot.c
downloadcrypto-6c027b4de25a529908be895e7ff19236f4002a57.zip
crypto-6c027b4de25a529908be895e7ff19236f4002a57.tar.gz
initial commit, resurrect one of my realy old projects
Diffstat (limited to 'cryptot.c')
-rw-r--r--cryptot.c570
1 files changed, 570 insertions, 0 deletions
diff --git a/cryptot.c b/cryptot.c
new file mode 100644
index 0000000..da565e1
--- /dev/null
+++ b/cryptot.c
@@ -0,0 +1,570 @@
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "cryptot.h"
+#include "crypto_buffer.h"
+#include "ipv4.h"
+#include "scan.h"
+#include "socket.h"
+
+#define HOSTLEN 64 /* length of hostname string in resolvip */
+
+/*
+ * adding ciphers, fct to update :
+ * usage_cipher
+ * change_cipher
+ * allocate_buffer
+ * do_stats
+ */
+
+
+static void connect_to_dist(int sock, struct cryptot_st *data, int verbose)
+{
+ int retry = 5;
+ char buf[2];
+ if(socket_local4(sock,data->local_ip,&data->local_port)==-1)
+ fprintf(stderr,"%s : socket_local4 error.\n",PROG_NAME);
+ if(verbose){
+ fprintf(stderr,"%s : trying to connect to %03d.%03d.%03d.%03d:%d "
+ "from %03d.%03d.%03d.%03d:%d\n",PROG_NAME,
+ NIPQUAD(data->dist_ip),data->dist_port,NIPQUAD(data->local_ip),data->local_port);
+ }
+ while(retry--){
+ if(!socket_connect4(sock,data->dist_ip,data->dist_port)){
+ /* TODO we may be rejected by -S option */
+ if(!recv(sock,buf,2,0)){
+ fprintf(stderr,"%s : rejected (because of -S option ?).\n",PROG_NAME); exit(1);
+ }
+ if(strncmp(buf,"OK",2)) {
+ fprintf(stderr,"%s : protocol error (middle man ?).\n",PROG_NAME); exit(1);
+ }
+ if(verbose)fprintf(stderr,"%s : connected.\n",PROG_NAME);
+ return;
+ }
+ sleep(3);
+ fprintf(stderr,"%s : connect failed, retry\n",PROG_NAME);
+ }
+ fprintf(stderr,"%s socket_connect4 error :",PROG_NAME);
+ perror("");
+ exit(1);
+}
+
+static int wait_connection(int sock, struct cryptot_st *data, int verbose)
+{
+ int client;
+ char peer_ip[4];
+ unsigned int peer_port;
+
+ for(;;){
+ if(verbose)
+ fprintf(stderr,"%s : waiting for a connection on %03d.%03d.%03d.%03d:%d.\n",
+ PROG_NAME, NIPQUAD(data->local_ip),data->local_port);
+ client = socket_accept4(sock,peer_ip,&peer_port);
+ if(client<0){ fprintf(stderr,"%s socket_accept error : ",PROG_NAME); perror(""); exit(1); }
+
+ if(data->check_accept){
+ if(peer_port != data->src_port || memcmp(data->src_ip,peer_ip,4)){
+ fprintf(stderr,"%s : REFUSE connection from %03d.%03d.%03d.%03d:%d.\n",
+ PROG_NAME,NIPQUAD(peer_ip),peer_port);
+ shutdown(client,SHUT_RDWR);
+ close(client);
+ continue;
+ }
+ }
+ send(client,"OK",2,0);
+ if(verbose)
+ fprintf(stderr,"%s : accept connection from %03d.%03d.%03d.%03d:%d.\n",
+ PROG_NAME,NIPQUAD(peer_ip),peer_port);
+ return client;
+ }
+}
+
+static void do_stats(struct cryptot_st *data, struct timespec *s0, struct timespec *s1, unsigned int count)
+{
+ char *cipher=NULL;
+ char b[6] = "bytes";
+ char kb[3] = "Kb";
+ char mb[3] = "Mb";
+ char gb[3] = "Gb";
+ char *unit = b;
+ float time;
+ int size =0;
+ float nbr =(float)count;
+
+ if(nbr> 1024){ nbr/=1024; unit=kb;}
+ if(nbr> 1024){ nbr/=1024; unit=mb;}
+ if(nbr> 1024){ nbr/=1024; unit=gb;}
+
+ time = (float)(s1->tv_sec - s0->tv_sec)+((float)(s1->tv_nsec-s0->tv_nsec))/1E9;
+ if (data->cipher & BLOWFISH) { cipher ="blowfish"; size = data->blocks*BF_BLOCK_SIZE;}
+ else if (data->cipher & TWOFISH) { cipher ="twofish"; size = data->blocks*TF_BLOCK_SIZE; }
+ else if (data->cipher & AES) { cipher ="aes"; size = data->blocks*AES_BLOCK_SIZE; }
+ else if (data->cipher & DES) { cipher ="des"; size = data->blocks*DES_BLOCK_SIZE; }
+ else if (data->cipher & DES3_EDE) { cipher ="des3_ede"; size = data->blocks*DES3_EDE_BLOCK_SIZE; }
+ fprintf(stderr,"\n%s statistics :\n",PROG_NAME);
+ fprintf(stderr,"\nusing %s cipher with a buffer of %d bytes.\n",cipher, size);
+ fprintf(stderr,"\n%.3f %s read in %0.2f second(s) ",nbr,unit,time);
+ fprintf(stderr,"=> %.3f %s/sec.\n",nbr/time,unit);
+}
+
+static void usage(void)
+{
+ fprintf(stderr,"%s version %s, Copyright (C) 2004 Zurcher Jeremy\n",PROG_NAME,VERSION);
+ fprintf(stderr,"\tThis program is free software; you can redistribute it and/or modify\n");
+ fprintf(stderr,"\tit under the terms of the GNU General Public License as published by\n");
+ fprintf(stderr,"\tthe Free Software Foundation; either version 2 of the License, or\n");
+ fprintf(stderr,"\t(at your option) any later version.\n");
+ fprintf(stderr,"\tThis program is distributed in the hope that it will be useful,\n");
+ fprintf(stderr,"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n");
+ fprintf(stderr,"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
+ fprintf(stderr,"\tGNU General Public License for more details.\n\n");
+
+ fprintf(stderr,"usage : %s [-v] [-x] [-c cipher] [-n nbr_blocks]\n"
+ " [-s [ip]:[port]] [-d [ip]:[port]] [-b [ip]:[port]] [-S [ip]:[port]] key\n",PROG_NAME);
+ fprintf(stderr,"\t\t-v : verbose mode (statistics)\n");
+ fprintf(stderr,"\t\t-x : decrypt input (default is encrypt input)\n");
+ fprintf(stderr,"\t\t-c cipher : -c h for help (default = blowfish)\n");
+ fprintf(stderr,"\t\t-n nbr_blocks : nbr blocks in buffer (default = %d/CIPHER_BLOCK_SIZE)\n",BUFFER_LENGTH);
+ fprintf(stderr,"\t\t-s ip:port : local address to read from\n");
+ fprintf(stderr,"\t\t-d ip:port : distant address to write to\n");
+ fprintf(stderr,"\t\t-b ip:port : local address used for distant connection (use with -d option)\n");
+ fprintf(stderr,"\t\t-S ip:port : distant address to accept connection from (use with -s option)\n");
+ fprintf(stderr,"\t\t key : symetric secret key (see '-c h' for tips about key length)\n");
+ fprintf(stderr,"\t\t MUST be the last argument of the command line.\n");
+ fprintf(stderr,"\n");
+ fprintf(stderr,"\twithout -s option reads input from stdin.\n");
+ fprintf(stderr,"\twithout -d option writes output to stdout.\n");
+ fprintf(stderr,"\twithout -S option accept connection from 'the first one'.\n");
+ fprintf(stderr,"\n");
+ fprintf(stderr,"\tif no ip is provided with s, d, b or S option, hostname is resolved and used.\n");
+ fprintf(stderr,"\tif no port is provided with s, d, b or S option %d is used.\n",DEFAULT_PORT);
+ fprintf(stderr,"\n");
+ fprintf(stderr,"\texample:\n\t\t%s -s :5000 -S 10.10.10.10:200 -d 10.10.10.10: -b : my_secret_key\n",PROG_NAME);
+ fprintf(stderr,"\t\twill listen on hostname:5000 for incoming data from 10.10.10.10:200, \n");
+ fprintf(stderr,"\t\tencrypt it and send it to 10.10.10.10:%d through hostname:%d. \n",DEFAULT_PORT,DEFAULT_PORT);
+ fprintf(stderr,"\n");
+ exit(1);
+}
+
+static void usage_cipher(void)
+{
+ fprintf(stderr,"available ciphers :\n");
+ fprintf(stderr,"\t0 : _Blowfish : A 64-Bit Block Cipher_ by Bruce Schneier...\n");
+ fprintf(stderr,"\t1 : _Towfish : A 128-Bit Block Cipher_ by Bruce Schneier... (keylength : 16,24,32)\n");
+ fprintf(stderr,"\t2 : _aes : A 128-Bit Block Cipher_ known as Rijndael... (keylength : 16,24,32)\n");
+ fprintf(stderr,"\t3 : _des : A 64-Bit BLock Cipher_ improvement of Lucifer from IBM.. (keylength : 56)\n");
+ fprintf(stderr,"\t4 : _des3_ede : Tripple des C = des_enc(des_dec(des_enc(M)))\n");
+ fprintf(stderr,"\tnext to come : ??\n\n");
+ exit(1);
+}
+
+static void init_data(struct cryptot_st *data)
+{
+ data->key = NULL;
+ data->buffer = NULL;
+ data->size = -1;
+ data->blocks = -1;
+ data->cipher = DEFAULT_CIPHER;
+ data->check_accept = 0;
+ data->in_fd = 0;
+ data->out_fd = 1;
+ data->src_port = DEFAULT_PORT;
+ data->dist_port = DEFAULT_PORT;
+ data->local_port = DEFAULT_PORT;
+ data->src_ip[0] = data->src_ip[1] = data->src_ip[2] = data->src_ip[3] = 0;
+ data->dist_ip[0] = data->dist_ip[1] = data->dist_ip[2] = data->dist_ip[3] = 0;
+ data->local_ip[0] = data->local_ip[1] = data->local_ip[2] = data->local_ip[3] = 0;
+}
+
+/* update cipher param */
+static void change_cipher(unsigned int *cipher, unsigned long param)
+{
+ *cipher &= DECRYPT;
+ if(param==0){ *cipher |= BLOWFISH; return ; }
+ if(param==1){ *cipher |= TWOFISH; return; }
+ if(param==2){ *cipher |= AES; return; }
+ if(param==3){ *cipher |= DES; return; }
+ if(param==4){ *cipher |= DES3_EDE; return; }
+ fprintf(stderr,"%s : unknown cipher.\n",PROG_NAME);
+ exit(1);
+}
+
+/* set ip to localhost if == 0:0:0:0 */
+static void resolve_ip(char *ip)
+{
+ char hostname[HOSTLEN];
+ struct hostent *hp;
+
+ if(ip[0] == ip[1] && ip[1] == ip[2] && ip[2] == ip[3] && ip[3] == 0){
+ if(gethostname(hostname,HOSTLEN)==-1){
+ fprintf(stderr,"%s error ",PROG_NAME);
+ perror("gethostname "); exit(1);
+ }
+ if((hp = gethostbyname(hostname))==NULL){
+ fprintf(stderr,"%s : can't resolve %s, ",PROG_NAME,hostname);
+ herror("\tgethostbyname "); exit(1);
+ }
+ memcpy(ip,hp->h_addr,4);
+ }
+}
+
+
+/* if ip is 0:0:0:0 use localhost, bind to ip/port call listen if required */
+static int bind_to(char *ip, int port, int listen)
+{
+ int socket;
+
+ if((socket = socket_tcp(1))==-1) { fprintf(stderr,"%s error in ",PROG_NAME); perror("socket_tcp "); exit(1); }
+
+ if(socket_bind4(socket,ip,port)==-1) {
+ fprintf(stderr,"%s : unable to bind to %03d.%03d.%03d.%03d:%d",PROG_NAME,NIPQUAD(*ip),port);
+ perror("\tsocket_bind "); exit(1);
+ }
+
+ if(listen) if(socket_listen(socket,20)==-1) {
+ fprintf(stderr,"%s error in ",PROG_NAME); perror("socket_listen "); exit(1);
+ }
+
+ return socket;
+}
+
+/* compute blocks if == -1, allocate buffer, set size */
+static char* allocate_buffer(unsigned int cipher, unsigned int *blocks, unsigned int *size)
+{
+ char *buffer = NULL;
+ int tmp = *blocks;
+
+ if(tmp==-1){
+ if(cipher & BLOWFISH) tmp = BUFFER_LENGTH/BF_BLOCK_SIZE;
+ else if(cipher & TWOFISH) tmp = BUFFER_LENGTH/TF_BLOCK_SIZE;
+ else if(cipher & AES) tmp = BUFFER_LENGTH/AES_BLOCK_SIZE;
+ else if(cipher & DES) tmp = BUFFER_LENGTH/DES_BLOCK_SIZE;
+ else if(cipher & DES3_EDE) tmp = BUFFER_LENGTH/DES3_EDE_BLOCK_SIZE;
+ buffer = (char*)malloc(BUFFER_LENGTH);
+ } else {
+ if(cipher & BLOWFISH) buffer = (char*)malloc(tmp*BF_BLOCK_SIZE);
+ else if(cipher & TWOFISH) buffer = (char*)malloc(tmp*TF_BLOCK_SIZE);
+ else if(cipher & AES) buffer = (char*)malloc(tmp*AES_BLOCK_SIZE);
+ else if(cipher & DES) buffer = (char*)malloc(tmp*DES_BLOCK_SIZE);
+ else if(cipher & DES3_EDE) buffer = (char*)malloc(tmp*DES3_EDE_BLOCK_SIZE);
+ }
+ if(buffer==NULL) { fprintf(stderr,"%s : not enough memory for buffer.\n",PROG_NAME); exit(1); }
+ if(cipher & BLOWFISH) *size = tmp * BF_BLOCK_SIZE;
+ else if(cipher & TWOFISH) *size = tmp * TF_BLOCK_SIZE;
+ else if(cipher & AES) *size = tmp * AES_BLOCK_SIZE;
+ else if(cipher & DES) *size = tmp * DES_BLOCK_SIZE;
+ else if(cipher & DES3_EDE) *size = tmp * DES3_EDE_BLOCK_SIZE;
+ *blocks = tmp;
+ return buffer;
+}
+
+static void c_encrypt(struct cryptot_st *data, int verbose)
+{
+ register unsigned int ret = 0;
+ register unsigned int reg = 0;
+ register unsigned int size = data->size;
+ register u8 *buffer = (u8*)data->buffer;
+
+ operation op;
+ int input, output;
+ crypto_buffer c_buffer;
+ struct timespec s0, s1;
+
+ input = data->in_fd;
+ output = data->out_fd;
+
+ if(output==1) op = &u8_unix_write;
+ else{
+ op = &u8_tcp_write;
+ connect_to_dist(output,data,verbose);
+ }
+ if(crypto_buffer_init(&c_buffer, output, op, data->blocks, data->cipher, (u8*)data->key, strlen(data->key))==-1){
+ fprintf(stderr,"%s : crypto_buffer_init_error. Check your key len. (try -c h)\n",PROG_NAME); exit(1);
+ }
+ /* now I'm ready to write */
+
+ if(input==0){
+ if(verbose){
+ clock_gettime(MY_CLOCK, &s0);
+ while((ret=read(input, buffer, size))>0){
+ reg += ret;
+ if(crypto_buffer_put(&c_buffer,buffer,ret)==-1){
+ fprintf(stderr,"%s crypto_buffer_put error ",PROG_NAME); perror(""); exit(1);
+ }
+ }
+ }
+ else{
+ reg = (unsigned int)&c_buffer;
+ while((ret=read(input, buffer, size))>0)
+ if(crypto_buffer_put((crypto_buffer*)reg,buffer,ret)==-1){
+ fprintf(stderr,"%s crypto_buffer_put error ",PROG_NAME); perror(""); exit(1);
+ }
+ }
+ } else {
+ reg = wait_connection(input,data,verbose);
+ if(verbose){
+ clock_gettime(MY_CLOCK, &s0);
+ while((ret=recv(reg, buffer, size, 0))>0){
+ reg += ret;
+ if(crypto_buffer_put(&c_buffer,buffer,ret)==-1){
+ fprintf(stderr,"%s crypto_buffer_put error ",PROG_NAME); perror(""); exit(1);
+ }
+ }
+ }
+ else{
+ reg = (unsigned int)&c_buffer;
+ while((ret=recv(reg, buffer, size, 0))>0)
+ if(crypto_buffer_put((crypto_buffer*)reg,buffer,ret)==-1){
+ fprintf(stderr,"%s crypto_buffer_put error ",PROG_NAME); perror(""); exit(1);
+ }
+ }
+ shutdown(reg,SHUT_RDWR);
+ close(reg); /* close client socket */
+ }
+ crypto_buffer_flush(&c_buffer);
+ if(ret==-1){ fprintf(stderr,"%s read error ",PROG_NAME); perror(""); exit(1); }
+ if(verbose) {
+ clock_gettime(MY_CLOCK, &s1);
+ do_stats(data, &s0, &s1, reg);
+ }
+}
+
+static void c_decrypt(struct cryptot_st *data, int verbose)
+{
+ register int n = 0;
+ register unsigned int ret = 0;
+ register unsigned int reg = 0;
+ register unsigned int size = data->size;
+ register u8 *buffer = (u8*)data->buffer;
+
+ operation op;
+ int input, output;
+ crypto_buffer c_buffer;
+ struct timespec s0, s1;
+
+ input = data->in_fd;
+ output = data->out_fd;
+
+ if(input==0) op = &u8_unix_read;
+ else{
+ op = &u8_tcp_read;
+ input = wait_connection(input,data,verbose);
+ }
+ if(crypto_buffer_init(&c_buffer, input, op, data->blocks, data->cipher, (u8*)data->key, strlen(data->key))==-1){
+ fprintf(stderr,"%s : crypto_buffer_init_error. Check your key len. (try -c ?)\n",PROG_NAME); exit(1);
+ }
+ /* now I'm ready to read */
+
+ if(output==1){
+ if(verbose){
+ clock_gettime(MY_CLOCK, &s0);
+ while((ret=crypto_buffer_get(&c_buffer, buffer, size))>0){
+ reg += ret;
+ n = write(output, buffer, ret);
+ }
+ }
+ else{
+ reg = (unsigned int)&c_buffer;
+ while((ret=crypto_buffer_get(&c_buffer, buffer, size))>0)
+ n = write(output, buffer, ret);
+ }
+ } else {
+ connect_to_dist(output,data,verbose);
+ if(verbose){
+ clock_gettime(MY_CLOCK, &s0);
+ while((ret=crypto_buffer_get(&c_buffer, buffer, size))>0){
+ reg += ret;
+ if(send(output, buffer, ret, MSG_CONFIRM)==-1){
+ fprintf(stderr,"%s send error ",PROG_NAME); perror(""); exit(1);
+ }
+ }
+ }
+ else{
+ reg = (unsigned int)&c_buffer;
+ while((ret=crypto_buffer_get(&c_buffer, buffer, size))>0)
+ if(send(output, buffer, ret, MSG_CONFIRM)==-1){
+ fprintf(stderr,"%s send error ",PROG_NAME); perror(""); exit(1);
+ }
+ }
+
+ }
+ if(input!=0) { shutdown(input,SHUT_RDWR); close(input); } /* close client socket */
+ if(ret==-1){ fprintf(stderr,"%s read error ",PROG_NAME); perror(""); exit(1); }
+ if(verbose) {
+ clock_gettime(MY_CLOCK, &s1);
+ do_stats(data, &s0, &s1, reg);
+ }
+}
+
+static void argument_error(char opt, int wrong)
+{
+ if(wrong) fprintf(stderr,"%s : -%c option, wrong argument.\n",PROG_NAME,opt);
+ else fprintf(stderr,"%s : -%c option, argument missing.\n",PROG_NAME,opt);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ /* general */
+ int ret;
+ char *tmp;
+ unsigned long param;
+ unsigned int verbose = 0;
+ char bind_ip[4];
+ unsigned int bind_port;
+
+ /* crypto */
+ struct cryptot_st data;
+
+ init_data(&data);
+ bind_ip[0] = bind_ip[1] = bind_ip[2] = bind_ip[3] = 0;
+ bind_port = DEFAULT_PORT;
+
+ if(!--argc) usage();
+ ++argv;
+ while(argc--){
+ if((*argv)[0]=='-'){
+ if((*argv)[1]=='v') verbose = 1;
+
+ else if((*argv)[1]=='x') data.cipher|=DECRYPT;
+
+ else if((*argv)[1]=='n') {
+ if(!argc--) argument_error('n',0);
+ ret=scan_ulong(*(++argv),&param);
+ if(!ret || (*argv)[ret]) argument_error('n',1);
+ data.blocks = (unsigned int)param;
+ }
+
+ else if((*argv)[1]=='c') {
+ if(!argc--) argument_error('c',0);
+ if(*(*(++argv))=='h') usage_cipher();
+ ret=scan_ulong(*argv,&param);
+ if(!ret || (*argv)[ret])argument_error('c',1);
+ change_cipher(&data.cipher,param);
+ }
+
+ else if((*argv)[1]=='s') {
+ if(!argc--) argument_error('s',0);
+ ret=ipv4_scan(*(++argv),data.local_ip);
+ tmp = &(*argv)[ret];
+ if(*tmp++!=':') argument_error('s',1);
+ ret=scan_ulong(tmp,&param);
+ if(ret) data.local_port = (unsigned int)param;
+ if(*(tmp+ret)) argument_error('s',1);
+ data.in_fd = -1;
+ }
+
+ else if((*argv)[1]=='b') {
+ if(!argc--) argument_error('b',0);
+ ret=ipv4_scan(*(++argv),bind_ip);
+ tmp = &(*argv)[ret];
+ if(*tmp++!=':') argument_error('b',1);
+ ret=scan_ulong(tmp,&param);
+ if(ret) bind_port = (unsigned int)param;
+ if(*(tmp+ret)) argument_error('b',1);
+ }
+
+ else if((*argv)[1]=='d') {
+ if(!argc--) argument_error('d',0);
+ ret=ipv4_scan(*(++argv),data.dist_ip);
+ tmp = &(*argv)[ret];
+ if(*tmp++!=':') argument_error('d',1);
+ ret=scan_ulong(tmp,&param);
+ if(ret) data.dist_port = (unsigned int)param;
+ if(*(tmp+ret)) argument_error('d',1);
+ data.out_fd = -1;
+ }
+
+ else if((*argv)[1]=='S') {
+ if(!argc--) argument_error('S',0);
+ ret=ipv4_scan(*(++argv),data.src_ip);
+ tmp = &(*argv)[ret];
+ if(*tmp++!=':') argument_error('S',1);
+ ret=scan_ulong(tmp,&param);
+ if(ret) data.src_port = (unsigned int)param;
+ if(*(tmp+ret)) argument_error('S',1);
+ data.check_accept = 1;
+ }
+ else usage();
+ }
+ else { data.key = *argv; break; }
+ argv++;
+ }
+ if(!data.key) usage();
+
+ /* if ip is 0:0:0:0 call gethostname and gethostbyname */
+ if(data.in_fd != 0) resolve_ip(data.local_ip);
+ if(data.out_fd != 1){ resolve_ip(data.dist_ip); resolve_ip(bind_ip); }
+ if(data.in_fd != 0 && data.check_accept) resolve_ip(data.src_ip);
+
+ /* if input AND output have been changed, check that local != bind AND local != distant */
+ if(data.in_fd != 0 && data.out_fd != 1){
+ if(data.local_port == bind_port && !memcmp(data.local_ip,bind_ip,4)){
+ fprintf(stderr,"%s : trying to bind twice to same address; use -b option.\n",PROG_NAME);
+ exit(1);
+ }
+ if(data.local_port == data.dist_port && !memcmp(data.local_ip,data.dist_ip,4)){
+ fprintf(stderr,"%s : trying to read from output, you crazy !\n",PROG_NAME);
+ exit(1);
+ }
+ }
+
+ if(data.in_fd != 0) data.in_fd = bind_to(data.local_ip, data.local_port, 1); /* bind and listen */
+ if(data.out_fd != 1) data.out_fd = bind_to(bind_ip, bind_port, 0); /* bind */
+
+ data.buffer = allocate_buffer(data.cipher, &data.blocks, &data.size); /* allocate buffer and set blocks & size */
+
+#ifdef _DEBUG_
+ fprintf(stderr,"user defind aprameters :\n");
+ fprintf(stderr,"\tcipher : %d\n",data.cipher);
+ fprintf(stderr,"\tblocks : %d\n",data.blocks);
+ fprintf(stderr,"\tsize : %d\n",data.size);
+ fprintf(stderr,"\tkey : %s\n",data.key);
+ fprintf(stderr,"\tlocal %03d.%03d.%03d.%03d:%d\n",
+ NIPQUAD(data.local_ip),data.local_port);
+ fprintf(stderr,"\tdist %03d.%03d.%03d.%03d:%d\n",
+ NIPQUAD(data.dist_ip),data.dist_port);
+ fprintf(stderr,"\tbind %03d.%03d.%03d.%03d:%d\n",
+ NIPQUAD(bind_ip),bind_port);
+ fprintf(stderr,"\tsrc %03d.%03d.%03d.%03d:%d\n",
+ NIPQUAD(src_ip),src_port);
+#endif
+
+ if(verbose){
+ fprintf(stderr,"%s : running in verbose mode:\n",PROG_NAME);
+ if(data.in_fd !=0){
+ socket_local4(data.in_fd,data.local_ip,&data.local_port);
+ fprintf(stderr,"%s : reading from : %03d.%03d.%03d.%03d:%d\n",
+ PROG_NAME,NIPQUAD(data.local_ip),data.local_port);
+ if(data.check_accept) fprintf(stderr,"%s : accept connection from : %03d.%03d.%03d.%03d:%d\n",
+ PROG_NAME,NIPQUAD(data.src_ip),data.src_port);
+ else fprintf(stderr,"%s : accept connection from anywhere.\n",PROG_NAME);
+ }
+ else fprintf(stderr,"%s : reading from stdin\n",PROG_NAME);
+ if(data.out_fd !=1){
+ socket_local4(data.out_fd,data.local_ip,&data.local_port);
+ fprintf(stderr,"%s : writing through to : %03d.%03d.%03d.%03d:%d\n",
+ PROG_NAME,NIPQUAD(data.local_ip),data.local_port);
+ }
+ else fprintf(stderr,"%s : writing to stdout\n",PROG_NAME);
+ }
+
+ if(data.cipher&DECRYPT){
+ c_decrypt(&data,verbose);
+ }
+ else{
+ c_encrypt(&data,verbose);
+ }
+
+ /* close sockets */
+ if(data.in_fd !=0) close(data.in_fd);
+ if(data.out_fd !=0) close(data.out_fd);
+
+ return 0;
+}