diff options
| -rw-r--r-- | net/atm/pppoatm.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c index b23c6723e87c..c4a57bca77bf 100644 --- a/net/atm/pppoatm.c +++ b/net/atm/pppoatm.c | |||
| @@ -272,10 +272,19 @@ static inline int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size) | |||
| 272 | static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) | 272 | static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) |
| 273 | { | 273 | { |
| 274 | struct pppoatm_vcc *pvcc = chan_to_pvcc(chan); | 274 | struct pppoatm_vcc *pvcc = chan_to_pvcc(chan); |
| 275 | struct atm_vcc *vcc; | ||
| 276 | int ret; | ||
| 277 | |||
| 275 | ATM_SKB(skb)->vcc = pvcc->atmvcc; | 278 | ATM_SKB(skb)->vcc = pvcc->atmvcc; |
| 276 | pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc); | 279 | pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc); |
| 277 | if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT)) | 280 | if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT)) |
| 278 | (void) skb_pull(skb, 1); | 281 | (void) skb_pull(skb, 1); |
| 282 | |||
| 283 | vcc = ATM_SKB(skb)->vcc; | ||
| 284 | bh_lock_sock(sk_atm(vcc)); | ||
| 285 | if (sock_owned_by_user(sk_atm(vcc))) | ||
| 286 | goto nospace; | ||
| 287 | |||
| 279 | switch (pvcc->encaps) { /* LLC encapsulation needed */ | 288 | switch (pvcc->encaps) { /* LLC encapsulation needed */ |
| 280 | case e_llc: | 289 | case e_llc: |
| 281 | if (skb_headroom(skb) < LLC_LEN) { | 290 | if (skb_headroom(skb) < LLC_LEN) { |
| @@ -288,8 +297,10 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) | |||
| 288 | } | 297 | } |
| 289 | consume_skb(skb); | 298 | consume_skb(skb); |
| 290 | skb = n; | 299 | skb = n; |
| 291 | if (skb == NULL) | 300 | if (skb == NULL) { |
| 301 | bh_unlock_sock(sk_atm(vcc)); | ||
| 292 | return DROP_PACKET; | 302 | return DROP_PACKET; |
| 303 | } | ||
| 293 | } else if (!pppoatm_may_send(pvcc, skb->truesize)) | 304 | } else if (!pppoatm_may_send(pvcc, skb->truesize)) |
| 294 | goto nospace; | 305 | goto nospace; |
| 295 | memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN); | 306 | memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN); |
| @@ -299,6 +310,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) | |||
| 299 | goto nospace; | 310 | goto nospace; |
| 300 | break; | 311 | break; |
| 301 | case e_autodetect: | 312 | case e_autodetect: |
| 313 | bh_unlock_sock(sk_atm(vcc)); | ||
| 302 | pr_debug("Trying to send without setting encaps!\n"); | 314 | pr_debug("Trying to send without setting encaps!\n"); |
| 303 | kfree_skb(skb); | 315 | kfree_skb(skb); |
| 304 | return 1; | 316 | return 1; |
| @@ -308,9 +320,12 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) | |||
| 308 | ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options; | 320 | ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options; |
| 309 | pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", | 321 | pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", |
| 310 | skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev); | 322 | skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev); |
| 311 | return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb) | 323 | ret = ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb) |
| 312 | ? DROP_PACKET : 1; | 324 | ? DROP_PACKET : 1; |
| 325 | bh_unlock_sock(sk_atm(vcc)); | ||
| 326 | return ret; | ||
| 313 | nospace: | 327 | nospace: |
| 328 | bh_unlock_sock(sk_atm(vcc)); | ||
| 314 | /* | 329 | /* |
| 315 | * We don't have space to send this SKB now, but we might have | 330 | * We don't have space to send this SKB now, but we might have |
| 316 | * already applied SC_COMP_PROT compression, so may need to undo | 331 | * already applied SC_COMP_PROT compression, so may need to undo |
