Deleted Added
sdiff udiff text old ( 57903 ) new ( 62587 )
full compact
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.
28 *
29 * $FreeBSD: head/sys/net/if_gif.c 57903 2000-03-11 11:17:24Z shin $
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

--- 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>
73#endif /* INET6 */
74
75#include <net/if_gif.h>
76
77#include "gif.h"
78
79#include <net/net_osdep.h>
80
81void gifattach __P((void *));
82
83/*
84 * gif global variable definitions
85 */
86int ngif = NGIF + 1; /* number of interfaces. +1 for stf. */
87struct gif_softc *gif = 0;
88
89void
90gifattach(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 - 1; sc++, i++) { /* leave last one for stf */
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 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
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 */
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 */
143 if (++called >= calllimit) {
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 }
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
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;
174
175 bpf_mtap(ifp, &m0);
176 }
177 ifp->if_opackets++;
178 ifp->if_obytes += m->m_pkthdr.len;
179
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:
192 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
217 if (m->m_pkthdr.rcvif)
218 m->m_pkthdr.rcvif = gifp;
219
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;
230
231 m0.m_next = m;
232 m0.m_len = 4;
233 m0.m_data = (char *)&af;
234
235 bpf_mtap(gifp, &m0);
236 }
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
285
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;
295 struct sockaddr *sa, *dst, *src;
296
297 switch (cmd) {
298 case SIOCSIFADDR:
299 break;
300
301 case SIOCSIFDSTADDR:
302 break;
303
304 case SIOCADDMULTI:
305 case SIOCDELMULTI:
306 break;
307
308 case SIOCGIFMTU:
309 break;
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;
320
321 case SIOCSIFPHYADDR:
322#ifdef INET6
323 case SIOCSIFPHYADDR_IN6:
324#endif /* INET6 */
325 switch (ifr->ifr_addr.sa_family) {
326#ifdef INET
327 case AF_INET:
328 src = (struct sockaddr *)
329 &(((struct in_aliasreq *)data)->ifra_addr);
330 dst = (struct sockaddr *)
331 &(((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;
357#endif /* INET */
358#ifdef INET6
359 case AF_INET6:
360 src = (struct sockaddr *)
361 &(((struct in6_aliasreq *)data)->ifra_addr);
362 dst = (struct sockaddr *)
363 &(((struct in6_aliasreq *)data)->ifra_dstaddr);
364
365 /* only one gif can have dst = in6addr_any */
366#define satoin6(sa) (&((struct sockaddr_in6 *)(sa))->sin6_addr)
367
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 }
382 }
383 size = sizeof(struct sockaddr_in6);
384 break;
385#endif /* INET6 */
386 default:
387 error = EPROTOTYPE;
388 goto bad;
389 break;
390 }
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
396 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
401 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
406 ifp->if_flags |= (IFF_UP|IFF_RUNNING);
407 {
408 int s;
409
410 s = splnet();
411 if_up(ifp); /* send up RTM_IFINFO */
412 splx(s);
413 }
414
415 break;
416
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;
446
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:
478 break;
479
480 default:
481 error = EINVAL;
482 break;
483 }
484 bad:
485 return error;
486}