xref: /minix/minix/net/lwip/lwip.c (revision 7f5f010b)
1 #include <unistd.h>
2 #include <minix/timers.h>
3 #include <sys/svrctl.h>
4 #include <minix/ds.h>
5 #include <minix/endpoint.h>
6 #include <errno.h>
7 #include <minix/sef.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <minix/chardriver.h>
12 #include <minix/syslib.h>
13 #include <minix/sysutil.h>
14 #include <minix/timers.h>
15 #include <minix/netsock.h>
16 
17 #include "proto.h"
18 
19 #include <lwip/mem.h>
20 #include <lwip/pbuf.h>
21 #include <lwip/stats.h>
22 #include <lwip/netif.h>
23 #include <netif/etharp.h>
24 #include <lwip/tcp_impl.h>
25 
26 endpoint_t lwip_ep;
27 
28 static minix_timer_t tcp_ftmr, tcp_stmr, arp_tmr;
29 static int arp_ticks, tcp_fticks, tcp_sticks;
30 
31 static struct netif * netif_lo;
32 
33 extern struct sock_ops sock_udp_ops;
34 extern struct sock_ops sock_tcp_ops;
35 extern struct sock_ops sock_raw_ip_ops;
36 
37 static void sys_init(void)
38 {
39 }
40 
41 static void arp_watchdog(__unused minix_timer_t *tp)
42 {
43 	etharp_tmr();
44 	set_timer(&arp_tmr, arp_ticks, arp_watchdog, 0);
45 }
46 
47 static void tcp_fwatchdog(__unused minix_timer_t *tp)
48 {
49 	tcp_fasttmr();
50 	set_timer(&tcp_ftmr, tcp_fticks, tcp_fwatchdog, 0);
51 }
52 
53 static void tcp_swatchdog(__unused minix_timer_t *tp)
54 {
55 	tcp_slowtmr();
56 	set_timer(&tcp_ftmr, tcp_sticks, tcp_swatchdog, 0);
57 }
58 
59 static int sef_cb_init_fresh(__unused int type, __unused sef_init_info_t *info)
60 {
61 	int err;
62 	unsigned int hz;
63 
64 	char my_name[16];
65 	int my_priv;
66 
67 	err = sys_whoami(&lwip_ep, my_name, sizeof(my_name), &my_priv);
68 	if (err != OK)
69 		panic("Cannot get own endpoint");
70 
71 	nic_init_all();
72 	inet_read_conf();
73 
74 	/* init lwip library */
75 	stats_init();
76 	sys_init();
77 	mem_init();
78 	memp_init();
79 	pbuf_init();
80 
81 	hz = sys_hz();
82 
83 	arp_ticks = ARP_TMR_INTERVAL / (1000 / hz);
84 	tcp_fticks = TCP_FAST_INTERVAL / (1000 / hz);
85 	tcp_sticks = TCP_SLOW_INTERVAL / (1000 / hz);
86 
87 	etharp_init();
88 
89 	set_timer(&arp_tmr, arp_ticks, arp_watchdog, 0);
90 	set_timer(&tcp_ftmr, tcp_fticks, tcp_fwatchdog, 0);
91 	set_timer(&tcp_stmr, tcp_sticks, tcp_swatchdog, 0);
92 
93 	netif_init();
94 	netif_lo = netif_find(__UNCONST("lo0"));
95 
96 	/* Read configuration. */
97 #if 0
98 	nw_conf();
99 
100 	/* Get a random number */
101 	timerand= 1;
102 	fd = open(RANDOM_DEV_NAME, O_RDONLY | O_NONBLOCK);
103 	if (fd != -1)
104 	{
105 		err= read(fd, randbits, sizeof(randbits));
106 		if (err == sizeof(randbits))
107 			timerand= 0;
108 		else
109 		{
110 			printf("inet: unable to read random data from %s: %s\n",
111 				RANDOM_DEV_NAME, err == -1 ? strerror(errno) :
112 				err == 0 ? "EOF" : "not enough data");
113 		}
114 		close(fd);
115 	}
116 	else
117 	{
118 		printf("inet: unable to open random device %s: %s\n",
119 				RANDOM_DEV_NAME, strerror(errno));
120 	}
121 	if (timerand)
122 	{
123 		printf("inet: using current time for random-number seed\n");
124 		err= gettimeofday(&tv, NULL);
125 		if (err == -1)
126 		{
127 			printf("sysutime failed: %s\n", strerror(errno));
128 			exit(1);
129 		}
130 		memcpy(randbits, &tv, sizeof(tv));
131 	}
132 	init_rand256(randbits);
133 #endif
134 
135 	/* Subscribe to driver events for network drivers. */
136 	if ((err = ds_subscribe("drv\\.net\\..*",
137 					DSF_INITIAL | DSF_OVERWRITE)) != OK)
138 		panic(("inet: can't subscribe to driver events"));
139 
140 	/* Announce we are up. LWIP announces its presence to VFS just like
141 	 * any other character driver.
142 	 */
143 	chardriver_announce();
144 
145 	return(OK);
146 }
147 
148 static void sef_local_startup(void)
149 {
150 	/* Register init callbacks. */
151 	sef_setcb_init_fresh(sef_cb_init_fresh);
152 	sef_setcb_init_restart(sef_cb_init_fresh);
153 
154 	/* No live update support for now. */
155 
156 	/* Let SEF perform startup. */
157 	sef_startup();
158 }
159 
160 static void ds_event(void)
161 {
162 	char key[DS_MAX_KEYLEN];
163 	const char *driver_prefix = "drv.net.";
164 	char *label;
165 	u32_t value;
166 	int type;
167 	endpoint_t owner_endpoint;
168 	int r;
169         int prefix_len;
170 
171         prefix_len = strlen(driver_prefix);
172 
173 	/* We may get one notification for multiple updates from DS. Get events
174 	 * and owners from DS, until DS tells us that there are no more.
175 	 */
176 	while ((r = ds_check(key, &type, &owner_endpoint)) == OK) {
177 		r = ds_retrieve_u32(key, &value);
178 		if(r != OK) {
179 			printf("LWIP : ds_event: ds_retrieve_u32 failed\n");
180 			return;
181 		}
182 
183 		/* Only check for network driver up events. */
184 		if(strncmp(key, driver_prefix, prefix_len)
185 		  || value != DS_DRIVER_UP) {
186 			return;
187 		}
188 
189 		/* The driver label comes after the prefix. */
190 		label = key + strlen(driver_prefix);
191 
192 		/* A driver is (re)started. */
193 		driver_up(label, owner_endpoint);
194 	}
195 
196 	if(r != ENOENT)
197 		printf("LWIP : ds_event: ds_check failed: %d\n", r);
198 }
199 
200 static void netif_poll_lo(void)
201 {
202 	if (netif_lo == NULL)
203 		return;
204 
205 	while (netif_lo->loop_first)
206 		netif_poll(netif_lo);
207 }
208 
209 int socket_open(devminor_t minor)
210 {
211         struct sock_ops * ops;
212         struct socket * sock;
213         int ret = OK;
214 
215         switch (minor) {
216         case SOCK_TYPE_TCP:
217                 ops = &sock_tcp_ops;
218                 break;
219         case SOCK_TYPE_UDP:
220                 ops = &sock_udp_ops;
221                 break;
222         case SOCK_TYPE_IP:
223                 ops = &sock_raw_ip_ops;
224                 break;
225         default:
226                 if (minor - SOCK_TYPES  < MAX_DEVS)
227 			return nic_open(minor - SOCK_TYPES);
228 
229                 printf("LWIP unknown socket type %d\n", minor);
230                 return EINVAL;
231         }
232 
233         sock = get_unused_sock();
234         if (!sock) {
235                 printf("LWIP : no free socket\n");
236                 return EAGAIN;
237         }
238 
239         sock->ops = ops;
240         sock->select_ep = NONE;
241         sock->recv_data_size = 0;
242 
243         if (sock->ops && sock->ops->open)
244                 ret = sock->ops->open(sock);
245 
246         if (ret == OK) {
247                 debug_print("new socket %ld", get_sock_num(sock));
248                 ret = get_sock_num(sock);
249         } else {
250                 debug_print("failed %d", ret);
251 		/* FIXME: shouldn't sock be freed now? */
252         }
253 	return ret;
254 }
255 
256 int main(__unused int argc, __unused char ** argv)
257 {
258 	sef_local_startup();
259 
260 	for(;;) {
261 		int err, ipc_status;
262 		message m;
263 
264 		netif_poll_lo();
265 
266 		mq_process();
267 
268 		if ((err = sef_receive_status(ANY, &m, &ipc_status)) != OK) {
269 			printf("LWIP : sef_receive_status errr %d\n", err);
270 			continue;
271 		}
272 
273 		if (m.m_source == VFS_PROC_NR)
274 			socket_request(&m, ipc_status);
275 		else if (is_ipc_notify(ipc_status)) {
276 			switch (m.m_source) {
277 			case CLOCK:
278 				expire_timers(m.m_notify.timestamp);
279 				break;
280 			case DS_PROC_NR:
281 				ds_event();
282 				break;
283 			case PM_PROC_NR:
284 				panic("LWIP : unhandled event from PM");
285 				break;
286 			default:
287 				printf("LWIP : unexpected notify from %d\n",
288 								m.m_source);
289 				continue;
290 			}
291 		} else
292 			/* all other request can be from drivers only */
293 			driver_request(&m);
294 	}
295 
296 	return 0;
297 }
298