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.5 (Berkeley) 10/12/88 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/netisr.h" 33 #include "../net/route.h" 34 35 #include "../machine/mtpr.h" 36 37 #ifdef INET 38 #include "../netinet/in.h" 39 #include "../netinet/in_systm.h" 40 #include "../netinet/in_var.h" 41 #include "../netinet/ip.h" 42 #endif 43 44 #ifdef NS 45 #include "../netns/ns.h" 46 #include "../netns/ns_if.h" 47 #endif 48 49 #define LOMTU (1024+512) 50 51 struct ifnet loif; 52 int looutput(), loioctl(); 53 54 loattach() 55 { 56 register struct ifnet *ifp = &loif; 57 58 ifp->if_name = "lo"; 59 ifp->if_mtu = LOMTU; 60 ifp->if_flags = IFF_LOOPBACK; 61 ifp->if_ioctl = loioctl; 62 ifp->if_output = looutput; 63 if_attach(ifp); 64 } 65 66 struct mbuf *Loop_Sanity; 67 68 looutput(ifp, m, dst) 69 struct ifnet *ifp; 70 register struct mbuf *m; 71 struct sockaddr *dst; 72 { 73 int s; 74 register struct ifqueue *ifq; 75 76 if ((m->m_flags & M_PKTHDR) == 0) 77 panic("looutput no HDR"); 78 m->m_pkthdr.rcvif = ifp; 79 80 {struct mbuf *mm; int mlen = 0; 81 for (mm = m; m; m = m->m_next) /* XXX debugging code -- sklwoer */ 82 mlen += m->m_len; 83 m = mm; 84 if (mlen != m->m_pkthdr.len) { 85 if (Loop_Sanity) 86 m_freem(Loop_Sanity); 87 Loop_Sanity = m_copy(m, 0, M_COPYALL); 88 } 89 } 90 91 s = splimp(); 92 ifp->if_opackets++; 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 default: 122 splx(s); 123 printf("lo%d: can't handle af%d\n", ifp->if_unit, 124 dst->sa_family); 125 m_freem(m); 126 return (EAFNOSUPPORT); 127 } 128 ifp->if_ipackets++; 129 splx(s); 130 return (0); 131 } 132 133 /* 134 * Process an ioctl request. 135 */ 136 /* ARGSUSED */ 137 loioctl(ifp, cmd, data) 138 register struct ifnet *ifp; 139 int cmd; 140 caddr_t data; 141 { 142 int error = 0; 143 144 switch (cmd) { 145 146 case SIOCSIFADDR: 147 ifp->if_flags |= IFF_UP; 148 /* 149 * Everything else is done at a higher level. 150 */ 151 break; 152 153 default: 154 error = EINVAL; 155 } 156 return (error); 157 } 158