aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ppp/pptp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ppp/pptp.c')
-rw-r--r--drivers/net/ppp/pptp.c34
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
132static int add_chan(struct pppox_sock *sock) 132static 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
444out:
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);