|
|
1.1 root 1: /* if.c 6.2 83/09/27 */
2:
3: #include "../h/param.h"
4: #include "../h/systm.h"
5: #include "../h/socket.h"
6: #include "../h/protosw.h"
7: #include "../h/dir.h"
8: #include "../h/user.h"
9: #include "../h/kernel.h"
10: #include "../h/ioctl.h"
11: #include "../h/errno.h"
1.1.1.2 ! root 12: #include "../h/mbuf.h"
1.1 root 13:
14: #include "../net/if.h"
15: #include "../net/af.h"
1.1.1.2 ! root 16: #include "../net/route.h"
1.1 root 17:
18: int ifqmaxlen = IFQ_MAXLEN;
19:
20: /*
21: * Change:
22: * . Add the check to make sure that only superuser can
23: * assign Ethernet station address with ioctl(SIOCSETETADDR).
1.1.1.2 ! root 24: * . 01/15/86. Add new ioctl SIOCGETETADDR
! 25: * . 01/15/86. if_ifwithnet(), if_ifwithaddr(): Add check for whether
! 26: * an interface is up before qualifying it for further tests.
! 27: * . 01/19/86. Add new routine if_ifptop(). See description below.
! 28: * . 01/22/86. if_down(). Delete routing entry for inactive interface.
! 29: * . 01/22/86. if_ioctl(). Add new routing entry for an inactive interface
! 30: * which is being brought up.
1.1 root 31: */
32:
33: /*
34: * Network interface utility routines.
35: *
36: * Routines with if_ifwith* names take sockaddr *'s as
37: * parameters. Other routines take value parameters,
38: * e.g. if_ifwithnet takes the network number.
39: */
40:
41: ifinit()
42: {
43: register struct ifnet *ifp;
44:
45: for (ifp = ifnet; ifp; ifp = ifp->if_next)
46: if (ifp->if_init) {
47: (*ifp->if_init)(ifp->if_unit);
48: if (ifp->if_snd.ifq_maxlen == 0)
49: ifp->if_snd.ifq_maxlen = ifqmaxlen;
50: }
51: if_slowtimo();
52: }
53:
54: #ifdef vax
55: /*
56: * Call each interface on a Unibus reset.
57: */
58: ifubareset(uban)
59: int uban;
60: {
61: register struct ifnet *ifp;
62:
63: for (ifp = ifnet; ifp; ifp = ifp->if_next)
64: if (ifp->if_reset)
65: (*ifp->if_reset)(ifp->if_unit, uban);
66: }
67: #endif
68:
69: /*
70: * Attach an interface to the
71: * list of "active" interfaces.
72: */
73: if_attach(ifp)
74: struct ifnet *ifp;
75: {
76: register struct ifnet **p = &ifnet;
77:
78: while (*p)
79: p = &((*p)->if_next);
80: *p = ifp;
81: }
82:
83: /*
84: * Detach an interface from the
85: * list of "active" interfaces.
86: */
87: if_detach(ifp)
88: struct ifnet *ifp;
89: {
90: short s = splimp();
91: register struct ifnet **p = &ifnet;
1.1.1.2 ! root 92: register struct mbuf *m;
1.1 root 93:
94: while (*p) {
95: if ((*p) == ifp) {
1.1.1.2 ! root 96: /* Deallocate output bufs */
! 97: while (ifp->if_snd.ifq_head) {
! 98: IF_DEQUEUE(&ifp->if_snd, m)
! 99: m_freem(m);
! 100: }
1.1 root 101: (*p) = (struct ifnet *)ifp->if_next;
102: ifp->if_next = (struct ifnet *)0;
103: break;
104: }
105: else p = &((*p)->if_next);
106: }
107:
108: splx(s);
109: }
110:
111: /*
112: * Locate an interface based on a complete address.
113: */
114: /*ARGSUSED*/
115: struct ifnet *
116: if_ifwithaddr(addr)
117: struct sockaddr *addr;
118: {
119: register struct ifnet *ifp;
120:
121: #define equal(a1, a2) \
122: (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0)
123: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
1.1.1.2 ! root 124: if ((ifp->if_addr.sa_family != addr->sa_family) ||
! 125: !(ifp->if_flags & IFF_UP))
1.1 root 126: continue;
127: if (equal(&ifp->if_addr, addr))
128: break;
129: if ((ifp->if_flags & IFF_BROADCAST) &&
130: equal(&ifp->if_broadaddr, addr))
131: break;
132: }
133: return (ifp);
134: }
135:
136: /*
137: * Find an interface on a specific network. If many, choice
138: * is first found.
139: */
140: struct ifnet *
141: if_ifwithnet(addr)
142: register struct sockaddr *addr;
143: {
144: register struct ifnet *ifp;
145: register u_int af = addr->sa_family;
146: register int (*netmatch)();
147:
148: if (af >= AF_MAX)
149: return (0);
150: netmatch = afswitch[af].af_netmatch;
151: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
1.1.1.2 ! root 152: if ((af != ifp->if_addr.sa_family) || !(ifp->if_flags & IFF_UP))
1.1 root 153: continue;
154: if ((*netmatch)(addr, &ifp->if_addr))
155: break;
156: }
157: return (ifp);
158: }
159:
160: /*
161: * As above, but parameter is network number.
162: */
163: struct ifnet *
164: if_ifonnetof(net)
165: register int net;
166: {
167: register struct ifnet *ifp;
168:
169: for (ifp = ifnet; ifp; ifp = ifp->if_next)
170: if (ifp->if_net == net)
171: break;
172: return (ifp);
173: }
174:
175: /*
176: * Find an interface using a specific address family
177: */
178: struct ifnet *
179: if_ifwithaf(af)
180: register int af;
181: {
182: register struct ifnet *ifp;
183:
184: for (ifp = ifnet; ifp; ifp = ifp->if_next)
185: if (ifp->if_addr.sa_family == af)
186: break;
187: return (ifp);
188: }
189:
190: /*
191: * Mark an interface down and notify protocols of
192: * the transition.
1.1.1.2 ! root 193: * NOTE: must be called at splnet or equivalent.
1.1 root 194: */
195: if_down(ifp)
196: register struct ifnet *ifp;
197: {
198:
199: ifp->if_flags &= ~IFF_UP;
200: pfctlinput(PRC_IFDOWN, (caddr_t)&ifp->if_addr);
1.1.1.2 ! root 201: if_rtinit(ifp, -1); /* delete routing entry */
1.1 root 202: }
203:
204: /*
205: * Handle interface watchdog timer routines. Called
206: * from softclock, we decrement timers (if set) and
207: * call the appropriate interface routine on expiration.
208: */
209: if_slowtimo()
210: {
211: register struct ifnet *ifp;
212:
213: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
214: if (ifp->if_timer == 0 || --ifp->if_timer)
215: continue;
216: if (ifp->if_watchdog)
217: (*ifp->if_watchdog)(ifp->if_unit);
218: }
219: timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ);
220: }
221:
222: /*
223: * Map interface name to
224: * interface structure pointer.
225: */
226: struct ifnet *
227: ifunit(name)
228: register char *name;
229: {
230: register char *cp;
231: register struct ifnet *ifp;
232: int unit;
233:
234: for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
235: if (*cp >= '0' && *cp <= '9')
236: break;
237: if (*cp == '\0' || cp == name + IFNAMSIZ)
238: return ((struct ifnet *)0);
239: unit = *cp - '0', *cp = 0;
240: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
241: if (bcmp(ifp->if_name, name, (unsigned)(cp - name)))
242: continue;
243: if (unit == ifp->if_unit)
244: break;
245: }
246: return (ifp);
247: }
248:
249: /*
250: * Interface ioctls.
251: */
252: ifioctl(cmd, data)
253: int cmd;
254: caddr_t data;
255: {
256: register struct ifnet *ifp;
257: register struct ifreq *ifr;
258:
259: switch (cmd) {
260:
261: case SIOCGIFCONF:
262: return (ifconf(cmd, data));
263:
264: case SIOCSIFADDR:
265: case SIOCSIFFLAGS:
266: case SIOCSIFDSTADDR:
267: case SIOCSETETADDR:
1.1.1.2 ! root 268: case SIOCIFDETACH:
1.1 root 269: if (!suser())
270: return (u.u_error);
1.1.1.2 ! root 271: case SIOCGETETADDR:
! 272: default:
1.1 root 273: break;
274: }
275: ifr = (struct ifreq *)data;
276: ifp = ifunit(ifr->ifr_name);
277: if (ifp == 0)
278: return (ENXIO);
279: switch (cmd) {
280:
281: case SIOCGIFADDR:
282: ifr->ifr_addr = ifp->if_addr;
283: break;
284:
285: case SIOCGIFDSTADDR:
286: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
287: return (EINVAL);
288: ifr->ifr_dstaddr = ifp->if_dstaddr;
289: break;
290:
291: case SIOCGIFFLAGS:
292: ifr->ifr_flags = ifp->if_flags;
293: break;
294:
295: case SIOCSIFFLAGS:
296: if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
297: int s = splimp();
298: if_down(ifp);
299: splx(s);
300: }
1.1.1.2 ! root 301: /*
! 302: * if interface was inactive and being brought up now,
! 303: * We should add routing entry for it because its old entry
! 304: * was deleted when we brought it down earlier.
! 305: */
! 306: if (!(ifp->if_flags & IFF_UP) && (ifr->ifr_flags & IFF_UP))
! 307: if_rtinit(ifp, RTF_UP);
1.1 root 308: ifp->if_flags = ifr->ifr_flags;
309: break;
310:
311: default:
312: if (ifp->if_ioctl == 0)
313: return (EOPNOTSUPP);
314: return ((*ifp->if_ioctl)(ifp, cmd, data));
315: }
316: return (0);
317: }
318:
319: /*
320: * Return interface configuration
321: * of system. List may be used
322: * in later ioctl's (above) to get
323: * other information.
324: */
325: /*ARGSUSED*/
326: ifconf(cmd, data)
327: int cmd;
328: caddr_t data;
329: {
330: register struct ifconf *ifc = (struct ifconf *)data;
331: register struct ifnet *ifp = ifnet;
332: register char *cp, *ep;
333: struct ifreq ifr, *ifrp;
334: int space = ifc->ifc_len, error = 0;
335:
336: ifrp = ifc->ifc_req;
337: ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
338: for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
339: bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2);
340: for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
341: ;
342: *cp++ = '0' + ifp->if_unit; *cp = '\0';
343: ifr.ifr_addr = ifp->if_addr;
344: error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr));
345: if (error)
346: break;
347: space -= sizeof (ifr), ifrp++;
348: }
349: ifc->ifc_len -= space;
350: return (error);
351: }
1.1.1.2 ! root 352: /*
! 353: * Search for a point-to-point link connected to
! 354: * (destination or gateway) host.
! 355: */
! 356: struct ifnet *
! 357: if_ifptop(rt)
! 358: register struct rtentry *rt;
! 359: {
! 360: register struct ifnet *ifp;
! 361:
! 362: /* When adding a route that use POINTTOPOINT interface, we
! 363: give priority to a direct connection before looking for
! 364: a gateway.
! 365: */
! 366: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
! 367: if (ifp->if_addr.sa_family != rt->rt_dst.sa_family ||
! 368: !(ifp->if_flags&IFF_UP))
! 369: continue;
! 370: if ((ifp->if_flags & IFF_POINTOPOINT) &&
! 371: (bcmp(ifp->if_dstaddr.sa_data,
! 372: rt->rt_dst.sa_data, 14) == 0 ))
! 373: break;
! 374: }
! 375: if (ifp == 0) {
! 376: for (ifp = ifnet; ifp; ifp = ifp->if_next) {
! 377: if (ifp->if_addr.sa_family !=
! 378: rt->rt_dst.sa_family ||
! 379: !(ifp->if_flags&IFF_UP))
! 380: continue;
! 381: if ((ifp->if_flags & IFF_POINTOPOINT) &&
! 382: (bcmp(ifp->if_dstaddr.sa_data,
! 383: rt->rt_gateway.sa_data, 14) == 0))
! 384: break;
! 385: }
! 386: }
! 387: return(ifp);
! 388: }
! 389:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.