--- /usr/src/sys/netinet/if_ether.orig 2010-12-02 16:52:06.000000000 +0800 +++ /usr/src/sys/netinet/if_ether.c 2010-12-08 02:49:07.000000000 +0800 @@ -57,6 +57,9 @@ #include #include #include +#include +#include +#include #include #include @@ -246,7 +249,7 @@ m->m_pkthdr.len = m->m_len; MH_ALIGN(m, m->m_len); ah = mtod(m, struct arphdr *); - bzero((caddr_t)ah, m->m_len); + bzero(ah, m->m_len); #ifdef MAC mac_netinet_arp_send(ifp, m); #endif @@ -254,9 +257,9 @@ ah->ar_hln = ifp->if_addrlen; /* hardware address length */ ah->ar_pln = sizeof(struct in_addr); /* protocol address length */ ah->ar_op = htons(ARPOP_REQUEST); - bcopy((caddr_t)enaddr, (caddr_t)ar_sha(ah), ah->ar_hln); - bcopy((caddr_t)sip, (caddr_t)ar_spa(ah), ah->ar_pln); - bcopy((caddr_t)tip, (caddr_t)ar_tpa(ah), ah->ar_pln); + bcopy(enaddr, ar_sha(ah), ah->ar_hln); + bcopy(sip, ar_spa(ah), ah->ar_pln); + bcopy(tip, ar_tpa(ah), ah->ar_pln); sa.sa_family = AF_ARP; sa.sa_len = 2; m->m_flags |= M_BCAST; @@ -292,8 +295,7 @@ if (m != NULL) { if (m->m_flags & M_BCAST) { /* broadcast */ - (void)memcpy(desten, - ifp->if_broadcastaddr, ifp->if_addrlen); + bcopy(ifp->if_broadcastaddr, desten, ifp->if_addrlen); return (0); } if (m->m_flags & M_MCAST && ifp->if_type != IFT_ARCNET) { @@ -429,42 +431,68 @@ static void arpintr(struct mbuf *m) { - struct arphdr *ar; + struct arphdr *ah; if (m->m_len < sizeof(struct arphdr) && ((m = m_pullup(m, sizeof(struct arphdr))) == NULL)) { log(LOG_ERR, "arp: runt packet -- m_pullup failed\n"); return; } - ar = mtod(m, struct arphdr *); + ah = mtod(m, struct arphdr *); - if (ntohs(ar->ar_hrd) != ARPHRD_ETHER && - ntohs(ar->ar_hrd) != ARPHRD_IEEE802 && - ntohs(ar->ar_hrd) != ARPHRD_ARCNET && - ntohs(ar->ar_hrd) != ARPHRD_IEEE1394) { - log(LOG_ERR, "arp: unknown hardware address format (0x%2D)\n", - (unsigned char *)&ar->ar_hrd, ""); - m_freem(m); - return; + /* check hw addr len and hw addr */ + switch (ntohs(ah->ar_hrd)){ + case ARPHRD_ETHER: + if (ah->ar_hln != ETHER_ADDR_LEN) { + log(LOG_ERR, "arp: invalid length of hardware address\n"); + goto drop; + } + /* is from [multi/broad]cast? - sender cant be [multi/broad]cast! */ + if (ETHER_IS_MULTICAST(ar_sha(ah)) != 0) { + log(LOG_ERR, "arp: link address is multicast\n"); + goto drop; + } + break; + case ARPHRD_IEEE802: + if (ah->ar_hln != ISO88025_ADDR_LEN) + goto drop; + break; + case ARPHRD_ARCNET: + if (ah->ar_hln != ARC_ADDR_LEN) + goto drop; + break; + case ARPHRD_FRELAY: + if (ah->ar_hln != 2) + goto drop; + break; + case ARPHRD_IEEE1394: + if (ah->ar_hln != sizeof(struct fw_hwaddr)) /* XXX 8? */ + goto drop; + break; + default: + log(LOG_ERR, "arp: unknown hardware address format\n"); + goto drop; } - if (m->m_len < arphdr_len(ar)) { - if ((m = m_pullup(m, arphdr_len(ar))) == NULL) { + if (m->m_len < arphdr_len(ah)) { + if ((m = m_pullup(m, arphdr_len(ah))) == NULL) { log(LOG_ERR, "arp: runt packet\n"); - m_freem(m); return; } - ar = mtod(m, struct arphdr *); + ah = mtod(m, struct arphdr *); } ARPSTAT_INC(received); - switch (ntohs(ar->ar_pro)) { + switch (ntohs(ah->ar_pro)) { #ifdef INET case ETHERTYPE_IP: in_arpinput(m); return; #endif } + + log(LOG_ERR, "arp: unknown format of protocol address\n"); +drop: m_freem(m); } @@ -507,11 +535,10 @@ struct rtentry *rt; struct ifaddr *ifa; struct in_ifaddr *ia; - struct sockaddr sa; + struct sockaddr dst; struct in_addr isaddr, itaddr, myaddr; u_int8_t *enaddr = NULL; int op, flags; - int req_len; int bridged = 0, is_bridge = 0; int carp_match = 0; struct sockaddr_in sin; @@ -519,25 +546,25 @@ sin.sin_family = AF_INET; sin.sin_addr.s_addr = 0; - if (ifp->if_bridge) - bridged = 1; - if (ifp->if_type == IFT_BRIDGE) - is_bridge = 1; - req_len = arphdr_len2(ifp->if_addrlen, sizeof(struct in_addr)); - if (m->m_len < req_len && (m = m_pullup(m, req_len)) == NULL) { - log(LOG_ERR, "in_arp: runt packet -- m_pullup failed\n"); - return; + ah = mtod(m, struct arphdr *); + if (ah->ar_pln != sizeof(struct in_addr)) { + log(LOG_ERR, "arp: invalid length of protocol address\n"); + goto drop; } - ah = mtod(m, struct arphdr *); op = ntohs(ah->ar_op); - (void)memcpy(&isaddr, ar_spa(ah), sizeof (isaddr)); - (void)memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr)); + bcopy(ar_spa(ah), &isaddr, sizeof (isaddr)); + bcopy(ar_tpa(ah), &itaddr, sizeof (itaddr)); if (op == ARPOP_REPLY) ARPSTAT_INC(rxreplies); + if (ifp->if_bridge) + bridged = 1; + if (ifp->if_type == IFT_BRIDGE) + is_bridge = 1; + /* * For a bridge, we want to check the address irrespective * of the receive interface. (This will change slightly @@ -626,6 +653,15 @@ enaddr = (u_int8_t *)IF_LLADDR(ifp); myaddr = ia->ia_addr.sin_addr; ifa_free(&ia->ia_ifa); + + /* XXX length of hardware address (ar_hln) already checked in arpintr */ + if (ifp->if_addrlen != ah->ar_hln) { + log(LOG_WARNING, + "arp from %*D: addr len: new %d, i/f %d (ignored)", + ifp->if_addrlen, (u_char *) ar_sha(ah), ":", + ah->ar_hln, ifp->if_addrlen); + goto drop; + } if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen)) goto drop; /* it's from me, ignore it. */ if (!bcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) { @@ -695,16 +731,8 @@ ifp->if_xname); } } - - if (ifp->if_addrlen != ah->ar_hln) { - LLE_WUNLOCK(la); - log(LOG_WARNING, - "arp from %*D: addr len: new %d, i/f %d (ignored)", - ifp->if_addrlen, (u_char *) ar_sha(ah), ":", - ah->ar_hln, ifp->if_addrlen); - goto reply; - } - (void)memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen); + + bcopy(ar_sha(ah), &la->ll_addr, ifp->if_addrlen); la->la_flags |= LLE_VALID; EVENTHANDLER_INVOKE(arp_update_event, la); @@ -728,31 +756,31 @@ * NB: The lock MUST be released before the call to the * output routine. */ - if (la->la_hold != NULL) { - struct mbuf *m_hold, *m_hold_next; + struct mbuf *m_hold, *m_hold_next; - memcpy(&sa, L3_ADDR(la), sizeof(sa)); - LLE_WUNLOCK(la); - for (m_hold = la->la_hold, la->la_hold = NULL; - m_hold != NULL; m_hold = m_hold_next) { - m_hold_next = m_hold->m_nextpkt; - m_hold->m_nextpkt = NULL; - (*ifp->if_output)(ifp, m_hold, &sa, NULL); - } - } else - LLE_WUNLOCK(la); + m_hold = la->la_hold; + if (m_hold != NULL) + bcopy(L3_ADDR(la), &dst, sizeof(dst)); la->la_hold = NULL; la->la_numheld = 0; - } /* end of FIB loop */ + LLE_WUNLOCK(la); + + /* send packets to output */ + for (; m_hold != NULL; m_hold = m_hold_next) { + m_hold_next = m_hold->m_nextpkt; + m_hold->m_nextpkt = NULL; + (*ifp->if_output)(ifp, m_hold, &dst, NULL); + } + } reply: if (op != ARPOP_REQUEST) goto drop; ARPSTAT_INC(rxrequests); + bcopy(ar_sha(ah), ar_tha(ah), ah->ar_hln); if (itaddr.s_addr == myaddr.s_addr) { /* Shortcut.. the receiving interface is the target. */ - (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); - (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); + bcopy(enaddr, ar_sha(ah), ah->ar_hln); } else { struct llentry *lle = NULL; @@ -762,8 +790,7 @@ IF_AFDATA_UNLOCK(ifp); if ((lle != NULL) && (lle->la_flags & LLE_PUB)) { - (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); - (void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln); + bcopy(&lle->ll_addr, ar_sha(ah), ah->ar_hln); LLE_RUNLOCK(lle); } else { @@ -790,9 +817,6 @@ } RTFREE_LOCKED(rt); - (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); - (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); - /* * Also check that the node which sent the ARP packet * is on the the interface we expect it to be on. This @@ -815,6 +839,8 @@ } RTFREE_LOCKED(rt); + bcopy(enaddr, ar_sha(ah), ah->ar_hln); + #ifdef DEBUG_PROXY printf("arp: proxying for %s\n", inet_ntoa(itaddr)); @@ -835,15 +861,15 @@ /* default behaviour; never reply by broadcast. */ m->m_flags &= ~(M_BCAST|M_MCAST); } - (void)memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln); - (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln); + bcopy(ar_spa(ah), ar_tpa(ah), ah->ar_pln); + bcopy(&itaddr, ar_spa(ah), ah->ar_pln); ah->ar_op = htons(ARPOP_REPLY); ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */ - m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); + m->m_len = arphdr_len(ah); m->m_pkthdr.len = m->m_len; - sa.sa_family = AF_ARP; - sa.sa_len = 2; - (*ifp->if_output)(ifp, m, &sa, NULL); + dst.sa_family = AF_ARP; + dst.sa_len = 2; + (*ifp->if_output)(ifp, m, &dst, NULL); ARPSTAT_INC(txreplies); return;