1 /*
2 * Copyright (c) 1980, 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)if.c 8.5 (Berkeley) 01/09/95
8 */
9
10 #include <sys/param.h>
11 #include <sys/mbuf.h>
12 #include <sys/systm.h>
13 #include <sys/proc.h>
14 #include <sys/socket.h>
15 #include <sys/socketvar.h>
16 #include <sys/protosw.h>
17 #include <sys/kernel.h>
18 #include <sys/ioctl.h>
19
20 #include <net/if.h>
21 #include <net/if_dl.h>
22 #include <net/if_types.h>
23
24 int ifqmaxlen = IFQ_MAXLEN;
25 void if_slowtimo __P((void *arg));
26
27 /*
28 * Network interface utility routines.
29 *
30 * Routines with ifa_ifwith* names take sockaddr *'s as
31 * parameters.
32 */
33 void
ifinit()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(0);
42 }
43
44 #ifdef vax
45 /*
46 * Call each interface on a Unibus reset.
47 */
48 void
ifubareset(uban)49 ifubareset(uban)
50 int uban;
51 {
52 register struct ifnet *ifp;
53
54 for (ifp = ifnet; ifp; ifp = ifp->if_next)
55 if (ifp->if_reset)
56 (*ifp->if_reset)(ifp->if_unit, uban);
57 }
58 #endif
59
60 int if_index = 0;
61 struct ifaddr **ifnet_addrs;
62 static char *sprint_d __P((u_int, char *, int));
63
64 /*
65 * Attach an interface to the
66 * list of "active" interfaces.
67 */
68 void
if_attach(ifp)69 if_attach(ifp)
70 struct ifnet *ifp;
71 {
72 unsigned socksize, ifasize;
73 int namelen, unitlen, masklen, ether_output();
74 char workbuf[12], *unitname;
75 register struct ifnet **p = &ifnet;
76 register struct sockaddr_dl *sdl;
77 register struct ifaddr *ifa;
78 static int if_indexlim = 8;
79 extern void link_rtrequest();
80
81 while (*p)
82 p = &((*p)->if_next);
83 *p = ifp;
84 ifp->if_index = ++if_index;
85 if (ifnet_addrs == 0 || if_index >= if_indexlim) {
86 unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
87 struct ifaddr **q = (struct ifaddr **)
88 malloc(n, M_IFADDR, M_WAITOK);
89 if (ifnet_addrs) {
90 bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
91 free((caddr_t)ifnet_addrs, M_IFADDR);
92 }
93 ifnet_addrs = q;
94 }
95 /*
96 * create a Link Level name for this device
97 */
98 unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
99 namelen = strlen(ifp->if_name);
100 unitlen = strlen(unitname);
101 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
102 masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) +
103 unitlen + namelen;
104 socksize = masklen + ifp->if_addrlen;
105 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
106 socksize = ROUNDUP(socksize);
107 if (socksize < sizeof(*sdl))
108 socksize = sizeof(*sdl);
109 ifasize = sizeof(*ifa) + 2 * socksize;
110 if (ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK)) {
111 bzero((caddr_t)ifa, ifasize);
112 sdl = (struct sockaddr_dl *)(ifa + 1);
113 sdl->sdl_len = socksize;
114 sdl->sdl_family = AF_LINK;
115 bcopy(ifp->if_name, sdl->sdl_data, namelen);
116 bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
117 sdl->sdl_nlen = (namelen += unitlen);
118 sdl->sdl_index = ifp->if_index;
119 sdl->sdl_type = ifp->if_type;
120 ifnet_addrs[if_index - 1] = ifa;
121 ifa->ifa_ifp = ifp;
122 ifa->ifa_next = ifp->if_addrlist;
123 ifa->ifa_rtrequest = link_rtrequest;
124 ifp->if_addrlist = ifa;
125 ifa->ifa_addr = (struct sockaddr *)sdl;
126 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
127 ifa->ifa_netmask = (struct sockaddr *)sdl;
128 sdl->sdl_len = masklen;
129 while (namelen != 0)
130 sdl->sdl_data[--namelen] = 0xff;
131 }
132 /* XXX -- Temporary fix before changing 10 ethernet drivers */
133 if (ifp->if_output == ether_output)
134 ether_ifattach(ifp);
135 }
136 /*
137 * Locate an interface based on a complete address.
138 */
139 /*ARGSUSED*/
140 struct ifaddr *
ifa_ifwithaddr(addr)141 ifa_ifwithaddr(addr)
142 register struct sockaddr *addr;
143 {
144 register struct ifnet *ifp;
145 register struct ifaddr *ifa;
146
147 #define equal(a1, a2) \
148 (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
149 for (ifp = ifnet; ifp; ifp = ifp->if_next)
150 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
151 if (ifa->ifa_addr->sa_family != addr->sa_family)
152 continue;
153 if (equal(addr, ifa->ifa_addr))
154 return (ifa);
155 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
156 equal(ifa->ifa_broadaddr, addr))
157 return (ifa);
158 }
159 return ((struct ifaddr *)0);
160 }
161 /*
162 * Locate the point to point interface with a given destination address.
163 */
164 /*ARGSUSED*/
165 struct ifaddr *
ifa_ifwithdstaddr(addr)166 ifa_ifwithdstaddr(addr)
167 register struct sockaddr *addr;
168 {
169 register struct ifnet *ifp;
170 register struct ifaddr *ifa;
171
172 for (ifp = ifnet; ifp; ifp = ifp->if_next)
173 if (ifp->if_flags & IFF_POINTOPOINT)
174 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
175 if (ifa->ifa_addr->sa_family != addr->sa_family ||
176 ifa->ifa_dstaddr == NULL)
177 continue;
178 if (equal(addr, ifa->ifa_dstaddr))
179 return (ifa);
180 }
181 return ((struct ifaddr *)0);
182 }
183
184 /*
185 * Find an interface on a specific network. If many, choice
186 * is most specific found.
187 */
188 struct ifaddr *
ifa_ifwithnet(addr)189 ifa_ifwithnet(addr)
190 struct sockaddr *addr;
191 {
192 register struct ifnet *ifp;
193 register struct ifaddr *ifa;
194 struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
195 u_int af = addr->sa_family;
196 char *addr_data = addr->sa_data, *cplim;
197
198 if (af == AF_LINK) {
199 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
200 if (sdl->sdl_index && sdl->sdl_index <= if_index)
201 return (ifnet_addrs[sdl->sdl_index - 1]);
202 }
203 for (ifp = ifnet; ifp; ifp = ifp->if_next)
204 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
205 register char *cp, *cp2, *cp3;
206
207 if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
208 next: continue;
209 cp = addr_data;
210 cp2 = ifa->ifa_addr->sa_data;
211 cp3 = ifa->ifa_netmask->sa_data;
212 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
213 while (cp3 < cplim)
214 if ((*cp++ ^ *cp2++) & *cp3++)
215 goto next;
216 if (ifa_maybe == 0 ||
217 rn_refines((caddr_t)ifa->ifa_netmask,
218 (caddr_t)ifa_maybe->ifa_netmask))
219 ifa_maybe = ifa;
220 }
221 return (ifa_maybe);
222 }
223
224 /*
225 * Find an interface using a specific address family
226 */
227 struct ifaddr *
ifa_ifwithaf(af)228 ifa_ifwithaf(af)
229 register int af;
230 {
231 register struct ifnet *ifp;
232 register struct ifaddr *ifa;
233
234 for (ifp = ifnet; ifp; ifp = ifp->if_next)
235 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
236 if (ifa->ifa_addr->sa_family == af)
237 return (ifa);
238 return ((struct ifaddr *)0);
239 }
240
241 /*
242 * Find an interface address specific to an interface best matching
243 * a given address.
244 */
245 struct ifaddr *
ifaof_ifpforaddr(addr,ifp)246 ifaof_ifpforaddr(addr, ifp)
247 struct sockaddr *addr;
248 register struct ifnet *ifp;
249 {
250 register struct ifaddr *ifa;
251 register char *cp, *cp2, *cp3;
252 register char *cplim;
253 struct ifaddr *ifa_maybe = 0;
254 u_int af = addr->sa_family;
255
256 if (af >= AF_MAX)
257 return (0);
258 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
259 if (ifa->ifa_addr->sa_family != af)
260 continue;
261 ifa_maybe = ifa;
262 if (ifa->ifa_netmask == 0) {
263 if (equal(addr, ifa->ifa_addr) ||
264 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
265 return (ifa);
266 continue;
267 }
268 cp = addr->sa_data;
269 cp2 = ifa->ifa_addr->sa_data;
270 cp3 = ifa->ifa_netmask->sa_data;
271 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
272 for (; cp3 < cplim; cp3++)
273 if ((*cp++ ^ *cp2++) & *cp3)
274 break;
275 if (cp3 == cplim)
276 return (ifa);
277 }
278 return (ifa_maybe);
279 }
280
281 #include <net/route.h>
282
283 /*
284 * Default action when installing a route with a Link Level gateway.
285 * Lookup an appropriate real ifa to point to.
286 * This should be moved to /sys/net/link.c eventually.
287 */
288 void
link_rtrequest(cmd,rt,sa)289 link_rtrequest(cmd, rt, sa)
290 int cmd;
291 register struct rtentry *rt;
292 struct sockaddr *sa;
293 {
294 register struct ifaddr *ifa;
295 struct sockaddr *dst;
296 struct ifnet *ifp;
297
298 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
299 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
300 return;
301 if (ifa = ifaof_ifpforaddr(dst, ifp)) {
302 IFAFREE(rt->rt_ifa);
303 rt->rt_ifa = ifa;
304 ifa->ifa_refcnt++;
305 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
306 ifa->ifa_rtrequest(cmd, rt, sa);
307 }
308 }
309
310 /*
311 * Mark an interface down and notify protocols of
312 * the transition.
313 * NOTE: must be called at splnet or eqivalent.
314 */
315 void
if_down(ifp)316 if_down(ifp)
317 register struct ifnet *ifp;
318 {
319 register struct ifaddr *ifa;
320
321 ifp->if_flags &= ~IFF_UP;
322 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
323 pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
324 if_qflush(&ifp->if_snd);
325 rt_ifmsg(ifp);
326 }
327
328 /*
329 * Mark an interface up and notify protocols of
330 * the transition.
331 * NOTE: must be called at splnet or eqivalent.
332 */
333 void
if_up(ifp)334 if_up(ifp)
335 register struct ifnet *ifp;
336 {
337 register struct ifaddr *ifa;
338
339 ifp->if_flags |= IFF_UP;
340 #ifdef notyet
341 /* this has no effect on IP, and will kill all iso connections XXX */
342 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
343 pfctlinput(PRC_IFUP, ifa->ifa_addr);
344 #endif
345 rt_ifmsg(ifp);
346 }
347
348 /*
349 * Flush an interface queue.
350 */
351 void
if_qflush(ifq)352 if_qflush(ifq)
353 register struct ifqueue *ifq;
354 {
355 register struct mbuf *m, *n;
356
357 n = ifq->ifq_head;
358 while (m = n) {
359 n = m->m_act;
360 m_freem(m);
361 }
362 ifq->ifq_head = 0;
363 ifq->ifq_tail = 0;
364 ifq->ifq_len = 0;
365 }
366
367 /*
368 * Handle interface watchdog timer routines. Called
369 * from softclock, we decrement timers (if set) and
370 * call the appropriate interface routine on expiration.
371 */
372 void
if_slowtimo(arg)373 if_slowtimo(arg)
374 void *arg;
375 {
376 register struct ifnet *ifp;
377 int s = splimp();
378
379 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
380 if (ifp->if_timer == 0 || --ifp->if_timer)
381 continue;
382 if (ifp->if_watchdog)
383 (*ifp->if_watchdog)(ifp->if_unit);
384 }
385 splx(s);
386 timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
387 }
388
389 /*
390 * Map interface name to
391 * interface structure pointer.
392 */
393 struct ifnet *
ifunit(name)394 ifunit(name)
395 register char *name;
396 {
397 register char *cp;
398 register struct ifnet *ifp;
399 int unit;
400 unsigned len;
401 char *ep, c;
402
403 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
404 if (*cp >= '0' && *cp <= '9')
405 break;
406 if (*cp == '\0' || cp == name + IFNAMSIZ)
407 return ((struct ifnet *)0);
408 /*
409 * Save first char of unit, and pointer to it,
410 * so we can put a null there to avoid matching
411 * initial substrings of interface names.
412 */
413 len = cp - name + 1;
414 c = *cp;
415 ep = cp;
416 for (unit = 0; *cp >= '0' && *cp <= '9'; )
417 unit = unit * 10 + *cp++ - '0';
418 *ep = 0;
419 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
420 if (bcmp(ifp->if_name, name, len))
421 continue;
422 if (unit == ifp->if_unit)
423 break;
424 }
425 *ep = c;
426 return (ifp);
427 }
428
429 /*
430 * Interface ioctls.
431 */
432 int
ifioctl(so,cmd,data,p)433 ifioctl(so, cmd, data, p)
434 struct socket *so;
435 u_long cmd;
436 caddr_t data;
437 struct proc *p;
438 {
439 register struct ifnet *ifp;
440 register struct ifreq *ifr;
441 int error;
442
443 switch (cmd) {
444
445 case SIOCGIFCONF:
446 case OSIOCGIFCONF:
447 return (ifconf(cmd, data));
448 }
449 ifr = (struct ifreq *)data;
450 ifp = ifunit(ifr->ifr_name);
451 if (ifp == 0)
452 return (ENXIO);
453 switch (cmd) {
454
455 case SIOCGIFFLAGS:
456 ifr->ifr_flags = ifp->if_flags;
457 break;
458
459 case SIOCGIFMETRIC:
460 ifr->ifr_metric = ifp->if_metric;
461 break;
462
463 case SIOCSIFFLAGS:
464 if (error = suser(p->p_ucred, &p->p_acflag))
465 return (error);
466 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
467 int s = splimp();
468 if_down(ifp);
469 splx(s);
470 }
471 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
472 int s = splimp();
473 if_up(ifp);
474 splx(s);
475 }
476 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
477 (ifr->ifr_flags &~ IFF_CANTCHANGE);
478 if (ifp->if_ioctl)
479 (void) (*ifp->if_ioctl)(ifp, cmd, data);
480 break;
481
482 case SIOCSIFMETRIC:
483 if (error = suser(p->p_ucred, &p->p_acflag))
484 return (error);
485 ifp->if_metric = ifr->ifr_metric;
486 break;
487
488 case SIOCADDMULTI:
489 case SIOCDELMULTI:
490 if (error = suser(p->p_ucred, &p->p_acflag))
491 return (error);
492 if (ifp->if_ioctl == NULL)
493 return (EOPNOTSUPP);
494 return ((*ifp->if_ioctl)(ifp, cmd, data));
495
496 default:
497 if (so->so_proto == 0)
498 return (EOPNOTSUPP);
499 #ifndef COMPAT_43
500 return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
501 cmd, data, ifp));
502 #else
503 {
504 int ocmd = cmd;
505
506 switch (cmd) {
507
508 case SIOCSIFDSTADDR:
509 case SIOCSIFADDR:
510 case SIOCSIFBRDADDR:
511 case SIOCSIFNETMASK:
512 #if BYTE_ORDER != BIG_ENDIAN
513 if (ifr->ifr_addr.sa_family == 0 &&
514 ifr->ifr_addr.sa_len < 16) {
515 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
516 ifr->ifr_addr.sa_len = 16;
517 }
518 #else
519 if (ifr->ifr_addr.sa_len == 0)
520 ifr->ifr_addr.sa_len = 16;
521 #endif
522 break;
523
524 case OSIOCGIFADDR:
525 cmd = SIOCGIFADDR;
526 break;
527
528 case OSIOCGIFDSTADDR:
529 cmd = SIOCGIFDSTADDR;
530 break;
531
532 case OSIOCGIFBRDADDR:
533 cmd = SIOCGIFBRDADDR;
534 break;
535
536 case OSIOCGIFNETMASK:
537 cmd = SIOCGIFNETMASK;
538 }
539 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
540 cmd, data, ifp));
541 switch (ocmd) {
542
543 case OSIOCGIFADDR:
544 case OSIOCGIFDSTADDR:
545 case OSIOCGIFBRDADDR:
546 case OSIOCGIFNETMASK:
547 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
548 }
549 return (error);
550
551 }
552 #endif
553 }
554 return (0);
555 }
556
557 /*
558 * Return interface configuration
559 * of system. List may be used
560 * in later ioctl's (above) to get
561 * other information.
562 */
563 /*ARGSUSED*/
564 int
ifconf(cmd,data)565 ifconf(cmd, data)
566 int cmd;
567 caddr_t data;
568 {
569 register struct ifconf *ifc = (struct ifconf *)data;
570 register struct ifnet *ifp = ifnet;
571 register struct ifaddr *ifa;
572 register char *cp, *ep;
573 struct ifreq ifr, *ifrp;
574 int space = ifc->ifc_len, error = 0;
575
576 ifrp = ifc->ifc_req;
577 ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
578 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
579 strncpy(ifr.ifr_name, ifp->if_name, sizeof (ifr.ifr_name) - 2);
580 for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
581 continue;
582 *cp++ = '0' + ifp->if_unit; *cp = '\0';
583 if ((ifa = ifp->if_addrlist) == 0) {
584 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
585 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
586 sizeof (ifr));
587 if (error)
588 break;
589 space -= sizeof (ifr), ifrp++;
590 } else
591 for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
592 register struct sockaddr *sa = ifa->ifa_addr;
593 #ifdef COMPAT_43
594 if (cmd == OSIOCGIFCONF) {
595 struct osockaddr *osa =
596 (struct osockaddr *)&ifr.ifr_addr;
597 ifr.ifr_addr = *sa;
598 osa->sa_family = sa->sa_family;
599 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
600 sizeof (ifr));
601 ifrp++;
602 } else
603 #endif
604 if (sa->sa_len <= sizeof(*sa)) {
605 ifr.ifr_addr = *sa;
606 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
607 sizeof (ifr));
608 ifrp++;
609 } else {
610 space -= sa->sa_len - sizeof(*sa);
611 if (space < sizeof (ifr))
612 break;
613 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
614 sizeof (ifr.ifr_name));
615 if (error == 0)
616 error = copyout((caddr_t)sa,
617 (caddr_t)&ifrp->ifr_addr, sa->sa_len);
618 ifrp = (struct ifreq *)
619 (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
620 }
621 if (error)
622 break;
623 space -= sizeof (ifr);
624 }
625 }
626 ifc->ifc_len -= space;
627 return (error);
628 }
629
630 static char *
sprint_d(n,buf,buflen)631 sprint_d(n, buf, buflen)
632 u_int n;
633 char *buf;
634 int buflen;
635 {
636 register char *cp = buf + buflen - 1;
637
638 *cp = 0;
639 do {
640 cp--;
641 *cp = "0123456789"[n % 10];
642 n /= 10;
643 } while (n != 0);
644 return (cp);
645 }
646