1 /* 2 * Copyright (c) 1980, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)if.c 7.6.1.1 (Berkeley) 02/17/89 18 */ 19 20 #include "param.h" 21 #include "mbuf.h" 22 #include "systm.h" 23 #include "socket.h" 24 #include "socketvar.h" 25 #include "protosw.h" 26 #include "dir.h" 27 #include "user.h" 28 #include "kernel.h" 29 #include "ioctl.h" 30 #include "errno.h" 31 32 #include "if.h" 33 #include "af.h" 34 35 #include "ether.h" 36 37 int ifqmaxlen = IFQ_MAXLEN; 38 39 /* 40 * Network interface utility routines. 41 * 42 * Routines with ifa_ifwith* names take sockaddr *'s as 43 * parameters. 44 */ 45 46 ifinit() 47 { 48 register struct ifnet *ifp; 49 50 for (ifp = ifnet; ifp; ifp = ifp->if_next) 51 if (ifp->if_snd.ifq_maxlen == 0) 52 ifp->if_snd.ifq_maxlen = ifqmaxlen; 53 if_slowtimo(); 54 } 55 56 #ifdef vax 57 /* 58 * Call each interface on a Unibus reset. 59 */ 60 ifubareset(uban) 61 int uban; 62 { 63 register struct ifnet *ifp; 64 65 for (ifp = ifnet; ifp; ifp = ifp->if_next) 66 if (ifp->if_reset) 67 (*ifp->if_reset)(ifp->if_unit, uban); 68 } 69 #endif 70 71 /* 72 * Attach an interface to the 73 * list of "active" interfaces. 74 */ 75 if_attach(ifp) 76 struct ifnet *ifp; 77 { 78 register struct ifnet **p = &ifnet; 79 80 while (*p) 81 p = &((*p)->if_next); 82 *p = ifp; 83 } 84 85 /* 86 * Locate an interface based on a complete address. 87 */ 88 /*ARGSUSED*/ 89 struct ifaddr * 90 ifa_ifwithaddr(addr) 91 struct sockaddr *addr; 92 { 93 register struct ifnet *ifp; 94 register struct ifaddr *ifa; 95 96 #define equal(a1, a2) \ 97 (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) 98 for (ifp = ifnet; ifp; ifp = ifp->if_next) 99 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 100 if (ifa->ifa_addr.sa_family != addr->sa_family) 101 continue; 102 if (equal(&ifa->ifa_addr, addr)) 103 return (ifa); 104 if ((ifp->if_flags & IFF_BROADCAST) && 105 equal(&ifa->ifa_broadaddr, addr)) 106 return (ifa); 107 } 108 return ((struct ifaddr *)0); 109 } 110 /* 111 * Locate the point to point interface with a given destination address. 112 */ 113 /*ARGSUSED*/ 114 struct ifaddr * 115 ifa_ifwithdstaddr(addr) 116 struct sockaddr *addr; 117 { 118 register struct ifnet *ifp; 119 register struct ifaddr *ifa; 120 121 for (ifp = ifnet; ifp; ifp = ifp->if_next) 122 if (ifp->if_flags & IFF_POINTOPOINT) 123 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 124 if (ifa->ifa_addr.sa_family != addr->sa_family) 125 continue; 126 if (equal(&ifa->ifa_dstaddr, addr)) 127 return (ifa); 128 } 129 return ((struct ifaddr *)0); 130 } 131 132 /* 133 * Find an interface on a specific network. If many, choice 134 * is first found. 135 */ 136 struct ifaddr * 137 ifa_ifwithnet(addr) 138 register struct sockaddr *addr; 139 { 140 register struct ifnet *ifp; 141 register struct ifaddr *ifa; 142 register u_int af = addr->sa_family; 143 register int (*netmatch)(); 144 145 if (af >= AF_MAX) 146 return (0); 147 netmatch = afswitch[af].af_netmatch; 148 for (ifp = ifnet; ifp; ifp = ifp->if_next) 149 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 150 if (ifa->ifa_addr.sa_family != addr->sa_family) 151 continue; 152 if ((*netmatch)(&ifa->ifa_addr, addr)) 153 return (ifa); 154 } 155 return ((struct ifaddr *)0); 156 } 157 158 #ifdef notdef 159 /* 160 * Find an interface using a specific address family 161 */ 162 struct ifaddr * 163 ifa_ifwithaf(af) 164 register int af; 165 { 166 register struct ifnet *ifp; 167 register struct ifaddr *ifa; 168 169 for (ifp = ifnet; ifp; ifp = ifp->if_next) 170 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 171 if (ifa->ifa_addr.sa_family == af) 172 return (ifa); 173 return ((struct ifaddr *)0); 174 } 175 #endif 176 177 /* 178 * Mark an interface down and notify protocols of 179 * the transition. 180 * NOTE: must be called at splnet or eqivalent. 181 */ 182 if_down(ifp) 183 register struct ifnet *ifp; 184 { 185 register struct ifaddr *ifa; 186 187 ifp->if_flags &= ~IFF_UP; 188 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 189 pfctlinput(PRC_IFDOWN, &ifa->ifa_addr); 190 if_qflush(&ifp->if_snd); 191 } 192 193 /* 194 * Flush an interface queue. 195 */ 196 if_qflush(ifq) 197 register struct ifqueue *ifq; 198 { 199 register struct mbuf *m, *n; 200 201 n = ifq->ifq_head; 202 while (m = n) { 203 n = m->m_act; 204 m_freem(m); 205 } 206 ifq->ifq_head = 0; 207 ifq->ifq_tail = 0; 208 ifq->ifq_len = 0; 209 } 210 211 /* 212 * Handle interface watchdog timer routines. Called 213 * from softclock, we decrement timers (if set) and 214 * call the appropriate interface routine on expiration. 215 */ 216 if_slowtimo() 217 { 218 register struct ifnet *ifp; 219 220 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 221 if (ifp->if_timer == 0 || --ifp->if_timer) 222 continue; 223 if (ifp->if_watchdog) 224 (*ifp->if_watchdog)(ifp->if_unit); 225 } 226 timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 227 } 228 229 /* 230 * Map interface name to 231 * interface structure pointer. 232 */ 233 struct ifnet * 234 ifunit(name) 235 register char *name; 236 { 237 register char *cp; 238 register struct ifnet *ifp; 239 int unit; 240 unsigned len; 241 char *ep, c; 242 243 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 244 if (*cp >= '0' && *cp <= '9') 245 break; 246 if (*cp == '\0' || cp == name + IFNAMSIZ) 247 return ((struct ifnet *)0); 248 /* 249 * Save first char of unit, and pointer to it, 250 * so we can put a null there to avoid matching 251 * initial substrings of interface names. 252 */ 253 len = cp - name + 1; 254 c = *cp; 255 ep = cp; 256 for (unit = 0; *cp >= '0' && *cp <= '9'; ) 257 unit = unit * 10 + *cp++ - '0'; 258 *ep = 0; 259 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 260 if (bcmp(ifp->if_name, name, len)) 261 continue; 262 if (unit == ifp->if_unit) 263 break; 264 } 265 *ep = c; 266 return (ifp); 267 } 268 269 /* 270 * Interface ioctls. 271 */ 272 ifioctl(so, cmd, data) 273 struct socket *so; 274 int cmd; 275 caddr_t data; 276 { 277 register struct ifnet *ifp; 278 register struct ifreq *ifr; 279 280 switch (cmd) { 281 282 case SIOCGIFCONF: 283 return (ifconf(cmd, data)); 284 285 #if defined(INET) && NETHER > 0 286 case SIOCSARP: 287 case SIOCDARP: 288 if (!suser()) 289 return (u.u_error); 290 /* FALL THROUGH */ 291 case SIOCGARP: 292 return (arpioctl(cmd, data)); 293 #endif 294 } 295 ifr = (struct ifreq *)data; 296 ifp = ifunit(ifr->ifr_name); 297 if (ifp == 0) 298 return (ENXIO); 299 switch (cmd) { 300 301 case SIOCGIFFLAGS: 302 ifr->ifr_flags = ifp->if_flags; 303 break; 304 305 case SIOCGIFMETRIC: 306 ifr->ifr_metric = ifp->if_metric; 307 break; 308 309 case SIOCSIFFLAGS: 310 if (!suser()) 311 return (u.u_error); 312 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 313 int s = splimp(); 314 if_down(ifp); 315 splx(s); 316 } 317 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 318 (ifr->ifr_flags &~ IFF_CANTCHANGE); 319 if (ifp->if_ioctl) 320 (void) (*ifp->if_ioctl)(ifp, cmd, data); 321 break; 322 323 case SIOCSIFMETRIC: 324 if (!suser()) 325 return (u.u_error); 326 ifp->if_metric = ifr->ifr_metric; 327 break; 328 329 default: 330 if (so->so_proto == 0) 331 return (EOPNOTSUPP); 332 return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 333 cmd, data, ifp)); 334 } 335 return (0); 336 } 337 338 /* 339 * Return interface configuration 340 * of system. List may be used 341 * in later ioctl's (above) to get 342 * other information. 343 */ 344 /*ARGSUSED*/ 345 ifconf(cmd, data) 346 int cmd; 347 caddr_t data; 348 { 349 register struct ifconf *ifc = (struct ifconf *)data; 350 register struct ifnet *ifp = ifnet; 351 register struct ifaddr *ifa; 352 register char *cp, *ep; 353 struct ifreq ifr, *ifrp; 354 int space = ifc->ifc_len, error = 0; 355 356 ifrp = ifc->ifc_req; 357 ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 358 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 359 bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 360 for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 361 ; 362 *cp++ = '0' + ifp->if_unit; *cp = '\0'; 363 if ((ifa = ifp->if_addrlist) == 0) { 364 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 365 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 366 if (error) 367 break; 368 space -= sizeof (ifr), ifrp++; 369 } else 370 for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 371 ifr.ifr_addr = ifa->ifa_addr; 372 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 373 if (error) 374 break; 375 space -= sizeof (ifr), ifrp++; 376 } 377 } 378 ifc->ifc_len -= space; 379 return (error); 380 } 381