Skip to content

Commit 7fb1b8c

Browse files
Sam Protsenkodavem330
authored andcommitted
ppp: Move PFC decompression to PPP generic layer
Extract "Protocol" field decompression code from transport protocols to PPP generic layer, where it actually belongs. As a consequence, this patch fixes incorrect place of PFC decompression in L2TP driver (when it's not PPPOX_BOUND) and also enables this decompression for other protocols, like PPPoE. Protocol field decompression also happens in PPP Multilink Protocol code and in PPP compression protocols implementations (bsd, deflate, mppe). It looks like there is no easy way to get rid of that, so it was decided to leave it as is, but provide those cases with appropriate comments instead. Changes in v2: - Fix the order of checking skb data room and proto decompression - Remove "inline" keyword from ppp_decompress_proto() - Don't split line before function name - Prefix ppp_decompress_proto() function with "__" - Add ppp_decompress_proto() function with skb data room checks - Add description for introduced functions - Fix comments (as per review on mailing list) Signed-off-by: Sam Protsenko <[email protected]> Reviewed-by: Guillaume Nault <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e69fbf3 commit 7fb1b8c

File tree

5 files changed

+62
-24
lines changed

5 files changed

+62
-24
lines changed

drivers/net/ppp/ppp_async.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,7 @@ process_input_packet(struct asyncppp *ap)
770770
{
771771
struct sk_buff *skb;
772772
unsigned char *p;
773-
unsigned int len, fcs, proto;
773+
unsigned int len, fcs;
774774

775775
skb = ap->rpkt;
776776
if (ap->state & (SC_TOSS | SC_ESCAPE))
@@ -799,14 +799,14 @@ process_input_packet(struct asyncppp *ap)
799799
goto err;
800800
p = skb_pull(skb, 2);
801801
}
802-
proto = p[0];
803-
if (proto & 1) {
804-
/* protocol is compressed */
805-
*(u8 *)skb_push(skb, 1) = 0;
806-
} else {
802+
803+
/* If protocol field is not compressed, it can be LCP packet */
804+
if (!(p[0] & 0x01)) {
805+
unsigned int proto;
806+
807807
if (skb->len < 2)
808808
goto err;
809-
proto = (proto << 8) + p[1];
809+
proto = (p[0] << 8) + p[1];
810810
if (proto == PPP_LCP)
811811
async_lcp_peek(ap, p, skb->len, 1);
812812
}

drivers/net/ppp/ppp_generic.c

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,6 +1965,46 @@ ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
19651965
ppp_recv_unlock(ppp);
19661966
}
19671967

1968+
/**
1969+
* __ppp_decompress_proto - Decompress protocol field, slim version.
1970+
* @skb: Socket buffer where protocol field should be decompressed. It must have
1971+
* at least 1 byte of head room and 1 byte of linear data. First byte of
1972+
* data must be a protocol field byte.
1973+
*
1974+
* Decompress protocol field in PPP header if it's compressed, e.g. when
1975+
* Protocol-Field-Compression (PFC) was negotiated. No checks w.r.t. skb data
1976+
* length are done in this function.
1977+
*/
1978+
static void __ppp_decompress_proto(struct sk_buff *skb)
1979+
{
1980+
if (skb->data[0] & 0x01)
1981+
*(u8 *)skb_push(skb, 1) = 0x00;
1982+
}
1983+
1984+
/**
1985+
* ppp_decompress_proto - Check skb data room and decompress protocol field.
1986+
* @skb: Socket buffer where protocol field should be decompressed. First byte
1987+
* of data must be a protocol field byte.
1988+
*
1989+
* Decompress protocol field in PPP header if it's compressed, e.g. when
1990+
* Protocol-Field-Compression (PFC) was negotiated. This function also makes
1991+
* sure that skb data room is sufficient for Protocol field, before and after
1992+
* decompression.
1993+
*
1994+
* Return: true - decompressed successfully, false - not enough room in skb.
1995+
*/
1996+
static bool ppp_decompress_proto(struct sk_buff *skb)
1997+
{
1998+
/* At least one byte should be present (if protocol is compressed) */
1999+
if (!pskb_may_pull(skb, 1))
2000+
return false;
2001+
2002+
__ppp_decompress_proto(skb);
2003+
2004+
/* Protocol field should occupy 2 bytes when not compressed */
2005+
return pskb_may_pull(skb, 2);
2006+
}
2007+
19682008
void
19692009
ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
19702010
{
@@ -1977,7 +2017,7 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
19772017
}
19782018

19792019
read_lock_bh(&pch->upl);
1980-
if (!pskb_may_pull(skb, 2)) {
2020+
if (!ppp_decompress_proto(skb)) {
19812021
kfree_skb(skb);
19822022
if (pch->ppp) {
19832023
++pch->ppp->dev->stats.rx_length_errors;
@@ -2074,6 +2114,9 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
20742114
if (ppp->flags & SC_MUST_COMP && ppp->rstate & SC_DC_FERROR)
20752115
goto err;
20762116

2117+
/* At this point the "Protocol" field MUST be decompressed, either in
2118+
* ppp_input(), ppp_decompress_frame() or in ppp_receive_mp_frame().
2119+
*/
20772120
proto = PPP_PROTO(skb);
20782121
switch (proto) {
20792122
case PPP_VJC_COMP:
@@ -2245,6 +2288,9 @@ ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb)
22452288
skb_put(skb, len);
22462289
skb_pull(skb, 2); /* pull off the A/C bytes */
22472290

2291+
/* Don't call __ppp_decompress_proto() here, but instead rely on
2292+
* corresponding algo (mppe/bsd/deflate) to decompress it.
2293+
*/
22482294
} else {
22492295
/* Uncompressed frame - pass to decompressor so it
22502296
can update its dictionary if necessary. */
@@ -2290,9 +2336,11 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
22902336

22912337
/*
22922338
* Do protocol ID decompression on the first fragment of each packet.
2339+
* We have to do that here, because ppp_receive_nonmp_frame() expects
2340+
* decompressed protocol field.
22932341
*/
2294-
if ((PPP_MP_CB(skb)->BEbits & B) && (skb->data[0] & 1))
2295-
*(u8 *)skb_push(skb, 1) = 0;
2342+
if (PPP_MP_CB(skb)->BEbits & B)
2343+
__ppp_decompress_proto(skb);
22962344

22972345
/*
22982346
* Expand sequence number to 32 bits, making it as close

drivers/net/ppp/ppp_synctty.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -709,11 +709,10 @@ ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
709709
p = skb_pull(skb, 2);
710710
}
711711

712-
/* decompress protocol field if compressed */
713-
if (p[0] & 1) {
714-
/* protocol is compressed */
715-
*(u8 *)skb_push(skb, 1) = 0;
716-
} else if (skb->len < 2)
712+
/* PPP packet length should be >= 2 bytes when protocol field is not
713+
* compressed.
714+
*/
715+
if (!(p[0] & 0x01) && skb->len < 2)
717716
goto err;
718717

719718
/* queue the frame to be processed */

drivers/net/ppp/pptp.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -325,11 +325,6 @@ static int pptp_rcv_core(struct sock *sk, struct sk_buff *skb)
325325
skb_pull(skb, 2);
326326
}
327327

328-
if ((*skb->data) & 1) {
329-
/* protocol is compressed */
330-
*(u8 *)skb_push(skb, 1) = 0;
331-
}
332-
333328
skb->ip_summed = CHECKSUM_NONE;
334329
skb_set_network_header(skb, skb->head-skb->data);
335330
ppp_input(&po->chan, skb);

net/l2tp/l2tp_ppp.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,6 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int
236236
skb->data[1] == PPP_UI)
237237
skb_pull(skb, 2);
238238

239-
/* Decompress protocol field if PFC is enabled */
240-
if ((*skb->data) & 0x1)
241-
*(u8 *)skb_push(skb, 1) = 0;
242-
243239
if (sk->sk_state & PPPOX_BOUND) {
244240
struct pppox_sock *po;
245241

0 commit comments

Comments
 (0)