Changeset View
Changeset View
Standalone View
Standalone View
sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
Show First 20 Lines • Show All 683 Lines • ▼ Show 20 Lines | ipf_fastroute(m0, mpp, fin, fdp) | ||||
mb_t *m0, **mpp; | mb_t *m0, **mpp; | ||||
fr_info_t *fin; | fr_info_t *fin; | ||||
frdest_t *fdp; | frdest_t *fdp; | ||||
{ | { | ||||
register struct ip *ip, *mhip; | register struct ip *ip, *mhip; | ||||
register struct mbuf *m = *mpp; | register struct mbuf *m = *mpp; | ||||
int len, off, error = 0, hlen, code; | int len, off, error = 0, hlen, code; | ||||
struct ifnet *ifp, *sifp; | struct ifnet *ifp, *sifp; | ||||
struct sockaddr_in dst; | struct route ro; | ||||
struct sockaddr_in *dst; | |||||
const struct sockaddr *gw; | |||||
struct nhop_object *nh; | struct nhop_object *nh; | ||||
u_long fibnum = 0; | u_long fibnum = 0; | ||||
u_short ip_off; | u_short ip_off; | ||||
frdest_t node; | frdest_t node; | ||||
frentry_t *fr; | frentry_t *fr; | ||||
#ifdef M_WRITABLE | #ifdef M_WRITABLE | ||||
/* | /* | ||||
Show All 33 Lines | #endif | ||||
hlen = fin->fin_hlen; | hlen = fin->fin_hlen; | ||||
ip = mtod(m0, struct ip *); | ip = mtod(m0, struct ip *); | ||||
ifp = NULL; | ifp = NULL; | ||||
/* | /* | ||||
* Route packet. | * Route packet. | ||||
*/ | */ | ||||
bzero(&dst, sizeof (dst)); | bzero(&ro, sizeof (ro)); | ||||
dst.sin_family = AF_INET; | dst = (struct sockaddr_in *)&ro.ro_dst; | ||||
dst.sin_addr = ip->ip_dst; | dst->sin_family = AF_INET; | ||||
dst.sin_len = sizeof(dst); | dst->sin_addr = ip->ip_dst; | ||||
dst->sin_len = sizeof(dst); | |||||
gw = (const struct sockaddr *)dst; | |||||
fr = fin->fin_fr; | fr = fin->fin_fr; | ||||
if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && | if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && | ||||
(fdp->fd_type == FRD_DSTLIST)) { | (fdp->fd_type == FRD_DSTLIST)) { | ||||
if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) | if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) | ||||
fdp = &node; | fdp = &node; | ||||
} | } | ||||
if (fdp != NULL) | if (fdp != NULL) | ||||
ifp = fdp->fd_ptr; | ifp = fdp->fd_ptr; | ||||
else | else | ||||
ifp = fin->fin_ifp; | ifp = fin->fin_ifp; | ||||
if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) { | if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) { | ||||
error = -2; | error = -2; | ||||
goto bad; | goto bad; | ||||
} | } | ||||
if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) | if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) | ||||
dst.sin_addr = fdp->fd_ip; | dst->sin_addr = fdp->fd_ip; | ||||
fibnum = M_GETFIB(m0); | fibnum = M_GETFIB(m0); | ||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
nh = fib4_lookup(fibnum, dst.sin_addr, 0, NHR_NONE, 0); | nh = fib4_lookup(fibnum, dst->sin_addr, 0, NHR_NONE, 0); | ||||
if (nh == NULL) { | if (nh == NULL) { | ||||
if (in_localaddr(ip->ip_dst)) | if (in_localaddr(ip->ip_dst)) | ||||
error = EHOSTUNREACH; | error = EHOSTUNREACH; | ||||
else | else | ||||
error = ENETUNREACH; | error = ENETUNREACH; | ||||
goto bad; | goto bad; | ||||
} | } | ||||
if (ifp == NULL) | if (ifp == NULL) | ||||
ifp = nh->nh_ifp; | ifp = nh->nh_ifp; | ||||
if (nh->nh_flags & NHF_GATEWAY) | if (nh->nh_flags & NHF_GATEWAY) { | ||||
dst.sin_addr = nh->gw4_sa.sin_addr; | gw = &nh->gw_sa; | ||||
ro.ro_flags |= RT_HAS_GW; | |||||
} | |||||
/* | /* | ||||
* For input packets which are being "fastrouted", they won't | * For input packets which are being "fastrouted", they won't | ||||
* go back through output filtering and miss their chance to get | * go back through output filtering and miss their chance to get | ||||
* NAT'd and counted. Duplicated packets aren't considered to be | * NAT'd and counted. Duplicated packets aren't considered to be | ||||
* part of the normal packet stream, so do not NAT them or pass | * part of the normal packet stream, so do not NAT them or pass | ||||
* them through stateful checking, etc. | * them through stateful checking, etc. | ||||
*/ | */ | ||||
Show All 27 Lines | #endif | ||||
} else | } else | ||||
ip->ip_sum = 0; | ip->ip_sum = 0; | ||||
/* | /* | ||||
* If small enough for interface, can just send directly. | * If small enough for interface, can just send directly. | ||||
*/ | */ | ||||
if (ntohs(ip->ip_len) <= ifp->if_mtu) { | if (ntohs(ip->ip_len) <= ifp->if_mtu) { | ||||
if (!ip->ip_sum) | if (!ip->ip_sum) | ||||
ip->ip_sum = in_cksum(m, hlen); | ip->ip_sum = in_cksum(m, hlen); | ||||
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)&dst, | error = (*ifp->if_output)(ifp, m, gw, &ro); | ||||
NULL | |||||
); | |||||
goto done; | goto done; | ||||
} | } | ||||
/* | /* | ||||
* Too large for interface; fragment if possible. | * Too large for interface; fragment if possible. | ||||
* Must be able to put at least 8 bytes per fragment. | * Must be able to put at least 8 bytes per fragment. | ||||
*/ | */ | ||||
ip_off = ntohs(ip->ip_off); | ip_off = ntohs(ip->ip_off); | ||||
if (ip_off & IP_DF) { | if (ip_off & IP_DF) { | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | #endif | ||||
ip->ip_off = htons((u_short)IP_MF); | ip->ip_off = htons((u_short)IP_MF); | ||||
ip->ip_sum = 0; | ip->ip_sum = 0; | ||||
ip->ip_sum = in_cksum(m0, hlen); | ip->ip_sum = in_cksum(m0, hlen); | ||||
sendorfree: | sendorfree: | ||||
for (m = m0; m; m = m0) { | for (m = m0; m; m = m0) { | ||||
m0 = m->m_act; | m0 = m->m_act; | ||||
m->m_act = 0; | m->m_act = 0; | ||||
if (error == 0) | if (error == 0) | ||||
error = (*ifp->if_output)(ifp, m, | error = (*ifp->if_output)(ifp, m, gw, &ro); | ||||
(struct sockaddr *)&dst, | |||||
NULL | |||||
); | |||||
else | else | ||||
FREE_MB_T(m); | FREE_MB_T(m); | ||||
} | } | ||||
} | } | ||||
done: | done: | ||||
if (!error) | if (!error) | ||||
V_ipfmain.ipf_frouteok[0]++; | V_ipfmain.ipf_frouteok[0]++; | ||||
else | else | ||||
▲ Show 20 Lines • Show All 578 Lines • Show Last 20 Lines |