|
Lines 1-4
Link Here
|
| 1 |
/* $FreeBSD: src/sys/net/if_gif.c,v 1.9 2001/06/03 17:31:11 yar Exp $ */ |
1 |
/* $FreeBSD: src/sys/net/if_gif.c,v 1.9 2001/06/03 17:31:11 yar Exp $ */ |
| 2 |
/* $KAME: if_gif.c,v 1.28 2000/06/20 12:30:03 jinmei Exp $ */ |
2 |
/* $KAME: if_gif.c,v 1.28 2000/06/20 12:30:03 jinmei Exp $ */ |
| 3 |
|
3 |
|
| 4 |
/* |
4 |
/* |
|
Lines 44-49
Link Here
|
| 44 |
#include <sys/time.h> |
44 |
#include <sys/time.h> |
| 45 |
#include <sys/syslog.h> |
45 |
#include <sys/syslog.h> |
| 46 |
#include <sys/protosw.h> |
46 |
#include <sys/protosw.h> |
|
|
47 |
#include <sys/conf.h> |
| 48 |
#include <machine/bus.h> /* XXX: Shouldn't really be required! */ |
| 49 |
#include <sys/rman.h> |
| 47 |
#include <machine/cpu.h> |
50 |
#include <machine/cpu.h> |
| 48 |
|
51 |
|
| 49 |
#include <net/if.h> |
52 |
#include <net/if.h> |
|
Lines 58-63
Link Here
|
| 58 |
#include <netinet/in_var.h> |
61 |
#include <netinet/in_var.h> |
| 59 |
#include <netinet/ip.h> |
62 |
#include <netinet/ip.h> |
| 60 |
#include <netinet/in_gif.h> |
63 |
#include <netinet/in_gif.h> |
|
|
64 |
#include <netinet/ip_var.h> |
| 65 |
#include <netinet/ipprotosw.h> |
| 61 |
#endif /* INET */ |
66 |
#endif /* INET */ |
| 62 |
|
67 |
|
| 63 |
#ifdef INET6 |
68 |
#ifdef INET6 |
|
Lines 74-101
Link Here
|
| 74 |
#include <netinet/ip_encap.h> |
79 |
#include <netinet/ip_encap.h> |
| 75 |
#include <net/if_gif.h> |
80 |
#include <net/if_gif.h> |
| 76 |
|
81 |
|
| 77 |
#include "gif.h" |
82 |
#if defined(__FreeBSD__) |
|
|
83 |
#define NBPFILTER 1 |
| 84 |
#else |
| 78 |
#include "bpf.h" |
85 |
#include "bpf.h" |
| 79 |
#define NBPFILTER NBPF |
86 |
#define NBPFILTER NBPF |
|
|
87 |
#endif |
| 80 |
|
88 |
|
| 81 |
#include <net/net_osdep.h> |
89 |
#include <net/net_osdep.h> |
| 82 |
|
|
|
| 83 |
#if NGIF > 0 |
| 84 |
|
90 |
|
| 85 |
void gifattach __P((void *)); |
91 |
#define GIFNAME "gif" |
|
|
92 |
#define GIFDEV "if_gif" |
| 93 |
#define GIF_MAXUNIT 0x7fff /* ifp->if_unit is only 15 bits */ |
| 94 |
|
| 95 |
static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface"); |
| 96 |
static struct rman gifunits[1]; |
| 97 |
TAILQ_HEAD(gifhead, gif_softc) gifs = TAILQ_HEAD_INITIALIZER(gifs); |
| 98 |
|
| 99 |
static int gifcreate __P((int *)); |
| 100 |
static int gifdelete __P((int)); |
| 101 |
static int gifmodevent __P((module_t, int, void *)); |
| 102 |
static struct gif_softc *gifunit2sc __P((int unit)); |
| 86 |
static int gif_encapcheck __P((const struct mbuf *, int, int, void *)); |
103 |
static int gif_encapcheck __P((const struct mbuf *, int, int, void *)); |
| 87 |
#ifdef INET |
|
|
| 88 |
extern struct protosw in_gif_protosw; |
| 89 |
#endif |
| 90 |
#ifdef INET6 |
| 91 |
extern struct ip6protosw in6_gif_protosw; |
| 92 |
#endif |
| 93 |
|
104 |
|
| 94 |
/* |
105 |
#ifdef INET |
| 95 |
* gif global variable definitions |
106 |
extern struct domain inetdomain; |
| 96 |
*/ |
107 |
struct ipprotosw in_gif_protosw = |
| 97 |
static int ngif; /* number of interfaces */ |
108 |
{ SOCK_RAW, &inetdomain, 0/*IPPROTO_IPV[46]*/, PR_ATOMIC|PR_ADDR, |
| 98 |
static struct gif_softc *gif = 0; |
109 |
in_gif_input, rip_output, 0, rip_ctloutput, |
|
|
110 |
0, |
| 111 |
0, 0, 0, 0, |
| 112 |
&rip_usrreqs |
| 113 |
}; |
| 114 |
#endif |
| 115 |
#ifdef INET6 |
| 116 |
extern struct domain6 inet6domain; |
| 117 |
struct ip6protosw in6_gif_protosw = |
| 118 |
{ SOCK_RAW, &inet6domain, 0/*IPPROTO_IPV[46]*/, PR_ATOMIC|PR_ADDR, |
| 119 |
in6_gif_input, rip6_output, 0, rip6_ctloutput, |
| 120 |
0, |
| 121 |
0, 0, 0, 0, |
| 122 |
&rip6_usrreqs |
| 123 |
}; |
| 124 |
#endif |
| 125 |
|
| 126 |
static d_ioctl_t gifioctl; |
| 127 |
|
| 128 |
#define CDEV_MAJOR 163 |
| 129 |
static struct cdevsw gif_cdevsw = { |
| 130 |
/* open */ nullopen, |
| 131 |
/* close */ nullclose, |
| 132 |
/* read */ noread, |
| 133 |
/* write */ nowrite, |
| 134 |
/* ioctl */ gifioctl, |
| 135 |
/* poll */ nopoll, |
| 136 |
/* mmap */ nommap, |
| 137 |
/* strategy */ nostrategy, |
| 138 |
/* name */ GIFDEV, |
| 139 |
/* maj */ CDEV_MAJOR, |
| 140 |
/* dump */ nodump, |
| 141 |
/* psize */ nopsize, |
| 142 |
/* flags */ 0, |
| 143 |
}; |
| 99 |
|
144 |
|
| 100 |
#ifndef MAX_GIF_NEST |
145 |
#ifndef MAX_GIF_NEST |
| 101 |
/* |
146 |
/* |
|
Lines 110-171
Link Here
|
| 110 |
#endif |
155 |
#endif |
| 111 |
static int max_gif_nesting = MAX_GIF_NEST; |
156 |
static int max_gif_nesting = MAX_GIF_NEST; |
| 112 |
|
157 |
|
| 113 |
void |
158 |
static struct gif_softc * |
| 114 |
gifattach(dummy) |
159 |
gifunit2sc(unit) |
| 115 |
void *dummy; |
160 |
int unit; |
| 116 |
{ |
161 |
{ |
| 117 |
register struct gif_softc *sc; |
162 |
struct gif_softc *sc; |
| 118 |
register int i; |
163 |
|
|
|
164 |
TAILQ_FOREACH(sc, &gifs, gif_link) { |
| 165 |
if (sc->gif_if.if_unit == unit) |
| 166 |
break; |
| 167 |
} |
| 168 |
if (sc->gif_if.if_unit != unit) |
| 169 |
return NULL; |
| 170 |
|
| 171 |
return sc; |
| 172 |
} |
| 173 |
|
| 174 |
static int |
| 175 |
gifcreate(unit) |
| 176 |
int *unit; |
| 177 |
{ |
| 178 |
struct resource *r; |
| 179 |
struct gif_softc *sc; |
| 180 |
|
| 181 |
if (*unit > GIF_MAXUNIT) |
| 182 |
return (ENXIO); |
| 119 |
|
183 |
|
| 120 |
ngif = NGIF; |
184 |
if (*unit < 0) { |
| 121 |
gif = sc = malloc (ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAITOK); |
185 |
r = rman_reserve_resource(gifunits, 0, GIF_MAXUNIT, 1, |
| 122 |
bzero(sc, ngif * sizeof(struct gif_softc)); |
186 |
RF_ALLOCATED | RF_ACTIVE, NULL); |
| 123 |
for (i = 0; i < ngif; sc++, i++) { |
187 |
if (r == NULL) |
| 124 |
sc->gif_if.if_name = "gif"; |
188 |
return (ENOSPC); |
| 125 |
sc->gif_if.if_unit = i; |
189 |
*unit = rman_get_start(r); |
|
|
190 |
} else { |
| 191 |
r = rman_reserve_resource(gifunits, *unit, *unit, 1, |
| 192 |
RF_ALLOCATED | RF_ACTIVE, NULL); |
| 193 |
if (r == NULL) |
| 194 |
return (EBUSY); |
| 195 |
} |
| 196 |
|
| 197 |
sc = malloc (sizeof(struct gif_softc), M_GIF, M_WAITOK); |
| 198 |
bzero(sc, sizeof(struct gif_softc)); |
| 199 |
sc->gif_if.if_softc = sc; |
| 200 |
sc->gif_if.if_name = GIFNAME; |
| 201 |
sc->gif_if.if_unit = *unit; |
| 202 |
sc->r_unit = r; |
| 126 |
|
203 |
|
| 127 |
sc->encap_cookie4 = sc->encap_cookie6 = NULL; |
204 |
sc->encap_cookie4 = sc->encap_cookie6 = NULL; |
| 128 |
#ifdef INET |
205 |
#ifdef INET |
| 129 |
sc->encap_cookie4 = encap_attach_func(AF_INET, -1, |
206 |
sc->encap_cookie4 = encap_attach_func(AF_INET, -1, |
| 130 |
gif_encapcheck, &in_gif_protosw, sc); |
207 |
gif_encapcheck, &in_gif_protosw, sc); |
| 131 |
if (sc->encap_cookie4 == NULL) { |
208 |
if (sc->encap_cookie4 == NULL) { |
| 132 |
printf("%s: attach failed\n", if_name(&sc->gif_if)); |
209 |
free(sc, M_GIF); |
| 133 |
continue; |
210 |
return (ENOMEM); |
| 134 |
} |
211 |
} |
| 135 |
#endif |
212 |
#endif |
| 136 |
#ifdef INET6 |
213 |
#ifdef INET6 |
| 137 |
sc->encap_cookie6 = encap_attach_func(AF_INET6, -1, |
214 |
sc->encap_cookie6 = encap_attach_func(AF_INET6, -1, |
| 138 |
gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc); |
215 |
gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc); |
| 139 |
if (sc->encap_cookie6 == NULL) { |
216 |
if (sc->encap_cookie6 == NULL) { |
| 140 |
if (sc->encap_cookie4) { |
217 |
if (sc->encap_cookie4) { |
| 141 |
encap_detach(sc->encap_cookie4); |
218 |
encap_detach(sc->encap_cookie4); |
| 142 |
sc->encap_cookie4 = NULL; |
219 |
sc->encap_cookie4 = NULL; |
| 143 |
} |
|
|
| 144 |
printf("%s: attach failed\n", if_name(&sc->gif_if)); |
| 145 |
continue; |
| 146 |
} |
220 |
} |
|
|
221 |
free(sc, M_GIF); |
| 222 |
return (ENOMEM); |
| 223 |
} |
| 147 |
#endif |
224 |
#endif |
| 148 |
|
225 |
|
| 149 |
sc->gif_if.if_mtu = GIF_MTU; |
226 |
sc->gif_if.if_mtu = GIF_MTU; |
| 150 |
sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; |
227 |
sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; |
| 151 |
sc->gif_if.if_ioctl = gif_ioctl; |
228 |
sc->gif_if.if_ioctl = gif_ifioctl; |
| 152 |
sc->gif_if.if_output = gif_output; |
229 |
sc->gif_if.if_output = gif_output; |
| 153 |
sc->gif_if.if_type = IFT_GIF; |
230 |
sc->gif_if.if_type = IFT_GIF; |
| 154 |
sc->gif_if.if_snd.ifq_maxlen = IFQ_MAXLEN; |
231 |
sc->gif_if.if_snd.ifq_maxlen = IFQ_MAXLEN; |
| 155 |
if_attach(&sc->gif_if); |
232 |
if_attach(&sc->gif_if); |
| 156 |
#if NBPFILTER > 0 |
233 |
#if NBPFILTER > 0 |
| 157 |
#ifdef HAVE_OLD_BPF |
234 |
#ifdef HAVE_OLD_BPF |
| 158 |
bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int)); |
235 |
bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int)); |
| 159 |
#else |
236 |
#else |
| 160 |
bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_NULL, sizeof(u_int)); |
237 |
bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_NULL, sizeof(u_int)); |
|
|
238 |
#endif |
| 239 |
#endif |
| 240 |
|
| 241 |
TAILQ_INSERT_TAIL(&gifs, sc, gif_link); |
| 242 |
|
| 243 |
return (0); |
| 244 |
} |
| 245 |
|
| 246 |
static int |
| 247 |
gifdelete(unit) |
| 248 |
int unit; |
| 249 |
{ |
| 250 |
int err; |
| 251 |
struct gif_softc *sc; |
| 252 |
|
| 253 |
sc = gifunit2sc(unit); |
| 254 |
if (sc == NULL) |
| 255 |
return (ENXIO); |
| 256 |
|
| 257 |
bpfdetach(&sc->gif_if); |
| 258 |
if_detach(&sc->gif_if); |
| 259 |
|
| 260 |
if (sc->encap_cookie4 != NULL) { |
| 261 |
err = encap_detach(sc->encap_cookie4); |
| 262 |
KASSERT(err == 0, ("Unexpected error detaching encap_cookie4")); |
| 263 |
} |
| 264 |
if (sc->encap_cookie6 != NULL) { |
| 265 |
err = encap_detach(sc->encap_cookie6); |
| 266 |
KASSERT(err == 0, ("Unexpected error detaching encap_cookie6")); |
| 267 |
} |
| 268 |
|
| 269 |
if (sc->gif_psrc) |
| 270 |
free((caddr_t)sc->gif_psrc, M_IFADDR); |
| 271 |
if (sc->gif_pdst) |
| 272 |
free((caddr_t)sc->gif_pdst, M_IFADDR); |
| 273 |
|
| 274 |
err = rman_release_resource(sc->r_unit); |
| 275 |
KASSERT(err == 0, ("Unexpected error freeing resource")); |
| 276 |
|
| 277 |
TAILQ_REMOVE(&gifs, sc, gif_link); |
| 278 |
free(sc, M_GIF); |
| 279 |
|
| 280 |
return 0; |
| 281 |
} |
| 282 |
|
| 283 |
static int |
| 284 |
gifmodevent(mod, type, data) |
| 285 |
module_t mod; |
| 286 |
int type; |
| 287 |
void *data; |
| 288 |
{ |
| 289 |
static dev_t dev; |
| 290 |
int err; |
| 291 |
|
| 292 |
switch (type) { |
| 293 |
case MOD_LOAD: |
| 294 |
if (!devfs_present) { |
| 295 |
err = cdevsw_add(&gif_cdevsw); |
| 296 |
if (err != 0) { |
| 297 |
return (err); |
| 298 |
} |
| 299 |
} |
| 300 |
gifunits->rm_type = RMAN_ARRAY; |
| 301 |
gifunits->rm_descr = "configurable if_gif units"; |
| 302 |
err = rman_init(gifunits); |
| 303 |
if (err != 0) { |
| 304 |
if (!devfs_present) |
| 305 |
cdevsw_remove(&gif_cdevsw); |
| 306 |
return (err); |
| 307 |
} |
| 308 |
err = rman_manage_region(gifunits, 0, GIF_MAXUNIT); |
| 309 |
if (err != 0) { |
| 310 |
printf("%s: gifunits: rman_manage_region: Failed %d\n", |
| 311 |
GIFNAME, err); |
| 312 |
rman_fini(gifunits); |
| 313 |
if (!devfs_present) |
| 314 |
cdevsw_remove(&gif_cdevsw); |
| 315 |
return (err); |
| 316 |
} |
| 317 |
dev = make_dev(&gif_cdevsw, unit2minor(0), |
| 318 |
UID_ROOT, GID_WHEEL, 0600, GIFDEV, 0); |
| 319 |
|
| 320 |
#ifdef INET6 |
| 321 |
ip6_gif_hlim = GIF_HLIM; |
| 161 |
#endif |
322 |
#endif |
|
|
323 |
|
| 324 |
break; |
| 325 |
case MOD_UNLOAD: |
| 326 |
destroy_dev(dev); |
| 327 |
|
| 328 |
while (!TAILQ_EMPTY(&gifs)) |
| 329 |
gifdelete(TAILQ_FIRST(&gifs)->gif_if.if_unit); |
| 330 |
|
| 331 |
err = rman_fini(gifunits); |
| 332 |
if (err != 0) |
| 333 |
return (err); |
| 334 |
|
| 335 |
if (!devfs_present) |
| 336 |
cdevsw_remove(&gif_cdevsw); |
| 337 |
|
| 338 |
#ifdef INET6 |
| 339 |
ip6_gif_hlim = 0; |
| 162 |
#endif |
340 |
#endif |
|
|
341 |
break; |
| 163 |
} |
342 |
} |
|
|
343 |
return 0; |
| 164 |
} |
344 |
} |
|
|
345 |
|
| 346 |
static moduledata_t gif_mod = { |
| 347 |
"if_gif", |
| 348 |
gifmodevent, |
| 349 |
0 |
| 350 |
}; |
| 165 |
|
351 |
|
| 166 |
PSEUDO_SET(gifattach, if_gif); |
352 |
DECLARE_MODULE(if_gif, gif_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); |
| 167 |
|
353 |
|
| 168 |
static int |
354 |
static int |
|
|
355 |
gifioctl(dev, cmd, data, flag, p) |
| 356 |
dev_t dev; |
| 357 |
u_long cmd; |
| 358 |
caddr_t data; |
| 359 |
int flag; |
| 360 |
struct proc *p; |
| 361 |
{ |
| 362 |
int err; |
| 363 |
struct if_manage *ifman; |
| 364 |
struct gif_softc *sc; |
| 365 |
|
| 366 |
/* all actions require root, so check now. */ |
| 367 |
err = suser(p); |
| 368 |
if (err != 0) |
| 369 |
return (err); |
| 370 |
|
| 371 |
switch (cmd) { |
| 372 |
case IOCIFMANAGE: |
| 373 |
ifman = (void*)data; |
| 374 |
switch (ifman->ifman_action) { |
| 375 |
case IFMAN_CREATE: |
| 376 |
if (strcmp(GIFNAME, ifman->ifman_name) != 0) |
| 377 |
return (EINVAL); |
| 378 |
err = gifcreate(&ifman->ifman_unit); |
| 379 |
if (err != 0) |
| 380 |
return (err); |
| 381 |
break; |
| 382 |
case IFMAN_DELETE: |
| 383 |
sc = gifunit2sc(ifman->ifman_unit); |
| 384 |
if (sc == NULL) |
| 385 |
return (ENXIO); |
| 386 |
if (sc->gif_if.if_flags & IFF_UP) |
| 387 |
return (EBUSY); |
| 388 |
err = gifdelete(ifman->ifman_unit); |
| 389 |
if(err != 0) |
| 390 |
return (err); |
| 391 |
break; |
| 392 |
default: |
| 393 |
return (EINVAL); |
| 394 |
} |
| 395 |
break; |
| 396 |
default: |
| 397 |
return (ENOTTY); |
| 398 |
} |
| 399 |
|
| 400 |
return (0); |
| 401 |
} |
| 402 |
|
| 403 |
static int |
| 169 |
gif_encapcheck(m, off, proto, arg) |
404 |
gif_encapcheck(m, off, proto, arg) |
| 170 |
const struct mbuf *m; |
405 |
const struct mbuf *m; |
| 171 |
int off; |
406 |
int off; |
|
Lines 390-396
Link Here
|
| 390 |
|
625 |
|
| 391 |
/* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */ |
626 |
/* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */ |
| 392 |
int |
627 |
int |
| 393 |
gif_ioctl(ifp, cmd, data) |
628 |
gif_ifioctl(ifp, cmd, data) |
| 394 |
struct ifnet *ifp; |
629 |
struct ifnet *ifp; |
| 395 |
u_long cmd; |
630 |
u_long cmd; |
| 396 |
caddr_t data; |
631 |
caddr_t data; |
|
Lines 400-407
Link Here
|
| 400 |
int error = 0, size; |
635 |
int error = 0, size; |
| 401 |
struct sockaddr *dst, *src; |
636 |
struct sockaddr *dst, *src; |
| 402 |
struct sockaddr *sa; |
637 |
struct sockaddr *sa; |
| 403 |
int i; |
|
|
| 404 |
int s; |
638 |
int s; |
|
|
639 |
struct ifnet *ifp2; |
| 405 |
struct gif_softc *sc2; |
640 |
struct gif_softc *sc2; |
| 406 |
|
641 |
|
| 407 |
switch (cmd) { |
642 |
switch (cmd) { |
|
Lines 451-459
Link Here
|
| 451 |
break; |
686 |
break; |
| 452 |
#endif |
687 |
#endif |
| 453 |
} |
688 |
} |
|
|
689 |
|
| 690 |
TAILQ_FOREACH(ifp2, &ifnet, if_link) { |
| 691 |
if (strcmp(ifp2->if_name, GIFNAME) != 0) |
| 692 |
continue; |
| 693 |
sc2 = ifp2->if_softc; |
| 454 |
|
694 |
|
| 455 |
for (i = 0; i < ngif; i++) { |
|
|
| 456 |
sc2 = gif + i; |
| 457 |
if (sc2 == sc) |
695 |
if (sc2 == sc) |
| 458 |
continue; |
696 |
continue; |
| 459 |
if (!sc2->gif_pdst || !sc2->gif_psrc) |
697 |
if (!sc2->gif_pdst || !sc2->gif_psrc) |
|
Lines 623-626
Link Here
|
| 623 |
bad: |
861 |
bad: |
| 624 |
return error; |
862 |
return error; |
| 625 |
} |
863 |
} |
| 626 |
#endif /*NGIF > 0*/ |
|
|