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