Enviado em 03/07/2021 - 12:11h
TL;DR
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SNDTIMEO 5
#define MAXCONN 10
static bool set_sock_opts(int sockfd, bool only_ipv6) {
bool ok = false;
const int optval = 1;
struct timeval timeout = {SNDTIMEO, 0};
do {
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != 0 ) {
break;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) != 0 ) {
break;
}
if (only_ipv6 == true) {
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)) != 0 ) {
break;
}
}
ok = true;
} while (false);
return ok;
}
static int make_server_socket(int af, const char *service, bool only_ipv6, size_t somaxconn) {
int sockfd, ecode;
struct addrinfo hints, *result = NULL, *rp = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = af;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
if ((ecode = getaddrinfo(NULL, service, &hints, &result)) != 0 ) {
fprintf(stderr, "make_server_socket() -> getaddrinfo() -> ERROR: %s\n", gai_strerror(ecode));
exit(EXIT_FAILURE);
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
if ((sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0 ) {
continue;
}
if (set_sock_opts(sockfd, only_ipv6) != true ) {
close(sockfd);
continue;
}
if (bind(sockfd, rp->ai_addr, rp->ai_addrlen) != -1 ) {
break;
}
close(sockfd);
}
if (rp == NULL) {
fprintf(stderr, "make_server_socket() -> socket()/bind() -> ERROR: %s\n", strerror(errno));
freeaddrinfo(rp);
exit(EXIT_FAILURE);
}
freeaddrinfo(rp);
if (listen(sockfd, somaxconn) < 0 ) {
fprintf(stderr, "make_server_socket() -> listen() -> ERROR: %s\n", strerror(errno));
close(sockfd);
exit(EXIT_FAILURE);
}
return sockfd;
}
static bool check_addr(int af, void *addr, void *adresses, size_t count) {
bool found = false;
if (af == AF_UNIX) {
struct sockaddr_un *un = addr;
for (size_t i = 0; i < count; i++) {
struct sockaddr_un *tmp = &adresses[i];
if (memcmp(un->sun_path, tmp->sun_path, sizeof(un->sun_path)) == 0 ) {
found = true;
break;
}
}
} else if (af == AF_INET) {
struct sockaddr_in *in = addr;
for (size_t i = 0; i < count; i++) {
struct sockaddr_in *tmp = &adresses[i];
if (memcmp(&in->sin_addr.s_addr, &tmp->sin_addr.s_addr, sizeof(in->sin_addr.s_addr)) == 0 ) {
found = true;
break;
}
}
} else {
struct sockaddr_in6 *in6 = addr;
for(size_t i = 0; i < count; i++) {
struct sockaddr_in6 *tmp = &adresses[i];
if (memcmp(&in6->sin6_addr.s6_addr, &tmp->sin6_addr.s6_addr, sizeof(in6->sin6_addr.s6_addr)) == 0 ) {
found = true;
break;
}
}
}
return found;
}
static void show_addr(int af, void *addr) {
char buff[INET6_ADDRSTRLEN];
if (af == AF_UNIX) {
struct sockaddr_un *un = addr;
printf("%s\n", un->sun_path);
} else if (af == AF_INET) {
struct sockaddr_in *in = addr;
if (inet_ntop(af, &in->sin_addr.s_addr, buff, INET_ADDRSTRLEN) < 0 ) {
fprintf(stderr, "show_addr() -> inet_ntop() -> ERROR: %s\n", strerror(errno));
} else {
printf("%s\n", buff);
}
} else {
struct sockaddr_in6 *in6 = addr;
if (inet_ntop(af, &in6->sin6_addr.s6_addr, buff, INET6_ADDRSTRLEN) < 0 ) {
fprintf(stderr, "show_addr() -> inet_ntop() -> ERROR: %s\n", strerror(errno));
} else {
printf("%s\n", buff);
}
}
}
static void search(char **argv, size_t somaxconn, size_t maxconn) {
int af;
bool only_ipv6 = false;
socklen_t addrlen;
if (strcmp(argv[1], "-u") == 0 ) {
af = AF_UNIX;
addrlen = sizeof(struct sockaddr_un);
} else if (strcmp(argv[1], "-4") == 0 ) {
af = AF_INET;
addrlen = sizeof(struct sockaddr_in);
} else if (strcmp(argv[1], "-6") == 0 ) {
af = AF_INET6;
only_ipv6 = true;
addrlen = sizeof(struct sockaddr_in6);
} else {
af = AF_INET6;
addrlen = sizeof(struct sockaddr_in6);
}
size_t i = 0;
int sockfd = make_server_socket(af, argv[2], only_ipv6, somaxconn);
void *addr = malloc(addrlen);
void *adresses = NULL;
const char msg_1[] = "Welcome!\n", err_msg[] = "Internal server error!", msg_2[] = "Get out!\n";
while (i < maxconn) {
int cli_sockfd;
if ((cli_sockfd = accept(sockfd, addr, &addrlen)) < 0 ) {
fprintf(stderr, "search() -> accept() -> ERROR: %s\n", strerror(errno));
} else {
if (check_addr(af, addr, adresses, i) == false ) {
void *tmp = realloc(adresses, addrlen * (i + 1));
if (!tmp) {
fprintf(stderr, "ERROR: Memory allocation for %zu bytes failed\nsearch() -> realloc() -> ERROR: %s\n",
addrlen * (i + 1), strerror(errno));
send(cli_sockfd, err_msg, sizeof(err_msg), 0);
} else {
i++;
adresses = tmp;
memcpy(&adresses[i-1], addr, addrlen);
show_addr(af, addr);
send(cli_sockfd, msg_1, sizeof(msg_1), 0);
}
}else{
send(cli_sockfd, msg_2, sizeof(msg_2), 0);
}
close(cli_sockfd);
}
}
free(addr);
free(adresses);
close(sockfd);
}
int main(int argc, char **argv) {
if (argc == 1) {
printf(" *** ERROR: No arguments! ***\n");
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
exit(EXIT_FAILURE);
}
int opt = getopt(argc, argv, "u46Mh");
if (strlen(argv[1]) > 2 ) {
printf("*** Invalid value for [OPTION]! ***\n");
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
} else if (opt == 'h' || opt == '?') {
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
} else if ((argc < 5) || (argc > 5)) {
printf("*** Invalid values! ***\n");
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
}else{
size_t somaxconn = strtoull(argv[3], NULL, 10);
size_t maxconn = strtoull(argv[4], NULL, 10);
if (somaxconn > SOMAXCONN) {
printf("*** Invalid value for [SOMAXCONN]. The value is too long! ***\n");
printf("The maximum allowed value is %u\n", SOMAXCONN);
} else if ( maxconn > MAXCONN ) {
printf("*** Invalid value for [MAXCONN]. The value is too long! ***\n");
printf("The maximum allowed value is %u\n", MAXCONN);
} else {
search(argv, somaxconn, maxconn);
}
}
return EXIT_SUCCESS;
}
//Terminal do servidor
$ gcc -Wall server_2.c -o server
server_2.c: In function 'check_addr':
server_2.c:135:60: warning: dereferencing 'void *' pointer
135 | struct sockaddr_un *tmp = &adresses[i];
| ^
server_2.c:149:60: warning: dereferencing 'void *' pointer
149 | struct sockaddr_in *tmp = &adresses[i];
| ^
server_2.c:163:61: warning: dereferencing 'void *' pointer
163 | struct sockaddr_in6 *tmp = &adresses[i];
| ^
server_2.c: In function 'search':
server_2.c:280:57: warning: dereferencing 'void *' pointer
280 | memcpy(&adresses[i-1], addr, addrlen);
| ^
$ ./server -M 9009 4096 3
::ffff:127.0.0.1
::1
::ffff:192.168.50.2
//Terminal do cliente
$ nc 127.0.0.1 9009
Welcome!
^C
$ nc ::1 9009
Welcome!
^C
$ nc 192.168.50.2 9009
Welcome!
^C
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SNDTIMEO 5
#define MAXCONN 10
static bool set_sock_opts(int sockfd, bool only_ipv6) {
bool ok = false;
const int optval = 1;
struct timeval timeout = {SNDTIMEO, 0};
do {
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != 0 ) {
break;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) != 0 ) {
break;
}
if (only_ipv6 == true) {
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)) != 0 ) {
break;
}
}
ok = true;
} while (false);
return ok;
}
static int make_server_socket(int af, const char *service, bool only_ipv6, size_t somaxconn) {
int sockfd, ecode;
struct addrinfo hints, *result = NULL, *rp = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = af;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
if ((ecode = getaddrinfo(NULL, service, &hints, &result)) != 0 ) {
fprintf(stderr, "make_server_socket() -> getaddrinfo() -> ERROR: %s\n", gai_strerror(ecode));
exit(EXIT_FAILURE);
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
if ((sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0 ) {
continue;
}
if (set_sock_opts(sockfd, only_ipv6) != true ) {
close(sockfd);
continue;
}
if (bind(sockfd, rp->ai_addr, rp->ai_addrlen) != -1 ) {
break;
}
close(sockfd);
}
if (rp == NULL) {
fprintf(stderr, "make_server_socket() -> socket()/bind() -> ERROR: %s\n", strerror(errno));
freeaddrinfo(rp);
exit(EXIT_FAILURE);
}
freeaddrinfo(rp);
if (listen(sockfd, somaxconn) < 0 ) {
fprintf(stderr, "make_server_socket() -> listen() -> ERROR: %s\n", strerror(errno));
close(sockfd);
exit(EXIT_FAILURE);
}
return sockfd;
}
static bool check_addr(int af, void *addr, void **addr_table, size_t count) {
bool found = false;
if (af == AF_UNIX) {
struct sockaddr_un *un = addr;
for (size_t i = 0; i < count; i++) {
struct sockaddr_un *tmp = addr_table[i];
if (memcmp(un->sun_path, tmp->sun_path, sizeof(un->sun_path)) == 0 ) {
found = true;
break;
}
}
} else if (af == AF_INET) {
struct sockaddr_in *in = addr;
for (size_t i = 0; i < count; i++) {
struct sockaddr_in *tmp = addr_table[i];
if (memcmp(&in->sin_addr.s_addr, &tmp->sin_addr.s_addr, sizeof(in->sin_addr.s_addr)) == 0 ) {
found = true;
break;
}
}
} else {
struct sockaddr_in6 *in6 = addr;
for(size_t i = 0; i < count; i++) {
struct sockaddr_in6 *tmp = addr_table[i];
if (memcmp(&in6->sin6_addr.s6_addr, &tmp->sin6_addr.s6_addr, sizeof(in6->sin6_addr.s6_addr)) == 0 ) {
found = true;
break;
}
}
}
return found;
}
static void show_addr(int af, void *addr) {
char buff[INET6_ADDRSTRLEN];
if (af == AF_UNIX) {
struct sockaddr_un *un = addr;
printf("%s\n", un->sun_path);
} else if (af == AF_INET) {
struct sockaddr_in *in = addr;
if (inet_ntop(af, &in->sin_addr.s_addr, buff, INET_ADDRSTRLEN) < 0 ) {
fprintf(stderr, "show_addr() -> inet_ntop() -> ERROR: %s\n", strerror(errno));
} else {
printf("%s\n", buff);
}
} else {
struct sockaddr_in6 *in6 = addr;
if (inet_ntop(af, &in6->sin6_addr.s6_addr, buff, INET6_ADDRSTRLEN) < 0 ) {
fprintf(stderr, "show_addr() -> inet_ntop() -> ERROR: %s\n", strerror(errno));
} else {
printf("%s\n", buff);
}
}
}
static void **realloc_addr_table(void **addr_table, size_t count, socklen_t addrlen) {
void **tmp = realloc(addr_table, count * sizeof(*addr_table));
if (tmp == NULL) {
fprintf(stderr, "ERROR: Memory allocation for %zu bytes failed\nrealloc_addr_table() -> realloc() -> ERROR: %s\n",
count * sizeof(*addr_table), strerror(errno));
} else {
tmp[count-1] = malloc(addrlen);
if (tmp == NULL) {
fprintf(stderr, "ERROR: Memory allocation for %u bytes failed\nrealloc_addr_table -> realloc() -> ERROR: %s\n",
addrlen, strerror(errno));
}
}
return tmp;
}
static void free_addr_table(void **addr_table, size_t count) {
for (size_t i = 0; i < count; i++) {
free(addr_table[i]);
}
free(addr_table);
}
static void search(char **argv, size_t somaxconn, size_t maxconn) {
int af;
bool only_ipv6 = false;
socklen_t addrlen;
if (strcmp(argv[1], "-u") == 0 ) {
af = AF_UNIX;
addrlen = sizeof(struct sockaddr_un);
} else if (strcmp(argv[1], "-4") == 0 ) {
af = AF_INET;
addrlen = sizeof(struct sockaddr_in);
} else if (strcmp(argv[1], "-6") == 0 ) {
af = AF_INET6;
only_ipv6 = true;
addrlen = sizeof(struct sockaddr_in6);
} else {
af = AF_INET6;
addrlen = sizeof(struct sockaddr_in6);
}
size_t i = 0;
int sockfd = make_server_socket(af, argv[2], only_ipv6, somaxconn);
void *addr = malloc(addrlen);
void **addr_table = NULL;
const char msg_1[] = "Welcome!\n", err_msg[] = "Internal server error!", msg_2[] = "Get out!\n";
while (i < maxconn) {
int cli_sockfd;
if ((cli_sockfd = accept(sockfd, addr, &addrlen)) < 0 ) {
fprintf(stderr, "search() -> accept() -> ERROR: %s\n", strerror(errno));
} else {
if (check_addr(af, addr, addr_table, i) == false ) {
void **tmp = realloc_addr_table(addr_table, i+1, addrlen);
if (!tmp) {
send(cli_sockfd, err_msg, sizeof(err_msg), 0);
} else {
i++;
addr_table = tmp;
memcpy(addr_table[i-1], addr, addrlen);
show_addr(af, addr);
send(cli_sockfd, msg_1, sizeof(msg_1), 0);
}
}else{
send(cli_sockfd, msg_2, sizeof(msg_2), 0);
}
close(cli_sockfd);
}
}
free(addr);
free_addr_table(addr_table, i);
close(sockfd);
}
int main(int argc, char **argv) {
if (argc == 1) {
printf(" *** ERROR: No arguments! ***\n");
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
exit(EXIT_FAILURE);
}
int opt = getopt(argc, argv, "u46Mh");
if (strlen(argv[1]) > 2 ) {
printf("*** Invalid value for [OPTION]! ***\n");
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
} else if (opt == 'h' || opt == '?') {
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
} else if ((argc < 5) || (argc > 5)) {
printf("*** Invalid arguments! ***\n");
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
} else {
size_t somaxconn = strtoull(argv[3], NULL, 10);
size_t maxconn = strtoull(argv[4], NULL, 10);
if (somaxconn > SOMAXCONN) {
printf("*** ERROR: The value passed for [SOMAXCONN] is too long! ***\n");
printf("The maximum allowed value is %d\n", SOMAXCONN);
} else if (maxconn > MAXCONN) {
printf("*** ERROR: The value passed for [MAXCONN] is too long! ***\n");
printf("The maximum allowed value is %d\n", MAXCONN);
} else {
search(argv, somaxconn, maxconn);
}
}
return EXIT_SUCCESS;
}
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Como renomear arquivos de letras maiúsculas para minúsculas
Imprimindo no formato livreto no Linux
Vim - incrementando números em substituição
Efeito "livro" em arquivos PDF
Como resolver o erro no CUPS: Unable to get list of printer drivers
Melhores Práticas de Nomenclatura: Pastas, Arquivos e Código [RESOLVID... (4)
Recuperar arquivos de HD em formato RAW usando Linux (0)
[Python] Automação de scan de vulnerabilidades
[Python] Script para analise de superficie de ataque
[Shell Script] Novo script para redimensionar, rotacionar, converter e espelhar arquivos de imagem
[Shell Script] Iniciador de DOOM (DSDA-DOOM, Doom Retro ou Woof!)
[Shell Script] Script para adicionar bordas às imagens de uma pasta