/********************************************************************** * Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. * * All Rights Reserved. * * Reference "/usr/src/COPYRIGHT" for applicable restrictions. * **********************************************************************/ /* * Copyright (c) 1982 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * SCCSID: @(#)if_loop.c 3.0 4/21/86 * Based on: @(#)if_loop.c 6.6 (Berkeley) 6/8/85 */ /* * Loopback interface driver for protocol testing and timing. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <errno.h> #include <sys/ioctl.h> #include <net/if.h> #include <net/netisr.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #ifdef vax #include "../vax/mtpr.h" #endif #ifdef NS #include "../netns/ns.h" #include "../netns/ns_if.h" #endif #define LOMTU (1024+512) struct ifnet loif; int looutput(), loioctl(); static char LOname[] = { 'l', 'o', '\0' }; loattach() { register struct ifnet *ifp = &loif; register struct sockaddr_in *sin; ifp->if_name = "lo"; ifp->if_mtu = LOMTU; ifp->if_ioctl = loioctl; ifp->if_output = looutput; if_attach(ifp); } looutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; { int s = splimp(); register struct ifqueue *ifq; ifp->if_opackets++; switch (dst->sa_family) { #ifdef INET case AF_INET: ifq = &ipintrq; if (IF_QFULL(ifq)) { IF_DROP(ifq); m_freem(m0); splx(s); return (ENOBUFS); } IF_ENQUEUE(ifq, m0); schednetisr(NETISR_IP); break; #endif #ifdef NS case AF_NS: ifq = &nsintrq; if (IF_QFULL(ifq)) { IF_DROP(ifq); m_freem(m0); splx(s); return (ENOBUFS); } IF_ENQUEUE(ifq, m0); schednetisr(NETISR_NS); break; #endif default: splx(s); printf("lo%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); m_freem(m0); return (EAFNOSUPPORT); } ifp->if_ipackets++; splx(s); return (0); } /* * Process an ioctl request. */ /* ARGSUSED */ loioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { int error = 0; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; /* * Everything else is done at a higher level. */ break; default: error = EINVAL; } return (error); }