1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)if_loop.c 7.10 (Berkeley) 06/28/90 8 */ 9 10 /* 11 * Loopback interface driver for protocol testing and timing. 12 */ 13 14 #include "param.h" 15 #include "systm.h" 16 #include "mbuf.h" 17 #include "socket.h" 18 #include "errno.h" 19 #include "ioctl.h" 20 21 #include "../net/if.h" 22 #include "../net/if_types.h" 23 #include "../net/netisr.h" 24 #include "../net/route.h" 25 26 #include "machine/mtpr.h" 27 28 #ifdef INET 29 #include "../netinet/in.h" 30 #include "../netinet/in_systm.h" 31 #include "../netinet/in_var.h" 32 #include "../netinet/ip.h" 33 #endif 34 35 #ifdef NS 36 #include "../netns/ns.h" 37 #include "../netns/ns_if.h" 38 #endif 39 40 #ifdef ISO 41 #include "../netiso/iso.h" 42 #include "../netiso/iso_var.h" 43 #endif 44 45 #define LOMTU (1024+512) 46 47 struct ifnet loif; 48 int looutput(), loioctl(); 49 50 loattach() 51 { 52 register struct ifnet *ifp = &loif; 53 54 ifp->if_name = "lo"; 55 ifp->if_mtu = LOMTU; 56 ifp->if_flags = IFF_LOOPBACK; 57 ifp->if_ioctl = loioctl; 58 ifp->if_output = looutput; 59 ifp->if_type = IFT_LOOP; 60 ifp->if_hdrlen = 0; 61 ifp->if_addrlen = 0; 62 if_attach(ifp); 63 } 64 65 struct mbuf *Loop_Sanity; 66 67 looutput(ifp, m, dst) 68 struct ifnet *ifp; 69 register struct mbuf *m; 70 struct sockaddr *dst; 71 { 72 int s; 73 register struct ifqueue *ifq; 74 75 if ((m->m_flags & M_PKTHDR) == 0) 76 panic("looutput no HDR"); 77 m->m_pkthdr.rcvif = ifp; 78 79 {struct mbuf *mm; int mlen = 0; 80 for (mm = m; m; m = m->m_next) /* XXX debugging code -- sklower */ 81 mlen += m->m_len; 82 m = mm; 83 if (mlen != m->m_pkthdr.len) { 84 if (Loop_Sanity) 85 m_freem(Loop_Sanity); 86 Loop_Sanity = m_copy(m, 0, (int)M_COPYALL); 87 } 88 } 89 90 s = splimp(); 91 ifp->if_opackets++; 92 ifp->if_obytes += m->m_pkthdr.len; 93 switch (dst->sa_family) { 94 95 #ifdef INET 96 case AF_INET: 97 ifq = &ipintrq; 98 if (IF_QFULL(ifq)) { 99 IF_DROP(ifq); 100 m_freem(m); 101 splx(s); 102 return (ENOBUFS); 103 } 104 IF_ENQUEUE(ifq, m); 105 schednetisr(NETISR_IP); 106 break; 107 #endif 108 #ifdef NS 109 case AF_NS: 110 ifq = &nsintrq; 111 if (IF_QFULL(ifq)) { 112 IF_DROP(ifq); 113 m_freem(m); 114 splx(s); 115 return (ENOBUFS); 116 } 117 IF_ENQUEUE(ifq, m); 118 schednetisr(NETISR_NS); 119 break; 120 #endif 121 #ifdef ISO 122 case AF_ISO: 123 ifq = &clnlintrq; 124 if (IF_QFULL(ifq)) { 125 IF_DROP(ifq); 126 m_freem(m); 127 splx(s); 128 return (ENOBUFS); 129 } 130 IF_ENQUEUE(ifq, m); 131 schednetisr(NETISR_ISO); 132 break; 133 #endif 134 default: 135 splx(s); 136 printf("lo%d: can't handle af%d\n", ifp->if_unit, 137 dst->sa_family); 138 m_freem(m); 139 return (EAFNOSUPPORT); 140 } 141 ifp->if_ipackets++; 142 ifp->if_ibytes += m->m_pkthdr.len; 143 splx(s); 144 return (0); 145 } 146 147 /* 148 * Process an ioctl request. 149 */ 150 /* ARGSUSED */ 151 loioctl(ifp, cmd, data) 152 register struct ifnet *ifp; 153 int cmd; 154 caddr_t data; 155 { 156 int error = 0; 157 158 switch (cmd) { 159 160 case SIOCSIFADDR: 161 ifp->if_flags |= IFF_UP; 162 /* 163 * Everything else is done at a higher level. 164 */ 165 break; 166 167 default: 168 error = EINVAL; 169 } 170 return (error); 171 } 172