|
43 | 43 | #include <net/udp.h>
|
44 | 44 | #include <net/tcp.h>
|
45 | 45 | #include <net/tcp_states.h>
|
| 46 | +#include <net/tls.h> |
46 | 47 | #include <linux/uaccess.h>
|
47 | 48 | #include <linux/highmem.h>
|
48 | 49 | #include <asm/ioctls.h>
|
@@ -216,6 +217,49 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
|
216 | 217 | return len;
|
217 | 218 | }
|
218 | 219 |
|
| 220 | +static int |
| 221 | +svc_tcp_sock_process_cmsg(struct svc_sock *svsk, struct msghdr *msg, |
| 222 | + struct cmsghdr *cmsg, int ret) |
| 223 | +{ |
| 224 | + if (cmsg->cmsg_level == SOL_TLS && |
| 225 | + cmsg->cmsg_type == TLS_GET_RECORD_TYPE) { |
| 226 | + u8 content_type = *((u8 *)CMSG_DATA(cmsg)); |
| 227 | + |
| 228 | + switch (content_type) { |
| 229 | + case TLS_RECORD_TYPE_DATA: |
| 230 | + /* TLS sets EOR at the end of each application data |
| 231 | + * record, even though there might be more frames |
| 232 | + * waiting to be decrypted. |
| 233 | + */ |
| 234 | + msg->msg_flags &= ~MSG_EOR; |
| 235 | + break; |
| 236 | + case TLS_RECORD_TYPE_ALERT: |
| 237 | + ret = -ENOTCONN; |
| 238 | + break; |
| 239 | + default: |
| 240 | + ret = -EAGAIN; |
| 241 | + } |
| 242 | + } |
| 243 | + return ret; |
| 244 | +} |
| 245 | + |
| 246 | +static int |
| 247 | +svc_tcp_sock_recv_cmsg(struct svc_sock *svsk, struct msghdr *msg) |
| 248 | +{ |
| 249 | + union { |
| 250 | + struct cmsghdr cmsg; |
| 251 | + u8 buf[CMSG_SPACE(sizeof(u8))]; |
| 252 | + } u; |
| 253 | + int ret; |
| 254 | + |
| 255 | + msg->msg_control = &u; |
| 256 | + msg->msg_controllen = sizeof(u); |
| 257 | + ret = sock_recvmsg(svsk->sk_sock, msg, MSG_DONTWAIT); |
| 258 | + if (unlikely(msg->msg_controllen != sizeof(u))) |
| 259 | + ret = svc_tcp_sock_process_cmsg(svsk, msg, &u.cmsg, ret); |
| 260 | + return ret; |
| 261 | +} |
| 262 | + |
219 | 263 | #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
|
220 | 264 | static void svc_flush_bvec(const struct bio_vec *bvec, size_t size, size_t seek)
|
221 | 265 | {
|
@@ -263,7 +307,7 @@ static ssize_t svc_tcp_read_msg(struct svc_rqst *rqstp, size_t buflen,
|
263 | 307 | iov_iter_advance(&msg.msg_iter, seek);
|
264 | 308 | buflen -= seek;
|
265 | 309 | }
|
266 |
| - len = sock_recvmsg(svsk->sk_sock, &msg, MSG_DONTWAIT); |
| 310 | + len = svc_tcp_sock_recv_cmsg(svsk, &msg); |
267 | 311 | if (len > 0)
|
268 | 312 | svc_flush_bvec(bvec, len, seek);
|
269 | 313 |
|
@@ -877,7 +921,7 @@ static ssize_t svc_tcp_read_marker(struct svc_sock *svsk,
|
877 | 921 | iov.iov_base = ((char *)&svsk->sk_marker) + svsk->sk_tcplen;
|
878 | 922 | iov.iov_len = want;
|
879 | 923 | iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, want);
|
880 |
| - len = sock_recvmsg(svsk->sk_sock, &msg, MSG_DONTWAIT); |
| 924 | + len = svc_tcp_sock_recv_cmsg(svsk, &msg); |
881 | 925 | if (len < 0)
|
882 | 926 | return len;
|
883 | 927 | svsk->sk_tcplen += len;
|
|
0 commit comments