if_gif.c (57903) | if_gif.c (62587) |
---|---|
1/* $FreeBSD: head/sys/net/if_gif.c 62587 2000-07-04 16:35:15Z itojun $ */ 2/* $KAME: if_gif.c,v 1.28 2000/06/20 12:30:03 jinmei Exp $ */ 3 |
|
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 --- 11 unchanged lines hidden (view full) --- 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. | 4/* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. |
28 * 29 * $FreeBSD: head/sys/net/if_gif.c 57903 2000-03-11 11:17:24Z shin $ | |
30 */ 31 | 31 */ 32 |
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> | 33#include "opt_inet.h" 34#include "opt_inet6.h" 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/kernel.h> 39#include <sys/malloc.h> 40#include <sys/mbuf.h> 41#include <sys/socket.h> 42#include <sys/sockio.h> 43#include <sys/errno.h> 44#include <sys/time.h> 45#include <sys/syslog.h> |
46#include <sys/protosw.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 --- 8 unchanged lines hidden (view full) --- 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> | 47#include <machine/cpu.h> 48 49#include <net/if.h> 50#include <net/if_types.h> 51#include <net/netisr.h> 52#include <net/route.h> 53#include <net/bpf.h> 54 --- 8 unchanged lines hidden (view full) --- 63#ifdef INET6 64#ifndef INET 65#include <netinet/in.h> 66#endif 67#include <netinet6/in6_var.h> 68#include <netinet/ip6.h> 69#include <netinet6/ip6_var.h> 70#include <netinet6/in6_gif.h> |
71#include <netinet6/ip6protosw.h> |
|
73#endif /* INET6 */ 74 | 72#endif /* INET6 */ 73 |
74#include <netinet/ip_encap.h> |
|
75#include <net/if_gif.h> 76 77#include "gif.h" | 75#include <net/if_gif.h> 76 77#include "gif.h" |
78#include "bpf.h" 79#define NBPFILTER NBPF |
|
78 79#include <net/net_osdep.h> 80 | 80 81#include <net/net_osdep.h> 82 |
83#if NGIF > 0 84 |
|
81void gifattach __P((void *)); | 85void gifattach __P((void *)); |
86static int gif_encapcheck __P((const struct mbuf *, int, int, void *)); 87#ifdef INET 88extern struct protosw in_gif_protosw; 89#endif 90#ifdef INET6 91extern struct ip6protosw in6_gif_protosw; 92#endif |
|
82 83/* 84 * gif global variable definitions 85 */ | 93 94/* 95 * gif global variable definitions 96 */ |
86int ngif = NGIF + 1; /* number of interfaces. +1 for stf. */ 87struct gif_softc *gif = 0; | 97static int ngif; /* number of interfaces */ 98static struct gif_softc *gif = 0; |
88 | 99 |
100#ifndef MAX_GIF_NEST 101/* 102 * This macro controls the upper limitation on nesting of gif tunnels. 103 * Since, setting a large value to this macro with a careless configuration 104 * may introduce system crash, we don't allow any nestings by default. 105 * If you need to configure nested gif tunnels, you can define this macro 106 * in your kernel configuration file. However, if you do so, please be 107 * careful to configure the tunnels so that it won't make a loop. 108 */ 109#define MAX_GIF_NEST 1 110#endif 111static int max_gif_nesting = MAX_GIF_NEST; 112 |
|
89void 90gifattach(dummy) 91 void *dummy; 92{ 93 register struct gif_softc *sc; 94 register int i; 95 | 113void 114gifattach(dummy) 115 void *dummy; 116{ 117 register struct gif_softc *sc; 118 register int i; 119 |
120 ngif = NGIF; |
|
96 gif = sc = malloc (ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAIT); 97 bzero(sc, ngif * sizeof(struct gif_softc)); | 121 gif = sc = malloc (ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAIT); 122 bzero(sc, ngif * sizeof(struct gif_softc)); |
98 for (i = 0; i < ngif - 1; sc++, i++) { /* leave last one for stf */ | 123 for (i = 0; i < ngif; sc++, i++) { |
99 sc->gif_if.if_name = "gif"; 100 sc->gif_if.if_unit = i; | 124 sc->gif_if.if_name = "gif"; 125 sc->gif_if.if_unit = i; |
126 127 sc->encap_cookie4 = sc->encap_cookie6 = NULL; 128#ifdef INET 129 sc->encap_cookie4 = encap_attach_func(AF_INET, -1, 130 gif_encapcheck, &in_gif_protosw, sc); 131 if (sc->encap_cookie4 == NULL) { 132 printf("%s: attach failed\n", if_name(&sc->gif_if)); 133 continue; 134 } 135#endif 136#ifdef INET6 137 sc->encap_cookie6 = encap_attach_func(AF_INET6, -1, 138 gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc); 139 if (sc->encap_cookie6 == NULL) { 140 if (sc->encap_cookie4) { 141 encap_detach(sc->encap_cookie4); 142 sc->encap_cookie4 = NULL; 143 } 144 printf("%s: attach failed\n", if_name(&sc->gif_if)); 145 continue; 146 } 147#endif 148 |
|
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; | 149 sc->gif_if.if_mtu = GIF_MTU; 150 sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 151 sc->gif_if.if_ioctl = gif_ioctl; 152 sc->gif_if.if_output = gif_output; 153 sc->gif_if.if_type = IFT_GIF; |
106 sc->gif_if.if_snd.ifq_maxlen = ifqmaxlen; | 154 sc->gif_if.if_snd.ifq_maxlen = IFQ_MAXLEN; |
107 if_attach(&sc->gif_if); | 155 if_attach(&sc->gif_if); |
156#if NBPFILTER > 0 157#ifdef HAVE_OLD_BPF |
|
108 bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int)); | 158 bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int)); |
159#else 160 bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_NULL, sizeof(u_int)); 161#endif 162#endif |
|
109 } | 163 } |
110 sc->gif_if.if_name = "stf"; 111 sc->gif_if.if_unit = 0; 112 sc->gif_if.if_mtu = GIF_MTU; 113 sc->gif_if.if_flags = IFF_MULTICAST; 114 sc->gif_if.if_ioctl = gif_ioctl; 115 sc->gif_if.if_output = gif_output; 116 sc->gif_if.if_type = IFT_GIF; 117 sc->gif_if.if_snd.ifq_maxlen = ifqmaxlen; 118 if_attach(&sc->gif_if); 119 bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int)); | |
120} 121 122PSEUDO_SET(gifattach, if_gif); 123 | 164} 165 166PSEUDO_SET(gifattach, if_gif); 167 |
168static int 169gif_encapcheck(m, off, proto, arg) 170 const struct mbuf *m; 171 int off; 172 int proto; 173 void *arg; 174{ 175 struct ip ip; 176 struct gif_softc *sc; 177 178 sc = (struct gif_softc *)arg; 179 if (sc == NULL) 180 return 0; 181 182 if ((sc->gif_if.if_flags & IFF_UP) == 0) 183 return 0; 184 185 /* no physical address */ 186 if (!sc->gif_psrc || !sc->gif_pdst) 187 return 0; 188 189 switch (proto) { 190#ifdef INET 191 case IPPROTO_IPV4: 192 break; 193#endif 194#ifdef INET6 195 case IPPROTO_IPV6: 196 break; 197#endif 198 default: 199 return 0; 200 } 201 202 /* LINTED const cast */ 203 m_copydata((struct mbuf *)m, 0, sizeof(ip), (caddr_t)&ip); 204 205 switch (ip.ip_v) { 206#ifdef INET 207 case 4: 208 if (sc->gif_psrc->sa_family != AF_INET || 209 sc->gif_pdst->sa_family != AF_INET) 210 return 0; 211 return gif_encapcheck4(m, off, proto, arg); 212#endif 213#ifdef INET6 214 case 6: 215 if (sc->gif_psrc->sa_family != AF_INET6 || 216 sc->gif_pdst->sa_family != AF_INET6) 217 return 0; 218 return gif_encapcheck6(m, off, proto, arg); 219#endif 220 default: 221 return 0; 222 } 223} 224 |
|
124int 125gif_output(ifp, m, dst, rt) 126 struct ifnet *ifp; 127 struct mbuf *m; 128 struct sockaddr *dst; 129 struct rtentry *rt; /* added in net2 */ 130{ 131 register struct gif_softc *sc = (struct gif_softc*)ifp; 132 int error = 0; 133 static int called = 0; /* XXX: MUTEX */ | 225int 226gif_output(ifp, m, dst, rt) 227 struct ifnet *ifp; 228 struct mbuf *m; 229 struct sockaddr *dst; 230 struct rtentry *rt; /* added in net2 */ 231{ 232 register struct gif_softc *sc = (struct gif_softc*)ifp; 233 int error = 0; 234 static int called = 0; /* XXX: MUTEX */ |
134 int calllimit = 10; /* XXX: adhoc */ | |
135 136 /* 137 * gif may cause infinite recursion calls when misconfigured. 138 * We'll prevent this by introducing upper limit. 139 * XXX: this mechanism may introduce another problem about 140 * mutual exclusion of the variable CALLED, especially if we 141 * use kernel thread. 142 */ | 235 236 /* 237 * gif may cause infinite recursion calls when misconfigured. 238 * We'll prevent this by introducing upper limit. 239 * XXX: this mechanism may introduce another problem about 240 * mutual exclusion of the variable CALLED, especially if we 241 * use kernel thread. 242 */ |
143 if (++called >= calllimit) { | 243 if (++called > max_gif_nesting) { |
144 log(LOG_NOTICE, 145 "gif_output: recursively called too many times(%d)\n", 146 called); 147 m_freem(m); 148 error = EIO; /* is there better errno? */ 149 goto end; 150 } | 244 log(LOG_NOTICE, 245 "gif_output: recursively called too many times(%d)\n", 246 called); 247 m_freem(m); 248 error = EIO; /* is there better errno? */ 249 goto end; 250 } |
251 |
|
151 getmicrotime(&ifp->if_lastchange); 152 m->m_flags &= ~(M_BCAST|M_MCAST); 153 if (!(ifp->if_flags & IFF_UP) || 154 sc->gif_psrc == NULL || sc->gif_pdst == NULL) { 155 m_freem(m); 156 error = ENETDOWN; 157 goto end; 158 } 159 | 252 getmicrotime(&ifp->if_lastchange); 253 m->m_flags &= ~(M_BCAST|M_MCAST); 254 if (!(ifp->if_flags & IFF_UP) || 255 sc->gif_psrc == NULL || sc->gif_pdst == NULL) { 256 m_freem(m); 257 error = ENETDOWN; 258 goto end; 259 } 260 |
261#if NBPFILTER > 0 |
|
160 if (ifp->if_bpf) { 161 /* 162 * We need to prepend the address family as 163 * a four byte field. Cons up a dummy header 164 * to pacify bpf. This is safe because bpf 165 * will only read from the mbuf (i.e., it won't 166 * try to free it or keep a pointer a to it). 167 */ 168 struct mbuf m0; 169 u_int af = dst->sa_family; 170 171 m0.m_next = m; 172 m0.m_len = 4; 173 m0.m_data = (char *)⁡ | 262 if (ifp->if_bpf) { 263 /* 264 * We need to prepend the address family as 265 * a four byte field. Cons up a dummy header 266 * to pacify bpf. This is safe because bpf 267 * will only read from the mbuf (i.e., it won't 268 * try to free it or keep a pointer a to it). 269 */ 270 struct mbuf m0; 271 u_int af = dst->sa_family; 272 273 m0.m_next = m; 274 m0.m_len = 4; 275 m0.m_data = (char *)⁡ |
174 | 276 277#ifdef HAVE_OLD_BPF |
175 bpf_mtap(ifp, &m0); | 278 bpf_mtap(ifp, &m0); |
279#else 280 bpf_mtap(ifp->if_bpf, &m0); 281#endif |
|
176 } | 282 } |
177 ifp->if_opackets++; | 283#endif 284 ifp->if_opackets++; |
178 ifp->if_obytes += m->m_pkthdr.len; 179 | 285 ifp->if_obytes += m->m_pkthdr.len; 286 |
287 /* XXX should we check if our outer source is legal? */ 288 |
|
180 switch (sc->gif_psrc->sa_family) { 181#ifdef INET 182 case AF_INET: 183 error = in_gif_output(ifp, dst->sa_family, m, rt); 184 break; 185#endif 186#ifdef INET6 187 case AF_INET6: 188 error = in6_gif_output(ifp, dst->sa_family, m, rt); 189 break; 190#endif 191 default: | 289 switch (sc->gif_psrc->sa_family) { 290#ifdef INET 291 case AF_INET: 292 error = in_gif_output(ifp, dst->sa_family, m, rt); 293 break; 294#endif 295#ifdef INET6 296 case AF_INET6: 297 error = in6_gif_output(ifp, dst->sa_family, m, rt); 298 break; 299#endif 300 default: |
192 m_freem(m); | 301 m_freem(m); |
193 error = ENETDOWN; 194 } 195 196 end: 197 called = 0; /* reset recursion counter */ 198 if (error) ifp->if_oerrors++; 199 return error; 200} --- 8 unchanged lines hidden (view full) --- 209 register struct ifqueue *ifq = 0; 210 211 if (gifp == NULL) { 212 /* just in case */ 213 m_freem(m); 214 return; 215 } 216 | 302 error = ENETDOWN; 303 } 304 305 end: 306 called = 0; /* reset recursion counter */ 307 if (error) ifp->if_oerrors++; 308 return error; 309} --- 8 unchanged lines hidden (view full) --- 318 register struct ifqueue *ifq = 0; 319 320 if (gifp == NULL) { 321 /* just in case */ 322 m_freem(m); 323 return; 324 } 325 |
217 if (m->m_pkthdr.rcvif) 218 m->m_pkthdr.rcvif = gifp; 219 | 326 m->m_pkthdr.rcvif = gifp; 327 328#if NBPFILTER > 0 |
220 if (gifp->if_bpf) { 221 /* 222 * We need to prepend the address family as 223 * a four byte field. Cons up a dummy header 224 * to pacify bpf. This is safe because bpf 225 * will only read from the mbuf (i.e., it won't 226 * try to free it or keep a pointer a to it). 227 */ 228 struct mbuf m0; 229 u_int af = AF_INET6; | 329 if (gifp->if_bpf) { 330 /* 331 * We need to prepend the address family as 332 * a four byte field. Cons up a dummy header 333 * to pacify bpf. This is safe because bpf 334 * will only read from the mbuf (i.e., it won't 335 * try to free it or keep a pointer a to it). 336 */ 337 struct mbuf m0; 338 u_int af = AF_INET6; |
230 | 339 |
231 m0.m_next = m; 232 m0.m_len = 4; 233 m0.m_data = (char *)⁡ | 340 m0.m_next = m; 341 m0.m_len = 4; 342 m0.m_data = (char *)⁡ |
234 | 343 344#ifdef HAVE_OLD_BPF |
235 bpf_mtap(gifp, &m0); | 345 bpf_mtap(gifp, &m0); |
346#else 347 bpf_mtap(gifp->if_bpf, &m0); 348#endif |
|
236 } | 349 } |
350#endif /*NBPFILTER > 0*/ |
|
237 238 /* 239 * Put the packet to the network layer input queue according to the 240 * specified address family. 241 * Note: older versions of gif_input directly called network layer 242 * input functions, e.g. ip6_input, here. We changed the policy to 243 * prevent too many recursive calls of such input functions, which 244 * might cause kernel panic. But the change may introduce another --- 32 unchanged lines hidden (view full) --- 277 schednetisr(isr); 278 gifp->if_ipackets++; 279 gifp->if_ibytes += m->m_pkthdr.len; 280 splx(s); 281 282 return; 283} 284 | 351 352 /* 353 * Put the packet to the network layer input queue according to the 354 * specified address family. 355 * Note: older versions of gif_input directly called network layer 356 * input functions, e.g. ip6_input, here. We changed the policy to 357 * prevent too many recursive calls of such input functions, which 358 * might cause kernel panic. But the change may introduce another --- 32 unchanged lines hidden (view full) --- 391 schednetisr(isr); 392 gifp->if_ipackets++; 393 gifp->if_ibytes += m->m_pkthdr.len; 394 splx(s); 395 396 return; 397} 398 |
285 | 399/* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */ |
286int 287gif_ioctl(ifp, cmd, data) 288 struct ifnet *ifp; 289 u_long cmd; 290 caddr_t data; 291{ 292 struct gif_softc *sc = (struct gif_softc*)ifp; 293 struct ifreq *ifr = (struct ifreq*)data; 294 int error = 0, size; | 400int 401gif_ioctl(ifp, cmd, data) 402 struct ifnet *ifp; 403 u_long cmd; 404 caddr_t data; 405{ 406 struct gif_softc *sc = (struct gif_softc*)ifp; 407 struct ifreq *ifr = (struct ifreq*)data; 408 int error = 0, size; |
295 struct sockaddr *sa, *dst, *src; 296 | 409 struct sockaddr *dst, *src; 410 struct sockaddr *sa; 411 int i; 412 struct gif_softc *sc2; 413 |
297 switch (cmd) { 298 case SIOCSIFADDR: 299 break; | 414 switch (cmd) { 415 case SIOCSIFADDR: 416 break; |
300 | 417 |
301 case SIOCSIFDSTADDR: 302 break; 303 304 case SIOCADDMULTI: 305 case SIOCDELMULTI: 306 break; 307 | 418 case SIOCSIFDSTADDR: 419 break; 420 421 case SIOCADDMULTI: 422 case SIOCDELMULTI: 423 break; 424 |
425#ifdef SIOCSIFMTU /* xxx */ |
|
308 case SIOCGIFMTU: 309 break; | 426 case SIOCGIFMTU: 427 break; |
428 |
|
310 case SIOCSIFMTU: 311 { 312 u_long mtu; 313 mtu = ifr->ifr_mtu; 314 if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) { 315 return (EINVAL); 316 } 317 ifp->if_mtu = mtu; 318 } 319 break; | 429 case SIOCSIFMTU: 430 { 431 u_long mtu; 432 mtu = ifr->ifr_mtu; 433 if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) { 434 return (EINVAL); 435 } 436 ifp->if_mtu = mtu; 437 } 438 break; |
439#endif /* SIOCSIFMTU */ |
|
320 321 case SIOCSIFPHYADDR: 322#ifdef INET6 323 case SIOCSIFPHYADDR_IN6: 324#endif /* INET6 */ | 440 441 case SIOCSIFPHYADDR: 442#ifdef INET6 443 case SIOCSIFPHYADDR_IN6: 444#endif /* INET6 */ |
325 switch (ifr->ifr_addr.sa_family) { 326#ifdef INET 327 case AF_INET: | 445 switch (cmd) { 446 case SIOCSIFPHYADDR: |
328 src = (struct sockaddr *) 329 &(((struct in_aliasreq *)data)->ifra_addr); 330 dst = (struct sockaddr *) 331 &(((struct in_aliasreq *)data)->ifra_dstaddr); | 447 src = (struct sockaddr *) 448 &(((struct in_aliasreq *)data)->ifra_addr); 449 dst = (struct sockaddr *) 450 &(((struct in_aliasreq *)data)->ifra_dstaddr); |
332 333 /* only one gif can have dst = INADDR_ANY */ 334#define satosaddr(sa) (((struct sockaddr_in *)(sa))->sin_addr.s_addr) 335 336#ifdef INET6 337 if (bcmp(ifp->if_name, "stf", 3) == 0) 338 satosaddr(dst) = INADDR_BROADCAST; 339#endif 340 341 if (satosaddr(dst) == INADDR_ANY) { 342 int i; 343 struct gif_softc *sc2; 344 345 for (i = 0, sc2 = gif; i < ngif; i++, sc2++) { 346 if (sc2 == sc) continue; 347 if (sc2->gif_pdst && 348 satosaddr(sc2->gif_pdst) 349 == INADDR_ANY) { 350 error = EADDRNOTAVAIL; 351 goto bad; 352 } 353 } 354 } 355 size = sizeof(struct sockaddr_in); | |
356 break; | 451 break; |
357#endif /* INET */ | |
358#ifdef INET6 | 452#ifdef INET6 |
359 case AF_INET6: | 453 case SIOCSIFPHYADDR_IN6: |
360 src = (struct sockaddr *) 361 &(((struct in6_aliasreq *)data)->ifra_addr); 362 dst = (struct sockaddr *) 363 &(((struct in6_aliasreq *)data)->ifra_dstaddr); | 454 src = (struct sockaddr *) 455 &(((struct in6_aliasreq *)data)->ifra_addr); 456 dst = (struct sockaddr *) 457 &(((struct in6_aliasreq *)data)->ifra_dstaddr); |
458 break; 459#endif 460 } |
|
364 | 461 |
365 /* only one gif can have dst = in6addr_any */ 366#define satoin6(sa) (&((struct sockaddr_in6 *)(sa))->sin6_addr) | 462 for (i = 0; i < ngif; i++) { 463 sc2 = gif + i; 464 if (sc2 == sc) 465 continue; 466 if (!sc2->gif_pdst || !sc2->gif_psrc) 467 continue; 468 if (sc2->gif_pdst->sa_family != dst->sa_family || 469 sc2->gif_pdst->sa_len != dst->sa_len || 470 sc2->gif_psrc->sa_family != src->sa_family || 471 sc2->gif_psrc->sa_len != src->sa_len) 472 continue; 473 /* can't configure same pair of address onto two gifs */ 474 if (bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 && 475 bcmp(sc2->gif_psrc, src, src->sa_len) == 0) { 476 error = EADDRNOTAVAIL; 477 goto bad; 478 } |
367 | 479 |
368 if (IN6_IS_ADDR_UNSPECIFIED(satoin6(dst))) { 369 int i; 370 struct gif_softc *sc2; 371 372 for (i = 0, sc2 = gif; i < ngif; i++, sc2++) { 373 if (sc2 == sc) continue; 374 if (sc2->gif_pdst && 375 IN6_IS_ADDR_UNSPECIFIED( 376 satoin6(sc2->gif_pdst) 377 )) { 378 error = EADDRNOTAVAIL; 379 goto bad; 380 } 381 } | 480 /* can't configure multiple multi-dest interfaces */ 481#define multidest(x) \ 482 (((struct sockaddr_in *)(x))->sin_addr.s_addr == INADDR_ANY) 483#ifdef INET6 484#define multidest6(x) \ 485 (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(x))->sin6_addr)) 486#endif 487 if (dst->sa_family == AF_INET && 488 multidest(dst) && multidest(sc2->gif_pdst)) { 489 error = EADDRNOTAVAIL; 490 goto bad; |
382 } | 491 } |
492#ifdef INET6 493 if (dst->sa_family == AF_INET6 && 494 multidest6(dst) && multidest6(sc2->gif_pdst)) { 495 error = EADDRNOTAVAIL; 496 goto bad; 497 } 498#endif 499 } 500 501 if (src->sa_family != dst->sa_family || 502 src->sa_len != dst->sa_len) { 503 error = EINVAL; 504 break; 505 } 506 switch (src->sa_family) { 507#ifdef INET 508 case AF_INET: 509 size = sizeof(struct sockaddr_in); 510 break; 511#endif 512#ifdef INET6 513 case AF_INET6: |
|
383 size = sizeof(struct sockaddr_in6); 384 break; | 514 size = sizeof(struct sockaddr_in6); 515 break; |
385#endif /* INET6 */ | 516#endif |
386 default: | 517 default: |
387 error = EPROTOTYPE; | 518 error = EAFNOSUPPORT; |
388 goto bad; | 519 goto bad; |
520 } 521 if (src->sa_len != size) { 522 error = EINVAL; |
|
389 break; 390 } | 523 break; 524 } |
391 if (sc->gif_psrc != NULL) 392 free((caddr_t)sc->gif_psrc, M_IFADDR); 393 if (sc->gif_pdst != NULL) 394 free((caddr_t)sc->gif_pdst, M_IFADDR); | |
395 | 525 |
526 if (sc->gif_psrc) 527 free((caddr_t)sc->gif_psrc, M_IFADDR); |
|
396 sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK); | 528 sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK); |
397 bzero((caddr_t)sa, size); | |
398 bcopy((caddr_t)src, (caddr_t)sa, size); 399 sc->gif_psrc = sa; 400 | 529 bcopy((caddr_t)src, (caddr_t)sa, size); 530 sc->gif_psrc = sa; 531 |
532 if (sc->gif_pdst) 533 free((caddr_t)sc->gif_pdst, M_IFADDR); |
|
401 sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK); | 534 sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK); |
402 bzero((caddr_t)sa, size); | |
403 bcopy((caddr_t)dst, (caddr_t)sa, size); 404 sc->gif_pdst = sa; 405 | 535 bcopy((caddr_t)dst, (caddr_t)sa, size); 536 sc->gif_pdst = sa; 537 |
406 ifp->if_flags |= (IFF_UP|IFF_RUNNING); 407 { 408 int s; | 538 ifp->if_flags |= IFF_UP; 539 if_up(ifp); /* send up RTM_IFINFO */ |
409 | 540 |
410 s = splnet(); 411 if_up(ifp); /* send up RTM_IFINFO */ 412 splx(s); 413 } 414 | 541 error = 0; |
415 break; 416 | 542 break; 543 |
544#ifdef SIOCDIFPHYADDR 545 case SIOCDIFPHYADDR: 546 if (sc->gif_psrc) { 547 free((caddr_t)sc->gif_psrc, M_IFADDR); 548 sc->gif_psrc = NULL; 549 } 550 if (sc->gif_pdst) { 551 free((caddr_t)sc->gif_pdst, M_IFADDR); 552 sc->gif_pdst = NULL; 553 } 554 /* change the IFF_UP flag as well? */ 555 break; 556#endif 557 |
|
417 case SIOCGIFPSRCADDR: 418#ifdef INET6 419 case SIOCGIFPSRCADDR_IN6: 420#endif /* INET6 */ 421 if (sc->gif_psrc == NULL) { 422 error = EADDRNOTAVAIL; 423 goto bad; 424 } --- 13 unchanged lines hidden (view full) --- 438 break; 439#endif /* INET6 */ 440 default: 441 error = EADDRNOTAVAIL; 442 goto bad; 443 } 444 bcopy((caddr_t)src, (caddr_t)dst, size); 445 break; | 558 case SIOCGIFPSRCADDR: 559#ifdef INET6 560 case SIOCGIFPSRCADDR_IN6: 561#endif /* INET6 */ 562 if (sc->gif_psrc == NULL) { 563 error = EADDRNOTAVAIL; 564 goto bad; 565 } --- 13 unchanged lines hidden (view full) --- 579 break; 580#endif /* INET6 */ 581 default: 582 error = EADDRNOTAVAIL; 583 goto bad; 584 } 585 bcopy((caddr_t)src, (caddr_t)dst, size); 586 break; |
446 | 587 |
447 case SIOCGIFPDSTADDR: 448#ifdef INET6 449 case SIOCGIFPDSTADDR_IN6: 450#endif /* INET6 */ 451 if (sc->gif_pdst == NULL) { 452 error = EADDRNOTAVAIL; 453 goto bad; 454 } --- 15 unchanged lines hidden (view full) --- 470 default: 471 error = EADDRNOTAVAIL; 472 goto bad; 473 } 474 bcopy((caddr_t)src, (caddr_t)dst, size); 475 break; 476 477 case SIOCSIFFLAGS: | 588 case SIOCGIFPDSTADDR: 589#ifdef INET6 590 case SIOCGIFPDSTADDR_IN6: 591#endif /* INET6 */ 592 if (sc->gif_pdst == NULL) { 593 error = EADDRNOTAVAIL; 594 goto bad; 595 } --- 15 unchanged lines hidden (view full) --- 611 default: 612 error = EADDRNOTAVAIL; 613 goto bad; 614 } 615 bcopy((caddr_t)src, (caddr_t)dst, size); 616 break; 617 618 case SIOCSIFFLAGS: |
619 /* if_ioctl() takes care of it */ |
|
478 break; 479 480 default: 481 error = EINVAL; 482 break; 483 } 484 bad: 485 return error; 486} | 620 break; 621 622 default: 623 error = EINVAL; 624 break; 625 } 626 bad: 627 return error; 628} |
629#endif /*NGIF > 0*/ |
|