Changeset View
Changeset View
Standalone View
Standalone View
sys/net/if_ethersubr.c
Show First 20 Lines • Show All 230 Lines • ▼ Show 20 Lines | else { | ||||||||||||||
etype = htons(ETHERTYPE_IP); | etype = htons(ETHERTYPE_IP); | ||||||||||||||
memcpy(&eh->ether_type, &etype, sizeof(etype)); | memcpy(&eh->ether_type, &etype, sizeof(etype)); | ||||||||||||||
memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN); | memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN); | ||||||||||||||
} | } | ||||||||||||||
break; | break; | ||||||||||||||
#endif | #endif | ||||||||||||||
#ifdef INET6 | #ifdef INET6 | ||||||||||||||
case AF_INET6: | case AF_INET6: | ||||||||||||||
if ((m->m_flags & M_MCAST) == 0) | if ((m->m_flags & M_MCAST) == 0) | ||||||||||||||
error = nd6_resolve(ifp, 0, m, dst, phdr, &lleflags, | error = nd6_resolve(ifp, 0, m, dst, phdr, &lleflags, | ||||||||||||||
plle); | plle); | ||||||||||||||
else { | else { | ||||||||||||||
melifaroUnsubmitted Done Inline Actions
melifaro: | |||||||||||||||
const struct in6_addr *a6; | const struct in6_addr *a6; | ||||||||||||||
a6 = &(((const struct sockaddr_in6 *)dst)->sin6_addr); | a6 = &(((const struct sockaddr_in6 *)dst)->sin6_addr); | ||||||||||||||
ETHER_MAP_IPV6_MULTICAST(a6, eh->ether_dhost); | ETHER_MAP_IPV6_MULTICAST(a6, eh->ether_dhost); | ||||||||||||||
etype = htons(ETHERTYPE_IPV6); | etype = htons(ETHERTYPE_IPV6); | ||||||||||||||
memcpy(&eh->ether_type, &etype, sizeof(etype)); | memcpy(&eh->ether_type, &etype, sizeof(etype)); | ||||||||||||||
memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN); | memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN); | ||||||||||||||
} | } | ||||||||||||||
break; | break; | ||||||||||||||
Show All 34 Lines | ether_output(struct ifnet *ifp, struct mbuf *m, | ||||||||||||||
char linkhdr[ETHER_HDR_LEN], *phdr; | char linkhdr[ETHER_HDR_LEN], *phdr; | ||||||||||||||
struct ether_header *eh; | struct ether_header *eh; | ||||||||||||||
struct pf_mtag *t; | struct pf_mtag *t; | ||||||||||||||
bool loop_copy; | bool loop_copy; | ||||||||||||||
int hlen; /* link layer header length */ | int hlen; /* link layer header length */ | ||||||||||||||
uint32_t pflags; | uint32_t pflags; | ||||||||||||||
struct llentry *lle = NULL; | struct llentry *lle = NULL; | ||||||||||||||
int addref = 0; | int addref = 0; | ||||||||||||||
int af = RO_GET_FAMILY(ro, dst); | |||||||||||||||
phdr = NULL; | phdr = NULL; | ||||||||||||||
pflags = 0; | pflags = 0; | ||||||||||||||
if (ro != NULL) { | if (ro != NULL) { | ||||||||||||||
/* XXX BPF uses ro_prepend */ | /* XXX BPF uses ro_prepend */ | ||||||||||||||
if (ro->ro_prepend != NULL) { | if (ro->ro_prepend != NULL) { | ||||||||||||||
phdr = ro->ro_prepend; | phdr = ro->ro_prepend; | ||||||||||||||
hlen = ro->ro_plen; | hlen = ro->ro_plen; | ||||||||||||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | if (phdr == NULL) { | ||||||||||||||
if (addref && lle != NULL) | if (addref && lle != NULL) | ||||||||||||||
ro->ro_lle = lle; | ro->ro_lle = lle; | ||||||||||||||
if (error != 0) | if (error != 0) | ||||||||||||||
return (error == EWOULDBLOCK ? 0 : error); | return (error == EWOULDBLOCK ? 0 : error); | ||||||||||||||
} | } | ||||||||||||||
if ((pflags & RT_L2_ME) != 0) { | if ((pflags & RT_L2_ME) != 0) { | ||||||||||||||
update_mbuf_csumflags(m, m); | update_mbuf_csumflags(m, m); | ||||||||||||||
return (if_simloop(ifp, m, dst->sa_family, 0)); | return (if_simloop(ifp, m, af, 0)); | ||||||||||||||
} | } | ||||||||||||||
loop_copy = (pflags & RT_MAY_LOOP) != 0; | loop_copy = (pflags & RT_MAY_LOOP) != 0; | ||||||||||||||
/* | /* | ||||||||||||||
* Add local net header. If no space in first mbuf, | * Add local net header. If no space in first mbuf, | ||||||||||||||
* allocate another. | * allocate another. | ||||||||||||||
* | * | ||||||||||||||
* Note that we do prepend regardless of RT_HAS_HEADER flag. | * Note that we do prepend regardless of RT_HAS_HEADER flag. | ||||||||||||||
* This is done because BPF code shifts m_data pointer | * This is done because BPF code shifts m_data pointer | ||||||||||||||
* to the end of ethernet header prior to calling if_output(). | * to the end of ethernet header prior to calling if_output(). | ||||||||||||||
*/ | */ | ||||||||||||||
M_PREPEND(m, hlen, M_NOWAIT); | M_PREPEND(m, hlen, M_NOWAIT); | ||||||||||||||
if (m == NULL) | if (m == NULL) | ||||||||||||||
senderr(ENOBUFS); | senderr(ENOBUFS); | ||||||||||||||
if ((pflags & RT_HAS_HEADER) == 0) { | if ((pflags & RT_HAS_HEADER) == 0) { | ||||||||||||||
eh = mtod(m, struct ether_header *); | eh = mtod(m, struct ether_header *); | ||||||||||||||
memcpy(eh, phdr, hlen); | memcpy(eh, phdr, hlen); | ||||||||||||||
#if defined(INET) && defined(INET6) | |||||||||||||||
melifaroUnsubmitted Done Inline ActionsNot needed anymore. melifaro: Not needed anymore. | |||||||||||||||
/* XXX phdr might be from lle cache, let's fix the ether_type */ | |||||||||||||||
if (dst->sa_family != af) { | |||||||||||||||
Done Inline ActionsIt is a HACK here to fix the link layer type. It is better that the lle cache has correct type. zlei: It is a HACK here to fix the link layer type. It is better that the lle cache has correct type. | |||||||||||||||
uint16_t etype = 0; | |||||||||||||||
if (af == AF_INET) | |||||||||||||||
etype = htons(ETHERTYPE_IP); | |||||||||||||||
else if (af == AF_INET6) | |||||||||||||||
etype = htons(ETHERTYPE_IPV6); | |||||||||||||||
if (etype != 0) | |||||||||||||||
memcpy(&eh->ether_type, &etype, sizeof(etype)); | |||||||||||||||
} | } | ||||||||||||||
#endif | |||||||||||||||
} | |||||||||||||||
/* | /* | ||||||||||||||
* If a simplex interface, and the packet is being sent to our | * If a simplex interface, and the packet is being sent to our | ||||||||||||||
* Ethernet address or a broadcast address, loopback a copy. | * Ethernet address or a broadcast address, loopback a copy. | ||||||||||||||
* XXX To make a simplex device behave exactly like a duplex | * XXX To make a simplex device behave exactly like a duplex | ||||||||||||||
* device, we should copy in the case of sending to our own | * device, we should copy in the case of sending to our own | ||||||||||||||
* ethernet address (thus letting the original actually appear | * ethernet address (thus letting the original actually appear | ||||||||||||||
* on the wire). However, we don't do that here for security | * on the wire). However, we don't do that here for security | ||||||||||||||
Show All 12 Lines | if ((m->m_flags & M_BCAST) && loop_copy && (ifp->if_flags & IFF_SIMPLEX) && | ||||||||||||||
* extra data copying vs. extra locking). | * extra data copying vs. extra locking). | ||||||||||||||
* | * | ||||||||||||||
* XXX This is a local workaround. A number of less | * XXX This is a local workaround. A number of less | ||||||||||||||
* often used kernel parts suffer from the same bug. | * often used kernel parts suffer from the same bug. | ||||||||||||||
* See PR kern/105943 for a proposed general solution. | * See PR kern/105943 for a proposed general solution. | ||||||||||||||
*/ | */ | ||||||||||||||
if ((n = m_dup(m, M_NOWAIT)) != NULL) { | if ((n = m_dup(m, M_NOWAIT)) != NULL) { | ||||||||||||||
update_mbuf_csumflags(m, n); | update_mbuf_csumflags(m, n); | ||||||||||||||
(void)if_simloop(ifp, n, dst->sa_family, hlen); | (void)if_simloop(ifp, n, af, hlen); | ||||||||||||||
} else | } else | ||||||||||||||
if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); | if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); | ||||||||||||||
} | } | ||||||||||||||
/* | /* | ||||||||||||||
* Bridges require special output handling. | * Bridges require special output handling. | ||||||||||||||
*/ | */ | ||||||||||||||
if (ifp->if_bridge) { | if (ifp->if_bridge) { | ||||||||||||||
▲ Show 20 Lines • Show All 1,078 Lines • Show Last 20 Lines |