1/*
2 * Copyright (c) 2014, University of Washington.
3 * All rights reserved.
4 *
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich.
8 * Attn: Systems Group.
9 */
10
11#ifndef ARRANET_IMPL_H
12#define ARRANET_IMPL_H
13
14#ifndef ETHARP_HWADDR_LEN
15#define ETHARP_HWADDR_LEN     6
16#endif
17
18PACK_STRUCT_BEGIN
19struct eth_addr {
20  PACK_STRUCT_FIELD(u8_t addr[ETHARP_HWADDR_LEN]);
21} PACK_STRUCT_STRUCT;
22PACK_STRUCT_END
23
24PACK_STRUCT_BEGIN
25/** Ethernet header */
26struct eth_hdr {
27#if ETH_PAD_SIZE
28  PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]);
29#endif
30  PACK_STRUCT_FIELD(struct eth_addr dest);
31  PACK_STRUCT_FIELD(struct eth_addr src);
32  PACK_STRUCT_FIELD(u16_t type);
33} PACK_STRUCT_STRUCT;
34PACK_STRUCT_END
35
36#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE)
37
38PACK_STRUCT_BEGIN
39/** the ARP message, see RFC 826 ("Packet format") */
40struct etharp_hdr {
41  PACK_STRUCT_FIELD(u16_t hwtype);
42  PACK_STRUCT_FIELD(u16_t proto);
43  PACK_STRUCT_FIELD(u8_t  hwlen);
44  PACK_STRUCT_FIELD(u8_t  protolen);
45  PACK_STRUCT_FIELD(u16_t opcode);
46  PACK_STRUCT_FIELD(struct eth_addr shwaddr);
47  PACK_STRUCT_FIELD(struct ip_addr2 sipaddr);
48  PACK_STRUCT_FIELD(struct eth_addr dhwaddr);
49  PACK_STRUCT_FIELD(struct ip_addr2 dipaddr);
50} PACK_STRUCT_STRUCT;
51PACK_STRUCT_END
52
53#define SIZEOF_ETHARP_HDR 28
54#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR)
55
56#define ETHTYPE_ARP       0x0806U
57#define ETHTYPE_IP        0x0800U
58#define ETHTYPE_VLAN      0x8100U
59#define ETHTYPE_PPPOEDISC 0x8863U  /* PPP Over Ethernet Discovery Stage */
60#define ETHTYPE_PPPOE     0x8864U  /* PPP Over Ethernet Session Stage */
61
62#define ETH_PAD_SIZE          0
63
64/** ARP message types (opcodes) */
65#define ARP_REQUEST 1
66#define ARP_REPLY   2
67
68PACK_STRUCT_BEGIN
69struct ip_hdr {
70  /* version / header length */
71  PACK_STRUCT_FIELD(u8_t _v_hl);
72  /* type of service */
73  PACK_STRUCT_FIELD(u8_t _tos);
74  /* total length */
75  PACK_STRUCT_FIELD(u16_t _len);
76  /* identification */
77  PACK_STRUCT_FIELD(u16_t _id);
78  /* fragment offset field */
79  PACK_STRUCT_FIELD(u16_t _offset);
80#define IP_RF 0x8000U        /* reserved fragment flag */
81#define IP_DF 0x4000U        /* dont fragment flag */
82#define IP_MF 0x2000U        /* more fragments flag */
83#define IP_OFFMASK 0x1fffU   /* mask for fragmenting bits */
84  /* time to live */
85  PACK_STRUCT_FIELD(u8_t _ttl);
86  /* protocol*/
87  PACK_STRUCT_FIELD(u8_t _proto);
88  /* checksum */
89  PACK_STRUCT_FIELD(u16_t _chksum);
90  /* source and destination IP addresses */
91  PACK_STRUCT_FIELD(ip_addr_p_t src);
92  PACK_STRUCT_FIELD(ip_addr_p_t dest);
93} PACK_STRUCT_STRUCT;
94PACK_STRUCT_END
95
96#define IPH_V(hdr)  ((hdr)->_v_hl >> 4)
97#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f)
98#define IPH_TOS(hdr) ((hdr)->_tos)
99#define IPH_LEN(hdr) ((hdr)->_len)
100#define IPH_ID(hdr) ((hdr)->_id)
101#define IPH_OFFSET(hdr) ((hdr)->_offset)
102#define IPH_TTL(hdr) ((hdr)->_ttl)
103#define IPH_PROTO(hdr) ((hdr)->_proto)
104#define IPH_CHKSUM(hdr) ((hdr)->_chksum)
105
106#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (((v) << 4) | (hl))
107#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos)
108#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len)
109#define IPH_ID_SET(hdr, id) (hdr)->_id = (id)
110#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off)
111#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl)
112#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto)
113#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
114
115#define IP_HLEN 20
116
117#define IP_PROTO_IP      0
118#define IP_PROTO_ICMP    1
119#define IP_PROTO_IGMP    2
120#define IP_PROTO_IPENCAP 4
121#define IP_PROTO_UDP     17
122#define IP_PROTO_UDPLITE 136
123#define IP_PROTO_TCP     6
124
125PACK_STRUCT_BEGIN
126struct udp_hdr {
127  PACK_STRUCT_FIELD(u16_t src);
128  PACK_STRUCT_FIELD(u16_t dest);  /* src/dest UDP ports */
129  PACK_STRUCT_FIELD(u16_t len);
130  PACK_STRUCT_FIELD(u16_t chksum);
131} PACK_STRUCT_STRUCT;
132PACK_STRUCT_END
133
134PACK_STRUCT_BEGIN
135struct tcp_hdr {
136  PACK_STRUCT_FIELD(u16_t src);
137  PACK_STRUCT_FIELD(u16_t dest);
138  PACK_STRUCT_FIELD(u32_t seqno);
139  PACK_STRUCT_FIELD(u32_t ackno);
140  PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
141  PACK_STRUCT_FIELD(u16_t wnd);
142  PACK_STRUCT_FIELD(u16_t chksum);
143  PACK_STRUCT_FIELD(u16_t urgp);
144} PACK_STRUCT_STRUCT;
145PACK_STRUCT_END
146
147#define TCP_FIN 0x01U
148#define TCP_SYN 0x02U
149#define TCP_RST 0x04U
150#define TCP_PSH 0x08U
151#define TCP_ACK 0x10U
152#define TCP_URG 0x20U
153#define TCP_ECE 0x40U
154#define TCP_CWR 0x80U
155
156#define TCP_FLAGS 0x3fU
157
158/* Length of the TCP header, excluding options. */
159#define TCP_HLEN 20
160
161#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
162#define TCPH_FLAGS(phdr)  (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
163
164#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
165#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags))
166#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags))
167
168#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
169#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
170
171#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))
172
173/** This returns a TCP header option for MSS in an u32_t */
174#define TCP_BUILD_MSS_OPTION(mss) htonl(0x02040000 | ((mss) & 0xFFFF))
175
176void lwip_mutex_lock(void);
177void lwip_mutex_unlock(void);
178
179// XXX: These assume a little-endian system!
180/* These macros should be calculated by the preprocessor and are used
181   with compile-time constants only (so that there is no little-endian
182   overhead at runtime). */
183#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
184#define PP_NTOHS(x) PP_HTONS(x)
185#define PP_HTONL(x) ((((x) & 0xff) << 24) | \
186                     (((x) & 0xff00) << 8) | \
187                     (((x) & 0xff0000UL) >> 8) | \
188                     (((x) & 0xff000000UL) >> 24))
189#define PP_NTOHL(x) PP_HTONL(x)
190
191#define lwip_htons(x) LWIP_PLATFORM_HTONS(x)
192#define lwip_ntohs(x) LWIP_PLATFORM_HTONS(x)
193#define lwip_htonl(x) LWIP_PLATFORM_HTONL(x)
194#define lwip_ntohl(x) LWIP_PLATFORM_HTONL(x)
195
196#define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif))
197u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif);
198
199#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr)
200u8_t ip4_addr_netmask_valid(u32_t netmask);
201
202u32_t ipaddr_addr(const char *cp);
203int ipaddr_aton(const char *cp, ip_addr_t *addr);
204/** returns ptr to static buffer; not reentrant! */
205char *ipaddr_ntoa(const ip_addr_t *addr);
206char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen);
207
208#endif
209