+/* if_loop.c 6.1 83/07/29 */
+
+/*
+ * Loopback interface driver for protocol testing and timing.
+ */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/mbuf.h"
+#include "../h/socket.h"
+#include "../h/errno.h"
+#include "../h/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
+
+#define LONET 127
+#define LOHOST 1 /* can't be 0, that's broadcast */
+#define LOMTU (1024+512)
+
+struct ifnet loif;
+int looutput(), loioctl();
+
+loattach()
+{
+ register struct ifnet *ifp = &loif;
+ register struct sockaddr_in *sin;
+
+ ifp->if_name = "lo";
+ ifp->if_mtu = LOMTU;
+ ifp->if_net = LONET;
+ ifp->if_host[0] = LOHOST;
+ sin = (struct sockaddr_in *)&ifp->if_addr;
+ sin->sin_family = AF_INET;
+ sin->sin_addr = if_makeaddr(LONET, LOHOST);
+ ifp->if_flags = IFF_UP | IFF_RUNNING;
+ ifp->if_ioctl = loioctl;
+ ifp->if_output = looutput;
+ if_attach(ifp);
+ if_rtinit(ifp, RTF_UP);
+}
+
+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
+ 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.
+ */
+loioctl(ifp, cmd, data)
+ register struct ifnet *ifp;
+ int cmd;
+ caddr_t data;
+{
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct sockaddr_in *sin;
+ int s = splimp(), error = 0;
+
+ switch (cmd) {
+
+ case SIOCSIFADDR:
+ if (ifp->if_flags & IFF_RUNNING)
+ if_rtinit(ifp, -1); /* delete previous route */
+ ifp->if_addr = ifr->ifr_addr;
+ sin = (struct sockaddr_in *)&ifp->if_addr;
+ ifp->if_net = in_netof(sin->sin_addr);
+ ifp->if_host[0] = in_lnaof(sin->sin_addr);
+ if_rtinit(ifp, RTF_UP);
+ break;
+
+ default:
+ error = EINVAL;
+ }
+ splx(s);
+ return (error);
+}