summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>1999-03-10 10:11:43 +0000
committerjulian <julian@FreeBSD.org>1999-03-10 10:11:43 +0000
commit6eb9a9adf91724bc8f8bb0516ce6bc9f52b58d95 (patch)
tree48c43f547b4c8f1730068ca134d2818794a2739c /sys/netinet
parent2ccd8bee025601450845f03de07e4614bb9468ea (diff)
downloadFreeBSD-src-6eb9a9adf91724bc8f8bb0516ce6bc9f52b58d95.zip
FreeBSD-src-6eb9a9adf91724bc8f8bb0516ce6bc9f52b58d95.tar.gz
Submitted by: Larry Lile
Move the Olicom token ring driver to the officially sanctionned location of /sys/contrib. Also fix some brokenness in the generic token ring support. Be warned that if_dl.h has been changed and SOME programs might like recompilation.
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/if_ether.c95
1 files changed, 79 insertions, 16 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index 5ee2e18..0941712 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)if_ether.c 8.1 (Berkeley) 6/10/93
- * $Id: if_ether.c,v 1.54 1999/02/20 11:18:00 julian Exp $
+ * $Id: if_ether.c,v 1.55 1999/03/04 04:03:57 wpaul Exp $
*/
/*
@@ -63,6 +63,8 @@
#include <netinet/in_var.h>
#include <netinet/if_ether.h>
+#include <net/iso88025.h>
+
#define SIN(s) ((struct sockaddr_in *)s)
#define SDL(s) ((struct sockaddr_dl *)s)
@@ -290,19 +292,37 @@ arprequest(ac, sip, tip, enaddr)
if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
return;
- m->m_len = sizeof(*ea);
- m->m_pkthdr.len = sizeof(*ea);
m->m_pkthdr.rcvif = (struct ifnet *)0;
- MH_ALIGN(m, sizeof(*ea));
- ea = mtod(m, struct ether_arp *);
- eh = (struct ether_header *)sa.sa_data;
- bzero((caddr_t)ea, sizeof (*ea));
- (void)memcpy(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dhost));
- eh->ether_type = htons(ETHERTYPE_ARP); /* if_output will not swap */
- if (ac->ac_if.if_type == IFT_ETHER)
- ea->arp_hrd = htons(ARPHRD_ETHER);
- if (ac->ac_if.if_type == IFT_ISO88025)
- ea->arp_hrd = htons(ARPHRD_IEEE802);
+ switch (ac->ac_if.if_type) {
+ case IFT_ETHER:
+ m->m_len = sizeof(*ea);
+ m->m_pkthdr.len = sizeof(*ea);
+ MH_ALIGN(m, sizeof(*ea));
+ ea = mtod(m, struct ether_arp *);
+ eh = (struct ether_header *)sa.sa_data;
+ bzero((caddr_t)ea, sizeof (*ea));
+ eh->ether_type = htons(ETHERTYPE_ARP); /* if_output will not swap */
+ (void)memcpy(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dhost));
+ ea->arp_hrd = htons(ARPHRD_ETHER);
+ break;
+ case IFT_ISO88025:
+ m->m_len = sizeof(*ea) + 10;
+ m->m_pkthdr.len = sizeof(*ea) + 10;
+ MH_ALIGN(m, sizeof(*ea) + 10);
+ (void)memcpy(mtod(m, caddr_t), "\x82\x40\xaa\xaa\x03\x00\x00\x00\x08\x06", 10);
+ (void)memcpy(sa.sa_data, etherbroadcastaddr, 6);
+ (void)memcpy(sa.sa_data + 6, enaddr, 6);
+ sa.sa_data[6] |= 0x80;
+ sa.sa_data[12] = 0x10;
+ sa.sa_data[13] = 0x40;
+ ea = (struct ether_arp *)(mtod(m, char *) + 10);
+ bzero((caddr_t)ea, sizeof (*ea));
+ ea->arp_hrd = htons(ARPHRD_IEEE802);
+ break;
+ default:
+ m_freem(m);
+ return;
+ }
ea->arp_pro = htons(ETHERTYPE_IP);
ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */
ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */
@@ -457,6 +477,7 @@ in_arpinput(m)
register struct ether_arp *ea;
register struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif;
struct ether_header *eh;
+ struct iso88025_header *th = (struct iso88025_header *)0;
register struct llinfo_arp *la = 0;
register struct rtentry *rt;
struct in_ifaddr *ia, *maybe_ia = 0;
@@ -538,6 +559,26 @@ in_arpinput(m)
}
(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 ?
+ htons(ntohs(th->rcf) & 0xff7f) : htons(ntohs(th->rcf) | 0x0080);
+ memcpy(sdl->sdl_route, th->rseg, ((ntohs(th->rcf) & 0x1f00) >> 8) - 2);
+ sdl->sdl_rcf = htons(ntohs(sdl->sdl_rcf) & 0x1fff);
+ /* Set up source routing information for reply packet (XXX)*/
+ m->m_data -= (((ntohs(th->rcf) & 0x1f00) >> 8) + 8);
+ m->m_len += (((ntohs(th->rcf) & 0x1f00) >> 8) + 8);
+ } else {
+ th->iso88025_shost[0] &= 0x7f;
+ m->m_data -= 8;
+ m->m_len += 8;
+ }
+ th->rcf = sdl->sdl_rcf;
+
+ }
if (rt->rt_expire)
rt->rt_expire = time_second + arpt_keep;
rt->rt_flags &= ~RTF_REJECT;
@@ -606,9 +647,31 @@ reply:
(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! */
- 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);
+ 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));
+ /* Set the source routing bit if neccesary */
+ if (th->iso88025_dhost[0] & 0x80) {
+ th->iso88025_dhost[0] &= 0x7f;
+ if (((ntohs(th->rcf) & 0x1f00) >> 8) - 2)
+ th->iso88025_shost[0] |= 0x80;
+ }
+ /* Copy the addresses, ac and fc into sa_data */
+ memcpy(sa.sa_data, th->iso88025_dhost, sizeof(th->iso88025_dhost) * 2);
+ 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);
+ break;
+ default:
+ m_free(m);
+ return;
+ }
sa.sa_family = AF_UNSPEC;
sa.sa_len = sizeof(sa);
(*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
OpenPOWER on IntegriCloud