diff options
Diffstat (limited to 'src/user/app/ethdump/ipv4.c')
-rw-r--r-- | src/user/app/ethdump/ipv4.c | 59 |
1 files changed, 47 insertions, 12 deletions
diff --git a/src/user/app/ethdump/ipv4.c b/src/user/app/ethdump/ipv4.c index 408e1df..c9b2df4 100644 --- a/src/user/app/ethdump/ipv4.c +++ b/src/user/app/ethdump/ipv4.c @@ -1,20 +1,23 @@ #include "proto.h" #include "util.h" +#include <stdlib.h> enum { - Version = 0, - HdrLen = 0, - PktLen = 2, - Id = 4, - Proto = 9, - SrcIP = 12, - DestIP = 16, + Version = 0, + HdrLen = 0, + PktLen = 2, + Id = 4, + TTL = 8, + Proto = 9, + Checksum = 10, + SrcIP = 12, + DstIP = 16, }; -void ipv4_parse(const uint8_t *buf, size_t len) { +void ipv4_parse(const uint8_t *buf, size_t len, struct ethernet ether) { uint8_t version, headerlen, proto; uint16_t packetlen, id; - uint32_t dest, src; + uint32_t dst, src; version = buf[Version] >> 4; if (version != 4) { @@ -26,25 +29,57 @@ void ipv4_parse(const uint8_t *buf, size_t len) { id = nget16(buf + Id); proto = buf[Proto]; src = nget32(buf + SrcIP); - dest = nget32(buf + DestIP); + dst = nget32(buf + DstIP); // TODO checksum // TODO fragmentation printf("headerlen %u, packetlen %u (real %u), id %u\n", headerlen, packetlen, len, id); - printf("from %x to %x\n", src, dest); + printf("from %x to %x\n", src, dst); printf("id %u\n", id); if (packetlen < headerlen) { printf("headerlen too big\n"); return; } + + struct ipv4 ip = (struct ipv4){ + .e = ether, + .src = src, + .dst = dst, + .proto = proto, + }; + switch (proto) { case 1: printf("proto %u - icmp\n", proto); - icmp_parse(buf + headerlen, packetlen - headerlen); + icmp_parse(buf + headerlen, packetlen - headerlen, ip); break; default: printf("proto %u - unknown\n", proto); break; } } + +uint8_t *ipv4_start(size_t len, struct ipv4 ip) { + ip.e.type = ET_IPv4; + if (!ip.src) ip.src = state.ip; + if (!ip.e.dst && ip.dst == 0xFFFFFFFF) + ip.e.dst = &MAC_BROADCAST; + + size_t hdrlen = 20; + uint8_t *pkt = ether_start(len + hdrlen, ip.e); + pkt[Version] = 0x40; + pkt[HdrLen] |= hdrlen / 4; + nput16(pkt + PktLen, len + hdrlen); + pkt[TTL] = 0xFF; + pkt[Proto] = ip.proto; + nput32(pkt + SrcIP, ip.src); + nput32(pkt + DstIP, ip.dst); + + nput16(pkt + Checksum, ip_checksum(pkt, hdrlen)); + + return pkt + hdrlen; +} +void ipv4_finish(uint8_t *pkt) { + ether_finish(pkt - 20); +} |