4 Copyright 1995 Philip Homburg
22 FORWARD ip_ass_t
*find_ass_ent
ARGS(( ip_port_t
*ip_port
, U16_t id
,
23 int proto
, ipaddr_t src
, ipaddr_t dst
));
24 FORWARD acc_t
*merge_frags
ARGS(( acc_t
*first
, acc_t
*second
));
25 FORWARD
int ip_frag_chk
ARGS(( acc_t
*pack
));
26 FORWARD acc_t
*reassemble
ARGS(( ip_port_t
*ip_port
, acc_t
*pack
,
28 FORWARD
void route_packets
ARGS(( event_t
*ev
, ev_arg_t ev_arg
));
29 FORWARD
int broadcast_dst
ARGS(( ip_port_t
*ip_port
, ipaddr_t dest
));
31 PUBLIC
int ip_read (fd
, count
)
38 ip_fd
= &ip_fd_table
[fd
];
39 if (!(ip_fd
->if_flags
& IFF_OPTSET
))
41 return (*ip_fd
->if_put_userdata
)(ip_fd
->if_srfd
, EBADMODE
,
45 ip_fd
->if_rd_count
= count
;
47 ip_fd
->if_flags
|= IFF_READ_IP
;
48 if (ip_fd
->if_rdbuf_head
)
50 if (get_time() <= ip_fd
->if_exp_time
)
52 pack
= ip_fd
->if_rdbuf_head
;
53 ip_fd
->if_rdbuf_head
= pack
->acc_ext_link
;
54 ip_packet2user (ip_fd
, pack
, ip_fd
->if_exp_time
,
56 assert(!(ip_fd
->if_flags
& IFF_READ_IP
));
59 while (ip_fd
->if_rdbuf_head
)
61 pack
= ip_fd
->if_rdbuf_head
;
62 ip_fd
->if_rdbuf_head
= pack
->acc_ext_link
;
69 PRIVATE acc_t
*reassemble (ip_port
, pack
, pack_hdr
)
75 size_t pack_hdr_len
, pack_data_len
, pack_offset
, tmp_offset
;
76 u16_t pack_flags_fragoff
;
77 acc_t
*prev_acc
, *curr_acc
, *next_acc
, *head_acc
, *tmp_acc
;
81 ass_ent
= find_ass_ent (ip_port
, pack_hdr
->ih_id
,
82 pack_hdr
->ih_proto
, pack_hdr
->ih_src
, pack_hdr
->ih_dst
);
84 pack_flags_fragoff
= ntohs(pack_hdr
->ih_flags_fragoff
);
85 pack_hdr_len
= (pack_hdr
->ih_vers_ihl
& IH_IHL_MASK
) * 4;
86 pack_data_len
= ntohs(pack_hdr
->ih_length
)-pack_hdr_len
;
87 pack_offset
= (pack_flags_fragoff
& IH_FRAGOFF_MASK
)*8;
88 pack
->acc_ext_link
= NULL
;
90 head_acc
= ass_ent
->ia_frags
;
91 ass_ent
->ia_frags
= NULL
;
94 ass_ent
->ia_frags
= pack
;
104 tmp_hdr
= (ip_hdr_t
*)ptr2acc_data(next_acc
);
105 tmp_offset
= (ntohs(tmp_hdr
->ih_flags_fragoff
) &
108 if (pack_offset
< tmp_offset
)
113 next_acc
= next_acc
->acc_ext_link
;
115 if (curr_acc
== NULL
)
117 assert(prev_acc
== NULL
);
118 assert(next_acc
!= NULL
);
120 curr_acc
= merge_frags(pack
, next_acc
);
125 curr_acc
= merge_frags(curr_acc
, pack
);
126 if (next_acc
!= NULL
)
127 curr_acc
= merge_frags(curr_acc
, next_acc
);
128 if (prev_acc
!= NULL
)
129 prev_acc
->acc_ext_link
= curr_acc
;
133 ass_ent
->ia_frags
= head_acc
;
135 pack
= ass_ent
->ia_frags
;
136 pack_hdr
= (ip_hdr_t
*)ptr2acc_data(pack
);
137 pack_flags_fragoff
= ntohs(pack_hdr
->ih_flags_fragoff
);
139 if (!(pack_flags_fragoff
& (IH_FRAGOFF_MASK
|IH_MORE_FRAGS
)))
140 /* it's now a complete packet */
142 first_time
= ass_ent
->ia_first_time
;
144 ass_ent
->ia_frags
= 0;
145 ass_ent
->ia_first_time
= 0;
147 while (pack
->acc_ext_link
)
149 tmp_acc
= pack
->acc_ext_link
;
150 pack
->acc_ext_link
= tmp_acc
->acc_ext_link
;
153 if ((ass_ent
->ia_min_ttl
) * HZ
+ first_time
<
156 if (broadcast_dst(ip_port
, pack_hdr
->ih_dst
))
159 "ip_read'reassemble: reassembly timeout for broadcast packet\n"););
160 bf_afree(pack
); pack
= NULL
;
163 icmp_snd_time_exceeded(ip_port
->ip_port
, pack
,
172 PRIVATE acc_t
*merge_frags (first
, second
)
173 acc_t
*first
, *second
;
175 ip_hdr_t
*first_hdr
, *second_hdr
;
176 size_t first_hdr_size
, second_hdr_size
, first_datasize
, second_datasize
,
177 first_offset
, second_offset
;
178 acc_t
*cut_second
, *tmp_acc
;
182 first
->acc_ext_link
= NULL
;
186 assert (first
->acc_length
>= IP_MIN_HDR_SIZE
);
187 assert (second
->acc_length
>= IP_MIN_HDR_SIZE
);
189 first_hdr
= (ip_hdr_t
*)ptr2acc_data(first
);
190 first_offset
= (ntohs(first_hdr
->ih_flags_fragoff
) &
191 IH_FRAGOFF_MASK
) * 8;
192 first_hdr_size
= (first_hdr
->ih_vers_ihl
& IH_IHL_MASK
) * 4;
193 first_datasize
= ntohs(first_hdr
->ih_length
) - first_hdr_size
;
195 second_hdr
= (ip_hdr_t
*)ptr2acc_data(second
);
196 second_offset
= (ntohs(second_hdr
->ih_flags_fragoff
) &
197 IH_FRAGOFF_MASK
) * 8;
198 second_hdr_size
= (second_hdr
->ih_vers_ihl
& IH_IHL_MASK
) * 4;
199 second_datasize
= ntohs(second_hdr
->ih_length
) - second_hdr_size
;
201 assert (first_hdr_size
+ first_datasize
== bf_bufsize(first
));
202 assert (second_hdr_size
+ second_datasize
== bf_bufsize(second
));
203 assert (second_offset
>= first_offset
);
205 if (second_offset
> first_offset
+first_datasize
)
207 DBLOCK(1, printf("ip fragments out of order\n"));
208 first
->acc_ext_link
= second
;
212 if (second_offset
+ second_datasize
<= first_offset
+
215 /* May cause problems if we try to merge. */
220 if (!(second_hdr
->ih_flags_fragoff
& HTONS(IH_MORE_FRAGS
)))
221 first_hdr
->ih_flags_fragoff
&= ~HTONS(IH_MORE_FRAGS
);
223 second_datasize
= second_offset
+second_datasize
-(first_offset
+
225 cut_second
= bf_cut(second
, second_hdr_size
+ first_offset
+
226 first_datasize
-second_offset
, second_datasize
);
227 tmp_acc
= second
->acc_ext_link
;
231 first_datasize
+= second_datasize
;
232 first_hdr
->ih_length
= htons(first_hdr_size
+ first_datasize
);
234 first
= bf_append (first
, cut_second
);
235 first
->acc_ext_link
= second
;
237 assert (first_hdr_size
+ first_datasize
== bf_bufsize(first
));
242 PRIVATE ip_ass_t
*find_ass_ent (ip_port
, id
, proto
, src
, dst
)
249 ip_ass_t
*new_ass_ent
, *tmp_ass_ent
;
251 acc_t
*tmp_acc
, *curr_acc
;
255 for (i
=0, tmp_ass_ent
= ip_ass_table
; i
<IP_ASS_NR
; i
++,
258 if (!tmp_ass_ent
->ia_frags
&& tmp_ass_ent
->ia_first_time
)
261 printf("strange ip_ass entry (can be a race condition)\n"));
265 if ((tmp_ass_ent
->ia_srcaddr
== src
) &&
266 (tmp_ass_ent
->ia_dstaddr
== dst
) &&
267 (tmp_ass_ent
->ia_proto
== proto
) &&
268 (tmp_ass_ent
->ia_id
== id
) &&
269 (tmp_ass_ent
->ia_port
== ip_port
))
273 if (!new_ass_ent
|| tmp_ass_ent
->ia_first_time
<
274 new_ass_ent
->ia_first_time
)
276 new_ass_ent
= tmp_ass_ent
;
280 if (new_ass_ent
->ia_frags
)
282 DBLOCK(2, printf("old frags id= %u, proto= %u, src= ",
283 ntohs(new_ass_ent
->ia_id
),
284 new_ass_ent
->ia_proto
);
285 writeIpAddr(new_ass_ent
->ia_srcaddr
); printf(" dst= ");
286 writeIpAddr(new_ass_ent
->ia_dstaddr
); printf(": ");
287 ip_print_frags(new_ass_ent
->ia_frags
); printf("\n"));
288 curr_acc
= new_ass_ent
->ia_frags
->acc_ext_link
;
291 tmp_acc
= curr_acc
->acc_ext_link
;
295 curr_acc
= new_ass_ent
->ia_frags
;
296 new_ass_ent
->ia_frags
= 0;
297 if (broadcast_dst(ip_port
, new_ass_ent
->ia_dstaddr
))
300 "ip_read'find_ass_ent: reassembly timeout for broadcast packet\n"));
301 bf_afree(curr_acc
); curr_acc
= NULL
;
305 icmp_snd_time_exceeded(ip_port
->ip_port
,
306 curr_acc
, ICMP_FRAG_REASSEM
);
309 new_ass_ent
->ia_min_ttl
= IP_MAX_TTL
;
310 new_ass_ent
->ia_port
= ip_port
;
311 new_ass_ent
->ia_first_time
= get_time();
312 new_ass_ent
->ia_srcaddr
= src
;
313 new_ass_ent
->ia_dstaddr
= dst
;
314 new_ass_ent
->ia_proto
= proto
;
315 new_ass_ent
->ia_id
= id
;
320 PRIVATE
int ip_frag_chk(pack
)
326 if (pack
->acc_length
< sizeof(ip_hdr_t
))
328 DBLOCK(1, printf("wrong length\n"));
332 ip_hdr
= (ip_hdr_t
*)ptr2acc_data(pack
);
334 hdr_len
= (ip_hdr
->ih_vers_ihl
& IH_IHL_MASK
) * 4;
335 if (pack
->acc_length
< hdr_len
)
337 DBLOCK(1, printf("wrong length\n"));
342 if (((ip_hdr
->ih_vers_ihl
>> 4) & IH_VERSION_MASK
) !=
345 DBLOCK(1, printf("wrong version (ih_vers_ihl=0x%x)\n",
346 ip_hdr
->ih_vers_ihl
));
349 if (ntohs(ip_hdr
->ih_length
) != bf_bufsize(pack
))
351 DBLOCK(1, printf("wrong size\n"));
355 if ((u16_t
)~oneC_sum(0, (u16_t
*)ip_hdr
, hdr_len
))
357 DBLOCK(1, printf("packet with wrong checksum (= %x)\n",
358 (u16_t
)~oneC_sum(0, (u16_t
*)ip_hdr
, hdr_len
)));
361 if (hdr_len
>IP_MIN_HDR_SIZE
&& ip_chk_hdropt((u8_t
*)
362 (ptr2acc_data(pack
) + IP_MIN_HDR_SIZE
),
363 hdr_len
-IP_MIN_HDR_SIZE
))
365 DBLOCK(1, printf("packet with wrong options\n"));
371 PUBLIC
void ip_packet2user (ip_fd
, pack
, exp_time
, data_len
)
379 int result
, ip_hdr_len
;
382 assert (ip_fd
->if_flags
& IFF_INUSE
);
383 if (!(ip_fd
->if_flags
& IFF_READ_IP
))
385 if (pack
->acc_linkC
!= 1)
387 tmp_pack
= bf_dupacc(pack
);
392 pack
->acc_ext_link
= NULL
;
393 if (ip_fd
->if_rdbuf_head
== NULL
)
395 ip_fd
->if_rdbuf_head
= pack
;
396 ip_fd
->if_exp_time
= exp_time
;
399 ip_fd
->if_rdbuf_tail
->acc_ext_link
= pack
;
400 ip_fd
->if_rdbuf_tail
= pack
;
404 assert (pack
->acc_length
>= IP_MIN_HDR_SIZE
);
405 ip_hdr
= (ip_hdr_t
*)ptr2acc_data(pack
);
407 if (ip_fd
->if_ipopt
.nwio_flags
& NWIO_RWDATONLY
)
409 ip_hdr_len
= (ip_hdr
->ih_vers_ihl
& IH_IHL_MASK
) * 4;
411 assert (data_len
> ip_hdr_len
);
412 data_len
-= ip_hdr_len
;
413 pack
= bf_delhead(pack
, ip_hdr_len
);
416 if (data_len
> ip_fd
->if_rd_count
)
418 tmp_pack
= bf_cut (pack
, 0, ip_fd
->if_rd_count
);
421 transf_size
= ip_fd
->if_rd_count
;
424 transf_size
= data_len
;
426 if (ip_fd
->if_put_pkt
)
428 (*ip_fd
->if_put_pkt
)(ip_fd
->if_srfd
, pack
, transf_size
);
432 result
= (*ip_fd
->if_put_userdata
)(ip_fd
->if_srfd
,
433 (size_t)0, pack
, FALSE
);
436 if (data_len
> transf_size
)
442 ip_fd
->if_flags
&= ~IFF_READ_IP
;
443 result
= (*ip_fd
->if_put_userdata
)(ip_fd
->if_srfd
, result
,
445 assert (result
>= 0);
448 PUBLIC
void ip_port_arrive (ip_port
, pack
, ip_hdr
)
453 ip_fd_t
*ip_fd
, *first_fd
, *share_fd
;
454 unsigned long ip_pack_stat
;
460 assert (pack
->acc_linkC
>0);
461 assert (pack
->acc_length
>= IP_MIN_HDR_SIZE
);
463 if (ntohs(ip_hdr
->ih_flags_fragoff
) & (IH_FRAGOFF_MASK
|IH_MORE_FRAGS
))
465 pack
= reassemble (ip_port
, pack
, ip_hdr
);
468 assert (pack
->acc_length
>= IP_MIN_HDR_SIZE
);
469 ip_hdr
= (ip_hdr_t
*)ptr2acc_data(pack
);
470 assert (!(ntohs(ip_hdr
->ih_flags_fragoff
) &
471 (IH_FRAGOFF_MASK
|IH_MORE_FRAGS
)));
473 size
= ntohs(ip_hdr
->ih_length
);
474 if (size
> bf_bufsize(pack
))
476 /* Should discard packet */
478 bf_afree(pack
); pack
= NULL
;
482 exp_time
= get_time() + (ip_hdr
->ih_ttl
+1) * HZ
;
484 if (ip_hdr
->ih_dst
== ip_port
->ip_ipaddr
)
485 ip_pack_stat
= NWIO_EN_LOC
;
487 ip_pack_stat
= NWIO_EN_BROAD
;
489 proto
= ip_hdr
->ih_proto
;
490 hash
= proto
& (IP_PROTO_HASH_NR
-1);
497 ip_fd
= (i
== 0) ? ip_port
->ip_proto_any
:
498 ip_port
->ip_proto
[hash
];
499 for (; ip_fd
; ip_fd
= ip_fd
->if_proto_next
)
501 if (i
&& ip_fd
->if_ipopt
.nwio_proto
!= proto
)
503 if (!(ip_fd
->if_ipopt
.nwio_flags
& ip_pack_stat
))
505 if ((ip_fd
->if_ipopt
.nwio_flags
& NWIO_REMSPEC
) &&
506 ip_hdr
->ih_src
!= ip_fd
->if_ipopt
.nwio_rem
)
510 if ((ip_fd
->if_ipopt
.nwio_flags
& NWIO_ACC_MASK
) ==
518 if (!ip_fd
->if_rdbuf_head
)
528 ip_packet2user(ip_fd
, pack
, exp_time
, size
);
534 ip_packet2user(share_fd
, pack
, exp_time
, size
);
539 if (first_fd
->if_put_pkt
&&
540 (first_fd
->if_flags
& IFF_READ_IP
) &&
541 !(first_fd
->if_ipopt
.nwio_flags
& NWIO_RWDATONLY
))
543 (*first_fd
->if_put_pkt
)(first_fd
->if_srfd
, pack
,
547 ip_packet2user(first_fd
, pack
, exp_time
, size
);
551 if (ip_pack_stat
== NWIO_EN_LOC
)
554 printf("ip_port_arrive: dropping packet for proto %d\n",
559 DBLOCK(0x20, printf("dropping packet for proto %d\n",
566 PUBLIC
void ip_arrived(ip_port
, pack
)
572 int ip_frag_len
, ip_hdr_len
, highbyte
;
574 acc_t
*tmp_pack
, *hdr_pack
;
577 pack_size
= bf_bufsize(pack
);
579 if (pack_size
< IP_MIN_HDR_SIZE
)
581 DBLOCK(1, printf("wrong acc_length\n"));
585 pack
= bf_align(pack
, IP_MIN_HDR_SIZE
, 4);
586 pack
= bf_packIffLess(pack
, IP_MIN_HDR_SIZE
);
587 assert (pack
->acc_length
>= IP_MIN_HDR_SIZE
);
589 ip_hdr
= (ip_hdr_t
*)ptr2acc_data(pack
);
590 ip_hdr_len
= (ip_hdr
->ih_vers_ihl
& IH_IHL_MASK
) << 2;
591 if (ip_hdr_len
>IP_MIN_HDR_SIZE
)
593 pack
= bf_packIffLess(pack
, ip_hdr_len
);
594 ip_hdr
= (ip_hdr_t
*)ptr2acc_data(pack
);
596 ip_frag_len
= ntohs(ip_hdr
->ih_length
);
597 if (ip_frag_len
!= pack_size
)
599 if (pack_size
< ip_frag_len
)
602 DBLOCK(1, printf("wrong acc_length\n"));
606 assert(ip_frag_len
<pack_size
);
608 pack
= bf_cut(tmp_pack
, 0, ip_frag_len
);
610 pack_size
= ip_frag_len
;
613 if (!ip_frag_chk(pack
))
615 DBLOCK(1, printf("fragment not allright\n"));
620 /* Decide about local delivery or routing. Local delivery can happen
621 * when the destination is the local ip address, or one of the
622 * broadcast addresses and the packet happens to be delivered
626 dest
= ip_hdr
->ih_dst
;
628 if (dest
== ip_port
->ip_ipaddr
)
630 ip_port_arrive (ip_port
, pack
, ip_hdr
);
633 if (broadcast_dst(ip_port
, dest
))
635 ip_port_arrive (ip_port
, pack
, ip_hdr
);
639 if (pack
->acc_linkC
!= 1 || pack
->acc_buffer
->buf_linkC
!= 1)
641 /* Get a private copy of the IP header */
642 hdr_pack
= bf_memreq(ip_hdr_len
);
643 memcpy(ptr2acc_data(hdr_pack
), ip_hdr
, ip_hdr_len
);
644 pack
= bf_delhead(pack
, ip_hdr_len
);
645 hdr_pack
->acc_next
= pack
;
646 pack
= hdr_pack
; hdr_pack
= NULL
;
647 ip_hdr
= (ip_hdr_t
*)ptr2acc_data(pack
);
649 assert(pack
->acc_linkC
== 1);
650 assert(pack
->acc_buffer
->buf_linkC
== 1);
652 /* Try to decrement the ttl field with one. */
653 if (ip_hdr
->ih_ttl
< 2)
655 icmp_snd_time_exceeded(ip_port
->ip_port
, pack
,
660 ip_hdr_chksum(ip_hdr
, ip_hdr_len
);
662 /* Avoid routing to bad destinations. */
663 highbyte
= ntohl(dest
) >> 24;
664 if (highbyte
== 0 || highbyte
== 127 ||
665 (highbyte
== 169 && (((ntohl(dest
) >> 16) & 0xff) == 254)) ||
668 /* Bogus destination address */
673 /* Further processing from an event handler */
674 if (pack
->acc_linkC
!= 1)
676 tmp_pack
= bf_dupacc(pack
);
681 pack
->acc_ext_link
= NULL
;
682 if (ip_port
->ip_routeq_head
)
684 ip_port
->ip_routeq_tail
->acc_ext_link
= pack
;
685 ip_port
->ip_routeq_tail
= pack
;
689 ip_port
->ip_routeq_head
= pack
;
690 ip_port
->ip_routeq_tail
= pack
;
691 ev_arg
.ev_ptr
= ip_port
;
692 ev_enqueue(&ip_port
->ip_routeq_event
, route_packets
, ev_arg
);
695 PUBLIC
void ip_arrived_broadcast(ip_port
, pack
)
700 int ip_frag_len
, ip_hdr_len
;
704 pack_size
= bf_bufsize(pack
);
706 if (pack_size
< IP_MIN_HDR_SIZE
)
708 DBLOCK(1, printf("wrong acc_length\n"));
712 pack
= bf_align(pack
, IP_MIN_HDR_SIZE
, 4);
713 pack
= bf_packIffLess(pack
, IP_MIN_HDR_SIZE
);
714 assert (pack
->acc_length
>= IP_MIN_HDR_SIZE
);
716 ip_hdr
= (ip_hdr_t
*)ptr2acc_data(pack
);
718 DIFBLOCK(0x20, (ip_hdr
->ih_dst
& HTONL(0xf0000000)) == HTONL(0xe0000000),
719 printf("got multicast packet\n"));
721 ip_hdr_len
= (ip_hdr
->ih_vers_ihl
& IH_IHL_MASK
) << 2;
722 if (ip_hdr_len
>IP_MIN_HDR_SIZE
)
724 pack
= bf_align(pack
, IP_MIN_HDR_SIZE
, 4);
725 pack
= bf_packIffLess(pack
, ip_hdr_len
);
726 ip_hdr
= (ip_hdr_t
*)ptr2acc_data(pack
);
728 ip_frag_len
= ntohs(ip_hdr
->ih_length
);
729 if (ip_frag_len
<pack_size
)
732 pack
= bf_cut(tmp_pack
, 0, ip_frag_len
);
736 if (!ip_frag_chk(pack
))
738 DBLOCK(1, printf("fragment not allright\n"));
743 if (!broadcast_dst(ip_port
, ip_hdr
->ih_dst
))
747 "ip[%d]: broadcast packet for ip-nonbroadcast addr, src=",
749 writeIpAddr(ip_hdr
->ih_src
);
751 writeIpAddr(ip_hdr
->ih_dst
);
758 ip_port_arrive (ip_port
, pack
, ip_hdr
);
761 PRIVATE
void route_packets(ev
, ev_arg
)
769 ip_port_t
*next_port
;
774 ip_port
= ev_arg
.ev_ptr
;
775 assert(&ip_port
->ip_routeq_event
== ev
);
777 while (pack
= ip_port
->ip_routeq_head
, pack
!= NULL
)
779 ip_port
->ip_routeq_head
= pack
->acc_ext_link
;
781 ip_hdr
= (ip_hdr_t
*)ptr2acc_data(pack
);
782 dest
= ip_hdr
->ih_dst
;
784 iroute
= iroute_frag(ip_port
->ip_port
, dest
);
785 if (iroute
== NULL
|| iroute
->irt_dist
== IRTD_UNREACHABLE
)
787 /* Also unreachable */
788 /* Finding out if we send a network unreachable is too
793 printf("ip[%d]: no route to ",
794 ip_port
-ip_port_table
);
798 icmp_snd_unreachable(ip_port
->ip_port
, pack
,
802 next_port
= &ip_port_table
[iroute
->irt_port
];
804 if (ip_hdr
->ih_flags_fragoff
& HTONS(IH_DONT_FRAG
))
806 req_mtu
= bf_bufsize(pack
);
807 if (req_mtu
> next_port
->ip_mtu
||
808 (iroute
->irt_mtu
&& req_mtu
>iroute
->irt_mtu
))
810 icmp_snd_mtu(ip_port
->ip_port
, pack
,
816 if (next_port
!= ip_port
)
818 if (iroute
->irt_gateway
!= 0)
820 /* Just send the packet to the next gateway */
821 pack
->acc_linkC
++; /* Extra ref for ICMP */
822 r
= next_port
->ip_dev_send(next_port
,
827 printf("ip[%d]: gw ",
828 ip_port
-ip_port_table
);
829 writeIpAddr(iroute
->irt_gateway
);
830 printf(" on ip[%d] is down for dest ",
831 next_port
-ip_port_table
);
834 icmp_snd_unreachable(next_port
-
842 bf_afree(pack
); pack
= NULL
;
846 /* The packet is for the attached network. Special
847 * addresses are the ip address of the interface and
848 * net.0 if no IP_42BSD_BCAST.
850 if (dest
== next_port
->ip_ipaddr
)
852 ip_port_arrive (next_port
, pack
, ip_hdr
);
855 if (dest
== iroute
->irt_dest
)
857 /* Never forward obsolete directed broadcasts */
858 #if IP_42BSD_BCAST && 0
859 type
= IP_LT_BROADCAST
;
861 /* Bogus destination address */
863 "ip[%d]: dropping old-fashioned directed broadcast ",
864 ip_port
-ip_port_table
);
867 icmp_snd_unreachable(next_port
-ip_port_table
,
868 pack
, ICMP_HOST_UNRCH
);
872 else if (dest
== (iroute
->irt_dest
|
873 ~iroute
->irt_subnetmask
))
875 if (!ip_forward_directed_bcast
)
877 /* Do not forward directed broadcasts */
879 "ip[%d]: dropping directed broadcast ",
880 ip_port
-ip_port_table
);
883 icmp_snd_unreachable(next_port
-
889 type
= IP_LT_BROADCAST
;
894 /* Just send the packet to it's destination */
895 pack
->acc_linkC
++; /* Extra ref for ICMP */
896 r
= next_port
->ip_dev_send(next_port
, dest
, pack
, type
);
899 DBLOCK(1, printf("ip[%d]: next hop ",
900 ip_port
-ip_port_table
);
902 printf(" on ip[%d] is down\n",
903 next_port
-ip_port_table
););
904 icmp_snd_unreachable(next_port
-ip_port_table
,
905 pack
, ICMP_HOST_UNRCH
);
910 assert(r
== 0 || (printf("r = %d\n", r
), 0));
911 bf_afree(pack
); pack
= NULL
;
916 /* Now we know that the packet should be routed over the same
917 * network as it came from. If there is a next hop gateway,
918 * we can send the packet to that gateway and send a redirect
919 * ICMP to the sender if the sender is on the attached
920 * network. If there is no gateway complain.
922 if (iroute
->irt_gateway
== 0)
924 printf("ip_arrived: packet should not be here, src=");
925 writeIpAddr(ip_hdr
->ih_src
);
927 writeIpAddr(ip_hdr
->ih_dst
);
932 if (((ip_hdr
->ih_src
^ ip_port
->ip_ipaddr
) &
933 ip_port
->ip_subnetmask
) == 0)
935 /* Finding out if we can send a network redirect
936 * instead of a host redirect is too much trouble.
939 icmp_snd_redirect(ip_port
->ip_port
, pack
,
940 ICMP_REDIRECT_HOST
, iroute
->irt_gateway
);
944 printf("ip_arrived: packet is wrongly routed, src=");
945 writeIpAddr(ip_hdr
->ih_src
);
947 writeIpAddr(ip_hdr
->ih_dst
);
949 printf("in port %d, output %d, dest net ",
952 writeIpAddr(iroute
->irt_dest
);
954 writeIpAddr(iroute
->irt_subnetmask
);
955 printf(" next hop ");
956 writeIpAddr(iroute
->irt_gateway
);
961 /* No code for unreachable ICMPs here. The sender should
962 * process the ICMP redirect and figure it out.
964 ip_port
->ip_dev_send(ip_port
, iroute
->irt_gateway
, pack
,
969 PRIVATE
int broadcast_dst(ip_port
, dest
)
973 ipaddr_t my_ipaddr
, netmask
, classmask
;
975 /* Treat class D (multicast) address as broadcasts. */
976 if ((dest
& HTONL(0xF0000000)) == HTONL(0xE0000000))
981 /* Accept without complaint if netmask not yet configured. */
982 if (!(ip_port
->ip_flags
& IPF_NETMASKSET
))
986 /* Two possibilities, 0 (iff IP_42BSD_BCAST) and -1 */
987 if (dest
== HTONL((ipaddr_t
)-1))
990 if (dest
== HTONL((ipaddr_t
)0))
993 netmask
= ip_port
->ip_subnetmask
;
994 my_ipaddr
= ip_port
->ip_ipaddr
;
996 if (((my_ipaddr
^ dest
) & netmask
) != 0)
998 classmask
= ip_port
->ip_classfulmask
;
1000 /* Not a subnet broadcast, maybe a classful broadcast */
1001 if (((my_ipaddr
^ dest
) & classmask
) != 0)
1005 /* Two possibilities, net.0 (iff IP_42BSD_BCAST) and net.-1 */
1006 if ((dest
& ~classmask
) == ~classmask
)
1011 if ((dest
& ~classmask
) == 0)
1017 if (!(ip_port
->ip_flags
& IPF_SUBNET_BCAST
))
1018 return 0; /* No subnet broadcasts on this network */
1020 /* Two possibilities, subnet.0 (iff IP_42BSD_BCAST) and subnet.-1 */
1021 if ((dest
& ~netmask
) == ~netmask
)
1024 if ((dest
& ~netmask
) == 0)
1030 void ip_process_loopb(ev
, arg
)
1037 ip_port
= arg
.ev_ptr
;
1038 assert(ev
== &ip_port
->ip_loopb_event
);
1040 while(pack
= ip_port
->ip_loopb_head
, pack
!= NULL
)
1042 ip_port
->ip_loopb_head
= pack
->acc_ext_link
;
1043 ip_arrived(ip_port
, pack
);
1048 * $PchId: ip_read.c,v 1.33 2005/06/28 14:18:50 philip Exp $