123174Smckusick /* 229071Skarels * Copyright (c) 1982, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423174Smckusick * 533183Sbostic * Redistribution and use in source and binary forms are permitted 634844Sbostic * provided that the above copyright notice and this paragraph are 734844Sbostic * duplicated in all such forms and that any documentation, 834844Sbostic * advertising materials, and other materials related to such 934844Sbostic * distribution and use acknowledge that the software was developed 1034844Sbostic * by the University of California, Berkeley. The name of the 1134844Sbostic * University may not be used to endorse or promote products derived 1234844Sbostic * from this software without specific prior written permission. 1334844Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434844Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534844Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633183Sbostic * 17*35795Skarels * @(#)if_loop.c 7.5 (Berkeley) 10/12/88 1823174Smckusick */ 195122Swnj 205122Swnj /* 215122Swnj * Loopback interface driver for protocol testing and timing. 225122Swnj */ 235122Swnj 2417058Sbloom #include "param.h" 2517058Sbloom #include "systm.h" 2617058Sbloom #include "mbuf.h" 2717058Sbloom #include "socket.h" 2817058Sbloom #include "errno.h" 2917058Sbloom #include "ioctl.h" 3010907Ssam 3110907Ssam #include "../net/if.h" 3210907Ssam #include "../net/netisr.h" 3310907Ssam #include "../net/route.h" 3410907Ssam 3529922Skarels #include "../machine/mtpr.h" 3629922Skarels 3724771Skarels #ifdef INET 3824771Skarels #include "../netinet/in.h" 3924771Skarels #include "../netinet/in_systm.h" 4029071Skarels #include "../netinet/in_var.h" 4124771Skarels #include "../netinet/ip.h" 4224771Skarels #endif 435122Swnj 4418815Ssklower #ifdef NS 4518815Ssklower #include "../netns/ns.h" 4618815Ssklower #include "../netns/ns_if.h" 4718815Ssklower #endif 4818815Ssklower 495207Swnj #define LOMTU (1024+512) 505122Swnj 515122Swnj struct ifnet loif; 5213066Ssam int looutput(), loioctl(); 535122Swnj 545122Swnj loattach() 555122Swnj { 565122Swnj register struct ifnet *ifp = &loif; 575122Swnj 585172Swnj ifp->if_name = "lo"; 595122Swnj ifp->if_mtu = LOMTU; 6026091Skarels ifp->if_flags = IFF_LOOPBACK; 6113066Ssam ifp->if_ioctl = loioctl; 625122Swnj ifp->if_output = looutput; 635161Swnj if_attach(ifp); 645122Swnj } 655122Swnj 66*35795Skarels struct mbuf *Loop_Sanity; 67*35795Skarels 68*35795Skarels looutput(ifp, m, dst) 695122Swnj struct ifnet *ifp; 70*35795Skarels register struct mbuf *m; 716337Ssam struct sockaddr *dst; 725122Swnj { 7324771Skarels int s; 746209Swnj register struct ifqueue *ifq; 755122Swnj 76*35795Skarels if ((m->m_flags & M_PKTHDR) == 0) 77*35795Skarels panic("looutput no HDR"); 78*35795Skarels m->m_pkthdr.rcvif = ifp; 79*35795Skarels 80*35795Skarels {struct mbuf *mm; int mlen = 0; 81*35795Skarels for (mm = m; m; m = m->m_next) /* XXX debugging code -- sklwoer */ 82*35795Skarels mlen += m->m_len; 83*35795Skarels m = mm; 84*35795Skarels if (mlen != m->m_pkthdr.len) { 85*35795Skarels if (Loop_Sanity) 86*35795Skarels m_freem(Loop_Sanity); 87*35795Skarels Loop_Sanity = m_copy(m, 0, M_COPYALL); 88*35795Skarels } 89*35795Skarels } 90*35795Skarels 9124771Skarels s = splimp(); 925172Swnj ifp->if_opackets++; 936337Ssam switch (dst->sa_family) { 945122Swnj 955122Swnj #ifdef INET 966337Ssam case AF_INET: 976209Swnj ifq = &ipintrq; 986209Swnj if (IF_QFULL(ifq)) { 996209Swnj IF_DROP(ifq); 100*35795Skarels m_freem(m); 1016209Swnj splx(s); 1026544Sfeldman return (ENOBUFS); 1036209Swnj } 104*35795Skarels IF_ENQUEUE(ifq, m); 1056262Swnj schednetisr(NETISR_IP); 1065122Swnj break; 1075122Swnj #endif 10818815Ssklower #ifdef NS 10918815Ssklower case AF_NS: 11018815Ssklower ifq = &nsintrq; 11118815Ssklower if (IF_QFULL(ifq)) { 11218815Ssklower IF_DROP(ifq); 113*35795Skarels m_freem(m); 11418815Ssklower splx(s); 11518815Ssklower return (ENOBUFS); 11618815Ssklower } 117*35795Skarels IF_ENQUEUE(ifq, m); 11818815Ssklower schednetisr(NETISR_NS); 11918815Ssklower break; 12018815Ssklower #endif 1215122Swnj default: 1225122Swnj splx(s); 1236337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 1246337Ssam dst->sa_family); 125*35795Skarels m_freem(m); 1266544Sfeldman return (EAFNOSUPPORT); 1275122Swnj } 1285172Swnj ifp->if_ipackets++; 1295122Swnj splx(s); 1306544Sfeldman return (0); 1315122Swnj } 13213066Ssam 13313066Ssam /* 13413066Ssam * Process an ioctl request. 13513066Ssam */ 13618370Skarels /* ARGSUSED */ 13713066Ssam loioctl(ifp, cmd, data) 13813066Ssam register struct ifnet *ifp; 13913066Ssam int cmd; 14013066Ssam caddr_t data; 14113066Ssam { 14218370Skarels int error = 0; 14313066Ssam 14413066Ssam switch (cmd) { 14513066Ssam 14613066Ssam case SIOCSIFADDR: 14718370Skarels ifp->if_flags |= IFF_UP; 14818370Skarels /* 14918370Skarels * Everything else is done at a higher level. 15018370Skarels */ 15113066Ssam break; 15213066Ssam 15313066Ssam default: 15413066Ssam error = EINVAL; 15513066Ssam } 15613066Ssam return (error); 15713066Ssam } 158