|
|
1.1 root 1: /*
2: * Copyright (c) 1980, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)if.c 7.1 (Berkeley) 6/4/86
7: */
8:
9: #include "param.h"
10: #include "systm.h"
11: #include "socket.h"
12: #include "socketvar.h"
13: #include "protosw.h"
14: #include "dir.h"
15: #include "user.h"
16: #include "kernel.h"
17: #include "ioctl.h"
18: #include "errno.h"
19:
20: #include "if.h"
21: #include "af.h"
22:
23: #include "ether.h"
24:
25: int ifqmaxlen = IFQ_MAXLEN;
26:
27: /*
28: * Network interface utility routines.
29: *
30: * Routines with ifa_ifwith* names take sockaddr *'s as
31: * parameters.
32: */
33:
34: ifinit()
35: {
36: register struct ifnet *ifp;
37:
38: for (ifp = ifnet; ifp; ifp = ifp->if_next)
39: if (ifp->if_snd.ifq_maxlen == 0)
40: ifp->if_snd.ifq_maxlen = ifqmaxlen;
41: if_slowtimo();
42: }
43:
44: #ifdef vax
45: /*
46: * Call each interface on a Unibus reset.
47: */
48: ifubareset(uban)
49: int uban;
50: {
51: register struct ifnet *ifp;
52:
53: for (ifp = ifnet; ifp; ifp = ifp->if_next)
54: if (ifp->if_reset)
55: (*ifp->if_reset)(ifp->if_unit, uban);
56: }
57: #endif
58:
59: /*
60: * Attach an interface to the
61: * list of "active" interfaces.
62: */
63: if_attach(ifp)
64: struct ifnet *ifp;
65: {
66: register struct ifnet **p = &ifnet;
67:
68: while (*p)
69: p = &((*p)->if_next);
70: *p = ifp;
71: }
72:
73: /*
74: * Locate an interface based on a complete address.
75: */
76: /*ARGSUSED*/
77: struct ifaddr *
78: ifa_ifwithaddr(addr)
79: struct sockaddr *addr;
80: {
81: register struct ifnet *ifp;
82: register struct ifaddr *ifa;
83:
84: #define equal(a1, a2) \
85: (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0)
86: for (ifp = ifnet; ifp; ifp = ifp->if_next)
87: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
88: if (ifa->ifa_addr.sa_family != addr->sa_family)
89: continue;
90: if (equal(&ifa->ifa_addr, addr))
91: return (ifa);
92: if ((ifp->if_flags & IFF_BROADCAST) &&
93: equal(&ifa->ifa_broadaddr, addr))
94: return (ifa);
95: }
96: return ((struct ifaddr *)0);
97: }
98: /*
99: * Locate the point to point interface with a given destination address.
100: */
101: /*ARGSUSED*/
102: struct ifaddr *
103: ifa_ifwithdstaddr(addr)
104: struct sockaddr *addr;
105: {
106: register struct ifnet *ifp;
107: register struct ifaddr *ifa;
108:
109: for (ifp = ifnet; ifp; ifp = ifp->if_next)
110: if (ifp->if_flags & IFF_POINTOPOINT)
111: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
112: if (ifa->ifa_addr.sa_family != addr->sa_family)
113: continue;
114: if (equal(&ifa->ifa_dstaddr, addr))
115: return (ifa);
116: }
117: return ((struct ifaddr *)0);
118: }
119:
120: /*
121: * Find an interface on a specific network. If many, choice
122: * is first found.
123: */
124: struct ifaddr *
125: ifa_ifwithnet(addr)
126: register struct sockaddr *addr;
127: {
128: register struct ifnet *ifp;
129: register struct ifaddr *ifa;
130: register u_int af = addr->sa_family;
131: register int (*netmatch)();
132:
133: if (af >= AF_MAX)
134: return (0);
135: netmatch = afswitch[af].af_netmatch;
136: for (ifp = ifnet; ifp; ifp = ifp->if_next)
137: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
138: if (ifa->ifa_addr.sa_family != addr->sa_family)
139: continue;
140: if ((*netmatch)(&ifa->ifa_addr, addr))
141: return (ifa);
142: }
143: return ((struct ifaddr *)0);
144: }
145:
146: #ifdef notdef
147: /*
148: * Find an interface using a specific address family
149: */
150: struct ifaddr *
151: ifa_ifwithaf(af)
152: register int af;
153: {
154: register struct ifnet *ifp;
155: register struct ifaddr *ifa;
156:
157: for (ifp = ifnet; ifp; ifp = ifp->if_next)
158: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
159: if (ifa->ifa_addr.sa_family == af)
160: return (ifa);
161: return ((struct ifaddr *)0);
162: }
163: #endif
164:
165: /*
166: * Mark an interface down and notify protocols of
167: * the transition.
168: * NOTE: must be called at splnet or eqivalent.
169: */
170: if_down(ifp)
171: register struct ifnet *ifp;
172: {
173: register struct ifaddr *ifa;
174:
175: ifp->if_flags &= ~IFF_UP;
176: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
177: pfctlinput(PRC_IFDOWN, &ifa->ifa_addr);
178: }
179:
180: /*
181: * Handle interface watchdog timer routines. Called
182: * from softclock, we decrement timers (if set) and
183: * call the appropriate interface routine on expiration.
184: */
185: if_slowtimo()
186: {
187: register struct ifnet *ifp;
188:
189: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
190: if (ifp->if_timer == 0 || --ifp->if_timer)
191: continue;
192: if (ifp->if_watchdog)
193: (*ifp->if_watchdog)(ifp->if_unit);
194: }
195: timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ);
196: }
197:
198: /*
199: * Map interface name to
200: * interface structure pointer.
201: */
202: struct ifnet *
203: ifunit(name)
204: register char *name;
205: {
206: register char *cp;
207: register struct ifnet *ifp;
208: int unit;
209:
210: for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
211: if (*cp >= '0' && *cp <= '9')
212: break;
213: if (*cp == '\0' || cp == name + IFNAMSIZ)
214: return ((struct ifnet *)0);
215: unit = *cp - '0';
216: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
217: if (bcmp(ifp->if_name, name, (unsigned)(cp - name)))
218: continue;
219: if (unit == ifp->if_unit)
220: break;
221: }
222: return (ifp);
223: }
224:
225: /*
226: * Interface ioctls.
227: */
228: ifioctl(so, cmd, data)
229: struct socket *so;
230: int cmd;
231: caddr_t data;
232: {
233: register struct ifnet *ifp;
234: register struct ifreq *ifr;
235:
236: switch (cmd) {
237:
238: case SIOCGIFCONF:
239: return (ifconf(cmd, data));
240:
241: #if defined(INET) && NETHER > 0
242: case SIOCSARP:
243: case SIOCDARP:
244: if (!suser())
245: return (u.u_error);
246: /* FALL THROUGH */
247: case SIOCGARP:
248: return (arpioctl(cmd, data));
249: #endif
250: }
251: ifr = (struct ifreq *)data;
252: ifp = ifunit(ifr->ifr_name);
253: if (ifp == 0)
254: return (ENXIO);
255: switch (cmd) {
256:
257: case SIOCGIFFLAGS:
258: ifr->ifr_flags = ifp->if_flags;
259: break;
260:
261: case SIOCGIFMETRIC:
262: ifr->ifr_metric = ifp->if_metric;
263: break;
264:
265: case SIOCSIFFLAGS:
266: if (!suser())
267: return (u.u_error);
268: if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
269: int s = splimp();
270: if_down(ifp);
271: splx(s);
272: }
273: ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
274: (ifr->ifr_flags &~ IFF_CANTCHANGE);
275: if (ifp->if_ioctl)
276: (void) (*ifp->if_ioctl)(ifp, cmd, data);
277: break;
278:
279: case SIOCSIFMETRIC:
280: if (!suser())
281: return (u.u_error);
282: ifp->if_metric = ifr->ifr_metric;
283: break;
284:
285: default:
286: if (so->so_proto == 0)
287: return (EOPNOTSUPP);
288: return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
289: cmd, data, ifp));
290: }
291: return (0);
292: }
293:
294: /*
295: * Return interface configuration
296: * of system. List may be used
297: * in later ioctl's (above) to get
298: * other information.
299: */
300: /*ARGSUSED*/
301: ifconf(cmd, data)
302: int cmd;
303: caddr_t data;
304: {
305: register struct ifconf *ifc = (struct ifconf *)data;
306: register struct ifnet *ifp = ifnet;
307: register struct ifaddr *ifa;
308: register char *cp, *ep;
309: struct ifreq ifr, *ifrp;
310: int space = ifc->ifc_len, error = 0;
311:
312: ifrp = ifc->ifc_req;
313: ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
314: for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
315: bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2);
316: for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
317: ;
318: *cp++ = '0' + ifp->if_unit; *cp = '\0';
319: if ((ifa = ifp->if_addrlist) == 0) {
320: bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
321: error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr));
322: if (error)
323: break;
324: space -= sizeof (ifr), ifrp++;
325: } else
326: for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
327: ifr.ifr_addr = ifa->ifa_addr;
328: error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr));
329: if (error)
330: break;
331: space -= sizeof (ifr), ifrp++;
332: }
333: }
334: ifc->ifc_len -= space;
335: return (error);
336: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.