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