|
|
@@ -1,7 +1,9 @@ |
|
|
|
/* notre passerelle TCP IPv4 */ |
|
|
|
/* Notre passerrelle TCP IPv4 */ |
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <string.h> |
|
|
|
#include <strings.h> |
|
|
|
#include <stdint.h> |
|
|
|
#include <unistd.h> |
|
|
|
#include <sys/types.h> |
|
|
@@ -9,315 +11,348 @@ |
|
|
|
#include <fcntl.h> |
|
|
|
#include <sys/socket.h> |
|
|
|
#include <arpa/inet.h> |
|
|
|
#include <netdb.h> |
|
|
|
#include <signal.h> |
|
|
|
#include <sys/wait.h> |
|
|
|
#include <netdb.h> |
|
|
|
#include <pthread.h> |
|
|
|
|
|
|
|
#include "chiffre.h" |
|
|
|
#include "pass.h" |
|
|
|
|
|
|
|
/* les variables globales */ |
|
|
|
int RUN=1; /* Indice qui permet de stopper en le mettant a zero */ |
|
|
|
int Chiff=0; /* =0 rien; =1 chiff. distant =-1 chiff. local */ |
|
|
|
in_port_t PORTL, PORTD; /* au format du reseau !! */ |
|
|
|
uint32_t ADDRD; /* adressse distante au format du reseau */ |
|
|
|
long long CLE = 0xABCD1276FA8745EC; |
|
|
|
/* Variables globales */ |
|
|
|
|
|
|
|
int RUN = 1; // booléen pour la boucle d'acceptation |
|
|
|
int Chiff = 0; // valeur pour l'option de chiffrement, -1 pour local, 1 pour distant, 0 pour rien |
|
|
|
in_port_t PORTL, PORTD; // ports distant et local au format du réseau ! |
|
|
|
uint32_t ADDRD; // adresse distante au format réseau |
|
|
|
int SidLoc, SidDist; // variables globales des deux taches de transfert |
|
|
|
|
|
|
|
|
|
|
|
/* Fonction qui agit en tant que handler pour signal() */ |
|
|
|
void interrupt(int S) |
|
|
|
{ |
|
|
|
switch(S) { |
|
|
|
case SIGCHLD : |
|
|
|
while (waitpid(-1,NULL,WNOHANG) != -1); |
|
|
|
break; |
|
|
|
case SIGINT: |
|
|
|
case SIGTERM: |
|
|
|
fprintf(stderr,"Arret de la passerelle !\n"); |
|
|
|
exit(0); |
|
|
|
default: |
|
|
|
fprintf(stderr,"Recu signal %d !?!?\n",S); |
|
|
|
} |
|
|
|
return; |
|
|
|
switch (S) { |
|
|
|
case SIGCHLD: |
|
|
|
while (waitpid(-1, NULL, WNOHANG) != -1); |
|
|
|
break; |
|
|
|
case SIGINT: |
|
|
|
RUN = 0; |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
break; |
|
|
|
case SIGTERM: |
|
|
|
fprintf(stderr, "Arret de la passerelle !\n"); |
|
|
|
exit(0); |
|
|
|
break; |
|
|
|
default: |
|
|
|
fprintf(stderr, "Reçu signal %d !?!\n", S); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* la structure sockaddr_in */ |
|
|
|
struct sockaddr_in Sin = { AF_INET }; /* Le reste de egal à 0 !! */ |
|
|
|
|
|
|
|
/* fct qui fabrique un IP v4 au format reseau |
|
|
|
exemple : makip4(127,0,0,1); */ |
|
|
|
uint32_t makip4(int a, int b, int c, int d) |
|
|
|
/* Fonction qui traduit une adresse IPv4 en chaîne de caractères xxx.xxx.xxx.xxx */ |
|
|
|
char *adip(uint32_t A) |
|
|
|
{ |
|
|
|
uint32_t A; |
|
|
|
char *p; |
|
|
|
p = (char *)&A; |
|
|
|
*p++ = (unsigned char)a; |
|
|
|
*p++ = (unsigned char)b; |
|
|
|
*p++ = (unsigned char)c; |
|
|
|
*p = (unsigned char)d; |
|
|
|
//return htonl(A); |
|
|
|
return A; |
|
|
|
} |
|
|
|
// 255.255.255.255 par exemple = 15 char + '\0' = 16 |
|
|
|
static char buffer[16]; |
|
|
|
|
|
|
|
/* fct qui traduit une adresse IP V4 en chaine de caractere xxx.xxx.xxx.xxx */ |
|
|
|
char * adip(uint32_t A) |
|
|
|
{ |
|
|
|
static char b[16]; |
|
|
|
sprintf(b,"%d.%d.%d.%d", (int)((A>>24)& 0xFF), (int)((A>>16)& 0xFF), (int)((A>>8)& 0xFF), (int)(A & 0xFF)); |
|
|
|
return b; |
|
|
|
} |
|
|
|
sprintf(buffer, "%d.%d.%d.%d", |
|
|
|
(int) ((A>>24) & 0xFF), |
|
|
|
(int) ((A>>16) & 0xFF), |
|
|
|
(int) ((A>>8) & 0xFF), |
|
|
|
(int) (A & 0xFF) |
|
|
|
); |
|
|
|
|
|
|
|
int readNbc(int fd, char*b, int t) |
|
|
|
{ |
|
|
|
char * d; |
|
|
|
int n, T=t; |
|
|
|
#ifdef TRACESP |
|
|
|
printf(" readNbc %d octets !\n",t); |
|
|
|
#endif |
|
|
|
d=b; |
|
|
|
while(T>0) { |
|
|
|
if ((n=read(fd,d,T)) == -1) return -1; |
|
|
|
d+=n; |
|
|
|
T-=n; |
|
|
|
} |
|
|
|
return 0; |
|
|
|
return buffer; |
|
|
|
} |
|
|
|
|
|
|
|
int SidLoc, SidDist; /* variables globales des 2 taches de transfert */ |
|
|
|
|
|
|
|
/* gestion des cles a partir d'un fichier externe */ |
|
|
|
char *NFCLE="/tmp/clepass"; |
|
|
|
/* ATTENTION choisir LCLE tel que = 8*n !!! */ |
|
|
|
#define LCLE 8192 /* 8 ko => cle de 65536 bits !! */ |
|
|
|
char BCLE[LCLE]; /* buffer contenant la cle */ |
|
|
|
|
|
|
|
/* on suppose dans tout le code que la fct de chiffrement est telle que |
|
|
|
fchiffre(fchiffre(buf)) = buf !! autrement dit qu'elle est involutive ! */ |
|
|
|
void fchiffre2(char * b, int l, int ori) /* travaille avec BCLE */ |
|
|
|
/* Fontion qui fabrique un IPv4 au format réseau */ |
|
|
|
uint32_t makeip4(int a, int b, int c, int d) |
|
|
|
{ |
|
|
|
long long *d, *f, *c, *fc; |
|
|
|
d=(long long*)b; |
|
|
|
f=(long long*)(b+l); |
|
|
|
c=(long long *)BCLE; |
|
|
|
fc=(long long *)(BCLE+LCLE); |
|
|
|
/* le chiffrement avec xor */ |
|
|
|
while (d<f) { |
|
|
|
*d++ ^= *c++; /* equiv. *d ^= *c; d++; c++; */ |
|
|
|
if (c==fc) c=(long long *)BCLE; |
|
|
|
} |
|
|
|
return; /* pour l'instant ne fait rien !! */ |
|
|
|
} |
|
|
|
// exemple : makeip4(127,0,0,1); |
|
|
|
uint32_t addresse; |
|
|
|
char *p; |
|
|
|
p = (char *) &addresse; |
|
|
|
*p++ = (unsigned char) a; |
|
|
|
*p++ = (unsigned char) b; |
|
|
|
*p++ = (unsigned char) c; |
|
|
|
*p = (unsigned char) d; |
|
|
|
|
|
|
|
int initCle(void) |
|
|
|
{ |
|
|
|
int fd; |
|
|
|
if ((fd = open(NFCLE,O_RDONLY)) == -1) return -1; |
|
|
|
if (read(fd,BCLE, LCLE) != LCLE) return -1; |
|
|
|
close(fd); |
|
|
|
return 0; |
|
|
|
return addresse; |
|
|
|
} |
|
|
|
|
|
|
|
void fchiffre(char * b, int l, int ori) /* travaille avec CLE de 64 bits */ |
|
|
|
/* Fonction qui lit taille octets à la fois */ |
|
|
|
int readNbc(int fd, char *buffer, int taille) |
|
|
|
{ |
|
|
|
long long *d, *f; |
|
|
|
d=(long long*)b; |
|
|
|
f=(long long*)(b+l); |
|
|
|
/* le chiffrement avec xor */ |
|
|
|
while (d<f) *d++ ^= CLE; |
|
|
|
#ifdef TRACECH |
|
|
|
if (ori==0) { /* le thread L -> D */ |
|
|
|
if (Chiff==1) printf("Chiffrement l=%d vers %d !\n",l,ntohs(PORTD)); |
|
|
|
else printf("Dechiffrement l=%d depuis %d !\n",l,ntohs(PORTL)); |
|
|
|
} else { /* le fils D -> L */ |
|
|
|
if (Chiff==1) printf("Dechiffrement l=%d depuis %d !\n",l,ntohs(PORTD)); |
|
|
|
else printf("Chiffrement l=%d vers %d !\n",l,ntohs(PORTL)); |
|
|
|
} |
|
|
|
char *debut; |
|
|
|
int n, T = taille; |
|
|
|
|
|
|
|
#ifdef TRACE_SP |
|
|
|
printf("readNbc %d octets !\n", taille); |
|
|
|
#endif |
|
|
|
return; /* pour l'instant ne fait rien !! */ |
|
|
|
|
|
|
|
debut = buffer; |
|
|
|
while (T > 0) { |
|
|
|
if ((n = read(fd, debut, T)) == -1) return -1; |
|
|
|
debut += n; |
|
|
|
T -= n; |
|
|
|
} |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* la fonction du thread qui lit le port local et ecrit vers le port distant */ |
|
|
|
void * fct_th(void * p) |
|
|
|
/* Fonction du thread qui lit le port local et écrit vers le port distant */ |
|
|
|
void *fct_th(void *p) |
|
|
|
{ |
|
|
|
int n; |
|
|
|
uint16_t lb; |
|
|
|
char buf[LBUF]; |
|
|
|
/* on s'occupe du transfert L -> D */ |
|
|
|
int n; |
|
|
|
uint16_t lb; |
|
|
|
char buf[LBUF]; |
|
|
|
|
|
|
|
/* On s'occupe du transfert local -> distant */ |
|
|
|
while (1) { |
|
|
|
/* lecture cote LOCAL */ |
|
|
|
if (Chiff == -1) { /* chiffrement cote local */ |
|
|
|
if (read(SidLoc,&lb,2)!=2) n=-1; |
|
|
|
else { |
|
|
|
n = (int)ntohs(lb); |
|
|
|
if (readNbc(SidLoc,buf,n) == -1) n=-1; |
|
|
|
fchiffre2(buf,n,0); |
|
|
|
} |
|
|
|
} else |
|
|
|
n=read(SidLoc,buf,LBUF); |
|
|
|
/* Lecture côté local */ |
|
|
|
if (Chiff == -1) { // chiffrement côté local |
|
|
|
if (read(SidLoc, &lb, sizeof(lb)) != sizeof(lb)) n = -1; |
|
|
|
else { |
|
|
|
n = (int) ntohs(lb); |
|
|
|
if (readNbc(SidLoc, buf, n) == -1) n = -1; |
|
|
|
#ifdef XOR_SIMPLE |
|
|
|
chiffre_xor_simple(buf, n); |
|
|
|
#endif |
|
|
|
#ifdef XOR_FICHIER |
|
|
|
chiffre_xor_fichier(buf, n); |
|
|
|
#endif |
|
|
|
#ifdef PLAYFAIR |
|
|
|
chiffre_playfair(buf, n); |
|
|
|
#endif |
|
|
|
} |
|
|
|
} else n = read(SidLoc, buf, LBUF); |
|
|
|
if (n > 0) { |
|
|
|
/* ecriture cote DISTANT */ |
|
|
|
if (Chiff == 1) { |
|
|
|
#ifdef TRACESP |
|
|
|
printf(" writeNbc %d octets !\n",n); |
|
|
|
/* Ecriture côté distant */ |
|
|
|
if (Chiff == 1) { |
|
|
|
#ifdef TRACE_SP |
|
|
|
printf("writeNbc %d octets !\n", n); |
|
|
|
#endif |
|
|
|
fchiffre2(buf,n,0); |
|
|
|
lb = htons((uint16_t)n); |
|
|
|
write(SidDist,&lb,2); /* on envoie le nb d'octets du paquet */ |
|
|
|
} |
|
|
|
write(SidDist,buf,n); |
|
|
|
#ifdef XOR_SIMPLE |
|
|
|
chiffre_xor_simple(buf, n); |
|
|
|
#endif |
|
|
|
#ifdef XOR_FICHIER |
|
|
|
chiffre_xor_fichier(buf, n); |
|
|
|
#endif |
|
|
|
#ifdef PLAYFAIR |
|
|
|
chiffre_playfair(buf, n); |
|
|
|
#endif |
|
|
|
lb = htons((uint16_t) n); |
|
|
|
write(SidDist, &lb, sizeof(lb)); // On envoie le nombre d'octets du paquet |
|
|
|
} |
|
|
|
write(SidDist, buf, n); |
|
|
|
} |
|
|
|
if (n==-1) break; |
|
|
|
if (n == -1) break; |
|
|
|
} |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int liaison(int fd) /* il faut creer la passerelle pour le client */ |
|
|
|
/* Création de la passerelle pour le client */ |
|
|
|
int liaison(int fd) |
|
|
|
{ |
|
|
|
int sid,n ; |
|
|
|
uint16_t lb; |
|
|
|
struct sockaddr_in Sin = { AF_INET }; |
|
|
|
pthread_t thid; |
|
|
|
char buf[LBUF]; |
|
|
|
/* on est dans le cas du client qui veut se connecter au serveur */ |
|
|
|
/* fabrication de l'interface reseau en IP V4 */ |
|
|
|
SidLoc = fd; /* pour que le thread l'utilise */ |
|
|
|
if ((sid = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) { |
|
|
|
perror("socket"); return 1; |
|
|
|
int sid, n; |
|
|
|
uint16_t lb; |
|
|
|
struct sockaddr_in Sin; |
|
|
|
pthread_t thid; |
|
|
|
char buf[LBUF]; |
|
|
|
|
|
|
|
/* On est dans le cas du client qui veut se connecter au serveur */ |
|
|
|
|
|
|
|
/* Fabrication de l'interface réseau en IPv4 */ |
|
|
|
SidLoc = fd; // pour que le thread l'utilise |
|
|
|
if ((sid = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { |
|
|
|
perror("socket"); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
Sin.sin_family = AF_INET; |
|
|
|
Sin.sin_port = PORTD; |
|
|
|
Sin.sin_addr.s_addr = ADDRD; |
|
|
|
/* on fait la connexion */ |
|
|
|
if (connect(sid, (struct sockaddr*)&Sin, sizeof(Sin)) < 0) { |
|
|
|
perror("connect"); return 2; |
|
|
|
|
|
|
|
/* On fait la connexion */ |
|
|
|
if (connect(sid, (struct sockaddr *) &Sin, sizeof(Sin)) == -1) { |
|
|
|
perror("connect"); |
|
|
|
return 2; |
|
|
|
} |
|
|
|
/* on masque le signal SIGPIPE */ |
|
|
|
signal(SIGPIPE,SIG_IGN); |
|
|
|
/* la connexion est faite ! */ |
|
|
|
SidDist = sid; /* pour que le thread l'utilise */ |
|
|
|
/* creation du thread qui va se charger du transfert L -> D */ |
|
|
|
if (pthread_create(&thid,NULL,fct_th,NULL) !=0) { |
|
|
|
fprintf(stderr,"Erreur creation thread !\n"); |
|
|
|
close(fd); |
|
|
|
close(sid); |
|
|
|
return 3; |
|
|
|
|
|
|
|
/* On masque le signal SIGPIPE */ |
|
|
|
signal(SIGPIPE, SIG_IGN); |
|
|
|
|
|
|
|
/* La connexion est faite ! */ |
|
|
|
SidDist = sid; // pour que le thread l'utilise |
|
|
|
|
|
|
|
/* Création du thread qui va se charger du transfert local vers distant */ |
|
|
|
if (pthread_create(&thid, NULL, fct_th, NULL) != 0) { |
|
|
|
fprintf(stderr, "Erreur création thread !\n"); |
|
|
|
close(fd); |
|
|
|
close(sid); |
|
|
|
return 3; |
|
|
|
} |
|
|
|
/* on s'occupe du transfert D -> L */ |
|
|
|
|
|
|
|
/* On s'occupe du transfert distant -> local */ |
|
|
|
while (1) { |
|
|
|
if (Chiff == 1) { /* chiffrement cote distant */ |
|
|
|
if (read(sid,&lb,2)!=2) n=-1; |
|
|
|
else { |
|
|
|
n = (int)ntohs(lb); |
|
|
|
if (readNbc(sid,buf,n) == -1) n=-1; |
|
|
|
fchiffre2(buf,n,0); |
|
|
|
} |
|
|
|
} else n=read(sid,buf,LBUF); |
|
|
|
if (Chiff == 1) { // chiffrement côté distant |
|
|
|
if (read(sid, &lb, sizeof(lb)) != sizeof(lb)) n = -1; |
|
|
|
else { |
|
|
|
n = (int) ntohs(lb); |
|
|
|
if (readNbc(sid, buf, n) == -1) n = -1; |
|
|
|
#ifdef XOR_SIMPLE |
|
|
|
chiffre_xor_simple(buf, n); |
|
|
|
#endif |
|
|
|
#ifdef XOR_FICHIER |
|
|
|
chiffre_xor_fichier(buf, n); |
|
|
|
#endif |
|
|
|
#ifdef PLAYFAIR |
|
|
|
chiffre_playfair(buf, n); |
|
|
|
#endif |
|
|
|
} |
|
|
|
} else n = read(sid, buf, LBUF); |
|
|
|
if (n > 0) { |
|
|
|
if (Chiff==-1) { |
|
|
|
#ifdef TRACESP |
|
|
|
printf(" writeNbc %d octets !\n",n); |
|
|
|
if (Chiff == -1) { |
|
|
|
#ifdef TRACE_SP |
|
|
|
printf("writeNbc %d octets !\n", n); |
|
|
|
#endif |
|
|
|
#ifdef XOR_SIMPLE |
|
|
|
chiffre_xor_simple(buf, n); |
|
|
|
#endif |
|
|
|
#ifdef XOR_FICHIER |
|
|
|
chiffre_xor_fichier(buf, n); |
|
|
|
#endif |
|
|
|
#ifdef PLAYFAIR |
|
|
|
chiffre_playfair(buf, n); |
|
|
|
#endif |
|
|
|
fchiffre2(buf,n,1); |
|
|
|
lb = htons((uint16_t)n); |
|
|
|
write(fd,&lb,2); /* on envoie le nb d'octets du paquet */ |
|
|
|
} |
|
|
|
write(fd,buf,n); |
|
|
|
lb = htons((uint16_t) n); |
|
|
|
write(fd, &lb, sizeof(lb)); |
|
|
|
} |
|
|
|
write(fd, buf, n); |
|
|
|
} |
|
|
|
if (n==-1) break; |
|
|
|
if (n == -1) break; |
|
|
|
} |
|
|
|
|
|
|
|
close(fd); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
void finerr(char * N, int err) |
|
|
|
/* Message d'aide pour l'utilisateur */ |
|
|
|
void finerr(char *N, int err) |
|
|
|
{ |
|
|
|
fprintf(stderr,"%s : version %s\n",N,Version); |
|
|
|
fprintf(stderr,"Utilisation : %s -d|-l|-s port_local nom_ou_ip_serveur port_distant !\n",N); |
|
|
|
fprintf(stderr, "%s : version %s\n", N, Version); |
|
|
|
fprintf(stderr, "Utilisation : %s -d|-l|-s port_local nom_ou_ip_serveur port_distant\n", N); |
|
|
|
exit(err); |
|
|
|
} |
|
|
|
|
|
|
|
int main(int N, char *P[]) |
|
|
|
{ |
|
|
|
int sid, newsid, err; /* socket id = file descriptor */ |
|
|
|
struct sockaddr_in Srec; |
|
|
|
struct hostent *h; |
|
|
|
pid_t pid; |
|
|
|
long lg; |
|
|
|
|
|
|
|
signal(SIGCHLD,interrupt); |
|
|
|
signal(SIGINT,interrupt); |
|
|
|
signal(SIGTERM,interrupt); |
|
|
|
if (initCle()) { |
|
|
|
fprintf(stderr,"Erreur lecture ficher cle %s !!\n", NFCLE); |
|
|
|
return 1; |
|
|
|
int sid, new_sid, err; // socket id = file descriptor |
|
|
|
struct sockaddr_in Sin, Srec; |
|
|
|
struct hostent *host; |
|
|
|
pid_t pid; |
|
|
|
long lg; |
|
|
|
|
|
|
|
/* Récupération des éventuels signaux qu'on pourrait recevoir, et appel de la fonction interrupt() */ |
|
|
|
signal(SIGCHLD, interrupt); |
|
|
|
signal(SIGINT, interrupt); |
|
|
|
signal(SIGTERM, interrupt); |
|
|
|
|
|
|
|
#ifdef XOR_FICHIER |
|
|
|
if (init_cle_xor_fichier()) { |
|
|
|
fprintf(stderr, "Erreur lecture fichier clé : '%s' !\n", NFCLE); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
/* verification que l'on a bien 4 parametres et seult 4 ! */ |
|
|
|
if (N != 5) finerr(P[0],1); |
|
|
|
/* verification du 1er parametres */ |
|
|
|
if (P[1][0] != '-') finerr(P[0],2); |
|
|
|
if (strlen(P[1]) != 2) finerr(P[0],2); |
|
|
|
switch(P[1][1]) { |
|
|
|
case 'l': |
|
|
|
Chiff = -1; |
|
|
|
break; |
|
|
|
case 'd': |
|
|
|
Chiff = 1; |
|
|
|
break; |
|
|
|
case 's': |
|
|
|
Chiff = 0; |
|
|
|
break; |
|
|
|
default : |
|
|
|
finerr(P[0],2); |
|
|
|
#endif |
|
|
|
#ifdef PLAYFAIR |
|
|
|
init_table_chiffre(CLE_PLAYFAIR); |
|
|
|
#endif |
|
|
|
|
|
|
|
/* Vérification que l'on a bien 4 paramètres et seulement 4 */ |
|
|
|
if (N != 5) finerr(P[0], 1); |
|
|
|
|
|
|
|
/* Vérification du 1er paramètre */ |
|
|
|
if (P[1][0] != '-') finerr(P[0], 1); |
|
|
|
if (strlen(P[1]) != 2) finerr(P[0], 2); |
|
|
|
switch (P[1][1]) { |
|
|
|
case 'l': |
|
|
|
Chiff = -1; |
|
|
|
break; |
|
|
|
case 'd': |
|
|
|
Chiff = 1; |
|
|
|
break; |
|
|
|
case 's': |
|
|
|
Chiff = 0; |
|
|
|
break; |
|
|
|
default: |
|
|
|
finerr(P[0], 2); |
|
|
|
break; |
|
|
|
} |
|
|
|
PORTL = htons(atoi(P[2])); |
|
|
|
PORTD = htons(atoi(P[4])); |
|
|
|
if ((h=gethostbyname(P[3])) == NULL) { |
|
|
|
fprintf(stderr,"Erreur gethostbyname no %d !\n",h_errno); |
|
|
|
return 2; |
|
|
|
|
|
|
|
PORTL = htons(atoi(P[2])); |
|
|
|
PORTD = htons(atoi(P[4])); |
|
|
|
|
|
|
|
/* Récuperation de l'adresse */ |
|
|
|
if ((host = gethostbyname(P[3])) == NULL) { |
|
|
|
fprintf(stderr, "Erreur gethostbyname no %d !\n", h_errno); |
|
|
|
return 2; |
|
|
|
} |
|
|
|
bcopy((void*)(h->h_addr),(void*)(&ADDRD),h->h_length); |
|
|
|
bcopy((void*) (host->h_addr), (void*) (&ADDRD), host->h_length); |
|
|
|
|
|
|
|
/* fabrication de l'interface reseau en IP V4 */ |
|
|
|
if ((sid = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) { |
|
|
|
perror("socket"); return 5; |
|
|
|
/* Fabrication de l'interface réseau en IPv4 */ |
|
|
|
if ((sid = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { |
|
|
|
perror("socket"); |
|
|
|
return 5; |
|
|
|
} |
|
|
|
/* initialiser la structure sockaddr_in pour dire quel port on veut */ |
|
|
|
|
|
|
|
Sin.sin_family = AF_INET; |
|
|
|
Sin.sin_port = PORTL; |
|
|
|
/* Sin.sin_addr.s_addr = makip4(127,0,0,1); */ |
|
|
|
Sin.sin_addr.s_addr = makip4(0,0,0,0); |
|
|
|
/* puis faire un bind() pour s'attacher a ce port */ |
|
|
|
if (bind(sid,(struct sockaddr *)&Sin,sizeof(Sin)) == -1) { |
|
|
|
perror("bind"); return 3; |
|
|
|
Sin.sin_addr.s_addr = makeip4(0, 0, 0, 0); |
|
|
|
// Sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
|
|
|
|
|
|
|
/* Puis faire un bind() pour s'attacher à ce port */ |
|
|
|
/* La fonction bind est une fonction unique, aveugle à la structure qui va envoyer les données. Elle ne se soucie |
|
|
|
* pas de savoir si on va communiquer en IPv4 ou IPv6 par exemple. |
|
|
|
* La fonction bind prend donc en fait une structure générique, sockaddr. Dans cette structure elle lit sa_family, |
|
|
|
* qui lui indique qu'il s'agit d'IPv4. */ |
|
|
|
/* Pour faire la conversion des struct on fait un cast. */ |
|
|
|
if (bind(sid, (struct sockaddr *) &Sin, sizeof(Sin)) == -1) { |
|
|
|
perror("bind"); |
|
|
|
return 3; |
|
|
|
} |
|
|
|
|
|
|
|
/* on definit le nombre d'ecoutes simultannees */ |
|
|
|
/* On définit le nombre d'écoutes simultanées */ |
|
|
|
if (listen(sid, NBCLI) == -1) { |
|
|
|
perror("listen"); return 4; |
|
|
|
perror("listen"); |
|
|
|
return 4; |
|
|
|
} |
|
|
|
while(RUN) { /* on attend le clients locaux pour transmettre les donnees */ |
|
|
|
lg = sizeof(Sin); |
|
|
|
if ((newsid=accept(sid,(struct sockaddr *)&Srec, (socklen_t*)&lg))<0){ |
|
|
|
perror("accept"); |
|
|
|
} else { |
|
|
|
/* message pour informer qui se connecte */ |
|
|
|
|
|
|
|
/* On laisse le serveur accepter des connexions |
|
|
|
* A chaque connexion établie, le serveur crée un fils pour gérer celle-ci. */ |
|
|
|
while (RUN) { // on attend les clients locaux pour transmettre les données |
|
|
|
lg = sizeof(Sin); |
|
|
|
if ((new_sid = accept(sid, (struct sockaddr *) &Srec, (socklen_t *) &lg)) < 0) { |
|
|
|
perror("accept"); |
|
|
|
} else { |
|
|
|
#ifdef TRACE_1 |
|
|
|
printf("Connexion de %s !\n",adip(ntohl(Srec.sin_addr.s_addr))); |
|
|
|
printf("Connexion de %s !\n", adip(ntohl(Srec.sin_addr.s_addr))); |
|
|
|
#endif |
|
|
|
/* creation du processus dedie au client */ |
|
|
|
if ((pid = fork()) == -1) { |
|
|
|
perror("fork"); |
|
|
|
write(newsid,"Erreur passerelle !\n",18); |
|
|
|
} else { |
|
|
|
if (pid==0) { /* code du fils */ |
|
|
|
err=liaison(newsid);/* creation passerelle privee pour client */ |
|
|
|
if (err) printf("Erreur liaison %d !\n",err); |
|
|
|
return err; |
|
|
|
} |
|
|
|
/* suite du pere : ie passerelle principale */ |
|
|
|
} |
|
|
|
close(newsid); |
|
|
|
} |
|
|
|
|
|
|
|
/* Création d'un processus dédié au client */ |
|
|
|
if ((pid = fork()) == -1) { |
|
|
|
perror("fork"); |
|
|
|
write(new_sid, "Erreur passerelle !\n", 21); |
|
|
|
} else { |
|
|
|
if (pid == 0) { // code du fils |
|
|
|
err = liaison(new_sid); // Création de la passerelle privée pour le client |
|
|
|
if (err) fprintf(stderr, "Erreur liaison %d !\n", err); |
|
|
|
return err; |
|
|
|
} |
|
|
|
} |
|
|
|
close(new_sid); // On ferme le file descriptor qu'on vient de créer puisque c'est le fils qui s'en occupe |
|
|
|
} |
|
|
|
} |
|
|
|
return 0; /* fin OK */ |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |