version 1.2, 1993/05/20 03:05:59 |
version 1.3, 1993/12/06 04:50:19 |
Line 109 ether_output(ifp, m0, dst, rt) |
|
Line 109 ether_output(ifp, m0, dst, rt) |
|
idst = ((struct sockaddr_in *)dst)->sin_addr; |
idst = ((struct sockaddr_in *)dst)->sin_addr; |
if (!arpresolve(ac, m, &idst, edst, &usetrailers)) |
if (!arpresolve(ac, m, &idst, edst, &usetrailers)) |
return (0); /* if not yet resolved */ |
return (0); /* if not yet resolved */ |
if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1)) |
/* If broadcasting on a simplex interface, loopback a copy */ |
|
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) |
mcopy = m_copy(m, 0, (int)M_COPYALL); |
mcopy = m_copy(m, 0, (int)M_COPYALL); |
off = m->m_pkthdr.len - m->m_len; |
off = m->m_pkthdr.len - m->m_len; |
if (usetrailers && off > 0 && (off & 0x1ff) == 0 && |
if (usetrailers && off > 0 && (off & 0x1ff) == 0 && |
Line 133 ether_output(ifp, m0, dst, rt) |
|
Line 134 ether_output(ifp, m0, dst, rt) |
|
(caddr_t)edst, sizeof (edst)); |
(caddr_t)edst, sizeof (edst)); |
if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))) |
if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))) |
return (looutput(ifp, m, dst, rt)); |
return (looutput(ifp, m, dst, rt)); |
if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1)) |
/* If broadcasting on a simplex interface, loopback a copy */ |
|
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) |
mcopy = m_copy(m, 0, (int)M_COPYALL); |
mcopy = m_copy(m, 0, (int)M_COPYALL); |
goto gottype; |
goto gottype; |
#endif |
#endif |
Line 164 ether_output(ifp, m0, dst, rt) |
|
Line 166 ether_output(ifp, m0, dst, rt) |
|
(char *)edst, &snpalen)) > 0) |
(char *)edst, &snpalen)) > 0) |
goto bad; /* Not Resolved */ |
goto bad; /* Not Resolved */ |
iso_resolved: |
iso_resolved: |
if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) && |
/* If broadcasting on a simplex interface, loopback a copy */ |
|
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) && |
(mcopy = m_copy(m, 0, (int)M_COPYALL))) { |
(mcopy = m_copy(m, 0, (int)M_COPYALL))) { |
M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); |
M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); |
if (mcopy) { |
if (mcopy) { |
Line 190 ether_output(ifp, m0, dst, rt) |
|
Line 193 ether_output(ifp, m0, dst, rt) |
|
printf("%x ", edst[i] & 0xff); |
printf("%x ", edst[i] & 0xff); |
printf("\n"); |
printf("\n"); |
ENDDEBUG |
ENDDEBUG |
} goto gottype; |
} |
|
goto gottype; |
#endif ISO |
#endif ISO |
#ifdef RMP |
#ifdef RMP |
case AF_RMP: |
case AF_RMP: |
|
|
(*ifp->if_start)(ifp); |
(*ifp->if_start)(ifp); |
splx(s); |
splx(s); |
ifp->if_obytes += len + sizeof (struct ether_header); |
ifp->if_obytes += len + sizeof (struct ether_header); |
|
#ifdef MULTICAST |
|
if (m->m_flags & M_MCAST) |
|
#else |
if (edst[0] & 1) |
if (edst[0] & 1) |
|
#endif |
ifp->if_omcasts++; |
ifp->if_omcasts++; |
return (error); |
return (error); |
|
|
Line 288 ether_input(ifp, eh, m) |
|
Line 296 ether_input(ifp, eh, m) |
|
|
|
ifp->if_lastchange = time; |
ifp->if_lastchange = time; |
ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); |
ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); |
|
#ifdef MULTICAST |
|
if (eh->ether_dhost[0] & 1) { |
|
if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, |
|
sizeof(etherbroadcastaddr)) == 0) |
|
m->m_flags |= M_BCAST; |
|
else |
|
m->m_flags |= M_MCAST; |
|
} |
|
#else |
if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, |
if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, |
sizeof(etherbroadcastaddr)) == 0) |
sizeof(etherbroadcastaddr)) == 0) |
m->m_flags |= M_BCAST; |
m->m_flags |= M_BCAST; |
else if (eh->ether_dhost[0] & 1) |
else if (eh->ether_dhost[0] & 1) |
m->m_flags |= M_MCAST; |
m->m_flags |= M_MCAST; |
|
#endif |
if (m->m_flags & (M_BCAST|M_MCAST)) |
if (m->m_flags & (M_BCAST|M_MCAST)) |
ifp->if_imcasts++; |
ifp->if_imcasts++; |
|
|
Line 416 ether_sprintf(ap) |
|
Line 434 ether_sprintf(ap) |
|
*--cp = 0; |
*--cp = 0; |
return (etherbuf); |
return (etherbuf); |
} |
} |
|
|
|
#ifdef MULTICAST |
|
u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; |
|
u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; |
|
|
|
/* XXX */ |
|
#undef ac |
|
/* |
|
* Add an Ethernet multicast address or range of addresses to the list for a |
|
* given interface. |
|
*/ |
|
int |
|
ether_addmulti(ifr, ac) |
|
struct ifreq *ifr; |
|
register struct arpcom *ac; |
|
{ |
|
register struct ether_multi *enm; |
|
struct sockaddr_in *sin; |
|
u_char addrlo[6]; |
|
u_char addrhi[6]; |
|
int s = splimp(); |
|
|
|
switch (ifr->ifr_addr.sa_family) { |
|
|
|
case AF_UNSPEC: |
|
bcopy(ifr->ifr_addr.sa_data, addrlo, 6); |
|
bcopy(addrlo, addrhi, 6); |
|
break; |
|
|
|
#ifdef INET |
|
case AF_INET: |
|
sin = (struct sockaddr_in *)&(ifr->ifr_addr); |
|
if (sin->sin_addr.s_addr == INADDR_ANY) { |
|
/* |
|
* An IP address of INADDR_ANY means listen to all |
|
* of the Ethernet multicast addresses used for IP. |
|
* (This is for the sake of IP multicast routers.) |
|
*/ |
|
bcopy(ether_ipmulticast_min, addrlo, 6); |
|
bcopy(ether_ipmulticast_max, addrhi, 6); |
|
} |
|
else { |
|
ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); |
|
bcopy(addrlo, addrhi, 6); |
|
} |
|
break; |
|
#endif |
|
|
|
default: |
|
splx(s); |
|
return (EAFNOSUPPORT); |
|
} |
|
|
|
/* |
|
* Verify that we have valid Ethernet multicast addresses. |
|
*/ |
|
if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { |
|
splx(s); |
|
return (EINVAL); |
|
} |
|
/* |
|
* See if the address range is already in the list. |
|
*/ |
|
ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); |
|
if (enm != NULL) { |
|
/* |
|
* Found it; just increment the reference count. |
|
*/ |
|
++enm->enm_refcount; |
|
splx(s); |
|
return (0); |
|
} |
|
/* |
|
* New address or range; malloc a new multicast record |
|
* and link it into the interface's multicast list. |
|
*/ |
|
enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); |
|
if (enm == NULL) { |
|
splx(s); |
|
return (ENOBUFS); |
|
} |
|
bcopy(addrlo, enm->enm_addrlo, 6); |
|
bcopy(addrhi, enm->enm_addrhi, 6); |
|
enm->enm_ac = ac; |
|
enm->enm_refcount = 1; |
|
enm->enm_next = ac->ac_multiaddrs; |
|
ac->ac_multiaddrs = enm; |
|
ac->ac_multicnt++; |
|
splx(s); |
|
/* |
|
* Return ENETRESET to inform the driver that the list has changed |
|
* and its reception filter should be adjusted accordingly. |
|
*/ |
|
return (ENETRESET); |
|
} |
|
|
|
/* |
|
* Delete a multicast address record. |
|
*/ |
|
int |
|
ether_delmulti(ifr, ac) |
|
struct ifreq *ifr; |
|
register struct arpcom *ac; |
|
{ |
|
register struct ether_multi *enm; |
|
register struct ether_multi **p; |
|
struct sockaddr_in *sin; |
|
u_char addrlo[6]; |
|
u_char addrhi[6]; |
|
int s = splimp(); |
|
|
|
switch (ifr->ifr_addr.sa_family) { |
|
|
|
case AF_UNSPEC: |
|
bcopy(ifr->ifr_addr.sa_data, addrlo, 6); |
|
bcopy(addrlo, addrhi, 6); |
|
break; |
|
|
|
#ifdef INET |
|
case AF_INET: |
|
sin = (struct sockaddr_in *)&(ifr->ifr_addr); |
|
if (sin->sin_addr.s_addr == INADDR_ANY) { |
|
/* |
|
* An IP address of INADDR_ANY means stop listening |
|
* to the range of Ethernet multicast addresses used |
|
* for IP. |
|
*/ |
|
bcopy(ether_ipmulticast_min, addrlo, 6); |
|
bcopy(ether_ipmulticast_max, addrhi, 6); |
|
} |
|
else { |
|
ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); |
|
bcopy(addrlo, addrhi, 6); |
|
} |
|
break; |
|
#endif |
|
|
|
default: |
|
splx(s); |
|
return (EAFNOSUPPORT); |
|
} |
|
|
|
/* |
|
* Look up the address in our list. |
|
*/ |
|
ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); |
|
if (enm == NULL) { |
|
splx(s); |
|
return (ENXIO); |
|
} |
|
if (--enm->enm_refcount != 0) { |
|
/* |
|
* Still some claims to this record. |
|
*/ |
|
splx(s); |
|
return (0); |
|
} |
|
/* |
|
* No remaining claims to this record; unlink and free it. |
|
*/ |
|
for (p = &enm->enm_ac->ac_multiaddrs; |
|
*p != enm; |
|
p = &(*p)->enm_next) |
|
continue; |
|
*p = (*p)->enm_next; |
|
free(enm, M_IFMADDR); |
|
ac->ac_multicnt--; |
|
splx(s); |
|
/* |
|
* Return ENETRESET to inform the driver that the list has changed |
|
* and its reception filter should be adjusted accordingly. |
|
*/ |
|
return (ENETRESET); |
|
} |
|
#endif |