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