commit c32e36c7e1eb3c9c2748670861641becb3f9ef60 Author: Namonay Date: Thu Sep 12 03:30:13 2024 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..722d5e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode diff --git a/ft_ping.h b/ft_ping.h new file mode 100644 index 0000000..716663a --- /dev/null +++ b/ft_ping.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +struct t_socket +{ + struct sockaddr_in dst, src; + int fd; + int len; +}; \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..b1b5833 --- /dev/null +++ b/main.c @@ -0,0 +1,87 @@ +#include "ft_ping.h" + +uint16_t calculate_checksum(uint16_t *data, int len) +{ + uint32_t checksum = 0; + + while (len > 1) + { + checksum += *data++; + len -= 2; + } + if (len == 1) + checksum += *(uint8_t *)data; + + while (checksum >> 16) + checksum = (checksum & 0xFFFF) + (checksum >> 16); + printf("checksum is : %X\n", (uint16_t)~checksum); + return (~checksum); +} + + +int ft_ping(struct t_socket sock, int *seq) +{ + unsigned char data[2048]; + unsigned char data2[2048]; + struct icmphdr *icmp_header = (struct icmphdr *)data; + + memset(data, 0, sizeof(data)); + memset(data2, 0, sizeof(data2)); + sock.fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (sock.fd < 0) + { + printf(strerror(errno)); + fprintf(stderr, "ERROR : socket() failed\n"); + return (0); + } + if (getsockname(sock.fd, (struct sockaddr *)&sock.src, &sock.len) < 0) + { + fprintf(stderr, "ERROR : getsockname() failed\n"); + return (0); + } + sock.dst.sin_family = AF_INET; + memset(icmp_header, 0, sizeof(icmp_header)); + icmp_header->type = ICMP_ECHO; + icmp_header->code = 0; + icmp_header->checksum = 0; + icmp_header->un.echo.id = getpid(); + icmp_header->un.echo.sequence = *seq++; + icmp_header->checksum = calculate_checksum((uint16_t *)icmp_header, sizeof(icmp_header)); + if (sendto(sock.fd, data, sizeof(data), 0, (struct sockaddr *)&sock.dst, sizeof(sock.dst)) == -1) + { + fprintf(stderr, "ERROR : sendto() failed\n"); + return (0); + } + if (recvfrom(sock.fd, data2, sizeof(data2), 0, (struct sockaddr *)&sock.src, &sock.len) == -1) + { + fprintf(stderr, "ERROR : recvfrom() failed\n"); + return (0); + } + struct icmphdr *icmp_recv_header = (struct icmphdr *)(data2 + 20); + if (icmp_recv_header->type != ICMP_ECHOREPLY || icmp_recv_header->code != 0) + { + fprintf(stderr, "ERROR : invalid packet received (code)\n"); + return (0); + } + printf("success"); + close(sock.fd); + return (1); +} + +int main(int argc, char **argv) +{ + struct t_socket sock; + int seq = 1; + sock.src.sin_family = AF_INET; + if (argc != 2 || argv[1] == NULL || argv[1][0] == 0) + { + fprintf(stderr, "ERROR : usage : ping {-v?} [ADRESS]\n"); + return (0); + } + if (gethostbyname(argv[1]) == NULL && inet_aton(argv[1], (struct in_addr *)&sock.dst.sin_addr.s_addr) == 0) + { + fprintf(stderr, "ERROR : %s is an invalid adress\n", argv[1]); + return (0); + } + return (ft_ping(sock, &seq)); +} \ No newline at end of file