/* déclaration des types de base */ #include /* constantes relatives aux domaines, types et protocoles */ #include /* constantes et structures propres au domaine INTERNET */ #include /* structures retournées par les fonctions de gestion de la base de données du réseau */ #include /* pour les entrées/sorties */ #include /* la lib standard */ #include /* pour le fork */ #include #include #include /* pour la manipulation des strings */ #include /* Taille du tableau d'int fourni au client */ #define SIZE_TAB 128 #define NB_SEP 65 #define NB_PAR_LIGNE 16 // printf("BEFORE: %p\n", __builtin_return_address(0)); // // DEBUT GESTION DES FILS // struct proc { int pid; int sock; struct proc *next; }; struct proc_list { int size; struct proc *first; }; struct proc_list new_list() { struct proc_list liste = {0, NULL}; return liste; } void add_proc(struct proc_list *l, int pid, int sock) { l->size++; struct proc *p = (struct proc *) malloc(sizeof(struct proc)); p->pid = pid; p->sock = sock; p->next = l->first; l->first = p; } int get_sock_and_remove_proc(struct proc_list *l, int pid) { int sock = -1; if (l->size == 0) { printf("Erreur : Liste vide.\n"); } else if (l->first->pid == pid) { struct proc *aux = l->first; l->size--; l->first = aux->next; sock = aux->sock; free(aux); } else { struct proc *aux = l->first; while (aux->next != NULL && aux->next->pid != pid) { aux = aux->next; } if (aux->next->pid == pid) { struct proc *aux2 = aux->next; l->size--; aux->next = aux2->next; sock = aux2->sock; free(aux2); } } return sock; } struct proc *get_first(struct proc_list *l) { struct proc *rt = NULL; if (l->size != 0) { rt = l->first; l->size--; l->first = rt->next; } return rt; } struct proc_list liste; // // FIN GESTION DES FILS // int main_sock; void handle_sigsegv(int signum) { fprintf(stderr, "Signal SIGSEGV (%d) received : SEG FAULT\n", signum); exit(134); // 134 est le code de retour habituel en cas de segfault } void handle_sigchild(int signum) { // Attente de l'arrêt du fils et récupération du code de retour int status; int pid = wait(&status); int retCode = WEXITSTATUS(status); // Récupération du socket int sock = get_sock_and_remove_proc(&liste, pid); // Envoi de l'info de Segfault au client if (retCode == 134) { char buf[40] = "SEGFAULT"; write(sock, buf, strlen(buf)); printf("SEGFAULT envoyé\n"); } // Fermeture du socket shutdown(sock, SHUT_RDWR); close(sock); } void handle_sigint(int signum) { // remove a handler for SIGCHLD in a part of your code if (signal(SIGCHLD, NULL) == SIG_ERR) { fprintf(stderr, "Could not install SIGSEGV handler"); exit(-1); } struct proc *rt = get_first(&liste); while (rt != NULL) { shutdown(rt->sock, SHUT_RDWR); close(rt->sock); kill(rt->pid, SIGINT); free(rt); rt = get_first(&liste); //printf("ON DETRUIT TOUT\n"); } shutdown(main_sock, SHUT_RDWR); close(main_sock); exit(3); } int min(int a, int b) { if (a < b) { return a; } else { return b; } } // affichage du nombre de connexions void print_nb_connexions(int nb_connexions) { if (nb_connexions == 1) { printf("Nouvelle connexion, 1ere connexion\n"); } else if (nb_connexions == 2) { printf("Nouvelle connexion, 2nd connexion\n"); } else { printf("Nouvelle connexion, %deme connexion\n", nb_connexions); } printf("L'adresse du nombre de connexions est : %p\n", &nb_connexions); } void print_ligne(int *ligne, int n) { printf("|"); int i; for (i = 0; i < n; i++) { printf(" %d |", ligne[i]); } printf("\n"); } void print_sep() { int i; for (i = 0; i < NB_SEP; i++) { printf("-"); } printf("\n"); } void print_tab(int *tab, int n) { print_sep(); int i; for (i = 0; i < n; i += NB_PAR_LIGNE) { print_ligne(&(tab[i]), min(n - i, NB_PAR_LIGNE)); print_sep(); } } // Fonction lancée a chaque fork void process(int sock) { // Tableau des datas du client int tab[SIZE_TAB]; // initialisation (tt a 0) int i; for (i = 0; i < SIZE_TAB; i++) { tab[i] = 0; } int quit = 0; while (quit == 0) { // récupération de l'input du client char buff[40] = "\0"; int nbBytesRead = read(sock, buff, 40); if (nbBytesRead == 0) { break; } char what; int param1; int param2; int param3; sscanf(buff, "%c.%d.%d.%d", &what, ¶m1, ¶m2, ¶m3); printf("%c.%d.%d.%d\n", what, param1, param2, param3); if (what == 'r') { char buff_envoi[40]; sprintf(buff_envoi, "%d", tab[param1]); send(sock, buff_envoi, strlen(buff_envoi), 0); } else if (what == 'w') { tab[param2] = param1; } else if (what == 'a') { tab[param1] = tab[param2] + tab[param3]; } else if (what == 's') { tab[param1] = tab[param2] - tab[param3]; } else if (what == 'm') { tab[param1] = tab[param2] * tab[param3]; } else if (what == 'd') { tab[param1] = tab[param2] / tab[param3]; } else if (what == 'l') { if (tab[param1] < tab[param2]) { send(sock, "1", 1, 0); } else { send(sock, "0", 1, 0); } } else if (what == 'e') { if (tab[param1] == tab[param2]) { send(sock, "1", 1, 0); } else { send(sock, "0", 1, 0); } } else if (what == 'p') { print_tab(tab, SIZE_TAB); } else { quit = -1; } } } // Fonction que l'on veut appeler en écrivant son adresse dans la pile void rop() { printf("Exploit successful!\n"); system("/bin/sh"); } int main(int argc, char *argv[]) { if (argc != 2) { printf("ERREUR : Usage : ./serveur N°Port\n"); exit(2); } // install a handler for SIGSEGV in a part of your code if (signal(SIGSEGV, &handle_sigsegv) == SIG_ERR) { fprintf(stderr, "Could not install SIGSEGV handler"); return -1; } // install a handler for SIGCHLD in a part of your code if (signal(SIGCHLD, &handle_sigchild) == SIG_ERR) { fprintf(stderr, "Could not install SIGCHLD handler"); return -1; } // install a handler for SIGINT in a part of your code if (signal(SIGINT, &handle_sigint) == SIG_ERR) { fprintf(stderr, "Could not install SIGINT handler"); return -1; } // On crée le socket local main_sock = socket(AF_INET, SOCK_STREAM, 0); if (main_sock == -1) { printf("ERREUR lors de la création du socket\n"); exit(1); } // On cree l'adresse du socket local struct sockaddr_in addr_local; int binder; addr_local.sin_family = AF_INET; addr_local.sin_port = htons(atoi(argv[1])); addr_local.sin_addr.s_addr = INADDR_ANY; // On bind l'adresse du socket créee avec le socket local binder = bind(main_sock, (struct sockaddr *) &addr_local, sizeof(struct sockaddr_in)); if (binder == -1) { perror("ERREUR lors du bind du socket"); exit(1); } // Initialisation file d'attente listen(main_sock, 100); // Variable de stockage de l'addresse emmeteur struct sockaddr_in addr_em; unsigned int longueur_addr_em = sizeof(struct sockaddr_in); // Initialisation de la liste des processus liste = new_list(); // On se met en état d'acceptation de connexion (et on crée un socket en // passant) int pid = 1; int nb_connexions = 0; printf("CTRL+C pour terminer\n"); printf("addresse de rop() : %ld\n", (long) &rop); while (pid != 0) { int sock_connexion = accept(main_sock, (struct sockaddr *) &addr_em, &longueur_addr_em); if (sock_connexion == -1) { printf("ERREUR lors de l'acceptation de la connexion\n"); exit(1); } else { nb_connexions++; } pid = fork(); if (pid == -1) { printf("ERREUR lors du fork\n"); exit(1); } else if (pid == 0) { process(sock_connexion); } else { add_proc(&liste, pid, sock_connexion); //printf("Processus %d created\n", pid); } } return 0; }