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