diff --git a/apps/ping.c b/apps/ping.c index 6454f053..2641fb05 100644 --- a/apps/ping.c +++ b/apps/ping.c @@ -22,24 +22,8 @@ #include #include -#include - #define BYTES_TO_SEND 56 -struct IPV4_Header { - uint8_t version_ihl; - uint8_t dscp_ecn; - uint16_t length; - uint16_t ident; - uint16_t flags_fragment; - uint8_t ttl; - uint8_t protocol; - uint16_t checksum; - uint32_t source; - uint32_t destination; - uint8_t payload[]; -}; - struct ICMP_Header { uint8_t type, code; uint16_t checksum; @@ -128,22 +112,22 @@ int main(int argc, char * argv[]) { if (ret > 0) { char data[4096]; - ssize_t len = recv(sock, data, 4096, 0); + struct sockaddr_in source; + socklen_t source_size = sizeof(struct sockaddr_in); + ssize_t len = recvfrom(sock, data, 4096, 0, (struct sockaddr*)&source, &source_size); clock_t rcvd_at = times(NULL); if (len > 0) { /* Is it actually a PING response ? */ - struct IPV4_Header * ipv4 = (void*)data; - struct ICMP_Header * icmp = (void*)ipv4->payload; + struct ICMP_Header * icmp = (void*)data; if (icmp->type == 0) { /* How much data, minus the header? */ - size_t len = ntohs(ipv4->length) - sizeof(struct IPV4_Header); /* Get the address */ - char * from = inet_ntoa(*(struct in_addr*)&ipv4->source); + char * from = inet_ntoa(source.sin_addr); int time_taken = (rcvd_at - sent_at); printf("%zd bytes from %s: icmp_seq=%d ttl=%d time=%d", - len, from, ntohs(icmp->sequence_number), ipv4->ttl, + len, from, ntohs(icmp->sequence_number), (unsigned char)source.sin_zero[0], /* we hide the ttl in here */ time_taken / 1000); if (time_taken < 1000) { printf(".%03d", time_taken % 1000); @@ -160,7 +144,7 @@ int main(int argc, char * argv[]) { } if (!break_from_loop) { - syscall_sleep(1,0); + sleep(1); } } diff --git a/kernel/net/ipv4.c b/kernel/net/ipv4.c index 14b56fad..e9afe7b0 100644 --- a/kernel/net/ipv4.c +++ b/kernel/net/ipv4.c @@ -209,15 +209,25 @@ static long sock_icmp_recv(sock_t * sock, struct msghdr * msg, int flags) { char * packet = net_sock_get(sock); if (!packet) return -EINTR; - size_t packet_size = *(size_t*)packet; - struct ipv4_packet * data = (struct ipv4_packet*)(packet + sizeof(size_t)); + size_t packet_size = *(size_t*)packet - sizeof(struct ipv4_packet); + + struct ipv4_packet * src = (struct ipv4_packet*)(packet + sizeof(size_t)); if (packet_size > msg->msg_iov[0].iov_len) { dprintf("ICMP recv too big for vector\n"); packet_size = msg->msg_iov[0].iov_len; } - memcpy(msg->msg_iov[0].iov_base, data, packet_size); + if (msg->msg_namelen == sizeof(struct sockaddr_in)) { + if (msg->msg_name) { + ((struct sockaddr_in*)msg->msg_name)->sin_family = AF_INET; + ((struct sockaddr_in*)msg->msg_name)->sin_port = 0; + ((struct sockaddr_in*)msg->msg_name)->sin_addr.s_addr = src->source; + ((struct sockaddr_in*)msg->msg_name)->sin_zero[0] = src->ttl; + } + } + + memcpy(msg->msg_iov[0].iov_base, src->payload, packet_size); free(packet); return packet_size; }