-/* if_loop.c 6.1 83/07/29 */
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)if_loop.c 7.9 (Berkeley) %G%
+ */
/*
* 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 "param.h"
+#include "systm.h"
+#include "mbuf.h"
+#include "socket.h"
+#include "errno.h"
+#include "ioctl.h"
#include "../net/if.h"
+#include "../net/if_types.h"
#include "../net/netisr.h"
#include "../net/route.h"
+#include "machine/mtpr.h"
+
+#ifdef INET
#include "../netinet/in.h"
#include "../netinet/in_systm.h"
+#include "../netinet/in_var.h"
#include "../netinet/ip.h"
-#include "../netinet/ip_var.h"
+#endif
-#ifdef vax
-#include "../vax/mtpr.h"
+#ifdef NS
+#include "../netns/ns.h"
+#include "../netns/ns_if.h"
+#endif
+
+#ifdef ISO
+#include "../netiso/iso.h"
+#include "../netiso/iso_var.h"
#endif
-#define LONET 127
-#define LOHOST 1 /* can't be 0, that's broadcast */
#define LOMTU (1024+512)
struct ifnet loif;
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_flags = IFF_LOOPBACK;
ifp->if_ioctl = loioctl;
ifp->if_output = looutput;
+ ifp->if_type = IFT_LOOP;
+ ifp->if_hdrlen = 0;
+ ifp->if_addrlen = 0;
if_attach(ifp);
- if_rtinit(ifp, RTF_UP);
}
-looutput(ifp, m0, dst)
+struct mbuf *Loop_Sanity;
+
+looutput(ifp, m, dst)
struct ifnet *ifp;
- struct mbuf *m0;
+ register struct mbuf *m;
struct sockaddr *dst;
{
- int s = splimp();
+ int s;
register struct ifqueue *ifq;
+ if ((m->m_flags & M_PKTHDR) == 0)
+ panic("looutput no HDR");
+ m->m_pkthdr.rcvif = ifp;
+
+{struct mbuf *mm; int mlen = 0;
+for (mm = m; m; m = m->m_next) /* XXX debugging code -- sklower */
+ mlen += m->m_len;
+m = mm;
+if (mlen != m->m_pkthdr.len) {
+ if (Loop_Sanity)
+ m_freem(Loop_Sanity);
+ Loop_Sanity = m_copy(m, 0, (int)M_COPYALL);
+}
+}
+
+ s = splimp();
ifp->if_opackets++;
+ ifp->if_obytes += m->m_pkthdr.len;
switch (dst->sa_family) {
#ifdef INET
ifq = &ipintrq;
if (IF_QFULL(ifq)) {
IF_DROP(ifq);
- m_freem(m0);
+ m_freem(m);
splx(s);
return (ENOBUFS);
}
- IF_ENQUEUE(ifq, m0);
+ IF_ENQUEUE(ifq, m);
schednetisr(NETISR_IP);
break;
+#endif
+#ifdef NS
+ case AF_NS:
+ ifq = &nsintrq;
+ if (IF_QFULL(ifq)) {
+ IF_DROP(ifq);
+ m_freem(m);
+ splx(s);
+ return (ENOBUFS);
+ }
+ IF_ENQUEUE(ifq, m);
+ schednetisr(NETISR_NS);
+ break;
+#endif
+#ifdef ISO
+ case AF_ISO:
+ ifq = &clnlintrq;
+ if (IF_QFULL(ifq)) {
+ IF_DROP(ifq);
+ m_freem(m);
+ splx(s);
+ return (ENOBUFS);
+ }
+ IF_ENQUEUE(ifq, m);
+ schednetisr(NETISR_ISO);
+ break;
#endif
default:
splx(s);
printf("lo%d: can't handle af%d\n", ifp->if_unit,
dst->sa_family);
- m_freem(m0);
+ m_freem(m);
return (EAFNOSUPPORT);
}
ifp->if_ipackets++;
+ ifp->if_ibytes += m->m_pkthdr.len;
splx(s);
return (0);
}
/*
* Process an ioctl request.
*/
+/* ARGSUSED */
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;
+ int 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);
+ ifp->if_flags |= IFF_UP;
+ /*
+ * Everything else is done at a higher level.
+ */
break;
default:
error = EINVAL;
}
- splx(s);
return (error);
}