1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Stream Parser
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2016 Tom Herbert <tom@herbertland.com>
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/bpf.h>
9*4882a593Smuzhiyun #include <linux/errno.h>
10*4882a593Smuzhiyun #include <linux/errqueue.h>
11*4882a593Smuzhiyun #include <linux/file.h>
12*4882a593Smuzhiyun #include <linux/in.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/export.h>
15*4882a593Smuzhiyun #include <linux/init.h>
16*4882a593Smuzhiyun #include <linux/net.h>
17*4882a593Smuzhiyun #include <linux/netdevice.h>
18*4882a593Smuzhiyun #include <linux/poll.h>
19*4882a593Smuzhiyun #include <linux/rculist.h>
20*4882a593Smuzhiyun #include <linux/skbuff.h>
21*4882a593Smuzhiyun #include <linux/socket.h>
22*4882a593Smuzhiyun #include <linux/uaccess.h>
23*4882a593Smuzhiyun #include <linux/workqueue.h>
24*4882a593Smuzhiyun #include <net/strparser.h>
25*4882a593Smuzhiyun #include <net/netns/generic.h>
26*4882a593Smuzhiyun #include <net/sock.h>
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun static struct workqueue_struct *strp_wq;
29*4882a593Smuzhiyun
_strp_msg(struct sk_buff * skb)30*4882a593Smuzhiyun static inline struct _strp_msg *_strp_msg(struct sk_buff *skb)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun return (struct _strp_msg *)((void *)skb->cb +
33*4882a593Smuzhiyun offsetof(struct sk_skb_cb, strp));
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /* Lower lock held */
strp_abort_strp(struct strparser * strp,int err)37*4882a593Smuzhiyun static void strp_abort_strp(struct strparser *strp, int err)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun /* Unrecoverable error in receive */
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun cancel_delayed_work(&strp->msg_timer_work);
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun if (strp->stopped)
44*4882a593Smuzhiyun return;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun strp->stopped = 1;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun if (strp->sk) {
49*4882a593Smuzhiyun struct sock *sk = strp->sk;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun /* Report an error on the lower socket */
52*4882a593Smuzhiyun sk->sk_err = -err;
53*4882a593Smuzhiyun sk->sk_error_report(sk);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
strp_start_timer(struct strparser * strp,long timeo)57*4882a593Smuzhiyun static void strp_start_timer(struct strparser *strp, long timeo)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun if (timeo && timeo != LONG_MAX)
60*4882a593Smuzhiyun mod_delayed_work(strp_wq, &strp->msg_timer_work, timeo);
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun /* Lower lock held */
strp_parser_err(struct strparser * strp,int err,read_descriptor_t * desc)64*4882a593Smuzhiyun static void strp_parser_err(struct strparser *strp, int err,
65*4882a593Smuzhiyun read_descriptor_t *desc)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun desc->error = err;
68*4882a593Smuzhiyun kfree_skb(strp->skb_head);
69*4882a593Smuzhiyun strp->skb_head = NULL;
70*4882a593Smuzhiyun strp->cb.abort_parser(strp, err);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
strp_peek_len(struct strparser * strp)73*4882a593Smuzhiyun static inline int strp_peek_len(struct strparser *strp)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun if (strp->sk) {
76*4882a593Smuzhiyun struct socket *sock = strp->sk->sk_socket;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun return sock->ops->peek_len(sock);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun /* If we don't have an associated socket there's nothing to peek.
82*4882a593Smuzhiyun * Return int max to avoid stopping the strparser.
83*4882a593Smuzhiyun */
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun return INT_MAX;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun /* Lower socket lock held */
__strp_recv(read_descriptor_t * desc,struct sk_buff * orig_skb,unsigned int orig_offset,size_t orig_len,size_t max_msg_size,long timeo)89*4882a593Smuzhiyun static int __strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
90*4882a593Smuzhiyun unsigned int orig_offset, size_t orig_len,
91*4882a593Smuzhiyun size_t max_msg_size, long timeo)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun struct strparser *strp = (struct strparser *)desc->arg.data;
94*4882a593Smuzhiyun struct _strp_msg *stm;
95*4882a593Smuzhiyun struct sk_buff *head, *skb;
96*4882a593Smuzhiyun size_t eaten = 0, cand_len;
97*4882a593Smuzhiyun ssize_t extra;
98*4882a593Smuzhiyun int err;
99*4882a593Smuzhiyun bool cloned_orig = false;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun if (strp->paused)
102*4882a593Smuzhiyun return 0;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun head = strp->skb_head;
105*4882a593Smuzhiyun if (head) {
106*4882a593Smuzhiyun /* Message already in progress */
107*4882a593Smuzhiyun if (unlikely(orig_offset)) {
108*4882a593Smuzhiyun /* Getting data with a non-zero offset when a message is
109*4882a593Smuzhiyun * in progress is not expected. If it does happen, we
110*4882a593Smuzhiyun * need to clone and pull since we can't deal with
111*4882a593Smuzhiyun * offsets in the skbs for a message expect in the head.
112*4882a593Smuzhiyun */
113*4882a593Smuzhiyun orig_skb = skb_clone(orig_skb, GFP_ATOMIC);
114*4882a593Smuzhiyun if (!orig_skb) {
115*4882a593Smuzhiyun STRP_STATS_INCR(strp->stats.mem_fail);
116*4882a593Smuzhiyun desc->error = -ENOMEM;
117*4882a593Smuzhiyun return 0;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun if (!pskb_pull(orig_skb, orig_offset)) {
120*4882a593Smuzhiyun STRP_STATS_INCR(strp->stats.mem_fail);
121*4882a593Smuzhiyun kfree_skb(orig_skb);
122*4882a593Smuzhiyun desc->error = -ENOMEM;
123*4882a593Smuzhiyun return 0;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun cloned_orig = true;
126*4882a593Smuzhiyun orig_offset = 0;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun if (!strp->skb_nextp) {
130*4882a593Smuzhiyun /* We are going to append to the frags_list of head.
131*4882a593Smuzhiyun * Need to unshare the frag_list.
132*4882a593Smuzhiyun */
133*4882a593Smuzhiyun err = skb_unclone(head, GFP_ATOMIC);
134*4882a593Smuzhiyun if (err) {
135*4882a593Smuzhiyun STRP_STATS_INCR(strp->stats.mem_fail);
136*4882a593Smuzhiyun desc->error = err;
137*4882a593Smuzhiyun return 0;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun if (unlikely(skb_shinfo(head)->frag_list)) {
141*4882a593Smuzhiyun /* We can't append to an sk_buff that already
142*4882a593Smuzhiyun * has a frag_list. We create a new head, point
143*4882a593Smuzhiyun * the frag_list of that to the old head, and
144*4882a593Smuzhiyun * then are able to use the old head->next for
145*4882a593Smuzhiyun * appending to the message.
146*4882a593Smuzhiyun */
147*4882a593Smuzhiyun if (WARN_ON(head->next)) {
148*4882a593Smuzhiyun desc->error = -EINVAL;
149*4882a593Smuzhiyun return 0;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun skb = alloc_skb_for_msg(head);
153*4882a593Smuzhiyun if (!skb) {
154*4882a593Smuzhiyun STRP_STATS_INCR(strp->stats.mem_fail);
155*4882a593Smuzhiyun desc->error = -ENOMEM;
156*4882a593Smuzhiyun return 0;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun strp->skb_nextp = &head->next;
160*4882a593Smuzhiyun strp->skb_head = skb;
161*4882a593Smuzhiyun head = skb;
162*4882a593Smuzhiyun } else {
163*4882a593Smuzhiyun strp->skb_nextp =
164*4882a593Smuzhiyun &skb_shinfo(head)->frag_list;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun while (eaten < orig_len) {
170*4882a593Smuzhiyun /* Always clone since we will consume something */
171*4882a593Smuzhiyun skb = skb_clone(orig_skb, GFP_ATOMIC);
172*4882a593Smuzhiyun if (!skb) {
173*4882a593Smuzhiyun STRP_STATS_INCR(strp->stats.mem_fail);
174*4882a593Smuzhiyun desc->error = -ENOMEM;
175*4882a593Smuzhiyun break;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun cand_len = orig_len - eaten;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun head = strp->skb_head;
181*4882a593Smuzhiyun if (!head) {
182*4882a593Smuzhiyun head = skb;
183*4882a593Smuzhiyun strp->skb_head = head;
184*4882a593Smuzhiyun /* Will set skb_nextp on next packet if needed */
185*4882a593Smuzhiyun strp->skb_nextp = NULL;
186*4882a593Smuzhiyun stm = _strp_msg(head);
187*4882a593Smuzhiyun memset(stm, 0, sizeof(*stm));
188*4882a593Smuzhiyun stm->strp.offset = orig_offset + eaten;
189*4882a593Smuzhiyun } else {
190*4882a593Smuzhiyun /* Unclone if we are appending to an skb that we
191*4882a593Smuzhiyun * already share a frag_list with.
192*4882a593Smuzhiyun */
193*4882a593Smuzhiyun if (skb_has_frag_list(skb)) {
194*4882a593Smuzhiyun err = skb_unclone(skb, GFP_ATOMIC);
195*4882a593Smuzhiyun if (err) {
196*4882a593Smuzhiyun STRP_STATS_INCR(strp->stats.mem_fail);
197*4882a593Smuzhiyun desc->error = err;
198*4882a593Smuzhiyun break;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun stm = _strp_msg(head);
203*4882a593Smuzhiyun *strp->skb_nextp = skb;
204*4882a593Smuzhiyun strp->skb_nextp = &skb->next;
205*4882a593Smuzhiyun head->data_len += skb->len;
206*4882a593Smuzhiyun head->len += skb->len;
207*4882a593Smuzhiyun head->truesize += skb->truesize;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun if (!stm->strp.full_len) {
211*4882a593Smuzhiyun ssize_t len;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun len = (*strp->cb.parse_msg)(strp, head);
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun if (!len) {
216*4882a593Smuzhiyun /* Need more header to determine length */
217*4882a593Smuzhiyun if (!stm->accum_len) {
218*4882a593Smuzhiyun /* Start RX timer for new message */
219*4882a593Smuzhiyun strp_start_timer(strp, timeo);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun stm->accum_len += cand_len;
222*4882a593Smuzhiyun eaten += cand_len;
223*4882a593Smuzhiyun STRP_STATS_INCR(strp->stats.need_more_hdr);
224*4882a593Smuzhiyun WARN_ON(eaten != orig_len);
225*4882a593Smuzhiyun break;
226*4882a593Smuzhiyun } else if (len < 0) {
227*4882a593Smuzhiyun if (len == -ESTRPIPE && stm->accum_len) {
228*4882a593Smuzhiyun len = -ENODATA;
229*4882a593Smuzhiyun strp->unrecov_intr = 1;
230*4882a593Smuzhiyun } else {
231*4882a593Smuzhiyun strp->interrupted = 1;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun strp_parser_err(strp, len, desc);
234*4882a593Smuzhiyun break;
235*4882a593Smuzhiyun } else if (len > max_msg_size) {
236*4882a593Smuzhiyun /* Message length exceeds maximum allowed */
237*4882a593Smuzhiyun STRP_STATS_INCR(strp->stats.msg_too_big);
238*4882a593Smuzhiyun strp_parser_err(strp, -EMSGSIZE, desc);
239*4882a593Smuzhiyun break;
240*4882a593Smuzhiyun } else if (len <= (ssize_t)head->len -
241*4882a593Smuzhiyun skb->len - stm->strp.offset) {
242*4882a593Smuzhiyun /* Length must be into new skb (and also
243*4882a593Smuzhiyun * greater than zero)
244*4882a593Smuzhiyun */
245*4882a593Smuzhiyun STRP_STATS_INCR(strp->stats.bad_hdr_len);
246*4882a593Smuzhiyun strp_parser_err(strp, -EPROTO, desc);
247*4882a593Smuzhiyun break;
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun stm->strp.full_len = len;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun extra = (ssize_t)(stm->accum_len + cand_len) -
254*4882a593Smuzhiyun stm->strp.full_len;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun if (extra < 0) {
257*4882a593Smuzhiyun /* Message not complete yet. */
258*4882a593Smuzhiyun if (stm->strp.full_len - stm->accum_len >
259*4882a593Smuzhiyun strp_peek_len(strp)) {
260*4882a593Smuzhiyun /* Don't have the whole message in the socket
261*4882a593Smuzhiyun * buffer. Set strp->need_bytes to wait for
262*4882a593Smuzhiyun * the rest of the message. Also, set "early
263*4882a593Smuzhiyun * eaten" since we've already buffered the skb
264*4882a593Smuzhiyun * but don't consume yet per strp_read_sock.
265*4882a593Smuzhiyun */
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun if (!stm->accum_len) {
268*4882a593Smuzhiyun /* Start RX timer for new message */
269*4882a593Smuzhiyun strp_start_timer(strp, timeo);
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun stm->accum_len += cand_len;
273*4882a593Smuzhiyun eaten += cand_len;
274*4882a593Smuzhiyun strp->need_bytes = stm->strp.full_len -
275*4882a593Smuzhiyun stm->accum_len;
276*4882a593Smuzhiyun STRP_STATS_ADD(strp->stats.bytes, cand_len);
277*4882a593Smuzhiyun desc->count = 0; /* Stop reading socket */
278*4882a593Smuzhiyun break;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun stm->accum_len += cand_len;
281*4882a593Smuzhiyun eaten += cand_len;
282*4882a593Smuzhiyun WARN_ON(eaten != orig_len);
283*4882a593Smuzhiyun break;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun /* Positive extra indicates more bytes than needed for the
287*4882a593Smuzhiyun * message
288*4882a593Smuzhiyun */
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun WARN_ON(extra > cand_len);
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun eaten += (cand_len - extra);
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun /* Hurray, we have a new message! */
295*4882a593Smuzhiyun cancel_delayed_work(&strp->msg_timer_work);
296*4882a593Smuzhiyun strp->skb_head = NULL;
297*4882a593Smuzhiyun strp->need_bytes = 0;
298*4882a593Smuzhiyun STRP_STATS_INCR(strp->stats.msgs);
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun /* Give skb to upper layer */
301*4882a593Smuzhiyun strp->cb.rcv_msg(strp, head);
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun if (unlikely(strp->paused)) {
304*4882a593Smuzhiyun /* Upper layer paused strp */
305*4882a593Smuzhiyun break;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun if (cloned_orig)
310*4882a593Smuzhiyun kfree_skb(orig_skb);
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun STRP_STATS_ADD(strp->stats.bytes, eaten);
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun return eaten;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
strp_process(struct strparser * strp,struct sk_buff * orig_skb,unsigned int orig_offset,size_t orig_len,size_t max_msg_size,long timeo)317*4882a593Smuzhiyun int strp_process(struct strparser *strp, struct sk_buff *orig_skb,
318*4882a593Smuzhiyun unsigned int orig_offset, size_t orig_len,
319*4882a593Smuzhiyun size_t max_msg_size, long timeo)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun read_descriptor_t desc; /* Dummy arg to strp_recv */
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun desc.arg.data = strp;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun return __strp_recv(&desc, orig_skb, orig_offset, orig_len,
326*4882a593Smuzhiyun max_msg_size, timeo);
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(strp_process);
329*4882a593Smuzhiyun
strp_recv(read_descriptor_t * desc,struct sk_buff * orig_skb,unsigned int orig_offset,size_t orig_len)330*4882a593Smuzhiyun static int strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
331*4882a593Smuzhiyun unsigned int orig_offset, size_t orig_len)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun struct strparser *strp = (struct strparser *)desc->arg.data;
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun return __strp_recv(desc, orig_skb, orig_offset, orig_len,
336*4882a593Smuzhiyun strp->sk->sk_rcvbuf, strp->sk->sk_rcvtimeo);
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
default_read_sock_done(struct strparser * strp,int err)339*4882a593Smuzhiyun static int default_read_sock_done(struct strparser *strp, int err)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun return err;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun /* Called with lock held on lower socket */
strp_read_sock(struct strparser * strp)345*4882a593Smuzhiyun static int strp_read_sock(struct strparser *strp)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun struct socket *sock = strp->sk->sk_socket;
348*4882a593Smuzhiyun read_descriptor_t desc;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun if (unlikely(!sock || !sock->ops || !sock->ops->read_sock))
351*4882a593Smuzhiyun return -EBUSY;
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun desc.arg.data = strp;
354*4882a593Smuzhiyun desc.error = 0;
355*4882a593Smuzhiyun desc.count = 1; /* give more than one skb per call */
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun /* sk should be locked here, so okay to do read_sock */
358*4882a593Smuzhiyun sock->ops->read_sock(strp->sk, &desc, strp_recv);
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun desc.error = strp->cb.read_sock_done(strp, desc.error);
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun return desc.error;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun /* Lower sock lock held */
strp_data_ready(struct strparser * strp)366*4882a593Smuzhiyun void strp_data_ready(struct strparser *strp)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun if (unlikely(strp->stopped) || strp->paused)
369*4882a593Smuzhiyun return;
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun /* This check is needed to synchronize with do_strp_work.
372*4882a593Smuzhiyun * do_strp_work acquires a process lock (lock_sock) whereas
373*4882a593Smuzhiyun * the lock held here is bh_lock_sock. The two locks can be
374*4882a593Smuzhiyun * held by different threads at the same time, but bh_lock_sock
375*4882a593Smuzhiyun * allows a thread in BH context to safely check if the process
376*4882a593Smuzhiyun * lock is held. In this case, if the lock is held, queue work.
377*4882a593Smuzhiyun */
378*4882a593Smuzhiyun if (sock_owned_by_user_nocheck(strp->sk)) {
379*4882a593Smuzhiyun queue_work(strp_wq, &strp->work);
380*4882a593Smuzhiyun return;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun if (strp->need_bytes) {
384*4882a593Smuzhiyun if (strp_peek_len(strp) < strp->need_bytes)
385*4882a593Smuzhiyun return;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun if (strp_read_sock(strp) == -ENOMEM)
389*4882a593Smuzhiyun queue_work(strp_wq, &strp->work);
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(strp_data_ready);
392*4882a593Smuzhiyun
do_strp_work(struct strparser * strp)393*4882a593Smuzhiyun static void do_strp_work(struct strparser *strp)
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun /* We need the read lock to synchronize with strp_data_ready. We
396*4882a593Smuzhiyun * need the socket lock for calling strp_read_sock.
397*4882a593Smuzhiyun */
398*4882a593Smuzhiyun strp->cb.lock(strp);
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun if (unlikely(strp->stopped))
401*4882a593Smuzhiyun goto out;
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun if (strp->paused)
404*4882a593Smuzhiyun goto out;
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun if (strp_read_sock(strp) == -ENOMEM)
407*4882a593Smuzhiyun queue_work(strp_wq, &strp->work);
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun out:
410*4882a593Smuzhiyun strp->cb.unlock(strp);
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
strp_work(struct work_struct * w)413*4882a593Smuzhiyun static void strp_work(struct work_struct *w)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun do_strp_work(container_of(w, struct strparser, work));
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
strp_msg_timeout(struct work_struct * w)418*4882a593Smuzhiyun static void strp_msg_timeout(struct work_struct *w)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun struct strparser *strp = container_of(w, struct strparser,
421*4882a593Smuzhiyun msg_timer_work.work);
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun /* Message assembly timed out */
424*4882a593Smuzhiyun STRP_STATS_INCR(strp->stats.msg_timeouts);
425*4882a593Smuzhiyun strp->cb.lock(strp);
426*4882a593Smuzhiyun strp->cb.abort_parser(strp, -ETIMEDOUT);
427*4882a593Smuzhiyun strp->cb.unlock(strp);
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun
strp_sock_lock(struct strparser * strp)430*4882a593Smuzhiyun static void strp_sock_lock(struct strparser *strp)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun lock_sock(strp->sk);
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
strp_sock_unlock(struct strparser * strp)435*4882a593Smuzhiyun static void strp_sock_unlock(struct strparser *strp)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun release_sock(strp->sk);
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
strp_init(struct strparser * strp,struct sock * sk,const struct strp_callbacks * cb)440*4882a593Smuzhiyun int strp_init(struct strparser *strp, struct sock *sk,
441*4882a593Smuzhiyun const struct strp_callbacks *cb)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun if (!cb || !cb->rcv_msg || !cb->parse_msg)
445*4882a593Smuzhiyun return -EINVAL;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun /* The sk (sock) arg determines the mode of the stream parser.
448*4882a593Smuzhiyun *
449*4882a593Smuzhiyun * If the sock is set then the strparser is in receive callback mode.
450*4882a593Smuzhiyun * The upper layer calls strp_data_ready to kick receive processing
451*4882a593Smuzhiyun * and strparser calls the read_sock function on the socket to
452*4882a593Smuzhiyun * get packets.
453*4882a593Smuzhiyun *
454*4882a593Smuzhiyun * If the sock is not set then the strparser is in general mode.
455*4882a593Smuzhiyun * The upper layer calls strp_process for each skb to be parsed.
456*4882a593Smuzhiyun */
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun if (!sk) {
459*4882a593Smuzhiyun if (!cb->lock || !cb->unlock)
460*4882a593Smuzhiyun return -EINVAL;
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun memset(strp, 0, sizeof(*strp));
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun strp->sk = sk;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun strp->cb.lock = cb->lock ? : strp_sock_lock;
468*4882a593Smuzhiyun strp->cb.unlock = cb->unlock ? : strp_sock_unlock;
469*4882a593Smuzhiyun strp->cb.rcv_msg = cb->rcv_msg;
470*4882a593Smuzhiyun strp->cb.parse_msg = cb->parse_msg;
471*4882a593Smuzhiyun strp->cb.read_sock_done = cb->read_sock_done ? : default_read_sock_done;
472*4882a593Smuzhiyun strp->cb.abort_parser = cb->abort_parser ? : strp_abort_strp;
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun INIT_DELAYED_WORK(&strp->msg_timer_work, strp_msg_timeout);
475*4882a593Smuzhiyun INIT_WORK(&strp->work, strp_work);
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun return 0;
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(strp_init);
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun /* Sock process lock held (lock_sock) */
__strp_unpause(struct strparser * strp)482*4882a593Smuzhiyun void __strp_unpause(struct strparser *strp)
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun strp->paused = 0;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun if (strp->need_bytes) {
487*4882a593Smuzhiyun if (strp_peek_len(strp) < strp->need_bytes)
488*4882a593Smuzhiyun return;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun strp_read_sock(strp);
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(__strp_unpause);
493*4882a593Smuzhiyun
strp_unpause(struct strparser * strp)494*4882a593Smuzhiyun void strp_unpause(struct strparser *strp)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun strp->paused = 0;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun /* Sync setting paused with RX work */
499*4882a593Smuzhiyun smp_mb();
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun queue_work(strp_wq, &strp->work);
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(strp_unpause);
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun /* strp must already be stopped so that strp_recv will no longer be called.
506*4882a593Smuzhiyun * Note that strp_done is not called with the lower socket held.
507*4882a593Smuzhiyun */
strp_done(struct strparser * strp)508*4882a593Smuzhiyun void strp_done(struct strparser *strp)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun WARN_ON(!strp->stopped);
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun cancel_delayed_work_sync(&strp->msg_timer_work);
513*4882a593Smuzhiyun cancel_work_sync(&strp->work);
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun if (strp->skb_head) {
516*4882a593Smuzhiyun kfree_skb(strp->skb_head);
517*4882a593Smuzhiyun strp->skb_head = NULL;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(strp_done);
521*4882a593Smuzhiyun
strp_stop(struct strparser * strp)522*4882a593Smuzhiyun void strp_stop(struct strparser *strp)
523*4882a593Smuzhiyun {
524*4882a593Smuzhiyun strp->stopped = 1;
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(strp_stop);
527*4882a593Smuzhiyun
strp_check_rcv(struct strparser * strp)528*4882a593Smuzhiyun void strp_check_rcv(struct strparser *strp)
529*4882a593Smuzhiyun {
530*4882a593Smuzhiyun queue_work(strp_wq, &strp->work);
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(strp_check_rcv);
533*4882a593Smuzhiyun
strp_dev_init(void)534*4882a593Smuzhiyun static int __init strp_dev_init(void)
535*4882a593Smuzhiyun {
536*4882a593Smuzhiyun strp_wq = create_singlethread_workqueue("kstrp");
537*4882a593Smuzhiyun if (unlikely(!strp_wq))
538*4882a593Smuzhiyun return -ENOMEM;
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun return 0;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun device_initcall(strp_dev_init);
543