15 uint16_t Identifcation;
16 uint16_t FragmentInfo; // rsvd:dont:more:[13]offset/8
19 uint16_t HeaderChecksum;
23 } __attribute__((packed)) tIPv4Hdr;
26 uint16_t IP_Checksum(uint16_t Prev, size_t Length, const void *Data)
28 //test_trace_hexdump("IP Checksum", Data, Length);
30 const uint16_t *words = Data;
32 for( int i = 0; i < Length/2; i ++ )
38 ret += ntohs(*(uint8_t*)words);
41 ret = (ret & 0xFFFF) + (ret >> 16);
43 //test_trace("IP Checksum = %04x + 0x%x", ret, (~Prev) & 0xFFFF);
45 ret += (~Prev) & 0xFFFF;
47 ret = (ret & 0xFFFF) + (ret >> 16);
52 void IP_Send(int IfNum, int AF, const void *Src, const void *Dst, uint8_t proto,
53 int BufCount, size_t BufLens[], const void *Bufs[])
55 size_t total_length = 0;
57 size_t out_buflens[BufCount+1];
58 const void *out_bufs[BufCount+1];
60 for( int i = 0; i < BufCount; i ++ )
62 total_length += BufLens[i];
63 out_buflens[1+i] = BufLens[i];
64 out_bufs[1+i] = Bufs[i];
70 hdr.VerLen = (4 << 4) | (sizeof(hdr)/4);
72 hdr.TotalLength = htons(sizeof(hdr) + total_length);
73 hdr.Identifcation = 0; // TODO: WTF is this?
74 hdr.FragmentInfo = htons(0);
75 hdr.TTL = 18; // TODO: Progammable TTL
77 hdr.HeaderChecksum = 0;
78 memcpy(hdr.SrcAddr, Src, 4);
79 memcpy(hdr.DstAddr, Dst, 4);
81 hdr.HeaderChecksum = htons( IP_Checksum(IP_CHECKSUM_START, sizeof(hdr), &hdr) );
83 out_buflens[0] = sizeof(hdr);
86 // TODO: Don't hard-code MAC addresses
87 Link_Send(IfNum, BLOB(HOST_MAC), BLOB(TEST_MAC), ETHER_PROTO_IPV4,
88 1+BufCount, out_buflens, out_bufs);
91 TEST_WARN("Invalid AF(%i) in IP_Send", AF);
95 bool IP_Pkt_Check(size_t len, const void *data, size_t *ofs_out, size_t *len_out, int AF, const void *Src, const void *Dst, uint8_t proto)
99 if( !Link_Pkt_Check(len, data, &ofs, BLOB(TEST_MAC), BLOB(HOST_MAC), ETHER_PROTO_IPV4) )
103 memcpy(&hdr, (const uint8_t*)data + ofs, sizeof(hdr));
104 TEST_ASSERT_REL(hdr.VerLen >> 4, ==, 4);
105 TEST_ASSERT_REL(IP_Checksum(IP_CHECKSUM_START, sizeof(hdr), &hdr), ==, 0);
107 TEST_ASSERT_REL(ntohs(hdr.TotalLength), <=, len - ofs);
108 TEST_ASSERT_REL(ntohs(hdr.TotalLength), >, (hdr.VerLen & 0xF) * 4);
109 TEST_ASSERT_REL(ntohs(hdr.FragmentInfo), ==, 0);
111 TEST_ASSERT_REL(hdr.TTL, >, 1); // >1 because there's no intervening hops
112 TEST_ASSERT_REL(hdr.Protocol, ==, proto);
114 if(Src) TEST_ASSERT( memcmp(hdr.SrcAddr, Src, 4) == 0 );
115 if(Dst) TEST_ASSERT( memcmp(hdr.DstAddr, Dst, 4) == 0 );
117 *len_out = ntohs(hdr.TotalLength) - sizeof(hdr);
118 *ofs_out = ofs + (hdr.VerLen & 0xF) * 4;
122 TEST_WARN("Invalid AF(%i) in IP_Pkt_Check", AF);