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 };
82 
83 enum {
84     ARP_OPER_REQUEST = 0x0001,
85     ARP_OPER_REPLY   = 0x0002,
86 };
87 
88 extern tx_func_t minip_tx_handler;
89 typedef struct udp_hdr udp_hdr_t;
90 static const uint8_t bcast_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
91 
92 void arp_cache_init(void);
93 void arp_cache_update(uint32_t addr, const uint8_t mac[6]);
94 uint8_t *arp_cache_lookup(uint32_t addr);
95 void arp_cache_dump(void);
96 int arp_send_request(uint32_t addr);
97 const uint8_t *arp_get_dest_mac(uint32_t host);
98 
99 uint16_t rfc1701_chksum(const uint8_t *buf, size_t len);
100 uint16_t rfc768_chksum(struct ipv4_hdr *ipv4, udp_hdr_t *udp);
101 uint16_t ones_sum16(uint32_t sum, const void *_buf, int len);
102 
103 /* Helper methods for building headers */
104 void minip_build_mac_hdr(struct eth_hdr *pkt, const uint8_t *dst, uint16_t type);
105 void minip_build_ipv4_hdr(struct ipv4_hdr *ipv4, uint32_t dst, uint8_t proto, uint16_t len);
106 
107 status_t minip_ipv4_send(pktbuf_t *p, uint32_t dest_addr, uint8_t proto);
108 
109 void tcp_input(pktbuf_t *p, uint32_t src_ip, uint32_t dst_ip);
110 void udp_input(pktbuf_t *p, uint32_t src_ip);
111 
112 const uint8_t *get_dest_mac(uint32_t host);
113 
114 // timers
115 typedef void (*net_timer_callback_t)(void *);
116 
117 typedef struct net_timer {
118     struct list_node node;
119 
120     lk_time_t sched_time;
121 
122     net_timer_callback_t cb;
123     void *arg;
124 } net_timer_t;
125 
126 /* set a net timer. returns true if the timer was not set before and is now */
127 bool net_timer_set(net_timer_t *, net_timer_callback_t, void *callback_args, lk_time_t delay) __NONNULL((1));
128 
129 /* cancels a net timer. returns true if it was previously set and is not now */
130 bool net_timer_cancel(net_timer_t *) __NONNULL();
131 
132 void net_timer_init(void);
133 
mac_addr_copy(uint8_t * dest,const uint8_t * src)134 static inline void mac_addr_copy(uint8_t *dest, const uint8_t *src) {
135     *(uint32_t *)dest = *(const uint32_t *)src;
136     *(uint16_t *)(dest + 4) = *(const uint16_t *)(src + 4);
137 }
138