1 /* 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the project nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32 /* 33 * gif.c 34 */ 35 36 #include "opt_inet.h" 37 #include "opt_inet6.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/malloc.h> 43 #include <sys/mbuf.h> 44 #include <sys/socket.h> 45 #include <sys/sockio.h> 46 #include <sys/errno.h> 47 #include <sys/time.h> 48 #include <sys/syslog.h> 49 #include <machine/cpu.h> 50 51 #include <net/if.h> 52 #include <net/if_types.h> 53 #include <net/netisr.h> 54 #include <net/route.h> 55 #include <net/bpf.h> 56 57 #ifdef INET 58 #include <netinet/in.h> 59 #include <netinet/in_systm.h> 60 #include <netinet/in_var.h> 61 #include <netinet/ip.h> 62 #include <netinet/in_gif.h> 63 #endif /* INET */ 64 65 #ifdef INET6 66 #ifndef INET 67 #include <netinet/in.h> 68 #endif 69 #include <netinet6/in6_var.h> 70 #include <netinet/ip6.h> 71 #include <netinet6/ip6_var.h> 72 #include <netinet6/in6_gif.h> 73 #endif /* INET6 */ 74 75 #include <net/if_gif.h> 76 77 #include "gif.h" 78 79 #include <net/net_osdep.h> 80 81 void gifattach __P((void *)); 82 83 /* 84 * gif global variable definitions 85 */ 86 int ngif = NGIF; /* number of interfaces */ 87 struct gif_softc *gif = 0; 88 89 void 90 gifattach(dummy) 91 void *dummy; 92 { 93 register struct gif_softc *sc; 94 register int i; 95 96 gif = sc = malloc (ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAIT); 97 bzero(sc, ngif * sizeof(struct gif_softc)); 98 for (i = 0; i < ngif; sc++, i++) { 99 sc->gif_if.if_name = "gif"; 100 sc->gif_if.if_unit = i; 101 sc->gif_if.if_mtu = GIF_MTU; 102 sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 103 sc->gif_if.if_ioctl = gif_ioctl; 104 sc->gif_if.if_output = gif_output; 105 sc->gif_if.if_type = IFT_GIF; 106 sc->gif_if.if_snd.ifq_maxlen = ifqmaxlen; 107 if_attach(&sc->gif_if); 108 bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int)); 109 } 110 } 111 112 PSEUDO_SET(gifattach, if_gif); 113 114 int 115 gif_output(ifp, m, dst, rt) 116 struct ifnet *ifp; 117 struct mbuf *m; 118 struct sockaddr *dst; 119 struct rtentry *rt; /* added in net2 */ 120 { 121 register struct gif_softc *sc = (struct gif_softc*)ifp; 122 int error = 0; 123 static int called = 0; /* XXX: MUTEX */ 124 int calllimit = 10; /* XXX: adhoc */ 125 126 /* 127 * gif may cause infinite recursion calls when misconfigured. 128 * We'll prevent this by introducing upper limit. 129 * XXX: this mechanism may introduce another problem about 130 * mutual exclusion of the variable CALLED, especially if we 131 * use kernel thread. 132 */ 133 if (++called >= calllimit) { 134 log(LOG_NOTICE, 135 "gif_output: recursively called too many times(%d)\n", 136 called); 137 m_freem(m); 138 error = EIO; /* is there better errno? */ 139 goto end; 140 } 141 getmicrotime(&ifp->if_lastchange); 142 m->m_flags &= ~(M_BCAST|M_MCAST); 143 if (!(ifp->if_flags & IFF_UP) || 144 sc->gif_psrc == NULL || sc->gif_pdst == NULL) { 145 m_freem(m); 146 error = ENETDOWN; 147 goto end; 148 } 149 150 if (ifp->if_bpf) { 151 /* 152 * We need to prepend the address family as 153 * a four byte field. Cons up a dummy header 154 * to pacify bpf. This is safe because bpf 155 * will only read from the mbuf (i.e., it won't 156 * try to free it or keep a pointer a to it). 157 */ 158 struct mbuf m0; 159 u_int af = dst->sa_family; 160 161 m0.m_next = m; 162 m0.m_len = 4; 163 m0.m_data = (char *)⁡ 164 165 bpf_mtap(ifp, &m0); 166 } 167 ifp->if_opackets++; 168 ifp->if_obytes += m->m_pkthdr.len; 169 170 switch (sc->gif_psrc->sa_family) { 171 #ifdef INET 172 case AF_INET: 173 error = in_gif_output(ifp, dst->sa_family, m, rt); 174 break; 175 #endif 176 #ifdef INET6 177 case AF_INET6: 178 error = in6_gif_output(ifp, dst->sa_family, m, rt); 179 break; 180 #endif 181 default: 182 m_freem(m); 183 error = ENETDOWN; 184 } 185 186 end: 187 called = 0; /* reset recursion counter */ 188 if (error) ifp->if_oerrors++; 189 return error; 190 } 191 192 void 193 gif_input(m, af, gifp) 194 struct mbuf *m; 195 int af; 196 struct ifnet *gifp; 197 { 198 int s, isr; 199 register struct ifqueue *ifq = 0; 200 201 if (gifp == NULL) { 202 /* just in case */ 203 m_freem(m); 204 return; 205 } 206 207 if (m->m_pkthdr.rcvif) 208 m->m_pkthdr.rcvif = gifp; 209 210 if (gifp->if_bpf) { 211 /* 212 * We need to prepend the address family as 213 * a four byte field. Cons up a dummy header 214 * to pacify bpf. This is safe because bpf 215 * will only read from the mbuf (i.e., it won't 216 * try to free it or keep a pointer a to it). 217 */ 218 struct mbuf m0; 219 u_int af = AF_INET6; 220 221 m0.m_next = m; 222 m0.m_len = 4; 223 m0.m_data = (char *)⁡ 224 225 bpf_mtap(gifp, &m0); 226 } 227 228 /* 229 * Put the packet to the network layer input queue according to the 230 * specified address family. 231 * Note: older versions of gif_input directly called network layer 232 * input functions, e.g. ip6_input, here. We changed the policy to 233 * prevent too many recursive calls of such input functions, which 234 * might cause kernel panic. But the change may introduce another 235 * problem; if the input queue is full, packets are discarded. 236 * We believed it rarely occurs and changed the policy. If we find 237 * it occurs more times than we thought, we may change the policy 238 * again. 239 */ 240 switch (af) { 241 #ifdef INET 242 case AF_INET: 243 ifq = &ipintrq; 244 isr = NETISR_IP; 245 break; 246 #endif 247 #ifdef INET6 248 case AF_INET6: 249 ifq = &ip6intrq; 250 isr = NETISR_IPV6; 251 break; 252 #endif 253 default: 254 m_freem(m); 255 return; 256 } 257 258 s = splimp(); 259 if (IF_QFULL(ifq)) { 260 IF_DROP(ifq); /* update statistics */ 261 m_freem(m); 262 splx(s); 263 return; 264 } 265 IF_ENQUEUE(ifq, m); 266 /* we need schednetisr since the address family may change */ 267 schednetisr(isr); 268 gifp->if_ipackets++; 269 gifp->if_ibytes += m->m_pkthdr.len; 270 splx(s); 271 272 return; 273 } 274 275 276 int 277 gif_ioctl(ifp, cmd, data) 278 struct ifnet *ifp; 279 u_long cmd; 280 caddr_t data; 281 { 282 struct gif_softc *sc = (struct gif_softc*)ifp; 283 struct ifreq *ifr = (struct ifreq*)data; 284 int error = 0, size; 285 struct sockaddr *sa, *dst, *src; 286 287 switch (cmd) { 288 case SIOCSIFADDR: 289 break; 290 291 case SIOCSIFDSTADDR: 292 break; 293 294 case SIOCADDMULTI: 295 case SIOCDELMULTI: 296 break; 297 298 case SIOCGIFMTU: 299 break; 300 case SIOCSIFMTU: 301 { 302 u_long mtu; 303 mtu = ifr->ifr_mtu; 304 if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) { 305 return (EINVAL); 306 } 307 ifp->if_mtu = mtu; 308 } 309 break; 310 311 case SIOCSIFPHYADDR: 312 #ifdef INET6 313 case SIOCSIFPHYADDR_IN6: 314 #endif /* INET6 */ 315 switch (ifr->ifr_addr.sa_family) { 316 #ifdef INET 317 case AF_INET: 318 src = (struct sockaddr *) 319 &(((struct in_aliasreq *)data)->ifra_addr); 320 dst = (struct sockaddr *) 321 &(((struct in_aliasreq *)data)->ifra_dstaddr); 322 323 /* only one gif can have dst = INADDR_ANY */ 324 #define satosaddr(sa) (((struct sockaddr_in *)(sa))->sin_addr.s_addr) 325 326 if (satosaddr(dst) == INADDR_ANY) { 327 int i; 328 struct gif_softc *sc2; 329 330 for (i = 0, sc2 = gif; i < ngif; i++, sc2++) { 331 if (sc2 == sc) continue; 332 if (sc2->gif_pdst && 333 satosaddr(sc2->gif_pdst) 334 == INADDR_ANY) { 335 error = EADDRNOTAVAIL; 336 goto bad; 337 } 338 } 339 } 340 size = sizeof(struct sockaddr_in); 341 break; 342 #endif /* INET */ 343 #ifdef INET6 344 case AF_INET6: 345 src = (struct sockaddr *) 346 &(((struct in6_aliasreq *)data)->ifra_addr); 347 dst = (struct sockaddr *) 348 &(((struct in6_aliasreq *)data)->ifra_dstaddr); 349 350 /* only one gif can have dst = in6addr_any */ 351 #define satoin6(sa) (&((struct sockaddr_in6 *)(sa))->sin6_addr) 352 353 if (IN6_IS_ADDR_UNSPECIFIED(satoin6(dst))) { 354 int i; 355 struct gif_softc *sc2; 356 357 for (i = 0, sc2 = gif; i < ngif; i++, sc2++) { 358 if (sc2 == sc) continue; 359 if (sc2->gif_pdst && 360 IN6_IS_ADDR_UNSPECIFIED( 361 satoin6(sc2->gif_pdst) 362 )) { 363 error = EADDRNOTAVAIL; 364 goto bad; 365 } 366 } 367 } 368 size = sizeof(struct sockaddr_in6); 369 break; 370 #endif /* INET6 */ 371 default: 372 error = EPROTOTYPE; 373 goto bad; 374 break; 375 } 376 if (sc->gif_psrc != NULL) 377 free((caddr_t)sc->gif_psrc, M_IFADDR); 378 if (sc->gif_pdst != NULL) 379 free((caddr_t)sc->gif_pdst, M_IFADDR); 380 381 sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK); 382 bzero((caddr_t)sa, size); 383 bcopy((caddr_t)src, (caddr_t)sa, size); 384 sc->gif_psrc = sa; 385 386 sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK); 387 bzero((caddr_t)sa, size); 388 bcopy((caddr_t)dst, (caddr_t)sa, size); 389 sc->gif_pdst = sa; 390 391 ifp->if_flags |= (IFF_UP|IFF_RUNNING); 392 { 393 int s; 394 395 s = splnet(); 396 if_up(ifp); /* send up RTM_IFINFO */ 397 splx(s); 398 } 399 400 break; 401 402 case SIOCGIFPSRCADDR: 403 #ifdef INET6 404 case SIOCGIFPSRCADDR_IN6: 405 #endif /* INET6 */ 406 if (sc->gif_psrc == NULL) { 407 error = EADDRNOTAVAIL; 408 goto bad; 409 } 410 src = sc->gif_psrc; 411 switch (sc->gif_psrc->sa_family) { 412 #ifdef INET 413 case AF_INET: 414 dst = &ifr->ifr_addr; 415 size = sizeof(struct sockaddr_in); 416 break; 417 #endif /* INET */ 418 #ifdef INET6 419 case AF_INET6: 420 dst = (struct sockaddr *) 421 &(((struct in6_ifreq *)data)->ifr_addr); 422 size = sizeof(struct sockaddr_in6); 423 break; 424 #endif /* INET6 */ 425 default: 426 error = EADDRNOTAVAIL; 427 goto bad; 428 } 429 bcopy((caddr_t)src, (caddr_t)dst, size); 430 break; 431 432 case SIOCGIFPDSTADDR: 433 #ifdef INET6 434 case SIOCGIFPDSTADDR_IN6: 435 #endif /* INET6 */ 436 if (sc->gif_pdst == NULL) { 437 error = EADDRNOTAVAIL; 438 goto bad; 439 } 440 src = sc->gif_pdst; 441 switch (sc->gif_pdst->sa_family) { 442 #ifdef INET 443 case AF_INET: 444 dst = &ifr->ifr_addr; 445 size = sizeof(struct sockaddr_in); 446 break; 447 #endif /* INET */ 448 #ifdef INET6 449 case AF_INET6: 450 dst = (struct sockaddr *) 451 &(((struct in6_ifreq *)data)->ifr_addr); 452 size = sizeof(struct sockaddr_in6); 453 break; 454 #endif /* INET6 */ 455 default: 456 error = EADDRNOTAVAIL; 457 goto bad; 458 } 459 bcopy((caddr_t)src, (caddr_t)dst, size); 460 break; 461 462 case SIOCSIFFLAGS: 463 break; 464 465 default: 466 error = EINVAL; 467 break; 468 } 469 bad: 470 return error; 471 } 472