HelenOS sources
This source file includes following definitions.
- icmp_recv
- icmp_recv_echo_request
- icmp_recv_echo_reply
- icmp_ping_send
#include <byteorder.h>
#include <errno.h>
#include <io/log.h>
#include <mem.h>
#include <stdlib.h>
#include <types/inetping.h>
#include "icmp.h"
#include "icmp_std.h"
#include "inetsrv.h"
#include "inetping.h"
#include "pdu.h"
#define INET_TTL_MAX 255
static errno_t icmp_recv_echo_request(inet_dgram_t *);
static errno_t icmp_recv_echo_reply(inet_dgram_t *);
errno_t icmp_recv(inet_dgram_t *dgram)
{
uint8_t type;
log_msg(LOG_DEFAULT, LVL_DEBUG, "icmp_recv()");
if (dgram->size < 1)
return EINVAL;
type = *(uint8_t *)dgram->data;
switch (type) {
case ICMP_ECHO_REQUEST:
return icmp_recv_echo_request(dgram);
case ICMP_ECHO_REPLY:
return icmp_recv_echo_reply(dgram);
default:
break;
}
return EINVAL;
}
static errno_t icmp_recv_echo_request(inet_dgram_t *dgram)
{
icmp_echo_t *request, *reply;
uint16_t checksum;
size_t size;
inet_dgram_t rdgram;
errno_t rc;
log_msg(LOG_DEFAULT, LVL_DEBUG, "icmp_recv_echo_request()");
if (dgram->size < sizeof(icmp_echo_t))
return EINVAL;
request = (icmp_echo_t *)dgram->data;
size = dgram->size;
reply = calloc(size, 1);
if (reply == NULL)
return ENOMEM;
memcpy(reply, request, size);
reply->type = ICMP_ECHO_REPLY;
reply->code = 0;
reply->checksum = 0;
checksum = inet_checksum_calc(INET_CHECKSUM_INIT, reply, size);
reply->checksum = host2uint16_t_be(checksum);
rdgram.iplink = 0;
rdgram.src = dgram->dest;
rdgram.dest = dgram->src;
rdgram.tos = ICMP_TOS;
rdgram.data = reply;
rdgram.size = size;
rc = inet_route_packet(&rdgram, IP_PROTO_ICMP, INET_TTL_MAX, 0);
free(reply);
return rc;
}
static errno_t icmp_recv_echo_reply(inet_dgram_t *dgram)
{
log_msg(LOG_DEFAULT, LVL_DEBUG, "icmp_recv_echo_reply()");
if (dgram->size < sizeof(icmp_echo_t))
return EINVAL;
icmp_echo_t *reply = (icmp_echo_t *) dgram->data;
inetping_sdu_t sdu;
sdu.src = dgram->src;
sdu.dest = dgram->dest;
sdu.seq_no = uint16_t_be2host(reply->seq_no);
sdu.data = dgram->data + sizeof(icmp_echo_t);
sdu.size = dgram->size - sizeof(icmp_echo_t);
uint16_t ident = uint16_t_be2host(reply->ident);
return inetping_recv(ident, &sdu);
}
errno_t icmp_ping_send(uint16_t ident, inetping_sdu_t *sdu)
{
size_t rsize = sizeof(icmp_echo_t) + sdu->size;
void *rdata = calloc(rsize, 1);
if (rdata == NULL)
return ENOMEM;
icmp_echo_t *request = (icmp_echo_t *) rdata;
request->type = ICMP_ECHO_REQUEST;
request->code = 0;
request->checksum = 0;
request->ident = host2uint16_t_be(ident);
request->seq_no = host2uint16_t_be(sdu->seq_no);
memcpy(rdata + sizeof(icmp_echo_t), sdu->data, sdu->size);
uint16_t checksum = inet_checksum_calc(INET_CHECKSUM_INIT, rdata, rsize);
request->checksum = host2uint16_t_be(checksum);
inet_dgram_t dgram;
dgram.src = sdu->src;
dgram.dest = sdu->dest;
dgram.iplink = 0;
dgram.tos = ICMP_TOS;
dgram.data = rdata;
dgram.size = rsize;
errno_t rc = inet_route_packet(&dgram, IP_PROTO_ICMP, INET_TTL_MAX, 0);
free(rdata);
return rc;
}
HelenOS homepage, sources at GitHub