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.7 (Berkeley) 04/25/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/iftypes.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 switch (dst->sa_family) { 103 104 #ifdef INET 105 case AF_INET: 106 ifq = &ipintrq; 107 if (IF_QFULL(ifq)) { 108 IF_DROP(ifq); 109 m_freem(m); 110 splx(s); 111 return (ENOBUFS); 112 } 113 IF_ENQUEUE(ifq, m); 114 schednetisr(NETISR_IP); 115 break; 116 #endif 117 #ifdef NS 118 case AF_NS: 119 ifq = &nsintrq; 120 if (IF_QFULL(ifq)) { 121 IF_DROP(ifq); 122 m_freem(m); 123 splx(s); 124 return (ENOBUFS); 125 } 126 IF_ENQUEUE(ifq, m); 127 schednetisr(NETISR_NS); 128 break; 129 #endif 130 #ifdef ISO 131 case AF_ISO: 132 ifq = &clnlintrq; 133 if (IF_QFULL(ifq)) { 134 IF_DROP(ifq); 135 m_freem(m); 136 splx(s); 137 return (ENOBUFS); 138 } 139 IF_ENQUEUE(ifq, m); 140 schednetisr(NETISR_ISO); 141 break; 142 #endif 143 default: 144 splx(s); 145 printf("lo%d: can't handle af%d\n", ifp->if_unit, 146 dst->sa_family); 147 m_freem(m); 148 return (EAFNOSUPPORT); 149 } 150 ifp->if_ipackets++; 151 splx(s); 152 return (0); 153 } 154 155 /* 156 * Process an ioctl request. 157 */ 158 /* ARGSUSED */ 159 loioctl(ifp, cmd, data) 160 register struct ifnet *ifp; 161 int cmd; 162 caddr_t data; 163 { 164 int error = 0; 165 166 switch (cmd) { 167 168 case SIOCSIFADDR: 169 ifp->if_flags |= IFF_UP; 170 /* 171 * Everything else is done at a higher level. 172 */ 173 break; 174 175 default: 176 error = EINVAL; 177 } 178 return (error); 179 } 180