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