// // endianness support // static inline uint16 bswaps(uint16 val) { return (((val & 0x00ffU) << 8) | ((val & 0xff00U) >> 8)); } static inline uint32 bswapl(uint32 val) { return (((val & 0x000000ffUL) << 24) | ((val & 0x0000ff00UL) << 8) | ((val & 0x00ff0000UL) >> 8) | ((val & 0xff000000UL) >> 24)); } // Use these macros to convert network bytes to the native byte order. // Note that Risc-V uses little endian while network order is big endian. #define ntohs bswaps #define ntohl bswapl #define htons bswaps #define htonl bswapl // // useful networking headers // #define ETHADDR_LEN 6 // an Ethernet packet header (start of the packet). struct eth { uint8 dhost[ETHADDR_LEN]; uint8 shost[ETHADDR_LEN]; uint16 type; } __attribute__((packed)); #define ETHTYPE_IP 0x0800 // Internet protocol #define ETHTYPE_ARP 0x0806 // Address resolution protocol // an IP packet header (comes after an Ethernet header). struct ip { uint8 ip_vhl; // version << 4 | header length >> 2 uint8 ip_tos; // type of service uint16 ip_len; // total length, including this IP header uint16 ip_id; // identification uint16 ip_off; // fragment offset field uint8 ip_ttl; // time to live uint8 ip_p; // protocol uint16 ip_sum; // checksum, covers just IP header uint32 ip_src, ip_dst; }; #define IPPROTO_ICMP 1 // Control message protocol #define IPPROTO_TCP 6 // Transmission control protocol #define IPPROTO_UDP 17 // User datagram protocol #define MAKE_IP_ADDR(a, b, c, d) \ (((uint32)a << 24) | ((uint32)b << 16) | \ ((uint32)c << 8) | (uint32)d) // a UDP packet header (comes after an IP header). struct udp { uint16 sport; // source port uint16 dport; // destination port uint16 ulen; // length, including udp header, not including IP header uint16 sum; // checksum }; // an ARP packet (comes after an Ethernet header). struct arp { uint16 hrd; // format of hardware address uint16 pro; // format of protocol address uint8 hln; // length of hardware address uint8 pln; // length of protocol address uint16 op; // operation char sha[ETHADDR_LEN]; // sender hardware address uint32 sip; // sender IP address char tha[ETHADDR_LEN]; // target hardware address uint32 tip; // target IP address } __attribute__((packed)); #define ARP_HRD_ETHER 1 // Ethernet enum { ARP_OP_REQUEST = 1, // requests hw addr given protocol addr ARP_OP_REPLY = 2, // replies with the hw addr of the protocol addr }; // an DNS packet (comes after an UDP header). struct dns { uint16 id; // request ID uint8 rd: 1; // recursion desired uint8 tc: 1; // truncated uint8 aa: 1; // authoritive uint8 opcode: 4; uint8 qr: 1; // query/response uint8 rcode: 4; // response code uint8 cd: 1; // checking disabled uint8 ad: 1; // authenticated data uint8 z: 1; uint8 ra: 1; // recursion available uint16 qdcount; // number of question entries uint16 ancount; // number of resource records in answer section uint16 nscount; // number of NS resource records in authority section uint16 arcount; // number of resource records in additional records } __attribute__((packed)); struct dns_question { uint16 qtype; uint16 qclass; } __attribute__((packed)); #define ARECORD (0x0001) #define QCLASS (0x0001) struct dns_data { uint16 type; uint16 class; uint32 ttl; uint16 len; } __attribute__((packed));