35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/endian.h> 38#include <sys/errno.h> 39#include <sys/mbuf.h> 40#include <sys/module.h> 41#include <sys/uio.h> 42 43#include <sys/mchain.h> 44 45MODULE_VERSION(libmchain, 1); 46 47#define MBERROR(format, ...) printf("%s(%d): "format, __func__ , \ 48 __LINE__ , ## __VA_ARGS__) 49 50#define MBPANIC(format, ...) printf("%s(%d): "format, __func__ , \ 51 __LINE__ , ## __VA_ARGS__) 52 53/* 54 * Various helper functions 55 */ 56int 57mb_init(struct mbchain *mbp) 58{ 59 struct mbuf *m; 60 61 m = m_gethdr(M_TRYWAIT, MT_DATA); 62 if (m == NULL) 63 return ENOBUFS; 64 m->m_len = 0; 65 mb_initm(mbp, m); 66 return 0; 67} 68 69void 70mb_initm(struct mbchain *mbp, struct mbuf *m) 71{ 72 bzero(mbp, sizeof(*mbp)); 73 mbp->mb_top = mbp->mb_cur = m; 74 mbp->mb_mleft = M_TRAILINGSPACE(m); 75} 76 77void 78mb_done(struct mbchain *mbp) 79{ 80 if (mbp->mb_top) { 81 m_freem(mbp->mb_top); 82 mbp->mb_top = NULL; 83 } 84} 85 86struct mbuf * 87mb_detach(struct mbchain *mbp) 88{ 89 struct mbuf *m; 90 91 m = mbp->mb_top; 92 mbp->mb_top = NULL; 93 return m; 94} 95 96int 97mb_fixhdr(struct mbchain *mbp) 98{ 99 return mbp->mb_top->m_pkthdr.len = m_fixhdr(mbp->mb_top); 100} 101 102/* 103 * Check if object of size 'size' fit to the current position and 104 * allocate new mbuf if not. Advance pointers and increase length of mbuf(s). 105 * Return pointer to the object placeholder or NULL if any error occured. 106 * Note: size should be <= MLEN 107 */ 108caddr_t 109mb_reserve(struct mbchain *mbp, int size) 110{ 111 struct mbuf *m, *mn; 112 caddr_t bpos; 113 114 if (size > MLEN) 115 panic("mb_reserve: size = %d\n", size); 116 m = mbp->mb_cur; 117 if (mbp->mb_mleft < size) { 118 mn = m_get(M_TRYWAIT, MT_DATA); 119 if (mn == NULL) 120 return NULL; 121 mbp->mb_cur = m->m_next = mn; 122 m = mn; 123 m->m_len = 0; 124 mbp->mb_mleft = M_TRAILINGSPACE(m); 125 } 126 mbp->mb_mleft -= size; 127 mbp->mb_count += size; 128 bpos = mtod(m, caddr_t) + m->m_len; 129 m->m_len += size; 130 return bpos; 131} 132 133int 134mb_put_uint8(struct mbchain *mbp, u_int8_t x) 135{ 136 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 137} 138 139int 140mb_put_uint16be(struct mbchain *mbp, u_int16_t x) 141{ 142 x = htobe16(x); 143 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 144} 145 146int 147mb_put_uint16le(struct mbchain *mbp, u_int16_t x) 148{ 149 x = htole16(x); 150 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 151} 152 153int 154mb_put_uint32be(struct mbchain *mbp, u_int32_t x) 155{ 156 x = htobe32(x); 157 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 158} 159 160int 161mb_put_uint32le(struct mbchain *mbp, u_int32_t x) 162{ 163 x = htole32(x); 164 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 165} 166 167int 168mb_put_int64be(struct mbchain *mbp, int64_t x) 169{ 170 x = htobe64(x); 171 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 172} 173 174int 175mb_put_int64le(struct mbchain *mbp, int64_t x) 176{ 177 x = htole64(x); 178 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 179} 180 181int 182mb_put_mem(struct mbchain *mbp, c_caddr_t source, int size, int type) 183{ 184 struct mbuf *m; 185 caddr_t dst; 186 c_caddr_t src; 187 int cplen, error, mleft, count; 188 189 m = mbp->mb_cur; 190 mleft = mbp->mb_mleft; 191 192 while (size > 0) { 193 if (mleft == 0) { 194 if (m->m_next == NULL) { 195 m = m_getm(m, size, M_TRYWAIT, MT_DATA); 196 if (m == NULL) 197 return ENOBUFS; 198 } else 199 m = m->m_next; 200 mleft = M_TRAILINGSPACE(m); 201 continue; 202 } 203 cplen = mleft > size ? size : mleft; 204 dst = mtod(m, caddr_t) + m->m_len; 205 switch (type) { 206 case MB_MCUSTOM: 207 error = mbp->mb_copy(mbp, source, dst, cplen); 208 if (error) 209 return error; 210 break; 211 case MB_MINLINE: 212 for (src = source, count = cplen; count; count--) 213 *dst++ = *src++; 214 break; 215 case MB_MSYSTEM: 216 bcopy(source, dst, cplen); 217 break; 218 case MB_MUSER: 219 error = copyin(source, dst, cplen); 220 if (error) 221 return error; 222 break; 223 case MB_MZERO: 224 bzero(dst, cplen); 225 break; 226 } 227 size -= cplen; 228 source += cplen; 229 m->m_len += cplen; 230 mleft -= cplen; 231 mbp->mb_count += cplen; 232 } 233 mbp->mb_cur = m; 234 mbp->mb_mleft = mleft; 235 return 0; 236} 237 238int 239mb_put_mbuf(struct mbchain *mbp, struct mbuf *m) 240{ 241 mbp->mb_cur->m_next = m; 242 while (m) { 243 mbp->mb_count += m->m_len; 244 if (m->m_next == NULL) 245 break; 246 m = m->m_next; 247 } 248 mbp->mb_mleft = M_TRAILINGSPACE(m); 249 mbp->mb_cur = m; 250 return 0; 251} 252 253/* 254 * copies a uio scatter/gather list to an mbuf chain. 255 */ 256int 257mb_put_uio(struct mbchain *mbp, struct uio *uiop, int size) 258{ 259 long left; 260 int mtype, error; 261 262 mtype = (uiop->uio_segflg == UIO_SYSSPACE) ? MB_MSYSTEM : MB_MUSER; 263 264 while (size > 0 && uiop->uio_resid) { 265 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 266 return EFBIG; 267 left = uiop->uio_iov->iov_len; 268 if (left == 0) { 269 uiop->uio_iov++; 270 uiop->uio_iovcnt--; 271 continue; 272 } 273 if (left > size) 274 left = size; 275 error = mb_put_mem(mbp, uiop->uio_iov->iov_base, left, mtype); 276 if (error) 277 return error; 278 uiop->uio_offset += left; 279 uiop->uio_resid -= left; 280 uiop->uio_iov->iov_base = 281 (char *)uiop->uio_iov->iov_base + left; 282 uiop->uio_iov->iov_len -= left; 283 size -= left; 284 } 285 return 0; 286} 287 288/* 289 * Routines for fetching data from an mbuf chain 290 */ 291int 292md_init(struct mdchain *mdp) 293{ 294 struct mbuf *m; 295 296 m = m_gethdr(M_TRYWAIT, MT_DATA); 297 if (m == NULL) 298 return ENOBUFS; 299 m->m_len = 0; 300 md_initm(mdp, m); 301 return 0; 302} 303 304void 305md_initm(struct mdchain *mdp, struct mbuf *m) 306{ 307 bzero(mdp, sizeof(*mdp)); 308 mdp->md_top = mdp->md_cur = m; 309 mdp->md_pos = mtod(m, u_char*); 310} 311 312void 313md_done(struct mdchain *mdp) 314{ 315 if (mdp->md_top) { 316 m_freem(mdp->md_top); 317 mdp->md_top = NULL; 318 } 319} 320 321/* 322 * Append a separate mbuf chain. It is caller responsibility to prevent 323 * multiple calls to fetch/record routines. 324 */ 325void 326md_append_record(struct mdchain *mdp, struct mbuf *top) 327{ 328 struct mbuf *m; 329 330 if (mdp->md_top == NULL) { 331 md_initm(mdp, top); 332 return; 333 } 334 m = mdp->md_top; 335 while (m->m_nextpkt) 336 m = m->m_nextpkt; 337 m->m_nextpkt = top; 338 top->m_nextpkt = NULL; 339 return; 340} 341 342/* 343 * Put next record in place of existing 344 */ 345int 346md_next_record(struct mdchain *mdp) 347{ 348 struct mbuf *m; 349 350 if (mdp->md_top == NULL) 351 return ENOENT; 352 m = mdp->md_top->m_nextpkt; 353 md_done(mdp); 354 if (m == NULL) 355 return ENOENT; 356 md_initm(mdp, m); 357 return 0; 358} 359 360int 361md_get_uint8(struct mdchain *mdp, u_int8_t *x) 362{ 363 return md_get_mem(mdp, x, 1, MB_MINLINE); 364} 365 366int 367md_get_uint16(struct mdchain *mdp, u_int16_t *x) 368{ 369 return md_get_mem(mdp, (caddr_t)x, 2, MB_MINLINE); 370} 371 372int 373md_get_uint16le(struct mdchain *mdp, u_int16_t *x) 374{ 375 u_int16_t v; 376 int error = md_get_uint16(mdp, &v); 377 378 if (x != NULL) 379 *x = le16toh(v); 380 return error; 381} 382 383int 384md_get_uint16be(struct mdchain *mdp, u_int16_t *x) { 385 u_int16_t v; 386 int error = md_get_uint16(mdp, &v); 387 388 if (x != NULL) 389 *x = be16toh(v); 390 return error; 391} 392 393int 394md_get_uint32(struct mdchain *mdp, u_int32_t *x) 395{ 396 return md_get_mem(mdp, (caddr_t)x, 4, MB_MINLINE); 397} 398 399int 400md_get_uint32be(struct mdchain *mdp, u_int32_t *x) 401{ 402 u_int32_t v; 403 int error; 404 405 error = md_get_uint32(mdp, &v); 406 if (x != NULL) 407 *x = be32toh(v); 408 return error; 409} 410 411int 412md_get_uint32le(struct mdchain *mdp, u_int32_t *x) 413{ 414 u_int32_t v; 415 int error; 416 417 error = md_get_uint32(mdp, &v); 418 if (x != NULL) 419 *x = le32toh(v); 420 return error; 421} 422 423int 424md_get_int64(struct mdchain *mdp, int64_t *x) 425{ 426 return md_get_mem(mdp, (caddr_t)x, 8, MB_MINLINE); 427} 428 429int 430md_get_int64be(struct mdchain *mdp, int64_t *x) 431{ 432 int64_t v; 433 int error; 434 435 error = md_get_int64(mdp, &v); 436 if (x != NULL) 437 *x = be64toh(v); 438 return error; 439} 440 441int 442md_get_int64le(struct mdchain *mdp, int64_t *x) 443{ 444 int64_t v; 445 int error; 446 447 error = md_get_int64(mdp, &v); 448 if (x != NULL) 449 *x = le64toh(v); 450 return error; 451} 452 453int 454md_get_mem(struct mdchain *mdp, caddr_t target, int size, int type) 455{ 456 struct mbuf *m = mdp->md_cur; 457 int error; 458 u_int count; 459 u_char *s; 460 461 while (size > 0) { 462 if (m == NULL) { 463 MBERROR("incomplete copy\n"); 464 return EBADRPC; 465 } 466 s = mdp->md_pos; 467 count = mtod(m, u_char*) + m->m_len - s; 468 if (count == 0) { 469 mdp->md_cur = m = m->m_next; 470 if (m) 471 s = mdp->md_pos = mtod(m, caddr_t); 472 continue; 473 } 474 if (count > size) 475 count = size; 476 size -= count; 477 mdp->md_pos += count; 478 if (target == NULL) 479 continue; 480 switch (type) { 481 case MB_MUSER: 482 error = copyout(s, target, count); 483 if (error) 484 return error; 485 break; 486 case MB_MSYSTEM: 487 bcopy(s, target, count); 488 break; 489 case MB_MINLINE: 490 while (count--) 491 *target++ = *s++; 492 continue; 493 } 494 target += count; 495 } 496 return 0; 497} 498 499int 500md_get_mbuf(struct mdchain *mdp, int size, struct mbuf **ret) 501{ 502 struct mbuf *m = mdp->md_cur, *rm; 503 504 rm = m_copym(m, mdp->md_pos - mtod(m, u_char*), size, M_TRYWAIT); 505 if (rm == NULL) 506 return EBADRPC; 507 md_get_mem(mdp, NULL, size, MB_MZERO); 508 *ret = rm; 509 return 0; 510} 511 512int 513md_get_uio(struct mdchain *mdp, struct uio *uiop, int size) 514{ 515 char *uiocp; 516 long left; 517 int mtype, error; 518 519 mtype = (uiop->uio_segflg == UIO_SYSSPACE) ? MB_MSYSTEM : MB_MUSER; 520 while (size > 0 && uiop->uio_resid) { 521 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 522 return EFBIG; 523 left = uiop->uio_iov->iov_len; 524 if (left == 0) { 525 uiop->uio_iov++; 526 uiop->uio_iovcnt--; 527 continue; 528 } 529 uiocp = uiop->uio_iov->iov_base; 530 if (left > size) 531 left = size; 532 error = md_get_mem(mdp, uiocp, left, mtype); 533 if (error) 534 return error; 535 uiop->uio_offset += left; 536 uiop->uio_resid -= left; 537 uiop->uio_iov->iov_base = 538 (char *)uiop->uio_iov->iov_base + left; 539 uiop->uio_iov->iov_len -= left; 540 size -= left; 541 } 542 return 0; 543}
| 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/endian.h> 39#include <sys/errno.h> 40#include <sys/mbuf.h> 41#include <sys/module.h> 42#include <sys/uio.h> 43 44#include <sys/mchain.h> 45 46MODULE_VERSION(libmchain, 1); 47 48#define MBERROR(format, ...) printf("%s(%d): "format, __func__ , \ 49 __LINE__ , ## __VA_ARGS__) 50 51#define MBPANIC(format, ...) printf("%s(%d): "format, __func__ , \ 52 __LINE__ , ## __VA_ARGS__) 53 54/* 55 * Various helper functions 56 */ 57int 58mb_init(struct mbchain *mbp) 59{ 60 struct mbuf *m; 61 62 m = m_gethdr(M_TRYWAIT, MT_DATA); 63 if (m == NULL) 64 return ENOBUFS; 65 m->m_len = 0; 66 mb_initm(mbp, m); 67 return 0; 68} 69 70void 71mb_initm(struct mbchain *mbp, struct mbuf *m) 72{ 73 bzero(mbp, sizeof(*mbp)); 74 mbp->mb_top = mbp->mb_cur = m; 75 mbp->mb_mleft = M_TRAILINGSPACE(m); 76} 77 78void 79mb_done(struct mbchain *mbp) 80{ 81 if (mbp->mb_top) { 82 m_freem(mbp->mb_top); 83 mbp->mb_top = NULL; 84 } 85} 86 87struct mbuf * 88mb_detach(struct mbchain *mbp) 89{ 90 struct mbuf *m; 91 92 m = mbp->mb_top; 93 mbp->mb_top = NULL; 94 return m; 95} 96 97int 98mb_fixhdr(struct mbchain *mbp) 99{ 100 return mbp->mb_top->m_pkthdr.len = m_fixhdr(mbp->mb_top); 101} 102 103/* 104 * Check if object of size 'size' fit to the current position and 105 * allocate new mbuf if not. Advance pointers and increase length of mbuf(s). 106 * Return pointer to the object placeholder or NULL if any error occured. 107 * Note: size should be <= MLEN 108 */ 109caddr_t 110mb_reserve(struct mbchain *mbp, int size) 111{ 112 struct mbuf *m, *mn; 113 caddr_t bpos; 114 115 if (size > MLEN) 116 panic("mb_reserve: size = %d\n", size); 117 m = mbp->mb_cur; 118 if (mbp->mb_mleft < size) { 119 mn = m_get(M_TRYWAIT, MT_DATA); 120 if (mn == NULL) 121 return NULL; 122 mbp->mb_cur = m->m_next = mn; 123 m = mn; 124 m->m_len = 0; 125 mbp->mb_mleft = M_TRAILINGSPACE(m); 126 } 127 mbp->mb_mleft -= size; 128 mbp->mb_count += size; 129 bpos = mtod(m, caddr_t) + m->m_len; 130 m->m_len += size; 131 return bpos; 132} 133 134int 135mb_put_uint8(struct mbchain *mbp, u_int8_t x) 136{ 137 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 138} 139 140int 141mb_put_uint16be(struct mbchain *mbp, u_int16_t x) 142{ 143 x = htobe16(x); 144 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 145} 146 147int 148mb_put_uint16le(struct mbchain *mbp, u_int16_t x) 149{ 150 x = htole16(x); 151 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 152} 153 154int 155mb_put_uint32be(struct mbchain *mbp, u_int32_t x) 156{ 157 x = htobe32(x); 158 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 159} 160 161int 162mb_put_uint32le(struct mbchain *mbp, u_int32_t x) 163{ 164 x = htole32(x); 165 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 166} 167 168int 169mb_put_int64be(struct mbchain *mbp, int64_t x) 170{ 171 x = htobe64(x); 172 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 173} 174 175int 176mb_put_int64le(struct mbchain *mbp, int64_t x) 177{ 178 x = htole64(x); 179 return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 180} 181 182int 183mb_put_mem(struct mbchain *mbp, c_caddr_t source, int size, int type) 184{ 185 struct mbuf *m; 186 caddr_t dst; 187 c_caddr_t src; 188 int cplen, error, mleft, count; 189 190 m = mbp->mb_cur; 191 mleft = mbp->mb_mleft; 192 193 while (size > 0) { 194 if (mleft == 0) { 195 if (m->m_next == NULL) { 196 m = m_getm(m, size, M_TRYWAIT, MT_DATA); 197 if (m == NULL) 198 return ENOBUFS; 199 } else 200 m = m->m_next; 201 mleft = M_TRAILINGSPACE(m); 202 continue; 203 } 204 cplen = mleft > size ? size : mleft; 205 dst = mtod(m, caddr_t) + m->m_len; 206 switch (type) { 207 case MB_MCUSTOM: 208 error = mbp->mb_copy(mbp, source, dst, cplen); 209 if (error) 210 return error; 211 break; 212 case MB_MINLINE: 213 for (src = source, count = cplen; count; count--) 214 *dst++ = *src++; 215 break; 216 case MB_MSYSTEM: 217 bcopy(source, dst, cplen); 218 break; 219 case MB_MUSER: 220 error = copyin(source, dst, cplen); 221 if (error) 222 return error; 223 break; 224 case MB_MZERO: 225 bzero(dst, cplen); 226 break; 227 } 228 size -= cplen; 229 source += cplen; 230 m->m_len += cplen; 231 mleft -= cplen; 232 mbp->mb_count += cplen; 233 } 234 mbp->mb_cur = m; 235 mbp->mb_mleft = mleft; 236 return 0; 237} 238 239int 240mb_put_mbuf(struct mbchain *mbp, struct mbuf *m) 241{ 242 mbp->mb_cur->m_next = m; 243 while (m) { 244 mbp->mb_count += m->m_len; 245 if (m->m_next == NULL) 246 break; 247 m = m->m_next; 248 } 249 mbp->mb_mleft = M_TRAILINGSPACE(m); 250 mbp->mb_cur = m; 251 return 0; 252} 253 254/* 255 * copies a uio scatter/gather list to an mbuf chain. 256 */ 257int 258mb_put_uio(struct mbchain *mbp, struct uio *uiop, int size) 259{ 260 long left; 261 int mtype, error; 262 263 mtype = (uiop->uio_segflg == UIO_SYSSPACE) ? MB_MSYSTEM : MB_MUSER; 264 265 while (size > 0 && uiop->uio_resid) { 266 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 267 return EFBIG; 268 left = uiop->uio_iov->iov_len; 269 if (left == 0) { 270 uiop->uio_iov++; 271 uiop->uio_iovcnt--; 272 continue; 273 } 274 if (left > size) 275 left = size; 276 error = mb_put_mem(mbp, uiop->uio_iov->iov_base, left, mtype); 277 if (error) 278 return error; 279 uiop->uio_offset += left; 280 uiop->uio_resid -= left; 281 uiop->uio_iov->iov_base = 282 (char *)uiop->uio_iov->iov_base + left; 283 uiop->uio_iov->iov_len -= left; 284 size -= left; 285 } 286 return 0; 287} 288 289/* 290 * Routines for fetching data from an mbuf chain 291 */ 292int 293md_init(struct mdchain *mdp) 294{ 295 struct mbuf *m; 296 297 m = m_gethdr(M_TRYWAIT, MT_DATA); 298 if (m == NULL) 299 return ENOBUFS; 300 m->m_len = 0; 301 md_initm(mdp, m); 302 return 0; 303} 304 305void 306md_initm(struct mdchain *mdp, struct mbuf *m) 307{ 308 bzero(mdp, sizeof(*mdp)); 309 mdp->md_top = mdp->md_cur = m; 310 mdp->md_pos = mtod(m, u_char*); 311} 312 313void 314md_done(struct mdchain *mdp) 315{ 316 if (mdp->md_top) { 317 m_freem(mdp->md_top); 318 mdp->md_top = NULL; 319 } 320} 321 322/* 323 * Append a separate mbuf chain. It is caller responsibility to prevent 324 * multiple calls to fetch/record routines. 325 */ 326void 327md_append_record(struct mdchain *mdp, struct mbuf *top) 328{ 329 struct mbuf *m; 330 331 if (mdp->md_top == NULL) { 332 md_initm(mdp, top); 333 return; 334 } 335 m = mdp->md_top; 336 while (m->m_nextpkt) 337 m = m->m_nextpkt; 338 m->m_nextpkt = top; 339 top->m_nextpkt = NULL; 340 return; 341} 342 343/* 344 * Put next record in place of existing 345 */ 346int 347md_next_record(struct mdchain *mdp) 348{ 349 struct mbuf *m; 350 351 if (mdp->md_top == NULL) 352 return ENOENT; 353 m = mdp->md_top->m_nextpkt; 354 md_done(mdp); 355 if (m == NULL) 356 return ENOENT; 357 md_initm(mdp, m); 358 return 0; 359} 360 361int 362md_get_uint8(struct mdchain *mdp, u_int8_t *x) 363{ 364 return md_get_mem(mdp, x, 1, MB_MINLINE); 365} 366 367int 368md_get_uint16(struct mdchain *mdp, u_int16_t *x) 369{ 370 return md_get_mem(mdp, (caddr_t)x, 2, MB_MINLINE); 371} 372 373int 374md_get_uint16le(struct mdchain *mdp, u_int16_t *x) 375{ 376 u_int16_t v; 377 int error = md_get_uint16(mdp, &v); 378 379 if (x != NULL) 380 *x = le16toh(v); 381 return error; 382} 383 384int 385md_get_uint16be(struct mdchain *mdp, u_int16_t *x) { 386 u_int16_t v; 387 int error = md_get_uint16(mdp, &v); 388 389 if (x != NULL) 390 *x = be16toh(v); 391 return error; 392} 393 394int 395md_get_uint32(struct mdchain *mdp, u_int32_t *x) 396{ 397 return md_get_mem(mdp, (caddr_t)x, 4, MB_MINLINE); 398} 399 400int 401md_get_uint32be(struct mdchain *mdp, u_int32_t *x) 402{ 403 u_int32_t v; 404 int error; 405 406 error = md_get_uint32(mdp, &v); 407 if (x != NULL) 408 *x = be32toh(v); 409 return error; 410} 411 412int 413md_get_uint32le(struct mdchain *mdp, u_int32_t *x) 414{ 415 u_int32_t v; 416 int error; 417 418 error = md_get_uint32(mdp, &v); 419 if (x != NULL) 420 *x = le32toh(v); 421 return error; 422} 423 424int 425md_get_int64(struct mdchain *mdp, int64_t *x) 426{ 427 return md_get_mem(mdp, (caddr_t)x, 8, MB_MINLINE); 428} 429 430int 431md_get_int64be(struct mdchain *mdp, int64_t *x) 432{ 433 int64_t v; 434 int error; 435 436 error = md_get_int64(mdp, &v); 437 if (x != NULL) 438 *x = be64toh(v); 439 return error; 440} 441 442int 443md_get_int64le(struct mdchain *mdp, int64_t *x) 444{ 445 int64_t v; 446 int error; 447 448 error = md_get_int64(mdp, &v); 449 if (x != NULL) 450 *x = le64toh(v); 451 return error; 452} 453 454int 455md_get_mem(struct mdchain *mdp, caddr_t target, int size, int type) 456{ 457 struct mbuf *m = mdp->md_cur; 458 int error; 459 u_int count; 460 u_char *s; 461 462 while (size > 0) { 463 if (m == NULL) { 464 MBERROR("incomplete copy\n"); 465 return EBADRPC; 466 } 467 s = mdp->md_pos; 468 count = mtod(m, u_char*) + m->m_len - s; 469 if (count == 0) { 470 mdp->md_cur = m = m->m_next; 471 if (m) 472 s = mdp->md_pos = mtod(m, caddr_t); 473 continue; 474 } 475 if (count > size) 476 count = size; 477 size -= count; 478 mdp->md_pos += count; 479 if (target == NULL) 480 continue; 481 switch (type) { 482 case MB_MUSER: 483 error = copyout(s, target, count); 484 if (error) 485 return error; 486 break; 487 case MB_MSYSTEM: 488 bcopy(s, target, count); 489 break; 490 case MB_MINLINE: 491 while (count--) 492 *target++ = *s++; 493 continue; 494 } 495 target += count; 496 } 497 return 0; 498} 499 500int 501md_get_mbuf(struct mdchain *mdp, int size, struct mbuf **ret) 502{ 503 struct mbuf *m = mdp->md_cur, *rm; 504 505 rm = m_copym(m, mdp->md_pos - mtod(m, u_char*), size, M_TRYWAIT); 506 if (rm == NULL) 507 return EBADRPC; 508 md_get_mem(mdp, NULL, size, MB_MZERO); 509 *ret = rm; 510 return 0; 511} 512 513int 514md_get_uio(struct mdchain *mdp, struct uio *uiop, int size) 515{ 516 char *uiocp; 517 long left; 518 int mtype, error; 519 520 mtype = (uiop->uio_segflg == UIO_SYSSPACE) ? MB_MSYSTEM : MB_MUSER; 521 while (size > 0 && uiop->uio_resid) { 522 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 523 return EFBIG; 524 left = uiop->uio_iov->iov_len; 525 if (left == 0) { 526 uiop->uio_iov++; 527 uiop->uio_iovcnt--; 528 continue; 529 } 530 uiocp = uiop->uio_iov->iov_base; 531 if (left > size) 532 left = size; 533 error = md_get_mem(mdp, uiocp, left, mtype); 534 if (error) 535 return error; 536 uiop->uio_offset += left; 537 uiop->uio_resid -= left; 538 uiop->uio_iov->iov_base = 539 (char *)uiop->uio_iov->iov_base + left; 540 uiop->uio_iov->iov_len -= left; 541 size -= left; 542 } 543 return 0; 544}
|