Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/net/if.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/net/if.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -p -r1.1.1.1 -r1.1.1.2 --- src/sys/net/if.c 1993/03/21 09:45:37 1.1.1.1 +++ src/sys/net/if.c 1998/03/01 02:10:06 1.1.1.2 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1980, 1986 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1980, 1986, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,27 +30,25 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)if.c 7.14 (Berkeley) 4/20/91 + * @(#)if.c 8.3 (Berkeley) 1/4/94 */ -#include "param.h" -#include "mbuf.h" -#include "systm.h" -#include "socket.h" -#include "socketvar.h" -#include "protosw.h" -#include "proc.h" -#include "kernel.h" -#include "ioctl.h" - -#include "if.h" -#include "af.h" -#include "if_dl.h" -#include "if_types.h" - -#include "ether.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include int ifqmaxlen = IFQ_MAXLEN; +void if_slowtimo __P((void *arg)); /* * Network interface utility routines. @@ -58,7 +56,7 @@ int ifqmaxlen = IFQ_MAXLEN; * Routines with ifa_ifwith* names take sockaddr *'s as * parameters. */ - +void ifinit() { register struct ifnet *ifp; @@ -66,13 +64,14 @@ ifinit() for (ifp = ifnet; ifp; ifp = ifp->if_next) if (ifp->if_snd.ifq_maxlen == 0) ifp->if_snd.ifq_maxlen = ifqmaxlen; - if_slowtimo(); + if_slowtimo(0); } #ifdef vax /* * Call each interface on a Unibus reset. */ +void ifubareset(uban) int uban; { @@ -86,23 +85,24 @@ ifubareset(uban) int if_index = 0; struct ifaddr **ifnet_addrs; -static char *sprint_d(); +static char *sprint_d __P((u_int, char *, int)); /* * Attach an interface to the * list of "active" interfaces. */ +void if_attach(ifp) struct ifnet *ifp; { unsigned socksize, ifasize; - int namelen, unitlen; + int namelen, unitlen, masklen, ether_output(); char workbuf[12], *unitname; register struct ifnet **p = &ifnet; register struct sockaddr_dl *sdl; register struct ifaddr *ifa; static int if_indexlim = 8; - extern link_rtrequest(), ether_output(); + extern void link_rtrequest(); while (*p) p = &((*p)->if_next); @@ -118,12 +118,6 @@ if_attach(ifp) } ifnet_addrs = q; } - /* XXX -- Temporary fix before changing 10 ethernet drivers */ - if (ifp->if_output == ether_output) { - ifp->if_type = IFT_ETHER; - ifp->if_addrlen = 6; - ifp->if_hdrlen = 14; - } /* * create a Link Level name for this device */ @@ -131,35 +125,39 @@ if_attach(ifp) namelen = strlen(ifp->if_name); unitlen = strlen(unitname); #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) - socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) + - unitlen + namelen + ifp->if_addrlen; + masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + + unitlen + namelen; + socksize = masklen + ifp->if_addrlen; #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) socksize = ROUNDUP(socksize); if (socksize < sizeof(*sdl)) socksize = sizeof(*sdl); ifasize = sizeof(*ifa) + 2 * socksize; - ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); - if (ifa == 0) - return; - ifnet_addrs[if_index - 1] = ifa; - bzero((caddr_t)ifa, ifasize); - sdl = (struct sockaddr_dl *)(ifa + 1); - ifa->ifa_addr = (struct sockaddr *)sdl; - ifa->ifa_ifp = ifp; - sdl->sdl_len = socksize; - sdl->sdl_family = AF_LINK; - bcopy(ifp->if_name, sdl->sdl_data, namelen); - bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen); - sdl->sdl_nlen = (namelen += unitlen); - sdl->sdl_index = ifp->if_index; - sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); - ifa->ifa_netmask = (struct sockaddr *)sdl; - sdl->sdl_len = socksize - ifp->if_addrlen; - while (namelen != 0) - sdl->sdl_data[--namelen] = 0xff; - ifa->ifa_next = ifp->if_addrlist; - ifa->ifa_rtrequest = link_rtrequest; - ifp->if_addrlist = ifa; + if (ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK)) { + bzero((caddr_t)ifa, ifasize); + sdl = (struct sockaddr_dl *)(ifa + 1); + sdl->sdl_len = socksize; + sdl->sdl_family = AF_LINK; + bcopy(ifp->if_name, sdl->sdl_data, namelen); + bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen); + sdl->sdl_nlen = (namelen += unitlen); + sdl->sdl_index = ifp->if_index; + sdl->sdl_type = ifp->if_type; + ifnet_addrs[if_index - 1] = ifa; + ifa->ifa_ifp = ifp; + ifa->ifa_next = ifp->if_addrlist; + ifa->ifa_rtrequest = link_rtrequest; + ifp->if_addrlist = ifa; + ifa->ifa_addr = (struct sockaddr *)sdl; + sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); + ifa->ifa_netmask = (struct sockaddr *)sdl; + sdl->sdl_len = masklen; + while (namelen != 0) + sdl->sdl_data[--namelen] = 0xff; + } + /* XXX -- Temporary fix before changing 10 ethernet drivers */ + if (ifp->if_output == ether_output) + ether_ifattach(ifp); } /* * Locate an interface based on a complete address. @@ -210,7 +208,7 @@ ifa_ifwithdstaddr(addr) /* * Find an interface on a specific network. If many, choice - * is first found. + * is most specific found. */ struct ifaddr * ifa_ifwithnet(addr) @@ -218,10 +216,10 @@ ifa_ifwithnet(addr) { register struct ifnet *ifp; register struct ifaddr *ifa; + struct ifaddr *ifa_maybe = (struct ifaddr *) 0; u_int af = addr->sa_family; + char *addr_data = addr->sa_data, *cplim; - if (af >= AF_MAX) - return (0); if (af == AF_LINK) { register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; if (sdl->sdl_index && sdl->sdl_index <= if_index) @@ -230,20 +228,22 @@ ifa_ifwithnet(addr) for (ifp = ifnet; ifp; ifp = ifp->if_next) for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { register char *cp, *cp2, *cp3; - register char *cplim; + if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) - continue; - cp = addr->sa_data; + next: continue; + cp = addr_data; cp2 = ifa->ifa_addr->sa_data; cp3 = ifa->ifa_netmask->sa_data; cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; - for (; cp3 < cplim; cp3++) - if ((*cp++ ^ *cp2++) & *cp3) - break; - if (cp3 == cplim) - return (ifa); + while (cp3 < cplim) + if ((*cp++ ^ *cp2++) & *cp3++) + goto next; + if (ifa_maybe == 0 || + rn_refines((caddr_t)ifa->ifa_netmask, + (caddr_t)ifa_maybe->ifa_netmask)) + ifa_maybe = ifa; } - return ((struct ifaddr *)0); + return (ifa_maybe); } /* @@ -302,25 +302,31 @@ ifaof_ifpforaddr(addr, ifp) } return (ifa_maybe); } -#include "route.h" + +#include + /* * Default action when installing a route with a Link Level gateway. * Lookup an appropriate real ifa to point to. * This should be moved to /sys/net/link.c eventually. */ +void link_rtrequest(cmd, rt, sa) -register struct rtentry *rt; -struct sockaddr *sa; + int cmd; + register struct rtentry *rt; + struct sockaddr *sa; { register struct ifaddr *ifa; struct sockaddr *dst; - struct ifnet *ifp, *oldifnet = ifnet; + struct ifnet *ifp; if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) return; if (ifa = ifaof_ifpforaddr(dst, ifp)) { + IFAFREE(rt->rt_ifa); rt->rt_ifa = ifa; + ifa->ifa_refcnt++; if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) ifa->ifa_rtrequest(cmd, rt, sa); } @@ -331,6 +337,7 @@ struct sockaddr *sa; * the transition. * NOTE: must be called at splnet or eqivalent. */ +void if_down(ifp) register struct ifnet *ifp; { @@ -340,11 +347,33 @@ if_down(ifp) for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) pfctlinput(PRC_IFDOWN, ifa->ifa_addr); if_qflush(&ifp->if_snd); + rt_ifmsg(ifp); +} + +/* + * Mark an interface up and notify protocols of + * the transition. + * NOTE: must be called at splnet or eqivalent. + */ +void +if_up(ifp) + register struct ifnet *ifp; +{ + register struct ifaddr *ifa; + + ifp->if_flags |= IFF_UP; +#ifdef notyet + /* this has no effect on IP, and will kill all iso connections XXX */ + for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) + pfctlinput(PRC_IFUP, ifa->ifa_addr); +#endif + rt_ifmsg(ifp); } /* * Flush an interface queue. */ +void if_qflush(ifq) register struct ifqueue *ifq; { @@ -365,7 +394,9 @@ if_qflush(ifq) * from softclock, we decrement timers (if set) and * call the appropriate interface routine on expiration. */ -if_slowtimo() +void +if_slowtimo(arg) + void *arg; { register struct ifnet *ifp; int s = splimp(); @@ -377,7 +408,7 @@ if_slowtimo() (*ifp->if_watchdog)(ifp->if_unit); } splx(s); - timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); + timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ); } /* @@ -423,6 +454,7 @@ ifunit(name) /* * Interface ioctls. */ +int ifioctl(so, cmd, data, p) struct socket *so; int cmd; @@ -438,17 +470,6 @@ ifioctl(so, cmd, data, p) case SIOCGIFCONF: case OSIOCGIFCONF: return (ifconf(cmd, data)); - -#if defined(INET) && NETHER > 0 - case SIOCSARP: - case SIOCDARP: - if (error = suser(p->p_ucred, &p->p_acflag)) - return (error); - /* FALL THROUGH */ - case SIOCGARP: - case OSIOCGARP: - return (arpioctl(cmd, data)); -#endif } ifr = (struct ifreq *)data; ifp = ifunit(ifr->ifr_name); @@ -472,6 +493,11 @@ ifioctl(so, cmd, data, p) if_down(ifp); splx(s); } + if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { + int s = splimp(); + if_up(ifp); + splx(s); + } ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | (ifr->ifr_flags &~ IFF_CANTCHANGE); if (ifp->if_ioctl) @@ -484,6 +510,14 @@ ifioctl(so, cmd, data, p) ifp->if_metric = ifr->ifr_metric; break; + case SIOCADDMULTI: + case SIOCDELMULTI: + if (error = suser(p->p_ucred, &p->p_acflag)) + return (error); + if (ifp->if_ioctl == NULL) + return (EOPNOTSUPP); + return ((*ifp->if_ioctl)(ifp, cmd, data)); + default: if (so->so_proto == 0) return (EOPNOTSUPP); @@ -552,6 +586,7 @@ ifioctl(so, cmd, data, p) * other information. */ /*ARGSUSED*/ +int ifconf(cmd, data) int cmd; caddr_t data; @@ -566,13 +601,14 @@ ifconf(cmd, data) ifrp = ifc->ifc_req; ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { - bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); + strncpy(ifr.ifr_name, ifp->if_name, sizeof (ifr.ifr_name) - 2); for (cp = ifr.ifr_name; cp < ep && *cp; cp++) - ; + continue; *cp++ = '0' + ifp->if_unit; *cp = '\0'; if ((ifa = ifp->if_addrlist) == 0) { bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); - error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); + error = copyout((caddr_t)&ifr, (caddr_t)ifrp, + sizeof (ifr)); if (error) break; space -= sizeof (ifr), ifrp++;