this implements MikroTiks Ethernet over IP protocol support.
The Mikrotik protocol is basically GRE, so this is implemented as
eoip(4) as (yet another) part of if_gre. the main differences between
egre and eoip is that eoip uses gre version 1 (not 0) and 0x6400
as the protocol identifier (not transparent ethernet as per rfc
1701), mandates a key header, but splits the key into 16bit len and
tunnel id fields (a bit like pptp).
the keepalive semantics are also different. keepalives are just 0
length packets, and arent echoed. each side listens for the others
packet to see if theyre up, but doesn't relay the keepalives. theyre
more hellos maybe?
like egre though, it still misaligns the payload, but what doesnt
these days?
this also tweaks tcpdump to better support the protocol.
ok?
Index: sys/net/if_gre.c
===
RCS file: /cvs/src/sys/net/if_gre.c,v
retrieving revision 1.122
diff -u -p -r1.122 if_gre.c
--- sys/net/if_gre.c12 Mar 2018 12:47:35 - 1.122
+++ sys/net/if_gre.c27 May 2018 00:12:36 -
@@ -124,6 +124,13 @@ struct gre_h_key {
uint32_tgre_key;
} __packed __aligned(4);
+#define GRE_EOIP 0x6400
+
+struct gre_h_key_eoip {
+ uint16_teoip_len; /* network order */
+ uint16_teoip_tunnel_id; /* little endian */
+} __packed __aligned(4);
+
#define NVGRE_VSID_RES_MIN 0x00 /* reserved for future use */
#define NVGRE_VSID_RES_MAX 0x000fff
#define NVGRE_VSID_NVE2NVE 0xff /* vendor specific NVE-to-NVE comms */
@@ -211,6 +218,12 @@ static struct mbuf *
#define gre_encap(_t, _m, _p, _ttl, _tos) \
gre_encap_dst((_t), &(_t)->t_dst, (_m), (_p), (_ttl), (_tos))
+static struct mbuf *
+ gre_encap_dst_ip(const struct gre_tunnel *,
+ const union gre_addr *, struct mbuf *, uint8_t, uint8_t);
+#define gre_encap_ip(_t, _m, _ttl, _tos) \
+ gre_encap_dst_ip((_t), &(_t)->t_dst, (_m), (_ttl), (_tos))
+
static int
gre_ip_output(const struct gre_tunnel *, struct mbuf *);
@@ -266,7 +279,7 @@ static int gre_ioctl(struct ifnet *, u_l
static int gre_up(struct gre_softc *);
static int gre_down(struct gre_softc *);
-static voidgre_link_state(struct gre_softc *);
+static voidgre_link_state(struct ifnet *, unsigned int);
static int gre_input_key(struct mbuf **, int *, int, int,
struct gre_tunnel *);
@@ -457,6 +470,61 @@ struct nvgre_ucast_tree nvgre_ucast_tree
struct nvgre_mcast_tree nvgre_mcast_tree = RBT_INITIALIZER();
/*
+ * MikroTik Ethernet over IP protocol (eoip)
+ */
+
+struct eoip_softc {
+ struct gre_tunnel sc_tunnel; /* must be first */
+ uint16_tsc_tunnel_id;
+ RBT_ENTRY(eoip_softc) sc_entry;
+
+ struct arpcom sc_ac;
+ struct ifmedia sc_media;
+
+ struct timeout sc_ka_send;
+ struct timeout sc_ka_hold;
+
+ unsigned intsc_ka_state;
+ unsigned intsc_ka_timeo;
+ unsigned intsc_ka_count;
+
+ unsigned intsc_ka_holdmax;
+ unsigned intsc_ka_holdcnt;
+};
+
+RBT_HEAD(eoip_tree, eoip_softc);
+
+static inline int
+ eoip_cmp(const struct eoip_softc *, const struct eoip_softc *);
+
+RBT_PROTOTYPE(eoip_tree, eoip_softc, sc_entry, eoip_cmp);
+
+static int eoip_clone_create(struct if_clone *, int);
+static int eoip_clone_destroy(struct ifnet *);
+
+static voideoip_start(struct ifnet *);
+static int eoip_ioctl(struct ifnet *, u_long, caddr_t);
+
+static voideoip_keepalive_send(void *);
+static voideoip_keepalive_recv(struct eoip_softc *);
+static voideoip_keepalive_hold(void *);
+
+static int eoip_up(struct eoip_softc *);
+static int eoip_down(struct eoip_softc *);
+
+static struct mbuf *
+ eoip_encap(struct eoip_softc *, struct mbuf *, uint8_t);
+
+static struct mbuf *
+ eoip_input(struct gre_tunnel *, struct mbuf *,
+ const struct gre_header *, int);
+struct if_clone eoip_cloner =
+IF_CLONE_INITIALIZER("eoip", eoip_clone_create, eoip_clone_destroy);
+
+/* protected by NET_LOCK */
+struct eoip_tree eoip_tree = RBT_INITIALIZER();
+
+/*
* It is not easy to calculate the right value for a GRE MTU.
* We leave this task to the admin and use the same default that
* other vendors use.
@@ -482,6 +550,7 @@ greattach(int n)
if_clone_attach(&mgre_cloner);
if_clone_attach(&egre_cloner);
if_clone_attach(&nvgre_cloner);
+ if_clone_attach(&eoip_cloner);
}
static int
@@ -725,6 +794,65 @@ nvgre_clone_destroy(struct ifnet *ifp)
return (0);
}
+static int
+eoip_clone_create(struct if_clone *ifc, int unit)
+{
+ struct eoip_softc *sc;
+ struct ifnet *ifp;
+
+ sc = malloc(sizeof(*sc),