Print this page
first pass
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/crypto/io/arcfour.c
+++ new/usr/src/uts/common/crypto/io/arcfour.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 27 * RC4 provider for the Kernel Cryptographic Framework (KCF)
28 28 */
29 29
30 30 #include <sys/types.h>
31 31 #include <sys/systm.h>
32 32 #include <sys/modctl.h>
33 33 #include <sys/cmn_err.h>
34 34 #include <sys/ddi.h>
35 35 #include <sys/crypto/common.h>
36 36 #include <sys/crypto/spi.h>
37 37 #include <sys/sysmacros.h>
38 38 #include <sys/strsun.h>
39 39 #include <arcfour.h>
40 40
41 41 extern struct mod_ops mod_cryptoops;
42 42
43 43 /*
44 44 * Module linkage information for the kernel.
45 45 */
46 46 static struct modlcrypto modlcrypto = {
47 47 &mod_cryptoops,
48 48 "RC4 Kernel SW Provider"
49 49 };
50 50
51 51 static struct modlinkage modlinkage = {
52 52 MODREV_1,
53 53 (void *)&modlcrypto,
54 54 NULL
55 55 };
56 56
57 57 /*
58 58 * CSPI information (entry points, provider info, etc.)
59 59 */
60 60
61 61 #define RC4_MECH_INFO_TYPE 0
62 62 /*
63 63 * Mechanism info structure passed to KCF during registration.
64 64 */
65 65 static crypto_mech_info_t rc4_mech_info_tab[] = {
66 66 {SUN_CKM_RC4, RC4_MECH_INFO_TYPE,
67 67 CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
68 68 CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
69 69 ARCFOUR_MIN_KEY_BITS, ARCFOUR_MAX_KEY_BITS,
70 70 CRYPTO_KEYSIZE_UNIT_IN_BITS | CRYPTO_CAN_SHARE_OPSTATE}
71 71 };
72 72
73 73 static void rc4_provider_status(crypto_provider_handle_t, uint_t *);
74 74
75 75 static crypto_control_ops_t rc4_control_ops = {
76 76 rc4_provider_status
77 77 };
78 78
79 79 static int rc4_common_init(crypto_ctx_t *, crypto_mechanism_t *,
80 80 crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
81 81
82 82 static int rc4_crypt_update(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
83 83 crypto_req_handle_t);
84 84
85 85 static int rc4_crypt_final(crypto_ctx_t *, crypto_data_t *,
86 86 crypto_req_handle_t);
87 87
88 88 static int rc4_crypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
89 89 crypto_req_handle_t);
90 90
91 91 static int rc4_crypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
92 92 crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
93 93 crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
94 94
95 95
96 96 static crypto_cipher_ops_t rc4_cipher_ops = {
97 97 rc4_common_init,
98 98 rc4_crypt,
99 99 rc4_crypt_update,
100 100 rc4_crypt_final,
101 101 rc4_crypt_atomic,
102 102 rc4_common_init,
103 103 rc4_crypt,
104 104 rc4_crypt_update,
105 105 rc4_crypt_final,
106 106 rc4_crypt_atomic
107 107 };
108 108
109 109 static int rc4_free_context(crypto_ctx_t *);
110 110
111 111 static crypto_ctx_ops_t rc4_ctx_ops = {
112 112 NULL,
113 113 rc4_free_context
114 114 };
115 115
116 116 static crypto_ops_t rc4_crypto_ops = {
117 117 &rc4_control_ops,
118 118 NULL,
119 119 &rc4_cipher_ops,
120 120 NULL,
121 121 NULL,
122 122 NULL,
123 123 NULL,
124 124 NULL,
125 125 NULL,
126 126 NULL,
127 127 NULL,
128 128 NULL,
129 129 NULL,
130 130 &rc4_ctx_ops
131 131 };
132 132
133 133 static crypto_provider_info_t rc4_prov_info = {
134 134 CRYPTO_SPI_VERSION_1,
135 135 "RC4 Software Provider",
136 136 CRYPTO_SW_PROVIDER,
137 137 {&modlinkage},
138 138 NULL,
139 139 &rc4_crypto_ops,
140 140 sizeof (rc4_mech_info_tab)/sizeof (crypto_mech_info_t),
141 141 rc4_mech_info_tab
142 142 };
143 143
144 144 static crypto_kcf_provider_handle_t rc4_prov_handle = NULL;
145 145
146 146 static mblk_t *advance_position(mblk_t *, off_t, uchar_t **);
147 147 static int crypto_arcfour_crypt(ARCFour_key *, uchar_t *, crypto_data_t *,
148 148 int);
149 149
150 150 int
151 151 _init(void)
152 152 {
153 153 int ret;
154 154
155 155 if ((ret = mod_install(&modlinkage)) != 0)
156 156 return (ret);
157 157
158 158 /* Register with KCF. If the registration fails, remove the module. */
159 159 if (crypto_register_provider(&rc4_prov_info, &rc4_prov_handle)) {
160 160 (void) mod_remove(&modlinkage);
161 161 return (EACCES);
162 162 }
163 163
164 164 return (0);
165 165 }
166 166
167 167 int
168 168 _fini(void)
169 169 {
170 170 /* Unregister from KCF if module is registered */
171 171 if (rc4_prov_handle != NULL) {
172 172 if (crypto_unregister_provider(rc4_prov_handle))
173 173 return (EBUSY);
174 174
175 175 rc4_prov_handle = NULL;
176 176 }
177 177
178 178 return (mod_remove(&modlinkage));
179 179 }
180 180
181 181 int
182 182 _info(struct modinfo *modinfop)
183 183 {
184 184 return (mod_info(&modlinkage, modinfop));
185 185 }
186 186
187 187
188 188 /*
189 189 * KCF software provider control entry points.
190 190 */
191 191 /* ARGSUSED */
192 192 static void
193 193 rc4_provider_status(crypto_provider_handle_t provider, uint_t *status)
↓ open down ↓ |
193 lines elided |
↑ open up ↑ |
194 194 {
195 195 *status = CRYPTO_PROVIDER_READY;
196 196 }
197 197
198 198 /* ARGSUSED */
199 199 static int
200 200 rc4_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
201 201 crypto_key_t *key, crypto_spi_ctx_template_t template,
202 202 crypto_req_handle_t req)
203 203 {
204 -
205 -/* EXPORT DELETE START */
206 -
207 204 ARCFour_key *keystream;
208 205
209 206 if ((mechanism)->cm_type != RC4_MECH_INFO_TYPE)
210 207 return (CRYPTO_MECHANISM_INVALID);
211 208
212 209 if (key->ck_format != CRYPTO_KEY_RAW)
213 210 return (CRYPTO_KEY_TYPE_INCONSISTENT);
214 211
215 212 if (key->ck_length < ARCFOUR_MIN_KEY_BITS ||
216 213 key->ck_length > ARCFOUR_MAX_KEY_BITS) {
217 214 return (CRYPTO_KEY_SIZE_RANGE);
218 215 }
219 216
220 217 /*
221 218 * Allocate an RC4 key stream.
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
222 219 */
223 220 if ((keystream = kmem_alloc(sizeof (ARCFour_key),
224 221 crypto_kmflag(req))) == NULL)
225 222 return (CRYPTO_HOST_MEMORY);
226 223
227 224 arcfour_key_init(keystream, key->ck_data,
228 225 CRYPTO_BITS2BYTES(key->ck_length));
229 226
230 227 ctx->cc_provider_private = keystream;
231 228
232 -/* EXPORT DELETE END */
233 -
234 229 return (CRYPTO_SUCCESS);
235 230 }
236 231
237 232 static int
238 233 rc4_crypt(crypto_ctx_t *ctx, crypto_data_t *input, crypto_data_t *output,
239 234 crypto_req_handle_t req)
240 235 {
241 236 int ret;
242 237
243 238 ret = rc4_crypt_update(ctx, input, output, req);
244 239
245 240 if (ret != CRYPTO_BUFFER_TOO_SMALL)
246 241 (void) rc4_free_context(ctx);
247 242
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
248 243 return (ret);
249 244 }
250 245
251 246 /* ARGSUSED */
252 247 static int
253 248 rc4_crypt_update(crypto_ctx_t *ctx, crypto_data_t *input, crypto_data_t *output,
254 249 crypto_req_handle_t req)
255 250 {
256 251 int ret = CRYPTO_SUCCESS;
257 252
258 -/* EXPORT DELETE START */
259 -
260 253 ARCFour_key *key;
261 254 off_t saveoffset;
262 255
263 256 ASSERT(ctx->cc_provider_private != NULL);
264 257
265 258 if ((ctx->cc_flags & CRYPTO_USE_OPSTATE) && ctx->cc_opstate != NULL)
266 259 key = ctx->cc_opstate;
267 260 else
268 261 key = ctx->cc_provider_private;
269 262
270 263 /* Simple case: in-line encipherment */
271 264
272 265 if (output == NULL) {
273 266 switch (input->cd_format) {
274 267 case CRYPTO_DATA_RAW: {
275 268 char *start, *end;
276 269 start = input->cd_raw.iov_base + input->cd_offset;
277 270
278 271 end = input->cd_raw.iov_base + input->cd_raw.iov_len;
279 272
280 273 if (start + input->cd_length > end)
281 274 return (CRYPTO_DATA_INVALID);
282 275
283 276 arcfour_crypt(key, (uchar_t *)start, (uchar_t *)start,
284 277 input->cd_length);
285 278 break;
286 279 }
287 280 case CRYPTO_DATA_MBLK: {
288 281 uchar_t *start, *end;
289 282 size_t len, left;
290 283 mblk_t *mp = input->cd_mp, *mp1, *mp2;
291 284
292 285 ASSERT(mp != NULL);
293 286
294 287 mp1 = advance_position(mp, input->cd_offset, &start);
295 288
296 289 if (mp1 == NULL)
297 290 return (CRYPTO_DATA_LEN_RANGE);
298 291
299 292 mp2 = advance_position(mp, input->cd_offset +
300 293 input->cd_length, &end);
301 294
302 295 if (mp2 == NULL)
303 296 return (CRYPTO_DATA_LEN_RANGE);
304 297
305 298 left = input->cd_length;
306 299 while (mp1 != NULL) {
307 300 if (_PTRDIFF(mp1->b_wptr, start) > left) {
308 301 len = left;
309 302 arcfour_crypt(key, start, start, len);
310 303 mp1 = NULL;
311 304 } else {
312 305 len = _PTRDIFF(mp1->b_wptr, start);
313 306 arcfour_crypt(key, start, start, len);
314 307 mp1 = mp1->b_cont;
315 308 start = mp1->b_rptr;
316 309 left -= len;
317 310 }
318 311 }
319 312 break;
320 313 }
321 314 case CRYPTO_DATA_UIO: {
322 315 uio_t *uiop = input->cd_uio;
323 316 off_t offset = input->cd_offset;
324 317 size_t length = input->cd_length;
325 318 uint_t vec_idx;
326 319 size_t cur_len;
327 320
328 321 /*
329 322 * Jump to the first iovec containing data to be
330 323 * processed.
331 324 */
332 325 for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
333 326 offset >= uiop->uio_iov[vec_idx].iov_len;
334 327 offset -= uiop->uio_iov[vec_idx++].iov_len)
335 328 ;
336 329 if (vec_idx == uiop->uio_iovcnt) {
337 330 return (CRYPTO_DATA_LEN_RANGE);
338 331 }
339 332
340 333 /*
341 334 * Now process the iovecs.
342 335 */
343 336 while (vec_idx < uiop->uio_iovcnt && length > 0) {
344 337 uchar_t *start;
345 338 iovec_t *iovp = &(uiop->uio_iov[vec_idx]);
346 339
347 340 cur_len = MIN(iovp->iov_len - offset, length);
348 341
349 342 start = (uchar_t *)(iovp->iov_base + offset);
350 343 arcfour_crypt(key, start + offset,
351 344 start + offset, cur_len);
352 345
353 346 length -= cur_len;
354 347 vec_idx++;
355 348 offset = 0;
356 349 }
357 350
358 351 if (vec_idx == uiop->uio_iovcnt && length > 0) {
359 352
360 353 return (CRYPTO_DATA_LEN_RANGE);
361 354 }
362 355 break;
363 356 }
364 357 }
365 358 return (CRYPTO_SUCCESS);
366 359 }
367 360
368 361 /*
369 362 * We need to just return the length needed to store the output.
370 363 * We should not destroy the context for the following case.
371 364 */
372 365
373 366 if (input->cd_length > output->cd_length) {
374 367 output->cd_length = input->cd_length;
375 368 return (CRYPTO_BUFFER_TOO_SMALL);
376 369 }
377 370
378 371 saveoffset = output->cd_offset;
379 372
380 373 switch (input->cd_format) {
381 374 case CRYPTO_DATA_RAW: {
382 375 char *start, *end;
383 376 start = input->cd_raw.iov_base + input->cd_offset;
384 377
385 378 end = input->cd_raw.iov_base + input->cd_raw.iov_len;
386 379
387 380 if (start + input->cd_length > end)
388 381 return (CRYPTO_DATA_LEN_RANGE);
389 382
390 383 ret = crypto_arcfour_crypt(key, (uchar_t *)start, output,
391 384 input->cd_length);
392 385
393 386 if (ret != CRYPTO_SUCCESS)
394 387 return (ret);
395 388 break;
396 389 }
397 390 case CRYPTO_DATA_MBLK: {
398 391 uchar_t *start, *end;
399 392 size_t len, left;
400 393 mblk_t *mp = input->cd_mp, *mp1, *mp2;
401 394
402 395 ASSERT(mp != NULL);
403 396
404 397 mp1 = advance_position(mp, input->cd_offset, &start);
405 398
406 399 if (mp1 == NULL)
407 400 return (CRYPTO_DATA_LEN_RANGE);
408 401
409 402 mp2 = advance_position(mp, input->cd_offset + input->cd_length,
410 403 &end);
411 404
412 405 if (mp2 == NULL)
413 406 return (CRYPTO_DATA_LEN_RANGE);
414 407
415 408 left = input->cd_length;
416 409 while (mp1 != NULL) {
417 410 if (_PTRDIFF(mp1->b_wptr, start) > left) {
418 411 len = left;
419 412 ret = crypto_arcfour_crypt(key, start, output,
420 413 len);
421 414 if (ret != CRYPTO_SUCCESS)
422 415 return (ret);
423 416 mp1 = NULL;
424 417 } else {
425 418 len = _PTRDIFF(mp1->b_wptr, start);
426 419 ret = crypto_arcfour_crypt(key, start, output,
427 420 len);
428 421 if (ret != CRYPTO_SUCCESS)
429 422 return (ret);
430 423 mp1 = mp1->b_cont;
431 424 start = mp1->b_rptr;
432 425 left -= len;
433 426 output->cd_offset += len;
434 427 }
435 428 }
436 429 break;
437 430 }
438 431 case CRYPTO_DATA_UIO: {
439 432 uio_t *uiop = input->cd_uio;
440 433 off_t offset = input->cd_offset;
441 434 size_t length = input->cd_length;
442 435 uint_t vec_idx;
443 436 size_t cur_len;
444 437
445 438 /*
446 439 * Jump to the first iovec containing data to be
447 440 * processed.
448 441 */
449 442 for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
450 443 offset >= uiop->uio_iov[vec_idx].iov_len;
451 444 offset -= uiop->uio_iov[vec_idx++].iov_len)
452 445 ;
453 446 if (vec_idx == uiop->uio_iovcnt) {
454 447 return (CRYPTO_DATA_LEN_RANGE);
455 448 }
456 449
457 450 /*
458 451 * Now process the iovecs.
459 452 */
460 453 while (vec_idx < uiop->uio_iovcnt && length > 0) {
461 454 uchar_t *start;
462 455 iovec_t *iovp = &(uiop->uio_iov[vec_idx]);
463 456 cur_len = MIN(iovp->iov_len - offset, length);
464 457
465 458 start = (uchar_t *)(iovp->iov_base + offset);
466 459 ret = crypto_arcfour_crypt(key, start + offset,
467 460 output, cur_len);
468 461 if (ret != CRYPTO_SUCCESS)
469 462 return (ret);
470 463
471 464 length -= cur_len;
472 465 vec_idx++;
473 466 offset = 0;
474 467 output->cd_offset += cur_len;
475 468 }
476 469
↓ open down ↓ |
207 lines elided |
↑ open up ↑ |
477 470 if (vec_idx == uiop->uio_iovcnt && length > 0) {
478 471
479 472 return (CRYPTO_DATA_LEN_RANGE);
480 473 }
481 474 }
482 475 }
483 476
484 477 output->cd_offset = saveoffset;
485 478 output->cd_length = input->cd_length;
486 479
487 -/* EXPORT DELETE END */
488 -
489 480 return (ret);
490 481 }
491 482
492 483 /* ARGSUSED */
493 484 static int rc4_crypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
494 485 crypto_req_handle_t req)
495 486 {
496 487 /* No final part for streams ciphers. Just free the context */
497 488 if (data != NULL)
498 489 data->cd_length = 0;
499 490
500 491 return (rc4_free_context(ctx));
501 492 }
502 493
503 494 /* ARGSUSED */
504 495 static int
505 496 rc4_crypt_atomic(crypto_provider_handle_t handle, crypto_session_id_t session,
506 497 crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *input,
507 498 crypto_data_t *output, crypto_spi_ctx_template_t template,
508 499 crypto_req_handle_t req)
509 500 {
510 501 crypto_ctx_t ctx;
511 502 int ret;
512 503
513 504 bzero(&ctx, sizeof (crypto_ctx_t));
514 505 ret = rc4_common_init(&ctx, mechanism, key, template, req);
515 506
516 507 if (ret != CRYPTO_SUCCESS)
517 508 return (ret);
518 509
519 510 ret = rc4_crypt_update(&ctx, input, output, req);
↓ open down ↓ |
21 lines elided |
↑ open up ↑ |
520 511
521 512 (void) rc4_free_context(&ctx);
522 513
523 514 return (ret);
524 515 }
525 516
526 517 /* ARGSUSED */
527 518 static int
528 519 rc4_free_context(crypto_ctx_t *ctx)
529 520 {
530 -
531 -/* EXPORT DELETE START */
532 -
533 521 ARCFour_key *keystream = ctx->cc_provider_private;
534 522
535 523 if (keystream != NULL) {
536 524 bzero(keystream, sizeof (ARCFour_key));
537 525 kmem_free(keystream, sizeof (ARCFour_key));
538 526 ctx->cc_provider_private = NULL;
539 527 }
540 528
541 -/* EXPORT DELETE END */
542 -
543 529 return (CRYPTO_SUCCESS);
544 530 }
545 531
546 532 /* Encrypts a contiguous input 'in' into the 'out' crypto_data_t */
547 533
548 534 static int
549 535 crypto_arcfour_crypt(ARCFour_key *key, uchar_t *in, crypto_data_t *out,
550 536 int length)
551 537 {
552 538 switch (out->cd_format) {
553 539 case CRYPTO_DATA_RAW: {
554 540 uchar_t *start, *end;
555 541 start = (uchar_t *)(out->cd_raw.iov_base +
556 542 out->cd_offset);
557 543
558 544 end = (uchar_t *)(out->cd_raw.iov_base +
559 545 out->cd_raw.iov_len);
560 546
561 547 if (start + out->cd_length > end)
562 548 return (CRYPTO_DATA_LEN_RANGE);
563 549
564 550 arcfour_crypt(key, in, start, length);
565 551
566 552 return (CRYPTO_SUCCESS);
567 553 }
568 554 case CRYPTO_DATA_MBLK: {
569 555 uchar_t *start, *end;
570 556 size_t len, left;
571 557 mblk_t *mp = out->cd_mp, *mp1, *mp2;
572 558
573 559 ASSERT(mp != NULL);
574 560
575 561 mp1 = advance_position(mp, out->cd_offset, &start);
576 562
577 563 if (mp1 == NULL)
578 564 return (CRYPTO_DATA_LEN_RANGE);
579 565
580 566 mp2 = advance_position(mp, out->cd_offset +
581 567 out->cd_length, &end);
582 568
583 569 if (mp2 == NULL)
584 570 return (CRYPTO_DATA_LEN_RANGE);
585 571
586 572 left = length;
587 573 while (mp1 != NULL) {
588 574 if (_PTRDIFF(mp1->b_wptr, start) > left) {
589 575 len = left;
590 576 arcfour_crypt(key, in, start, len);
591 577 mp1 = NULL;
592 578 } else {
593 579 len = _PTRDIFF(mp1->b_wptr, start);
594 580 arcfour_crypt(key, in, start, len);
595 581 mp1 = mp1->b_cont;
596 582 start = mp1->b_rptr;
597 583 left -= len;
598 584 }
599 585 }
600 586 break;
601 587 }
602 588 case CRYPTO_DATA_UIO: {
603 589 uio_t *uiop = out->cd_uio;
604 590 off_t offset = out->cd_offset;
605 591 size_t len = length;
606 592 uint_t vec_idx;
607 593 size_t cur_len;
608 594
609 595 /*
610 596 * Jump to the first iovec containing data to be
611 597 * processed.
612 598 */
613 599 for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
614 600 offset >= uiop->uio_iov[vec_idx].iov_len;
615 601 offset -= uiop->uio_iov[vec_idx++].iov_len)
616 602 ;
617 603 if (vec_idx == uiop->uio_iovcnt) {
618 604 return (CRYPTO_DATA_LEN_RANGE);
619 605 }
620 606
621 607 /*
622 608 * Now process the iovecs.
623 609 */
624 610 while (vec_idx < uiop->uio_iovcnt && len > 0) {
625 611 uchar_t *start;
626 612 iovec_t *iovp = &(uiop->uio_iov[vec_idx]);
627 613 cur_len = MIN(iovp->iov_len - offset, len);
628 614
629 615 start = (uchar_t *)(iovp->iov_base + offset);
630 616 arcfour_crypt(key, start + offset,
631 617 start + offset, cur_len);
632 618
633 619 len -= cur_len;
634 620 vec_idx++;
635 621 offset = 0;
636 622 }
637 623
638 624 if (vec_idx == uiop->uio_iovcnt && len > 0) {
639 625 return (CRYPTO_DATA_LEN_RANGE);
640 626 }
641 627 break;
642 628 }
643 629 default:
644 630 return (CRYPTO_DATA_INVALID);
645 631 }
646 632 return (CRYPTO_SUCCESS);
647 633 }
648 634
649 635 /*
650 636 * Advances 'offset' bytes from the beginning of the first block in 'mp',
651 637 * possibly jumping across b_cont boundary
652 638 * '*cpp' is set to the position of the byte we want, and the block where
653 639 * 'cpp' is returned.
654 640 */
655 641 static mblk_t *
656 642 advance_position(mblk_t *mp, off_t offset, uchar_t **cpp)
657 643 {
658 644 mblk_t *mp1 = mp;
659 645 size_t l;
660 646 off_t o = offset;
661 647
662 648 while (mp1 != NULL) {
663 649 l = MBLKL(mp1);
664 650
665 651 if (l <= o) {
666 652 o -= l;
667 653 mp1 = mp1->b_cont;
668 654 } else {
669 655 *cpp = (uchar_t *)(mp1->b_rptr + o);
670 656 break;
671 657 }
672 658 }
673 659 return (mp1);
674 660 }
↓ open down ↓ |
122 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX