diff options
Diffstat (limited to 'drivers/net/ppp/pptp.c')
-rw-r--r-- | drivers/net/ppp/pptp.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 90868ca5e341..ae0905ed4a32 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c | |||
@@ -129,24 +129,27 @@ static int lookup_chan_dst(u16 call_id, __be32 d_addr) | |||
129 | return i < MAX_CALLID; | 129 | return i < MAX_CALLID; |
130 | } | 130 | } |
131 | 131 | ||
132 | static int add_chan(struct pppox_sock *sock) | 132 | static int add_chan(struct pppox_sock *sock, |
133 | struct pptp_addr *sa) | ||
133 | { | 134 | { |
134 | static int call_id; | 135 | static int call_id; |
135 | 136 | ||
136 | spin_lock(&chan_lock); | 137 | spin_lock(&chan_lock); |
137 | if (!sock->proto.pptp.src_addr.call_id) { | 138 | if (!sa->call_id) { |
138 | call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1); | 139 | call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1); |
139 | if (call_id == MAX_CALLID) { | 140 | if (call_id == MAX_CALLID) { |
140 | call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1); | 141 | call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1); |
141 | if (call_id == MAX_CALLID) | 142 | if (call_id == MAX_CALLID) |
142 | goto out_err; | 143 | goto out_err; |
143 | } | 144 | } |
144 | sock->proto.pptp.src_addr.call_id = call_id; | 145 | sa->call_id = call_id; |
145 | } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap)) | 146 | } else if (test_bit(sa->call_id, callid_bitmap)) { |
146 | goto out_err; | 147 | goto out_err; |
148 | } | ||
147 | 149 | ||
148 | set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap); | 150 | sock->proto.pptp.src_addr = *sa; |
149 | rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock); | 151 | set_bit(sa->call_id, callid_bitmap); |
152 | rcu_assign_pointer(callid_sock[sa->call_id], sock); | ||
150 | spin_unlock(&chan_lock); | 153 | spin_unlock(&chan_lock); |
151 | 154 | ||
152 | return 0; | 155 | return 0; |
@@ -416,7 +419,6 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr, | |||
416 | struct sock *sk = sock->sk; | 419 | struct sock *sk = sock->sk; |
417 | struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr; | 420 | struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr; |
418 | struct pppox_sock *po = pppox_sk(sk); | 421 | struct pppox_sock *po = pppox_sk(sk); |
419 | struct pptp_opt *opt = &po->proto.pptp; | ||
420 | int error = 0; | 422 | int error = 0; |
421 | 423 | ||
422 | if (sockaddr_len < sizeof(struct sockaddr_pppox)) | 424 | if (sockaddr_len < sizeof(struct sockaddr_pppox)) |
@@ -424,10 +426,22 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr, | |||
424 | 426 | ||
425 | lock_sock(sk); | 427 | lock_sock(sk); |
426 | 428 | ||
427 | opt->src_addr = sp->sa_addr.pptp; | 429 | if (sk->sk_state & PPPOX_DEAD) { |
428 | if (add_chan(po)) | 430 | error = -EALREADY; |
431 | goto out; | ||
432 | } | ||
433 | |||
434 | if (sk->sk_state & PPPOX_BOUND) { | ||
429 | error = -EBUSY; | 435 | error = -EBUSY; |
436 | goto out; | ||
437 | } | ||
438 | |||
439 | if (add_chan(po, &sp->sa_addr.pptp)) | ||
440 | error = -EBUSY; | ||
441 | else | ||
442 | sk->sk_state |= PPPOX_BOUND; | ||
430 | 443 | ||
444 | out: | ||
431 | release_sock(sk); | 445 | release_sock(sk); |
432 | return error; | 446 | return error; |
433 | } | 447 | } |
@@ -498,7 +512,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, | |||
498 | } | 512 | } |
499 | 513 | ||
500 | opt->dst_addr = sp->sa_addr.pptp; | 514 | opt->dst_addr = sp->sa_addr.pptp; |
501 | sk->sk_state = PPPOX_CONNECTED; | 515 | sk->sk_state |= PPPOX_CONNECTED; |
502 | 516 | ||
503 | end: | 517 | end: |
504 | release_sock(sk); | 518 | release_sock(sk); |