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