Annotation of sys/net/if_faith.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: if_faith.c,v 1.22 2006/03/25 22:41:47 djm Exp $ */
! 2: /*
! 3: * Copyright (c) 1982, 1986, 1993
! 4: * The Regents of the University of California. All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: * 3. Neither the name of the University nor the names of its contributors
! 15: * may be used to endorse or promote products derived from this software
! 16: * without specific prior written permission.
! 17: *
! 18: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 19: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 20: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 21: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 22: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 23: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 24: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 25: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 26: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 27: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 28: * SUCH DAMAGE.
! 29: */
! 30: /*
! 31: * derived from
! 32: * @(#)if_loop.c 8.1 (Berkeley) 6/10/93
! 33: * Id: if_loop.c,v 1.22 1996/06/19 16:24:10 wollman Exp
! 34: */
! 35:
! 36: /*
! 37: * Loopback interface driver for protocol testing and timing.
! 38: */
! 39: #include "faith.h"
! 40:
! 41: #if NFAITH > 0
! 42:
! 43: #include <sys/param.h>
! 44: #include <sys/systm.h>
! 45: #include <sys/mbuf.h>
! 46: #include <sys/socket.h>
! 47: #include <sys/ioctl.h>
! 48:
! 49: #include <net/if.h>
! 50: #include <net/if_types.h>
! 51: #include <net/netisr.h>
! 52: #include <net/route.h>
! 53: #include <net/bpf.h>
! 54:
! 55: #ifdef INET
! 56: #include <netinet/in.h>
! 57: #include <netinet/in_var.h>
! 58: #endif
! 59:
! 60: #ifdef INET6
! 61: #ifndef INET
! 62: #include <netinet/in.h>
! 63: #endif
! 64: #include <netinet6/in6_var.h>
! 65: #endif
! 66:
! 67: #include "bpfilter.h"
! 68:
! 69: static int faithioctl(struct ifnet *, u_long, caddr_t);
! 70: int faithoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
! 71: struct rtentry *);
! 72: static void faithrtrequest(int, struct rtentry *, struct rt_addrinfo *);
! 73:
! 74: void faithattach(int);
! 75: int faith_clone_create(struct if_clone *, int);
! 76: int faith_clone_destroy(struct ifnet *ifp);
! 77:
! 78: struct if_clone faith_cloner =
! 79: IF_CLONE_INITIALIZER("faith", faith_clone_create, faith_clone_destroy);
! 80:
! 81: #define FAITHMTU 1500
! 82:
! 83: /* ARGSUSED */
! 84: void
! 85: faithattach(faith)
! 86: int faith;
! 87: {
! 88: if_clone_attach(&faith_cloner);
! 89: }
! 90:
! 91: int
! 92: faith_clone_create(ifc, unit)
! 93: struct if_clone *ifc;
! 94: int unit;
! 95: {
! 96: struct ifnet *ifp;
! 97:
! 98: ifp = malloc(sizeof(*ifp), M_DEVBUF, M_NOWAIT);
! 99: if (!ifp)
! 100: return (ENOMEM);
! 101: bzero(ifp, sizeof(*ifp));
! 102: snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
! 103: unit);
! 104: ifp->if_mtu = FAITHMTU;
! 105: /* Change to BROADCAST experimentaly to announce its prefix. */
! 106: ifp->if_flags = /* IFF_LOOPBACK */ IFF_BROADCAST | IFF_MULTICAST;
! 107: ifp->if_ioctl = faithioctl;
! 108: ifp->if_output = faithoutput;
! 109: ifp->if_type = IFT_FAITH;
! 110: ifp->if_hdrlen = 0;
! 111: ifp->if_addrlen = 0;
! 112: if_attach(ifp);
! 113: if_alloc_sadl(ifp);
! 114: #if NBPFILTER > 0
! 115: bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
! 116: #endif
! 117: return (0);
! 118: }
! 119:
! 120: int
! 121: faith_clone_destroy(ifp)
! 122: struct ifnet *ifp;
! 123: {
! 124: if_detach(ifp);
! 125:
! 126: free(ifp, M_DEVBUF);
! 127: return (0);
! 128: }
! 129:
! 130: int
! 131: faithoutput(ifp, m, dst, rt)
! 132: struct ifnet *ifp;
! 133: struct mbuf *m;
! 134: struct sockaddr *dst;
! 135: struct rtentry *rt;
! 136: {
! 137: int s, isr;
! 138: struct ifqueue *ifq = 0;
! 139:
! 140: if ((m->m_flags & M_PKTHDR) == 0)
! 141: panic("faithoutput no HDR");
! 142: #if NBPFILTER > 0
! 143: /* BPF write needs to be handled specially */
! 144: if (dst->sa_family == AF_UNSPEC) {
! 145: dst->sa_family = *(mtod(m, int *));
! 146: m->m_len -= sizeof(int);
! 147: m->m_pkthdr.len -= sizeof(int);
! 148: m->m_data += sizeof(int);
! 149: }
! 150:
! 151: if (ifp->if_bpf)
! 152: bpf_mtap_af(ifp->if_bpf, dst->sa_family, m, BPF_DIRECTION_OUT);
! 153: #endif
! 154:
! 155: if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
! 156: m_freem(m);
! 157: return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
! 158: rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
! 159: }
! 160: ifp->if_opackets++;
! 161: ifp->if_obytes += m->m_pkthdr.len;
! 162: switch (dst->sa_family) {
! 163: #ifdef INET
! 164: case AF_INET:
! 165: ifq = &ipintrq;
! 166: isr = NETISR_IP;
! 167: break;
! 168: #endif
! 169: #ifdef INET6
! 170: case AF_INET6:
! 171: ifq = &ip6intrq;
! 172: isr = NETISR_IPV6;
! 173: break;
! 174: #endif
! 175: default:
! 176: m_freem(m);
! 177: return EAFNOSUPPORT;
! 178: }
! 179:
! 180: /* XXX do we need more sanity checks? */
! 181:
! 182: m->m_pkthdr.rcvif = ifp;
! 183: s = splnet();
! 184: if (IF_QFULL(ifq)) {
! 185: IF_DROP(ifq);
! 186: m_freem(m);
! 187: splx(s);
! 188: return (ENOBUFS);
! 189: }
! 190: IF_ENQUEUE(ifq, m);
! 191: schednetisr(isr);
! 192: ifp->if_ipackets++;
! 193: ifp->if_ibytes += m->m_pkthdr.len;
! 194: splx(s);
! 195: return (0);
! 196: }
! 197:
! 198: /* ARGSUSED */
! 199: static void
! 200: faithrtrequest(cmd, rt, info)
! 201: int cmd;
! 202: struct rtentry *rt;
! 203: struct rt_addrinfo *info;
! 204: {
! 205: if (rt)
! 206: rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */
! 207: }
! 208:
! 209: /*
! 210: * Process an ioctl request.
! 211: */
! 212: /* ARGSUSED */
! 213: static int
! 214: faithioctl(ifp, cmd, data)
! 215: struct ifnet *ifp;
! 216: u_long cmd;
! 217: caddr_t data;
! 218: {
! 219: struct ifaddr *ifa;
! 220: struct ifreq *ifr = (struct ifreq *)data;
! 221: int error = 0;
! 222:
! 223: switch (cmd) {
! 224:
! 225: case SIOCSIFADDR:
! 226: ifp->if_flags |= IFF_UP | IFF_RUNNING;
! 227: ifa = (struct ifaddr *)data;
! 228: ifa->ifa_rtrequest = faithrtrequest;
! 229: /*
! 230: * Everything else is done at a higher level.
! 231: */
! 232: break;
! 233:
! 234: case SIOCADDMULTI:
! 235: case SIOCDELMULTI:
! 236: if (ifr == 0) {
! 237: error = EAFNOSUPPORT; /* XXX */
! 238: break;
! 239: }
! 240: switch (ifr->ifr_addr.sa_family) {
! 241: #ifdef INET
! 242: case AF_INET:
! 243: break;
! 244: #endif
! 245: #ifdef INET6
! 246: case AF_INET6:
! 247: break;
! 248: #endif
! 249:
! 250: default:
! 251: error = EAFNOSUPPORT;
! 252: break;
! 253: }
! 254: break;
! 255:
! 256: case SIOCSIFFLAGS:
! 257: break;
! 258:
! 259: default:
! 260: error = EINVAL;
! 261: }
! 262: return (error);
! 263: }
! 264: #endif /* NFAITH > 0 */
CVSweb