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.12 (Berkeley) 11/06/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 #ifdef CCITT 46 #include "../netccitt/x25.h" 47 #include "../netccitt/hdlc.h" 48 #include "../netccitt/hd_var.h" 49 #endif 50 51 #define LOMTU (1024+512) 52 53 struct ifnet loif; 54 int looutput(), loioctl(); 55 56 loattach() 57 { 58 register struct ifnet *ifp = &loif; 59 60 ifp->if_name = "lo"; 61 ifp->if_mtu = LOMTU; 62 ifp->if_flags = IFF_LOOPBACK; 63 ifp->if_ioctl = loioctl; 64 ifp->if_output = looutput; 65 ifp->if_type = IFT_LOOP; 66 ifp->if_hdrlen = 0; 67 ifp->if_addrlen = 0; 68 if_attach(ifp); 69 } 70 71 looutput(ifp, m, dst, rt) 72 struct ifnet *ifp; 73 register struct mbuf *m; 74 struct sockaddr *dst; 75 register struct rtentry *rt; 76 { 77 int s, isr; 78 register struct ifqueue *ifq = 0; 79 80 if ((m->m_flags & M_PKTHDR) == 0) 81 panic("looutput no HDR"); 82 m->m_pkthdr.rcvif = ifp; 83 84 if (rt && rt->rt_flags & RTF_REJECT) { 85 m_freem(m); 86 return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 87 } 88 s = splimp(); 89 ifp->if_opackets++; 90 ifp->if_obytes += m->m_pkthdr.len; 91 switch (dst->sa_family) { 92 93 #ifdef INET 94 case AF_INET: 95 ifq = &ipintrq; 96 isr = NETISR_IP; 97 break; 98 #endif 99 #ifdef NS 100 case AF_NS: 101 ifq = &nsintrq; 102 isr = NETISR_NS; 103 break; 104 #endif 105 #ifdef ISO 106 case AF_ISO: 107 ifq = &clnlintrq; 108 isr = NETISR_ISO; 109 break; 110 #endif 111 #ifdef CCITT 112 case AF_CCITT: 113 ifq = &hdintrq; 114 isr = NETISR_CCITT; 115 break; 116 #endif 117 default: 118 splx(s); 119 printf("lo%d: can't handle af%d\n", ifp->if_unit, 120 dst->sa_family); 121 m_freem(m); 122 return (EAFNOSUPPORT); 123 } 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(isr); 132 ifp->if_ipackets++; 133 ifp->if_ibytes += m->m_pkthdr.len; 134 splx(s); 135 return (0); 136 } 137 138 /* 139 * Process an ioctl request. 140 */ 141 /* ARGSUSED */ 142 loioctl(ifp, cmd, data) 143 register struct ifnet *ifp; 144 int cmd; 145 caddr_t data; 146 { 147 int error = 0; 148 149 switch (cmd) { 150 151 #ifdef CCITT 152 case SIOCSIFCONF_X25: 153 #endif 154 case SIOCSIFADDR: 155 ifp->if_flags |= IFF_UP; 156 /* 157 * Everything else is done at a higher level. 158 */ 159 break; 160 161 default: 162 error = EINVAL; 163 } 164 return (error); 165 } 166