summaryrefslogtreecommitdiffstats
path: root/sys/net/if_spppsubr.c
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>2001-12-30 16:13:35 +0000
committerjoerg <joerg@FreeBSD.org>2001-12-30 16:13:35 +0000
commitdbbd8a474415fcb0219f39af431a6d9c6a2558f2 (patch)
tree66a14fdbbaf64ea2f34d423e74334e5bd7f9801a /sys/net/if_spppsubr.c
parent49006afe46de6cc5c1364f1642b8b223fa8656ec (diff)
downloadFreeBSD-src-dbbd8a474415fcb0219f39af431a6d9c6a2558f2.zip
FreeBSD-src-dbbd8a474415fcb0219f39af431a6d9c6a2558f2.tar.gz
Fix the handling of VJ uncompression. Unfortunately, tcp_uncompress()
makes the implied assumption there were another 128 bytes of space in front of the packet handed off to it... which is not the case for sppp. This could easily end up in corrupting random memory. This fix is about the same as revs 1.6, 1.8, and 1.9 from our i4b_ispppsubr.c. Also fixed IPCP option negotiation to zero out the options when starting IPCP. Otherwise, if negotiation parameters change between various IPCP startups, it could happen that old options would still be requested (this happened if VJ was turned off, and ended up in half off the link still negotiating for VJ compression). IMHO, the base system's sppp is now feature-wise up to date with the one in the i4b part of the tree, so the latter can be disabled. MFC after: 1 month
Diffstat (limited to 'sys/net/if_spppsubr.c')
-rw-r--r--sys/net/if_spppsubr.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c
index d6783c0..c716518 100644
--- a/sys/net/if_spppsubr.c
+++ b/sys/net/if_spppsubr.c
@@ -506,7 +506,8 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
struct ppp_header *h;
struct ifqueue *inq = 0;
struct sppp *sp = (struct sppp *)ifp;
- int len, do_account = 0;
+ u_char *iphdr;
+ int hlen, vjlen, do_account = 0;
int debug = ifp->if_flags & IFF_DEBUG;
if (ifp->if_flags & IFF_UP)
@@ -520,9 +521,10 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
SPP_FMT "input packet is too small, %d bytes\n",
SPP_ARGS(ifp), m->m_pkthdr.len);
drop:
+ m_freem (m);
+ drop2:
++ifp->if_ierrors;
++ifp->if_iqdrops;
- m_freem (m);
return;
}
@@ -586,13 +588,31 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
break;
case PPP_VJ_COMP:
if (sp->state[IDX_IPCP] == STATE_OPENED) {
- if ((len =
- sl_uncompress_tcp((u_char **)&m->m_data,
- m->m_len,
- TYPE_COMPRESSED_TCP,
- sp->pp_comp)) <= 0)
+ if ((vjlen =
+ sl_uncompress_tcp_core(mtod(m, u_char *),
+ m->m_len, m->m_len,
+ TYPE_COMPRESSED_TCP,
+ sp->pp_comp,
+ &iphdr, &hlen)) <= 0) {
+ if (debug)
+ log(LOG_INFO,
+ SPP_FMT "VJ uncompress failed on compressed packet\n",
+ SPP_ARGS(ifp));
goto drop;
- m->m_len = m->m_pkthdr.len = len;
+ }
+
+ /*
+ * Trim the VJ header off the packet, and prepend
+ * the uncompressed IP header (which will usually
+ * end up in two chained mbufs since there's not
+ * enough leading space in the existing mbuf).
+ */
+ m_adj(m, vjlen);
+ M_PREPEND(m, hlen, M_DONTWAIT);
+ if (m == NULL)
+ goto drop2;
+ bcopy(iphdr, mtod(m, u_char *), hlen);
+
schednetisr (NETISR_IP);
inq = &ipintrq;
}
@@ -600,13 +620,17 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
break;
case PPP_VJ_UCOMP:
if (sp->state[IDX_IPCP] == STATE_OPENED) {
- if ((len =
- sl_uncompress_tcp((u_char **)&m->m_data,
- m->m_len,
- TYPE_UNCOMPRESSED_TCP,
- sp->pp_comp)) <= 0)
+ if (sl_uncompress_tcp_core(mtod(m, u_char *),
+ m->m_len, m->m_len,
+ TYPE_UNCOMPRESSED_TCP,
+ sp->pp_comp,
+ &iphdr, &hlen) != 0) {
+ if (debug)
+ log(LOG_INFO,
+ SPP_FMT "VJ uncompress failed on uncompressed packet\n",
+ SPP_ARGS(ifp));
goto drop;
- m->m_len = m->m_pkthdr.len = len;
+ }
schednetisr (NETISR_IP);
inq = &ipintrq;
}
@@ -2772,6 +2796,7 @@ sppp_ipcp_open(struct sppp *sp)
sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN |
IPCP_MYADDR_DYN | IPCP_VJ);
+ sp->ipcp.opts = 0;
sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0);
/*
OpenPOWER on IntegriCloud