source: trunk/minix/servers/inet/generic/ip.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 9.8 KB
RevLine 
[9]1/*
2ip.c
3
4Copyright 1995 Philip Homburg
5*/
6
7#include "inet.h"
8#include "buf.h"
9#include "event.h"
10#include "type.h"
11
12#include "arp.h"
13#include "assert.h"
14#include "clock.h"
15#include "eth.h"
16#include "icmp.h"
17#include "icmp_lib.h"
18#include "io.h"
19#include "ip.h"
20#include "ip_int.h"
21#include "ipr.h"
22#include "sr.h"
23
24THIS_FILE
25
26FORWARD void ip_close ARGS(( int fd ));
27FORWARD int ip_cancel ARGS(( int fd, int which_operation ));
28FORWARD int ip_select ARGS(( int fd, unsigned operations ));
29
30FORWARD void ip_buffree ARGS(( int priority ));
31#ifdef BUF_CONSISTENCY_CHECK
32FORWARD void ip_bufcheck ARGS(( void ));
33#endif
34FORWARD void ip_bad_callback ARGS(( struct ip_port *ip_port ));
35
36PUBLIC ip_port_t *ip_port_table;
37PUBLIC ip_fd_t ip_fd_table[IP_FD_NR];
38PUBLIC ip_ass_t ip_ass_table[IP_ASS_NR];
39
40PUBLIC void ip_prep()
41{
42 ip_port_table= alloc(ip_conf_nr * sizeof(ip_port_table[0]));
43 icmp_prep();
44}
45
46PUBLIC void ip_init()
47{
48 int i, j, result;
49 ip_ass_t *ip_ass;
50 ip_fd_t *ip_fd;
51 ip_port_t *ip_port;
52 struct ip_conf *icp;
53
54 assert (BUF_S >= sizeof(struct nwio_ethopt));
55 assert (BUF_S >= IP_MAX_HDR_SIZE + ETH_HDR_SIZE);
56 assert (BUF_S >= sizeof(nwio_ipopt_t));
57 assert (BUF_S >= sizeof(nwio_route_t));
58
59 for (i=0, ip_ass= ip_ass_table; i<IP_ASS_NR; i++, ip_ass++)
60 {
61 ip_ass->ia_frags= 0;
62 ip_ass->ia_first_time= 0;
63 ip_ass->ia_port= 0;
64 }
65
66 for (i=0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
67 {
68 ip_fd->if_flags= IFF_EMPTY;
69 ip_fd->if_rdbuf_head= 0;
70 }
71
72 for (i=0, ip_port= ip_port_table, icp= ip_conf;
73 i<ip_conf_nr; i++, ip_port++, icp++)
74 {
75 ip_port->ip_port= i;
76 ip_port->ip_flags= IPF_EMPTY;
77 ip_port->ip_dev_main= (ip_dev_t)ip_bad_callback;
78 ip_port->ip_dev_set_ipaddr= (ip_dev_t)ip_bad_callback;
79 ip_port->ip_dev_send= (ip_dev_send_t)ip_bad_callback;
80 ip_port->ip_dl_type= icp->ic_devtype;
81 ip_port->ip_mtu= IP_DEF_MTU;
82 ip_port->ip_mtu_max= IP_MAX_PACKSIZE;
83
84 switch(ip_port->ip_dl_type)
85 {
86 case IPDL_ETH:
87 ip_port->ip_dl.dl_eth.de_port= icp->ic_port;
88 result= ipeth_init(ip_port);
89 if (result == -1)
90 continue;
91 assert(result == NW_OK);
92 break;
93 case IPDL_PSIP:
94 ip_port->ip_dl.dl_ps.ps_port= icp->ic_port;
95 result= ipps_init(ip_port);
96 if (result == -1)
97 continue;
98 assert(result == NW_OK);
99 break;
100 default:
101 ip_panic(( "unknown ip_dl_type %d",
102 ip_port->ip_dl_type ));
103 break;
104 }
105 ip_port->ip_loopb_head= NULL;
106 ip_port->ip_loopb_tail= NULL;
107 ev_init(&ip_port->ip_loopb_event);
108 ip_port->ip_routeq_head= NULL;
109 ip_port->ip_routeq_tail= NULL;
110 ev_init(&ip_port->ip_routeq_event);
111 ip_port->ip_flags |= IPF_CONFIGURED;
112 ip_port->ip_proto_any= NULL;
113 for (j= 0; j<IP_PROTO_HASH_NR; j++)
114 ip_port->ip_proto[j]= NULL;
115 }
116
117#ifndef BUF_CONSISTENCY_CHECK
118 bf_logon(ip_buffree);
119#else
120 bf_logon(ip_buffree, ip_bufcheck);
121#endif
122
123 icmp_init();
124 ipr_init();
125
126 for (i=0, ip_port= ip_port_table; i<ip_conf_nr; i++, ip_port++)
127 {
128 if (!(ip_port->ip_flags & IPF_CONFIGURED))
129 continue;
130 ip_port->ip_frame_id= (u16_t)get_time();
131
132 sr_add_minor(if2minor(ip_conf[i].ic_ifno, IP_DEV_OFF),
133 i, ip_open, ip_close, ip_read,
134 ip_write, ip_ioctl, ip_cancel, ip_select);
135
136 (*ip_port->ip_dev_main)(ip_port);
137 }
138}
139
140PRIVATE int ip_cancel (fd, which_operation)
141int fd;
142int which_operation;
143{
144 ip_fd_t *ip_fd;
145 acc_t *repl_res;
146 int result;
147
148 ip_fd= &ip_fd_table[fd];
149
150 switch (which_operation)
151 {
152 case SR_CANCEL_IOCTL:
153 assert (ip_fd->if_flags & IFF_IOCTL_IP);
154 ip_fd->if_flags &= ~IFF_IOCTL_IP;
155 repl_res= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
156 (size_t)EINTR, (size_t)0, TRUE);
157 assert (!repl_res);
158 break;
159 case SR_CANCEL_READ:
160 assert (ip_fd->if_flags & IFF_READ_IP);
161 ip_fd->if_flags &= ~IFF_READ_IP;
162 result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
163 (size_t)EINTR, (acc_t *)0, FALSE);
164 assert (!result);
165 break;
166#if 0
167 case SR_CANCEL_WRITE:
168 assert(0);
169 assert (ip_fd->if_flags & IFF_WRITE_MASK);
170 ip_fd->if_flags &= ~IFF_WRITE_MASK;
171 repl_res= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
172 (size_t)EINTR, (size_t)0, FALSE);
173 assert (!repl_res);
174 break;
175#endif
176 default:
177 ip_panic(( "unknown cancel request" ));
178 break;
179 }
180 return NW_OK;
181}
182
183PRIVATE int ip_select(fd, operations)
184int fd;
185unsigned operations;
186{
187 printf("ip_select: not implemented\n");
188 return 0;
189}
190
191PUBLIC int ip_open (port, srfd, get_userdata, put_userdata, put_pkt,
192 select_res)
193int port;
194int srfd;
195get_userdata_t get_userdata;
196put_userdata_t put_userdata;
197put_pkt_t put_pkt;
198select_res_t select_res;
199{
200 int i;
201 ip_fd_t *ip_fd;
202 ip_port_t *ip_port;
203
204 ip_port= &ip_port_table[port];
205 if (!(ip_port->ip_flags & IPF_CONFIGURED))
206 return ENXIO;
207
208 for (i=0; i<IP_FD_NR && (ip_fd_table[i].if_flags & IFF_INUSE);
209 i++);
210
211 if (i>=IP_FD_NR)
212 {
213 DBLOCK(1, printf("out of fds\n"));
214 return EAGAIN;
215 }
216
217 ip_fd= &ip_fd_table[i];
218
219 ip_fd->if_flags= IFF_INUSE;
220
221 ip_fd->if_ipopt.nwio_flags= NWIO_DEFAULT;
222 ip_fd->if_ipopt.nwio_tos= 0;
223 ip_fd->if_ipopt.nwio_df= FALSE;
224 ip_fd->if_ipopt.nwio_ttl= 255;
225 ip_fd->if_ipopt.nwio_hdropt.iho_opt_siz= 0;
226
227 ip_fd->if_port= ip_port;
228 ip_fd->if_srfd= srfd;
229 assert(ip_fd->if_rdbuf_head == NULL);
230 ip_fd->if_get_userdata= get_userdata;
231 ip_fd->if_put_userdata= put_userdata;
232 ip_fd->if_put_pkt= put_pkt;
233
234 return i;
235}
236
237PRIVATE void ip_close (fd)
238int fd;
239{
240 ip_fd_t *ip_fd;
241 acc_t *pack;
242
243 ip_fd= &ip_fd_table[fd];
244
245 assert ((ip_fd->if_flags & IFF_INUSE) &&
246 !(ip_fd->if_flags & IFF_BUSY));
247
248 if (ip_fd->if_flags & IFF_OPTSET)
249 ip_unhash_proto(ip_fd);
250 while (ip_fd->if_rdbuf_head)
251 {
252 pack= ip_fd->if_rdbuf_head;
253 ip_fd->if_rdbuf_head= pack->acc_ext_link;
254 bf_afree(pack);
255 }
256 ip_fd->if_flags= IFF_EMPTY;
257}
258
259PRIVATE void ip_buffree(priority)
260int priority;
261{
262 int i;
263 ip_port_t *ip_port;
264 ip_fd_t *ip_fd;
265 ip_ass_t *ip_ass;
266 acc_t *pack, *next_pack;
267
268 for (i= 0, ip_port= ip_port_table; i<ip_conf_nr; i++, ip_port++)
269 {
270 if (ip_port->ip_dl_type == IPDL_ETH)
271 {
272 /* Can't free de_frame.
273 * bf_check_acc(ip_port->ip_dl.dl_eth.de_frame);
274 */
275 if (priority == IP_PRI_PORTBUFS)
276 {
277 next_pack= ip_port->ip_dl.dl_eth.de_arp_head;
278 while(next_pack != NULL)
279 {
280 pack= next_pack;
281 next_pack= pack->acc_ext_link;
282 bf_afree(pack);
283 }
284 ip_port->ip_dl.dl_eth.de_arp_head= next_pack;
285
286 next_pack= ip_port->ip_dl.dl_eth.de_q_head;
287 while(next_pack != NULL)
288 {
289 pack= next_pack;
290 next_pack= pack->acc_ext_link;
291 bf_afree(pack);
292 }
293 ip_port->ip_dl.dl_eth.de_q_head= next_pack;
294 }
295 }
296 else if (ip_port->ip_dl_type == IPDL_PSIP)
297 {
298 if (priority == IP_PRI_PORTBUFS)
299 {
300 next_pack= ip_port->ip_dl.dl_ps.ps_send_head;
301 while (next_pack != NULL)
302 {
303 pack= next_pack;
304 next_pack= pack->acc_ext_link;
305 bf_afree(pack);
306 }
307 ip_port->ip_dl.dl_ps.ps_send_head= next_pack;
308 }
309 }
310 if (priority == IP_PRI_PORTBUFS)
311 {
312 next_pack= ip_port->ip_loopb_head;
313 while(next_pack && next_pack->acc_ext_link)
314 {
315 pack= next_pack;
316 next_pack= pack->acc_ext_link;
317 bf_afree(pack);
318 }
319 if (next_pack)
320 {
321 if (ev_in_queue(&ip_port->ip_loopb_event))
322 {
323#if DEBUG
324 printf(
325"not freeing ip_loopb_head, ip_loopb_event enqueued\n");
326#endif
327 }
328 else
329 {
330 bf_afree(next_pack);
331 next_pack= NULL;
332 }
333 }
334 ip_port->ip_loopb_head= next_pack;
335
336 next_pack= ip_port->ip_routeq_head;
337 while(next_pack && next_pack->acc_ext_link)
338 {
339 pack= next_pack;
340 next_pack= pack->acc_ext_link;
341 bf_afree(pack);
342 }
343 if (next_pack)
344 {
345 if (ev_in_queue(&ip_port->ip_routeq_event))
346 {
347#if DEBUG
348 printf(
349"not freeing ip_loopb_head, ip_routeq_event enqueued\n");
350#endif
351 }
352 else
353 {
354 bf_afree(next_pack);
355 next_pack= NULL;
356 }
357 }
358 ip_port->ip_routeq_head= next_pack;
359 }
360 }
361 if (priority == IP_PRI_FDBUFS_EXTRA)
362 {
363 for (i= 0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
364 {
365 while (ip_fd->if_rdbuf_head &&
366 ip_fd->if_rdbuf_head->acc_ext_link)
367 {
368 pack= ip_fd->if_rdbuf_head;
369 ip_fd->if_rdbuf_head= pack->acc_ext_link;
370 bf_afree(pack);
371 }
372 }
373 }
374 if (priority == IP_PRI_FDBUFS)
375 {
376 for (i= 0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
377 {
378 while (ip_fd->if_rdbuf_head)
379 {
380 pack= ip_fd->if_rdbuf_head;
381 ip_fd->if_rdbuf_head= pack->acc_ext_link;
382 bf_afree(pack);
383 }
384 }
385 }
386 if (priority == IP_PRI_ASSBUFS)
387 {
388 for (i= 0, ip_ass= ip_ass_table; i<IP_ASS_NR; i++, ip_ass++)
389 {
390 next_pack= ip_ass->ia_frags;
391 while(ip_ass->ia_frags != NULL)
392 {
393 pack= ip_ass->ia_frags;
394 ip_ass->ia_frags= pack->acc_ext_link;
395 bf_afree(pack);
396 }
397 ip_ass->ia_first_time= 0;
398 }
399 }
400}
401
402#ifdef BUF_CONSISTENCY_CHECK
403PRIVATE void ip_bufcheck()
404{
405 int i;
406 ip_port_t *ip_port;
407 ip_fd_t *ip_fd;
408 ip_ass_t *ip_ass;
409 acc_t *pack;
410
411 for (i= 0, ip_port= ip_port_table; i<ip_conf_nr; i++, ip_port++)
412 {
413 if (ip_port->ip_dl_type == IPDL_ETH)
414 {
415 bf_check_acc(ip_port->ip_dl.dl_eth.de_frame);
416 for (pack= ip_port->ip_dl.dl_eth.de_q_head; pack;
417 pack= pack->acc_ext_link)
418 {
419 bf_check_acc(pack);
420 }
421 for (pack= ip_port->ip_dl.dl_eth.de_arp_head; pack;
422 pack= pack->acc_ext_link)
423 {
424 bf_check_acc(pack);
425 }
426 }
427 else if (ip_port->ip_dl_type == IPDL_PSIP)
428 {
429 for (pack= ip_port->ip_dl.dl_ps.ps_send_head; pack;
430 pack= pack->acc_ext_link)
431 {
432 bf_check_acc(pack);
433 }
434 }
435 for (pack= ip_port->ip_loopb_head; pack;
436 pack= pack->acc_ext_link)
437 {
438 bf_check_acc(pack);
439 }
440 for (pack= ip_port->ip_routeq_head; pack;
441 pack= pack->acc_ext_link)
442 {
443 bf_check_acc(pack);
444 }
445 }
446 for (i= 0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
447 {
448 for (pack= ip_fd->if_rdbuf_head; pack;
449 pack= pack->acc_ext_link)
450 {
451 bf_check_acc(pack);
452 }
453 }
454 for (i= 0, ip_ass= ip_ass_table; i<IP_ASS_NR; i++, ip_ass++)
455 {
456 for (pack= ip_ass->ia_frags; pack; pack= pack->acc_ext_link)
457 bf_check_acc(pack);
458 }
459}
460#endif /* BUF_CONSISTENCY_CHECK */
461
462PRIVATE void ip_bad_callback(ip_port)
463struct ip_port *ip_port;
464{
465 ip_panic(( "no callback filled in for port %d", ip_port->ip_port ));
466}
467
468/*
469 * $PchId: ip.c,v 1.19 2005/06/28 14:17:40 philip Exp $
470 */
Note: See TracBrowser for help on using the repository browser.