Deleted Added
full compact
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 *)&af;
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 *)&af;
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 *)&af;
340 m0.m_next = m;
341 m0.m_len = 4;
342 m0.m_data = (char *)&af;
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*/