1 /* if.c 6.6 85/04/01 */ 2 3 #include "param.h" 4 #include "systm.h" 5 #include "socket.h" 6 #include "socketvar.h" 7 #include "protosw.h" 8 #include "dir.h" 9 #include "user.h" 10 #include "kernel.h" 11 #include "ioctl.h" 12 #include "errno.h" 13 14 #include "if.h" 15 #include "af.h" 16 17 #include "ether.h" 18 19 int ifqmaxlen = IFQ_MAXLEN; 20 21 /* 22 * Network interface utility routines. 23 * 24 * Routines with ifa_ifwith* names take sockaddr *'s as 25 * parameters. 26 */ 27 28 ifinit() 29 { 30 register struct ifnet *ifp; 31 32 for (ifp = ifnet; ifp; ifp = ifp->if_next) 33 if (ifp->if_init) { 34 (*ifp->if_init)(ifp->if_unit); 35 if (ifp->if_snd.ifq_maxlen == 0) 36 ifp->if_snd.ifq_maxlen = ifqmaxlen; 37 } 38 if_slowtimo(); 39 } 40 41 #ifdef vax 42 /* 43 * Call each interface on a Unibus reset. 44 */ 45 ifubareset(uban) 46 int uban; 47 { 48 register struct ifnet *ifp; 49 50 for (ifp = ifnet; ifp; ifp = ifp->if_next) 51 if (ifp->if_reset) 52 (*ifp->if_reset)(ifp->if_unit, uban); 53 } 54 #endif 55 56 /* 57 * Attach an interface to the 58 * list of "active" interfaces. 59 */ 60 if_attach(ifp) 61 struct ifnet *ifp; 62 { 63 register struct ifnet **p = &ifnet; 64 65 while (*p) 66 p = &((*p)->if_next); 67 *p = ifp; 68 } 69 70 /* 71 * Locate an interface based on a complete address. 72 */ 73 /*ARGSUSED*/ 74 struct ifaddr * 75 ifa_ifwithaddr(addr) 76 struct sockaddr *addr; 77 { 78 register struct ifnet *ifp; 79 register struct ifaddr *ifa; 80 81 #define equal(a1, a2) \ 82 (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) 83 for (ifp = ifnet; ifp; ifp = ifp->if_next) 84 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 85 if (ifa->ifa_addr.sa_family != addr->sa_family) 86 continue; 87 if (equal(&ifa->ifa_addr, addr)) 88 return (ifa); 89 if ((ifp->if_flags & IFF_BROADCAST) && 90 equal(&ifa->ifa_broadaddr, addr)) 91 return (ifa); 92 } 93 return ((struct ifaddr *)0); 94 } 95 96 /* 97 * Find an interface on a specific network. If many, choice 98 * is first found. 99 */ 100 struct ifaddr * 101 ifa_ifwithnet(addr) 102 register struct sockaddr *addr; 103 { 104 register struct ifnet *ifp; 105 register struct ifaddr *ifa; 106 register u_int af = addr->sa_family; 107 register int (*netmatch)(); 108 109 if (af >= AF_MAX) 110 return (0); 111 netmatch = afswitch[af].af_netmatch; 112 for (ifp = ifnet; ifp; ifp = ifp->if_next) 113 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 114 if (ifa->ifa_addr.sa_family != addr->sa_family) 115 continue; 116 if ((*netmatch)(&ifa->ifa_addr, addr)) 117 return (ifa); 118 } 119 return ((struct ifaddr *)0); 120 } 121 122 /* 123 * Find an interface using a specific address family 124 */ 125 struct ifaddr * 126 ifa_ifwithaf(af) 127 register int af; 128 { 129 register struct ifnet *ifp; 130 register struct ifaddr *ifa; 131 132 for (ifp = ifnet; ifp; ifp = ifp->if_next) 133 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 134 if (ifa->ifa_addr.sa_family == af) 135 return (ifa); 136 return ((struct ifaddr *)0); 137 } 138 139 /* 140 * Mark an interface down and notify protocols of 141 * the transition. 142 * NOTE: must be called at splnet or eqivalent. 143 */ 144 if_down(ifp) 145 register struct ifnet *ifp; 146 { 147 register struct ifaddr *ifa; 148 149 ifp->if_flags &= ~IFF_UP; 150 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 151 pfctlinput(PRC_IFDOWN, (caddr_t)&ifa->ifa_addr); 152 } 153 154 /* 155 * Handle interface watchdog timer routines. Called 156 * from softclock, we decrement timers (if set) and 157 * call the appropriate interface routine on expiration. 158 */ 159 if_slowtimo() 160 { 161 register struct ifnet *ifp; 162 163 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 164 if (ifp->if_timer == 0 || --ifp->if_timer) 165 continue; 166 if (ifp->if_watchdog) 167 (*ifp->if_watchdog)(ifp->if_unit); 168 } 169 timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 170 } 171 172 /* 173 * Map interface name to 174 * interface structure pointer. 175 */ 176 struct ifnet * 177 ifunit(name) 178 register char *name; 179 { 180 register char *cp; 181 register struct ifnet *ifp; 182 int unit; 183 184 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 185 if (*cp >= '0' && *cp <= '9') 186 break; 187 if (*cp == '\0' || cp == name + IFNAMSIZ) 188 return ((struct ifnet *)0); 189 unit = *cp - '0'; 190 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 191 if (bcmp(ifp->if_name, name, (unsigned)(cp - name))) 192 continue; 193 if (unit == ifp->if_unit) 194 break; 195 } 196 return (ifp); 197 } 198 199 /* 200 * Interface ioctls. 201 */ 202 ifioctl(so, cmd, data) 203 struct socket *so; 204 int cmd; 205 caddr_t data; 206 { 207 register struct ifnet *ifp; 208 register struct ifreq *ifr; 209 210 switch (cmd) { 211 212 case SIOCGIFCONF: 213 return (ifconf(cmd, data)); 214 215 #if defined(INET) && NETHER > 0 216 case SIOCSARP: 217 case SIOCDARP: 218 if (!suser()) 219 return (u.u_error); 220 /* FALL THROUGH */ 221 case SIOCGARP: 222 return (arpioctl(cmd, data)); 223 #endif 224 } 225 ifr = (struct ifreq *)data; 226 ifp = ifunit(ifr->ifr_name); 227 if (ifp == 0) 228 return (ENXIO); 229 switch (cmd) { 230 231 case SIOCGIFFLAGS: 232 ifr->ifr_flags = ifp->if_flags; 233 break; 234 235 case SIOCSIFFLAGS: 236 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 237 int s = splimp(); 238 if_down(ifp); 239 splx(s); 240 } 241 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 242 (ifr->ifr_flags &~ IFF_CANTCHANGE); 243 break; 244 245 default: 246 if (so->so_proto == 0) 247 return (EOPNOTSUPP); 248 return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 249 cmd, data, ifp)); 250 } 251 return (0); 252 } 253 254 /* 255 * Return interface configuration 256 * of system. List may be used 257 * in later ioctl's (above) to get 258 * other information. 259 */ 260 /*ARGSUSED*/ 261 ifconf(cmd, data) 262 int cmd; 263 caddr_t data; 264 { 265 register struct ifconf *ifc = (struct ifconf *)data; 266 register struct ifnet *ifp = ifnet; 267 register struct ifaddr *ifa; 268 register char *cp, *ep; 269 struct ifreq ifr, *ifrp; 270 int space = ifc->ifc_len, error = 0; 271 272 ifrp = ifc->ifc_req; 273 ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 274 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 275 bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 276 for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 277 ; 278 *cp++ = '0' + ifp->if_unit; *cp = '\0'; 279 if ((ifa = ifp->if_addrlist) == 0) { 280 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 281 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 282 if (error) 283 break; 284 space -= sizeof (ifr), ifrp++; 285 } else 286 for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 287 ifr.ifr_addr = ifa->ifa_addr; 288 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 289 if (error) 290 break; 291 space -= sizeof (ifr), ifrp++; 292 } 293 } 294 ifc->ifc_len -= space; 295 return (error); 296 } 297