1/* $NetBSD: if_gre.c,v 1.171 2016/10/02 14:17:07 christos Exp $ */
2
3/*
4 * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Heiko W.Rupp <hwr@pilhuhn.de>
9 *
10 * IPv6-over-GRE contributed by Gert Doering <gert@greenie.muc.de>
11 *
12 * GRE over UDP/IPv4/IPv6 sockets contributed by David Young <dyoung@NetBSD.org>
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 * This material is based upon work partially supported by NSF
36 * under Contract No. NSF CNS-0626584.
37 */
38
39/*
40 * Encapsulate L3 protocols into IP
41 * See RFC 1701 and 1702 for more details.
42 * If_gre is compatible with Cisco GRE tunnels, so you can
43 * have a NetBSD box as the other end of a tunnel interface of a Cisco
44 * router. See gre(4) for more details.
45 */
46
47#include <sys/cdefs.h>
48__KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1.171 2016/10/02 14:17:07 christos Exp $");
49
50#ifdef _KERNEL_OPT
51#include "opt_atalk.h"
52#include "opt_gre.h"
53#include "opt_inet.h"
54#include "opt_mpls.h"
55#endif
56
57#include <sys/param.h>
58#include <sys/file.h>
59#include <sys/filedesc.h>
60#include <sys/malloc.h>
61#include <sys/mallocvar.h>
62#include <sys/mbuf.h>
63#include <sys/proc.h>
64#include <sys/domain.h>
65#include <sys/protosw.h>
66#include <sys/socket.h>
67#include <sys/socketvar.h>
68#include <sys/ioctl.h>
69#include <sys/queue.h>
70#include <sys/intr.h>
71#include <sys/systm.h>
72#include <sys/sysctl.h>
73#include <sys/kauth.h>
74#include <sys/device.h>
75#include <sys/module.h>
76
77#include <sys/kernel.h>
78#include <sys/mutex.h>
79#include <sys/condvar.h>
80#include <sys/kthread.h>
81
82#include <sys/cpu.h>
83
84#include <net/ethertypes.h>
85#include <net/if.h>
86#include <net/if_types.h>
87#include <net/netisr.h>
88#include <net/route.h>
89#include <sys/device.h>
90#include <sys/module.h>
91#include <sys/atomic.h>
92
93#include <netinet/in_systm.h>
94#include <netinet/in.h>
95#include <netinet/ip.h> /* we always need this for sizeof(struct ip) */
96
97#ifdef INET
98#include <netinet/in_var.h>
99#include <netinet/ip_var.h>
100#endif
101
102#ifdef INET6
103#include <netinet6/in6_var.h>
104#endif
105
106#ifdef MPLS
107#include <netmpls/mpls.h>
108#include <netmpls/mpls_var.h>
109#endif
110
111#ifdef NETATALK
112#include <netatalk/at.h>
113#include <netatalk/at_var.h>
114#include <netatalk/at_extern.h>
115#endif
116
117#include <sys/time.h>
118#include <net/bpf.h>
119
120#include <net/if_gre.h>
121
122#include <compat/sys/socket.h>
123#include <compat/sys/sockio.h>
124
125#include "ioconf.h"
126
127/*
128 * It is not easy to calculate the right value for a GRE MTU.
129 * We leave this task to the admin and use the same default that
130 * other vendors use.
131 */
132#define GREMTU 1476
133
134#ifdef GRE_DEBUG
135int gre_debug = 0;
136#define GRE_DPRINTF(__sc, ...) \
137 do { \
138 if (__predict_false(gre_debug || \
139 ((__sc)->sc_if.if_flags & IFF_DEBUG) != 0)) { \
140 printf("%s.%d: ", __func__, __LINE__); \
141 printf(__VA_ARGS__); \
142 } \
143 } while (/*CONSTCOND*/0)
144#else
145#define GRE_DPRINTF(__sc, __fmt, ...) do { } while (/*CONSTCOND*/0)
146#endif /* GRE_DEBUG */
147
148int ip_gre_ttl = GRE_TTL;
149
150static u_int gre_count;
151
152static int gre_clone_create(struct if_clone *, int);
153static int gre_clone_destroy(struct ifnet *);
154
155static struct if_clone gre_cloner =
156 IF_CLONE_INITIALIZER("gre", gre_clone_create, gre_clone_destroy);
157
158static int gre_input(struct gre_softc *, struct mbuf *, int,
159 const struct gre_h *);
160static bool gre_is_nullconf(const struct gre_soparm *);
161static int gre_output(struct ifnet *, struct mbuf *,
162 const struct sockaddr *, const struct rtentry *);
163static int gre_ioctl(struct ifnet *, u_long, void *);
164static int gre_getsockname(struct socket *, struct sockaddr *);
165static int gre_getpeername(struct socket *, struct sockaddr *);
166static int gre_getnames(struct socket *, struct lwp *,
167 struct sockaddr_storage *, struct sockaddr_storage *);
168static void gre_clearconf(struct gre_soparm *, bool);
169static int gre_soreceive(struct socket *, struct mbuf **);
170static int gre_sosend(struct socket *, struct mbuf *);
171static struct socket *gre_reconf(struct gre_softc *, const struct gre_soparm *);
172
173static bool gre_fp_send(struct gre_softc *, enum gre_msg, file_t *);
174static bool gre_fp_recv(struct gre_softc *);
175static void gre_fp_recvloop(void *);
176
177static void
178gre_bufq_init(struct gre_bufq *bq, size_t len0)
179{
180 memset(bq, 0, sizeof(*bq));
181 bq->bq_q = pcq_create(len0, KM_SLEEP);
182 KASSERT(bq->bq_q != NULL);
183}
184
185static struct mbuf *
186gre_bufq_dequeue(struct gre_bufq *bq)
187{
188 return pcq_get(bq->bq_q);
189}
190
191static void
192gre_bufq_purge(struct gre_bufq *bq)
193{
194 struct mbuf *m;
195
196 while ((m = gre_bufq_dequeue(bq)) != NULL)
197 m_freem(m);
198}
199
200static void
201gre_bufq_destroy(struct gre_bufq *bq)
202{
203 gre_bufq_purge(bq);
204 pcq_destroy(bq->bq_q);
205}
206
207static int
208gre_bufq_enqueue(struct gre_bufq *bq, struct mbuf *m)
209{
210 KASSERT(bq->bq_q != NULL);
211
212 if (!pcq_put(bq->bq_q, m)) {
213 bq->bq_drops++;
214 return ENOBUFS;
215 }
216 return 0;
217}
218
219static void
220greintr(void *arg)
221{
222 struct gre_softc *sc = (struct gre_softc *)arg;
223 struct socket *so = sc->sc_soparm.sp_so;
224 int rc;
225 struct mbuf *m;
226
227 KASSERT(so != NULL);
228
229 sc->sc_send_ev.ev_count++;
230 GRE_DPRINTF(sc, "enter\n");
231 while ((m = gre_bufq_dequeue(&sc->sc_snd)) != NULL) {
232 /* XXX handle ENOBUFS? */
233 if ((rc = gre_sosend(so, m)) != 0)
234 GRE_DPRINTF(sc, "gre_sosend failed %d\n", rc);
235 }
236}
237
238/* Caller must hold sc->sc_mtx. */
239static void
240gre_fp_wait(struct gre_softc *sc)
241{
242 sc->sc_fp_waiters++;
243 cv_wait(&sc->sc_fp_condvar, &sc->sc_mtx);
244 sc->sc_fp_waiters--;
245}
246
247static void
248gre_evcnt_detach(struct gre_softc *sc)
249{
250 evcnt_detach(&sc->sc_recv_ev);
251 evcnt_detach(&sc->sc_block_ev);
252 evcnt_detach(&sc->sc_error_ev);
253 evcnt_detach(&sc->sc_pullup_ev);
254 evcnt_detach(&sc->sc_unsupp_ev);
255
256 evcnt_detach(&sc->sc_send_ev);
257 evcnt_detach(&sc->sc_oflow_ev);
258}
259
260static void
261gre_evcnt_attach(struct gre_softc *sc)
262{
263 evcnt_attach_dynamic(&sc->sc_recv_ev, EVCNT_TYPE_MISC,
264 NULL, sc->sc_if.if_xname, "recv");
265 evcnt_attach_dynamic(&sc->sc_block_ev, EVCNT_TYPE_MISC,
266 &sc->sc_recv_ev, sc->sc_if.if_xname, "would block");
267 evcnt_attach_dynamic(&sc->sc_error_ev, EVCNT_TYPE_MISC,
268 &sc->sc_recv_ev, sc->sc_if.if_xname, "error");
269 evcnt_attach_dynamic(&sc->sc_pullup_ev, EVCNT_TYPE_MISC,
270 &sc->sc_recv_ev, sc->sc_if.if_xname, "pullup failed");
271 evcnt_attach_dynamic(&sc->sc_unsupp_ev, EVCNT_TYPE_MISC,
272 &sc->sc_recv_ev, sc->sc_if.if_xname, "unsupported");
273
274 evcnt_attach_dynamic(&sc->sc_send_ev, EVCNT_TYPE_MISC,
275 NULL, sc->sc_if.if_xname, "send");
276 evcnt_attach_dynamic(&sc->sc_oflow_ev, EVCNT_TYPE_MISC,
277 &sc->sc_send_ev, sc->sc_if.if_xname, "overflow");
278}
279
280static int
281gre_clone_create(struct if_clone *ifc, int unit)
282{
283 int rc;
284 struct gre_softc *sc;
285 struct gre_soparm *sp;
286 const struct sockaddr *any;
287
288 if ((any = sockaddr_any_by_family(AF_INET)) == NULL &&
289 (any = sockaddr_any_by_family(AF_INET6)) == NULL)
290 goto fail0;
291
292 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
293 mutex_init(&sc->sc_mtx, MUTEX_DRIVER, IPL_SOFTNET);
294 cv_init(&sc->sc_condvar, "gre wait");
295 cv_init(&sc->sc_fp_condvar, "gre fp");
296
297 if_initname(&sc->sc_if, ifc->ifc_name, unit);
298 sc->sc_if.if_softc = sc;
299 sc->sc_if.if_type = IFT_TUNNEL;
300 sc->sc_if.if_addrlen = 0;
301 sc->sc_if.if_hdrlen = sizeof(struct ip) + sizeof(struct gre_h);
302 sc->sc_if.if_dlt = DLT_NULL;
303 sc->sc_if.if_mtu = GREMTU;
304 sc->sc_if.if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
305 sc->sc_if.if_output = gre_output;
306 sc->sc_if.if_ioctl = gre_ioctl;
307 sp = &sc->sc_soparm;
308 sockaddr_copy(sstosa(&sp->sp_dst), sizeof(sp->sp_dst), any);
309 sockaddr_copy(sstosa(&sp->sp_src), sizeof(sp->sp_src), any);
310 sp->sp_proto = IPPROTO_GRE;
311 sp->sp_type = SOCK_RAW;
312
313 sc->sc_fd = -1;
314
315 rc = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, gre_fp_recvloop, sc,
316 NULL, "%s", sc->sc_if.if_xname);
317 if (rc)
318 goto fail1;
319
320 gre_evcnt_attach(sc);
321
322 gre_bufq_init(&sc->sc_snd, 17);
323 sc->sc_if.if_flags |= IFF_LINK0;
324 if_attach(&sc->sc_if);
325 if_alloc_sadl(&sc->sc_if);
326 bpf_attach(&sc->sc_if, DLT_NULL, sizeof(uint32_t));
327 atomic_inc_uint(&gre_count);
328 return 0;
329
330fail1: cv_destroy(&sc->sc_fp_condvar);
331 cv_destroy(&sc->sc_condvar);
332 mutex_destroy(&sc->sc_mtx);
333 free(sc, M_DEVBUF);
334fail0: return -1;
335}
336
337static int
338gre_clone_destroy(struct ifnet *ifp)
339{
340 int s;
341 struct gre_softc *sc = ifp->if_softc;
342
343 GRE_DPRINTF(sc, "\n");
344
345 bpf_detach(ifp);
346 s = splnet();
347 if_detach(ifp);
348
349 GRE_DPRINTF(sc, "\n");
350 /* Note that we must not hold the mutex while we call gre_reconf(). */
351 gre_reconf(sc, NULL);
352
353 mutex_enter(&sc->sc_mtx);
354 sc->sc_msg = GRE_M_STOP;
355 cv_signal(&sc->sc_fp_condvar);
356 while (sc->sc_fp_waiters > 0)
357 cv_wait(&sc->sc_fp_condvar, &sc->sc_mtx);
358 mutex_exit(&sc->sc_mtx);
359
360 splx(s);
361
362 cv_destroy(&sc->sc_condvar);
363 cv_destroy(&sc->sc_fp_condvar);
364 mutex_destroy(&sc->sc_mtx);
365 gre_bufq_destroy(&sc->sc_snd);
366 gre_evcnt_detach(sc);
367 free(sc, M_DEVBUF);
368
369 atomic_dec_uint(&gre_count);
370 return 0;
371}
372
373static void
374gre_receive(struct socket *so, void *arg, int events, int waitflag)
375{
376 struct gre_softc *sc = (struct gre_softc *)arg;
377 int rc;
378 const struct gre_h *gh;
379 struct mbuf *m;
380
381 GRE_DPRINTF(sc, "enter\n");
382
383 sc->sc_recv_ev.ev_count++;
384
385 rc = gre_soreceive(so, &m);
386 /* TBD Back off if ECONNREFUSED (indicates
387 * ICMP Port Unreachable)?
388 */
389 if (rc == EWOULDBLOCK) {
390 GRE_DPRINTF(sc, "EWOULDBLOCK\n");
391 sc->sc_block_ev.ev_count++;
392 return;
393 } else if (rc != 0 || m == NULL) {
394 GRE_DPRINTF(sc, "%s: rc %d m %p\n",
395 sc->sc_if.if_xname, rc, (void *)m);
396 sc->sc_error_ev.ev_count++;
397 return;
398 }
399 if (m->m_len < sizeof(*gh) && (m = m_pullup(m, sizeof(*gh))) == NULL) {
400 GRE_DPRINTF(sc, "m_pullup failed\n");
401 sc->sc_pullup_ev.ev_count++;
402 return;
403 }
404 gh = mtod(m, const struct gre_h *);
405
406 if (gre_input(sc, m, 0, gh) == 0) {
407 sc->sc_unsupp_ev.ev_count++;
408 GRE_DPRINTF(sc, "dropping unsupported\n");
409 m_freem(m);
410 }
411}
412
413static void
414gre_upcall_add(struct socket *so, void *arg)
415{
416 /* XXX What if the kernel already set an upcall? */
417 KASSERT((so->so_rcv.sb_flags & SB_UPCALL) == 0);
418 so->so_upcallarg = arg;
419 so->so_upcall = gre_receive;
420 so->so_rcv.sb_flags |= SB_UPCALL;
421}
422
423static void
424gre_upcall_remove(struct socket *so)
425{
426 so->so_rcv.sb_flags &= ~SB_UPCALL;
427 so->so_upcallarg = NULL;
428 so->so_upcall = NULL;
429}
430
431static int
432gre_socreate(struct gre_softc *sc, const struct gre_soparm *sp, int *fdout)
433{
434 int fd, rc;
435 struct socket *so;
436 struct sockaddr_big sbig;
437 sa_family_t af;
438 int val;
439
440 GRE_DPRINTF(sc, "enter\n");
441
442 af = sp->sp_src.ss_family;
443 rc = fsocreate(af, NULL, sp->sp_type, sp->sp_proto, &fd);
444 if (rc != 0) {
445 GRE_DPRINTF(sc, "fsocreate failed\n");
446 return rc;
447 }
448
449 if ((rc = fd_getsock(fd, &so)) != 0)
450 return rc;
451
452 memcpy(&sbig, &sp->sp_src, sizeof(sp->sp_src));
453 if ((rc = sobind(so, (struct sockaddr *)&sbig, curlwp)) != 0) {
454 GRE_DPRINTF(sc, "sobind failed\n");
455 goto out;
456 }
457
458 memcpy(&sbig, &sp->sp_dst, sizeof(sp->sp_dst));
459 solock(so);
460 if ((rc = soconnect(so, (struct sockaddr *)&sbig, curlwp)) != 0) {
461 GRE_DPRINTF(sc, "soconnect failed\n");
462 sounlock(so);
463 goto out;
464 }
465 sounlock(so);
466
467 /* XXX convert to a (new) SOL_SOCKET call */
468 KASSERT(so->so_proto != NULL);
469 rc = so_setsockopt(curlwp, so, IPPROTO_IP, IP_TTL,
470 &ip_gre_ttl, sizeof(ip_gre_ttl));
471 if (rc != 0) {
472 GRE_DPRINTF(sc, "so_setsockopt ttl failed\n");
473 rc = 0;
474 }
475
476 val = 1;
477 rc = so_setsockopt(curlwp, so, SOL_SOCKET, SO_NOHEADER,
478 &val, sizeof(val));
479 if (rc != 0) {
480 GRE_DPRINTF(sc, "so_setsockopt SO_NOHEADER failed\n");
481 rc = 0;
482 }
483out:
484 if (rc != 0)
485 fd_close(fd);
486 else {
487 fd_putfile(fd);
488 *fdout = fd;
489 }
490
491 return rc;
492}
493
494static int
495gre_sosend(struct socket *so, struct mbuf *top)
496{
497 struct proc *p;
498 long space, resid;
499 int error;
500 struct lwp * const l = curlwp;
501
502 p = l->l_proc;
503
504 resid = top->m_pkthdr.len;
505 if (p)
506 l->l_ru.ru_msgsnd++;
507#define snderr(errno) { error = errno; goto release; }
508
509 solock(so);
510 if ((error = sblock(&so->so_snd, M_NOWAIT)) != 0)
511 goto out;
512 if (so->so_state & SS_CANTSENDMORE)
513 snderr(EPIPE);
514 if (so->so_error) {
515 error = so->so_error;
516 so->so_error = 0;
517 goto release;
518 }
519 if ((so->so_state & SS_ISCONNECTED) == 0) {
520 if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
521 snderr(ENOTCONN);
522 } else {
523 snderr(EDESTADDRREQ);
524 }
525 }
526 space = sbspace(&so->so_snd);
527 if (resid > so->so_snd.sb_hiwat)
528 snderr(EMSGSIZE);
529 if (space < resid)
530 snderr(EWOULDBLOCK);
531 /*
532 * Data is prepackaged in "top".
533 */
534 if (so->so_state & SS_CANTSENDMORE)
535 snderr(EPIPE);
536 error = (*so->so_proto->pr_usrreqs->pr_send)(so,
537 top, NULL, NULL, l);
538 top = NULL;
539 release:
540 sbunlock(&so->so_snd);
541 out:
542 sounlock(so);
543 if (top != NULL)
544 m_freem(top);
545 return error;
546}
547
548/* This is a stripped-down version of soreceive() that will never
549 * block. It will support SOCK_DGRAM sockets. It may also support
550 * SOCK_SEQPACKET sockets.
551 */
552static int
553gre_soreceive(struct socket *so, struct mbuf **mp0)
554{
555 struct mbuf *m, **mp;
556 int flags, len, error, type;
557 const struct protosw *pr;
558 struct mbuf *nextrecord;
559
560 KASSERT(mp0 != NULL);
561
562 flags = MSG_DONTWAIT;
563 pr = so->so_proto;
564 mp = mp0;
565 type = 0;
566
567 *mp = NULL;
568
569 KASSERT(pr->pr_flags & PR_ATOMIC);
570 restart:
571 if ((error = sblock(&so->so_rcv, M_NOWAIT)) != 0) {
572 return error;
573 }
574 m = so->so_rcv.sb_mb;
575 /*
576 * If we have less data than requested, do not block awaiting more.
577 */
578 if (m == NULL) {
579#ifdef DIAGNOSTIC
580 if (so->so_rcv.sb_cc)
581 panic("receive 1");
582#endif
583 if (so->so_error) {
584 error = so->so_error;
585 so->so_error = 0;
586 } else if (so->so_state & SS_CANTRCVMORE)
587 ;
588 else if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0
589 && (so->so_proto->pr_flags & PR_CONNREQUIRED))
590 error = ENOTCONN;
591 else
592 error = EWOULDBLOCK;
593 goto release;
594 }
595 /*
596 * On entry here, m points to the first record of the socket buffer.
597 * While we process the initial mbufs containing address and control
598 * info, we save a copy of m->m_nextpkt into nextrecord.
599 */
600 if (curlwp != NULL)
601 curlwp->l_ru.ru_msgrcv++;
602 KASSERT(m == so->so_rcv.sb_mb);
603 SBLASTRECORDCHK(&so->so_rcv, "soreceive 1");
604 SBLASTMBUFCHK(&so->so_rcv, "soreceive 1");
605 nextrecord = m->m_nextpkt;
606 if (pr->pr_flags & PR_ADDR) {
607#ifdef DIAGNOSTIC
608 if (m->m_type != MT_SONAME)
609 panic("receive 1a");
610#endif
611 sbfree(&so->so_rcv, m);
612 m = so->so_rcv.sb_mb = m_free(m);
613 }
614 while (m != NULL && m->m_type == MT_CONTROL && error == 0) {
615 sbfree(&so->so_rcv, m);
616 /*
617 * Dispose of any SCM_RIGHTS message that went
618 * through the read path rather than recv.
619 */
620 if (pr->pr_domain->dom_dispose &&
621 mtod(m, struct cmsghdr *)->cmsg_type == SCM_RIGHTS)
622 (*pr->pr_domain->dom_dispose)(m);
623 m = so->so_rcv.sb_mb = m_free(m);
624 }
625
626 /*
627 * If m is non-NULL, we have some data to read. From now on,
628 * make sure to keep sb_lastrecord consistent when working on
629 * the last packet on the chain (nextrecord == NULL) and we
630 * change m->m_nextpkt.
631 */
632 if (m != NULL) {
633 m->m_nextpkt = nextrecord;
634 /*
635 * If nextrecord == NULL (this is a single chain),
636 * then sb_lastrecord may not be valid here if m
637 * was changed earlier.
638 */
639 if (nextrecord == NULL) {
640 KASSERT(so->so_rcv.sb_mb == m);
641 so->so_rcv.sb_lastrecord = m;
642 }
643 type = m->m_type;
644 if (type == MT_OOBDATA)
645 flags |= MSG_OOB;
646 } else {
647 KASSERT(so->so_rcv.sb_mb == m);
648 so->so_rcv.sb_mb = nextrecord;
649 SB_EMPTY_FIXUP(&so->so_rcv);
650 }
651 SBLASTRECORDCHK(&so->so_rcv, "soreceive 2");
652 SBLASTMBUFCHK(&so->so_rcv, "soreceive 2");
653
654 while (m != NULL) {
655 if (m->m_type == MT_OOBDATA) {
656 if (type != MT_OOBDATA)
657 break;
658 } else if (type == MT_OOBDATA)
659 break;
660#ifdef DIAGNOSTIC
661 else if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
662 panic("receive 3");
663#endif
664 so->so_state &= ~SS_RCVATMARK;
665 if (so->so_oobmark != 0 && so->so_oobmark < m->m_len)
666 break;
667 len = m->m_len;
668 /*
669 * mp is set, just pass back the mbufs.
670 * Sockbuf must be consistent here (points to current mbuf,
671 * it points to next record) when we drop priority;
672 * we must note any additions to the sockbuf when we
673 * block interrupts again.
674 */
675 if (m->m_flags & M_EOR)
676 flags |= MSG_EOR;
677 nextrecord = m->m_nextpkt;
678 sbfree(&so->so_rcv, m);
679 *mp = m;
680 mp = &m->m_next;
681 so->so_rcv.sb_mb = m = m->m_next;
682 *mp = NULL;
683 /*
684 * If m != NULL, we also know that
685 * so->so_rcv.sb_mb != NULL.
686 */
687 KASSERT(so->so_rcv.sb_mb == m);
688 if (m) {
689 m->m_nextpkt = nextrecord;
690 if (nextrecord == NULL)
691 so->so_rcv.sb_lastrecord = m;
692 } else {
693 so->so_rcv.sb_mb = nextrecord;
694 SB_EMPTY_FIXUP(&so->so_rcv);
695 }
696 SBLASTRECORDCHK(&so->so_rcv, "soreceive 3");
697 SBLASTMBUFCHK(&so->so_rcv, "soreceive 3");
698 if (so->so_oobmark) {
699 so->so_oobmark -= len;
700 if (so->so_oobmark == 0) {
701 so->so_state |= SS_RCVATMARK;
702 break;
703 }
704 }
705 if (flags & MSG_EOR)
706 break;
707 }
708
709 if (m != NULL) {
710 m_freem(*mp);
711 *mp = NULL;
712 error = ENOMEM;
713 (void) sbdroprecord(&so->so_rcv);
714 } else {
715 /*
716 * First part is an inline SB_EMPTY_FIXUP(). Second
717 * part makes sure sb_lastrecord is up-to-date if
718 * there is still data in the socket buffer.
719 */
720 so->so_rcv.sb_mb = nextrecord;
721 if (so->so_rcv.sb_mb == NULL) {
722 so->so_rcv.sb_mbtail = NULL;
723 so->so_rcv.sb_lastrecord = NULL;
724 } else if (nextrecord->m_nextpkt == NULL)
725 so->so_rcv.sb_lastrecord = nextrecord;
726 }
727 SBLASTRECORDCHK(&so->so_rcv, "soreceive 4");
728 SBLASTMBUFCHK(&so->so_rcv, "soreceive 4");
729 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
730 (*pr->pr_usrreqs->pr_rcvd)(so, flags, curlwp);
731 if (*mp0 == NULL && (flags & MSG_EOR) == 0 &&
732 (so->so_state & SS_CANTRCVMORE) == 0) {
733 sbunlock(&so->so_rcv);
734 goto restart;
735 }
736
737 release:
738 sbunlock(&so->so_rcv);
739 return error;
740}
741
742static struct socket *
743gre_reconf(struct gre_softc *sc, const struct gre_soparm *newsoparm)
744{
745 struct ifnet *ifp = &sc->sc_if;
746
747 GRE_DPRINTF(sc, "enter\n");
748
749shutdown:
750 if (sc->sc_soparm.sp_so != NULL) {
751 GRE_DPRINTF(sc, "\n");
752 gre_upcall_remove(sc->sc_soparm.sp_so);
753 softint_disestablish(sc->sc_si);
754 sc->sc_si = NULL;
755 gre_fp_send(sc, GRE_M_DELFP, NULL);
756 gre_clearconf(&sc->sc_soparm, false);
757 }
758
759 if (newsoparm != NULL) {
760 GRE_DPRINTF(sc, "\n");
761 sc->sc_soparm = *newsoparm;
762 newsoparm = NULL;
763 }
764
765 if (sc->sc_soparm.sp_so != NULL) {
766 GRE_DPRINTF(sc, "\n");
767 sc->sc_si = softint_establish(SOFTINT_NET, greintr, sc);
768 gre_upcall_add(sc->sc_soparm.sp_so, sc);
769 if ((ifp->if_flags & IFF_UP) == 0) {
770 GRE_DPRINTF(sc, "down\n");
771 goto shutdown;
772 }
773 }
774
775 GRE_DPRINTF(sc, "\n");
776 if (sc->sc_soparm.sp_so != NULL)
777 sc->sc_if.if_flags |= IFF_RUNNING;
778 else {
779 gre_bufq_purge(&sc->sc_snd);
780 sc->sc_if.if_flags &= ~IFF_RUNNING;
781 }
782 return sc->sc_soparm.sp_so;
783}
784
785static int
786gre_input(struct gre_softc *sc, struct mbuf *m, int hlen,
787 const struct gre_h *gh)
788{
789 pktqueue_t *pktq = NULL;
790 struct ifqueue *ifq = NULL;
791 uint16_t flags;
792 uint32_t af; /* af passed to BPF tap */
793 int isr = 0, s;
794
795 sc->sc_if.if_ipackets++;
796 sc->sc_if.if_ibytes += m->m_pkthdr.len;
797
798 hlen += sizeof(struct gre_h);
799
800 /* process GRE flags as packet can be of variable len */
801 flags = ntohs(gh->flags);
802
803 /* Checksum & Offset are present */
804 if ((flags & GRE_CP) | (flags & GRE_RP))
805 hlen += 4;
806 /* We don't support routing fields (variable length) */
807 if (flags & GRE_RP) {
808 sc->sc_if.if_ierrors++;
809 return 0;
810 }
811 if (flags & GRE_KP)
812 hlen += 4;
813 if (flags & GRE_SP)
814 hlen += 4;
815
816 switch (ntohs(gh->ptype)) { /* ethertypes */
817#ifdef INET
818 case ETHERTYPE_IP:
819 pktq = ip_pktq;
820 af = AF_INET;
821 break;
822#endif
823#ifdef NETATALK
824 case ETHERTYPE_ATALK:
825 ifq = &atintrq1;
826 isr = NETISR_ATALK;
827 af = AF_APPLETALK;
828 break;
829#endif
830#ifdef INET6
831 case ETHERTYPE_IPV6:
832 pktq = ip6_pktq;
833 af = AF_INET6;
834 break;
835#endif
836#ifdef MPLS
837 case ETHERTYPE_MPLS:
838 ifq = &mplsintrq;
839 isr = NETISR_MPLS;
840 af = AF_MPLS;
841 break;
842#endif
843 default: /* others not yet supported */
844 GRE_DPRINTF(sc, "unhandled ethertype 0x%04x\n",
845 ntohs(gh->ptype));
846 sc->sc_if.if_noproto++;
847 return 0;
848 }
849
850 if (hlen > m->m_pkthdr.len) {
851 m_freem(m);
852 sc->sc_if.if_ierrors++;
853 return EINVAL;
854 }
855 m_adj(m, hlen);
856
857 bpf_mtap_af(&sc->sc_if, af, m);
858
859 m_set_rcvif(m, &sc->sc_if);
860
861 if (__predict_true(pktq)) {
862 if (__predict_false(!pktq_enqueue(pktq, m, 0))) {
863 m_freem(m);
864 }
865 return 1;
866 }
867
868 s = splnet();
869 if (IF_QFULL(ifq)) {
870 IF_DROP(ifq);
871 m_freem(m);
872 } else {
873 IF_ENQUEUE(ifq, m);
874 }
875 /* we need schednetisr since the address family may change */
876 schednetisr(isr);
877 splx(s);
878
879 return 1; /* packet is done, no further processing needed */
880}
881
882/*
883 * The output routine. Takes a packet and encapsulates it in the protocol
884 * given by sc->sc_soparm.sp_proto. See also RFC 1701 and RFC 2004
885 */
886static int
887gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
888 const struct rtentry *rt)
889{
890 int error = 0;
891 struct gre_softc *sc = ifp->if_softc;
892 struct gre_h *gh;
893 uint16_t etype = 0;
894
895 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
896 m_freem(m);
897 error = ENETDOWN;
898 goto end;
899 }
900
901 bpf_mtap_af(ifp, dst->sa_family, m);
902
903 m->m_flags &= ~(M_BCAST|M_MCAST);
904
905 GRE_DPRINTF(sc, "dst->sa_family=%d\n", dst->sa_family);
906 switch (dst->sa_family) {
907#ifdef INET
908 case AF_INET:
909 /* TBD Extract the IP ToS field and set the
910 * encapsulating protocol's ToS to suit.
911 */
912 etype = htons(ETHERTYPE_IP);
913 break;
914#endif
915#ifdef NETATALK
916 case AF_APPLETALK:
917 etype = htons(ETHERTYPE_ATALK);
918 break;
919#endif
920#ifdef INET6
921 case AF_INET6:
922 etype = htons(ETHERTYPE_IPV6);
923 break;
924#endif
925 default:
926 IF_DROP(&ifp->if_snd);
927 m_freem(m);
928 error = EAFNOSUPPORT;
929 goto end;
930 }
931
932#ifdef MPLS
933 if (rt != NULL && rt_gettag(rt) != NULL) {
934 union mpls_shim msh;
935 msh.s_addr = MPLS_GETSADDR(rt);
936 if (msh.shim.label != MPLS_LABEL_IMPLNULL)
937 etype = htons(ETHERTYPE_MPLS);
938 }
939#endif
940
941 M_PREPEND(m, sizeof(*gh), M_DONTWAIT);
942
943 if (m == NULL) {
944 IF_DROP(&ifp->if_snd);
945 error = ENOBUFS;
946 goto end;
947 }
948
949 gh = mtod(m, struct gre_h *);
950 gh->flags = 0;
951 gh->ptype = etype;
952 /* XXX Need to handle IP ToS. Look at how I handle IP TTL. */
953
954 ifp->if_opackets++;
955 ifp->if_obytes += m->m_pkthdr.len;
956
957 /* Clear checksum-offload flags. */
958 m->m_pkthdr.csum_flags = 0;
959 m->m_pkthdr.csum_data = 0;
960
961 /* send it off */
962 if ((error = gre_bufq_enqueue(&sc->sc_snd, m)) != 0) {
963 sc->sc_oflow_ev.ev_count++;
964 m_freem(m);
965 } else
966 softint_schedule(sc->sc_si);
967 end:
968 if (error)
969 ifp->if_oerrors++;
970 return error;
971}
972
973static int
974gre_getsockname(struct socket *so, struct sockaddr *nam)
975{
976 return (*so->so_proto->pr_usrreqs->pr_sockaddr)(so, nam);
977}
978
979static int
980gre_getpeername(struct socket *so, struct sockaddr *nam)
981{
982 return (*so->so_proto->pr_usrreqs->pr_peeraddr)(so, nam);
983}
984
985static int
986gre_getnames(struct socket *so, struct lwp *l, struct sockaddr_storage *src,
987 struct sockaddr_storage *dst)
988{
989 struct sockaddr_storage ss;
990 int rc;
991
992 solock(so);
993 if ((rc = gre_getsockname(so, (struct sockaddr *)&ss)) != 0)
994 goto out;
995 *src = ss;
996
997 if ((rc = gre_getpeername(so, (struct sockaddr *)&ss)) != 0)
998 goto out;
999 *dst = ss;
1000out:
1001 sounlock(so);
1002 return rc;
1003}
1004
1005static void
1006gre_fp_recvloop(void *arg)
1007{
1008 struct gre_softc *sc = arg;
1009
1010 mutex_enter(&sc->sc_mtx);
1011 while (gre_fp_recv(sc))
1012 ;
1013 mutex_exit(&sc->sc_mtx);
1014 kthread_exit(0);
1015}
1016
1017static bool
1018gre_fp_recv(struct gre_softc *sc)
1019{
1020 int fd, ofd, rc;
1021 file_t *fp;
1022
1023 fp = sc->sc_fp;
1024 ofd = sc->sc_fd;
1025 fd = -1;
1026
1027 switch (sc->sc_msg) {
1028 case GRE_M_STOP:
1029 cv_signal(&sc->sc_fp_condvar);
1030 return false;
1031 case GRE_M_SETFP:
1032 mutex_exit(&sc->sc_mtx);
1033 rc = fd_dup(fp, 0, &fd, 0);
1034 mutex_enter(&sc->sc_mtx);
1035 if (rc != 0) {
1036 sc->sc_msg = GRE_M_ERR;
1037 break;
1038 }
1039 /*FALLTHROUGH*/
1040 case GRE_M_DELFP:
1041 mutex_exit(&sc->sc_mtx);
1042 if (ofd != -1 && fd_getfile(ofd) != NULL)
1043 fd_close(ofd);
1044 mutex_enter(&sc->sc_mtx);
1045 sc->sc_fd = fd;
1046 sc->sc_msg = GRE_M_OK;
1047 break;
1048 default:
1049 gre_fp_wait(sc);
1050 return true;
1051 }
1052 cv_signal(&sc->sc_fp_condvar);
1053 return true;
1054}
1055
1056static bool
1057gre_fp_send(struct gre_softc *sc, enum gre_msg msg, file_t *fp)
1058{
1059 bool rc;
1060
1061 mutex_enter(&sc->sc_mtx);
1062 while (sc->sc_msg != GRE_M_NONE)
1063 gre_fp_wait(sc);
1064 sc->sc_fp = fp;
1065 sc->sc_msg = msg;
1066 cv_signal(&sc->sc_fp_condvar);
1067 while (sc->sc_msg != GRE_M_STOP && sc->sc_msg != GRE_M_OK &&
1068 sc->sc_msg != GRE_M_ERR)
1069 gre_fp_wait(sc);
1070 rc = (sc->sc_msg != GRE_M_ERR);
1071 sc->sc_msg = GRE_M_NONE;
1072 cv_signal(&sc->sc_fp_condvar);
1073 mutex_exit(&sc->sc_mtx);
1074 return rc;
1075}
1076
1077static int
1078gre_ssock(struct ifnet *ifp, struct gre_soparm *sp, int fd)
1079{
1080 int error = 0;
1081 const struct protosw *pr;
1082 file_t *fp;
1083 struct gre_softc *sc = ifp->if_softc;
1084 struct socket *so;
1085 struct sockaddr_storage dst, src;
1086
1087 if ((fp = fd_getfile(fd)) == NULL)
1088 return EBADF;
1089 if (fp->f_type != DTYPE_SOCKET) {
1090 fd_putfile(fd);
1091 return ENOTSOCK;
1092 }
1093
1094 GRE_DPRINTF(sc, "\n");
1095
1096 so = fp->f_socket;
1097 pr = so->so_proto;
1098
1099 GRE_DPRINTF(sc, "type %d, proto %d\n", pr->pr_type, pr->pr_protocol);
1100
1101 if ((pr->pr_flags & PR_ATOMIC) == 0 ||
1102 (sp->sp_type != 0 && pr->pr_type != sp->sp_type) ||
1103 (sp->sp_proto != 0 && pr->pr_protocol != 0 &&
1104 pr->pr_protocol != sp->sp_proto)) {
1105 error = EINVAL;
1106 goto err;
1107 }
1108
1109 GRE_DPRINTF(sc, "\n");
1110
1111 /* check address */
1112 if ((error = gre_getnames(so, curlwp, &src, &dst)) != 0)
1113 goto err;
1114
1115 GRE_DPRINTF(sc, "\n");
1116
1117 if (!gre_fp_send(sc, GRE_M_SETFP, fp)) {
1118 error = EBUSY;
1119 goto err;
1120 }
1121
1122 GRE_DPRINTF(sc, "\n");
1123
1124 sp->sp_src = src;
1125 sp->sp_dst = dst;
1126
1127 sp->sp_so = so;
1128
1129err:
1130 fd_putfile(fd);
1131 return error;
1132}
1133
1134static bool
1135sockaddr_is_anyaddr(const struct sockaddr *sa)
1136{
1137 socklen_t anylen, salen;
1138 const void *anyaddr, *addr;
1139
1140 if ((anyaddr = sockaddr_anyaddr(sa, &anylen)) == NULL ||
1141 (addr = sockaddr_const_addr(sa, &salen)) == NULL)
1142 return false;
1143
1144 if (salen > anylen)
1145 return false;
1146
1147 return memcmp(anyaddr, addr, MIN(anylen, salen)) == 0;
1148}
1149
1150static bool
1151gre_is_nullconf(const struct gre_soparm *sp)
1152{
1153 return sockaddr_is_anyaddr(sstocsa(&sp->sp_src)) ||
1154 sockaddr_is_anyaddr(sstocsa(&sp->sp_dst));
1155}
1156
1157static void
1158gre_clearconf(struct gre_soparm *sp, bool force)
1159{
1160 if (sp->sp_bysock || force) {
1161 sockaddr_copy(sstosa(&sp->sp_src), sizeof(sp->sp_src),
1162 sockaddr_any(sstosa(&sp->sp_src)));
1163 sockaddr_copy(sstosa(&sp->sp_dst), sizeof(sp->sp_dst),
1164 sockaddr_any(sstosa(&sp->sp_dst)));
1165 sp->sp_bysock = false;
1166 }
1167 sp->sp_so = NULL; /* XXX */
1168}
1169
1170static int
1171gre_ioctl(struct ifnet *ifp, const u_long cmd, void *data)
1172{
1173 struct ifreq *ifr;
1174 struct ifaddr *ifa = (struct ifaddr *)data;
1175 struct if_laddrreq *lifr = (struct if_laddrreq *)data;
1176 struct gre_softc *sc = ifp->if_softc;
1177 struct gre_soparm *sp;
1178 int fd, error = 0, oproto, otype, s;
1179 struct gre_soparm sp0;
1180
1181 ifr = data;
1182
1183 GRE_DPRINTF(sc, "cmd %lu\n", cmd);
1184
1185 switch (cmd) {
1186 case GRESPROTO:
1187 case GRESADDRD:
1188 case GRESADDRS:
1189 case GRESSOCK:
1190 case GREDSOCK:
1191 if (kauth_authorize_network(curlwp->l_cred,
1192 KAUTH_NETWORK_INTERFACE,
1193 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
1194 NULL) != 0)
1195 return EPERM;
1196 break;
1197 default:
1198 break;
1199 }
1200
1201 s = splnet();
1202
1203 sp0 = sc->sc_soparm;
1204 sp0.sp_so = NULL;
1205 sp = &sp0;
1206
1207 GRE_DPRINTF(sc, "\n");
1208
1209 switch (cmd) {
1210 case SIOCINITIFADDR:
1211 GRE_DPRINTF(sc, "\n");
1212 if ((ifp->if_flags & IFF_UP) != 0)
1213 break;
1214 gre_clearconf(sp, false);
1215 ifp->if_flags |= IFF_UP;
1216 ifa->ifa_rtrequest = p2p_rtrequest;
1217 goto mksocket;
1218 case SIOCSIFFLAGS:
1219 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
1220 break;
1221 oproto = sp->sp_proto;
1222 otype = sp->sp_type;
1223 switch (ifr->ifr_flags & (IFF_LINK0|IFF_LINK2)) {
1224 case IFF_LINK0|IFF_LINK2:
1225 sp->sp_proto = IPPROTO_UDP;
1226 sp->sp_type = SOCK_DGRAM;
1227 break;
1228 case IFF_LINK2:
1229 sp->sp_proto = 0;
1230 sp->sp_type = 0;
1231 break;
1232 case IFF_LINK0:
1233 sp->sp_proto = IPPROTO_GRE;
1234 sp->sp_type = SOCK_RAW;
1235 break;
1236 default:
1237 GRE_DPRINTF(sc, "\n");
1238 error = EINVAL;
1239 goto out;
1240 }
1241 GRE_DPRINTF(sc, "\n");
1242 gre_clearconf(sp, false);
1243 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) ==
1244 (IFF_UP|IFF_RUNNING) &&
1245 (oproto == sp->sp_proto || sp->sp_proto == 0) &&
1246 (otype == sp->sp_type || sp->sp_type == 0))
1247 break;
1248 switch (sp->sp_proto) {
1249 case IPPROTO_UDP:
1250 case IPPROTO_GRE:
1251 goto mksocket;
1252 default:
1253 break;
1254 }
1255 break;
1256 case SIOCSIFMTU:
1257 /* XXX determine MTU automatically by probing w/
1258 * XXX do-not-fragment packets?
1259 */
1260 if (ifr->ifr_mtu < 576) {
1261 error = EINVAL;
1262 break;
1263 }
1264 /*FALLTHROUGH*/
1265 case SIOCGIFMTU:
1266 if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET)
1267 error = 0;
1268 break;
1269 case SIOCADDMULTI:
1270 case SIOCDELMULTI:
1271 if (ifr == NULL) {
1272 error = EAFNOSUPPORT;
1273 break;
1274 }
1275 switch (ifreq_getaddr(cmd, ifr)->sa_family) {
1276#ifdef INET
1277 case AF_INET:
1278 break;
1279#endif
1280#ifdef INET6
1281 case AF_INET6:
1282 break;
1283#endif
1284 default:
1285 error = EAFNOSUPPORT;
1286 break;
1287 }
1288 break;
1289 case GRESPROTO:
1290 gre_clearconf(sp, false);
1291 oproto = sp->sp_proto;
1292 otype = sp->sp_type;
1293 sp->sp_proto = ifr->ifr_flags;
1294 switch (sp->sp_proto) {
1295 case IPPROTO_UDP:
1296 ifp->if_flags |= IFF_LINK0|IFF_LINK2;
1297 sp->sp_type = SOCK_DGRAM;
1298 break;
1299 case IPPROTO_GRE:
1300 ifp->if_flags |= IFF_LINK0;
1301 ifp->if_flags &= ~IFF_LINK2;
1302 sp->sp_type = SOCK_RAW;
1303 break;
1304 case 0:
1305 ifp->if_flags &= ~IFF_LINK0;
1306 ifp->if_flags |= IFF_LINK2;
1307 sp->sp_type = 0;
1308 break;
1309 default:
1310 error = EPROTONOSUPPORT;
1311 break;
1312 }
1313 if ((oproto == sp->sp_proto || sp->sp_proto == 0) &&
1314 (otype == sp->sp_type || sp->sp_type == 0))
1315 break;
1316 switch (sp->sp_proto) {
1317 case IPPROTO_UDP:
1318 case IPPROTO_GRE:
1319 goto mksocket;
1320 default:
1321 break;
1322 }
1323 break;
1324 case GREGPROTO:
1325 ifr->ifr_flags = sp->sp_proto;
1326 break;
1327 case GRESADDRS:
1328 case GRESADDRD:
1329 gre_clearconf(sp, false);
1330 /* set tunnel endpoints and mark interface as up */
1331 switch (cmd) {
1332 case GRESADDRS:
1333 sockaddr_copy(sstosa(&sp->sp_src),
1334 sizeof(sp->sp_src), ifreq_getaddr(cmd, ifr));
1335 break;
1336 case GRESADDRD:
1337 sockaddr_copy(sstosa(&sp->sp_dst),
1338 sizeof(sp->sp_dst), ifreq_getaddr(cmd, ifr));
1339 break;
1340 }
1341 checkaddr:
1342 if (sockaddr_any(sstosa(&sp->sp_src)) == NULL ||
1343 sockaddr_any(sstosa(&sp->sp_dst)) == NULL) {
1344 error = EINVAL;
1345 break;
1346 }
1347 /* let gre_socreate() check the rest */
1348 mksocket:
1349 GRE_DPRINTF(sc, "\n");
1350 /* If we're administratively down, or the configuration
1351 * is empty, there's no use creating a socket.
1352 */
1353 if ((ifp->if_flags & IFF_UP) == 0 || gre_is_nullconf(sp))
1354 goto sendconf;
1355
1356 GRE_DPRINTF(sc, "\n");
1357 fd = 0;
1358 error = gre_socreate(sc, sp, &fd);
1359 if (error != 0)
1360 break;
1361
1362 setsock:
1363 GRE_DPRINTF(sc, "\n");
1364
1365 error = gre_ssock(ifp, sp, fd);
1366
1367 if (cmd != GRESSOCK) {
1368 GRE_DPRINTF(sc, "\n");
1369 /* XXX v. dodgy */
1370 if (fd_getfile(fd) != NULL)
1371 fd_close(fd);
1372 }
1373
1374 if (error == 0) {
1375 sendconf:
1376 GRE_DPRINTF(sc, "\n");
1377 ifp->if_flags &= ~IFF_RUNNING;
1378 gre_reconf(sc, sp);
1379 }
1380
1381 break;
1382 case GREGADDRS:
1383 ifreq_setaddr(cmd, ifr, sstosa(&sp->sp_src));
1384 break;
1385 case GREGADDRD:
1386 ifreq_setaddr(cmd, ifr, sstosa(&sp->sp_dst));
1387 break;
1388 case GREDSOCK:
1389 GRE_DPRINTF(sc, "\n");
1390 if (sp->sp_bysock)
1391 ifp->if_flags &= ~IFF_UP;
1392 gre_clearconf(sp, false);
1393 goto mksocket;
1394 case GRESSOCK:
1395 GRE_DPRINTF(sc, "\n");
1396 gre_clearconf(sp, true);
1397 fd = (int)ifr->ifr_value;
1398 sp->sp_bysock = true;
1399 ifp->if_flags |= IFF_UP;
1400 goto setsock;
1401 case SIOCSLIFPHYADDR:
1402 GRE_DPRINTF(sc, "\n");
1403 if (lifr->addr.ss_family != lifr->dstaddr.ss_family) {
1404 error = EAFNOSUPPORT;
1405 break;
1406 }
1407 sockaddr_copy(sstosa(&sp->sp_src), sizeof(sp->sp_src),
1408 sstosa(&lifr->addr));
1409 sockaddr_copy(sstosa(&sp->sp_dst), sizeof(sp->sp_dst),
1410 sstosa(&lifr->dstaddr));
1411 GRE_DPRINTF(sc, "\n");
1412 goto checkaddr;
1413 case SIOCDIFPHYADDR:
1414 GRE_DPRINTF(sc, "\n");
1415 gre_clearconf(sp, true);
1416 ifp->if_flags &= ~IFF_UP;
1417 goto mksocket;
1418 case SIOCGLIFPHYADDR:
1419 GRE_DPRINTF(sc, "\n");
1420 if (gre_is_nullconf(sp)) {
1421 error = EADDRNOTAVAIL;
1422 break;
1423 }
1424 sockaddr_copy(sstosa(&lifr->addr), sizeof(lifr->addr),
1425 sstosa(&sp->sp_src));
1426 sockaddr_copy(sstosa(&lifr->dstaddr), sizeof(lifr->dstaddr),
1427 sstosa(&sp->sp_dst));
1428 GRE_DPRINTF(sc, "\n");
1429 break;
1430 default:
1431 error = ifioctl_common(ifp, cmd, data);
1432 break;
1433 }
1434out:
1435 GRE_DPRINTF(sc, "\n");
1436 splx(s);
1437 return error;
1438}
1439
1440/* ARGSUSED */
1441void
1442greattach(int count)
1443{
1444
1445 /*
1446 * Nothing to do here, initialization is handled by the
1447 * module initialization code in greinit() below).
1448 */
1449}
1450
1451static void
1452greinit(void)
1453{
1454 if_clone_attach(&gre_cloner);
1455}
1456
1457static int
1458gredetach(void)
1459{
1460 int error = 0;
1461
1462 if (gre_count != 0)
1463 error = EBUSY;
1464
1465 if (error == 0)
1466 if_clone_detach(&gre_cloner);
1467
1468 return error;
1469}
1470
1471/*
1472 * Module infrastructure
1473 */
1474#include "if_module.h"
1475
1476IF_MODULE(MODULE_CLASS_DRIVER, gre, "")
1477