X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/0c33c83235f2d8403e63e61da3f36153f038b032..5658e54ccedc665bd9eedaacab8aa1d857374c7b:/usr/src/sys/net/if.c diff --git a/usr/src/sys/net/if.c b/usr/src/sys/net/if.c index 2abb68c4d2..c04bff6445 100644 --- a/usr/src/sys/net/if.c +++ b/usr/src/sys/net/if.c @@ -1,25 +1,40 @@ -/* if.c 4.26 83/03/15 */ +/* + * Copyright (c) 1980, 1986 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of California at Berkeley. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. This software + * is provided ``as is'' without express or implied warranty. + * + * @(#)if.c 7.2 (Berkeley) %G% + */ + +#include "param.h" +#include "systm.h" +#include "socket.h" +#include "socketvar.h" +#include "protosw.h" +#include "dir.h" +#include "user.h" +#include "kernel.h" +#include "ioctl.h" +#include "errno.h" -#include "../h/param.h" -#include "../h/systm.h" -#include "../h/socket.h" -#include "../h/protosw.h" -#include "../h/time.h" -#include "../h/kernel.h" -#include "../h/ioctl.h" -#include "../h/errno.h" +#include "if.h" +#include "af.h" -#include "../net/if.h" -#include "../net/af.h" +#include "ether.h" int ifqmaxlen = IFQ_MAXLEN; /* * Network interface utility routines. * - * Routines with if_ifwith* names take sockaddr *'s as - * parameters. Other routines take value parameters, - * e.g. if_ifwithnet takes the network number. + * Routines with ifa_ifwith* names take sockaddr *'s as + * parameters. */ ifinit() @@ -27,15 +42,12 @@ ifinit() register struct ifnet *ifp; for (ifp = ifnet; ifp; ifp = ifp->if_next) - if (ifp->if_init) { - (*ifp->if_init)(ifp->if_unit); - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - } + if (ifp->if_snd.ifq_maxlen == 0) + ifp->if_snd.ifq_maxlen = ifqmaxlen; if_slowtimo(); } -#if vax +#ifdef vax /* * Call each interface on a Unibus reset. */ @@ -46,7 +58,7 @@ ifubareset(uban) for (ifp = ifnet; ifp; ifp = ifp->if_next) if (ifp->if_reset) - (*ifp->if_reset)(uban); + (*ifp->if_reset)(ifp->if_unit, uban); } #endif @@ -68,79 +80,93 @@ if_attach(ifp) * Locate an interface based on a complete address. */ /*ARGSUSED*/ -struct ifnet * -if_ifwithaddr(addr) +struct ifaddr * +ifa_ifwithaddr(addr) struct sockaddr *addr; { register struct ifnet *ifp; + register struct ifaddr *ifa; #define equal(a1, a2) \ (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) - for (ifp = ifnet; ifp; ifp = ifp->if_next) { - if (ifp->if_addr.sa_family != addr->sa_family) + for (ifp = ifnet; ifp; ifp = ifp->if_next) + for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { + if (ifa->ifa_addr.sa_family != addr->sa_family) continue; - if (equal(&ifp->if_addr, addr)) - break; + if (equal(&ifa->ifa_addr, addr)) + return (ifa); if ((ifp->if_flags & IFF_BROADCAST) && - equal(&ifp->if_broadaddr, addr)) - break; + equal(&ifa->ifa_broadaddr, addr)) + return (ifa); } - return (ifp); + return ((struct ifaddr *)0); +} +/* + * Locate the point to point interface with a given destination address. + */ +/*ARGSUSED*/ +struct ifaddr * +ifa_ifwithdstaddr(addr) + struct sockaddr *addr; +{ + register struct ifnet *ifp; + register struct ifaddr *ifa; + + for (ifp = ifnet; ifp; ifp = ifp->if_next) + if (ifp->if_flags & IFF_POINTOPOINT) + for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { + if (ifa->ifa_addr.sa_family != addr->sa_family) + continue; + if (equal(&ifa->ifa_dstaddr, addr)) + return (ifa); + } + return ((struct ifaddr *)0); } /* * Find an interface on a specific network. If many, choice * is first found. */ -struct ifnet * -if_ifwithnet(addr) +struct ifaddr * +ifa_ifwithnet(addr) register struct sockaddr *addr; { register struct ifnet *ifp; + register struct ifaddr *ifa; register u_int af = addr->sa_family; register int (*netmatch)(); if (af >= AF_MAX) return (0); netmatch = afswitch[af].af_netmatch; - for (ifp = ifnet; ifp; ifp = ifp->if_next) { - if (af != ifp->if_addr.sa_family) + for (ifp = ifnet; ifp; ifp = ifp->if_next) + for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { + if (ifa->ifa_addr.sa_family != addr->sa_family) continue; - if ((*netmatch)(addr, &ifp->if_addr)) - break; + if ((*netmatch)(&ifa->ifa_addr, addr)) + return (ifa); } - return (ifp); -} - -/* - * As above, but parameter is network number. - */ -struct ifnet * -if_ifonnetof(net) - register int net; -{ - register struct ifnet *ifp; - - for (ifp = ifnet; ifp; ifp = ifp->if_next) - if (ifp->if_net == net) - break; - return (ifp); + return ((struct ifaddr *)0); } +#ifdef notdef /* * Find an interface using a specific address family */ -struct ifnet * -if_ifwithaf(af) +struct ifaddr * +ifa_ifwithaf(af) register int af; { register struct ifnet *ifp; + register struct ifaddr *ifa; for (ifp = ifnet; ifp; ifp = ifp->if_next) - if (ifp->if_addr.sa_family == af) - break; - return (ifp); + for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) + if (ifa->ifa_addr.sa_family == af) + return (ifa); + return ((struct ifaddr *)0); } +#endif /* * Mark an interface down and notify protocols of @@ -150,9 +176,11 @@ if_ifwithaf(af) if_down(ifp) register struct ifnet *ifp; { + register struct ifaddr *ifa; ifp->if_flags &= ~IFF_UP; - pfctlinput(PRC_IFDOWN, (caddr_t)&ifp->if_addr); + for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) + pfctlinput(PRC_IFDOWN, &ifa->ifa_addr); } /* @@ -174,78 +202,97 @@ if_slowtimo() } /* - * Service a socket ioctl request directed - * to an interface. + * Map interface name to + * interface structure pointer. */ -ifrequest(cmd, data) - int cmd; - caddr_t data; +struct ifnet * +ifunit(name) + register char *name; { - register struct ifnet *ifp; - register struct ifreq *ifr; register char *cp; - int unit, s; + register struct ifnet *ifp; + int unit; - ifr = (struct ifreq *)data; - for (cp = ifr->ifr_name; *cp; cp++) + for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) if (*cp >= '0' && *cp <= '9') break; - if (*cp == 0) - return (ENXIO); /* couldn't find unit */ - unit = *cp - '0', *cp = 0; + if (*cp == '\0' || cp == name + IFNAMSIZ) + return ((struct ifnet *)0); + unit = *cp - '0'; for (ifp = ifnet; ifp; ifp = ifp->if_next) { - if (bcmp(ifp->if_name, ifr->ifr_name, cp - ifr->ifr_name)) + if (bcmp(ifp->if_name, name, (unsigned)(cp - name))) continue; if (unit == ifp->if_unit) - goto found; + break; } - return (ENXIO); - -found: - switch (cmd) { - - case SIOCGIFADDR: - ifr->ifr_addr = ifp->if_addr; - break; + return (ifp); +} - case SIOCSIFADDR: - if_rtinit(ifp, -1); /* delete previous route */ - s = splimp(); - ifp->if_addr = ifr->ifr_addr; - (*ifp->if_init)(unit); - splx(s); - break; +/* + * Interface ioctls. + */ +ifioctl(so, cmd, data) + struct socket *so; + int cmd; + caddr_t data; +{ + register struct ifnet *ifp; + register struct ifreq *ifr; - case SIOCGIFDSTADDR: - if ((ifp->if_flags & IFF_POINTOPOINT) == 0) - return (EINVAL); - ifr->ifr_dstaddr = ifp->if_dstaddr; - break; + switch (cmd) { - case SIOCSIFDSTADDR: - if ((ifp->if_flags & IFF_POINTOPOINT) == 0) - return (EINVAL); - s = splimp(); - ifp->if_dstaddr = ifr->ifr_dstaddr; - splx(s); - break; + case SIOCGIFCONF: + return (ifconf(cmd, data)); + +#if defined(INET) && NETHER > 0 + case SIOCSARP: + case SIOCDARP: + if (!suser()) + return (u.u_error); + /* FALL THROUGH */ + case SIOCGARP: + return (arpioctl(cmd, data)); +#endif + } + ifr = (struct ifreq *)data; + ifp = ifunit(ifr->ifr_name); + if (ifp == 0) + return (ENXIO); + switch (cmd) { case SIOCGIFFLAGS: ifr->ifr_flags = ifp->if_flags; break; + case SIOCGIFMETRIC: + ifr->ifr_metric = ifp->if_metric; + break; + case SIOCSIFFLAGS: - if ((ifr->ifr_flags & IFF_UP) == 0 && - (ifp->if_flags & IFF_UP)) { - s = splimp(); + if (!suser()) + return (u.u_error); + if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { + int s = splimp(); if_down(ifp); splx(s); } - ifp->if_flags = ifr->ifr_flags; + ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | + (ifr->ifr_flags &~ IFF_CANTCHANGE); + if (ifp->if_ioctl) + (void) (*ifp->if_ioctl)(ifp, cmd, data); + break; + + case SIOCSIFMETRIC: + if (!suser()) + return (u.u_error); + ifp->if_metric = ifr->ifr_metric; break; default: - return (EINVAL); + if (so->so_proto == 0) + return (EOPNOTSUPP); + return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, + cmd, data, ifp)); } return (0); } @@ -256,27 +303,39 @@ found: * in later ioctl's (above) to get * other information. */ +/*ARGSUSED*/ ifconf(cmd, data) int cmd; caddr_t data; { register struct ifconf *ifc = (struct ifconf *)data; register struct ifnet *ifp = ifnet; - register char *cp; - struct ifreq ifr; + register struct ifaddr *ifa; + register char *cp, *ep; + struct ifreq ifr, *ifrp; int space = ifc->ifc_len, error = 0; + 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)); - for (cp = ifr.ifr_name; *cp; cp++) + bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); + for (cp = ifr.ifr_name; cp < ep && *cp; cp++) ; - *cp = '0' + ifp->if_unit; - ifr.ifr_addr = ifp->if_addr; - error = copyout((caddr_t)&ifr, ifc->ifc_buf, sizeof (ifr)); - if (error) - break; - space -= sizeof (ifr); - ifc->ifc_req++; + *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)); + if (error) + break; + space -= sizeof (ifr), ifrp++; + } else + for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { + ifr.ifr_addr = ifa->ifa_addr; + error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); + if (error) + break; + space -= sizeof (ifr), ifrp++; + } } ifc->ifc_len -= space; return (error);