-/* $OpenBSD: if_mobileip.c,v 1.6 2018/02/12 02:33:50 dlg Exp $ */
+/* $OpenBSD: if_mobileip.c,v 1.7 2018/02/12 02:55:40 dlg Exp $ */
/*
* Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/timeout.h>
-#include <sys/tree.h>
+#include <sys/queue.h>
#include <net/if.h>
#include <net/if_types.h>
struct in_addr t_src;
struct in_addr t_dst;
- RBT_ENTRY(mobileip_softc)
+ TAILQ_ENTRY(mobileip_tunnel)
t_entry;
};
-RBT_HEAD(mobileip_tree, mobileip_tunnel);
+TAILQ_HEAD(mobileip_list, mobileip_tunnel);
struct mobileip_softc {
struct mobileip_tunnel sc_tunnel;
mobileip_cmp(const struct mobileip_tunnel *,
const struct mobileip_tunnel *);
-RBT_PROTOTYPE(mobileip_tree, mobileip_tunnel, t_entry, mobileip_cmp);
-
-struct mobileip_tree mobileip_tree = RBT_INITIALIZER();
+struct mobileip_list mobileip_list = TAILQ_HEAD_INITIALIZER(mobileip_list);
#define MOBILEIPMTU (1500 - (sizeof(struct mobileip_header) + \
sizeof(struct mobileip_h_src))) \
struct sockaddr *, struct rtentry *);
static void mobileip_start(struct ifnet *);
static int mobileip_encap(struct mobileip_softc *, struct mbuf *);
+static struct mobileip_softc *
+ mobileip_find(const struct mobileip_tunnel *);
/*
* let's begin
bpfattach(&sc->sc_if.if_bpf, &sc->sc_if, DLT_LOOP, sizeof(uint32_t));
#endif
+ NET_LOCK();
+ TAILQ_INSERT_TAIL(&mobileip_list, &sc->sc_tunnel, t_entry);
+ NET_UNLOCK();
+
return (0);
}
NET_LOCK();
if (ISSET(ifp->if_flags, IFF_RUNNING))
mobileip_down(sc);
+
+ TAILQ_REMOVE(&mobileip_list, &sc->sc_tunnel, t_entry);
NET_UNLOCK();
free(sc, M_DEVBUF, sizeof(*sc));
break;
case SIOCSLIFPHYRTABLE:
- if (ISSET(ifp->if_flags, IFF_RUNNING)) {
- error = EBUSY;
- break;
- }
-
if (ifr->ifr_rdomainid < 0 ||
ifr->ifr_rdomainid > RT_TABLEID_MAX ||
!rtable_exists(ifr->ifr_rdomainid)) {
static int
mobileip_up(struct mobileip_softc *sc)
{
- if (sc->sc_tunnel.t_dst.s_addr == INADDR_ANY)
- return (EDESTADDRREQ);
-
NET_ASSERT_LOCKED();
- if (RBT_INSERT(mobileip_tree, &mobileip_tree, &sc->sc_tunnel) != NULL)
- return (EADDRINUSE);
SET(sc->sc_if.if_flags, IFF_RUNNING);
mobileip_down(struct mobileip_softc *sc)
{
NET_ASSERT_LOCKED();
- RBT_REMOVE(mobileip_tree, &mobileip_tree, &sc->sc_tunnel);
CLR(sc->sc_if.if_flags, IFF_RUNNING);
struct sockaddr_in *src = (struct sockaddr_in *)&req->addr;
struct sockaddr_in *dst = (struct sockaddr_in *)&req->dstaddr;
- if (ISSET(sc->sc_if.if_flags, IFF_RUNNING))
- return (EBUSY);
-
/* sa_family and sa_len must be equal */
if (src->sin_family != dst->sin_family || src->sin_len != dst->sin_len)
return (EINVAL);
static int
mobileip_del_tunnel(struct mobileip_softc *sc)
{
- if (ISSET(sc->sc_if.if_flags, IFF_RUNNING))
- return (EBUSY);
-
/* commit */
sc->sc_tunnel.t_src.s_addr = INADDR_ANY;
sc->sc_tunnel.t_dst.s_addr = INADDR_ANY;
return (0);
}
+static struct mobileip_softc *
+mobileip_find(const struct mobileip_tunnel *key)
+{
+ struct mobileip_tunnel *t;
+ struct mobileip_softc *sc;
+
+ TAILQ_FOREACH(t, &mobileip_list, t_entry) {
+ if (mobileip_cmp(key, t) != 0)
+ continue;
+
+ sc = (struct mobileip_softc *)t;
+ if (!ISSET(sc->sc_if.if_flags, IFF_RUNNING))
+ continue;
+
+ return (sc);
+ }
+
+ return (NULL);
+}
+
int
mobileip_input(struct mbuf **mp, int *offp, int type, int af)
{
key.t_dst = ip->ip_src;
/* NET_ASSERT_READ_LOCKED() */
- sc = (struct mobileip_softc *)RBT_FIND(mobileip_tree,
- &mobileip_tree, &key);
+ sc = mobileip_find(&key);
if (sc == NULL)
goto drop;
return (0);
}
-
-RBT_GENERATE(mobileip_tree, mobileip_tunnel, t_entry, mobileip_cmp);