diff options
Diffstat (limited to 'drivers/net/ppp_generic.c')
-rw-r--r-- | drivers/net/ppp_generic.c | 88 |
1 files changed, 64 insertions, 24 deletions
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index d3c9958b00d0..50430f79f8cf 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c | |||
@@ -137,13 +137,14 @@ struct ppp { | |||
137 | 137 | ||
138 | /* | 138 | /* |
139 | * Bits in flags: SC_NO_TCP_CCID, SC_CCP_OPEN, SC_CCP_UP, SC_LOOP_TRAFFIC, | 139 | * Bits in flags: SC_NO_TCP_CCID, SC_CCP_OPEN, SC_CCP_UP, SC_LOOP_TRAFFIC, |
140 | * SC_MULTILINK, SC_MP_SHORTSEQ, SC_MP_XSHORTSEQ, SC_COMP_TCP, SC_REJ_COMP_TCP. | 140 | * SC_MULTILINK, SC_MP_SHORTSEQ, SC_MP_XSHORTSEQ, SC_COMP_TCP, SC_REJ_COMP_TCP, |
141 | * SC_MUST_COMP | ||
141 | * Bits in rstate: SC_DECOMP_RUN, SC_DC_ERROR, SC_DC_FERROR. | 142 | * Bits in rstate: SC_DECOMP_RUN, SC_DC_ERROR, SC_DC_FERROR. |
142 | * Bits in xstate: SC_COMP_RUN | 143 | * Bits in xstate: SC_COMP_RUN |
143 | */ | 144 | */ |
144 | #define SC_FLAG_BITS (SC_NO_TCP_CCID|SC_CCP_OPEN|SC_CCP_UP|SC_LOOP_TRAFFIC \ | 145 | #define SC_FLAG_BITS (SC_NO_TCP_CCID|SC_CCP_OPEN|SC_CCP_UP|SC_LOOP_TRAFFIC \ |
145 | |SC_MULTILINK|SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ \ | 146 | |SC_MULTILINK|SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ \ |
146 | |SC_COMP_TCP|SC_REJ_COMP_TCP) | 147 | |SC_COMP_TCP|SC_REJ_COMP_TCP|SC_MUST_COMP) |
147 | 148 | ||
148 | /* | 149 | /* |
149 | * Private data structure for each channel. | 150 | * Private data structure for each channel. |
@@ -1027,6 +1028,56 @@ ppp_xmit_process(struct ppp *ppp) | |||
1027 | ppp_xmit_unlock(ppp); | 1028 | ppp_xmit_unlock(ppp); |
1028 | } | 1029 | } |
1029 | 1030 | ||
1031 | static inline struct sk_buff * | ||
1032 | pad_compress_skb(struct ppp *ppp, struct sk_buff *skb) | ||
1033 | { | ||
1034 | struct sk_buff *new_skb; | ||
1035 | int len; | ||
1036 | int new_skb_size = ppp->dev->mtu + | ||
1037 | ppp->xcomp->comp_extra + ppp->dev->hard_header_len; | ||
1038 | int compressor_skb_size = ppp->dev->mtu + | ||
1039 | ppp->xcomp->comp_extra + PPP_HDRLEN; | ||
1040 | new_skb = alloc_skb(new_skb_size, GFP_ATOMIC); | ||
1041 | if (!new_skb) { | ||
1042 | if (net_ratelimit()) | ||
1043 | printk(KERN_ERR "PPP: no memory (comp pkt)\n"); | ||
1044 | return NULL; | ||
1045 | } | ||
1046 | if (ppp->dev->hard_header_len > PPP_HDRLEN) | ||
1047 | skb_reserve(new_skb, | ||
1048 | ppp->dev->hard_header_len - PPP_HDRLEN); | ||
1049 | |||
1050 | /* compressor still expects A/C bytes in hdr */ | ||
1051 | len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2, | ||
1052 | new_skb->data, skb->len + 2, | ||
1053 | compressor_skb_size); | ||
1054 | if (len > 0 && (ppp->flags & SC_CCP_UP)) { | ||
1055 | kfree_skb(skb); | ||
1056 | skb = new_skb; | ||
1057 | skb_put(skb, len); | ||
1058 | skb_pull(skb, 2); /* pull off A/C bytes */ | ||
1059 | } else if (len == 0) { | ||
1060 | /* didn't compress, or CCP not up yet */ | ||
1061 | kfree_skb(new_skb); | ||
1062 | new_skb = skb; | ||
1063 | } else { | ||
1064 | /* | ||
1065 | * (len < 0) | ||
1066 | * MPPE requires that we do not send unencrypted | ||
1067 | * frames. The compressor will return -1 if we | ||
1068 | * should drop the frame. We cannot simply test | ||
1069 | * the compress_proto because MPPE and MPPC share | ||
1070 | * the same number. | ||
1071 | */ | ||
1072 | if (net_ratelimit()) | ||
1073 | printk(KERN_ERR "ppp: compressor dropped pkt\n"); | ||
1074 | kfree_skb(skb); | ||
1075 | kfree_skb(new_skb); | ||
1076 | new_skb = NULL; | ||
1077 | } | ||
1078 | return new_skb; | ||
1079 | } | ||
1080 | |||
1030 | /* | 1081 | /* |
1031 | * Compress and send a frame. | 1082 | * Compress and send a frame. |
1032 | * The caller should have locked the xmit path, | 1083 | * The caller should have locked the xmit path, |
@@ -1113,29 +1164,14 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) | |||
1113 | /* try to do packet compression */ | 1164 | /* try to do packet compression */ |
1114 | if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0 | 1165 | if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0 |
1115 | && proto != PPP_LCP && proto != PPP_CCP) { | 1166 | && proto != PPP_LCP && proto != PPP_CCP) { |
1116 | new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len, | 1167 | if (!(ppp->flags & SC_CCP_UP) && (ppp->flags & SC_MUST_COMP)) { |
1117 | GFP_ATOMIC); | 1168 | if (net_ratelimit()) |
1118 | if (new_skb == 0) { | 1169 | printk(KERN_ERR "ppp: compression required but down - pkt dropped.\n"); |
1119 | printk(KERN_ERR "PPP: no memory (comp pkt)\n"); | ||
1120 | goto drop; | 1170 | goto drop; |
1121 | } | 1171 | } |
1122 | if (ppp->dev->hard_header_len > PPP_HDRLEN) | 1172 | skb = pad_compress_skb(ppp, skb); |
1123 | skb_reserve(new_skb, | 1173 | if (!skb) |
1124 | ppp->dev->hard_header_len - PPP_HDRLEN); | 1174 | goto drop; |
1125 | |||
1126 | /* compressor still expects A/C bytes in hdr */ | ||
1127 | len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2, | ||
1128 | new_skb->data, skb->len + 2, | ||
1129 | ppp->dev->mtu + PPP_HDRLEN); | ||
1130 | if (len > 0 && (ppp->flags & SC_CCP_UP)) { | ||
1131 | kfree_skb(skb); | ||
1132 | skb = new_skb; | ||
1133 | skb_put(skb, len); | ||
1134 | skb_pull(skb, 2); /* pull off A/C bytes */ | ||
1135 | } else { | ||
1136 | /* didn't compress, or CCP not up yet */ | ||
1137 | kfree_skb(new_skb); | ||
1138 | } | ||
1139 | } | 1175 | } |
1140 | 1176 | ||
1141 | /* | 1177 | /* |
@@ -1155,7 +1191,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) | |||
1155 | return; | 1191 | return; |
1156 | 1192 | ||
1157 | drop: | 1193 | drop: |
1158 | kfree_skb(skb); | 1194 | if (skb) |
1195 | kfree_skb(skb); | ||
1159 | ++ppp->stats.tx_errors; | 1196 | ++ppp->stats.tx_errors; |
1160 | } | 1197 | } |
1161 | 1198 | ||
@@ -1552,6 +1589,9 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) | |||
1552 | && (ppp->rstate & (SC_DC_FERROR | SC_DC_ERROR)) == 0) | 1589 | && (ppp->rstate & (SC_DC_FERROR | SC_DC_ERROR)) == 0) |
1553 | skb = ppp_decompress_frame(ppp, skb); | 1590 | skb = ppp_decompress_frame(ppp, skb); |
1554 | 1591 | ||
1592 | if (ppp->flags & SC_MUST_COMP && ppp->rstate & SC_DC_FERROR) | ||
1593 | goto err; | ||
1594 | |||
1555 | proto = PPP_PROTO(skb); | 1595 | proto = PPP_PROTO(skb); |
1556 | switch (proto) { | 1596 | switch (proto) { |
1557 | case PPP_VJC_COMP: | 1597 | case PPP_VJC_COMP: |