#include <net/kcm.h>
#include <net/netns/generic.h>
#include <net/sock.h>
-#include <net/tcp.h>
#include <uapi/linux/kcm.h>
unsigned int kcm_net_id;
}
/* Lower sock lock held */
-static void psock_tcp_data_ready(struct sock *sk)
+static void psock_data_ready(struct sock *sk)
{
struct kcm_psock *psock;
psock = (struct kcm_psock *)sk->sk_user_data;
if (likely(psock))
- strp_tcp_data_ready(&psock->strp);
+ strp_data_ready(&psock->strp);
read_unlock_bh(&sk->sk_callback_lock);
}
return err;
}
-static void psock_tcp_state_change(struct sock *sk)
+static void psock_state_change(struct sock *sk)
{
/* TCP only does a POLLIN for a half close. Do a POLLHUP here
* since application will normally not poll with POLLIN
report_csk_error(sk, EPIPE);
}
-static void psock_tcp_write_space(struct sock *sk)
+static void psock_write_space(struct sock *sk)
{
struct kcm_psock *psock;
struct kcm_mux *mux;
struct list_head *head;
int index = 0;
struct strp_callbacks cb;
-
- if (csock->ops->family != PF_INET &&
- csock->ops->family != PF_INET6)
- return -EINVAL;
+ int err;
csk = csock->sk;
if (!csk)
return -EINVAL;
- /* Only support TCP for now */
- if (csk->sk_protocol != IPPROTO_TCP)
- return -EINVAL;
-
psock = kmem_cache_zalloc(kcm_psockp, GFP_KERNEL);
if (!psock)
return -ENOMEM;
cb.parse_msg = kcm_parse_func_strparser;
cb.read_sock_done = kcm_read_sock_done;
- strp_init(&psock->strp, csk, &cb);
+ err = strp_init(&psock->strp, csk, &cb);
+ if (err) {
+ kmem_cache_free(kcm_psockp, psock);
+ return err;
+ }
sock_hold(csk);
psock->save_write_space = csk->sk_write_space;
psock->save_state_change = csk->sk_state_change;
csk->sk_user_data = psock;
- csk->sk_data_ready = psock_tcp_data_ready;
- csk->sk_write_space = psock_tcp_write_space;
- csk->sk_state_change = psock_tcp_state_change;
+ csk->sk_data_ready = psock_data_ready;
+ csk->sk_write_space = psock_write_space;
+ csk->sk_state_change = psock_state_change;
write_unlock_bh(&csk->sk_callback_lock);
/* Finished initialization, now add the psock to the MUX. */
#include <net/strparser.h>
#include <net/netns/generic.h>
#include <net/sock.h>
-#include <net/tcp.h>
static struct workqueue_struct *strp_wq;
strp->cb.abort_parser(strp, err);
}
+static inline int strp_peek_len(struct strparser *strp)
+{
+ struct socket *sock = strp->sk->sk_socket;
+
+ return sock->ops->peek_len(sock);
+}
+
/* Lower socket lock held */
-static int strp_tcp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
- unsigned int orig_offset, size_t orig_len)
+static int strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
+ unsigned int orig_offset, size_t orig_len)
{
struct strparser *strp = (struct strparser *)desc->arg.data;
struct _strp_rx_msg *rxm;
if (extra < 0) {
/* Message not complete yet. */
if (rxm->strp.full_len - rxm->accum_len >
- tcp_inq(strp->sk)) {
+ strp_peek_len(strp)) {
/* Don't have the whole messages in the socket
* buffer. Set strp->rx_need_bytes to wait for
* the rest of the message. Also, set "early
* eaten" since we've already buffered the skb
- * but don't consume yet per tcp_read_sock.
+ * but don't consume yet per strp_read_sock.
*/
if (!rxm->accum_len) {
}
/* Called with lock held on lower socket */
-static int strp_tcp_read_sock(struct strparser *strp)
+static int strp_read_sock(struct strparser *strp)
{
+ struct socket *sock = strp->sk->sk_socket;
read_descriptor_t desc;
desc.arg.data = strp;
desc.error = 0;
desc.count = 1; /* give more than one skb per call */
- /* sk should be locked here, so okay to do tcp_read_sock */
- tcp_read_sock(strp->sk, &desc, strp_tcp_recv);
+ /* sk should be locked here, so okay to do read_sock */
+ sock->ops->read_sock(strp->sk, &desc, strp_recv);
desc.error = strp->cb.read_sock_done(strp, desc.error);
}
/* Lower sock lock held */
-void strp_tcp_data_ready(struct strparser *strp)
+void strp_data_ready(struct strparser *strp)
{
- struct sock *csk = strp->sk;
-
if (unlikely(strp->rx_stopped))
return;
* allows a thread in BH context to safely check if the process
* lock is held. In this case, if the lock is held, queue work.
*/
- if (sock_owned_by_user(csk)) {
+ if (sock_owned_by_user(strp->sk)) {
queue_work(strp_wq, &strp->rx_work);
return;
}
return;
if (strp->rx_need_bytes) {
- if (tcp_inq(csk) >= strp->rx_need_bytes)
+ if (strp_peek_len(strp) >= strp->rx_need_bytes)
strp->rx_need_bytes = 0;
else
return;
}
- if (strp_tcp_read_sock(strp) == -ENOMEM)
+ if (strp_read_sock(strp) == -ENOMEM)
queue_work(strp_wq, &strp->rx_work);
}
-EXPORT_SYMBOL_GPL(strp_tcp_data_ready);
+EXPORT_SYMBOL_GPL(strp_data_ready);
static void do_strp_rx_work(struct strparser *strp)
{
read_descriptor_t rd_desc;
struct sock *csk = strp->sk;
- /* We need the read lock to synchronize with strp_tcp_data_ready. We
- * need the socket lock for calling tcp_read_sock.
+ /* We need the read lock to synchronize with strp_data_ready. We
+ * need the socket lock for calling strp_read_sock.
*/
lock_sock(csk);
rd_desc.arg.data = strp;
- if (strp_tcp_read_sock(strp) == -ENOMEM)
+ if (strp_read_sock(strp) == -ENOMEM)
queue_work(strp_wq, &strp->rx_work);
out:
int strp_init(struct strparser *strp, struct sock *csk,
struct strp_callbacks *cb)
{
+ struct socket *sock = csk->sk_socket;
+
if (!cb || !cb->rcv_msg || !cb->parse_msg)
return -EINVAL;
+ if (!sock->ops->read_sock || !sock->ops->peek_len)
+ return -EAFNOSUPPORT;
+
memset(strp, 0, sizeof(*strp));
strp->sk = csk;
}
EXPORT_SYMBOL_GPL(strp_unpause);
-/* strp must already be stopped so that strp_tcp_recv will no longer be called.
+/* strp must already be stopped so that strp_recv will no longer be called.
* Note that strp_done is not called with the lower socket held.
*/
void strp_done(struct strparser *strp)