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