/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* ft_ping.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: tomoron +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 19:54:25 by tomoron #+# #+# */ /* Updated: 2025/04/30 17:59:21 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ #include "includes/ft_ping.h" struct addrinfo *resolve_ip(char *host, t_settings *settings) { struct addrinfo hints, *result; int s; struct addrinfo *ret; memset(&hints, 0, sizeof(hints)); ret = 0; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; s = getaddrinfo(host, NULL, &hints, &result); if (s != 0) { fprintf(stderr, "%s: %s\n",settings->name, gai_strerror(s)); return(ret); } ret = result; if(!ret) return(ret); ret->ai_next = 0; result = result->ai_next; freeaddrinfo(result); return(ret); } double timediff(struct timeval *from) { struct timeval now; float diff; gettimeofday(&now, 0); diff = ((double)now.tv_sec - from->tv_sec); diff += (((double)now.tv_usec / 1000000) - ((double)from->tv_usec / 1000000)); return(diff); } t_waitlist *send_icmp(t_settings *set, struct addrinfo *host, uint16_t *seq, struct timeval *last) { t_icmp_echo packet; t_waitlist *ret; if(timediff(last) < set->interval) return (0); packet = prepare_icmp_echo(*seq, set->id); sendto(set->socket, &packet, sizeof(t_icmp_echo), 0, host->ai_addr, host->ai_addrlen); gettimeofday(last, 0); (*seq)++; ret = malloc(sizeof(t_waitlist)); if(!ret) return(0); ret->time = *last; ret->seq = *seq; ret->next = 0; return(ret); } void waitlist_add(t_waitlist **waitlist, t_waitlist *elem) { t_waitlist *cur; cur = *waitlist; while(cur && cur->next) cur = cur->next; if(cur) cur->next = elem; else *waitlist = elem; } void waitlist_free(t_waitlist *lst) { t_waitlist *tmp; while(lst) { tmp = lst->next; free(lst); lst = tmp; } } void waitlist_remove(t_waitlist **lst, uint16_t seq) { t_waitlist *cur; t_waitlist *prev; if(!*lst) return ; cur = *lst; prev = 0; while(cur && cur->seq != seq) { prev = cur; cur = cur->next; } if(!prev) return ; if(!prev && *lst) *lst = (*lst)->next; if(cur) prev->next = cur->next; free(cur); } void receive_icmp(t_settings *set, struct addrinfo *info, t_waitlist **wl) { size_t len; char buf[256]; t_icmp_echo *res; uint16_t checksum; len = recvfrom(set->socket, buf, sizeof(t_icmp_echo) + 20, 0, info->ai_addr, &info->ai_addrlen); res = (void*)(buf + 20); if(len == (size_t)-1 || !len) return; if(res->type != 0 && res->identifier != set->id) return ; checksum = res->checksum; res->checksum = 0; if(calc_checksum(res, sizeof(t_icmp_echo)) != checksum) return ; waitlist_remove(wl, res->sequence); } int ping_host(t_settings *set, char *host) { uint16_t seq; struct addrinfo *info; struct timeval last_sent; t_waitlist *wl; t_waitlist *tmp; seq = 0; info = resolve_ip(host, set); if(!info) return(0); last_sent.tv_sec = 0; last_sent.tv_usec = 0; wl = 0; while(seq < set->count || set->count == -1) { tmp = send_icmp(set, info, &seq, &last_sent); if(tmp) waitlist_add(&wl, tmp); usleep(1000); receive_icmp(set, info, &wl); } while(wl) receive_icmp(set, info, &wl); freeaddrinfo(info); waitlist_free(wl); return(1); } void send_pings(t_settings *set) { t_host_list *cur; cur = set->hosts; while(cur) { if(!ping_host(set, cur->host)) return; cur = cur->next; } }