1 /* if.c 6.5 84/08/28 */ 2 3 #include "param.h" 4 #include "systm.h" 5 #include "socket.h" 6 #include "protosw.h" 7 #include "dir.h" 8 #include "user.h" 9 #include "kernel.h" 10 #include "ioctl.h" 11 #include "errno.h" 12 13 #include "if.h" 14 #include "af.h" 15 16 #include "ether.h" 17 18 int ifqmaxlen = IFQ_MAXLEN; 19 20 /* 21 * Network interface utility routines. 22 * 23 * Routines with if_ifwith* names take sockaddr *'s as 24 * parameters. Other routines take value parameters, 25 * e.g. if_ifwithnet takes the network number. 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 ifnet * 75 if_ifwithaddr(addr) 76 struct sockaddr *addr; 77 { 78 register struct ifnet *ifp; 79 80 #define equal(a1, a2) \ 81 (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) 82 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 83 if (ifp->if_addr.sa_family != addr->sa_family) 84 continue; 85 if (equal(&ifp->if_addr, addr)) 86 break; 87 if ((ifp->if_flags & IFF_BROADCAST) && 88 equal(&ifp->if_broadaddr, addr)) 89 break; 90 } 91 return (ifp); 92 } 93 94 /* 95 * Find an interface on a specific network. If many, choice 96 * is first found. 97 */ 98 struct ifnet * 99 if_ifwithnet(addr) 100 register struct sockaddr *addr; 101 { 102 register struct ifnet *ifp; 103 register u_int af = addr->sa_family; 104 register int (*netmatch)(); 105 106 if (af >= AF_MAX) 107 return (0); 108 netmatch = afswitch[af].af_netmatch; 109 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 110 if (af != ifp->if_addr.sa_family) 111 continue; 112 if ((*netmatch)(addr, &ifp->if_addr)) 113 break; 114 } 115 return (ifp); 116 } 117 118 /* 119 * As above, but parameter is network number. 120 */ 121 struct ifnet * 122 if_ifonnetof(net) 123 register int net; 124 { 125 register struct ifnet *ifp; 126 127 for (ifp = ifnet; ifp; ifp = ifp->if_next) 128 if (ifp->if_net == net) 129 break; 130 return (ifp); 131 } 132 133 /* 134 * Find an interface using a specific address family 135 */ 136 struct ifnet * 137 if_ifwithaf(af) 138 register int af; 139 { 140 register struct ifnet *ifp; 141 142 for (ifp = ifnet; ifp; ifp = ifp->if_next) 143 if (ifp->if_addr.sa_family == af) 144 break; 145 return (ifp); 146 } 147 148 /* 149 * Mark an interface down and notify protocols of 150 * the transition. 151 * NOTE: must be called at splnet or eqivalent. 152 */ 153 if_down(ifp) 154 register struct ifnet *ifp; 155 { 156 157 ifp->if_flags &= ~IFF_UP; 158 pfctlinput(PRC_IFDOWN, (caddr_t)&ifp->if_addr); 159 } 160 161 /* 162 * Handle interface watchdog timer routines. Called 163 * from softclock, we decrement timers (if set) and 164 * call the appropriate interface routine on expiration. 165 */ 166 if_slowtimo() 167 { 168 register struct ifnet *ifp; 169 170 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 171 if (ifp->if_timer == 0 || --ifp->if_timer) 172 continue; 173 if (ifp->if_watchdog) 174 (*ifp->if_watchdog)(ifp->if_unit); 175 } 176 timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 177 } 178 179 /* 180 * Map interface name to 181 * interface structure pointer. 182 */ 183 struct ifnet * 184 ifunit(name) 185 register char *name; 186 { 187 register char *cp; 188 register struct ifnet *ifp; 189 int unit; 190 191 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 192 if (*cp >= '0' && *cp <= '9') 193 break; 194 if (*cp == '\0' || cp == name + IFNAMSIZ) 195 return ((struct ifnet *)0); 196 unit = *cp - '0'; 197 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 198 if (bcmp(ifp->if_name, name, (unsigned)(cp - name))) 199 continue; 200 if (unit == ifp->if_unit) 201 break; 202 } 203 return (ifp); 204 } 205 206 /* 207 * Interface ioctls. 208 */ 209 ifioctl(cmd, data) 210 int cmd; 211 caddr_t data; 212 { 213 register struct ifnet *ifp; 214 register struct ifreq *ifr; 215 216 switch (cmd) { 217 218 case SIOCGIFCONF: 219 return (ifconf(cmd, data)); 220 221 #if defined(INET) && NETHER > 0 222 case SIOCSARP: 223 case SIOCDARP: 224 if (!suser()) 225 return (u.u_error); 226 /* FALL THROUGH */ 227 case SIOCGARP: 228 return (arpioctl(cmd, data)); 229 #endif 230 231 case SIOCSIFADDR: 232 case SIOCSIFFLAGS: 233 case SIOCSIFDSTADDR: 234 if (!suser()) 235 return (u.u_error); 236 break; 237 } 238 ifr = (struct ifreq *)data; 239 ifp = ifunit(ifr->ifr_name); 240 if (ifp == 0) 241 return (ENXIO); 242 switch (cmd) { 243 244 case SIOCGIFADDR: 245 ifr->ifr_addr = ifp->if_addr; 246 break; 247 248 case SIOCGIFDSTADDR: 249 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 250 return (EINVAL); 251 ifr->ifr_dstaddr = ifp->if_dstaddr; 252 break; 253 254 case SIOCGIFFLAGS: 255 ifr->ifr_flags = ifp->if_flags; 256 break; 257 258 case SIOCSIFFLAGS: 259 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 260 int s = splimp(); 261 if_down(ifp); 262 splx(s); 263 } 264 ifp->if_flags = ifr->ifr_flags; 265 break; 266 267 default: 268 if (ifp->if_ioctl == 0) 269 return (EOPNOTSUPP); 270 return ((*ifp->if_ioctl)(ifp, cmd, data)); 271 } 272 return (0); 273 } 274 275 /* 276 * Return interface configuration 277 * of system. List may be used 278 * in later ioctl's (above) to get 279 * other information. 280 */ 281 /*ARGSUSED*/ 282 ifconf(cmd, data) 283 int cmd; 284 caddr_t data; 285 { 286 register struct ifconf *ifc = (struct ifconf *)data; 287 register struct ifnet *ifp = ifnet; 288 register char *cp, *ep; 289 struct ifreq ifr, *ifrp; 290 int space = ifc->ifc_len, error = 0; 291 292 ifrp = ifc->ifc_req; 293 ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 294 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 295 bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 296 for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 297 ; 298 *cp++ = '0' + ifp->if_unit; *cp = '\0'; 299 ifr.ifr_addr = ifp->if_addr; 300 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 301 if (error) 302 break; 303 space -= sizeof (ifr), ifrp++; 304 } 305 ifc->ifc_len -= space; 306 return (error); 307 } 308