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