simple reliable networking over ethernet. Provides IPv4 ARP, ICMP echo reply, and UDP unicast. Does NOT provide TCP, that's not simple :-).

Committer:
altasoul
Date:
Wed Mar 04 02:04:32 2015 +0000
Revision:
0:6df0a6ed91d4
Child:
2:397316d97354
refactor into Snet

Who changed what in which revision?

UserRevisionLine numberNew contents of line
altasoul 0:6df0a6ed91d4 1 #include "flyer.h"
altasoul 0:6df0a6ed91d4 2 #include "snet.h"
altasoul 0:6df0a6ed91d4 3
altasoul 0:6df0a6ed91d4 4 void handle_icmp_packet(uint8_t *buf, int len);
altasoul 0:6df0a6ed91d4 5 void handle_udp_packet(uint8_t *buf, int len);
altasoul 0:6df0a6ed91d4 6
altasoul 0:6df0a6ed91d4 7 //extern Ethernet eth;
altasoul 0:6df0a6ed91d4 8 //extern uint8_t my_mac[];
altasoul 0:6df0a6ed91d4 9 //uint8_t my_ip[4] = { 192, 168, 32, 191 };
altasoul 0:6df0a6ed91d4 10
altasoul 0:6df0a6ed91d4 11 //extern uint16_t ip_checksum_of(const uint8_t *buf, int len);
altasoul 0:6df0a6ed91d4 12 //extern uint16_t ones_complement_sum(const uint8_t *buf, const int len, int sum);
altasoul 0:6df0a6ed91d4 13
altasoul 0:6df0a6ed91d4 14 //-- IP utilities
altasoul 0:6df0a6ed91d4 15
altasoul 0:6df0a6ed91d4 16 // Calculate the ones' complement sum of a buffer, initialized
altasoul 0:6df0a6ed91d4 17 // See also RFC1071 http://tools.ietf.org/html/rfc1071
altasoul 0:6df0a6ed91d4 18 uint16_t Snet::ones_complement_sum(const uint8_t *buf, int len, int sum) {
altasoul 0:6df0a6ed91d4 19 for (int i=0; i<len/2; i++) {
altasoul 0:6df0a6ed91d4 20 sum += (buf[0] << 8) + (buf[1]);
altasoul 0:6df0a6ed91d4 21 buf += 2;
altasoul 0:6df0a6ed91d4 22 }
altasoul 0:6df0a6ed91d4 23 if (len & 1) sum += buf[0] << 8; // odd length
altasoul 0:6df0a6ed91d4 24 while (sum & 0xffff0000) sum = (sum & 0xffff) + (sum >> 16);
altasoul 0:6df0a6ed91d4 25 return sum;
altasoul 0:6df0a6ed91d4 26 }
altasoul 0:6df0a6ed91d4 27
altasoul 0:6df0a6ed91d4 28 // Calculate the RFC1071 IP checksum. No assumption about byte alignment is made.
altasoul 0:6df0a6ed91d4 29 uint16_t Snet::ip_checksum_of(const uint8_t *buf, const int len) {
altasoul 0:6df0a6ed91d4 30 return ~ones_complement_sum(buf, len, 0);
altasoul 0:6df0a6ed91d4 31 };
altasoul 0:6df0a6ed91d4 32
altasoul 0:6df0a6ed91d4 33 void Snet::turn_ip_packet_around(uint8_t *buf) {
altasoul 0:6df0a6ed91d4 34 memcpy(&buf[ENET_DMAC_O], &buf[ENET_SMAC_O], 6);
altasoul 0:6df0a6ed91d4 35 memcpy(&buf[ENET_SMAC_O], my_mac, 6);
altasoul 0:6df0a6ed91d4 36 memcpy(&buf[IP_DADDR_O], &buf[IP_SADDR_O], 4);
altasoul 0:6df0a6ed91d4 37 memcpy(&buf[IP_SADDR_O], my_ip, 4);
altasoul 0:6df0a6ed91d4 38 };
altasoul 0:6df0a6ed91d4 39
altasoul 0:6df0a6ed91d4 40
altasoul 0:6df0a6ed91d4 41 void Snet::handle_icmp_packet(uint8_t *buf, int len) {
altasoul 0:6df0a6ed91d4 42 #if 0
altasoul 0:6df0a6ed91d4 43 printf("ICMP:");
altasoul 0:6df0a6ed91d4 44 print_hex(&buf[ICMP_HEADER_O], len-ICMP_HEADER_O);
altasoul 0:6df0a6ed91d4 45 #endif
altasoul 0:6df0a6ed91d4 46 #if 0
altasoul 0:6df0a6ed91d4 47 printf("ip header checksum = 0x%x\r\n",
altasoul 0:6df0a6ed91d4 48 ip_checksum_of(&buf[IP_HEADER_O], IP_HEADER_LEN));
altasoul 0:6df0a6ed91d4 49 #endif
altasoul 0:6df0a6ed91d4 50 #if 0
altasoul 0:6df0a6ed91d4 51 printf("icmp checksum = 0x%x\r\n",
altasoul 0:6df0a6ed91d4 52 ip_checksum_of(&buf[ICMP_HEADER_O], len-ICMP_HEADER_O));
altasoul 0:6df0a6ed91d4 53 #endif
altasoul 0:6df0a6ed91d4 54 if (buf[ICMP_TYPE_O] != 8 || buf[ICMP_CODE_O] != 0) return;
altasoul 0:6df0a6ed91d4 55 // Here we have ICMP echo request
altasoul 0:6df0a6ed91d4 56 #if 0
altasoul 0:6df0a6ed91d4 57 printf("ICMP echo request\r\n");
altasoul 0:6df0a6ed91d4 58 #endif
altasoul 0:6df0a6ed91d4 59 buf[ICMP_TYPE_O] = 0x0; // make it an echo reply
altasoul 0:6df0a6ed91d4 60 // Fix the ICMP checksum
altasoul 0:6df0a6ed91d4 61 // HC' = ~(C + (-m) + m') -- [Eqn. 3]
altasoul 0:6df0a6ed91d4 62 // = ~(~HC + ~m + m')
altasoul 0:6df0a6ed91d4 63 // HC' = HC - ~m - m' -- [Eqn. 4] of RFC1624, where:
altasoul 0:6df0a6ed91d4 64 // HC - old checksum in header
altasoul 0:6df0a6ed91d4 65 // C - one's complement sum of old header
altasoul 0:6df0a6ed91d4 66 // HC' - new checksum in header
altasoul 0:6df0a6ed91d4 67 // m - old value of a 16-bit field
altasoul 0:6df0a6ed91d4 68 // m' - new value of a 16-bit field
altasoul 0:6df0a6ed91d4 69 // we have m == 0x800 and m' == 0
altasoul 0:6df0a6ed91d4 70 // so HC' = HC - ~0x800 = HC - 0xf7ff
altasoul 0:6df0a6ed91d4 71 uint32_t sum = (buf[ICMP_CHECKSUM_O] << 8)
altasoul 0:6df0a6ed91d4 72 + buf[ICMP_CHECKSUM_O + 1]
altasoul 0:6df0a6ed91d4 73 - 0xf7ff;
altasoul 0:6df0a6ed91d4 74 if (sum & 0xffff0000) sum -= 1; // handle borrow-around
altasoul 0:6df0a6ed91d4 75 //printf("adj: 0x%x\r\n", sum);
altasoul 0:6df0a6ed91d4 76 buf[ICMP_CHECKSUM_O] = sum >> 8; // type casting takes care of the masking
altasoul 0:6df0a6ed91d4 77 buf[ICMP_CHECKSUM_O + 1] = sum;
altasoul 0:6df0a6ed91d4 78 turn_ip_packet_around(buf);
altasoul 0:6df0a6ed91d4 79 eth.write((char *) buf, len);
altasoul 0:6df0a6ed91d4 80 eth.send();
altasoul 0:6df0a6ed91d4 81 #if 0
altasoul 0:6df0a6ed91d4 82 printf("check new checksums: ip = 0x%x, icmp = 0x%x\r\n",
altasoul 0:6df0a6ed91d4 83 ip_checksum_of(&buf[IP_HEADER_O], IP_HEADER_LEN),
altasoul 0:6df0a6ed91d4 84 ip_checksum_of(&buf[ICMP_HEADER_O], len-ICMP_HEADER_O));
altasoul 0:6df0a6ed91d4 85 #endif
altasoul 0:6df0a6ed91d4 86 #if 1
altasoul 0:6df0a6ed91d4 87 if (int v = ip_checksum_of(&buf[IP_HEADER_O], IP_HEADER_LEN))
altasoul 0:6df0a6ed91d4 88 printf("Bad new IP checksum: %d\r\n", v);
altasoul 0:6df0a6ed91d4 89 if (int v = ip_checksum_of(&buf[ICMP_HEADER_O], len-ICMP_HEADER_O))
altasoul 0:6df0a6ed91d4 90 printf("Bad new ICMP checksum: %d\r\n", v);
altasoul 0:6df0a6ed91d4 91 #endif
altasoul 0:6df0a6ed91d4 92 #if 0
altasoul 0:6df0a6ed91d4 93 printf("sent");
altasoul 0:6df0a6ed91d4 94 print_hex(buf, len);
altasoul 0:6df0a6ed91d4 95 #endif
altasoul 0:6df0a6ed91d4 96 };
altasoul 0:6df0a6ed91d4 97
altasoul 0:6df0a6ed91d4 98
altasoul 0:6df0a6ed91d4 99 void Snet::interpret_inet_packet(uint8_t *buf, int len) {
altasoul 0:6df0a6ed91d4 100 //printf("Got inet:");
altasoul 0:6df0a6ed91d4 101 //print_hex(&buf[ENET_PAYLOAD_O], len-IP_HEADER_O); //DEBUG
altasoul 0:6df0a6ed91d4 102 // skip packets with certain attributes we don't like
altasoul 0:6df0a6ed91d4 103 #if 0
altasoul 0:6df0a6ed91d4 104 printf("ip header checksum = 0x%x\r\n",
altasoul 0:6df0a6ed91d4 105 ip_checksum_of(&buf[IP_HEADER_O], IP_HEADER_LEN));
altasoul 0:6df0a6ed91d4 106 #endif
altasoul 0:6df0a6ed91d4 107 if (buf[IP_VIHL_O] != 0x45
altasoul 0:6df0a6ed91d4 108 || buf[IP_FLAGS_FRAGOFF_O+0] & ~0x40 != 0x00 // allow Don't Fragment flag
altasoul 0:6df0a6ed91d4 109 || buf[IP_FLAGS_FRAGOFF_O+1] != 0x00
altasoul 0:6df0a6ed91d4 110 || memcmp(&buf[IP_DADDR_O], my_ip, 4)) {
altasoul 0:6df0a6ed91d4 111 printf("don't like: fragoff 0x%x, dest %d.%d.%d.%d\r\n",
altasoul 0:6df0a6ed91d4 112 (buf[IP_FLAGS_FRAGOFF_O+0] << 8) + buf[IP_FLAGS_FRAGOFF_O+1],
altasoul 0:6df0a6ed91d4 113 buf[IP_DADDR_O+0],
altasoul 0:6df0a6ed91d4 114 buf[IP_DADDR_O+1],
altasoul 0:6df0a6ed91d4 115 buf[IP_DADDR_O+2],
altasoul 0:6df0a6ed91d4 116 buf[IP_DADDR_O+3]
altasoul 0:6df0a6ed91d4 117 ); //DEBUG
altasoul 0:6df0a6ed91d4 118 return;
altasoul 0:6df0a6ed91d4 119 };
altasoul 0:6df0a6ed91d4 120 if (buf[IP_PROTO_O] == 0x01) handle_icmp_packet(buf, len);
altasoul 0:6df0a6ed91d4 121 else if (buf[IP_PROTO_O] == 0x11) handle_udp_packet(buf, len);
altasoul 0:6df0a6ed91d4 122 else printf("Protocol 0x%x\r\n", buf[IP_PROTO_O]);
altasoul 0:6df0a6ed91d4 123 }