143a0c675STom Herbert /* 243a0c675STom Herbert * Stream Parser 343a0c675STom Herbert * 443a0c675STom Herbert * Copyright (c) 2016 Tom Herbert <[email protected]> 543a0c675STom Herbert * 643a0c675STom Herbert * This program is free software; you can redistribute it and/or modify 743a0c675STom Herbert * it under the terms of the GNU General Public License version 2 843a0c675STom Herbert * as published by the Free Software Foundation. 943a0c675STom Herbert */ 1043a0c675STom Herbert 1143a0c675STom Herbert #include <linux/bpf.h> 1243a0c675STom Herbert #include <linux/errno.h> 1343a0c675STom Herbert #include <linux/errqueue.h> 1443a0c675STom Herbert #include <linux/file.h> 1543a0c675STom Herbert #include <linux/in.h> 1643a0c675STom Herbert #include <linux/kernel.h> 1743a0c675STom Herbert #include <linux/module.h> 1843a0c675STom Herbert #include <linux/net.h> 1943a0c675STom Herbert #include <linux/netdevice.h> 2043a0c675STom Herbert #include <linux/poll.h> 2143a0c675STom Herbert #include <linux/rculist.h> 2243a0c675STom Herbert #include <linux/skbuff.h> 2343a0c675STom Herbert #include <linux/socket.h> 2443a0c675STom Herbert #include <linux/uaccess.h> 2543a0c675STom Herbert #include <linux/workqueue.h> 2643a0c675STom Herbert #include <net/strparser.h> 2743a0c675STom Herbert #include <net/netns/generic.h> 2843a0c675STom Herbert #include <net/sock.h> 2943a0c675STom Herbert 3043a0c675STom Herbert static struct workqueue_struct *strp_wq; 3143a0c675STom Herbert 32*bbb03029STom Herbert struct _strp_msg { 33*bbb03029STom Herbert /* Internal cb structure. struct strp_msg must be first for passing 3443a0c675STom Herbert * to upper layer. 3543a0c675STom Herbert */ 36*bbb03029STom Herbert struct strp_msg strp; 3743a0c675STom Herbert int accum_len; 3843a0c675STom Herbert int early_eaten; 3943a0c675STom Herbert }; 4043a0c675STom Herbert 41*bbb03029STom Herbert static inline struct _strp_msg *_strp_msg(struct sk_buff *skb) 4243a0c675STom Herbert { 43*bbb03029STom Herbert return (struct _strp_msg *)((void *)skb->cb + 4443a0c675STom Herbert offsetof(struct qdisc_skb_cb, data)); 4543a0c675STom Herbert } 4643a0c675STom Herbert 4743a0c675STom Herbert /* Lower lock held */ 48*bbb03029STom Herbert static void strp_abort_strp(struct strparser *strp, int err) 4943a0c675STom Herbert { 5043a0c675STom Herbert /* Unrecoverable error in receive */ 5143a0c675STom Herbert 52*bbb03029STom Herbert del_timer(&strp->msg_timer); 5343a0c675STom Herbert 54*bbb03029STom Herbert if (strp->stopped) 5543a0c675STom Herbert return; 5643a0c675STom Herbert 57*bbb03029STom Herbert strp->stopped = 1; 58*bbb03029STom Herbert 59*bbb03029STom Herbert if (strp->sk) { 60*bbb03029STom Herbert struct sock *sk = strp->sk; 6143a0c675STom Herbert 6243a0c675STom Herbert /* Report an error on the lower socket */ 63*bbb03029STom Herbert sk->sk_err = err; 64*bbb03029STom Herbert sk->sk_error_report(sk); 65*bbb03029STom Herbert } 6643a0c675STom Herbert } 6743a0c675STom Herbert 68*bbb03029STom Herbert static void strp_start_timer(struct strparser *strp, long timeo) 6943a0c675STom Herbert { 70*bbb03029STom Herbert if (timeo) 71*bbb03029STom Herbert mod_timer(&strp->msg_timer, timeo); 7243a0c675STom Herbert } 7343a0c675STom Herbert 7443a0c675STom Herbert /* Lower lock held */ 7543a0c675STom Herbert static void strp_parser_err(struct strparser *strp, int err, 7643a0c675STom Herbert read_descriptor_t *desc) 7743a0c675STom Herbert { 7843a0c675STom Herbert desc->error = err; 79*bbb03029STom Herbert kfree_skb(strp->skb_head); 80*bbb03029STom Herbert strp->skb_head = NULL; 8143a0c675STom Herbert strp->cb.abort_parser(strp, err); 8243a0c675STom Herbert } 8343a0c675STom Herbert 8496a59083STom Herbert static inline int strp_peek_len(struct strparser *strp) 8596a59083STom Herbert { 86*bbb03029STom Herbert if (strp->sk) { 8796a59083STom Herbert struct socket *sock = strp->sk->sk_socket; 8896a59083STom Herbert 8996a59083STom Herbert return sock->ops->peek_len(sock); 9096a59083STom Herbert } 9196a59083STom Herbert 92*bbb03029STom Herbert /* If we don't have an associated socket there's nothing to peek. 93*bbb03029STom Herbert * Return int max to avoid stopping the strparser. 94*bbb03029STom Herbert */ 95*bbb03029STom Herbert 96*bbb03029STom Herbert return INT_MAX; 97*bbb03029STom Herbert } 98*bbb03029STom Herbert 9943a0c675STom Herbert /* Lower socket lock held */ 100*bbb03029STom Herbert static int __strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb, 101*bbb03029STom Herbert unsigned int orig_offset, size_t orig_len, 102*bbb03029STom Herbert size_t max_msg_size, long timeo) 10343a0c675STom Herbert { 10443a0c675STom Herbert struct strparser *strp = (struct strparser *)desc->arg.data; 105*bbb03029STom Herbert struct _strp_msg *stm; 10643a0c675STom Herbert struct sk_buff *head, *skb; 10743a0c675STom Herbert size_t eaten = 0, cand_len; 10843a0c675STom Herbert ssize_t extra; 10943a0c675STom Herbert int err; 11043a0c675STom Herbert bool cloned_orig = false; 11143a0c675STom Herbert 112*bbb03029STom Herbert if (strp->paused) 11343a0c675STom Herbert return 0; 11443a0c675STom Herbert 115*bbb03029STom Herbert head = strp->skb_head; 11643a0c675STom Herbert if (head) { 11743a0c675STom Herbert /* Message already in progress */ 11843a0c675STom Herbert 119*bbb03029STom Herbert stm = _strp_msg(head); 120*bbb03029STom Herbert if (unlikely(stm->early_eaten)) { 12143a0c675STom Herbert /* Already some number of bytes on the receive sock 122*bbb03029STom Herbert * data saved in skb_head, just indicate they 12343a0c675STom Herbert * are consumed. 12443a0c675STom Herbert */ 125*bbb03029STom Herbert eaten = orig_len <= stm->early_eaten ? 126*bbb03029STom Herbert orig_len : stm->early_eaten; 127*bbb03029STom Herbert stm->early_eaten -= eaten; 12843a0c675STom Herbert 12943a0c675STom Herbert return eaten; 13043a0c675STom Herbert } 13143a0c675STom Herbert 13243a0c675STom Herbert if (unlikely(orig_offset)) { 13343a0c675STom Herbert /* Getting data with a non-zero offset when a message is 13443a0c675STom Herbert * in progress is not expected. If it does happen, we 13543a0c675STom Herbert * need to clone and pull since we can't deal with 13643a0c675STom Herbert * offsets in the skbs for a message expect in the head. 13743a0c675STom Herbert */ 13843a0c675STom Herbert orig_skb = skb_clone(orig_skb, GFP_ATOMIC); 13943a0c675STom Herbert if (!orig_skb) { 140*bbb03029STom Herbert STRP_STATS_INCR(strp->stats.mem_fail); 14143a0c675STom Herbert desc->error = -ENOMEM; 14243a0c675STom Herbert return 0; 14343a0c675STom Herbert } 14443a0c675STom Herbert if (!pskb_pull(orig_skb, orig_offset)) { 145*bbb03029STom Herbert STRP_STATS_INCR(strp->stats.mem_fail); 14643a0c675STom Herbert kfree_skb(orig_skb); 14743a0c675STom Herbert desc->error = -ENOMEM; 14843a0c675STom Herbert return 0; 14943a0c675STom Herbert } 15043a0c675STom Herbert cloned_orig = true; 15143a0c675STom Herbert orig_offset = 0; 15243a0c675STom Herbert } 15343a0c675STom Herbert 154*bbb03029STom Herbert if (!strp->skb_nextp) { 15543a0c675STom Herbert /* We are going to append to the frags_list of head. 15643a0c675STom Herbert * Need to unshare the frag_list. 15743a0c675STom Herbert */ 15843a0c675STom Herbert err = skb_unclone(head, GFP_ATOMIC); 15943a0c675STom Herbert if (err) { 160*bbb03029STom Herbert STRP_STATS_INCR(strp->stats.mem_fail); 16143a0c675STom Herbert desc->error = err; 16243a0c675STom Herbert return 0; 16343a0c675STom Herbert } 16443a0c675STom Herbert 16543a0c675STom Herbert if (unlikely(skb_shinfo(head)->frag_list)) { 16643a0c675STom Herbert /* We can't append to an sk_buff that already 16743a0c675STom Herbert * has a frag_list. We create a new head, point 16843a0c675STom Herbert * the frag_list of that to the old head, and 16943a0c675STom Herbert * then are able to use the old head->next for 17043a0c675STom Herbert * appending to the message. 17143a0c675STom Herbert */ 17243a0c675STom Herbert if (WARN_ON(head->next)) { 17343a0c675STom Herbert desc->error = -EINVAL; 17443a0c675STom Herbert return 0; 17543a0c675STom Herbert } 17643a0c675STom Herbert 17743a0c675STom Herbert skb = alloc_skb(0, GFP_ATOMIC); 17843a0c675STom Herbert if (!skb) { 179*bbb03029STom Herbert STRP_STATS_INCR(strp->stats.mem_fail); 18043a0c675STom Herbert desc->error = -ENOMEM; 18143a0c675STom Herbert return 0; 18243a0c675STom Herbert } 18343a0c675STom Herbert skb->len = head->len; 18443a0c675STom Herbert skb->data_len = head->len; 18543a0c675STom Herbert skb->truesize = head->truesize; 186*bbb03029STom Herbert *_strp_msg(skb) = *_strp_msg(head); 187*bbb03029STom Herbert strp->skb_nextp = &head->next; 18843a0c675STom Herbert skb_shinfo(skb)->frag_list = head; 189*bbb03029STom Herbert strp->skb_head = skb; 19043a0c675STom Herbert head = skb; 19143a0c675STom Herbert } else { 192*bbb03029STom Herbert strp->skb_nextp = 19343a0c675STom Herbert &skb_shinfo(head)->frag_list; 19443a0c675STom Herbert } 19543a0c675STom Herbert } 19643a0c675STom Herbert } 19743a0c675STom Herbert 19843a0c675STom Herbert while (eaten < orig_len) { 19943a0c675STom Herbert /* Always clone since we will consume something */ 20043a0c675STom Herbert skb = skb_clone(orig_skb, GFP_ATOMIC); 20143a0c675STom Herbert if (!skb) { 202*bbb03029STom Herbert STRP_STATS_INCR(strp->stats.mem_fail); 20343a0c675STom Herbert desc->error = -ENOMEM; 20443a0c675STom Herbert break; 20543a0c675STom Herbert } 20643a0c675STom Herbert 20743a0c675STom Herbert cand_len = orig_len - eaten; 20843a0c675STom Herbert 209*bbb03029STom Herbert head = strp->skb_head; 21043a0c675STom Herbert if (!head) { 21143a0c675STom Herbert head = skb; 212*bbb03029STom Herbert strp->skb_head = head; 213*bbb03029STom Herbert /* Will set skb_nextp on next packet if needed */ 214*bbb03029STom Herbert strp->skb_nextp = NULL; 215*bbb03029STom Herbert stm = _strp_msg(head); 216*bbb03029STom Herbert memset(stm, 0, sizeof(*stm)); 217*bbb03029STom Herbert stm->strp.offset = orig_offset + eaten; 21843a0c675STom Herbert } else { 21943a0c675STom Herbert /* Unclone since we may be appending to an skb that we 22043a0c675STom Herbert * already share a frag_list with. 22143a0c675STom Herbert */ 22243a0c675STom Herbert err = skb_unclone(skb, GFP_ATOMIC); 22343a0c675STom Herbert if (err) { 224*bbb03029STom Herbert STRP_STATS_INCR(strp->stats.mem_fail); 22543a0c675STom Herbert desc->error = err; 22643a0c675STom Herbert break; 22743a0c675STom Herbert } 22843a0c675STom Herbert 229*bbb03029STom Herbert stm = _strp_msg(head); 230*bbb03029STom Herbert *strp->skb_nextp = skb; 231*bbb03029STom Herbert strp->skb_nextp = &skb->next; 23243a0c675STom Herbert head->data_len += skb->len; 23343a0c675STom Herbert head->len += skb->len; 23443a0c675STom Herbert head->truesize += skb->truesize; 23543a0c675STom Herbert } 23643a0c675STom Herbert 237*bbb03029STom Herbert if (!stm->strp.full_len) { 23843a0c675STom Herbert ssize_t len; 23943a0c675STom Herbert 24043a0c675STom Herbert len = (*strp->cb.parse_msg)(strp, head); 24143a0c675STom Herbert 24243a0c675STom Herbert if (!len) { 24343a0c675STom Herbert /* Need more header to determine length */ 244*bbb03029STom Herbert if (!stm->accum_len) { 24543a0c675STom Herbert /* Start RX timer for new message */ 246*bbb03029STom Herbert strp_start_timer(strp, timeo); 24743a0c675STom Herbert } 248*bbb03029STom Herbert stm->accum_len += cand_len; 24943a0c675STom Herbert eaten += cand_len; 250*bbb03029STom Herbert STRP_STATS_INCR(strp->stats.need_more_hdr); 25143a0c675STom Herbert WARN_ON(eaten != orig_len); 25243a0c675STom Herbert break; 25343a0c675STom Herbert } else if (len < 0) { 254*bbb03029STom Herbert if (len == -ESTRPIPE && stm->accum_len) { 25543a0c675STom Herbert len = -ENODATA; 256*bbb03029STom Herbert strp->unrecov_intr = 1; 25743a0c675STom Herbert } else { 258*bbb03029STom Herbert strp->interrupted = 1; 25943a0c675STom Herbert } 2606d3a4c40SGeert Uytterhoeven strp_parser_err(strp, len, desc); 26143a0c675STom Herbert break; 262*bbb03029STom Herbert } else if (len > max_msg_size) { 26343a0c675STom Herbert /* Message length exceeds maximum allowed */ 264*bbb03029STom Herbert STRP_STATS_INCR(strp->stats.msg_too_big); 26543a0c675STom Herbert strp_parser_err(strp, -EMSGSIZE, desc); 26643a0c675STom Herbert break; 26743a0c675STom Herbert } else if (len <= (ssize_t)head->len - 268*bbb03029STom Herbert skb->len - stm->strp.offset) { 26943a0c675STom Herbert /* Length must be into new skb (and also 27043a0c675STom Herbert * greater than zero) 27143a0c675STom Herbert */ 272*bbb03029STom Herbert STRP_STATS_INCR(strp->stats.bad_hdr_len); 27343a0c675STom Herbert strp_parser_err(strp, -EPROTO, desc); 27443a0c675STom Herbert break; 27543a0c675STom Herbert } 27643a0c675STom Herbert 277*bbb03029STom Herbert stm->strp.full_len = len; 27843a0c675STom Herbert } 27943a0c675STom Herbert 280*bbb03029STom Herbert extra = (ssize_t)(stm->accum_len + cand_len) - 281*bbb03029STom Herbert stm->strp.full_len; 28243a0c675STom Herbert 28343a0c675STom Herbert if (extra < 0) { 28443a0c675STom Herbert /* Message not complete yet. */ 285*bbb03029STom Herbert if (stm->strp.full_len - stm->accum_len > 28696a59083STom Herbert strp_peek_len(strp)) { 287*bbb03029STom Herbert /* Don't have the whole message in the socket 288*bbb03029STom Herbert * buffer. Set strp->need_bytes to wait for 28943a0c675STom Herbert * the rest of the message. Also, set "early 29043a0c675STom Herbert * eaten" since we've already buffered the skb 29196a59083STom Herbert * but don't consume yet per strp_read_sock. 29243a0c675STom Herbert */ 29343a0c675STom Herbert 294*bbb03029STom Herbert if (!stm->accum_len) { 29543a0c675STom Herbert /* Start RX timer for new message */ 296*bbb03029STom Herbert strp_start_timer(strp, timeo); 29743a0c675STom Herbert } 29843a0c675STom Herbert 299*bbb03029STom Herbert strp->need_bytes = stm->strp.full_len - 300*bbb03029STom Herbert stm->accum_len; 301*bbb03029STom Herbert stm->accum_len += cand_len; 302*bbb03029STom Herbert stm->early_eaten = cand_len; 303*bbb03029STom Herbert STRP_STATS_ADD(strp->stats.bytes, cand_len); 30443a0c675STom Herbert desc->count = 0; /* Stop reading socket */ 30543a0c675STom Herbert break; 30643a0c675STom Herbert } 307*bbb03029STom Herbert stm->accum_len += cand_len; 30843a0c675STom Herbert eaten += cand_len; 30943a0c675STom Herbert WARN_ON(eaten != orig_len); 31043a0c675STom Herbert break; 31143a0c675STom Herbert } 31243a0c675STom Herbert 31343a0c675STom Herbert /* Positive extra indicates ore bytes than needed for the 31443a0c675STom Herbert * message 31543a0c675STom Herbert */ 31643a0c675STom Herbert 31743a0c675STom Herbert WARN_ON(extra > cand_len); 31843a0c675STom Herbert 31943a0c675STom Herbert eaten += (cand_len - extra); 32043a0c675STom Herbert 32143a0c675STom Herbert /* Hurray, we have a new message! */ 322*bbb03029STom Herbert del_timer(&strp->msg_timer); 323*bbb03029STom Herbert strp->skb_head = NULL; 324*bbb03029STom Herbert STRP_STATS_INCR(strp->stats.msgs); 32543a0c675STom Herbert 32643a0c675STom Herbert /* Give skb to upper layer */ 32743a0c675STom Herbert strp->cb.rcv_msg(strp, head); 32843a0c675STom Herbert 329*bbb03029STom Herbert if (unlikely(strp->paused)) { 33043a0c675STom Herbert /* Upper layer paused strp */ 33143a0c675STom Herbert break; 33243a0c675STom Herbert } 33343a0c675STom Herbert } 33443a0c675STom Herbert 33543a0c675STom Herbert if (cloned_orig) 33643a0c675STom Herbert kfree_skb(orig_skb); 33743a0c675STom Herbert 338*bbb03029STom Herbert STRP_STATS_ADD(strp->stats.bytes, eaten); 33943a0c675STom Herbert 34043a0c675STom Herbert return eaten; 34143a0c675STom Herbert } 34243a0c675STom Herbert 343*bbb03029STom Herbert int strp_process(struct strparser *strp, struct sk_buff *orig_skb, 344*bbb03029STom Herbert unsigned int orig_offset, size_t orig_len, 345*bbb03029STom Herbert size_t max_msg_size, long timeo) 346*bbb03029STom Herbert { 347*bbb03029STom Herbert read_descriptor_t desc; /* Dummy arg to strp_recv */ 348*bbb03029STom Herbert 349*bbb03029STom Herbert desc.arg.data = strp; 350*bbb03029STom Herbert 351*bbb03029STom Herbert return __strp_recv(&desc, orig_skb, orig_offset, orig_len, 352*bbb03029STom Herbert max_msg_size, timeo); 353*bbb03029STom Herbert } 354*bbb03029STom Herbert EXPORT_SYMBOL_GPL(strp_process); 355*bbb03029STom Herbert 356*bbb03029STom Herbert static int strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb, 357*bbb03029STom Herbert unsigned int orig_offset, size_t orig_len) 358*bbb03029STom Herbert { 359*bbb03029STom Herbert struct strparser *strp = (struct strparser *)desc->arg.data; 360*bbb03029STom Herbert 361*bbb03029STom Herbert return __strp_recv(desc, orig_skb, orig_offset, orig_len, 362*bbb03029STom Herbert strp->sk->sk_rcvbuf, strp->sk->sk_rcvtimeo); 363*bbb03029STom Herbert } 364*bbb03029STom Herbert 36543a0c675STom Herbert static int default_read_sock_done(struct strparser *strp, int err) 36643a0c675STom Herbert { 36743a0c675STom Herbert return err; 36843a0c675STom Herbert } 36943a0c675STom Herbert 37043a0c675STom Herbert /* Called with lock held on lower socket */ 37196a59083STom Herbert static int strp_read_sock(struct strparser *strp) 37243a0c675STom Herbert { 37396a59083STom Herbert struct socket *sock = strp->sk->sk_socket; 37443a0c675STom Herbert read_descriptor_t desc; 37543a0c675STom Herbert 37643a0c675STom Herbert desc.arg.data = strp; 37743a0c675STom Herbert desc.error = 0; 37843a0c675STom Herbert desc.count = 1; /* give more than one skb per call */ 37943a0c675STom Herbert 38096a59083STom Herbert /* sk should be locked here, so okay to do read_sock */ 38196a59083STom Herbert sock->ops->read_sock(strp->sk, &desc, strp_recv); 38243a0c675STom Herbert 38343a0c675STom Herbert desc.error = strp->cb.read_sock_done(strp, desc.error); 38443a0c675STom Herbert 38543a0c675STom Herbert return desc.error; 38643a0c675STom Herbert } 38743a0c675STom Herbert 38843a0c675STom Herbert /* Lower sock lock held */ 38996a59083STom Herbert void strp_data_ready(struct strparser *strp) 39043a0c675STom Herbert { 391*bbb03029STom Herbert if (unlikely(strp->stopped)) 39243a0c675STom Herbert return; 39343a0c675STom Herbert 394*bbb03029STom Herbert /* This check is needed to synchronize with do_strp_work. 395*bbb03029STom Herbert * do_strp_work acquires a process lock (lock_sock) whereas 39643a0c675STom Herbert * the lock held here is bh_lock_sock. The two locks can be 39743a0c675STom Herbert * held by different threads at the same time, but bh_lock_sock 39843a0c675STom Herbert * allows a thread in BH context to safely check if the process 39943a0c675STom Herbert * lock is held. In this case, if the lock is held, queue work. 40043a0c675STom Herbert */ 40196a59083STom Herbert if (sock_owned_by_user(strp->sk)) { 402*bbb03029STom Herbert queue_work(strp_wq, &strp->work); 40343a0c675STom Herbert return; 40443a0c675STom Herbert } 40543a0c675STom Herbert 406*bbb03029STom Herbert if (strp->paused) 40743a0c675STom Herbert return; 40843a0c675STom Herbert 409*bbb03029STom Herbert if (strp->need_bytes) { 410*bbb03029STom Herbert if (strp_peek_len(strp) >= strp->need_bytes) 411*bbb03029STom Herbert strp->need_bytes = 0; 41243a0c675STom Herbert else 41343a0c675STom Herbert return; 41443a0c675STom Herbert } 41543a0c675STom Herbert 41696a59083STom Herbert if (strp_read_sock(strp) == -ENOMEM) 417*bbb03029STom Herbert queue_work(strp_wq, &strp->work); 41843a0c675STom Herbert } 41996a59083STom Herbert EXPORT_SYMBOL_GPL(strp_data_ready); 42043a0c675STom Herbert 421*bbb03029STom Herbert static void do_strp_work(struct strparser *strp) 42243a0c675STom Herbert { 42343a0c675STom Herbert read_descriptor_t rd_desc; 42443a0c675STom Herbert 42596a59083STom Herbert /* We need the read lock to synchronize with strp_data_ready. We 42696a59083STom Herbert * need the socket lock for calling strp_read_sock. 42743a0c675STom Herbert */ 428*bbb03029STom Herbert strp->cb.lock(strp); 42943a0c675STom Herbert 430*bbb03029STom Herbert if (unlikely(strp->stopped)) 43143a0c675STom Herbert goto out; 43243a0c675STom Herbert 433*bbb03029STom Herbert if (strp->paused) 43443a0c675STom Herbert goto out; 43543a0c675STom Herbert 43643a0c675STom Herbert rd_desc.arg.data = strp; 43743a0c675STom Herbert 43896a59083STom Herbert if (strp_read_sock(strp) == -ENOMEM) 439*bbb03029STom Herbert queue_work(strp_wq, &strp->work); 44043a0c675STom Herbert 44143a0c675STom Herbert out: 442*bbb03029STom Herbert strp->cb.unlock(strp); 44343a0c675STom Herbert } 44443a0c675STom Herbert 445*bbb03029STom Herbert static void strp_work(struct work_struct *w) 44643a0c675STom Herbert { 447*bbb03029STom Herbert do_strp_work(container_of(w, struct strparser, work)); 44843a0c675STom Herbert } 44943a0c675STom Herbert 450*bbb03029STom Herbert static void strp_msg_timeout(unsigned long arg) 45143a0c675STom Herbert { 45243a0c675STom Herbert struct strparser *strp = (struct strparser *)arg; 45343a0c675STom Herbert 45443a0c675STom Herbert /* Message assembly timed out */ 455*bbb03029STom Herbert STRP_STATS_INCR(strp->stats.msg_timeouts); 456*bbb03029STom Herbert strp->cb.lock(strp); 45743a0c675STom Herbert strp->cb.abort_parser(strp, ETIMEDOUT); 458*bbb03029STom Herbert strp->cb.unlock(strp); 459*bbb03029STom Herbert } 460*bbb03029STom Herbert 461*bbb03029STom Herbert static void strp_sock_lock(struct strparser *strp) 462*bbb03029STom Herbert { 463*bbb03029STom Herbert lock_sock(strp->sk); 464*bbb03029STom Herbert } 465*bbb03029STom Herbert 466*bbb03029STom Herbert static void strp_sock_unlock(struct strparser *strp) 467*bbb03029STom Herbert { 46843a0c675STom Herbert release_sock(strp->sk); 46943a0c675STom Herbert } 47043a0c675STom Herbert 471*bbb03029STom Herbert int strp_init(struct strparser *strp, struct sock *sk, 47243a0c675STom Herbert struct strp_callbacks *cb) 47343a0c675STom Herbert { 47496a59083STom Herbert 47543a0c675STom Herbert if (!cb || !cb->rcv_msg || !cb->parse_msg) 47643a0c675STom Herbert return -EINVAL; 47743a0c675STom Herbert 478*bbb03029STom Herbert /* The sk (sock) arg determines the mode of the stream parser. 479*bbb03029STom Herbert * 480*bbb03029STom Herbert * If the sock is set then the strparser is in receive callback mode. 481*bbb03029STom Herbert * The upper layer calls strp_data_ready to kick receive processing 482*bbb03029STom Herbert * and strparser calls the read_sock function on the socket to 483*bbb03029STom Herbert * get packets. 484*bbb03029STom Herbert * 485*bbb03029STom Herbert * If the sock is not set then the strparser is in general mode. 486*bbb03029STom Herbert * The upper layer calls strp_process for each skb to be parsed. 487*bbb03029STom Herbert */ 488*bbb03029STom Herbert 489*bbb03029STom Herbert if (sk) { 490*bbb03029STom Herbert struct socket *sock = sk->sk_socket; 491*bbb03029STom Herbert 49296a59083STom Herbert if (!sock->ops->read_sock || !sock->ops->peek_len) 49396a59083STom Herbert return -EAFNOSUPPORT; 494*bbb03029STom Herbert } else { 495*bbb03029STom Herbert if (!cb->lock || !cb->unlock) 496*bbb03029STom Herbert return -EINVAL; 497*bbb03029STom Herbert } 49896a59083STom Herbert 49943a0c675STom Herbert memset(strp, 0, sizeof(*strp)); 50043a0c675STom Herbert 501*bbb03029STom Herbert strp->sk = sk; 50243a0c675STom Herbert 503*bbb03029STom Herbert strp->cb.lock = cb->lock ? : strp_sock_lock; 504*bbb03029STom Herbert strp->cb.unlock = cb->unlock ? : strp_sock_unlock; 50543a0c675STom Herbert strp->cb.rcv_msg = cb->rcv_msg; 50643a0c675STom Herbert strp->cb.parse_msg = cb->parse_msg; 50743a0c675STom Herbert strp->cb.read_sock_done = cb->read_sock_done ? : default_read_sock_done; 508*bbb03029STom Herbert strp->cb.abort_parser = cb->abort_parser ? : strp_abort_strp; 509*bbb03029STom Herbert 510*bbb03029STom Herbert setup_timer(&strp->msg_timer, strp_msg_timeout, 511*bbb03029STom Herbert (unsigned long)strp); 512*bbb03029STom Herbert 513*bbb03029STom Herbert INIT_WORK(&strp->work, strp_work); 51443a0c675STom Herbert 51543a0c675STom Herbert return 0; 51643a0c675STom Herbert } 51743a0c675STom Herbert EXPORT_SYMBOL_GPL(strp_init); 51843a0c675STom Herbert 519cff6a334STom Herbert void strp_unpause(struct strparser *strp) 520cff6a334STom Herbert { 521*bbb03029STom Herbert strp->paused = 0; 522cff6a334STom Herbert 523*bbb03029STom Herbert /* Sync setting paused with RX work */ 524cff6a334STom Herbert smp_mb(); 525cff6a334STom Herbert 526*bbb03029STom Herbert queue_work(strp_wq, &strp->work); 527cff6a334STom Herbert } 528cff6a334STom Herbert EXPORT_SYMBOL_GPL(strp_unpause); 529cff6a334STom Herbert 53096a59083STom Herbert /* strp must already be stopped so that strp_recv will no longer be called. 53143a0c675STom Herbert * Note that strp_done is not called with the lower socket held. 53243a0c675STom Herbert */ 53343a0c675STom Herbert void strp_done(struct strparser *strp) 53443a0c675STom Herbert { 535*bbb03029STom Herbert WARN_ON(!strp->stopped); 53643a0c675STom Herbert 537*bbb03029STom Herbert del_timer_sync(&strp->msg_timer); 538*bbb03029STom Herbert cancel_work_sync(&strp->work); 53943a0c675STom Herbert 540*bbb03029STom Herbert if (strp->skb_head) { 541*bbb03029STom Herbert kfree_skb(strp->skb_head); 542*bbb03029STom Herbert strp->skb_head = NULL; 54343a0c675STom Herbert } 54443a0c675STom Herbert } 54543a0c675STom Herbert EXPORT_SYMBOL_GPL(strp_done); 54643a0c675STom Herbert 54743a0c675STom Herbert void strp_stop(struct strparser *strp) 54843a0c675STom Herbert { 549*bbb03029STom Herbert strp->stopped = 1; 55043a0c675STom Herbert } 55143a0c675STom Herbert EXPORT_SYMBOL_GPL(strp_stop); 55243a0c675STom Herbert 55343a0c675STom Herbert void strp_check_rcv(struct strparser *strp) 55443a0c675STom Herbert { 555*bbb03029STom Herbert queue_work(strp_wq, &strp->work); 55643a0c675STom Herbert } 55743a0c675STom Herbert EXPORT_SYMBOL_GPL(strp_check_rcv); 55843a0c675STom Herbert 55943a0c675STom Herbert static int __init strp_mod_init(void) 56043a0c675STom Herbert { 56143a0c675STom Herbert strp_wq = create_singlethread_workqueue("kstrp"); 56243a0c675STom Herbert 56343a0c675STom Herbert return 0; 56443a0c675STom Herbert } 56543a0c675STom Herbert 56643a0c675STom Herbert static void __exit strp_mod_exit(void) 56743a0c675STom Herbert { 568f78ef7cdSWANG Cong destroy_workqueue(strp_wq); 56943a0c675STom Herbert } 57043a0c675STom Herbert module_init(strp_mod_init); 57143a0c675STom Herbert module_exit(strp_mod_exit); 57243a0c675STom Herbert MODULE_LICENSE("GPL"); 573