diff options
Diffstat (limited to 'net/l2tp/l2tp_ip6.c')
-rw-r--r-- | net/l2tp/l2tp_ip6.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index a4abcbc4c09a..88b397c30d86 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c | |||
@@ -156,19 +156,19 @@ static int l2tp_ip6_recv(struct sk_buff *skb) | |||
156 | } | 156 | } |
157 | 157 | ||
158 | /* Ok, this is a data packet. Lookup the session. */ | 158 | /* Ok, this is a data packet. Lookup the session. */ |
159 | session = l2tp_session_find(net, NULL, session_id); | 159 | session = l2tp_session_get(net, NULL, session_id, true); |
160 | if (session == NULL) | 160 | if (!session) |
161 | goto discard; | 161 | goto discard; |
162 | 162 | ||
163 | tunnel = session->tunnel; | 163 | tunnel = session->tunnel; |
164 | if (tunnel == NULL) | 164 | if (!tunnel) |
165 | goto discard; | 165 | goto discard_sess; |
166 | 166 | ||
167 | /* Trace packet contents, if enabled */ | 167 | /* Trace packet contents, if enabled */ |
168 | if (tunnel->debug & L2TP_MSG_DATA) { | 168 | if (tunnel->debug & L2TP_MSG_DATA) { |
169 | length = min(32u, skb->len); | 169 | length = min(32u, skb->len); |
170 | if (!pskb_may_pull(skb, length)) | 170 | if (!pskb_may_pull(skb, length)) |
171 | goto discard; | 171 | goto discard_sess; |
172 | 172 | ||
173 | /* Point to L2TP header */ | 173 | /* Point to L2TP header */ |
174 | optr = ptr = skb->data; | 174 | optr = ptr = skb->data; |
@@ -179,6 +179,8 @@ static int l2tp_ip6_recv(struct sk_buff *skb) | |||
179 | 179 | ||
180 | l2tp_recv_common(session, skb, ptr, optr, 0, skb->len, | 180 | l2tp_recv_common(session, skb, ptr, optr, 0, skb->len, |
181 | tunnel->recv_payload_hook); | 181 | tunnel->recv_payload_hook); |
182 | l2tp_session_dec_refcount(session); | ||
183 | |||
182 | return 0; | 184 | return 0; |
183 | 185 | ||
184 | pass_up: | 186 | pass_up: |
@@ -191,9 +193,10 @@ pass_up: | |||
191 | 193 | ||
192 | tunnel_id = ntohl(*(__be32 *) &skb->data[4]); | 194 | tunnel_id = ntohl(*(__be32 *) &skb->data[4]); |
193 | tunnel = l2tp_tunnel_find(net, tunnel_id); | 195 | tunnel = l2tp_tunnel_find(net, tunnel_id); |
194 | if (tunnel != NULL) | 196 | if (tunnel) { |
195 | sk = tunnel->sock; | 197 | sk = tunnel->sock; |
196 | else { | 198 | sock_hold(sk); |
199 | } else { | ||
197 | struct ipv6hdr *iph = ipv6_hdr(skb); | 200 | struct ipv6hdr *iph = ipv6_hdr(skb); |
198 | 201 | ||
199 | read_lock_bh(&l2tp_ip6_lock); | 202 | read_lock_bh(&l2tp_ip6_lock); |
@@ -215,6 +218,12 @@ pass_up: | |||
215 | 218 | ||
216 | return sk_receive_skb(sk, skb, 1); | 219 | return sk_receive_skb(sk, skb, 1); |
217 | 220 | ||
221 | discard_sess: | ||
222 | if (session->deref) | ||
223 | session->deref(session); | ||
224 | l2tp_session_dec_refcount(session); | ||
225 | goto discard; | ||
226 | |||
218 | discard_put: | 227 | discard_put: |
219 | sock_put(sk); | 228 | sock_put(sk); |
220 | 229 | ||