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*39187Ssklower * @(#)if_loop.c 7.9 (Berkeley) 09/20/89 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" 3238988Skarels #include "../net/if_types.h" 3310907Ssam #include "../net/netisr.h" 3410907Ssam #include "../net/route.h" 3510907Ssam 3637500Smckusick #include "machine/mtpr.h" 3729922Skarels 3824771Skarels #ifdef INET 3924771Skarels #include "../netinet/in.h" 4024771Skarels #include "../netinet/in_systm.h" 4129071Skarels #include "../netinet/in_var.h" 4224771Skarels #include "../netinet/ip.h" 4324771Skarels #endif 445122Swnj 4518815Ssklower #ifdef NS 4618815Ssklower #include "../netns/ns.h" 4718815Ssklower #include "../netns/ns_if.h" 4818815Ssklower #endif 4918815Ssklower 5037472Ssklower #ifdef ISO 5137472Ssklower #include "../netiso/iso.h" 5237472Ssklower #include "../netiso/iso_var.h" 5337472Ssklower #endif 5437472Ssklower 555207Swnj #define LOMTU (1024+512) 565122Swnj 575122Swnj struct ifnet loif; 5813066Ssam int looutput(), loioctl(); 595122Swnj 605122Swnj loattach() 615122Swnj { 625122Swnj register struct ifnet *ifp = &loif; 635122Swnj 645172Swnj ifp->if_name = "lo"; 655122Swnj ifp->if_mtu = LOMTU; 6626091Skarels ifp->if_flags = IFF_LOOPBACK; 6713066Ssam ifp->if_ioctl = loioctl; 685122Swnj ifp->if_output = looutput; 6937472Ssklower ifp->if_type = IFT_LOOP; 7037472Ssklower ifp->if_hdrlen = 0; 7137472Ssklower ifp->if_addrlen = 0; 725161Swnj if_attach(ifp); 735122Swnj } 745122Swnj 7535795Skarels struct mbuf *Loop_Sanity; 7635795Skarels 7735795Skarels looutput(ifp, m, dst) 785122Swnj struct ifnet *ifp; 7935795Skarels register struct mbuf *m; 806337Ssam struct sockaddr *dst; 815122Swnj { 8224771Skarels int s; 836209Swnj register struct ifqueue *ifq; 845122Swnj 8535795Skarels if ((m->m_flags & M_PKTHDR) == 0) 8635795Skarels panic("looutput no HDR"); 8735795Skarels m->m_pkthdr.rcvif = ifp; 8835795Skarels 8935795Skarels {struct mbuf *mm; int mlen = 0; 9037472Ssklower for (mm = m; m; m = m->m_next) /* XXX debugging code -- sklower */ 9135795Skarels mlen += m->m_len; 9235795Skarels m = mm; 9335795Skarels if (mlen != m->m_pkthdr.len) { 9435795Skarels if (Loop_Sanity) 9535795Skarels m_freem(Loop_Sanity); 9637472Ssklower Loop_Sanity = m_copy(m, 0, (int)M_COPYALL); 9735795Skarels } 9835795Skarels } 9935795Skarels 10024771Skarels s = splimp(); 1015172Swnj ifp->if_opackets++; 102*39187Ssklower ifp->if_obytes += m->m_pkthdr.len; 1036337Ssam switch (dst->sa_family) { 1045122Swnj 1055122Swnj #ifdef INET 1066337Ssam case AF_INET: 1076209Swnj ifq = &ipintrq; 1086209Swnj if (IF_QFULL(ifq)) { 1096209Swnj IF_DROP(ifq); 11035795Skarels m_freem(m); 1116209Swnj splx(s); 1126544Sfeldman return (ENOBUFS); 1136209Swnj } 11435795Skarels IF_ENQUEUE(ifq, m); 1156262Swnj schednetisr(NETISR_IP); 1165122Swnj break; 1175122Swnj #endif 11818815Ssklower #ifdef NS 11918815Ssklower case AF_NS: 12018815Ssklower ifq = &nsintrq; 12118815Ssklower if (IF_QFULL(ifq)) { 12218815Ssklower IF_DROP(ifq); 12335795Skarels m_freem(m); 12418815Ssklower splx(s); 12518815Ssklower return (ENOBUFS); 12618815Ssklower } 12735795Skarels IF_ENQUEUE(ifq, m); 12818815Ssklower schednetisr(NETISR_NS); 12918815Ssklower break; 13018815Ssklower #endif 13137472Ssklower #ifdef ISO 13237472Ssklower case AF_ISO: 13337472Ssklower ifq = &clnlintrq; 13437472Ssklower if (IF_QFULL(ifq)) { 13537472Ssklower IF_DROP(ifq); 13637472Ssklower m_freem(m); 13737472Ssklower splx(s); 13837472Ssklower return (ENOBUFS); 13937472Ssklower } 14037472Ssklower IF_ENQUEUE(ifq, m); 14137472Ssklower schednetisr(NETISR_ISO); 14237472Ssklower break; 14337472Ssklower #endif 1445122Swnj default: 1455122Swnj splx(s); 1466337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 1476337Ssam dst->sa_family); 14835795Skarels m_freem(m); 1496544Sfeldman return (EAFNOSUPPORT); 1505122Swnj } 1515172Swnj ifp->if_ipackets++; 152*39187Ssklower ifp->if_ibytes += m->m_pkthdr.len; 1535122Swnj splx(s); 1546544Sfeldman return (0); 1555122Swnj } 15613066Ssam 15713066Ssam /* 15813066Ssam * Process an ioctl request. 15913066Ssam */ 16018370Skarels /* ARGSUSED */ 16113066Ssam loioctl(ifp, cmd, data) 16213066Ssam register struct ifnet *ifp; 16313066Ssam int cmd; 16413066Ssam caddr_t data; 16513066Ssam { 16618370Skarels int error = 0; 16713066Ssam 16813066Ssam switch (cmd) { 16913066Ssam 17013066Ssam case SIOCSIFADDR: 17118370Skarels ifp->if_flags |= IFF_UP; 17218370Skarels /* 17318370Skarels * Everything else is done at a higher level. 17418370Skarels */ 17513066Ssam break; 17613066Ssam 17713066Ssam default: 17813066Ssam error = EINVAL; 17913066Ssam } 18013066Ssam return (error); 18113066Ssam } 182