summaryrefslogtreecommitdiffstats
path: root/sys/contrib/ipfilter/netinet/ip_fil.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/ipfilter/netinet/ip_fil.c')
-rw-r--r--sys/contrib/ipfilter/netinet/ip_fil.c582
1 files changed, 449 insertions, 133 deletions
diff --git a/sys/contrib/ipfilter/netinet/ip_fil.c b/sys/contrib/ipfilter/netinet/ip_fil.c
index 5e5bfce..643592c 100644
--- a/sys/contrib/ipfilter/netinet/ip_fil.c
+++ b/sys/contrib/ipfilter/netinet/ip_fil.c
@@ -17,7 +17,7 @@
#endif
#include <sys/param.h>
#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
- defined(_KERNEL)
+ defined(_KERNEL) && !defined(_LKM)
# include "opt_ipfilter_log.h"
#endif
#if defined(__FreeBSD__) && !defined(__FreeBSD_version)
@@ -25,6 +25,9 @@
# include <osreldate.h>
# endif
#endif
+#ifdef __sgi
+# include <sys/ptimers.h>
+#endif
#ifndef _KERNEL
# include <stdio.h>
# include <string.h>
@@ -45,7 +48,6 @@
#ifdef _KERNEL
# include <sys/systm.h>
#endif
-#include <sys/uio.h>
#if !SOLARIS
# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
# include <sys/dirent.h>
@@ -94,12 +96,16 @@
#include "netinet/ip_compat.h"
#ifdef USE_INET6
# include <netinet/icmp6.h>
+# if !SOLARIS
+# include <netinet6/ip6protosw.h>
+# include <netinet6/nd6.h>
+# endif
#endif
#include "netinet/ip_fil.h"
-#include "netinet/ip_proxy.h"
#include "netinet/ip_nat.h"
#include "netinet/ip_frag.h"
#include "netinet/ip_state.h"
+#include "netinet/ip_proxy.h"
#include "netinet/ip_auth.h"
#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
# include <sys/malloc.h>
@@ -147,15 +153,18 @@ static int frrequest __P((int, int, caddr_t, int));
#endif
#ifdef _KERNEL
static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **));
-static int send_ip __P((ip_t *, fr_info_t *, struct mbuf *));
+static int send_ip __P((ip_t *, fr_info_t *, struct mbuf **));
+# ifdef USE_INET6
+static int ipfr_fastroute6 __P((struct mbuf *, struct mbuf **,
+ fr_info_t *, frdest_t *));
+# endif
# ifdef __sgi
extern kmutex_t ipf_rw;
extern KRWLOCK_T ipf_mutex;
# endif
#else
-int ipllog __P((void));
void init_ifp __P((void));
-# ifdef __sgi
+# if defined(__sgi) && (IRIX < 605)
static int no_output __P((struct ifnet *, struct mbuf *,
struct sockaddr *));
static int write_output __P((struct ifnet *, struct mbuf *,
@@ -212,6 +221,77 @@ int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp));
# endif /* NETBSD_PF */
#endif /* __NetBSD__ */
+
+#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) && \
+ defined(_KERNEL)
+# include <net/pfil.h>
+
+static int fr_check_wrapper(void *, struct mbuf **, struct ifnet *, int );
+
+static int fr_check_wrapper(arg, mp, ifp, dir)
+void *arg;
+struct mbuf **mp;
+struct ifnet *ifp;
+int dir;
+{
+ struct ip *ip = mtod(*mp, struct ip *);
+ int rv, hlen = ip->ip_hl << 2;
+
+#if defined(M_CSUM_TCPv4)
+ /*
+ * If the packet is out-bound, we can't delay checksums
+ * here. For in-bound, the checksum has already been
+ * validated.
+ */
+ if (dir == PFIL_OUT) {
+ if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
+ in_delayed_cksum(*mp);
+ (*mp)->m_pkthdr.csum_flags &=
+ ~(M_CSUM_TCPv4|M_CSUM_UDPv4);
+ }
+ }
+#endif /* M_CSUM_TCPv4 */
+
+ /*
+ * We get the packet with all fields in network byte
+ * order. We expect ip_len and ip_off to be in host
+ * order. We frob them, call the filter, then frob
+ * them back.
+ *
+ * Note, we don't need to update the checksum, because
+ * it has already been verified.
+ */
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
+
+ rv = fr_check(ip, hlen, ifp, (dir == PFIL_OUT), mp);
+
+ if (rv == 0 && *mp != NULL) {
+ ip = mtod(*mp, struct ip *);
+ HTONS(ip->ip_len);
+ HTONS(ip->ip_off);
+ }
+
+ return (rv);
+}
+
+# ifdef USE_INET6
+# include <netinet/ip6.h>
+
+static int fr_check_wrapper6(void *, struct mbuf **, struct ifnet *, int );
+
+static int fr_check_wrapper6(arg, mp, ifp, dir)
+void *arg;
+struct mbuf **mp;
+struct ifnet *ifp;
+int dir;
+{
+
+ return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
+ ifp, (dir == PFIL_OUT), mp));
+}
+# endif
+#endif /* __NetBSD_Version >= 105110000 && _KERNEL */
#ifdef _KERNEL
# if defined(IPFILTER_LKM) && !defined(__sgi)
int iplidentify(s)
@@ -232,13 +312,20 @@ void
ipfilterattach(count)
int count;
{
- if (iplattach() != 0)
- printf("IP Filter failed to attach\n");
+
+ /*
+ * Do nothing here, really. The filter will be enabled
+ * by the SIOCFRENB ioctl.
+ */
}
# endif
+# if defined(__NetBSD__)
+int ipl_enable()
+# else
int iplattach()
+# endif
{
char *defpass;
int s;
@@ -246,6 +333,12 @@ int iplattach()
((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011)))
int error = 0;
# endif
+#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)
+ struct pfil_head *ph_inet;
+# ifdef USE_INET6
+ struct pfil_head *ph_inet6;
+# endif
+#endif
SPL_NET(s);
if (fr_running || (fr_checkp == fr_check)) {
@@ -272,8 +365,24 @@ int iplattach()
# ifdef NETBSD_PF
# if (__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011)
+# if __NetBSD_Version__ >= 105110000
+ if (
+ !(ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET))
+# ifdef USE_INET6
+ && !(ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6))
+# endif
+ )
+ return ENODEV;
+
+ if (ph_inet != NULL)
+ error = pfil_add_hook((void *)fr_check_wrapper, NULL,
+ PFIL_IN|PFIL_OUT, ph_inet);
+ else
+ error = 0;
+# else
error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+# endif
if (error) {
# ifdef USE_INET6
goto pfil_error;
@@ -289,11 +398,22 @@ int iplattach()
pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
# endif
# ifdef USE_INET6
+# if __NetBSD_Version__ >= 105110000
+ if (ph_inet6 != NULL)
+ error = pfil_add_hook((void *)fr_check_wrapper6, NULL,
+ PFIL_IN|PFIL_OUT, ph_inet6);
+ else
+ error = 0;
+ if (error) {
+ pfil_remove_hook((void *)fr_check_wrapper6, NULL,
+ PFIL_IN|PFIL_OUT, ph_inet6);
+# else
error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
- &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
+ &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
if (error) {
pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+# endif
pfil_error:
SPL_X(s);
appr_unload();
@@ -360,12 +480,22 @@ pfil_error:
* Disable the filter by removing the hooks from the IP input/output
* stream.
*/
+# if defined(__NetBSD__)
+int ipl_disable()
+# else
int ipldetach()
+# endif
{
int s, i = FR_INQUE|FR_OUTQUE;
#if defined(NETBSD_PF) && \
((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011))
int error = 0;
+# if __NetBSD_Version__ >= 105150000
+ struct pfil_head *ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
+# ifdef USE_INET6
+ struct pfil_head *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
+# endif
+# endif
#endif
#ifdef _KERNEL
@@ -403,8 +533,16 @@ int ipldetach()
# ifdef NETBSD_PF
# if ((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011))
+# if __NetBSD_Version__ >= 105110000
+ if (ph_inet != NULL)
+ error = pfil_remove_hook((void *)fr_check_wrapper, NULL,
+ PFIL_IN|PFIL_OUT, ph_inet);
+ else
+ error = 0;
+# else
error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+# endif
if (error) {
SPL_X(s);
return error;
@@ -413,8 +551,16 @@ int ipldetach()
pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
# endif
# ifdef USE_INET6
+# if __NetBSD_Version__ >= 105110000
+ if (ph_inet6 != NULL)
+ error = pfil_remove_hook((void *)fr_check_wrapper6, NULL,
+ PFIL_IN|PFIL_OUT, ph_inet6);
+ else
+ error = 0;
+# else
error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
- &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
+ &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
+# endif
if (error) {
SPL_X(s);
return error;
@@ -536,7 +682,7 @@ int mode;
sizeof(iplused[IPL_LOGIPF]));
#endif
break;
-#if !defined(IPFILTER_LKM) && defined(_KERNEL)
+#if (!defined(IPFILTER_LKM) || defined(__NetBSD__)) && defined(_KERNEL)
case SIOCFRENB :
{
u_int enable;
@@ -548,9 +694,17 @@ int mode;
if (error)
break;
if (enable)
+# if defined(__NetBSD__)
+ error = ipl_enable();
+# else
error = iplattach();
+# endif
else
+# if defined(__NetBSD__)
+ error = ipl_disable();
+# else
error = ipldetach();
+# endif
}
break;
}
@@ -717,11 +871,11 @@ caddr_t data;
{
register frentry_t *fp, *f, **fprev;
register frentry_t **ftail;
- frentry_t frd;
- frdest_t *fdp;
frgroup_t *fg = NULL;
+ int error = 0, in, i;
u_int *p, *pp;
- int error = 0, in;
+ frentry_t frd;
+ frdest_t *fdp;
u_int group;
fp = &frd;
@@ -770,18 +924,17 @@ caddr_t data;
bzero((char *)frcache, sizeof(frcache[0]) * 2);
- if (*fp->fr_ifname) {
- fp->fr_ifa = GETUNIT(fp->fr_ifname, fp->fr_v);
- if (!fp->fr_ifa)
- fp->fr_ifa = (void *)-1;
- }
-#if BSD >= 199306
- if (*fp->fr_oifname) {
- fp->fr_oifa = GETUNIT(fp->fr_oifname, fp->fr_v);
- if (!fp->fr_oifa)
- fp->fr_oifa = (void *)-1;
+ for (i = 0; i < 4; i++) {
+ if ((fp->fr_ifnames[i][1] == '\0') &&
+ ((fp->fr_ifnames[i][0] == '-') ||
+ (fp->fr_ifnames[i][0] == '*'))) {
+ fp->fr_ifas[i] = NULL;
+ } else if (*fp->fr_ifnames[i]) {
+ fp->fr_ifas[i] = GETUNIT(fp->fr_ifnames[i], fp->fr_v);
+ if (!fp->fr_ifas[i])
+ fp->fr_ifas[i] = (void *)-1;
+ }
}
-#endif
fdp = &fp->fr_dif;
fp->fr_flags &= ~FR_DUP;
@@ -860,6 +1013,7 @@ caddr_t data;
fixskip(fprev, f, -1);
*ftail = f->fr_next;
f->fr_next = NULL;
+ f->fr_ref--;
if (f->fr_ref == 0)
KFREE(f);
}
@@ -1008,7 +1162,7 @@ fr_info_t *fin;
if (m == NULL)
return -1;
- tlen = oip->ip_len - fin->fin_hlen - (tcp->th_off << 2) +
+ tlen = fin->fin_dlen - (tcp->th_off << 2) +
((tcp->th_flags & TH_SYN) ? 1 : 0) +
((tcp->th_flags & TH_FIN) ? 1 : 0);
@@ -1050,7 +1204,7 @@ fr_info_t *fin;
ip6->ip6_dst = oip6->ip6_src;
tcp2->th_sum = in6_cksum(m, IPPROTO_TCP,
sizeof(*ip6), sizeof(*tcp2));
- return send_ip(oip, fin, m);
+ return send_ip(oip, fin, &m);
}
# endif
ip->ip_p = IPPROTO_TCP;
@@ -1059,17 +1213,25 @@ fr_info_t *fin;
ip->ip_dst.s_addr = oip->ip_src.s_addr;
tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2));
ip->ip_len = hlen + sizeof(*tcp2);
- return send_ip(oip, fin, m);
+ return send_ip(oip, fin, &m);
}
-static int send_ip(oip, fin, m)
+/*
+ * Send an IP(v4/v6) datagram out into the network
+ */
+static int send_ip(oip, fin, mp)
ip_t *oip;
fr_info_t *fin;
-struct mbuf *m;
+struct mbuf **mp;
{
+ struct mbuf *m = *mp;
+ char *dpsave;
+ int error;
ip_t *ip;
+ dpsave = fin->fin_dp;
+
ip = mtod(m, ip_t *);
ip->ip_v = fin->fin_v;
@@ -1085,20 +1247,22 @@ struct mbuf *m;
ip->ip_ttl = ip_defttl;
# endif
ip->ip_sum = 0;
+ fin->fin_dp = (char *)(ip + 1);
}
# ifdef USE_INET6
else if (ip->ip_v == 6) {
ip6_t *ip6 = (ip6_t *)ip;
ip6->ip6_hlim = 127;
-
- return ip6_output(m, NULL, NULL, 0, NULL, NULL);
+ fin->fin_dp = (char *)(ip6 + 1);
}
# endif
# ifdef IPSEC
m->m_pkthdr.rcvif = NULL;
# endif
- return ipfr_fastroute(m, fin->fin_mp, fin, NULL);
+ error = ipfr_fastroute(m, mp, fin, NULL);
+ fin->fin_dp = dpsave;
+ return error;
}
@@ -1272,7 +1436,7 @@ int dst;
shlen = fin->fin_hlen;
fin->fin_hlen = hlen;
- err = send_ip(oip, fin, m);
+ err = send_ip(oip, fin, &m);
fin->fin_hlen = shlen;
#ifdef USE_INET6
if (fin->fin_v == 4)
@@ -1285,7 +1449,8 @@ int dst;
}
-# if !defined(IPFILTER_LKM) && (__FreeBSD_version < 300000) && !defined(__sgi)
+# if !defined(IPFILTER_LKM) && !defined(__sgi) && \
+ (!defined(__FreeBSD_version) || (__FreeBSD_version < 300000))
# if (BSD < 199306)
int iplinit __P((void));
@@ -1297,21 +1462,35 @@ void
# endif
iplinit()
{
+
+# if defined(__NetBSD__)
+ if (ipl_enable() != 0)
+# else
if (iplattach() != 0)
+# endif
+ {
printf("IP Filter failed to attach\n");
+ }
ip_init();
}
# endif /* ! __NetBSD__ */
+/*
+ * Return the length of the entire mbuf.
+ */
size_t mbufchainlen(m0)
register struct mbuf *m0;
{
+#if BSD >= 199306
+ return m0->m_pkthdr.len;
+#else
register size_t len = 0;
for (; m0; m0 = m0->m_next)
len += m0->m_len;
return len;
+#endif
}
@@ -1329,6 +1508,24 @@ frdest_t *fdp;
struct route iproute;
frentry_t *fr;
+ ip = NULL;
+ ro = NULL;
+ ifp = NULL;
+ ro = &iproute;
+ ro->ro_rt = NULL;
+
+#ifdef USE_INET6
+ if (fin->fin_v == 6) {
+ error = ipfr_fastroute6(m0, mpp, fin, fdp);
+ if (error != 0)
+ goto bad;
+ goto done;
+ }
+#else
+ if (fin->fin_v == 6)
+ goto bad;
+#endif
+
#ifdef M_WRITABLE
/*
* HOT FIX/KLUDGE:
@@ -1342,13 +1539,14 @@ frdest_t *fdp;
* problem.
*/
if (M_WRITABLE(m) == 0) {
- if ((m0 = m_dup(m, M_DONTWAIT)) != 0) {
- m_freem(m);
+ if ((m0 = m_dup(m, M_DONTWAIT)) != NULL) {
+ m_freem(*mpp);
+ *mpp = m0;
m = m0;
} else {
error = ENOBUFS;
- m_freem(m);
- ipl_frouteok[1]++;
+ m_freem(*mpp);
+ goto done;
}
}
#endif
@@ -1360,35 +1558,26 @@ frdest_t *fdp;
/*
* Clear any in-bound checksum flags for this packet.
*/
+# if (__NetBSD_Version__ > 105009999)
+ m0->m_pkthdr.csum_flags = 0;
+# else
m0->m_pkthdr.csuminfo = 0;
+# endif
#endif /* __NetBSD__ && M_CSUM_IPv4 */
-#ifdef USE_INET6
- if (ip->ip_v == 6) {
- /*
- * currently "to <if>" and "to <if>:ip#" are not supported
- * for IPv6
- */
- error = ip6_output(m0, NULL, NULL, 0, NULL, NULL);
- *mpp = NULL;
- return error;
- }
-#endif
/*
* Route packet.
*/
- ro = &iproute;
bzero((caddr_t)ro, sizeof (*ro));
dst = (struct sockaddr_in *)&ro->ro_dst;
dst->sin_family = AF_INET;
+ dst->sin_addr = ip->ip_dst;
fr = fin->fin_fr;
- if (fdp)
+ if (fdp != NULL)
ifp = fdp->fd_ifp;
- else {
+ else
ifp = fin->fin_ifp;
- dst->sin_addr = ip->ip_dst;
- }
/*
* In case we're here due to "to <if>" being used with "keep state",
@@ -1397,13 +1586,9 @@ frdest_t *fdp;
if ((fr != NULL) && (fin->fin_rev != 0)) {
if ((ifp != NULL) && (fdp == &fr->fr_tif))
return 0;
- dst->sin_addr = ip->ip_dst;
- } else if (fdp) {
- if (fdp->fd_ip.s_addr) {
+ } else if (fdp != NULL) {
+ if (fdp->fd_ip.s_addr != 0)
dst->sin_addr = fdp->fd_ip;
- ip->ip_dst = fdp->fd_ip;
- } else
- dst->sin_addr = ip->ip_dst;
}
# if BSD >= 199306
@@ -1424,26 +1609,36 @@ frdest_t *fdp;
error = -2;
goto bad;
}
- if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
- if (in_localaddr(ip->ip_dst))
- error = EHOSTUNREACH;
- else
- error = ENETUNREACH;
- goto bad;
- }
- if (ro->ro_rt->rt_flags & RTF_GATEWAY)
- dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
}
- if (ro->ro_rt)
- ro->ro_rt->rt_use++;
+
+ if ((ifp == NULL) && (ro->ro_rt != NULL))
+ ifp = ro->ro_rt->rt_ifp;
+
+ if ((ro->ro_rt == NULL) || (ifp == NULL)) {
+ if (in_localaddr(ip->ip_dst))
+ error = EHOSTUNREACH;
+ else
+ error = ENETUNREACH;
+ goto bad;
+ }
+
+ if (ro->ro_rt->rt_flags & RTF_GATEWAY) {
+#if BSD >= 199306
+ dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
+#else
+ dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
+#endif
+ }
+ ro->ro_rt->rt_use++;
/*
* For input packets which are being "fastrouted", they won't
* go back through output filtering and miss their chance to get
* NAT'd and counted.
*/
- fin->fin_ifp = ifp;
if (fin->fin_out == 0) {
+ sifp = fin->fin_ifp;
+ fin->fin_ifp = ifp;
fin->fin_out = 1;
if ((fin->fin_fr = ipacct[1][fr_active]) &&
(fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
@@ -1453,46 +1648,39 @@ frdest_t *fdp;
if (!fr || !(fr->fr_flags & FR_RETMASK))
(void) fr_checkstate(ip, fin);
(void) ip_natout(ip, fin);
+ fin->fin_ifp = sifp;
} else
ip->ip_sum = 0;
/*
* If small enough for interface, can just send directly.
*/
if (ip->ip_len <= ifp->if_mtu) {
-# if defined(MCLISREFERENCED) && !defined(sparc)
- int i = 0;
-
- if ((m->m_flags & M_EXT) && MCLISREFERENCED(m))
- i = 1;
-# endif
# ifndef sparc
-# if !(_BSDI_VERSION >= 199510)
+# if (!defined(__FreeBSD__) && !(_BSDI_VERSION >= 199510))
ip->ip_id = htons(ip->ip_id);
# endif
ip->ip_len = htons(ip->ip_len);
ip->ip_off = htons(ip->ip_off);
# endif
# if defined(__NetBSD__) && defined(M_CSUM_IPv4)
+# if (__NetBSD_Version__ > 105009999)
+ if (ifp->if_csum_flags_tx & IFCAP_CSUM_IPv4)
+ m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
+ else if (ip->ip_sum == 0)
+ ip->ip_sum = in_cksum(m, hlen);
+# else
if (ifp->if_capabilities & IFCAP_CSUM_IPv4)
m->m_pkthdr.csuminfo |= M_CSUM_IPv4;
else if (ip->ip_sum == 0)
ip->ip_sum = in_cksum(m, hlen);
+# endif
# else
if (!ip->ip_sum)
ip->ip_sum = in_cksum(m, hlen);
# endif /* __NetBSD__ && M_CSUM_IPv4 */
-# if BSD >= 199306
+# if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605))
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
ro->ro_rt);
-# if defined(MCLISREFERENCED) && !defined(sparc)
- if (i) {
-# ifndef __FreeBSD__
- ip->ip_id = ntohs(ip->ip_id);
-# endif
- ip->ip_len = ntohs(ip->ip_len);
- ip->ip_off = ntohs(ip->ip_off);
- }
-# endif
# else
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst);
# endif
@@ -1562,9 +1750,7 @@ frdest_t *fdp;
m->m_pkthdr.len = mhlen + len;
m->m_pkthdr.rcvif = NULL;
# endif
-# ifndef sparc
mhip->ip_off = htons((u_short)mhip->ip_off);
-# endif
mhip->ip_sum = 0;
mhip->ip_sum = in_cksum(m, mhlen);
*mnext = m;
@@ -1584,7 +1770,7 @@ sendorfree:
m0 = m->m_act;
m->m_act = 0;
if (error == 0)
-# if BSD >= 199306
+# if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605))
error = (*ifp->if_output)(ifp, m,
(struct sockaddr *)dst, ro->ro_rt);
# else
@@ -1601,13 +1787,13 @@ done:
else
ipl_frouteok[1]++;
- if (ro->ro_rt) {
+ if (ro->ro_rt != NULL) {
RTFREE(ro->ro_rt);
}
*mpp = NULL;
return error;
bad:
- if (error == EMSGSIZE) {
+ if ((error == EMSGSIZE) && (fin->fin_v == 4)) {
sifp = fin->fin_ifp;
code = fin->fin_icode;
fin->fin_icode = ICMP_UNREACH_NEEDFRAG;
@@ -1621,6 +1807,10 @@ bad:
}
+/*
+ * Return true or false depending on whether the route to the
+ * given IP address uses the same interface as the one passed.
+ */
int fr_verifysrc(ipa, ifp)
struct in_addr ipa;
void *ifp;
@@ -1630,6 +1820,9 @@ void *ifp;
bzero((char *)&iproute, sizeof(iproute));
dst = (struct sockaddr_in *)&iproute.ro_dst;
+# if (BSD >= 199306)
+ dst->sin_len = sizeof(*dst);
+# endif
dst->sin_family = AF_INET;
dst->sin_addr = ipa;
# if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \
@@ -1659,10 +1852,78 @@ struct ifnet *ifp;
return workbuf;
}
# endif
+
+
+# if defined(USE_INET6)
+/*
+ * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's
+ * or ensure that it is an IPv6 packet that is being forwarded, those are
+ * expected to be done by the called (ipfr_fastroute).
+ */
+static int ipfr_fastroute6(m0, mpp, fin, fdp)
+struct mbuf *m0, **mpp;
+fr_info_t *fin;
+frdest_t *fdp;
+{
+ struct route_in6 ip6route;
+ struct sockaddr_in6 *dst6;
+ struct route_in6 *ro;
+ struct ifnet *ifp;
+ frentry_t *fr;
+ int error;
+
+ ifp = NULL;
+ ro = &ip6route;
+ fr = fin->fin_fr;
+ bzero((caddr_t)ro, sizeof(*ro));
+ dst6 = (struct sockaddr_in6 *)&ro->ro_dst;
+ dst6->sin6_family = AF_INET6;
+ dst6->sin6_len = sizeof(struct sockaddr_in6);
+ dst6->sin6_addr = fin->fin_fi.fi_src.in6;
+
+ if (fdp != NULL)
+ ifp = fdp->fd_ifp;
+
+ if ((fr != NULL) && (fin->fin_rev != 0)) {
+ if ((ifp != NULL) && (fdp == &fr->fr_tif))
+ return 0;
+ } else if (fdp != NULL) {
+ if (IP6_NOTZERO(&fdp->fd_ip6))
+ dst6->sin6_addr = fdp->fd_ip6.in6;
+ }
+ if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE)))
+ return -2;
+
+ rtalloc((struct route *)ro);
+
+ if ((ifp == NULL) && (ro->ro_rt != NULL))
+ ifp = ro->ro_rt->rt_ifp;
+
+ if ((ro->ro_rt == NULL) || (ifp == NULL) ||
+ (ifp != ro->ro_rt->rt_ifp)) {
+ error = EHOSTUNREACH;
+ } else {
+ if (ro->ro_rt->rt_flags & RTF_GATEWAY)
+ dst6 = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway;
+ ro->ro_rt->rt_use++;
+
+ if (m0->m_pkthdr.len <= nd_ifinfo[ifp->if_index].linkmtu)
+ error = nd6_output(ifp, fin->fin_ifp, m0, dst6,
+ ro->ro_rt);
+ else
+ error = EMSGSIZE;
+ }
+
+ if (ro->ro_rt != NULL) {
+ RTFREE(ro->ro_rt);
+ }
+ return error;
+}
+# endif
#else /* #ifdef _KERNEL */
-# ifdef __sgi
+# if defined(__sgi) && (IRIX < 605)
static int no_output __P((struct ifnet *ifp, struct mbuf *m,
struct sockaddr *s))
# else
@@ -1675,7 +1936,7 @@ static int no_output __P((struct ifnet *ifp, struct mbuf *m,
# ifdef __STDC__
-# ifdef __sgi
+# if defined(__sgi) && (IRIX < 605)
static int write_output __P((struct ifnet *ifp, struct mbuf *m,
struct sockaddr *s))
# else
@@ -1710,26 +1971,39 @@ ip_t *ip;
}
-struct ifnet *get_unit(name, v)
-char *name;
+char *get_ifname(ifp)
+struct ifnet *ifp;
+{
+# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
+ (defined(OpenBSD) && (OpenBSD >= 199603))
+ return ifp->if_xname;
+# else
+ static char fullifname[LIFNAMSIZ];
+
+ sprintf(fullifname, "%s%d", ifp->if_name, ifp->if_unit);
+ return fullifname;
+# endif
+}
+
+
+struct ifnet *get_unit(ifname, v)
+char *ifname;
int v;
{
struct ifnet *ifp, **ifa, **old_ifneta;
-# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
- (defined(OpenBSD) && (OpenBSD >= 199603))
+
for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
- if (!strcmp(name, ifp->if_xname))
- return ifp;
- }
+# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
+ (defined(OpenBSD) && (OpenBSD >= 199603))
+ if (!strncmp(ifname, ifp->if_xname, sizeof(ifp->if_xname)))
# else
- char ifname[32], *s;
+ char fullname[LIFNAMSIZ];
- for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
- (void) sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
- if (!strcmp(name, ifname))
+ sprintf(fullname, "%s%d", ifp->if_name, ifp->if_unit);
+ if (!strcmp(ifname, fullname))
+# endif
return ifp;
}
-# endif
if (!ifneta) {
ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
@@ -1762,20 +2036,19 @@ int v;
ifp = ifneta[nifs - 1];
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
- (defined(OpenBSD) && (OpenBSD >= 199603))
- strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
+ (defined(OpenBSD) && (OpenBSD >= 199603))
+ strncpy(ifp->if_xname, ifname, sizeof(ifp->if_xname));
# else
- for (s = name; *s && !isdigit(*s); s++)
- ;
- if (*s && isdigit(*s)) {
- ifp->if_unit = atoi(s);
- ifp->if_name = (char *)malloc(s - name + 1);
- strncpy(ifp->if_name, name, s - name);
- ifp->if_name[s - name] = '\0';
- } else {
- ifp->if_name = strdup(name);
+ ifp->if_name = strdup(ifname);
+
+ ifname = ifp->if_name;
+ while (*ifname && !isdigit(*ifname))
+ ifname++;
+ if (*ifname && isdigit(*ifname)) {
+ ifp->if_unit = atoi(ifname);
+ *ifname = '\0';
+ } else
ifp->if_unit = -1;
- }
# endif
ifp->if_output = no_output;
return ifp;
@@ -1815,27 +2088,22 @@ void init_ifp()
}
-int ipllog __P((void))
-{
- verbose("l");
- return 0;
-}
-
-
-int send_reset(ip, ifp)
+int send_reset(ip, fin)
ip_t *ip;
-struct ifnet *ifp;
+fr_info_t *fin;
{
verbose("- TCP RST sent\n");
return 0;
}
-int icmp_error(ip, ifp)
+int send_icmp_err(ip, code, fin, dst)
ip_t *ip;
-struct ifnet *ifp;
+int code;
+fr_info_t *fin;
+int dst;
{
- verbose("- TCP RST sent\n");
+ verbose("- ICMP UNREACHABLE RST sent\n");
return 0;
}
@@ -1844,4 +2112,52 @@ void frsync()
{
return;
}
+
+void m_copydata(m, off, len, cp)
+mb_t *m;
+int off, len;
+caddr_t cp;
+{
+ bcopy((char *)m + off, cp, len);
+}
+
+
+int ipfuiomove(buf, len, rwflag, uio)
+caddr_t buf;
+int len, rwflag;
+struct uio *uio;
+{
+ int left, ioc, num, offset;
+ struct iovec *io;
+ char *start;
+
+ if (rwflag == UIO_READ) {
+ left = len;
+ ioc = 0;
+
+ offset = uio->uio_offset;
+
+ while ((left > 0) && (ioc < uio->uio_iovcnt)) {
+ io = uio->uio_iov + ioc;
+ num = io->iov_len;
+ if (num > left)
+ num = left;
+ start = io->iov_base + offset;
+ if (start > io->iov_base + io->iov_len) {
+ offset -= io->iov_len;
+ ioc++;
+ continue;
+ }
+ bcopy(buf, start, num);
+ uio->uio_resid -= num;
+ uio->uio_offset += num;
+ left -= num;
+ if (left > 0)
+ ioc++;
+ }
+ if (left > 0)
+ return EFAULT;
+ }
+ return 0;
+}
#endif /* _KERNEL */
OpenPOWER on IntegriCloud