commit fca1caf5ea695a5ce9bb866f35a19feafd1cc54b Author: gasc Date: Sun Aug 22 13:28:14 2021 +0200 Importation du code depuis GitHub diff --git a/README.md b/README.md new file mode 100644 index 0000000..88689a4 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Tsocks (Computer science lab) +Here I share my own implementation of [Tsocks](http://tsocks.sourceforge.net/) in C carried out as part of the computer science work at INSA Toulouse. + diff --git a/tsock_v1_gasc_m.c b/tsock_v1_gasc_m.c new file mode 100644 index 0000000..c10b462 --- /dev/null +++ b/tsock_v1_gasc_m.c @@ -0,0 +1,274 @@ +/* librairie standard ... */ +#include +/* pour getopt */ +#include +/* déclaration des types de base */ +#include +/* constantes relatives aux domaines, types et protocoles */ +#include +/* constantes et structures propres au domaine UNIX */ +#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 +/* pour la gestion des erreurs */ +#include + +/* + TP AIPS + Version 1 - Fonctionnelle +*/ + +/////////////////////////////////////////////////////////// + +// Fonctions d'erreurs +/// Afficher l'usage et quitte +void err_args() { + printf("[!] Usage: cmd [-u][-p|-s][-n ##][-l ##]\n"); + exit(EXIT_FAILURE); +} + +/// Affiche erreur socket +void err_socks(){ + printf("\n[-] Erreur lors de la création/affectation du socket"); +} + +/// Affiche erreur connexion +void err_conn(){ + printf("\n[-] Erreur lors de la connexion serveur/client"); +} + +/////////////////////////////////////////////////////////// + + +// Given functions +void construire_message(char *message, char motif, int lg) { + int i; + for (i=0;ih_addr, hp->h_length); + servaddr.sin_port = PORT; + printf("Ok!\n"); + + printf("[+] Envoi des messages à %s:%d...\n", HOSTNAME, PORT); + + // TEST + char *pmesg = malloc(l_msg*sizeof(char)); + char c = 'a'; + + // Création des messages à envoyer et envoi + for (int i = 1; i <= nb_message; i++){ + construire_message(pmesg, c, l_msg); + afficher_message(pmesg, l_msg); + sendto(s_udp, + pmesg, + strlen(pmesg), + 0, + (const struct sockaddr *) &servaddr, + sizeof(servaddr) + ); + c++; + } + + return 0; +} + +int puit_UDP(int PORT, int nb_message, int l_msg) { + // Création du socket UDP + printf("[+] Création du socket local..."); + int s_udp = socket(AF_INET,SOCK_DGRAM, 0); + + if (s_udp == -1){ + err_socks(); + return 1; + } else printf("Ok!\n"); + + struct sockaddr_in servaddr, cliaddr; + memset(&servaddr, 0, sizeof(servaddr)); + memset(&cliaddr, 0, sizeof(cliaddr)); + + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = INADDR_ANY; + servaddr.sin_port = PORT; + + if ( bind(s_udp, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) { + err_socks(); + return 1; + } + printf("[+] Bind ok !\n"); + + int n; + int len; + int msg_count = 0; + char buffer[l_msg]; + + printf("[+] Waiting for messages...\n"); + + while (msg_count >= nb_message || nb_message != -1){ + n = recvfrom(s_udp, (char *)buffer, l_msg, + MSG_WAITALL, (struct sockaddr *) &cliaddr, + &len); + buffer[n] = '\0'; + printf("[>] Reception du message n°%d : %s\n", msg_count, buffer); + + n = 0; + msg_count++; + } + + + + return 0; +} + +////////////////////////////TCP///////////////////////////// + +int source_TCP(char *HOSTNAME, int PORT, int nb_message, int l_msg){ + + return 1; +} + +int puit_TCP(int PORT, int nb_message, int l_msg){ + + return 1; +} + +/////////////////////////////////////////////////////////// + +/// Main entry +int main (int argc, char **argv) +{ + int c; + extern char *optarg; + extern int optind; + int nb_message = -1; /* Nb de messages à envoyer ou à recevoir, par défaut : 10 en émission, infini en réception */ + int source = -1; /* 0 = puits, 1 = source */ + int tcp = 1; /* 0 = UDP, 1 = TCP */ + int l_msg = 30; /* longueur du message, en octet. Defaut : 30. */ + + while ((c = getopt(argc, argv, "pn:sul:")) != -1) { + switch (c) { + case 'p': + if (source == 1) { + err_args(); + } + source = 0; + break; + + case 's': + if (source == 0) { + err_args(); + } + source = 1; + break; + + case 'n': + nb_message = atoi(optarg); + break; + + case 'u': + tcp = 0; + break; + + case 'l': + l_msg = atoi(optarg); + + default: + err_args(); + break; + } + } + + int PORT = atoi(argv[argc-1]); + //PORT = htons(PORT); + + if (source == -1) { + err_args(); + } + + if (tcp) + printf("[+] On utilise le protocol TCP\n"); + else + printf("[+] On utilise le protocol UDP\n"); + + + char* HOSTNAME = ""; + if (source == 1){ + printf("[+] On est dans la source\n"); + HOSTNAME = argv[argc-2]; + } + else + printf("[+] On est dans le puit\n"); + + if (nb_message != -1) { + if (source == 1) + printf("[+] Nombre de tampons à envoyer : %d\n", nb_message); + else + printf("[+] Nombre de tampons à recevoir : %d\n", nb_message); + } else { + if (source == 1) { + nb_message = 10 ; + printf("[~] Nombre de tampons à envoyer = 10 par défaut\n"); + } + else + printf("[+] Nombre de tampons à envoyer = infini\n"); + } + + if (l_msg == 30) + printf("[~] Longueur des messages à envoyer/recevoir : 30 par défaut\n"); + else + printf("[+] Nombre de tampons à envoyer/recevoir : %d \n", l_msg); + + int s = 1; + + // Choose the right function + if (tcp){ + if (source) s = source_TCP(HOSTNAME, PORT, nb_message, l_msg); + else s = puit_TCP(PORT, nb_message, l_msg); + } + else { + if (source) s = source_UDP(HOSTNAME, PORT, nb_message, l_msg); + else s = puit_UDP(PORT, nb_message, l_msg); + } + + return s; +} + diff --git a/tsock_v2_gasc_m.c b/tsock_v2_gasc_m.c new file mode 100644 index 0000000..5407b4e --- /dev/null +++ b/tsock_v2_gasc_m.c @@ -0,0 +1,379 @@ +/* librairie standard ... */ +#include +/* pour getopt */ +#include +/* déclaration des types de base */ +#include +/* constantes relatives aux domaines, types et protocoles */ +#include +/* constantes et structures propres au domaine UNIX */ +#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 +/* pour la gestion des erreurs */ +#include + +/* + TP AIPS + Version 2 - FONCTIONNELLE +*/ + +/////////////////////////////////////////////////////////// + +// Fonctions d'erreurs +/// Afficher l'usage et quitte +void err_args() { + printf("[!] Usage: cmd [-u][-p|-s][-n ##][-l ##]\n"); + exit(EXIT_FAILURE); +} + +/// Affiche erreur socket +void err_socks(){ + printf("\n[-] Erreur lors de la création/affectation du socket\n"); +} + +/// Affiche erreur connexion +void err_conn(){ + printf("\n[-] Erreur lors de la connexion serveur/client\n"); +} + +/////////////////////////////////////////////////////////// + + +// Given functions +void construire_message(char *message, char motif, int lg) { + int i; + for (i=0;ih_addr, hp->h_length); + servaddr.sin_port = PORT; + printf("Ok!\n"); + + printf("[+] Envoi des messages à %s:%d...\n", HOSTNAME, PORT); + + // TEST + char *pmesg = malloc(l_msg*sizeof(char)); + char c = 'a'; + + // Création des messages à envoyer et envoi + for (int i = 1; i <= nb_message; i++){ + construire_message(pmesg, c, l_msg); + afficher_message(pmesg, l_msg); + sendto(s_udp, + pmesg, + strlen(pmesg), + 0, + (const struct sockaddr *) &servaddr, + sizeof(servaddr) + ); + c++; + if (c >= '{') c = 'a'; + } + + return 0; +} + +int puit_UDP(int PORT, int nb_message, int l_msg) { + // Création du socket UDP + printf("[+] Création du socket local..."); + int s_udp = socket(AF_INET,SOCK_DGRAM, 0); + + if (s_udp == -1){ + err_socks(); + return 1; + } else printf("Ok!\n"); + + struct sockaddr_in servaddr, cliaddr; + memset(&servaddr, 0, sizeof(servaddr)); + memset(&cliaddr, 0, sizeof(cliaddr)); + + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = INADDR_ANY; + servaddr.sin_port = PORT; + + if ( bind(s_udp, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) { + err_socks(); + return 1; + } + printf("[+] Bind ok !\n"); + + int n; + int len; + int msg_count = 0; + char buffer[l_msg]; + + printf("[+] Waiting for messages...\n"); + + while (msg_count >= nb_message || nb_message != -1){ + n = recvfrom(s_udp, (char *)buffer, l_msg, + MSG_WAITALL, (struct sockaddr *) &cliaddr, + &len); + buffer[n] = '\0'; + printf("[>] Reception du message n°%d : %s\n", msg_count, buffer); + + n = 0; + msg_count++; + } + + return 0; +} + +////////////////////////////TCP///////////////////////////// + +int source_TCP(char *HOSTNAME, int PORT, int nb_message, int l_msg){ + // Création du socket TCP + printf("[+] Création du socket local..."); + int s_tcp = socket(AF_INET,SOCK_STREAM, 0); + + if (s_tcp == -1){ + err_socks(); + return 1; + } else printf("Ok!\n"); + + // Création du socket distant + printf("[+] Création du socket distant..."); + struct sockaddr_in servaddr; + memset(&servaddr, 0, sizeof(servaddr)); + struct hostent *hp ; + + // Résolution du nom + if ((hp = gethostbyname(HOSTNAME)) == NULL) { + err_conn(); + return 1; + } + + // Creation de la struct du socket distant + servaddr.sin_family = AF_INET; + memcpy((char*)&(servaddr.sin_addr.s_addr), hp->h_addr, hp->h_length); + servaddr.sin_port = PORT; + printf("Ok!\n"); + + if (connect(s_tcp, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){ + err_conn(); + return 1; + } + + + printf("[+] Envoi des messages...\n"); + + // TEST + char *pmesg = malloc(l_msg*sizeof(char)); + char c = 'a'; + + // Création des messages à envoyer et envoi + for (int i = 1; i <= nb_message; i++){ + construire_message(pmesg, c, l_msg); + afficher_message(pmesg, l_msg); + if (write(s_tcp, pmesg, l_msg) < 0){ + err_conn(); + return 1; + } + c++; + if (c >= '{') c = 'a'; + } + + close(s_tcp); + + return 0; +} + +int puit_TCP(int PORT, int nb_message, int l_msg){ + // Création du socket TCP + printf("[+] Création du socket local..."); + int s_tcp = socket(AF_INET,SOCK_STREAM, 0); + + if (s_tcp == -1){ + err_socks(); + return 1; + } else printf("Ok!\n"); + + struct sockaddr_in servaddr, cliaddr; + memset(&servaddr, 0, sizeof(servaddr)); + memset(&cliaddr, 0, sizeof(cliaddr)); + + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = INADDR_ANY; + servaddr.sin_port = PORT; + + if (bind(s_tcp, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) { + err_socks(); + return 1; + } + printf("[+] Bind ok !\n"); + + if (listen(s_tcp, 5) != 0){ + err_conn(); + return 1; + } + printf("[+] Listening on port %d\n", PORT); + + int s_conn, l_recpt, msg_count = 1; + int lg_cliaddr = sizeof(cliaddr); + + if ((s_conn = accept(s_tcp, (struct sockaddr *)&cliaddr, &lg_cliaddr)) < 0){ + err_conn(); + return 1; + } + printf("[+] Connection accepted\n"); + + + int n; + char buffer[l_msg]; + + printf("[+] Waiting for messages...\n"); + + while (msg_count <= nb_message || nb_message == -1){ + if ((l_recpt = read(s_conn, buffer, sizeof(buffer))) < 0){ + err_conn(); + return 1; + } + if (l_recpt > 0){ + printf("[>] Reception du message n°%d : %s\n", msg_count, buffer); + + n = 0; + msg_count++; + bzero(buffer, l_msg); + } + } + + return 0; +} + +/////////////////////////////////////////////////////////// + +/// Main entry +int main (int argc, char **argv) +{ + int c; + extern char *optarg; + extern int optind; + int nb_message = -1; /* Nb de messages à envoyer ou à recevoir, par défaut : 10 en émission, infini en réception */ + int source = -1; /* 0 = puits, 1 = source */ + int tcp = 1; /* 0 = UDP, 1 = TCP */ + int l_msg = 30; /* longueur du message, en octet. Defaut : 30. */ + + while ((c = getopt(argc, argv, "pn:su")) != -1) { + switch (c) { + case 'p': + if (source == 1) { + err_args(); + } + source = 0; + break; + + case 's': + if (source == 0) { + err_args(); + } + source = 1; + break; + + case 'n': + nb_message = atoi(optarg); + break; + + case 'u': + tcp = 0; + break; + + default: + err_args(); + break; + } + } + + int PORT = atoi(argv[argc-1]); + //PORT = htons(PORT); + + if (source == -1) { + err_args(); + } + + if (tcp) + printf("[+] On utilise le protocol TCP\n"); + else + printf("[+] On utilise le protocol UDP\n"); + + + char* HOSTNAME = ""; + if (source == 1){ + printf("[+] On est dans la source\n"); + HOSTNAME = argv[argc-2]; + } + else + printf("[+] On est dans le puit\n"); + + if (nb_message != -1) { + if (source == 1) + printf("[+] Nombre de tampons à envoyer : %d\n", nb_message); + else + printf("[+] Nombre de tampons à recevoir : %d\n", nb_message); + } else { + if (source == 1) { + nb_message = 10 ; + printf("[~] Nombre de tampons à envoyer : 10 par défaut\n"); + } + else + printf("[+] Nombre de tampons à envoyer : infini\n"); + } + + if (l_msg == 30) + printf("[~] Longueur des messages à envoyer/recevoir : 30 par défaut\n"); + else + printf("[+] Nombre de tampons à envoyer/recevoir : %d \n", l_msg); + + int s = 1; + + // Choose the right function + if (tcp){ + if (source) s = source_TCP(HOSTNAME, PORT, nb_message, l_msg); + else s = puit_TCP(PORT, nb_message, l_msg); + } + else { + if (source) s = source_UDP(HOSTNAME, PORT, nb_message, l_msg); + else s = puit_UDP(PORT, nb_message, l_msg); + } + + return s; +} + diff --git a/tsock_v3_gasc_m.c b/tsock_v3_gasc_m.c new file mode 100644 index 0000000..fd8cb78 --- /dev/null +++ b/tsock_v3_gasc_m.c @@ -0,0 +1,387 @@ +/* librairie standard ... */ +#include +/* pour getopt */ +#include +/* déclaration des types de base */ +#include +/* constantes relatives aux domaines, types et protocoles */ +#include +/* constantes et structures propres au domaine UNIX */ +#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 +/* pour la gestion des erreurs */ +#include + +/* + TP AIPS + Version 3 alpha - NON COMPLETE +*/ + +/////////////////////////////////////////////////////////// + +// Fonctions d'erreurs +/// Afficher l'usage et quitte +void err_args() { + printf("[!] Usage: cmd [-u][-p|-s][-n ##][-l ##]\n"); + exit(EXIT_FAILURE); +} + +/// Affiche erreur socket +void err_socks(){ + printf("\n[-] Erreur lors de la création/affectation du socket\n"); +} + +/// Affiche erreur connexion +void err_conn(){ + printf("\n[-] Erreur lors de la connexion serveur/client\n"); +} + +/////////////////////////////////////////////////////////// + + +// Given functions +void construire_message(char *message, char motif, int lg, int numero) { + int i; + char str[5]; + for (i=0;i<5;++i) str[i] = '-'; + sprintf(str, "%5d", numero); + for (i=0;ih_addr_list[0], hp->h_length); + servaddr.sin_port = PORT; + printf("Ok!\n"); + + printf("[+] Envoi des messages à %s:%d...\n", HOSTNAME, PORT); + + // TEST + char *pmesg = malloc(l_msg*sizeof(char)); + char c = 'a'; + + // Création des messages à envoyer et envoi + for (int i = 1; i <= nb_message; i++){ + construire_message(pmesg, c, l_msg, i); + afficher_message(pmesg, l_msg); + sendto(s_udp, + pmesg, + strlen(pmesg), + 0, + (const struct sockaddr *) &servaddr, + sizeof(servaddr) + ); + c++; + if (c >= '{') c = 'a'; + } + + return 0; +} + +int puit_UDP(int PORT, int nb_message, int l_msg) { + // Création du socket UDP + printf("[+] Création du socket local..."); + int s_udp = socket(AF_INET,SOCK_DGRAM, 0); + + if (s_udp == -1){ + err_socks(); + return 1; + } else printf("Ok!\n"); + + struct sockaddr_in servaddr, cliaddr; + memset(&servaddr, 0, sizeof(servaddr)); + memset(&cliaddr, 0, sizeof(cliaddr)); + + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = INADDR_ANY; + servaddr.sin_port = PORT; + + if ( bind(s_udp, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) { + err_socks(); + return 1; + } + printf("[+] Bind ok !\n"); + + int n; + int len; + int msg_count = 0; + char buffer[l_msg]; + + printf("[+] Waiting for messages...\n"); + + while (msg_count >= nb_message || nb_message != -1){ + n = recvfrom(s_udp, (char *)buffer, l_msg, + MSG_WAITALL, (struct sockaddr *) &cliaddr, + &len); + buffer[n] = '\0'; + printf("[>] Reception du message n°%d : %s\n", msg_count, buffer); + + n = 0; + msg_count++; + } + + return 0; +} + +////////////////////////////TCP///////////////////////////// + +int source_TCP(char *HOSTNAME, int PORT, int nb_message, int l_msg){ + // Création du socket TCP + printf("[+] Création du socket local..."); + int s_tcp = socket(AF_INET,SOCK_STREAM, 0); + + if (s_tcp == -1){ + err_socks(); + return 1; + } else printf("Ok!\n"); + + // Création du socket distant + printf("[+] Création du socket distant..."); + struct sockaddr_in servaddr; + memset(&servaddr, 0, sizeof(servaddr)); + struct hostent *hp ; + + // Résolution du nom + if ((hp = gethostbyname(HOSTNAME)) == NULL) { + err_conn(); + return 1; + } + + // Creation de la struct du socket distant + servaddr.sin_family = AF_INET; + memcpy((char*)&(servaddr.sin_addr.s_addr), hp->h_addr_list[0], hp->h_length); + servaddr.sin_port = PORT; + printf("Ok!\n"); + + if (connect(s_tcp, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){ + err_conn(); + return 1; + } + + + printf("[+] Envoi des messages...\n"); + + // TEST + char *pmesg = malloc(l_msg*sizeof(char)); + char c = 'a'; + + // Création des messages à envoyer et envoi + for (int i = 1; i <= nb_message; i++){ + construire_message(pmesg, c, l_msg, i); + afficher_message(pmesg, l_msg); + if (write(s_tcp, pmesg, l_msg) < 0){ + err_conn(); + return 1; + } + c++; + if (c >= '{') c = 'a'; + } + + close(s_tcp); + + return 0; +} + +int puit_TCP(int PORT, int nb_message, int l_msg){ + // Création du socket TCP + printf("[+] Création du socket local..."); + int s_tcp = socket(AF_INET,SOCK_STREAM, 0); + + if (s_tcp == -1){ + err_socks(); + return 1; + } else printf("Ok!\n"); + + struct sockaddr_in servaddr, cliaddr; + memset(&servaddr, 0, sizeof(servaddr)); + memset(&cliaddr, 0, sizeof(cliaddr)); + + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = INADDR_ANY; + servaddr.sin_port = PORT; + + if (bind(s_tcp, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) { + err_socks(); + return 1; + } + printf("[+] Bind ok !\n"); + + if (listen(s_tcp, 5) != 0){ + err_conn(); + return 1; + } + printf("[+] Listening on port %d\n", PORT); + + int s_conn, l_recpt, msg_count = 1; + int lg_cliaddr = sizeof(cliaddr); + + if ((s_conn = accept(s_tcp, (struct sockaddr *)&cliaddr, &lg_cliaddr)) < 0){ + err_conn(); + return 1; + } + printf("[+] Connection accepted\n"); + + + int n; + char buffer[l_msg]; + + printf("[+] Waiting for messages...\n"); + + while (msg_count <= nb_message || nb_message == -1){ + if ((l_recpt = read(s_conn, buffer, sizeof(buffer))) < 0){ + err_conn(); + return 1; + } + if (l_recpt > 0){ + printf("[>] Reception du message n°%d : %s\n", msg_count, buffer); + + n = 0; + msg_count++; + bzero(buffer, l_msg); + } + } + + return 0; +} + +/////////////////////////////////////////////////////////// + +/// Main entry +int main (int argc, char **argv) +{ + int c; + extern char *optarg; + extern int optind; + int nb_message = -1; /* Nb de messages à envoyer ou à recevoir, par défaut : 10 en émission, infini en réception */ + int source = -1; /* 0 = puits, 1 = source */ + int tcp = 1; /* 0 = UDP, 1 = TCP */ + int l_msg = 30; /* longueur du message, en octet. Defaut : 30. */ + + while ((c = getopt(argc, argv, "pn:sul:")) != -1) { + switch (c) { + case 'p': + if (source == 1) { + err_args(); + } + source = 0; + break; + + case 's': + if (source == 0) { + err_args(); + } + source = 1; + break; + + case 'n': + nb_message = atoi(optarg); + break; + + case 'u': + tcp = 0; + break; + + case 'l': + l_msg = atoi(optarg) + 5; + break; + + default: + err_args(); + break; + } + } + + int PORT = atoi(argv[argc-1]); + //PORT = htons(PORT); + + if (source == -1) { + err_args(); + } + + if (tcp) + printf("[+] On utilise le protocol TCP\n"); + else + printf("[+] On utilise le protocol UDP\n"); + + + char* HOSTNAME = ""; + if (source == 1){ + printf("[+] On est dans la source\n"); + HOSTNAME = argv[argc-2]; + } + else + printf("[+] On est dans le puit\n"); + + if (nb_message != -1) { + if (source == 1) + printf("[+] Nombre de tampons à envoyer : %d\n", nb_message); + else + printf("[+] Nombre de tampons à recevoir : %d\n", nb_message); + } else { + if (source == 1) { + nb_message = 10 ; + printf("[~] Nombre de tampons à envoyer : 10 par défaut\n"); + } + else + printf("[+] Nombre de tampons à envoyer : infini\n"); + } + + if (l_msg == 30) + printf("[~] Longueur des messages à envoyer/recevoir : 30 par défaut\n"); + else + printf("[+] Nombre de tampons à envoyer/recevoir : %d \n", l_msg); + + int s = 1; + + // Choose the right function + if (tcp){ + if (source) s = source_TCP(HOSTNAME, PORT, nb_message, l_msg); + else s = puit_TCP(PORT, nb_message, l_msg); + } + else { + if (source) s = source_UDP(HOSTNAME, PORT, nb_message, l_msg); + else s = puit_UDP(PORT, nb_message, l_msg); + } + + return s; +} +