diff options
Diffstat (limited to 'drivers/isdn/mISDN/socket.c')
-rw-r--r-- | drivers/isdn/mISDN/socket.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index 508945d1b9c1..c36f52137456 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c | |||
@@ -209,7 +209,7 @@ mISDN_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
209 | 209 | ||
210 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { | 210 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { |
211 | err = -EFAULT; | 211 | err = -EFAULT; |
212 | goto drop; | 212 | goto done; |
213 | } | 213 | } |
214 | 214 | ||
215 | memcpy(mISDN_HEAD_P(skb), skb->data, MISDN_HEADER_LEN); | 215 | memcpy(mISDN_HEAD_P(skb), skb->data, MISDN_HEADER_LEN); |
@@ -222,7 +222,7 @@ mISDN_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
222 | } else { /* use default for L2 messages */ | 222 | } else { /* use default for L2 messages */ |
223 | if ((sk->sk_protocol == ISDN_P_LAPD_TE) || | 223 | if ((sk->sk_protocol == ISDN_P_LAPD_TE) || |
224 | (sk->sk_protocol == ISDN_P_LAPD_NT)) | 224 | (sk->sk_protocol == ISDN_P_LAPD_NT)) |
225 | mISDN_HEAD_ID(skb) = _pms(sk)->ch.nr; | 225 | mISDN_HEAD_ID(skb) = _pms(sk)->ch.nr; |
226 | } | 226 | } |
227 | 227 | ||
228 | if (*debug & DEBUG_SOCKET) | 228 | if (*debug & DEBUG_SOCKET) |
@@ -230,19 +230,21 @@ mISDN_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
230 | __func__, mISDN_HEAD_ID(skb)); | 230 | __func__, mISDN_HEAD_ID(skb)); |
231 | 231 | ||
232 | err = -ENODEV; | 232 | err = -ENODEV; |
233 | if (!_pms(sk)->ch.peer || | 233 | if (!_pms(sk)->ch.peer) |
234 | (err = _pms(sk)->ch.recv(_pms(sk)->ch.peer, skb))) | 234 | goto done; |
235 | goto drop; | 235 | err = _pms(sk)->ch.recv(_pms(sk)->ch.peer, skb); |
236 | 236 | if (err) | |
237 | err = len; | 237 | goto done; |
238 | else { | ||
239 | skb = NULL; | ||
240 | err = len; | ||
241 | } | ||
238 | 242 | ||
239 | done: | 243 | done: |
244 | if (skb) | ||
245 | kfree_skb(skb); | ||
240 | release_sock(sk); | 246 | release_sock(sk); |
241 | return err; | 247 | return err; |
242 | |||
243 | drop: | ||
244 | kfree_skb(skb); | ||
245 | goto done; | ||
246 | } | 248 | } |
247 | 249 | ||
248 | static int | 250 | static int |
@@ -292,7 +294,7 @@ static int | |||
292 | data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p) | 294 | data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p) |
293 | { | 295 | { |
294 | struct mISDN_ctrl_req cq; | 296 | struct mISDN_ctrl_req cq; |
295 | int err = -EINVAL, val; | 297 | int err = -EINVAL, val[2]; |
296 | struct mISDNchannel *bchan, *next; | 298 | struct mISDNchannel *bchan, *next; |
297 | 299 | ||
298 | lock_sock(sk); | 300 | lock_sock(sk); |
@@ -328,12 +330,27 @@ data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p) | |||
328 | err = -EINVAL; | 330 | err = -EINVAL; |
329 | break; | 331 | break; |
330 | } | 332 | } |
331 | if (get_user(val, (int __user *)p)) { | 333 | val[0] = cmd; |
334 | if (get_user(val[1], (int __user *)p)) { | ||
335 | err = -EFAULT; | ||
336 | break; | ||
337 | } | ||
338 | err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr, | ||
339 | CONTROL_CHANNEL, val); | ||
340 | break; | ||
341 | case IMHOLD_L1: | ||
342 | if (sk->sk_protocol != ISDN_P_LAPD_NT | ||
343 | && sk->sk_protocol != ISDN_P_LAPD_TE) { | ||
344 | err = -EINVAL; | ||
345 | break; | ||
346 | } | ||
347 | val[0] = cmd; | ||
348 | if (get_user(val[1], (int __user *)p)) { | ||
332 | err = -EFAULT; | 349 | err = -EFAULT; |
333 | break; | 350 | break; |
334 | } | 351 | } |
335 | err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr, | 352 | err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr, |
336 | CONTROL_CHANNEL, &val); | 353 | CONTROL_CHANNEL, val); |
337 | break; | 354 | break; |
338 | default: | 355 | default: |
339 | err = -EINVAL; | 356 | err = -EINVAL; |