iPXE
pccrc.c File Reference

Peer Content Caching and Retrieval: Content Identification [MS-PCCRC]. More...

#include <errno.h>
#include <assert.h>
#include <ipxe/sha256.h>
#include <ipxe/sha512.h>
#include <ipxe/hmac.h>
#include <ipxe/base16.h>
#include <ipxe/pccrc.h>

Go to the source code of this file.

Data Structures

struct  peerdist_info_v2_cursor
 A segment cursor. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static const char * peerdist_info_hash_ntoa (const struct peerdist_info *info, const void *hash)
 Transcribe hash value (for debugging)
static int peerdist_info_get (const struct peerdist_info *info, void *data, size_t offset, size_t len)
 Get raw data.
static void peerdist_info_segment_hash (struct peerdist_info_segment *segment, const void *hash, const void *secret)
 Populate segment hashes.
static int peerdist_info_v1_blocks (const struct peerdist_info *info, size_t offset)
 Get number of blocks within a block description.
static ssize_t peerdist_info_v1_block_offset (const struct peerdist_info *info, unsigned int index)
 Locate block description.
static int peerdist_info_v1 (struct peerdist_info *info)
 Populate content information.
static int peerdist_info_v1_segment (struct peerdist_info_segment *segment)
 Populate content information segment.
static int peerdist_info_v1_block (struct peerdist_info_block *block)
 Populate content information block.
static void peerdist_info_v2_cursor_init (struct peerdist_info_v2_cursor *cursor)
 Initialise segment cursor.
static int peerdist_info_v2_cursor_next (const struct peerdist_info *info, struct peerdist_info_v2_cursor *cursor)
 Update segment cursor to next segment description.
static int peerdist_info_v2_segments (const struct peerdist_info *info, size_t *len)
 Get number of segments and total length.
static int peerdist_info_v2 (struct peerdist_info *info)
 Populate content information.
static int peerdist_info_v2_segment (struct peerdist_info_segment *segment)
 Populate content information segment.
static int peerdist_info_v2_block (struct peerdist_info_block *block)
 Populate content information block.
int peerdist_info (const void *data, size_t len, struct peerdist_info *info)
 Populate content information.
int peerdist_info_segment (const struct peerdist_info *info, struct peerdist_info_segment *segment, unsigned int index)
 Populate content information segment.
int peerdist_info_block (const struct peerdist_info_segment *segment, struct peerdist_info_block *block, unsigned int index)
 Populate content information block.

Variables

static struct peerdist_info_operations peerdist_info_v1_operations
 Content information version 1 operations.
static struct peerdist_info_operations peerdist_info_v2_operations
 Content information version 2 operations.

Detailed Description

Peer Content Caching and Retrieval: Content Identification [MS-PCCRC].

Definition in file pccrc.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ peerdist_info_hash_ntoa()

const char * peerdist_info_hash_ntoa ( const struct peerdist_info * info,
const void * hash )
inlinestatic

Transcribe hash value (for debugging)

Parameters
infoContent information
hashHash value
Return values
stringHash value string

Definition at line 56 of file pccrc.c.

56 {
57 static char buf[ ( 2 * PEERDIST_DIGEST_MAX_SIZE ) + 1 /* NUL */ ];
58 size_t digestsize = info->digestsize;
59
60 /* Sanity check */
61 assert ( info != NULL );
62 assert ( digestsize != 0 );
63 assert ( base16_encoded_len ( digestsize ) < sizeof ( buf ) );
64
65 /* Transcribe hash value */
66 base16_encode ( hash, digestsize, buf, sizeof ( buf ) );
67 return buf;
68}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
u32 info
Definition ar9003_mac.h:0
pseudo_bit_t hash[0x00010]
Definition arbel.h:2
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
static size_t base16_encoded_len(size_t raw_len)
Calculate length of base16-encoded data.
Definition base16.h:25
#define PEERDIST_DIGEST_MAX_SIZE
Maximum digest size for any supported algorithm.
Definition pccrc.h:298
uint32_t digestsize
Digest size (i.e.
Definition pccrr.h:1

References assert, base16_encoded_len(), digestsize, hash, info, NULL, and PEERDIST_DIGEST_MAX_SIZE.

Referenced by peerdist_info_block(), and peerdist_info_segment().

◆ peerdist_info_get()

int peerdist_info_get ( const struct peerdist_info * info,
void * data,
size_t offset,
size_t len )
static

Get raw data.

Parameters
infoContent information
dataData buffer
offsetStarting offset
lenLength
Return values
rcReturn status code

Definition at line 79 of file pccrc.c.

80 {
81
82 /* Sanity check */
83 if ( ( offset > info->raw.len ) ||
84 ( len > ( info->raw.len - offset ) ) ) {
85 DBGC ( info, "PCCRC %p data underrun at [%zx,%zx) of %zx\n",
86 info, offset, ( offset + len ), info->raw.len );
87 return -ERANGE;
88 }
89
90 /* Copy data */
91 memcpy ( data, ( info->raw.data + offset ), len );
92
93 return 0;
94}
uint16_t offset
Offset to command line.
Definition bzimage.h:3
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
#define DBGC(...)
Definition compiler.h:505
#define ERANGE
Result too large.
Definition errno.h:640
void * memcpy(void *dest, const void *src, size_t len) __nonnull

References data, DBGC, ERANGE, info, len, memcpy(), and offset.

Referenced by peerdist_info(), peerdist_info_v1(), peerdist_info_v1_block(), peerdist_info_v1_blocks(), peerdist_info_v1_segment(), peerdist_info_v2(), peerdist_info_v2_cursor_next(), and peerdist_info_v2_segment().

◆ peerdist_info_segment_hash()

void peerdist_info_segment_hash ( struct peerdist_info_segment * segment,
const void * hash,
const void * secret )
static

Populate segment hashes.

Parameters
segmentContent information segment to fill in
hashSegment hash of data
secretSegment secret

Definition at line 103 of file pccrc.c.

104 {
105 const struct peerdist_info *info = segment->info;
106 struct digest_algorithm *digest = info->digest;
107 uint8_t ctx[ hmac_ctxsize ( digest ) ];
108 size_t digestsize = info->digestsize;
110
111 /* Sanity check */
112 assert ( digestsize <= sizeof ( segment->hash ) );
113 assert ( digestsize <= sizeof ( segment->secret ) );
114 assert ( digestsize <= sizeof ( segment->id ) );
115
116 /* Get segment hash of data */
117 memcpy ( segment->hash, hash, digestsize );
118
119 /* Get segment secret */
120 memcpy ( segment->secret, secret, digestsize );
121
122 /* Calculate segment identifier */
123 hmac_init ( digest, ctx, segment->secret, digestsize );
124 hmac_update ( digest, ctx, segment->hash, digestsize );
125 hmac_update ( digest, ctx, magic, sizeof ( magic ) );
126 hmac_final ( digest, ctx, segment->id );
127}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
unsigned short uint16_t
Definition stdint.h:11
unsigned char uint8_t
Definition stdint.h:10
uint16_t magic
Magic signature.
Definition bzimage.h:1
void hmac_init(struct digest_algorithm *digest, void *ctx, const void *key, size_t key_len)
Initialise HMAC.
Definition hmac.c:58
void hmac_final(struct digest_algorithm *digest, void *ctx, void *hmac)
Finalise HMAC.
Definition hmac.c:88
static void hmac_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Update HMAC.
Definition hmac.h:43
static size_t hmac_ctxsize(struct digest_algorithm *digest)
Calculate HMAC context size.
Definition hmac.h:29
uint16_t segment
Code segment.
Definition librm.h:3
#define PEERDIST_SEGMENT_ID_MAGIC
Magic string constant used to calculate segment identifier.
Definition pccrc.h:391
A message digest algorithm.
Definition crypto.h:19
Content information.
Definition pccrc.h:317

References assert, ctx, digestsize, hash, hmac_ctxsize(), hmac_final(), hmac_init(), hmac_update(), info, magic, memcpy(), PEERDIST_SEGMENT_ID_MAGIC, and segment.

Referenced by peerdist_info_v1_segment(), and peerdist_info_v2_segment().

◆ peerdist_info_v1_blocks()

int peerdist_info_v1_blocks ( const struct peerdist_info * info,
size_t offset )
static

Get number of blocks within a block description.

Parameters
infoContent information
offsetBlock description offset
Return values
blocksNumber of blocks, or negative error

Definition at line 143 of file pccrc.c.

144 {
146 unsigned int blocks;
147 int rc;
148
149 /* Get block description header */
150 if ( ( rc = peerdist_info_get ( info, &raw, offset,
151 sizeof ( raw ) ) ) != 0 )
152 return rc;
153
154 /* Calculate number of blocks */
155 blocks = le32_to_cpu ( raw.blocks );
156
157 return blocks;
158}
__be32 raw[7]
Definition CIB_PRM.h:0
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define le32_to_cpu(value)
Definition byteswap.h:114
static int peerdist_info_get(const struct peerdist_info *info, void *data, size_t offset, size_t len)
Get raw data.
Definition pccrc.c:79
Content Information version 1 block description header.
Definition pccrc.h:157
uint32_t blocks
Number of blocks within the block description.
Definition pccrc.h:164

References peerdist_info_v1_block::blocks, info, le32_to_cpu, offset, peerdist_info_get(), raw, and rc.

Referenced by peerdist_info_v1_block_offset(), and peerdist_info_v1_segment().

◆ peerdist_info_v1_block_offset()

ssize_t peerdist_info_v1_block_offset ( const struct peerdist_info * info,
unsigned int index )
static

Locate block description.

Parameters
infoContent information
indexSegment index
Return values
offsetBlock description offset, or negative error

Definition at line 167 of file pccrc.c.

168 {
169 size_t digestsize = info->digestsize;
170 unsigned int i;
171 size_t offset;
172 int blocks;
173 int rc;
174
175 /* Sanity check */
176 assert ( index < info->segments );
177
178 /* Calculate offset of first block description */
179 offset = ( sizeof ( struct peerdist_info_v1 ) +
180 ( info->segments *
181 sizeof ( peerdist_info_v1_segment_t ( digestsize ) ) ) );
182
183 /* Iterate over block descriptions until we find this segment */
184 for ( i = 0 ; i < index ; i++ ) {
185
186 /* Get number of blocks */
187 blocks = peerdist_info_v1_blocks ( info, offset );
188 if ( blocks < 0 ) {
189 rc = blocks;
190 DBGC ( info, "PCCRC %p segment %d could not get number "
191 "of blocks: %s\n", info, i, strerror ( rc ) );
192 return rc;
193 }
194
195 /* Move to next block description */
197 blocks ) );
198 }
199
200 return offset;
201}
long index
Definition bigint.h:65
static int peerdist_info_v1_blocks(const struct peerdist_info *info, size_t offset)
Get number of blocks within a block description.
Definition pccrc.c:143
#define peerdist_info_v1_block_t(digestsize, blocks)
Content Information version 1 block description.
Definition pccrc.h:179
#define peerdist_info_v1_segment_t(digestsize)
Content Information version 1 segment description.
Definition pccrc.h:146
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
Content Information version 1 data structure header.
Definition pccrc.h:62
uint32_t segments
Number of segments within the content information.
Definition pccrc.h:84

References assert, peerdist_info_v1_block::blocks, DBGC, digestsize, index, info, offset, peerdist_info_v1_block_t, peerdist_info_v1_blocks(), peerdist_info_v1_segment_t, rc, peerdist_info_v1::segments, and strerror().

Referenced by peerdist_info_v1_block(), and peerdist_info_v1_segment().

◆ peerdist_info_v1()

int peerdist_info_v1 ( struct peerdist_info * info)
static

Populate content information.

Parameters
infoContent information to fill in
Return values
rcReturn status code

Definition at line 209 of file pccrc.c.

209 {
210 struct peerdist_info_v1 raw;
212 struct peerdist_info_segment last;
213 size_t first_skip;
214 size_t last_skip;
215 size_t last_read;
216 int rc;
217
218 /* Get raw header */
219 if ( ( rc = peerdist_info_get ( info, &raw, 0, sizeof ( raw ) ) ) != 0){
220 DBGC ( info, "PCCRC %p could not get V1 content information: "
221 "%s\n", info, strerror ( rc ) );
222 return rc;
223 }
224 assert ( raw.version.raw == cpu_to_le16 ( PEERDIST_INFO_V1 ) );
225
226 /* Determine hash algorithm */
227 switch ( raw.hash ) {
229 info->digest = &sha256_algorithm;
230 break;
232 info->digest = &sha384_algorithm;
233 break;
235 info->digest = &sha512_algorithm;
236 break;
237 default:
238 DBGC ( info, "PCCRC %p unsupported hash algorithm %#08x\n",
239 info, le32_to_cpu ( raw.hash ) );
240 return -ENOTSUP;
241 }
242 info->digestsize = info->digest->digestsize;
243 assert ( info->digest != NULL );
244 DBGC2 ( info, "PCCRC %p using %s[%zd]\n",
245 info, info->digest->name, ( info->digestsize * 8 ) );
246
247 /* Calculate number of segments */
248 info->segments = le32_to_cpu ( raw.segments );
249
250 /* Get first segment */
251 if ( ( rc = peerdist_info_segment ( info, &first, 0 ) ) != 0 )
252 return rc;
253
254 /* Calculate range start offset */
255 info->range.start = first.range.start;
256
257 /* Calculate trimmed range start offset */
258 first_skip = le32_to_cpu ( raw.first );
259 info->trim.start = ( first.range.start + first_skip );
260
261 /* Get last segment */
262 if ( ( rc = peerdist_info_segment ( info, &last,
263 ( info->segments - 1 ) ) ) != 0 )
264 return rc;
265
266 /* Calculate range end offset */
267 info->range.end = last.range.end;
268
269 /* Calculate trimmed range end offset */
270 if ( raw.last ) {
271 /* Explicit length to include from last segment is given */
272 last_read = le32_to_cpu ( raw.last );
273 last_skip = ( last.index ? 0 : first_skip );
274 info->trim.end = ( last.range.start + last_skip + last_read );
275 } else {
276 /* No explicit length given: range extends to end of segment */
277 info->trim.end = last.range.end;
278 }
279
280 return 0;
281}
#define DBGC2(...)
Definition compiler.h:522
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define cpu_to_le32(value)
Definition byteswap.h:108
#define cpu_to_le16(value)
Definition byteswap.h:107
#define PEERDIST_INFO_V1_HASH_SHA512
SHA-512 hash algorithm.
Definition pccrc.h:103
#define PEERDIST_INFO_V1_HASH_SHA384
SHA-384 hash algorithm.
Definition pccrc.h:100
#define PEERDIST_INFO_V1_HASH_SHA256
SHA-256 hash algorithm.
Definition pccrc.h:97
#define PEERDIST_INFO_V1
Content Information version 1.
Definition pccrc.h:46
uint32_t first
First block in range.
Definition pccrr.h:1
struct digest_algorithm sha256_algorithm
SHA-256 algorithm.
Definition sha256.c:265
struct digest_algorithm sha384_algorithm
SHA-384 algorithm.
Definition sha384.c:64
struct digest_algorithm sha512_algorithm
SHA-512 algorithm.
Definition sha512.c:285
A content information segment.
Definition pccrc.h:347

References assert, cpu_to_le16, cpu_to_le32, DBGC, DBGC2, peerdist_range::end, ENOTSUP, first, peerdist_info_segment::index, info, le32_to_cpu, NULL, peerdist_info_get(), PEERDIST_INFO_V1, PEERDIST_INFO_V1_HASH_SHA256, PEERDIST_INFO_V1_HASH_SHA384, PEERDIST_INFO_V1_HASH_SHA512, peerdist_info_segment::range, raw, rc, sha256_algorithm, sha384_algorithm, sha512_algorithm, peerdist_range::start, and strerror().

◆ peerdist_info_v1_segment()

int peerdist_info_v1_segment ( struct peerdist_info_segment * segment)
static

Populate content information segment.

Parameters
segmentContent information segment to fill in
Return values
rcReturn status code

Definition at line 289 of file pccrc.c.

289 {
290 const struct peerdist_info *info = segment->info;
291 size_t digestsize = info->digestsize;
293 ssize_t raw_offset;
294 int blocks;
295 int rc;
296
297 /* Sanity checks */
298 assert ( segment->index < info->segments );
299
300 /* Get raw description */
301 raw_offset = ( sizeof ( struct peerdist_info_v1 ) +
302 ( segment->index * sizeof ( raw ) ) );
303 if ( ( rc = peerdist_info_get ( info, &raw, raw_offset,
304 sizeof ( raw ) ) ) != 0 ) {
305 DBGC ( info, "PCCRC %p segment %d could not get segment "
306 "description: %s\n", info, segment->index,
307 strerror ( rc ) );
308 return rc;
309 }
310
311 /* Calculate start offset of this segment */
312 segment->range.start = le64_to_cpu ( raw.segment.offset );
313
314 /* Calculate end offset of this segment */
315 segment->range.end = ( segment->range.start +
316 le32_to_cpu ( raw.segment.len ) );
317
318 /* Calculate block size of this segment */
319 segment->blksize = le32_to_cpu ( raw.segment.blksize );
320
321 /* Locate block description for this segment */
322 raw_offset = peerdist_info_v1_block_offset ( info, segment->index );
323 if ( raw_offset < 0 ) {
324 rc = raw_offset;
325 return rc;
326 }
327
328 /* Get number of blocks */
329 blocks = peerdist_info_v1_blocks ( info, raw_offset );
330 if ( blocks < 0 ) {
331 rc = blocks;
332 DBGC ( info, "PCCRC %p segment %d could not get number of "
333 "blocks: %s\n", info, segment->index, strerror ( rc ) );
334 return rc;
335 }
336 segment->blocks = blocks;
337
338 /* Calculate segment hashes */
339 peerdist_info_segment_hash ( segment, raw.hash, raw.secret );
340
341 return 0;
342}
signed long ssize_t
Definition stdint.h:7
#define le64_to_cpu(value)
Definition byteswap.h:115
static void peerdist_info_segment_hash(struct peerdist_info_segment *segment, const void *hash, const void *secret)
Populate segment hashes.
Definition pccrc.c:103
static ssize_t peerdist_info_v1_block_offset(const struct peerdist_info *info, unsigned int index)
Locate block description.
Definition pccrc.c:167

References assert, DBGC, digestsize, index, info, le32_to_cpu, le64_to_cpu, peerdist_info_get(), peerdist_info_segment_hash(), peerdist_info_v1_block_offset(), peerdist_info_v1_blocks(), peerdist_info_v1_segment_t, raw, rc, segment, and strerror().

◆ peerdist_info_v1_block()

int peerdist_info_v1_block ( struct peerdist_info_block * block)
static

Populate content information block.

Parameters
blockContent information block to fill in
Return values
rcReturn status code

Definition at line 350 of file pccrc.c.

350 {
351 const struct peerdist_info_segment *segment = block->segment;
352 const struct peerdist_info *info = segment->info;
353 size_t digestsize = info->digestsize;
355 ssize_t raw_offset;
356 int rc;
357
358 /* Sanity checks */
359 assert ( block->index < segment->blocks );
360
361 /* Calculate start offset of this block */
363 ( block->index * segment->blksize ) );
364
365 /* Calculate end offset of this block */
369
370 /* Locate block description */
372 if ( raw_offset < 0 ) {
373 rc = raw_offset;
374 return rc;
375 }
376
377 /* Get block hash */
378 raw_offset += offsetof ( typeof ( raw ), hash[block->index] );
379 if ( ( rc = peerdist_info_get ( info, block->hash, raw_offset,
380 digestsize ) ) != 0 ) {
381 DBGC ( info, "PCCRC %p segment %d block %d could not get "
382 "hash: %s\n", info, segment->index, block->index,
383 strerror ( rc ) );
384 return rc;
385 }
386
387 return 0;
388}
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
uint32_t start
Starting offset.
Definition netvsc.h:1
uint8_t block[3][8]
DES-encrypted blocks.
Definition mschapv2.h:1
if(natsemi->flags &NATSEMI_64BIT) return 1
uint32_t end
Ending offset.
Definition netvsc.h:7
uint32_t blksize
Cipher block size.
Definition pccrr.h:1
struct pci_range range
PCI bus:dev.fn address range.
Definition pcicloud.c:40
#define offsetof(type, field)
Get offset of a field within a structure.
Definition stddef.h:25

References assert, block, DBGC, digestsize, hash, info, offsetof, peerdist_info_get(), peerdist_info_v1_block_offset(), peerdist_info_v1_block_t, raw, rc, segment, strerror(), and typeof().

◆ peerdist_info_v2_cursor_init()

void peerdist_info_v2_cursor_init ( struct peerdist_info_v2_cursor * cursor)
inlinestatic

Initialise segment cursor.

Parameters
cursorSegment cursor

Definition at line 420 of file pccrc.c.

420 {
421
422 /* Initialise cursor */
423 cursor->offset = ( sizeof ( struct peerdist_info_v2 ) +
424 sizeof ( struct peerdist_info_v2_chunk ) );
425 cursor->remaining = 0;
426 cursor->len = 0;
427}
Content Information version 2 chunk description header.
Definition pccrc.h:231
unsigned int remaining
Number of segments remaining within this chunk.
Definition pccrc.c:409
size_t offset
Raw data offset.
Definition pccrc.c:407
size_t len
Accumulated segment length.
Definition pccrc.c:411
Content Information version 2 data structure header.
Definition pccrc.h:196

References peerdist_info_v2_cursor::len, peerdist_info_v2_cursor::offset, and peerdist_info_v2_cursor::remaining.

Referenced by peerdist_info_v2_segment(), and peerdist_info_v2_segments().

◆ peerdist_info_v2_cursor_next()

int peerdist_info_v2_cursor_next ( const struct peerdist_info * info,
struct peerdist_info_v2_cursor * cursor )
static

Update segment cursor to next segment description.

Parameters
infoContent information
offsetCurrent offset
remainingNumber of segments remaining within this chunk
Return values
rcReturn status code

Definition at line 438 of file pccrc.c.

439 {
440 size_t digestsize = info->digestsize;
442 struct peerdist_info_v2_chunk chunk;
443 int rc;
444
445 /* Get chunk description if applicable */
446 if ( ! cursor->remaining ) {
447
448 /* Get chunk description */
449 if ( ( rc = peerdist_info_get ( info, &chunk,
450 ( cursor->offset -
451 sizeof ( chunk ) ),
452 sizeof ( chunk ) ) ) != 0 )
453 return rc;
454
455 /* Update number of segments remaining */
456 cursor->remaining = ( be32_to_cpu ( chunk.len ) /
457 sizeof ( raw ) );
458 }
459
460 /* Get segment description header */
461 if ( ( rc = peerdist_info_get ( info, &raw.segment, cursor->offset,
462 sizeof ( raw.segment ) ) ) != 0 )
463 return rc;
464
465 /* Update cursor */
466 cursor->offset += sizeof ( raw );
467 cursor->remaining--;
468 if ( ! cursor->remaining )
469 cursor->offset += sizeof ( chunk );
470 cursor->len += be32_to_cpu ( raw.segment.len );
471
472 return 0;
473}
#define be32_to_cpu(value)
Definition byteswap.h:117
#define peerdist_info_v2_segment_t(digestsize)
Content Information version 2 segment description.
Definition pccrc.h:280

References be32_to_cpu, digestsize, info, peerdist_info_v2_chunk::len, peerdist_info_v2_cursor::len, peerdist_info_v2_cursor::offset, peerdist_info_get(), peerdist_info_v2_segment_t, raw, rc, and peerdist_info_v2_cursor::remaining.

Referenced by peerdist_info_v2_segment(), and peerdist_info_v2_segments().

◆ peerdist_info_v2_segments()

int peerdist_info_v2_segments ( const struct peerdist_info * info,
size_t * len )
static

Get number of segments and total length.

Parameters
infoContent information
lenLength to fill in
Return values
rcNumber of segments, or negative error

Definition at line 482 of file pccrc.c.

483 {
484 struct peerdist_info_v2_cursor cursor;
485 unsigned int segments;
486 int rc;
487
488 /* Iterate over all segments */
489 for ( peerdist_info_v2_cursor_init ( &cursor ), segments = 0 ;
490 cursor.offset < info->raw.len ; segments++ ) {
491
492 /* Update segment cursor */
494 &cursor ) ) != 0 ) {
495 DBGC ( info, "PCCRC %p segment %d could not update "
496 "segment cursor: %s\n",
497 info, segments, strerror ( rc ) );
498 return rc;
499 }
500 }
501
502 /* Record accumulated length */
503 *len = cursor.len;
504
505 return segments;
506}
static int peerdist_info_v2_cursor_next(const struct peerdist_info *info, struct peerdist_info_v2_cursor *cursor)
Update segment cursor to next segment description.
Definition pccrc.c:438
static void peerdist_info_v2_cursor_init(struct peerdist_info_v2_cursor *cursor)
Initialise segment cursor.
Definition pccrc.c:420
A segment cursor.
Definition pccrc.c:405

References DBGC, info, len, peerdist_info_v2_cursor::len, peerdist_info_v2_cursor::offset, peerdist_info_v2_cursor_init(), peerdist_info_v2_cursor_next(), rc, and strerror().

Referenced by peerdist_info_v2().

◆ peerdist_info_v2()

int peerdist_info_v2 ( struct peerdist_info * info)
static

Populate content information.

Parameters
infoContent information to fill in
Return values
rcReturn status code

Definition at line 514 of file pccrc.c.

514 {
515 struct peerdist_info_v2 raw;
516 size_t len = 0;
517 int segments;
518 int rc;
519
520 /* Get raw header */
521 if ( ( rc = peerdist_info_get ( info, &raw, 0, sizeof ( raw ) ) ) != 0){
522 DBGC ( info, "PCCRC %p could not get V2 content information: "
523 "%s\n", info, strerror ( rc ) );
524 return rc;
525 }
526 assert ( raw.version.raw == cpu_to_le16 ( PEERDIST_INFO_V2 ) );
527
528 /* Determine hash algorithm */
529 switch ( raw.hash ) {
531 info->digest = &sha512_algorithm;
532 info->digestsize = ( 256 / 8 );
533 break;
534 default:
535 DBGC ( info, "PCCRC %p unsupported hash algorithm %#02x\n",
536 info, raw.hash );
537 return -ENOTSUP;
538 }
539 assert ( info->digest != NULL );
540 DBGC2 ( info, "PCCRC %p using %s[%zd]\n",
541 info, info->digest->name, ( info->digestsize * 8 ) );
542
543 /* Calculate number of segments and total length */
544 segments = peerdist_info_v2_segments ( info, &len );
545 if ( segments < 0 ) {
546 rc = segments;
547 DBGC ( info, "PCCRC %p could not get segment count and length: "
548 "%s\n", info, strerror ( rc ) );
549 return rc;
550 }
551 info->segments = segments;
552
553 /* Calculate range start offset */
554 info->range.start = be64_to_cpu ( raw.offset );
555
556 /* Calculate trimmed range start offset */
557 info->trim.start = ( info->range.start + be32_to_cpu ( raw.first ) );
558
559 /* Calculate range end offset */
560 info->range.end = ( info->range.start + len );
561
562 /* Calculate trimmed range end offset */
563 info->trim.end = ( raw.len ? be64_to_cpu ( raw.len ) :
564 info->range.end );
565
566 return 0;
567}
#define be64_to_cpu(value)
Definition byteswap.h:118
static int peerdist_info_v2_segments(const struct peerdist_info *info, size_t *len)
Get number of segments and total length.
Definition pccrc.c:482
#define PEERDIST_INFO_V2
Content Information version 2.
Definition pccrc.h:49
#define PEERDIST_INFO_V2_HASH_SHA512_TRUNC
SHA-512 hash algorithm with output truncated to first 256 bits.
Definition pccrc.h:225

References assert, be32_to_cpu, be64_to_cpu, cpu_to_le16, DBGC, DBGC2, ENOTSUP, info, len, NULL, peerdist_info_get(), PEERDIST_INFO_V2, PEERDIST_INFO_V2_HASH_SHA512_TRUNC, peerdist_info_v2_segments(), raw, rc, sha512_algorithm, and strerror().

◆ peerdist_info_v2_segment()

int peerdist_info_v2_segment ( struct peerdist_info_segment * segment)
static

Populate content information segment.

Parameters
segmentContent information segment to fill in
Return values
rcReturn status code

Definition at line 575 of file pccrc.c.

575 {
576 const struct peerdist_info *info = segment->info;
577 size_t digestsize = info->digestsize;
579 struct peerdist_info_v2_cursor cursor;
580 unsigned int index;
581 size_t len;
582 int rc;
583
584 /* Sanity checks */
585 assert ( segment->index < info->segments );
586
587 /* Iterate over all segments before the target segment */
588 for ( peerdist_info_v2_cursor_init ( &cursor ), index = 0 ;
589 index < segment->index ; index++ ) {
590
591 /* Update segment cursor */
593 &cursor ) ) != 0 ) {
594 DBGC ( info, "PCCRC %p segment %d could not update "
595 "segment cursor: %s\n",
596 info, index, strerror ( rc ) );
597 return rc;
598 }
599 }
600
601 /* Get raw description */
602 if ( ( rc = peerdist_info_get ( info, &raw, cursor.offset,
603 sizeof ( raw ) ) ) != 0 ) {
604 DBGC ( info, "PCCRC %p segment %d could not get segment "
605 "description: %s\n",
606 info, segment->index, strerror ( rc ) );
607 return rc;
608 }
609
610 /* Calculate start offset of this segment */
611 segment->range.start = ( info->range.start + cursor.len );
612
613 /* Calculate end offset of this segment */
614 len = be32_to_cpu ( raw.segment.len );
615 segment->range.end = ( segment->range.start + len );
616
617 /* Model as a segment containing a single block */
618 segment->blocks = 1;
619 segment->blksize = len;
620
621 /* Calculate segment hashes */
622 peerdist_info_segment_hash ( segment, raw.hash, raw.secret );
623
624 return 0;
625}

References assert, be32_to_cpu, DBGC, digestsize, index, info, len, peerdist_info_v2_cursor::len, peerdist_info_v2_cursor::offset, peerdist_info_get(), peerdist_info_segment_hash(), peerdist_info_v2_cursor_init(), peerdist_info_v2_cursor_next(), peerdist_info_v2_segment_t, raw, rc, segment, and strerror().

◆ peerdist_info_v2_block()

int peerdist_info_v2_block ( struct peerdist_info_block * block)
static

Populate content information block.

Parameters
blockContent information block to fill in
Return values
rcReturn status code

Definition at line 633 of file pccrc.c.

633 {
634 const struct peerdist_info_segment *segment = block->segment;
635 const struct peerdist_info *info = segment->info;
636 size_t digestsize = info->digestsize;
637
638 /* Sanity checks */
639 assert ( block->index < segment->blocks );
640
641 /* Model as a block covering the whole segment */
642 memcpy ( &block->range, &segment->range, sizeof ( block->range ) );
643 memcpy ( block->hash, segment->hash, digestsize );
644
645 return 0;
646}

References assert, block, digestsize, info, memcpy(), and segment.

◆ peerdist_info()

int peerdist_info ( const void * data,
size_t len,
struct peerdist_info * info )

Populate content information.

Parameters
dataRaw data
lenLength of raw data
infoContent information to fill in
Return values
rcReturn status code

Definition at line 670 of file pccrc.c.

671 {
673 int rc;
674
675 /* Initialise structure */
676 memset ( info, 0, sizeof ( *info ) );
677 info->raw.data = data;
678 info->raw.len = len;
679
680 /* Get version */
681 if ( ( rc = peerdist_info_get ( info, &version, 0,
682 sizeof ( version ) ) ) != 0 ) {
683 DBGC ( info, "PCCRC %p could not get version: %s\n",
684 info, strerror ( rc ) );
685 return rc;
686 }
687 DBGC2 ( info, "PCCRC %p version %d.%d\n",
688 info, version.major, version.minor );
689
690 /* Determine version */
691 switch ( version.raw ) {
694 break;
697 break;
698 default:
699 DBGC ( info, "PCCRC %p unsupported version %d.%d\n",
700 info, version.major, version.minor );
701 return -ENOTSUP;
702 }
703 assert ( info->op != NULL );
704 assert ( info->op->info != NULL );
705
706 /* Populate content information */
707 if ( ( rc = info->op->info ( info ) ) != 0 )
708 return rc;
709
710 DBGC2 ( info, "PCCRC %p range [%08zx,%08zx) covers [%08zx,%08zx) with "
711 "%d segments\n", info, info->range.start, info->range.end,
712 info->trim.start, info->trim.end, info->segments );
713 return 0;
714}
u32 version
Driver version.
Definition ath9k_hw.c:1985
void * memset(void *dest, int character, size_t len) __nonnull
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
static struct peerdist_info_operations peerdist_info_v1_operations
Content information version 1 operations.
Definition pccrc.c:391
static struct peerdist_info_operations peerdist_info_v2_operations
Content information version 2 operations.
Definition pccrc.c:649
Content Information version number.
Definition pccrc.h:28

References assert, cpu_to_le16, data, DBGC, DBGC2, ENOTSUP, info, len, memset(), NULL, peerdist_info_get(), PEERDIST_INFO_V1, peerdist_info_v1_operations, PEERDIST_INFO_V2, peerdist_info_v2_operations, rc, strerror(), and version.

◆ peerdist_info_segment()

int peerdist_info_segment ( const struct peerdist_info * info,
struct peerdist_info_segment * segment,
unsigned int index )

Populate content information segment.

Parameters
infoContent information
segmentContent information segment to fill in
indexSegment index
Return values
rcReturn status code

Definition at line 724 of file pccrc.c.

726 {
727 int rc;
728
729 /* Sanity checks */
730 assert ( info != NULL );
731 assert ( info->op != NULL );
732 assert ( info->op->segment != NULL );
733 if ( index >= info->segments ) {
734 DBGC ( info, "PCCRC %p segment %d of [0,%d) out of range\n",
735 info, index, info->segments );
736 return -ERANGE;
737 }
738
739 /* Initialise structure */
740 memset ( segment, 0, sizeof ( *segment ) );
741 segment->info = info;
742 segment->index = index;
743
744 /* Populate content information segment */
745 if ( ( rc = info->op->segment ( segment ) ) != 0 )
746 return rc;
747
748 DBGC2 ( info, "PCCRC %p segment %d range [%08zx,%08zx) with %d "
749 "blocks\n", info, segment->index, segment->range.start,
750 segment->range.end, segment->blocks );
751 DBGC2 ( info, "PCCRC %p segment %d digest %s\n", info, segment->index,
753 DBGC2 ( info, "PCCRC %p segment %d secret %s\n", info, segment->index,
754 peerdist_info_hash_ntoa ( info, segment->secret ) );
755 DBGC2 ( info, "PCCRC %p segment %d identf %s\n", info, segment->index,
757 return 0;
758}
static const char * peerdist_info_hash_ntoa(const struct peerdist_info *info, const void *hash)
Transcribe hash value (for debugging)
Definition pccrc.c:56

References assert, DBGC, DBGC2, ERANGE, index, info, memset(), NULL, peerdist_info_hash_ntoa(), rc, and segment.

◆ peerdist_info_block()

int peerdist_info_block ( const struct peerdist_info_segment * segment,
struct peerdist_info_block * block,
unsigned int index )

Populate content information block.

Parameters
segmentContent information segment
blockContent information block to fill in
indexBlock index
Return values
rcReturn status code

Definition at line 768 of file pccrc.c.

770 {
771 const struct peerdist_info *info = segment->info;
772 size_t start;
773 size_t end;
774 int rc;
775
776 /* Sanity checks */
777 assert ( segment != NULL );
778 assert ( info != NULL );
779 assert ( info->op != NULL );
780 assert ( info->op->block != NULL );
781 if ( index >= segment->blocks ) {
782 DBGC ( info, "PCCRC %p segment %d block %d of [0,%d) out of "
783 "range\n", info, segment->index, index, segment->blocks);
784 return -ERANGE;
785 }
786
787 /* Initialise structure */
788 memset ( block, 0, sizeof ( *block ) );
789 block->segment = segment;
790 block->index = index;
791
792 /* Populate content information block */
793 if ( ( rc = info->op->block ( block ) ) != 0 )
794 return rc;
795
796 /* Calculate trimmed range */
797 start = block->range.start;
799 start = info->trim.start;
800 end = block->range.end;
801 if ( end > info->trim.end )
802 end = info->trim.end;
803 if ( end < start )
804 end = start;
805 block->trim.start = start;
806 block->trim.end = end;
807
808 DBGC2 ( info, "PCCRC %p segment %d block %d hash %s\n",
809 info, segment->index, block->index,
811 DBGC2 ( info, "PCCRC %p segment %d block %d range [%08zx,%08zx) covers "
812 "[%08zx,%08zx)\n", info, segment->index, block->index,
813 block->range.start, block->range.end, block->trim.start,
814 block->trim.end );
815 return 0;
816}
struct peerdist_range trim
Trimmed content range.
Definition pccrc.h:341
size_t start
Start offset.
Definition pccrc.h:311

References assert, block, DBGC, DBGC2, end, ERANGE, index, info, memset(), NULL, peerdist_info_hash_ntoa(), rc, segment, peerdist_range::start, start, and peerdist_info::trim.

Variable Documentation

◆ peerdist_info_v1_operations

struct peerdist_info_operations peerdist_info_v1_operations
static
Initial value:
= {
}
Content Information version 1 segment description header.
Definition pccrc.h:109

Content information version 1 operations.

Definition at line 391 of file pccrc.c.

391 {
392 .info = peerdist_info_v1,
393 .segment = peerdist_info_v1_segment,
394 .block = peerdist_info_v1_block,
395};

Referenced by peerdist_info().

◆ peerdist_info_v2_operations

struct peerdist_info_operations peerdist_info_v2_operations
static
Initial value:
= {
}
static int peerdist_info_v2_block(struct peerdist_info_block *block)
Populate content information block.
Definition pccrc.c:633
Content Information version 2 segment description header.
Definition pccrc.h:263

Content information version 2 operations.

Definition at line 649 of file pccrc.c.

649 {
650 .block = peerdist_info_v2_block,
651 .segment = peerdist_info_v2_segment,
652 .info = peerdist_info_v2,
653};

Referenced by peerdist_info().