net: Make ICMP sockets more normal

This commit is contained in:
K. Lange 2022-03-22 15:32:58 +09:00
parent 887bbc45a0
commit f6ea45f60e
2 changed files with 20 additions and 26 deletions

View File

@ -22,24 +22,8 @@
#include <netdb.h>
#include <arpa/inet.h>
#include <syscall.h>
#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);
}
}

View File

@ -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;
}