hedrick@topaz.RUTGERS.EDU (Charles Hedrick) (01/21/87)
Our network is being flooded by ICMP unreachable messages. We have systems that use the new broadcast address of all ones. Unfortunately, 4.3 recognizes this address only in certain parts of the code. Suppose a machine sends a broadcast packet to a UDP port that we don't have a server on. ip_input recognizes all ones, and passes it to udp_usrreq. udp sees that there is no port, and then sends ICMP port unreachable. It should not do this in response to broadcast messages. There is an attempt to test for this, but it calls in_broadcast. This only tests for the default broadcast address. The test should be for all legal broadcast addresses. Since similar code appears in several places, I have added a routine in_any_broadcast. This extends in_broadcast to include the same set of addresses that ip_input tests for. Here are the changes. WARNING: I have not tested these changes. I'm about to go to a conference and don't have time to test a new kernel. These should be close enough to show what needs to be done. *** in.c.HOLD Thu Nov 20 13:38:42 1986 --- in.c Tue Jan 20 22:36:46 1987 *************** *** 456,458 UNLOCKSEM(&ip_lock); return (0); } --- 456,493 ----- UNLOCKSEM(&ip_lock); return (0); } + + /* + * Return 1 if the address is any of the possible broadcast addresses. + * in_broadcast is used to recognize things that we intend as broadcasts. + * So it only looks at broadaddr on each net. This one is used to test + * incoming addresses, so it must allow any of the various standards. + */ + in_any_broadcast(in) + struct in_addr in; + { + register struct in_ifaddr *ia; + + /* + * Look through the list of addresses for a match + * with a broadcast address. + */ + if (in.s_addr == 0 || in.s_addr == 0xffffffff) + return(1); + SPINLOCK(&ip_lock); + for (ia = in_ifaddr; ia; ia = ia->ia_next) + if (ia->ia_ifp->if_flags & IFF_BROADCAST) { + if (((struct sockaddr_in *)&ia->ia_broadaddr)->sin_addr.s_addr == + in.s_addr) + goto isbroad; + if (ia->ia_subnet == ntohl(in.s_addr)) + goto isbroad; + if (ia->ia_net == ntohl(in.s_addr)) + goto isbroad; + } + UNLOCKSEM(&ip_lock); + return (0); + isbroad: + UNLOCKSEM(&ip_lock); + return (1); + } *** ip_input.c.HOLD Sat Jan 10 06:46:57 1987 --- ip_input.c Tue Jan 20 22:39:57 1987 *************** *** 1003,1009 break; } sendicmp: ! if (in_broadcast(ip->ip_dst)) { m_freem(dtom(ip)); return; } --- 1003,1010 ----- break; } sendicmp: ! /* 48 - change in_broadcast to in_any_broadcast */ ! if (in_any_broadcast(ip->ip_dst)) { m_freem(dtom(ip)); return; } *** tcp_input.c.HOLD Fri Jan 2 22:09:03 1987 --- tcp_input.c Tue Jan 20 22:41:08 1987 *************** *** 439,445 goto dropwithreset; if ((tiflags & TH_SYN) == 0) goto drop; ! if (in_broadcast(ti->ti_dst)) goto drop; am = m_get(M_DONTWAIT, MT_SONAME); if (am == NULL) --- 439,446 ----- goto dropwithreset; if ((tiflags & TH_SYN) == 0) goto drop; ! /* 48 - use in_any_broadcast, so we recognize -1, 0, etc. */ ! if (in_any_broadcast(ti->ti_dst)) goto drop; am = m_get(M_DONTWAIT, MT_SONAME); if (am == NULL) *************** *** 1020,1025 * Make ACK acceptable to originator of segment. * Don't bother to respond if destination was broadcast. */ if ((tiflags & TH_RST) || in_broadcast(ti->ti_dst)) goto drop; if (tiflags & TH_ACK) --- 1021,1027 ----- * Make ACK acceptable to originator of segment. * Don't bother to respond if destination was broadcast. */ + /* 48 - use in_any_broadcast, to recognize 0 and -1 */ if ((tiflags & TH_RST) || in_broadcast(ti->ti_dst)) goto drop; if (tiflags & TH_ACK) *** udp_usrreq.c.HOLD Fri Jan 2 22:31:21 1987 --- udp_usrreq.c Tue Jan 20 22:41:51 1987 *************** *** 120,126 if (inp == 0) { UNLOCKSEM(&udb.pcb_lock); /* don't send ICMP response for broadcast packet */ ! if (in_broadcast(ui->ui_dst)) goto bad; *(struct ip *)ui = ip; icmp_error((struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT, --- 120,127 ----- if (inp == 0) { UNLOCKSEM(&udb.pcb_lock); /* don't send ICMP response for broadcast packet */ ! /* 48 - recognize all broadcast addresses */ ! if (in_any_broadcast(ui->ui_dst)) goto bad; *(struct ip *)ui = ip; icmp_error((struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT,