Do not return unlocked/unreferenced lle in arpresolve/nd6_storelladdr -
return lle flags IFF needed. Do not pass rte to arpresolve - pass is_gateway flag instead.
This commit is contained in:
parent
c69aeaad14
commit
74860d4f7c
@ -103,9 +103,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
|||||||
u_int8_t atype, adst;
|
u_int8_t atype, adst;
|
||||||
int loop_copy = 0;
|
int loop_copy = 0;
|
||||||
int isphds;
|
int isphds;
|
||||||
#if defined(INET) || defined(INET6)
|
int is_gw;
|
||||||
struct llentry *lle;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!((ifp->if_flags & IFF_UP) &&
|
if (!((ifp->if_flags & IFF_UP) &&
|
||||||
(ifp->if_drv_flags & IFF_DRV_RUNNING)))
|
(ifp->if_drv_flags & IFF_DRV_RUNNING)))
|
||||||
@ -125,8 +123,11 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
|||||||
else if (ifp->if_flags & IFF_NOARP)
|
else if (ifp->if_flags & IFF_NOARP)
|
||||||
adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF;
|
adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF;
|
||||||
else {
|
else {
|
||||||
error = arpresolve(ifp, ro ? ro->ro_rt : NULL,
|
is_gw = 0;
|
||||||
m, dst, &adst, &lle);
|
if (ro != NULL && ro->ro_rt != NULL &&
|
||||||
|
(ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
|
||||||
|
is_gw = 1;
|
||||||
|
error = arpresolve(ifp, is_gw, m, dst, &adst, NULL);
|
||||||
if (error)
|
if (error)
|
||||||
return (error == EWOULDBLOCK ? 0 : error);
|
return (error == EWOULDBLOCK ? 0 : error);
|
||||||
}
|
}
|
||||||
@ -164,7 +165,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
|||||||
#endif
|
#endif
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
error = nd6_storelladdr(ifp, m, dst, (u_char *)&adst, &lle);
|
error = nd6_storelladdr(ifp, m, dst, (u_char *)&adst, NULL);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
atype = ARCTYPE_INET6;
|
atype = ARCTYPE_INET6;
|
||||||
|
@ -154,11 +154,18 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
|
|||||||
struct pf_mtag *t;
|
struct pf_mtag *t;
|
||||||
int loop_copy = 1;
|
int loop_copy = 1;
|
||||||
int hlen; /* link layer header length */
|
int hlen; /* link layer header length */
|
||||||
|
int is_gw = 0;
|
||||||
|
uint32_t pflags = 0;
|
||||||
|
|
||||||
if (ro != NULL) {
|
if (ro != NULL) {
|
||||||
if (!(m->m_flags & (M_BCAST | M_MCAST)))
|
if (!(m->m_flags & (M_BCAST | M_MCAST))) {
|
||||||
lle = ro->ro_lle;
|
lle = ro->ro_lle;
|
||||||
|
if (lle != NULL)
|
||||||
|
pflags = lle->la_flags;
|
||||||
|
}
|
||||||
rt0 = ro->ro_rt;
|
rt0 = ro->ro_rt;
|
||||||
|
if (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) != 0)
|
||||||
|
is_gw = 1;
|
||||||
}
|
}
|
||||||
#ifdef MAC
|
#ifdef MAC
|
||||||
error = mac_ifnet_check_transmit(ifp, m);
|
error = mac_ifnet_check_transmit(ifp, m);
|
||||||
@ -177,10 +184,10 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
|
|||||||
switch (dst->sa_family) {
|
switch (dst->sa_family) {
|
||||||
#ifdef INET
|
#ifdef INET
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
if (lle != NULL && (lle->la_flags & LLE_VALID))
|
if (lle != NULL && (pflags & LLE_VALID) != 0)
|
||||||
memcpy(edst, &lle->ll_addr.mac16, sizeof(edst));
|
memcpy(edst, &lle->ll_addr.mac16, sizeof(edst));
|
||||||
else
|
else
|
||||||
error = arpresolve(ifp, rt0, m, dst, edst, &lle);
|
error = arpresolve(ifp, is_gw, m, dst, edst, &pflags);
|
||||||
if (error)
|
if (error)
|
||||||
return (error == EWOULDBLOCK ? 0 : error);
|
return (error == EWOULDBLOCK ? 0 : error);
|
||||||
type = htons(ETHERTYPE_IP);
|
type = htons(ETHERTYPE_IP);
|
||||||
@ -215,10 +222,11 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
|
|||||||
#endif
|
#endif
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
if (lle != NULL && (lle->la_flags & LLE_VALID))
|
if (lle != NULL && (pflags & LLE_VALID))
|
||||||
memcpy(edst, &lle->ll_addr.mac16, sizeof(edst));
|
memcpy(edst, &lle->ll_addr.mac16, sizeof(edst));
|
||||||
else
|
else
|
||||||
error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle);
|
error = nd6_storelladdr(ifp, m, dst, (u_char *)edst,
|
||||||
|
&pflags);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
type = htons(ETHERTYPE_IPV6);
|
type = htons(ETHERTYPE_IPV6);
|
||||||
@ -241,7 +249,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
|
|||||||
senderr(EAFNOSUPPORT);
|
senderr(EAFNOSUPPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lle != NULL && (lle->la_flags & LLE_IFADDR)) {
|
if ((pflags & LLE_IFADDR) != 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, dst->sa_family, 0));
|
||||||
}
|
}
|
||||||
|
@ -101,9 +101,7 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
|||||||
int loop_copy = 0, error = 0, hdrcmplt = 0;
|
int loop_copy = 0, error = 0, hdrcmplt = 0;
|
||||||
u_char esrc[FDDI_ADDR_LEN], edst[FDDI_ADDR_LEN];
|
u_char esrc[FDDI_ADDR_LEN], edst[FDDI_ADDR_LEN];
|
||||||
struct fddi_header *fh;
|
struct fddi_header *fh;
|
||||||
#if defined(INET) || defined(INET6)
|
int is_gw;
|
||||||
struct llentry *lle;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MAC
|
#ifdef MAC
|
||||||
error = mac_ifnet_check_transmit(ifp, m);
|
error = mac_ifnet_check_transmit(ifp, m);
|
||||||
@ -121,11 +119,11 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
|||||||
switch (dst->sa_family) {
|
switch (dst->sa_family) {
|
||||||
#ifdef INET
|
#ifdef INET
|
||||||
case AF_INET: {
|
case AF_INET: {
|
||||||
struct rtentry *rt0 = NULL;
|
is_gw = 0;
|
||||||
|
if (ro != NULL && ro->ro_rt != NULL &&
|
||||||
if (ro != NULL)
|
(ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
|
||||||
rt0 = ro->ro_rt;
|
is_gw = 1;
|
||||||
error = arpresolve(ifp, rt0, m, dst, edst, &lle);
|
error = arpresolve(ifp, is_gw, m, dst, edst, NULL);
|
||||||
if (error)
|
if (error)
|
||||||
return (error == EWOULDBLOCK ? 0 : error);
|
return (error == EWOULDBLOCK ? 0 : error);
|
||||||
type = htons(ETHERTYPE_IP);
|
type = htons(ETHERTYPE_IP);
|
||||||
@ -161,7 +159,7 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
|||||||
#endif /* INET */
|
#endif /* INET */
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle);
|
error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, NULL);
|
||||||
if (error)
|
if (error)
|
||||||
return (error); /* Something bad happened */
|
return (error); /* Something bad happened */
|
||||||
type = htons(ETHERTYPE_IPV6);
|
type = htons(ETHERTYPE_IPV6);
|
||||||
|
@ -89,9 +89,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
|||||||
struct mbuf *mtail;
|
struct mbuf *mtail;
|
||||||
int unicast, dgl, foff;
|
int unicast, dgl, foff;
|
||||||
static int next_dgl;
|
static int next_dgl;
|
||||||
#if defined(INET) || defined(INET6)
|
int is_gw;
|
||||||
struct llentry *lle;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MAC
|
#ifdef MAC
|
||||||
error = mac_ifnet_check_transmit(ifp, m);
|
error = mac_ifnet_check_transmit(ifp, m);
|
||||||
@ -140,7 +138,11 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
|||||||
* doesn't fit into the arp model.
|
* doesn't fit into the arp model.
|
||||||
*/
|
*/
|
||||||
if (unicast) {
|
if (unicast) {
|
||||||
error = arpresolve(ifp, ro ? ro->ro_rt : NULL, m, dst, (u_char *) destfw, &lle);
|
is_gw = 0;
|
||||||
|
if (ro != NULL && ro->ro_rt != NULL &&
|
||||||
|
(ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
|
||||||
|
is_gw = 1;
|
||||||
|
error = arpresolve(ifp, is_gw, m, dst, (u_char *) destfw, NULL);
|
||||||
if (error)
|
if (error)
|
||||||
return (error == EWOULDBLOCK ? 0 : error);
|
return (error == EWOULDBLOCK ? 0 : error);
|
||||||
}
|
}
|
||||||
@ -170,7 +172,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
|||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
if (unicast) {
|
if (unicast) {
|
||||||
error = nd6_storelladdr(fc->fc_ifp, m, dst,
|
error = nd6_storelladdr(fc->fc_ifp, m, dst,
|
||||||
(u_char *) destfw, &lle);
|
(u_char *) destfw, NULL);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
@ -212,12 +212,13 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
|||||||
struct iso88025_header gen_th;
|
struct iso88025_header gen_th;
|
||||||
struct sockaddr_dl *sdl = NULL;
|
struct sockaddr_dl *sdl = NULL;
|
||||||
struct rtentry *rt0 = NULL;
|
struct rtentry *rt0 = NULL;
|
||||||
#if defined(INET) || defined(INET6)
|
int is_gw = 0;
|
||||||
struct llentry *lle;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ro != NULL)
|
if (ro != NULL) {
|
||||||
rt0 = ro->ro_rt;
|
rt0 = ro->ro_rt;
|
||||||
|
if (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) != 0)
|
||||||
|
is_gw = 1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MAC
|
#ifdef MAC
|
||||||
error = mac_ifnet_check_transmit(ifp, m);
|
error = mac_ifnet_check_transmit(ifp, m);
|
||||||
@ -257,7 +258,7 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
|||||||
switch (dst->sa_family) {
|
switch (dst->sa_family) {
|
||||||
#ifdef INET
|
#ifdef INET
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
error = arpresolve(ifp, rt0, m, dst, edst, &lle);
|
error = arpresolve(ifp, is_gw, m, dst, edst, NULL);
|
||||||
if (error)
|
if (error)
|
||||||
return (error == EWOULDBLOCK ? 0 : error);
|
return (error == EWOULDBLOCK ? 0 : error);
|
||||||
snap_type = ETHERTYPE_IP;
|
snap_type = ETHERTYPE_IP;
|
||||||
@ -292,7 +293,7 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
|||||||
#endif /* INET */
|
#endif /* INET */
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle);
|
error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, NULL);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
snap_type = ETHERTYPE_IPV6;
|
snap_type = ETHERTYPE_IPV6;
|
||||||
|
@ -286,19 +286,20 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip,
|
|||||||
* Resolve an IP address into an ethernet address.
|
* Resolve an IP address into an ethernet address.
|
||||||
* On input:
|
* On input:
|
||||||
* ifp is the interface we use
|
* ifp is the interface we use
|
||||||
* rt0 is the route to the final destination (possibly useless)
|
* is_gw != if @dst represents gateway to some destination
|
||||||
* m is the mbuf. May be NULL if we don't have a packet.
|
* m is the mbuf. May be NULL if we don't have a packet.
|
||||||
* dst is the next hop,
|
* dst is the next hop,
|
||||||
* desten is where we want the address.
|
* desten is where we want the address.
|
||||||
|
* flags returns lle entry flags.
|
||||||
*
|
*
|
||||||
* On success, desten is filled in and the function returns 0;
|
* On success, desten and flags are filled in and the function returns 0;
|
||||||
* If the packet must be held pending resolution, we return EWOULDBLOCK
|
* If the packet must be held pending resolution, we return EWOULDBLOCK
|
||||||
* On other errors, we return the corresponding error code.
|
* On other errors, we return the corresponding error code.
|
||||||
* Note that m_freem() handles NULL.
|
* Note that m_freem() handles NULL.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
|
arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
|
||||||
const struct sockaddr *dst, u_char *desten, struct llentry **lle)
|
const struct sockaddr *dst, u_char *desten, uint32_t *pflags)
|
||||||
{
|
{
|
||||||
struct llentry *la = 0;
|
struct llentry *la = 0;
|
||||||
u_int flags = 0;
|
u_int flags = 0;
|
||||||
@ -306,7 +307,9 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
|
|||||||
struct mbuf *next = NULL;
|
struct mbuf *next = NULL;
|
||||||
int error, renew;
|
int error, renew;
|
||||||
|
|
||||||
*lle = NULL;
|
if (pflags != NULL)
|
||||||
|
*pflags = 0;
|
||||||
|
|
||||||
if (m != NULL) {
|
if (m != NULL) {
|
||||||
if (m->m_flags & M_BCAST) {
|
if (m->m_flags & M_BCAST) {
|
||||||
/* broadcast */
|
/* broadcast */
|
||||||
@ -354,7 +357,8 @@ retry:
|
|||||||
la->la_preempt--;
|
la->la_preempt--;
|
||||||
}
|
}
|
||||||
|
|
||||||
*lle = la;
|
if (pflags != NULL)
|
||||||
|
*pflags = la->la_flags;
|
||||||
error = 0;
|
error = 0;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -412,8 +416,7 @@ retry:
|
|||||||
if (la->la_asked < V_arp_maxtries)
|
if (la->la_asked < V_arp_maxtries)
|
||||||
error = EWOULDBLOCK; /* First request. */
|
error = EWOULDBLOCK; /* First request. */
|
||||||
else
|
else
|
||||||
error = rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) ?
|
error = is_gw != 0 ? EHOSTUNREACH : EHOSTDOWN;
|
||||||
EHOSTUNREACH : EHOSTDOWN;
|
|
||||||
|
|
||||||
if (renew) {
|
if (renew) {
|
||||||
int canceled;
|
int canceled;
|
||||||
|
@ -112,11 +112,10 @@ struct sockaddr_inarp {
|
|||||||
extern u_char ether_ipmulticast_min[ETHER_ADDR_LEN];
|
extern u_char ether_ipmulticast_min[ETHER_ADDR_LEN];
|
||||||
extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN];
|
extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN];
|
||||||
|
|
||||||
struct llentry;
|
|
||||||
struct ifaddr;
|
struct ifaddr;
|
||||||
|
|
||||||
int arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m,
|
int arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
|
||||||
const struct sockaddr *dst, u_char *desten, struct llentry **lle);
|
const struct sockaddr *dst, u_char *desten, uint32_t *pflags);
|
||||||
void arprequest(struct ifnet *, const struct in_addr *,
|
void arprequest(struct ifnet *, const struct in_addr *,
|
||||||
const struct in_addr *, u_char *);
|
const struct in_addr *, u_char *);
|
||||||
void arp_ifinit(struct ifnet *, struct ifaddr *);
|
void arp_ifinit(struct ifnet *, struct ifaddr *);
|
||||||
|
@ -516,15 +516,12 @@ int
|
|||||||
toe_l2_resolve(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa,
|
toe_l2_resolve(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa,
|
||||||
uint8_t *lladdr, uint16_t *vtag)
|
uint8_t *lladdr, uint16_t *vtag)
|
||||||
{
|
{
|
||||||
#ifdef INET
|
|
||||||
struct llentry *lle;
|
|
||||||
#endif
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
switch (sa->sa_family) {
|
switch (sa->sa_family) {
|
||||||
#ifdef INET
|
#ifdef INET
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
rc = arpresolve(ifp, NULL, NULL, sa, lladdr, &lle);
|
rc = arpresolve(ifp, 0, NULL, sa, lladdr, NULL);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
|
@ -2278,11 +2278,12 @@ nd6_rem_ifa_lle(struct in6_ifaddr *ia)
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
|
nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
|
||||||
const struct sockaddr *dst, u_char *desten, struct llentry **lle)
|
const struct sockaddr *dst, u_char *desten, uint32_t *pflags)
|
||||||
{
|
{
|
||||||
struct llentry *ln;
|
struct llentry *ln;
|
||||||
|
|
||||||
*lle = NULL;
|
if (pflags != NULL)
|
||||||
|
*pflags = 0;
|
||||||
IF_AFDATA_UNLOCK_ASSERT(ifp);
|
IF_AFDATA_UNLOCK_ASSERT(ifp);
|
||||||
if (m != NULL && m->m_flags & M_MCAST) {
|
if (m != NULL && m->m_flags & M_MCAST) {
|
||||||
int i;
|
int i;
|
||||||
@ -2334,7 +2335,8 @@ nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bcopy(&ln->ll_addr, desten, ifp->if_addrlen);
|
bcopy(&ln->ll_addr, desten, ifp->if_addrlen);
|
||||||
*lle = ln;
|
if (pflags != NULL)
|
||||||
|
*pflags = ln->la_flags;
|
||||||
LLE_RUNLOCK(ln);
|
LLE_RUNLOCK(ln);
|
||||||
/*
|
/*
|
||||||
* A *small* use after free race exists here
|
* A *small* use after free race exists here
|
||||||
|
@ -418,7 +418,7 @@ int nd6_need_cache(struct ifnet *);
|
|||||||
int nd6_add_ifa_lle(struct in6_ifaddr *);
|
int nd6_add_ifa_lle(struct in6_ifaddr *);
|
||||||
void nd6_rem_ifa_lle(struct in6_ifaddr *);
|
void nd6_rem_ifa_lle(struct in6_ifaddr *);
|
||||||
int nd6_storelladdr(struct ifnet *, struct mbuf *,
|
int nd6_storelladdr(struct ifnet *, struct mbuf *,
|
||||||
const struct sockaddr *, u_char *, struct llentry **);
|
const struct sockaddr *, u_char *, uint32_t *);
|
||||||
|
|
||||||
/* nd6_nbr.c */
|
/* nd6_nbr.c */
|
||||||
void nd6_na_input(struct mbuf *, int, int);
|
void nd6_na_input(struct mbuf *, int, int);
|
||||||
|
@ -347,14 +347,12 @@ static int addr_resolve(struct sockaddr *src_in,
|
|||||||
struct sockaddr_in6 *sin6;
|
struct sockaddr_in6 *sin6;
|
||||||
struct ifaddr *ifa;
|
struct ifaddr *ifa;
|
||||||
struct ifnet *ifp;
|
struct ifnet *ifp;
|
||||||
#if defined(INET) || defined(INET6)
|
|
||||||
struct llentry *lle;
|
|
||||||
#endif
|
|
||||||
struct rtentry *rte;
|
struct rtentry *rte;
|
||||||
in_port_t port;
|
in_port_t port;
|
||||||
u_char edst[MAX_ADDR_LEN];
|
u_char edst[MAX_ADDR_LEN];
|
||||||
int multi;
|
int multi;
|
||||||
int bcast;
|
int bcast;
|
||||||
|
int is_gw = 0;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -430,6 +428,8 @@ static int addr_resolve(struct sockaddr *src_in,
|
|||||||
RTFREE_LOCKED(rte);
|
RTFREE_LOCKED(rte);
|
||||||
return -EHOSTUNREACH;
|
return -EHOSTUNREACH;
|
||||||
}
|
}
|
||||||
|
if (rte->rt_flags & RTF_GATEWAY)
|
||||||
|
is_gw = 1;
|
||||||
/*
|
/*
|
||||||
* If it's not multicast or broadcast and the route doesn't match the
|
* If it's not multicast or broadcast and the route doesn't match the
|
||||||
* requested interface return unreachable. Otherwise fetch the
|
* requested interface return unreachable. Otherwise fetch the
|
||||||
@ -467,12 +467,12 @@ mcast:
|
|||||||
switch (dst_in->sa_family) {
|
switch (dst_in->sa_family) {
|
||||||
#ifdef INET
|
#ifdef INET
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
error = arpresolve(ifp, rte, NULL, dst_in, edst, &lle);
|
error = arpresolve(ifp, is_gw, NULL, dst_in, edst, NULL);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
error = nd6_storelladdr(ifp, NULL, dst_in, (u_char *)edst, &lle);
|
error = nd6_storelladdr(ifp, NULL, dst_in, (u_char *)edst,NULL);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
@ -1259,13 +1259,15 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m,
|
|||||||
struct llentry *lle = NULL;
|
struct llentry *lle = NULL;
|
||||||
struct rtentry *rt0 = NULL;
|
struct rtentry *rt0 = NULL;
|
||||||
struct ipoib_header *eh;
|
struct ipoib_header *eh;
|
||||||
int error = 0;
|
int error = 0, is_gw = 0;
|
||||||
short type;
|
short type;
|
||||||
|
|
||||||
if (ro != NULL) {
|
if (ro != NULL) {
|
||||||
if (!(m->m_flags & (M_BCAST | M_MCAST)))
|
if (!(m->m_flags & (M_BCAST | M_MCAST)))
|
||||||
lle = ro->ro_lle;
|
lle = ro->ro_lle;
|
||||||
rt0 = ro->ro_rt;
|
rt0 = ro->ro_rt;
|
||||||
|
if (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) != 0)
|
||||||
|
is_gw = 1;
|
||||||
}
|
}
|
||||||
#ifdef MAC
|
#ifdef MAC
|
||||||
error = mac_ifnet_check_transmit(ifp, m);
|
error = mac_ifnet_check_transmit(ifp, m);
|
||||||
@ -1292,7 +1294,7 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m,
|
|||||||
else if (m->m_flags & M_MCAST)
|
else if (m->m_flags & M_MCAST)
|
||||||
ip_ib_mc_map(((struct sockaddr_in *)dst)->sin_addr.s_addr, ifp->if_broadcastaddr, edst);
|
ip_ib_mc_map(((struct sockaddr_in *)dst)->sin_addr.s_addr, ifp->if_broadcastaddr, edst);
|
||||||
else
|
else
|
||||||
error = arpresolve(ifp, rt0, m, dst, edst, &lle);
|
error = arpresolve(ifp, is_gw, m, dst, edst, NULL);
|
||||||
if (error)
|
if (error)
|
||||||
return (error == EWOULDBLOCK ? 0 : error);
|
return (error == EWOULDBLOCK ? 0 : error);
|
||||||
type = htons(ETHERTYPE_IP);
|
type = htons(ETHERTYPE_IP);
|
||||||
@ -1330,7 +1332,7 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m,
|
|||||||
else if (m->m_flags & M_MCAST)
|
else if (m->m_flags & M_MCAST)
|
||||||
ipv6_ib_mc_map(&((struct sockaddr_in6 *)dst)->sin6_addr, ifp->if_broadcastaddr, edst);
|
ipv6_ib_mc_map(&((struct sockaddr_in6 *)dst)->sin6_addr, ifp->if_broadcastaddr, edst);
|
||||||
else
|
else
|
||||||
error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle);
|
error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, NULL);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
type = htons(ETHERTYPE_IPV6);
|
type = htons(ETHERTYPE_IPV6);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user