Index: net/if_gre.c =================================================================== RCS file: /cvs/src/sys/net/if_gre.c,v retrieving revision 1.89 diff -u -p -r1.89 if_gre.c --- net/if_gre.c 9 Jan 2018 15:24:24 -0000 1.89 +++ net/if_gre.c 22 Jan 2018 02:25:40 -0000 @@ -89,8 +89,6 @@ struct gre_softc_head gre_softc_list; struct if_clone gre_cloner = IF_CLONE_INITIALIZER("gre", gre_clone_create, gre_clone_destroy); -struct if_clone mobileip_cloner = - IF_CLONE_INITIALIZER("mobileip", gre_clone_create, gre_clone_destroy); /* * We can control the acceptance of GRE and MobileIP packets by @@ -103,7 +101,6 @@ struct if_clone mobileip_cloner = */ int gre_allow = 0; int gre_wccp = 0; -int ip_mobile_allow = 0; void gre_keepalive(void *); void gre_send_keepalive(void *); @@ -114,7 +111,6 @@ greattach(int n) { LIST_INIT(&gre_softc_list); if_clone_attach(&gre_cloner); - if_clone_attach(&mobileip_cloner); } int @@ -193,7 +189,6 @@ gre_output(struct ifnet *ifp, struct mbu struct ip *inp = NULL; u_int8_t ip_tos = 0; u_int16_t etype = 0; - struct mobile_h mob_h; struct m_tag *mtag; if ((ifp->if_flags & IFF_UP) == 0 || @@ -238,102 +233,7 @@ gre_output(struct ifnet *ifp, struct mbu bpf_mtap_af(ifp->if_bpf, dst->sa_family, m, BPF_DIRECTION_OUT); #endif - if (sc->g_proto == IPPROTO_MOBILE) { - if (ip_mobile_allow == 0) { - m_freem(m); - error = EACCES; - goto end; - } - - if (dst->sa_family == AF_INET) { - struct mbuf *m0; - int msiz; - - /* - * Make sure the complete IP header (with options) - * is in the first mbuf. - */ - if (m->m_len < sizeof(struct ip)) { - m = m_pullup(m, sizeof(struct ip)); - if (m == NULL) { - error = ENOBUFS; - goto end; - } else - inp = mtod(m, struct ip *); - - if (m->m_len < inp->ip_hl << 2) { - m = m_pullup(m, inp->ip_hl << 2); - if (m == NULL) { - error = ENOBUFS; - goto end; - } - } - } - - inp = mtod(m, struct ip *); - - bzero(&mob_h, MOB_H_SIZ_L); - mob_h.proto = (inp->ip_p) << 8; - mob_h.odst = inp->ip_dst.s_addr; - inp->ip_dst.s_addr = sc->g_dst.s_addr; - - /* - * If the packet comes from our host, we only change - * the destination address in the IP header. - * Otherwise we need to save and change the source. - */ - if (inp->ip_src.s_addr == sc->g_src.s_addr) { - msiz = MOB_H_SIZ_S; - } else { - mob_h.proto |= MOB_H_SBIT; - mob_h.osrc = inp->ip_src.s_addr; - inp->ip_src.s_addr = sc->g_src.s_addr; - msiz = MOB_H_SIZ_L; - } - - mob_h.proto = htons(mob_h.proto); - mob_h.hcrc = gre_in_cksum((u_int16_t *) &mob_h, msiz); - - /* Squeeze in the mobility header */ - if ((m->m_data - msiz) < m->m_pktdat) { - /* Need new mbuf */ - MGETHDR(m0, M_DONTWAIT, MT_HEADER); - if (m0 == NULL) { - m_freem(m); - error = ENOBUFS; - goto end; - } - M_MOVE_HDR(m0, m); - - m0->m_len = msiz + (inp->ip_hl << 2); - m0->m_data += max_linkhdr; - m0->m_pkthdr.len = m->m_pkthdr.len + msiz; - m->m_data += inp->ip_hl << 2; - m->m_len -= inp->ip_hl << 2; - - bcopy((caddr_t) inp, mtod(m0, caddr_t), - sizeof(struct ip)); - - m0->m_next = m; - m = m0; - } else { /* we have some space left in the old one */ - m->m_data -= msiz; - m->m_len += msiz; - m->m_pkthdr.len += msiz; - bcopy(inp, mtod(m, caddr_t), - inp->ip_hl << 2); - } - - /* Copy Mobility header */ - inp = mtod(m, struct ip *); - bcopy(&mob_h, (caddr_t)(inp + 1), (unsigned) msiz); - inp->ip_len = htons(ntohs(inp->ip_len) + msiz); - } else { /* AF_INET */ - m_freem(m); - error = EINVAL; - goto end; - } - } else if (sc->g_proto == IPPROTO_GRE) { + if (sc->g_proto == IPPROTO_GRE) { if (gre_allow == 0) { m_freem(m); error = EACCES; Index: net/if_mobileip.c =================================================================== RCS file: net/if_mobileip.c diff -N net/if_mobileip.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ net/if_mobileip.c 22 Jan 2018 02:25:40 -0000 @@ -0,0 +1,637 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2016 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "mobileip.h" + +#include "bpfilter.h" +#include "pf.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#if NBPFILTER > 0 +#include +#endif + +#if NPF > 0 +#include +#endif + +#include + +struct mobileip_softc { + struct ifnet sc_if; + + RBT_ENTRY(mobileip_softc) + sc_entry; + + unsigned int sc_rtableid; + uint32_t sc_src; + uint32_t sc_dst; +}; + +static int mobileip_clone_create(struct if_clone *, int); +static int mobileip_clone_destroy(struct ifnet *); + +static struct if_clone mobileip_cloner = IF_CLONE_INITIALIZER("mobileip", + mobileip_clone_create, mobileip_clone_destroy); + +RBT_HEAD(mobileip_tree, mobileip_softc); + +static inline int + mobileip_cmp(const struct mobileip_softc *, + const struct mobileip_softc *); + +RBT_PROTOTYPE(mobileip_tree, mobileip_softc, sc_entry, mobileip_cmp); + +struct mobileip_tree mobileip_softcs = RBT_INITIALIZER(); + +#define MOBILEIPMTU (1500 - (sizeof(struct mobileip_header) + \ + sizeof(struct mobileip_h_src))) \ + +static int mobileip_ioctl(struct ifnet *, u_long, caddr_t); +static int mobileip_up(struct mobileip_softc *); +static int mobileip_down(struct mobileip_softc *); +static int mobileip_set_tunnel(struct mobileip_softc *, + struct if_laddrreq *); +static int mobileip_get_tunnel(struct mobileip_softc *, + struct if_laddrreq *); +static int mobileip_del_tunnel(struct mobileip_softc *); + +static int mobileip_output(struct ifnet *, struct mbuf *, + struct sockaddr *, struct rtentry *); +static void mobileip_start(struct ifnet *); +static int mobileip_encap(struct mobileip_softc *, struct mbuf *); + +/* + * let's begin + */ + +int mobileip_allow = 0; + +void +mobileipattach(int n) +{ + if_clone_attach(&mobileip_cloner); +} + +int +mobileip_clone_create(struct if_clone *ifc, int unit) +{ + struct mobileip_softc *sc; + + sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT|M_ZERO); + if (!sc) + return (ENOMEM); + + sc->sc_rtableid = 0; + sc->sc_src = INADDR_ANY; + sc->sc_dst = INADDR_ANY; + + snprintf(sc->sc_if.if_xname, sizeof sc->sc_if.if_xname, "%s%d", + ifc->ifc_name, unit); + sc->sc_if.if_softc = sc; + sc->sc_if.if_type = IFT_TUNNEL; + sc->sc_if.if_addrlen = 0; + sc->sc_if.if_mtu = MOBILEIPMTU; + sc->sc_if.if_flags = IFF_POINTOPOINT|IFF_MULTICAST; + sc->sc_if.if_output = mobileip_output; + sc->sc_if.if_start = mobileip_start; + sc->sc_if.if_ioctl = mobileip_ioctl; + sc->sc_if.if_rtrequest = p2p_rtrequest; + + if_attach(&sc->sc_if); + if_alloc_sadl(&sc->sc_if); + +#if NBPFILTER > 0 + bpfattach(&sc->sc_if.if_bpf, &sc->sc_if, DLT_LOOP, sizeof(uint32_t)); +#endif + + return (0); +} + +int +mobileip_clone_destroy(struct ifnet *ifp) +{ + struct mobileip_softc *sc = ifp->if_softc; + + if_detach(ifp); + + free(sc, M_DEVBUF, sizeof(*sc)); + + return (0); +} + +/* + * do a checksum of a header. + * + * assumes len is aligned correctly, and not an odd number of bytes. + */ +static inline uint16_t +mobileip_cksum(const void *buf, size_t len) +{ + const uint16_t *p = buf; + uint32_t sum = 0; + + do { + sum += bemtoh16(p++); + } while (len -= 2); + + /* end-around-carry */ + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + return (~sum); +} + +static inline int +mobileip_cmp(const struct mobileip_softc *a, const struct mobileip_softc *b) +{ + if (a->sc_src > b->sc_src) + return (1); + if (a->sc_src < b->sc_src) + return (-1); + + if (a->sc_dst > b->sc_dst) + return (1); + if (a->sc_dst < b->sc_dst) + return (-1); + + if (a->sc_rtableid > b->sc_rtableid) + return (1); + if (a->sc_rtableid < b->sc_rtableid) + return (-1); + + return (0); +} + +static int +mobileip_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, + struct rtentry *rt) +{ + struct m_tag *mtag; + int error = 0; + + if (!mobileip_allow) { + m_freem(m); + error = EACCES; + goto end; + } + + if (!ISSET(ifp->if_flags, IFF_RUNNING)) { + m_freem(m); + error = ENETDOWN; + goto end; + } + + if (dst->sa_family != AF_INET) { + m_freem(m); + error = EAFNOSUPPORT; + goto end; + } + + /* Try to limit infinite recursion through misconfiguration. */ + for (mtag = m_tag_find(m, PACKET_TAG_GRE, NULL); mtag; + mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) { + if (memcmp(mtag + 1, &ifp->if_index, + sizeof(ifp->if_index)) == 0) { + m_freem(m); + error = EIO; + goto end; + } + } + + mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT); + if (mtag == NULL) { + m_freem(m); + error = ENOBUFS; + goto end; + } + memcpy(mtag + 1, &ifp->if_index, sizeof(ifp->if_index)); + m_tag_prepend(m, mtag); + + error = if_enqueue(ifp, m); + end: + if (error) + ifp->if_oerrors++; + return (error); +} + +static void +mobileip_start(struct ifnet *ifp) +{ + struct mobileip_softc *sc = ifp->if_softc; + struct mbuf *m; + + while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) { +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap_af(ifp->if_bpf, AF_INET, m, BPF_DIRECTION_OUT); +#endif + + if (mobileip_encap(sc, m) != 0) + ifp->if_oerrors++; + } +} + +static int +mobileip_encap(struct mobileip_softc *sc, struct mbuf *m) +{ + struct ip *ip; + struct mobileip_header *mh; + struct mobileip_h_src *msh; + caddr_t hdr; + int iphlen, hlen; + + /* look at the current IP header */ + m = m_pullup(m, sizeof(*ip)); + if (m == NULL) + return (ENOBUFS); + + /* figure out how long it is */ + ip = mtod(m, struct ip *); + iphlen = ip->ip_hl << 2; + + /* figure out how much extra space we'll need */ + hlen = sizeof(*mh); + if (ip->ip_src.s_addr != sc->sc_src) + hlen += sizeof(*msh); + + /* add the space */ + m = m_prepend(m, hlen, M_DONTWAIT); + if (m == NULL) + return (ENOBUFS); + + /* make the IP and mobileip headers contig */ + m = m_pullup(m, iphlen + hlen); + if (m == NULL) + return (ENOBUFS); + + /* move the IP header to the front */ + hdr = mtod(m, caddr_t); + memmove(hdr, hdr + hlen, iphlen); + + /* fill in the headers */ + ip = (struct ip *)hdr; + mh = (struct mobileip_header *)(hdr + iphlen); + mh->mip_proto = ip->ip_p; + mh->mip_flags = 0; + mh->mip_hcrc = 0; + mh->mip_dst = ip->ip_dst.s_addr; + + if (ip->ip_src.s_addr != sc->sc_src) { + mh->mip_flags |= MOBILEIP_SP; + + msh = (struct mobileip_h_src *)(mh + 1); + msh->mip_src = ip->ip_src.s_addr; + + ip->ip_src.s_addr = sc->sc_src; + } + + htobem16(&mh->mip_hcrc, mobileip_cksum(mh, hlen)); + + ip->ip_p = IPPROTO_MOBILE; + htobem16(&ip->ip_len, bemtoh16(&ip->ip_len) + hlen); + ip->ip_dst.s_addr = sc->sc_dst; + + m->m_flags &= ~(M_BCAST|M_MCAST); + m->m_pkthdr.ph_rtableid = sc->sc_rtableid; + +#if NPF > 0 + pf_pkt_addr_changed(m); +#endif + + ip_send(m); + + return (0); +} + +int +mobileip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +{ + struct mobileip_softc *sc = ifp->if_softc; + struct ifreq *ifr = (struct ifreq *)data; + int error = 0; + + switch(cmd) { + case SIOCSIFADDR: + /* XXX restrict to AF_INET */ + ifp->if_flags |= IFF_UP; + /* FALLTHROUGH */ + case SIOCSIFFLAGS: + if (ISSET(ifp->if_flags, IFF_UP)) { + if (!ISSET(ifp->if_flags, IFF_RUNNING)) + error = mobileip_up(sc); + else + error = ENETRESET; + } else { + if (ISSET(ifp->if_flags, IFF_RUNNING)) + error = mobileip_down(sc); + } + break; + case SIOCSIFDSTADDR: + break; + case SIOCSIFMTU: + if (ifr->ifr_mtu < 576) { + error = EINVAL; + break; + } + ifp->if_mtu = ifr->ifr_mtu; + break; + case SIOCGIFMTU: + ifr->ifr_mtu = sc->sc_if.if_mtu; + break; + case SIOCADDMULTI: + case SIOCDELMULTI: + break; + + case SIOCSLIFPHYADDR: + error = mobileip_set_tunnel(sc, (struct if_laddrreq *)data); + break; + case SIOCGLIFPHYADDR: + error = mobileip_get_tunnel(sc, (struct if_laddrreq *)data); + break; + case SIOCDIFPHYADDR: + error = mobileip_del_tunnel(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)) { + error = EINVAL; + break; + } + sc->sc_rtableid = ifr->ifr_rdomainid; + break; + case SIOCGLIFPHYRTABLE: + ifr->ifr_rdomainid = sc->sc_rtableid; + break; + + default: + error = ENOTTY; + break; + } + + return (error); +} + +static int +mobileip_up(struct mobileip_softc *sc) +{ + struct mobileip_softc *osc; + + if (sc->sc_dst == INADDR_ANY) + return (EDESTADDRREQ); + + NET_ASSERT_LOCKED(); + osc = RBT_INSERT(mobileip_tree, &mobileip_softcs, sc); + if (osc != NULL) + return (EADDRINUSE); + + SET(sc->sc_if.if_flags, IFF_RUNNING); + + return (0); +} + +static int +mobileip_down(struct mobileip_softc *sc) +{ + NET_ASSERT_LOCKED(); + RBT_REMOVE(mobileip_tree, &mobileip_softcs, sc); + + CLR(sc->sc_if.if_flags, IFF_RUNNING); + + ifq_barrier(&sc->sc_if.if_snd); + + return (0); +} + +static int +mobileip_set_tunnel(struct mobileip_softc *sc, struct if_laddrreq *req) +{ + 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); + + if (dst->sin_family != AF_INET) + return (EAFNOSUPPORT); + if (dst->sin_len != sizeof(*dst)) + return (EINVAL); + + if (in_nullhost(src->sin_addr) || + IN_MULTICAST(src->sin_addr.s_addr) || + in_nullhost(dst->sin_addr) || + IN_MULTICAST(dst->sin_addr.s_addr)) + return (EINVAL); + + /* commit */ + sc->sc_src = src->sin_addr.s_addr; + sc->sc_dst = dst->sin_addr.s_addr; + + return (0); +} + +static int +mobileip_get_tunnel(struct mobileip_softc *sc, struct if_laddrreq *req) +{ + struct sockaddr_in *src = (struct sockaddr_in *)&req->addr; + struct sockaddr_in *dst = (struct sockaddr_in *)&req->dstaddr; + + if (sc->sc_dst == INADDR_ANY) + return (EADDRNOTAVAIL); + + memset(src, 0, sizeof(*src)); + src->sin_family = AF_INET; + src->sin_len = sizeof(*src); + src->sin_addr.s_addr = sc->sc_src; + + memset(dst, 0, sizeof(*dst)); + dst->sin_family = AF_INET; + dst->sin_len = sizeof(*dst); + dst->sin_addr.s_addr = sc->sc_dst; + + return (0); +} + +static int +mobileip_del_tunnel(struct mobileip_softc *sc) +{ + if (ISSET(sc->sc_if.if_flags, IFF_RUNNING)) + return (EBUSY); + + /* commit */ + sc->sc_src = INADDR_ANY; + sc->sc_dst = INADDR_ANY; + + return (0); +} + +int +mobileip_input(struct mbuf **mp, int *offp, int type, int af) +{ + struct mobileip_softc key; + struct mbuf *m = *mp; + struct ifnet *ifp; + struct mobileip_softc *sc; + caddr_t hdr; + struct ip *ip; + struct mobileip_header *mh; + struct mobileip_h_src *msh; + int iphlen = 0; + int hlen; + + if (!mobileip_allow) + goto drop; + + ip = mtod(m, struct ip *); + + key.sc_rtableid = m->m_pkthdr.ph_rtableid; + key.sc_src = ip->ip_dst.s_addr; + key.sc_dst = ip->ip_src.s_addr; + + /* NET_ASSERT_READ_LOCKED() */ + sc = RBT_FIND(mobileip_tree, &mobileip_softcs, &key); + if (sc == NULL) + goto drop; + + /* it's ours now, we can do what we want */ + + iphlen = ip->ip_hl << 2; + hlen = sizeof(*mh); + m = m_pullup(m, iphlen + hlen); + if (m == NULL) + return (IPPROTO_DONE); + + hdr = mtod(m, caddr_t); + ip = (struct ip *)hdr; + mh = (struct mobileip_header *)(hdr + iphlen); + + if (mh->mip_flags & ~MOBILEIP_SP) + goto drop; + + if (ISSET(mh->mip_flags, MOBILEIP_SP)) { + hlen += sizeof(*msh); + m = m_pullup(m, iphlen + hlen); + if (m == NULL) + return (IPPROTO_DONE); + + hdr = mtod(m, caddr_t); + ip = (struct ip *)hdr; + mh = (struct mobileip_header *)(hdr + iphlen); + msh = (struct mobileip_h_src *)(mh + 1); + + ip->ip_src.s_addr = msh->mip_src; + } + + if (mobileip_cksum(mh, hlen) != 0) + goto drop; + + ip->ip_p = mh->mip_proto; + htobem16(&ip->ip_len, bemtoh16(&ip->ip_len) - hlen); + ip->ip_dst.s_addr = mh->mip_dst; + + memmove(hdr + hlen, hdr, iphlen); + m_adj(m, hlen); + + ifp = &sc->sc_if; + + CLR(m->m_flags, M_MCAST|M_BCAST); + SET(m->m_pkthdr.csum_flags, M_IPV4_CSUM_IN_OK); + m->m_pkthdr.ph_ifidx = ifp->if_index; + m->m_pkthdr.ph_rtableid = ifp->if_rdomain; + +#if NPF > 0 + pf_pkt_addr_changed(m); +#endif + + ifp->if_ipackets++; + ifp->if_ibytes += m->m_pkthdr.len; + +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap_af(ifp->if_bpf, AF_INET, m, BPF_DIRECTION_IN); +#endif + + ipv4_input(ifp, m); + + return (IPPROTO_DONE); + +drop: + m_freem(m); + return (IPPROTO_DONE); +} + +#include +#include + +int +mobileip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, + void *newp, size_t newlen) +{ + int allow; + int error; + + /* All sysctl names at this level are terminal. */ + if (namelen != 1) + return (ENOTDIR); + + switch (name[0]) { + case MOBILEIPCTL_ALLOW: + allow = mobileip_allow; + + error = sysctl_int(oldp, oldlenp, newp, newlen, + &allow); + if (error != 0) + return (error); + + mobileip_allow = allow; + break; + default: + return (ENOPROTOOPT); + } + + return (0); +} + +RBT_GENERATE(mobileip_tree, mobileip_softc, sc_entry, mobileip_cmp); Index: net/if_mobileip.h =================================================================== RCS file: net/if_mobileip.h diff -N net/if_mobileip.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ net/if_mobileip.h 22 Jan 2018 02:25:40 -0000 @@ -0,0 +1,41 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2016 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_IF_MOBILEIP_H +#define _NET_IF_MOBILEIP_H + +struct mobileip_header { + uint8_t mip_proto; /* original protocol */ + uint8_t mip_flags; +#define MOBILEIP_SP 0x80 /* src address is present */ + uint16_t mip_hcrc; /* header checksum */ + uint32_t mip_dst; /* original dst address */ +} __packed __aligned(4); + +struct mobileip_h_src { + uint32_t mip_src; /* original src address */ +} __packed __aligned(4); + +#ifdef _KERNEL +void mobileipattach(int); +int mobileip_input(struct mbuf **, int *, int, int); +int mobileip_sysctl(int *, u_int, void *, size_t *, + void *, size_t); +#endif /* _KERNEL */ + +#endif /* _NET_IF_MOBILEIP_H_ */ Index: netinet/in_proto.c =================================================================== RCS file: /cvs/src/sys/netinet/in_proto.c,v retrieving revision 1.88 diff -u -p -r1.88 in_proto.c --- netinet/in_proto.c 23 Nov 2017 13:45:46 -0000 1.88 +++ netinet/in_proto.c 22 Jan 2018 02:25:40 -0000 @@ -172,6 +172,11 @@ #include #endif +#include "mobileip.h" +#if NMOBILEIP > 0 +#include +#endif + u_char ip_protox[IPPROTO_MAX]; const struct protosw inetsw[] = { @@ -348,19 +358,21 @@ const struct protosw inetsw[] = { .pr_detach = rip_detach, .pr_sysctl = gre_sysctl }, +#endif /* NGRE > 0 */ +#if NMOBILEIP > 0 { .pr_type = SOCK_RAW, .pr_domain = &inetdomain, .pr_protocol = IPPROTO_MOBILE, .pr_flags = PR_ATOMIC|PR_ADDR, - .pr_input = gre_mobile_input, + .pr_input = mobileip_input, .pr_ctloutput = rip_ctloutput, .pr_usrreq = rip_usrreq, .pr_attach = rip_attach, .pr_detach = rip_detach, - .pr_sysctl = ipmobile_sysctl + .pr_sysctl = mobileip_sysctl }, -#endif /* NGRE > 0 */ +#endif /* NMOBILEIP > 0 */ #if NCARP > 0 { .pr_type = SOCK_RAW, Index: netinet/ip_gre.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_gre.c,v retrieving revision 1.69 diff -u -p -r1.69 ip_gre.c --- netinet/ip_gre.c 9 Jan 2018 06:24:15 -0000 1.69 +++ netinet/ip_gre.c 22 Jan 2018 02:25:40 -0000 @@ -261,93 +261,6 @@ gre_input(struct mbuf **mp, int *offp, i } /* - * Input routine for IPPROTO_MOBILE. - * This is a little bit different from the other modes, as the - * encapsulating header was not prepended, but instead inserted - * between IP header and payload. - */ - -int -gre_mobile_input(struct mbuf **mp, int *offp, int proto, int af) -{ - struct mbuf *m = *mp; - struct ip *ip; - struct mobip_h *mip; - struct gre_softc *sc; - u_char osrc = 0; - int msiz; - - if (!ip_mobile_allow) { - m_freem(m); - return IPPROTO_DONE; - } - - if ((sc = gre_lookup(m, proto)) == NULL) { - /* No matching tunnel or tunnel is down. */ - m_freem(m); - return IPPROTO_DONE; - } - - if (m->m_len < sizeof(*mip)) { - m = *mp = m_pullup(m, sizeof(*mip)); - if (m == NULL) - return IPPROTO_DONE; - } - ip = mtod(m, struct ip *); - mip = mtod(m, struct mobip_h *); - - m->m_pkthdr.ph_ifidx = sc->sc_if.if_index; - - sc->sc_if.if_ipackets++; - sc->sc_if.if_ibytes += m->m_pkthdr.len; - - if (ntohs(mip->mh.proto) & MOB_H_SBIT) { - osrc = 1; - msiz = MOB_H_SIZ_L; - mip->mi.ip_src.s_addr = mip->mh.osrc; - } else - msiz = MOB_H_SIZ_S; - - if (m->m_len < (ip->ip_hl << 2) + msiz) { - m = *mp = m_pullup(m, (ip->ip_hl << 2) + msiz); - if (m == NULL) - return IPPROTO_DONE; - ip = mtod(m, struct ip *); - mip = mtod(m, struct mobip_h *); - } - - mip->mi.ip_dst.s_addr = mip->mh.odst; - mip->mi.ip_p = (ntohs(mip->mh.proto) >> 8); - - if (gre_in_cksum((u_short *) &mip->mh, msiz) != 0) { - m_freem(m); - return IPPROTO_DONE; - } - - memmove(ip + (ip->ip_hl << 2), ip + (ip->ip_hl << 2) + msiz, - m->m_len - msiz - (ip->ip_hl << 2)); - - m->m_len -= msiz; - ip->ip_len = htons(ntohs(ip->ip_len) - msiz); - m->m_pkthdr.len -= msiz; - - ip->ip_sum = 0; - ip->ip_sum = in_cksum(m,(ip->ip_hl << 2)); - -#if NBPFILTER > 0 - if (sc->sc_if.if_bpf) - bpf_mtap_af(sc->sc_if.if_bpf, AF_INET, m, BPF_DIRECTION_IN); -#endif - -#if NPF > 0 - pf_pkt_addr_changed(m); -#endif - - ipv4_input(&sc->sc_if, m); - return IPPROTO_DONE; -} - -/* * Find the gre interface associated with our src/dst/proto set. */ struct gre_softc * @@ -389,29 +302,6 @@ gre_sysctl(int *name, u_int namelen, voi case GRECTL_WCCP: NET_LOCK(); error = sysctl_int(oldp, oldlenp, newp, newlen, &gre_wccp); - NET_UNLOCK(); - return (error); - default: - return (ENOPROTOOPT); - } - /* NOTREACHED */ -} - -int -ipmobile_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen) -{ - int error; - - /* All sysctl names at this level are terminal. */ - if (namelen != 1) - return (ENOTDIR); - - switch (name[0]) { - case MOBILEIPCTL_ALLOW: - NET_LOCK(); - error = sysctl_int(oldp, oldlenp, newp, newlen, - &ip_mobile_allow); NET_UNLOCK(); return (error); default: