net: Make ICMP sockets more normal
This commit is contained in:
parent
887bbc45a0
commit
f6ea45f60e
30
apps/ping.c
30
apps/ping.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user