if_me.c (c00bf7307678c1ec7feb5b0c16f0ad888bd8fac6) if_me.c (6d8fdfa9d5e7d4871c5039b0131829f9cbefeee9)
1/*-
2 * Copyright (c) 2014 Andrey V. Elsukov <ae@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *

--- 23 unchanged lines hidden (view full) ---

32#include <sys/kernel.h>
33#include <sys/lock.h>
34#include <sys/libkern.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
37#include <sys/mbuf.h>
38#include <sys/priv.h>
39#include <sys/proc.h>
1/*-
2 * Copyright (c) 2014 Andrey V. Elsukov <ae@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *

--- 23 unchanged lines hidden (view full) ---

32#include <sys/kernel.h>
33#include <sys/lock.h>
34#include <sys/libkern.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
37#include <sys/mbuf.h>
38#include <sys/priv.h>
39#include <sys/proc.h>
40#include <sys/protosw.h>
41#include <sys/rmlock.h>
42#include <sys/socket.h>
43#include <sys/sockio.h>
44#include <sys/sx.h>
45#include <sys/sysctl.h>
46#include <sys/syslog.h>
47#include <sys/systm.h>
48

--- 68 unchanged lines hidden (view full) ---

117static VNET_DEFINE(struct if_clone *, me_cloner);
118#define V_me_cloner VNET(me_cloner)
119
120static void me_qflush(struct ifnet *);
121static int me_transmit(struct ifnet *, struct mbuf *);
122static int me_ioctl(struct ifnet *, u_long, caddr_t);
123static int me_output(struct ifnet *, struct mbuf *,
124 const struct sockaddr *, struct route *);
40#include <sys/rmlock.h>
41#include <sys/socket.h>
42#include <sys/sockio.h>
43#include <sys/sx.h>
44#include <sys/sysctl.h>
45#include <sys/syslog.h>
46#include <sys/systm.h>
47

--- 68 unchanged lines hidden (view full) ---

116static VNET_DEFINE(struct if_clone *, me_cloner);
117#define V_me_cloner VNET(me_cloner)
118
119static void me_qflush(struct ifnet *);
120static int me_transmit(struct ifnet *, struct mbuf *);
121static int me_ioctl(struct ifnet *, u_long, caddr_t);
122static int me_output(struct ifnet *, struct mbuf *,
123 const struct sockaddr *, struct route *);
125static int me_input(struct mbuf **, int *, int);
124static int me_input(struct mbuf *, int, int, void *);
126
127static int me_set_tunnel(struct ifnet *, struct sockaddr_in *,
128 struct sockaddr_in *);
129static void me_delete_tunnel(struct ifnet *);
125
126static int me_set_tunnel(struct ifnet *, struct sockaddr_in *,
127 struct sockaddr_in *);
128static void me_delete_tunnel(struct ifnet *);
129static int me_encapcheck(const struct mbuf *, int, int, void *);
130
130
131#define ME_MINLEN (sizeof(struct ip) + sizeof(struct mobhdr) -\
132 sizeof(in_addr_t))
133static const struct encap_config ipv4_encap_cfg = {
134 .proto = IPPROTO_MOBILE,
135 .min_length = ME_MINLEN,
136 .exact_match = (sizeof(in_addr_t) << 4) + 8,
137 .check = me_encapcheck,
138 .input = me_input
139};
140
131SYSCTL_DECL(_net_link);
132static SYSCTL_NODE(_net_link, IFT_TUNNEL, me, CTLFLAG_RW, 0,
133 "Minimal Encapsulation for IP (RFC 2004)");
134#ifndef MAX_ME_NEST
135#define MAX_ME_NEST 1
136#endif
137
138static VNET_DEFINE(int, max_me_nesting) = MAX_ME_NEST;
139#define V_max_me_nesting VNET(max_me_nesting)
140SYSCTL_INT(_net_link_me, OID_AUTO, max_nesting, CTLFLAG_RW | CTLFLAG_VNET,
141 &VNET_NAME(max_me_nesting), 0, "Max nested tunnels");
142
141SYSCTL_DECL(_net_link);
142static SYSCTL_NODE(_net_link, IFT_TUNNEL, me, CTLFLAG_RW, 0,
143 "Minimal Encapsulation for IP (RFC 2004)");
144#ifndef MAX_ME_NEST
145#define MAX_ME_NEST 1
146#endif
147
148static VNET_DEFINE(int, max_me_nesting) = MAX_ME_NEST;
149#define V_max_me_nesting VNET(max_me_nesting)
150SYSCTL_INT(_net_link_me, OID_AUTO, max_nesting, CTLFLAG_RW | CTLFLAG_VNET,
151 &VNET_NAME(max_me_nesting), 0, "Max nested tunnels");
152
143extern struct domain inetdomain;
144static const struct protosw in_mobile_protosw = {
145 .pr_type = SOCK_RAW,
146 .pr_domain = &inetdomain,
147 .pr_protocol = IPPROTO_MOBILE,
148 .pr_flags = PR_ATOMIC|PR_ADDR,
149 .pr_input = me_input,
150 .pr_output = rip_output,
151 .pr_ctlinput = rip_ctlinput,
152 .pr_ctloutput = rip_ctloutput,
153 .pr_usrreqs = &rip_usrreqs
154};
155
156static void
157vnet_me_init(const void *unused __unused)
158{
159 LIST_INIT(&V_me_softc_list);
160 ME_LIST_LOCK_INIT();
161 V_me_cloner = if_clone_simple(mename, me_clone_create,
162 me_clone_destroy, 0);
163}

--- 165 unchanged lines hidden (view full) ---

329 int ret;
330
331 sc = (struct me_softc *)arg;
332 if ((ME2IFP(sc)->if_flags & IFF_UP) == 0)
333 return (0);
334
335 M_ASSERTPKTHDR(m);
336
153static void
154vnet_me_init(const void *unused __unused)
155{
156 LIST_INIT(&V_me_softc_list);
157 ME_LIST_LOCK_INIT();
158 V_me_cloner = if_clone_simple(mename, me_clone_create,
159 me_clone_destroy, 0);
160}

--- 165 unchanged lines hidden (view full) ---

326 int ret;
327
328 sc = (struct me_softc *)arg;
329 if ((ME2IFP(sc)->if_flags & IFF_UP) == 0)
330 return (0);
331
332 M_ASSERTPKTHDR(m);
333
337 if (m->m_pkthdr.len < sizeof(struct ip) + sizeof(struct mobhdr) -
338 sizeof(struct in_addr))
339 return (0);
340
341 ret = 0;
342 ME_RLOCK(sc);
343 if (ME_READY(sc)) {
344 ip = mtod(m, struct ip *);
345 if (sc->me_src.s_addr == ip->ip_dst.s_addr &&
346 sc->me_dst.s_addr == ip->ip_src.s_addr)
334 ret = 0;
335 ME_RLOCK(sc);
336 if (ME_READY(sc)) {
337 ip = mtod(m, struct ip *);
338 if (sc->me_src.s_addr == ip->ip_dst.s_addr &&
339 sc->me_dst.s_addr == ip->ip_src.s_addr)
347 ret = 32 * 2;
340 ret = 32 * 2 + 8;
348 }
349 ME_RUNLOCK(sc);
350 return (ret);
351}
352
353static int
354me_set_tunnel(struct ifnet *ifp, struct sockaddr_in *src,
355 struct sockaddr_in *dst)

--- 15 unchanged lines hidden (view full) ---

371 ME_LIST_UNLOCK();
372
373 ME_WLOCK(sc);
374 sc->me_dst = dst->sin_addr;
375 sc->me_src = src->sin_addr;
376 ME_WUNLOCK(sc);
377
378 if (sc->me_ecookie == NULL)
341 }
342 ME_RUNLOCK(sc);
343 return (ret);
344}
345
346static int
347me_set_tunnel(struct ifnet *ifp, struct sockaddr_in *src,
348 struct sockaddr_in *dst)

--- 15 unchanged lines hidden (view full) ---

364 ME_LIST_UNLOCK();
365
366 ME_WLOCK(sc);
367 sc->me_dst = dst->sin_addr;
368 sc->me_src = src->sin_addr;
369 ME_WUNLOCK(sc);
370
371 if (sc->me_ecookie == NULL)
379 sc->me_ecookie = encap_attach_func(AF_INET, IPPROTO_MOBILE,
380 me_encapcheck, &in_mobile_protosw, sc);
372 sc->me_ecookie = ip_encap_attach(&ipv4_encap_cfg,
373 sc, M_WAITOK);
381 if (sc->me_ecookie != NULL) {
382 ifp->if_drv_flags |= IFF_DRV_RUNNING;
383 if_link_state_change(ifp, LINK_STATE_UP);
384 }
385 return (0);
386}
387
388static void
389me_delete_tunnel(struct ifnet *ifp)
390{
391 struct me_softc *sc = ifp->if_softc;
392
393 sx_assert(&me_ioctl_sx, SA_XLOCKED);
394 if (sc->me_ecookie != NULL)
374 if (sc->me_ecookie != NULL) {
375 ifp->if_drv_flags |= IFF_DRV_RUNNING;
376 if_link_state_change(ifp, LINK_STATE_UP);
377 }
378 return (0);
379}
380
381static void
382me_delete_tunnel(struct ifnet *ifp)
383{
384 struct me_softc *sc = ifp->if_softc;
385
386 sx_assert(&me_ioctl_sx, SA_XLOCKED);
387 if (sc->me_ecookie != NULL)
395 encap_detach(sc->me_ecookie);
388 ip_encap_detach(sc->me_ecookie);
396 sc->me_ecookie = NULL;
397 ME_WLOCK(sc);
398 sc->me_src.s_addr = 0;
399 sc->me_dst.s_addr = 0;
400 ME_WUNLOCK(sc);
401 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
402 if_link_state_change(ifp, LINK_STATE_DOWN);
403}

--- 5 unchanged lines hidden (view full) ---

409
410 while (nwords-- > 0)
411 sum += *p++;
412 sum = (sum >> 16) + (sum & 0xffff);
413 sum += (sum >> 16);
414 return (~sum);
415}
416
389 sc->me_ecookie = NULL;
390 ME_WLOCK(sc);
391 sc->me_src.s_addr = 0;
392 sc->me_dst.s_addr = 0;
393 ME_WUNLOCK(sc);
394 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
395 if_link_state_change(ifp, LINK_STATE_DOWN);
396}

--- 5 unchanged lines hidden (view full) ---

402
403 while (nwords-- > 0)
404 sum += *p++;
405 sum = (sum >> 16) + (sum & 0xffff);
406 sum += (sum >> 16);
407 return (~sum);
408}
409
417int
418me_input(struct mbuf **mp, int *offp, int proto)
410static int
411me_input(struct mbuf *m, int off, int proto, void *arg)
419{
412{
420 struct me_softc *sc;
413 struct me_softc *sc = arg;
421 struct mobhdr *mh;
422 struct ifnet *ifp;
414 struct mobhdr *mh;
415 struct ifnet *ifp;
423 struct mbuf *m;
424 struct ip *ip;
425 int hlen;
426
416 struct ip *ip;
417 int hlen;
418
427 m = *mp;
428 sc = encap_getarg(m);
429 KASSERT(sc != NULL, ("encap_getarg returned NULL"));
430
431 ifp = ME2IFP(sc);
432 /* checks for short packets */
433 hlen = sizeof(struct mobhdr);
434 if (m->m_pkthdr.len < sizeof(struct ip) + hlen)
435 hlen -= sizeof(struct in_addr);
436 if (m->m_len < sizeof(struct ip) + hlen)
437 m = m_pullup(m, sizeof(struct ip) + hlen);
438 if (m == NULL)

--- 226 unchanged lines hidden ---
419 ifp = ME2IFP(sc);
420 /* checks for short packets */
421 hlen = sizeof(struct mobhdr);
422 if (m->m_pkthdr.len < sizeof(struct ip) + hlen)
423 hlen -= sizeof(struct in_addr);
424 if (m->m_len < sizeof(struct ip) + hlen)
425 m = m_pullup(m, sizeof(struct ip) + hlen);
426 if (m == NULL)

--- 226 unchanged lines hidden ---