diff options
| -rw-r--r-- | include/linux/sunrpc/xdr.h | 2 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_crypto.c | 73 | ||||
| -rw-r--r-- | net/sunrpc/xdr.c | 68 |
3 files changed, 74 insertions, 69 deletions
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 441b91dbafe5..4d17846cd78a 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include <linux/uio.h> | 12 | #include <linux/uio.h> |
| 13 | #include <asm/byteorder.h> | 13 | #include <asm/byteorder.h> |
| 14 | #include <linux/scatterlist.h> | ||
| 14 | 15 | ||
| 15 | /* | 16 | /* |
| 16 | * Buffer adjustment | 17 | * Buffer adjustment |
| @@ -196,6 +197,7 @@ extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 | |||
| 196 | extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes); | 197 | extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes); |
| 197 | extern void xdr_read_pages(struct xdr_stream *xdr, unsigned int len); | 198 | extern void xdr_read_pages(struct xdr_stream *xdr, unsigned int len); |
| 198 | extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len); | 199 | extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len); |
| 200 | extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data); | ||
| 199 | 201 | ||
| 200 | #endif /* __KERNEL__ */ | 202 | #endif /* __KERNEL__ */ |
| 201 | 203 | ||
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 4c53896f1b08..10d05ea37213 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c | |||
| @@ -43,6 +43,7 @@ | |||
| 43 | #include <linux/highmem.h> | 43 | #include <linux/highmem.h> |
| 44 | #include <linux/pagemap.h> | 44 | #include <linux/pagemap.h> |
| 45 | #include <linux/sunrpc/gss_krb5.h> | 45 | #include <linux/sunrpc/gss_krb5.h> |
| 46 | #include <linux/sunrpc/xdr.h> | ||
| 46 | 47 | ||
| 47 | #ifdef RPC_DEBUG | 48 | #ifdef RPC_DEBUG |
| 48 | # define RPCDBG_FACILITY RPCDBG_AUTH | 49 | # define RPCDBG_FACILITY RPCDBG_AUTH |
| @@ -120,72 +121,6 @@ out: | |||
| 120 | EXPORT_SYMBOL(krb5_decrypt); | 121 | EXPORT_SYMBOL(krb5_decrypt); |
| 121 | 122 | ||
| 122 | static int | 123 | static int |
| 123 | process_xdr_buf(struct xdr_buf *buf, int offset, int len, | ||
| 124 | int (*actor)(struct scatterlist *, void *), void *data) | ||
| 125 | { | ||
| 126 | int i, page_len, thislen, page_offset, ret = 0; | ||
| 127 | struct scatterlist sg[1]; | ||
| 128 | |||
| 129 | if (offset >= buf->head[0].iov_len) { | ||
| 130 | offset -= buf->head[0].iov_len; | ||
| 131 | } else { | ||
| 132 | thislen = buf->head[0].iov_len - offset; | ||
| 133 | if (thislen > len) | ||
| 134 | thislen = len; | ||
| 135 | sg_set_buf(sg, buf->head[0].iov_base + offset, thislen); | ||
| 136 | ret = actor(sg, data); | ||
| 137 | if (ret) | ||
| 138 | goto out; | ||
| 139 | offset = 0; | ||
| 140 | len -= thislen; | ||
| 141 | } | ||
| 142 | if (len == 0) | ||
| 143 | goto out; | ||
| 144 | |||
| 145 | if (offset >= buf->page_len) { | ||
| 146 | offset -= buf->page_len; | ||
| 147 | } else { | ||
| 148 | page_len = buf->page_len - offset; | ||
| 149 | if (page_len > len) | ||
| 150 | page_len = len; | ||
| 151 | len -= page_len; | ||
| 152 | page_offset = (offset + buf->page_base) & (PAGE_CACHE_SIZE - 1); | ||
| 153 | i = (offset + buf->page_base) >> PAGE_CACHE_SHIFT; | ||
| 154 | thislen = PAGE_CACHE_SIZE - page_offset; | ||
| 155 | do { | ||
| 156 | if (thislen > page_len) | ||
| 157 | thislen = page_len; | ||
| 158 | sg->page = buf->pages[i]; | ||
| 159 | sg->offset = page_offset; | ||
| 160 | sg->length = thislen; | ||
| 161 | ret = actor(sg, data); | ||
| 162 | if (ret) | ||
| 163 | goto out; | ||
| 164 | page_len -= thislen; | ||
| 165 | i++; | ||
| 166 | page_offset = 0; | ||
| 167 | thislen = PAGE_CACHE_SIZE; | ||
| 168 | } while (page_len != 0); | ||
| 169 | offset = 0; | ||
| 170 | } | ||
| 171 | if (len == 0) | ||
| 172 | goto out; | ||
| 173 | |||
| 174 | if (offset < buf->tail[0].iov_len) { | ||
| 175 | thislen = buf->tail[0].iov_len - offset; | ||
| 176 | if (thislen > len) | ||
| 177 | thislen = len; | ||
| 178 | sg_set_buf(sg, buf->tail[0].iov_base + offset, thislen); | ||
| 179 | ret = actor(sg, data); | ||
| 180 | len -= thislen; | ||
| 181 | } | ||
| 182 | if (len != 0) | ||
| 183 | ret = -EINVAL; | ||
| 184 | out: | ||
| 185 | return ret; | ||
| 186 | } | ||
| 187 | |||
| 188 | static int | ||
| 189 | checksummer(struct scatterlist *sg, void *data) | 124 | checksummer(struct scatterlist *sg, void *data) |
| 190 | { | 125 | { |
| 191 | struct hash_desc *desc = data; | 126 | struct hash_desc *desc = data; |
| @@ -225,7 +160,7 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body, | |||
| 225 | err = crypto_hash_update(&desc, sg, hdrlen); | 160 | err = crypto_hash_update(&desc, sg, hdrlen); |
| 226 | if (err) | 161 | if (err) |
| 227 | goto out; | 162 | goto out; |
| 228 | err = process_xdr_buf(body, body_offset, body->len - body_offset, | 163 | err = xdr_process_buf(body, body_offset, body->len - body_offset, |
| 229 | checksummer, &desc); | 164 | checksummer, &desc); |
| 230 | if (err) | 165 | if (err) |
| 231 | goto out; | 166 | goto out; |
| @@ -323,7 +258,7 @@ gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf, | |||
| 323 | desc.fragno = 0; | 258 | desc.fragno = 0; |
| 324 | desc.fraglen = 0; | 259 | desc.fraglen = 0; |
| 325 | 260 | ||
| 326 | ret = process_xdr_buf(buf, offset, buf->len - offset, encryptor, &desc); | 261 | ret = xdr_process_buf(buf, offset, buf->len - offset, encryptor, &desc); |
| 327 | return ret; | 262 | return ret; |
| 328 | } | 263 | } |
| 329 | 264 | ||
| @@ -389,7 +324,7 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf, | |||
| 389 | desc.desc.flags = 0; | 324 | desc.desc.flags = 0; |
| 390 | desc.fragno = 0; | 325 | desc.fragno = 0; |
| 391 | desc.fraglen = 0; | 326 | desc.fraglen = 0; |
| 392 | return process_xdr_buf(buf, offset, buf->len - offset, decryptor, &desc); | 327 | return xdr_process_buf(buf, offset, buf->len - offset, decryptor, &desc); |
| 393 | } | 328 | } |
| 394 | 329 | ||
| 395 | EXPORT_SYMBOL(gss_decrypt_xdr_buf); | 330 | EXPORT_SYMBOL(gss_decrypt_xdr_buf); |
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 5a6485946f3c..a0af250ca319 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
| @@ -1021,3 +1021,71 @@ xdr_encode_array2(struct xdr_buf *buf, unsigned int base, | |||
| 1021 | 1021 | ||
| 1022 | return xdr_xcode_array2(buf, base, desc, 1); | 1022 | return xdr_xcode_array2(buf, base, desc, 1); |
| 1023 | } | 1023 | } |
| 1024 | |||
| 1025 | int | ||
| 1026 | xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, | ||
| 1027 | int (*actor)(struct scatterlist *, void *), void *data) | ||
| 1028 | { | ||
| 1029 | int i, ret = 0; | ||
| 1030 | unsigned page_len, thislen, page_offset; | ||
| 1031 | struct scatterlist sg[1]; | ||
| 1032 | |||
| 1033 | if (offset >= buf->head[0].iov_len) { | ||
| 1034 | offset -= buf->head[0].iov_len; | ||
| 1035 | } else { | ||
| 1036 | thislen = buf->head[0].iov_len - offset; | ||
| 1037 | if (thislen > len) | ||
| 1038 | thislen = len; | ||
| 1039 | sg_set_buf(sg, buf->head[0].iov_base + offset, thislen); | ||
| 1040 | ret = actor(sg, data); | ||
| 1041 | if (ret) | ||
| 1042 | goto out; | ||
| 1043 | offset = 0; | ||
| 1044 | len -= thislen; | ||
| 1045 | } | ||
| 1046 | if (len == 0) | ||
| 1047 | goto out; | ||
| 1048 | |||
| 1049 | if (offset >= buf->page_len) { | ||
| 1050 | offset -= buf->page_len; | ||
| 1051 | } else { | ||
| 1052 | page_len = buf->page_len - offset; | ||
| 1053 | if (page_len > len) | ||
| 1054 | page_len = len; | ||
| 1055 | len -= page_len; | ||
| 1056 | page_offset = (offset + buf->page_base) & (PAGE_CACHE_SIZE - 1); | ||
| 1057 | i = (offset + buf->page_base) >> PAGE_CACHE_SHIFT; | ||
| 1058 | thislen = PAGE_CACHE_SIZE - page_offset; | ||
| 1059 | do { | ||
| 1060 | if (thislen > page_len) | ||
| 1061 | thislen = page_len; | ||
| 1062 | sg->page = buf->pages[i]; | ||
| 1063 | sg->offset = page_offset; | ||
| 1064 | sg->length = thislen; | ||
| 1065 | ret = actor(sg, data); | ||
| 1066 | if (ret) | ||
| 1067 | goto out; | ||
| 1068 | page_len -= thislen; | ||
| 1069 | i++; | ||
| 1070 | page_offset = 0; | ||
| 1071 | thislen = PAGE_CACHE_SIZE; | ||
| 1072 | } while (page_len != 0); | ||
| 1073 | offset = 0; | ||
| 1074 | } | ||
| 1075 | if (len == 0) | ||
| 1076 | goto out; | ||
| 1077 | if (offset < buf->tail[0].iov_len) { | ||
| 1078 | thislen = buf->tail[0].iov_len - offset; | ||
| 1079 | if (thislen > len) | ||
| 1080 | thislen = len; | ||
| 1081 | sg_set_buf(sg, buf->tail[0].iov_base + offset, thislen); | ||
| 1082 | ret = actor(sg, data); | ||
| 1083 | len -= thislen; | ||
| 1084 | } | ||
| 1085 | if (len != 0) | ||
| 1086 | ret = -EINVAL; | ||
| 1087 | out: | ||
| 1088 | return ret; | ||
| 1089 | } | ||
| 1090 | EXPORT_SYMBOL(xdr_process_buf); | ||
| 1091 | |||
