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