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