source: trunk/minix/servers/inet/generic/ip_eth.c@ 11

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

Minix 3.1.2a

File size: 16.6 KB
RevLine 
[9]1/*
2generic/ip_eth.c
3
4Ethernet specific part of the IP implementation
5
6Created: Apr 22, 1993 by Philip Homburg
7
8Copyright 1995 Philip Homburg
9*/
10
11#include "inet.h"
12#include "type.h"
13#include "arp.h"
14#include "assert.h"
15#include "buf.h"
16#include "clock.h"
17#include "eth.h"
18#include "event.h"
19#include "icmp_lib.h"
20#include "io.h"
21#include "ip.h"
22#include "ip_int.h"
23
24THIS_FILE
25
26typedef struct xmit_hdr
27{
28 time_t xh_time;
29 ipaddr_t xh_ipaddr;
30} xmit_hdr_t;
31
32PRIVATE ether_addr_t broadcast_ethaddr=
33{
34 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
35};
36PRIVATE ether_addr_t ipmulticast_ethaddr=
37{
38 { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }
39};
40
41FORWARD void do_eth_read ARGS(( ip_port_t *port ));
42FORWARD acc_t *get_eth_data ARGS(( int fd, size_t offset,
43 size_t count, int for_ioctl ));
44FORWARD int put_eth_data ARGS(( int fd, size_t offset,
45 acc_t *data, int for_ioctl ));
46FORWARD void ipeth_main ARGS(( ip_port_t *port ));
47FORWARD void ipeth_set_ipaddr ARGS(( ip_port_t *port ));
48FORWARD void ipeth_restart_send ARGS(( ip_port_t *ip_port ));
49FORWARD int ipeth_send ARGS(( struct ip_port *ip_port, ipaddr_t dest,
50 acc_t *pack, int type ));
51FORWARD void ipeth_arp_reply ARGS(( int ip_port_nr, ipaddr_t ipaddr,
52 ether_addr_t *dst_ether_ptr ));
53FORWARD int ipeth_update_ttl ARGS(( time_t enq_time, time_t now,
54 acc_t *eth_pack ));
55FORWARD void ip_eth_arrived ARGS(( int port, acc_t *pack,
56 size_t pack_size ));
57
58
59PUBLIC int ipeth_init(ip_port)
60ip_port_t *ip_port;
61{
62 assert(BUF_S >= sizeof(xmit_hdr_t));
63 assert(BUF_S >= sizeof(eth_hdr_t));
64
65 ip_port->ip_dl.dl_eth.de_fd= eth_open(ip_port->
66 ip_dl.dl_eth.de_port, ip_port->ip_port,
67 get_eth_data, put_eth_data, ip_eth_arrived,
68 0 /* no select_res */);
69 if (ip_port->ip_dl.dl_eth.de_fd < 0)
70 {
71 DBLOCK(1, printf("ip.c: unable to open eth port\n"));
72 return -1;
73 }
74 ip_port->ip_dl.dl_eth.de_state= IES_EMPTY;
75 ip_port->ip_dl.dl_eth.de_flags= IEF_EMPTY;
76 ip_port->ip_dl.dl_eth.de_q_head= NULL;
77 ip_port->ip_dl.dl_eth.de_q_tail= NULL;
78 ip_port->ip_dl.dl_eth.de_arp_head= NULL;
79 ip_port->ip_dl.dl_eth.de_arp_tail= NULL;
80 ip_port->ip_dev_main= ipeth_main;
81 ip_port->ip_dev_set_ipaddr= ipeth_set_ipaddr;
82 ip_port->ip_dev_send= ipeth_send;
83 ip_port->ip_mtu= ETH_MAX_PACK_SIZE-ETH_HDR_SIZE;
84 ip_port->ip_mtu_max= ip_port->ip_mtu;
85 return 0;
86}
87
88PRIVATE void ipeth_main(ip_port)
89ip_port_t *ip_port;
90{
91 int result;
92
93 switch (ip_port->ip_dl.dl_eth.de_state)
94 {
95 case IES_EMPTY:
96 ip_port->ip_dl.dl_eth.de_state= IES_SETPROTO;
97
98 result= eth_ioctl(ip_port->ip_dl.dl_eth.de_fd, NWIOSETHOPT);
99 if (result == NW_SUSPEND)
100 ip_port->ip_dl.dl_eth.de_flags |= IEF_SUSPEND;
101 if (result<0)
102 {
103 DBLOCK(1, printf("eth_ioctl(..,0x%lx)=%d\n",
104 (unsigned long)NWIOSETHOPT, result));
105 return;
106 }
107 if (ip_port->ip_dl.dl_eth.de_state != IES_SETPROTO)
108 return;
109 /* drops through */
110 case IES_SETPROTO:
111 result= arp_set_cb(ip_port->ip_dl.dl_eth.de_port,
112 ip_port->ip_port,
113 ipeth_arp_reply);
114 if (result != NW_OK)
115 {
116 printf("ipeth_main: arp_set_cb failed: %d\n",
117 result);
118 return;
119 }
120
121 /* Wait until the interface is configured up. */
122 ip_port->ip_dl.dl_eth.de_state= IES_GETIPADDR;
123 if (!(ip_port->ip_flags & IPF_IPADDRSET))
124 {
125 ip_port->ip_dl.dl_eth.de_flags |= IEF_SUSPEND;
126 return;
127 }
128
129 /* fall through */
130 case IES_GETIPADDR:
131 ip_port->ip_dl.dl_eth.de_state= IES_MAIN;
132 do_eth_read(ip_port);
133 return;
134 default:
135 ip_panic(( "unknown state: %d",
136 ip_port->ip_dl.dl_eth.de_state));
137 }
138}
139
140PRIVATE acc_t *get_eth_data (fd, offset, count, for_ioctl)
141int fd;
142size_t offset;
143size_t count;
144int for_ioctl;
145{
146 ip_port_t *ip_port;
147 acc_t *data;
148 int result;
149
150 ip_port= &ip_port_table[fd];
151
152 switch (ip_port->ip_dl.dl_eth.de_state)
153 {
154 case IES_SETPROTO:
155 if (!count)
156 {
157 result= (int)offset;
158 if (result<0)
159 {
160 ip_port->ip_dl.dl_eth.de_state= IES_ERROR;
161 break;
162 }
163 if (ip_port->ip_dl.dl_eth.de_flags & IEF_SUSPEND)
164 ipeth_main(ip_port);
165 return NW_OK;
166 }
167 assert ((!offset) && (count == sizeof(struct nwio_ethopt)));
168 {
169 struct nwio_ethopt *ethopt;
170 acc_t *acc;
171
172 acc= bf_memreq(sizeof(*ethopt));
173 ethopt= (struct nwio_ethopt *)ptr2acc_data(acc);
174 ethopt->nweo_flags= NWEO_COPY|NWEO_EN_BROAD|
175 NWEO_EN_MULTI|NWEO_TYPESPEC;
176 ethopt->nweo_type= HTONS(ETH_IP_PROTO);
177 return acc;
178 }
179
180 case IES_MAIN:
181 if (!count)
182 {
183 result= (int)offset;
184 if (result<0)
185 ip_warning(( "error on write: %d\n", result ));
186 bf_afree (ip_port->ip_dl.dl_eth.de_frame);
187 ip_port->ip_dl.dl_eth.de_frame= 0;
188
189 if (ip_port->ip_dl.dl_eth.de_flags & IEF_WRITE_SP)
190 {
191 ip_port->ip_dl.dl_eth.de_flags &=
192 ~IEF_WRITE_SP;
193 ipeth_restart_send(ip_port);
194 }
195 return NW_OK;
196 }
197 data= bf_cut (ip_port->ip_dl.dl_eth.de_frame, offset, count);
198 assert (data);
199 return data;
200 default:
201 printf(
202 "get_eth_data(%d, 0x%d, 0x%d) called but ip_state=0x%x\n",
203 fd, offset, count, ip_port->ip_dl.dl_eth.de_state);
204 break;
205 }
206 return 0;
207}
208
209PRIVATE int put_eth_data (port, offset, data, for_ioctl)
210int port;
211size_t offset;
212acc_t *data;
213int for_ioctl;
214{
215 ip_port_t *ip_port;
216 int result;
217
218 ip_port= &ip_port_table[port];
219
220 assert(0);
221
222 if (ip_port->ip_dl.dl_eth.de_flags & IEF_READ_IP)
223 {
224 if (!data)
225 {
226 result= (int)offset;
227 if (result<0)
228 {
229 DBLOCK(1, printf(
230 "ip.c: put_eth_data(..,%d,..)\n", result));
231 return NW_OK;
232 }
233 if (ip_port->ip_dl.dl_eth.de_flags & IEF_READ_SP)
234 {
235 ip_port->ip_dl.dl_eth.de_flags &=
236 ~(IEF_READ_IP|IEF_READ_SP);
237 do_eth_read(ip_port);
238 }
239 else
240 ip_port->ip_dl.dl_eth.de_flags &= ~IEF_READ_IP;
241 return NW_OK;
242 }
243 assert (!offset);
244 /* Warning: the above assertion is illegal; puts and
245 gets of data can be brokenup in any piece the server
246 likes. However we assume that the server is eth.c
247 and it transfers only whole packets. */
248 ip_eth_arrived(port, data, bf_bufsize(data));
249 return NW_OK;
250 }
251 printf("ip_port->ip_dl.dl_eth.de_state= 0x%x",
252 ip_port->ip_dl.dl_eth.de_state);
253 ip_panic (( "strange status" ));
254}
255
256PRIVATE void ipeth_set_ipaddr(ip_port)
257ip_port_t *ip_port;
258{
259 arp_set_ipaddr (ip_port->ip_dl.dl_eth.de_port, ip_port->ip_ipaddr);
260 if (ip_port->ip_dl.dl_eth.de_state == IES_GETIPADDR)
261 ipeth_main(ip_port);
262}
263
264PRIVATE int ipeth_send(ip_port, dest, pack, type)
265struct ip_port *ip_port;
266ipaddr_t dest;
267acc_t *pack;
268int type;
269{
270 int i, r;
271 acc_t *eth_pack, *tail;
272 size_t pack_size;
273 eth_hdr_t *eth_hdr;
274 xmit_hdr_t *xmit_hdr;
275 ipaddr_t hostpart, tmpaddr;
276 time_t t;
277 u32_t *p;
278
279 /* Start optimistic: the arp will succeed without blocking and the
280 * ethernet packet can be sent without blocking also. Start with
281 * the allocation of the ethernet header.
282 */
283 eth_pack= bf_memreq(sizeof(*eth_hdr));
284 assert(eth_pack->acc_next == NULL);
285 eth_pack->acc_next= pack;
286 pack_size= bf_bufsize(eth_pack);
287 if (pack_size<ETH_MIN_PACK_SIZE)
288 {
289 tail= bf_memreq(ETH_MIN_PACK_SIZE-pack_size);
290
291 /* Clear padding */
292 for (i= (ETH_MIN_PACK_SIZE-pack_size)/sizeof(*p),
293 p= (u32_t *)ptr2acc_data(tail);
294 i >= 0; i--, p++)
295 {
296 *p= 0xdeadbeef;
297 }
298
299 eth_pack= bf_append(eth_pack, tail);
300 }
301 eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
302
303 /* Lookup the ethernet address */
304 if (type != IP_LT_NORMAL)
305 {
306 if (type == IP_LT_BROADCAST)
307 eth_hdr->eh_dst= broadcast_ethaddr;
308 else
309 {
310 tmpaddr= ntohl(dest);
311 eth_hdr->eh_dst= ipmulticast_ethaddr;
312 eth_hdr->eh_dst.ea_addr[5]= tmpaddr & 0xff;
313 eth_hdr->eh_dst.ea_addr[4]= (tmpaddr >> 8) & 0xff;
314 eth_hdr->eh_dst.ea_addr[3]= (tmpaddr >> 16) & 0x7f;
315 }
316 }
317 else
318 {
319 if ((dest ^ ip_port->ip_ipaddr) & ip_port->ip_subnetmask)
320 {
321 ip_panic(( "invalid destination" ));
322 }
323
324 hostpart= (dest & ~ip_port->ip_subnetmask);
325 assert(dest != ip_port->ip_ipaddr);
326
327 r= arp_ip_eth(ip_port->ip_dl.dl_eth.de_port,
328 dest, &eth_hdr->eh_dst);
329 if (r == NW_SUSPEND)
330 {
331 /* Unfortunately, the arp takes some time, use
332 * the ethernet header to store the next hop
333 * ip address and the current time.
334 */
335 xmit_hdr= (xmit_hdr_t *)eth_hdr;
336 xmit_hdr->xh_time= get_time();
337 xmit_hdr->xh_ipaddr= dest;
338 eth_pack->acc_ext_link= NULL;
339 if (ip_port->ip_dl.dl_eth.de_arp_head == NULL)
340 ip_port->ip_dl.dl_eth.de_arp_head= eth_pack;
341 else
342 {
343 ip_port->ip_dl.dl_eth.de_arp_tail->
344 acc_ext_link= eth_pack;
345 }
346 ip_port->ip_dl.dl_eth.de_arp_tail= eth_pack;
347 return NW_OK;
348 }
349 if (r == EDSTNOTRCH)
350 {
351 bf_afree(eth_pack);
352 return EDSTNOTRCH;
353 }
354 assert(r == NW_OK);
355 }
356
357 /* If we have no write in progress, we can try to send the ethernet
358 * packet using eth_send. If the IP packet is larger than mtu,
359 * enqueue the packet and let ipeth_restart_send deal with it.
360 */
361 pack_size= bf_bufsize(eth_pack);
362 if (ip_port->ip_dl.dl_eth.de_frame == NULL && pack_size <=
363 ip_port->ip_mtu + sizeof(*eth_hdr))
364 {
365 r= eth_send(ip_port->ip_dl.dl_eth.de_fd,
366 eth_pack, pack_size);
367 if (r == NW_OK)
368 return NW_OK;
369
370 /* A non-blocking send is not possible, start a regular
371 * send.
372 */
373 assert(r == NW_WOULDBLOCK);
374 ip_port->ip_dl.dl_eth.de_frame= eth_pack;
375 r= eth_write(ip_port->ip_dl.dl_eth.de_fd, pack_size);
376 if (r == NW_SUSPEND)
377 {
378 assert(!(ip_port->ip_dl.dl_eth.de_flags &
379 IEF_WRITE_SP));
380 ip_port->ip_dl.dl_eth.de_flags |= IEF_WRITE_SP;
381 }
382 assert(r == NW_OK || r == NW_SUSPEND);
383 return NW_OK;
384 }
385
386 /* Enqueue the packet, and store the current time, in the
387 * space for the ethernet source address.
388 */
389 t= get_time();
390 assert(sizeof(t) <= sizeof(eth_hdr->eh_src));
391 memcpy(&eth_hdr->eh_src, &t, sizeof(t));
392
393 eth_pack->acc_ext_link= NULL;
394 if (ip_port->ip_dl.dl_eth.de_q_head == NULL)
395 ip_port->ip_dl.dl_eth.de_q_head= eth_pack;
396 else
397 {
398 ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link= eth_pack;
399 }
400 ip_port->ip_dl.dl_eth.de_q_tail= eth_pack;
401 if (ip_port->ip_dl.dl_eth.de_frame == NULL)
402 ipeth_restart_send(ip_port);
403 return NW_OK;
404}
405
406PRIVATE void ipeth_restart_send(ip_port)
407ip_port_t *ip_port;
408{
409 time_t now, enq_time;
410 int i, r;
411 acc_t *eth_pack, *ip_pack, *next_eth_pack, *next_part, *tail;
412 size_t pack_size;
413 eth_hdr_t *eth_hdr, *next_eth_hdr;
414 u32_t *p;
415
416 now= get_time();
417
418 while (ip_port->ip_dl.dl_eth.de_q_head != NULL)
419 {
420 eth_pack= ip_port->ip_dl.dl_eth.de_q_head;
421 ip_port->ip_dl.dl_eth.de_q_head= eth_pack->acc_ext_link;
422
423 eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
424
425 pack_size= bf_bufsize(eth_pack);
426
427 if (pack_size > ip_port->ip_mtu+sizeof(*eth_hdr))
428 {
429 /* Split the IP packet */
430 assert(eth_pack->acc_linkC == 1);
431 ip_pack= eth_pack->acc_next; eth_pack->acc_next= NULL;
432 next_part= ip_pack; ip_pack= NULL;
433 ip_pack= ip_split_pack(ip_port, &next_part,
434 ip_port->ip_mtu);
435 if (ip_pack == NULL)
436 {
437 bf_afree(eth_pack);
438 continue;
439 }
440
441 eth_pack->acc_next= ip_pack; ip_pack= NULL;
442
443 /* Allocate new ethernet header */
444 next_eth_pack= bf_memreq(sizeof(*next_eth_hdr));
445 next_eth_hdr= (eth_hdr_t *)ptr2acc_data(next_eth_pack);
446 *next_eth_hdr= *eth_hdr;
447 next_eth_pack->acc_next= next_part;
448
449 next_eth_pack->acc_ext_link= NULL;
450 if (ip_port->ip_dl.dl_eth.de_q_head == NULL)
451 ip_port->ip_dl.dl_eth.de_q_head= next_eth_pack;
452 else
453 {
454 ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link=
455 next_eth_pack;
456 }
457 ip_port->ip_dl.dl_eth.de_q_tail= next_eth_pack;
458
459 pack_size= bf_bufsize(eth_pack);
460 }
461
462 memcpy(&enq_time, &eth_hdr->eh_src, sizeof(enq_time));
463 if (enq_time + HZ < now)
464 {
465 r= ipeth_update_ttl(enq_time, now, eth_pack);
466 if (r == ETIMEDOUT)
467 {
468 ip_pack= bf_delhead(eth_pack, sizeof(*eth_hdr));
469 eth_pack= NULL;
470 icmp_snd_time_exceeded(ip_port->ip_port,
471 ip_pack, ICMP_TTL_EXC);
472 continue;
473 }
474 assert(r == NW_OK);
475 }
476
477 if (pack_size<ETH_MIN_PACK_SIZE)
478 {
479 tail= bf_memreq(ETH_MIN_PACK_SIZE-pack_size);
480
481 /* Clear padding */
482 for (i= (ETH_MIN_PACK_SIZE-pack_size)/sizeof(*p),
483 p= (u32_t *)ptr2acc_data(tail);
484 i >= 0; i--, p++)
485 {
486 *p= 0xdeadbeef;
487 }
488
489 eth_pack= bf_append(eth_pack, tail);
490 pack_size= ETH_MIN_PACK_SIZE;
491 }
492
493 assert(ip_port->ip_dl.dl_eth.de_frame == NULL);
494
495 r= eth_send(ip_port->ip_dl.dl_eth.de_fd, eth_pack, pack_size);
496 if (r == NW_OK)
497 continue;
498
499 /* A non-blocking send is not possible, start a regular
500 * send.
501 */
502 assert(r == NW_WOULDBLOCK);
503 ip_port->ip_dl.dl_eth.de_frame= eth_pack;
504 r= eth_write(ip_port->ip_dl.dl_eth.de_fd, pack_size);
505 if (r == NW_SUSPEND)
506 {
507 assert(!(ip_port->ip_dl.dl_eth.de_flags &
508 IEF_WRITE_SP));
509 ip_port->ip_dl.dl_eth.de_flags |= IEF_WRITE_SP;
510 return;
511 }
512 assert(r == NW_OK);
513 }
514}
515
516
517PRIVATE void ipeth_arp_reply(ip_port_nr, ipaddr, eth_addr)
518int ip_port_nr;
519ipaddr_t ipaddr;
520ether_addr_t *eth_addr;
521{
522 acc_t *prev, *eth_pack;
523 int r;
524 xmit_hdr_t *xmit_hdr;
525 ip_port_t *ip_port;
526 time_t t;
527 eth_hdr_t *eth_hdr;
528 ether_addr_t tmp_eth_addr;
529
530 assert (ip_port_nr >= 0 && ip_port_nr < ip_conf_nr);
531 ip_port= &ip_port_table[ip_port_nr];
532
533 for (;;)
534 {
535 for (prev= 0, eth_pack= ip_port->ip_dl.dl_eth.de_arp_head;
536 eth_pack;
537 prev= eth_pack, eth_pack= eth_pack->acc_ext_link)
538 {
539 xmit_hdr= (xmit_hdr_t *)ptr2acc_data(eth_pack);
540 if (xmit_hdr->xh_ipaddr == ipaddr)
541 break;
542 }
543
544 if (eth_pack == NULL)
545 {
546 /* No packet found. */
547 break;
548 }
549
550 /* Delete packet from the queue. */
551 if (prev == NULL)
552 {
553 ip_port->ip_dl.dl_eth.de_arp_head=
554 eth_pack->acc_ext_link;
555 }
556 else
557 {
558 prev->acc_ext_link= eth_pack->acc_ext_link;
559 if (prev->acc_ext_link == NULL)
560 ip_port->ip_dl.dl_eth.de_arp_tail= prev;
561 }
562
563 if (eth_addr == NULL)
564 {
565 /* Destination is unreachable, delete packet. */
566 bf_afree(eth_pack);
567 continue;
568 }
569
570 /* Fill in the ethernet address and put the packet on the
571 * transmit queue.
572 */
573 t= xmit_hdr->xh_time;
574 eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
575 eth_hdr->eh_dst= *eth_addr;
576 memcpy(&eth_hdr->eh_src, &t, sizeof(t));
577
578 eth_pack->acc_ext_link= NULL;
579 if (ip_port->ip_dl.dl_eth.de_q_head == NULL)
580 ip_port->ip_dl.dl_eth.de_q_head= eth_pack;
581 else
582 {
583 ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link=
584 eth_pack;
585 }
586 ip_port->ip_dl.dl_eth.de_q_tail= eth_pack;
587 }
588
589 /* Try to get some more ARPs in progress. */
590 while (ip_port->ip_dl.dl_eth.de_arp_head)
591 {
592 eth_pack= ip_port->ip_dl.dl_eth.de_arp_head;
593 xmit_hdr= (xmit_hdr_t *)ptr2acc_data(eth_pack);
594 r= arp_ip_eth(ip_port->ip_dl.dl_eth.de_port,
595 xmit_hdr->xh_ipaddr, &tmp_eth_addr);
596 if (r == NW_SUSPEND)
597 break; /* Normal case */
598
599 /* Dequeue the packet */
600 ip_port->ip_dl.dl_eth.de_arp_head= eth_pack->acc_ext_link;
601
602 if (r == EDSTNOTRCH)
603 {
604 bf_afree(eth_pack);
605 continue;
606 }
607 assert(r == NW_OK);
608
609 /* Fill in the ethernet address and put the packet on the
610 * transmit queue.
611 */
612 t= xmit_hdr->xh_time;
613 eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
614 eth_hdr->eh_dst= tmp_eth_addr;
615 memcpy(&eth_hdr->eh_src, &t, sizeof(t));
616
617 eth_pack->acc_ext_link= NULL;
618 if (ip_port->ip_dl.dl_eth.de_q_head == NULL)
619 ip_port->ip_dl.dl_eth.de_q_head= eth_pack;
620 else
621 {
622 ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link=
623 eth_pack;
624 }
625 ip_port->ip_dl.dl_eth.de_q_tail= eth_pack;
626 }
627
628 /* Restart sending ethernet packets. */
629 if (ip_port->ip_dl.dl_eth.de_frame == NULL)
630 ipeth_restart_send(ip_port);
631}
632
633PRIVATE int ipeth_update_ttl(enq_time, now, eth_pack)
634time_t enq_time;
635time_t now;
636acc_t *eth_pack;
637{
638 int ttl_diff;
639 ip_hdr_t *ip_hdr;
640 u32_t sum;
641 u16_t word;
642 acc_t *ip_pack;
643
644 ttl_diff= (now-enq_time)/HZ;
645 enq_time += ttl_diff*HZ;
646 assert(enq_time <= now && enq_time + HZ > now);
647
648 ip_pack= eth_pack->acc_next;
649 assert(ip_pack->acc_length >= sizeof(*ip_hdr));
650 assert(ip_pack->acc_linkC == 1 &&
651 ip_pack->acc_buffer->buf_linkC == 1);
652
653 ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack);
654 if (ip_hdr->ih_ttl <= ttl_diff)
655 return ETIMEDOUT;
656 sum= (u16_t)~ip_hdr->ih_hdr_chk;
657 word= *(u16_t *)&ip_hdr->ih_ttl;
658 if (word > sum)
659 sum += 0xffff - word;
660 else
661 sum -= word;
662 ip_hdr->ih_ttl -= ttl_diff;
663 word= *(u16_t *)&ip_hdr->ih_ttl;
664 sum += word;
665 if (sum > 0xffff)
666 sum -= 0xffff;
667 assert(!(sum & 0xffff0000));
668 ip_hdr->ih_hdr_chk= ~sum;
669 assert(ip_hdr->ih_ttl > 0);
670 return NW_OK;
671}
672
673PRIVATE void do_eth_read(ip_port)
674ip_port_t *ip_port;
675{
676 int result;
677
678 assert(!(ip_port->ip_dl.dl_eth.de_flags & IEF_READ_IP));
679
680 for (;;)
681 {
682 ip_port->ip_dl.dl_eth.de_flags |= IEF_READ_IP;
683
684 result= eth_read (ip_port->ip_dl.dl_eth.de_fd,
685 ETH_MAX_PACK_SIZE);
686 if (result == NW_SUSPEND)
687 {
688 assert(!(ip_port->ip_dl.dl_eth.de_flags &
689 IEF_READ_SP));
690 ip_port->ip_dl.dl_eth.de_flags |= IEF_READ_SP;
691 return;
692 }
693 ip_port->ip_dl.dl_eth.de_flags &= ~IEF_READ_IP;
694 if (result<0)
695 {
696 return;
697 }
698 }
699}
700
701PRIVATE void ip_eth_arrived(port, pack, pack_size)
702int port;
703acc_t *pack;
704size_t pack_size;
705{
706 int broadcast;
707 ip_port_t *ip_port;
708
709 ip_port= &ip_port_table[port];
710 broadcast= (*(u8_t *)ptr2acc_data(pack) & 1);
711
712 pack= bf_delhead(pack, ETH_HDR_SIZE);
713
714 if (broadcast)
715 ip_arrived_broadcast(ip_port, pack);
716 else
717 ip_arrived(ip_port, pack);
718}
719
720/*
721 * $PchId: ip_eth.c,v 1.25 2005/06/28 14:18:10 philip Exp $
722 */
Note: See TracBrowser for help on using the repository browser.