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, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)if_loop.c 7.13 (Berkeley) 4/26/91 34 * $Id: if_loop.c,v 1.5 1993/05/20 03:06:02 cgd Exp $ 35 */ 36 37 /* 38 * Loopback interface driver for protocol testing and timing. 39 */ 40 41 #include "param.h" 42 #include "systm.h" 43 #include "mbuf.h" 44 #include "socket.h" 45 #include "errno.h" 46 #include "ioctl.h" 47 #include "protosw.h" 48 49 #include "loop.h" 50 51 #include "../net/if.h" 52 #include "../net/if_types.h" 53 #include "../net/netisr.h" 54 #include "../net/route.h" 55 56 #include "machine/mtpr.h" 57 58 #ifdef INET 59 #include "../netinet/in.h" 60 #include "../netinet/in_systm.h" 61 #include "../netinet/in_var.h" 62 #include "../netinet/ip.h" 63 #endif 64 65 #ifdef NS 66 #include "../netns/ns.h" 67 #include "../netns/ns_if.h" 68 #endif 69 70 #ifdef ISO 71 #include "../netiso/iso.h" 72 #include "../netiso/iso_var.h" 73 #endif 74 75 #include "bpfilter.h" 76 #if NBPFILTER > 0 77 #include <sys/time.h> 78 #include <net/bpf.h> 79 static caddr_t lo_bpf; 80 #endif 81 82 #define LOMTU (1024+512) 83 84 struct ifnet loif[NLOOP]; 85 int looutput(), loioctl(); 86 87 loattach() 88 { 89 register int i; 90 register struct ifnet *ifp; 91 92 for (i = 0; i < NLOOP; i++) 93 { 94 ifp = &loif[i]; 95 ifp->if_unit = i; 96 ifp->if_name = "lo"; 97 ifp->if_mtu = LOMTU; 98 ifp->if_flags = IFF_LOOPBACK; 99 ifp->if_ioctl = loioctl; 100 ifp->if_output = looutput; 101 ifp->if_type = IFT_LOOP; 102 ifp->if_hdrlen = 0; 103 ifp->if_addrlen = 0; 104 if_attach(ifp); 105 #if NBPFILTER > 0 106 bpfattach(&lo_bpf, ifp, DLT_NULL, sizeof(u_int)); 107 #endif 108 } 109 } 110 111 looutput(ifp, m, dst, rt) 112 struct ifnet *ifp; 113 register struct mbuf *m; 114 struct sockaddr *dst; 115 register struct rtentry *rt; 116 { 117 int s, isr; 118 register struct ifqueue *ifq = 0; 119 120 if ((m->m_flags & M_PKTHDR) == 0) 121 panic("looutput no HDR"); 122 #if NBPFILTER > 0 123 if (lo_bpf) { 124 /* 125 * We need to prepend the address family as 126 * a four byte field. Cons up a dummy header 127 * to pacify bpf. This is safe because bpf 128 * will only read from the mbuf (i.e., it won't 129 * try to free it or keep a pointer to it). 130 */ 131 struct mbuf m0; 132 u_int af = dst->sa_family; 133 134 m0.m_next = m; 135 m0.m_len = 4; 136 m0.m_data = (char *)⁡ 137 138 bpf_mtap(lo_bpf, &m0); 139 } 140 #endif 141 m->m_pkthdr.rcvif = ifp; 142 143 if (rt && rt->rt_flags & RTF_REJECT) { 144 m_freem(m); 145 return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 146 } 147 ifp->if_opackets++; 148 ifp->if_obytes += m->m_pkthdr.len; 149 switch (dst->sa_family) { 150 151 #ifdef INET 152 case AF_INET: 153 ifq = &ipintrq; 154 isr = NETISR_IP; 155 break; 156 #endif 157 #ifdef NS 158 case AF_NS: 159 ifq = &nsintrq; 160 isr = NETISR_NS; 161 break; 162 #endif 163 #ifdef ISO 164 case AF_ISO: 165 ifq = &clnlintrq; 166 isr = NETISR_ISO; 167 break; 168 #endif 169 default: 170 printf("lo%d: can't handle af%d\n", ifp->if_unit, 171 dst->sa_family); 172 m_freem(m); 173 return (EAFNOSUPPORT); 174 } 175 s = splimp(); 176 if (IF_QFULL(ifq)) { 177 IF_DROP(ifq); 178 m_freem(m); 179 splx(s); 180 return (ENOBUFS); 181 } 182 IF_ENQUEUE(ifq, m); 183 schednetisr(isr); 184 ifp->if_ipackets++; 185 ifp->if_ibytes += m->m_pkthdr.len; 186 splx(s); 187 return (0); 188 } 189 190 /* ARGSUSED */ 191 lortrequest(cmd, rt, sa) 192 struct rtentry *rt; 193 struct sockaddr *sa; 194 { 195 if (rt) 196 rt->rt_rmx.rmx_mtu = LOMTU; 197 } 198 199 /* 200 * Process an ioctl request. 201 */ 202 /* ARGSUSED */ 203 loioctl(ifp, cmd, data) 204 register struct ifnet *ifp; 205 int cmd; 206 caddr_t data; 207 { 208 register struct ifaddr *ifa; 209 int error = 0; 210 211 switch (cmd) { 212 213 case SIOCSIFADDR: 214 ifp->if_flags |= IFF_UP; 215 ifa = (struct ifaddr *)data; 216 if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO) 217 ifa->ifa_rtrequest = lortrequest; 218 /* 219 * Everything else is done at a higher level. 220 */ 221 break; 222 223 default: 224 error = EINVAL; 225 } 226 return (error); 227 } 228