diff options
Diffstat (limited to 'sys/contrib/ipfilter/netinet/ip_fil.c')
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_fil.c | 582 |
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 */ |