The problem Mr. Pallfreeman was seeing are related to how I was building the arp-reply based on the sources arp_hrd type. I never expected to see a token-ring arp arrive over an ethernet interface. Therefore the arp code was trying to check for and collect the source route that the arp took on its way. I have modified the arp code to go looking for the source-route information only if the arp comes from a token-ring station and is received on a token-ring interface. The arp-reply packet generated is based on the type of interface the arp was received on. I think the bridge should have changed the arp_hrd type when it forwarded the packet, while it was changing everything else, but I think that falls into a religous debate. Thanks to Mr. Pallfreeman for helping me debug this and testing my patch.
What this means is: you should be able to arp in both directions over a token-ring<->ethernet (translational|non-translational) bridge. The inherent "brokenness" of translational bridging is left as an exercise for the reader :) Here's the patch, if someone would be kind enough to commit it. It seems to have resolved Mr. Pallfreeman's issue and doesn't seem to break anything else. Larry Lile l...@stdio.com
*** if_ether.c.orig Wed Apr 14 09:54:35 1999 --- if_ether.c Wed Apr 14 12:50:02 1999 *************** *** 560,567 **** (void)memcpy(LLADDR(sdl), ea->arp_sha, sizeof(ea->arp_sha)); sdl->sdl_alen = sizeof(ea->arp_sha); sdl->sdl_rcf = NULL; ! /* Save source routing information for Token-ring interfaces, if available */ ! if (ea->arp_hrd == htons(ARPHRD_IEEE802)) { th = (struct iso88025_header *)m->m_pkthdr.header; if ((th->iso88025_shost[0] & 0x80) && (((ntohs(th->rcf) & 0x1f00) >> 8) > 2)) { sdl->sdl_rcf = ntohs(th->rcf) & 0x0080 ? --- 560,569 ---- (void)memcpy(LLADDR(sdl), ea->arp_sha, sizeof(ea->arp_sha)); sdl->sdl_alen = sizeof(ea->arp_sha); sdl->sdl_rcf = NULL; ! /* If we receive an arp from a token-ring station over a token-ring nic ! * then try to save the source routing info. ! */ ! if ((ac->ac_if.if_type == IFT_ISO88025) && (ea->arp_hrd == htons(ARPHRD_IEEE802))) { th = (struct iso88025_header *)m->m_pkthdr.header; if ((th->iso88025_shost[0] & 0x80) && (((ntohs(th->rcf) & 0x1f00) >> 8) > 2)) { sdl->sdl_rcf = ntohs(th->rcf) & 0x0080 ? *************** *** 578,583 **** --- 580,587 ---- } th->rcf = sdl->sdl_rcf; + } else { + sdl->sdl_rcf = NULL; } if (rt->rt_expire) rt->rt_expire = time_second + arpt_keep; *************** *** 647,654 **** (void)memcpy(ea->arp_spa, &itaddr, sizeof(ea->arp_spa)); ea->arp_op = htons(ARPOP_REPLY); ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */ ! switch (ntohs(ea->arp_hrd)) { ! case ARPHRD_IEEE802: /* Re-arrange the source/dest address */ memcpy(th->iso88025_dhost, th->iso88025_shost, sizeof(th->iso88025_dhost)); memcpy(th->iso88025_shost, ac->ac_enaddr, sizeof(th->iso88025_shost)); --- 651,658 ---- (void)memcpy(ea->arp_spa, &itaddr, sizeof(ea->arp_spa)); ea->arp_op = htons(ARPOP_REPLY); ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */ ! switch (ac->ac_if.if_type) { ! case IFT_ISO88025: /* Re-arrange the source/dest address */ memcpy(th->iso88025_dhost, th->iso88025_shost, sizeof(th->iso88025_dhost)); memcpy(th->iso88025_shost, ac->ac_enaddr, sizeof(th->iso88025_shost)); *************** *** 663,669 **** sa.sa_data[(sizeof(th->iso88025_dhost) * 2)] = 0x10; sa.sa_data[(sizeof(th->iso88025_dhost) * 2) + 1] = 0x40; break; ! case ARPHRD_ETHER: eh = (struct ether_header *)sa.sa_data; (void)memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost)); eh->ether_type = htons(ETHERTYPE_ARP); --- 667,673 ---- sa.sa_data[(sizeof(th->iso88025_dhost) * 2)] = 0x10; sa.sa_data[(sizeof(th->iso88025_dhost) * 2) + 1] = 0x40; break; ! case IFT_ETHER: eh = (struct ether_header *)sa.sa_data; (void)memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost)); eh->ether_type = htons(ETHERTYPE_ARP);