1 /*
2  * Copyright (c) 2014 Chris Anderson
3  * Copyright (c) 2014 Brian Swetland
4  *
5  * Use of this source code is governed by a MIT-style
6  * license that can be found in the LICENSE file or at
7  * https://opensource.org/licenses/MIT
8  */
9 #pragma once
10 
11 #include <lib/minip.h>
12 
13 #include <lk/compiler.h>
14 #include <endian.h>
15 #include <lk/list.h>
16 #include <stdint.h>
17 #include <string.h>
18 
19 /* Lib configuration */
20 #define MINIP_USE_UDP_CHECKSUM    0
21 #define MINIP_MTU_SIZE            1536
22 #define MINIP_USE_ARP             1
23 
24 #pragma pack(push, 1)
25 struct arp_pkt {
26     uint16_t htype;
27     uint16_t ptype;
28     uint8_t  hlen;
29     uint8_t  plen;
30     uint16_t oper;
31     uint8_t  sha[6];
32     uint32_t spa;
33     uint8_t  tha[6];
34     uint32_t tpa;
35 };
36 
37 struct ipv4_hdr {
38     uint8_t  ver_ihl;
39     uint8_t  dscp_ecn;
40     uint16_t len;
41     uint16_t id;
42     uint16_t flags_frags;
43     uint8_t  ttl;
44     uint8_t  proto;
45     uint16_t chksum;
46     uint32_t src_addr;
47     uint32_t dst_addr;
48     uint8_t  data[];
49 };
50 
51 struct icmp_pkt {
52     uint8_t  type;
53     uint8_t  code;
54     uint16_t chksum;
55     uint8_t  hdr_data[4];
56     uint8_t  data[];
57 };
58 
59 struct eth_hdr {
60     uint8_t dst_mac[6];
61     uint8_t src_mac[6];
62     uint16_t type;
63 };
64 
65 #pragma pack(pop)
66 
67 enum {
68     ICMP_ECHO_REPLY   = 0,
69     ICMP_ECHO_REQUEST = 8,
70 };
71 
72 enum {
73     IP_PROTO_ICMP = 0x1,
74     IP_PROTO_TCP  = 0x6,
75     IP_PROTO_UDP  = 0x11,
76 };
77 
78 enum {
79     ETH_TYPE_IPV4 = 0x0800,
80     ETH_TYPE_ARP  = 0x0806,
81     ETH_TYPE_IPV6 = 0x88dd,
82 };
83 
84 enum {
85     ARP_OPER_REQUEST = 0x0001,
86     ARP_OPER_REPLY   = 0x0002,
87 };
88 
89 extern tx_func_t minip_tx_handler;
90 extern void *minip_tx_arg;
91 
92 typedef struct udp_hdr udp_hdr_t;
93 static const uint8_t bcast_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
94 typedef uint32_t ipv4_addr;
95 typedef union {
96     uint32_t u;
97     uint8_t b[4];
98 } ipv4_t;
99 
100 // ARP cache
101 void arp_cache_init(void);
102 void arp_cache_update(uint32_t addr, const uint8_t mac[6]);
103 uint8_t *arp_cache_lookup(uint32_t addr);
104 void arp_cache_dump(void);
105 int arp_send_request(uint32_t addr);
106 const uint8_t *arp_get_dest_mac(uint32_t host);
107 
108 uint16_t rfc1701_chksum(const uint8_t *buf, size_t len);
109 uint16_t rfc768_chksum(struct ipv4_hdr *ipv4, udp_hdr_t *udp);
110 uint16_t ones_sum16(uint32_t sum, const void *_buf, int len);
111 
112 // Helper methods for building headers
113 void minip_build_mac_hdr(struct eth_hdr *pkt, const uint8_t *dst, uint16_t type);
114 void minip_build_ipv4_hdr(struct ipv4_hdr *ipv4, uint32_t dst, uint8_t proto, uint16_t len);
115 
116 status_t minip_ipv4_send(pktbuf_t *p, uint32_t dest_addr, uint8_t proto);
117 
118 void tcp_input(pktbuf_t *p, uint32_t src_ip, uint32_t dst_ip);
119 void udp_input(pktbuf_t *p, uint32_t src_ip);
120 
121 const uint8_t *get_dest_mac(uint32_t host);
122 
123 // timers
124 typedef void (*net_timer_callback_t)(void *);
125 
126 typedef struct net_timer {
127     struct list_node node;
128 
129     lk_time_t sched_time;
130 
131     net_timer_callback_t cb;
132     void *arg;
133 } net_timer_t;
134 
135 /* set a net timer. returns true if the timer was not set before and is now */
136 bool net_timer_set(net_timer_t *, net_timer_callback_t, void *callback_args, lk_time_t delay) __NONNULL((1));
137 
138 /* cancels a net timer. returns true if it was previously set and is not now */
139 bool net_timer_cancel(net_timer_t *) __NONNULL();
140 
141 void net_timer_init(void);
142 
mac_addr_copy(uint8_t * dest,const uint8_t * src)143 static inline void mac_addr_copy(uint8_t *dest, const uint8_t *src) {
144     memcpy(dest, src, 6);
145 }
146