date and time created 87/04/07 19:51:14 by karels
[unix-history] / usr / src / sys / net / if_loop.c
CommitLineData
8ae0e4b4 1/*
21622db8 2 * Copyright (c) 1982, 1986 Regents of the University of California.
8ae0e4b4
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
2e62d00d 6 * @(#)if_loop.c 7.2 (Berkeley) %G%
8ae0e4b4 7 */
0a486d2b
BJ
8
9/*
10 * Loopback interface driver for protocol testing and timing.
11 */
12
20666ad3
JB
13#include "param.h"
14#include "systm.h"
15#include "mbuf.h"
16#include "socket.h"
17#include "errno.h"
18#include "ioctl.h"
1cc8c949 19
0a486d2b 20#include "../net/if.h"
fcfe450e 21#include "../net/netisr.h"
1cc8c949
SL
22#include "../net/route.h"
23
2e62d00d
MK
24#include "../machine/mtpr.h"
25
dbc42650
MK
26#ifdef INET
27#include "../netinet/in.h"
28#include "../netinet/in_systm.h"
21622db8 29#include "../netinet/in_var.h"
dbc42650 30#include "../netinet/ip.h"
dbc42650 31#endif
1cc8c949 32
edecfd58
KS
33#ifdef NS
34#include "../netns/ns.h"
35#include "../netns/ns_if.h"
36#endif
37
56e0df97 38#define LOMTU (1024+512)
0a486d2b
BJ
39
40struct ifnet loif;
639a8848 41int looutput(), loioctl();
0a486d2b
BJ
42
43loattach()
44{
45 register struct ifnet *ifp = &loif;
46
b454c3ea 47 ifp->if_name = "lo";
0a486d2b 48 ifp->if_mtu = LOMTU;
484ee22e 49 ifp->if_flags = IFF_LOOPBACK;
639a8848 50 ifp->if_ioctl = loioctl;
0a486d2b 51 ifp->if_output = looutput;
405c9168 52 if_attach(ifp);
0a486d2b
BJ
53}
54
ee787340 55looutput(ifp, m0, dst)
0a486d2b 56 struct ifnet *ifp;
dbc42650 57 register struct mbuf *m0;
ee787340 58 struct sockaddr *dst;
0a486d2b 59{
dbc42650 60 int s;
1e977657 61 register struct ifqueue *ifq;
dbc42650
MK
62 struct mbuf *m;
63
64 /*
65 * Place interface pointer before the data
66 * for the receiving protocol.
67 */
68 if (m0->m_off <= MMAXOFF &&
69 m0->m_off >= MMINOFF + sizeof(struct ifnet *)) {
70 m0->m_off -= sizeof(struct ifnet *);
71 m0->m_len += sizeof(struct ifnet *);
72 } else {
73 MGET(m, M_DONTWAIT, MT_HEADER);
74 if (m == (struct mbuf *)0)
75 return (ENOBUFS);
76 m->m_off = MMINOFF;
77 m->m_len = sizeof(struct ifnet *);
78 m->m_next = m0;
79 m0 = m;
80 }
81 *(mtod(m0, struct ifnet **)) = ifp;
82 s = splimp();
b454c3ea 83 ifp->if_opackets++;
ee787340 84 switch (dst->sa_family) {
0a486d2b
BJ
85
86#ifdef INET
ee787340 87 case AF_INET:
1e977657
BJ
88 ifq = &ipintrq;
89 if (IF_QFULL(ifq)) {
90 IF_DROP(ifq);
ee787340 91 m_freem(m0);
1e977657 92 splx(s);
4c5902e0 93 return (ENOBUFS);
1e977657
BJ
94 }
95 IF_ENQUEUE(ifq, m0);
9c8692e9 96 schednetisr(NETISR_IP);
0a486d2b 97 break;
edecfd58
KS
98#endif
99#ifdef NS
100 case AF_NS:
101 ifq = &nsintrq;
102 if (IF_QFULL(ifq)) {
103 IF_DROP(ifq);
104 m_freem(m0);
105 splx(s);
106 return (ENOBUFS);
107 }
108 IF_ENQUEUE(ifq, m0);
109 schednetisr(NETISR_NS);
110 break;
0a486d2b 111#endif
0a486d2b
BJ
112 default:
113 splx(s);
ee787340
SL
114 printf("lo%d: can't handle af%d\n", ifp->if_unit,
115 dst->sa_family);
116 m_freem(m0);
4c5902e0 117 return (EAFNOSUPPORT);
0a486d2b 118 }
b454c3ea 119 ifp->if_ipackets++;
0a486d2b 120 splx(s);
4c5902e0 121 return (0);
0a486d2b 122}
639a8848
SL
123
124/*
125 * Process an ioctl request.
126 */
bba52753 127/* ARGSUSED */
639a8848
SL
128loioctl(ifp, cmd, data)
129 register struct ifnet *ifp;
130 int cmd;
131 caddr_t data;
132{
bba52753 133 int error = 0;
639a8848
SL
134
135 switch (cmd) {
136
137 case SIOCSIFADDR:
bba52753
MK
138 ifp->if_flags |= IFF_UP;
139 /*
140 * Everything else is done at a higher level.
141 */
639a8848
SL
142 break;
143
144 default:
145 error = EINVAL;
146 }
639a8848
SL
147 return (error);
148}