00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef HAVE_CONFIG_H
00018 # include <dtn-config.h>
00019 #endif
00020
00021 #include <string>
00022 #include <sys/types.h>
00023 #include <netinet/in.h>
00024
00025 #include "Bundle.h"
00026 #include "BundleProtocol.h"
00027 #include "PrimaryBlockProcessor.h"
00028 #include "naming/EndpointID.h"
00029 #include "SDNV.h"
00030
00031 namespace dtn {
00032
00033
00034 PrimaryBlockProcessor::PrimaryBlockProcessor()
00035 : BlockProcessor(BundleProtocol::PRIMARY_BLOCK)
00036 {
00037 }
00038
00039
00040 u_int64_t
00041 PrimaryBlockProcessor::format_bundle_flags(const Bundle* bundle)
00042 {
00043 u_int64_t flags = 0;
00044
00045 if (bundle->is_fragment()) {
00046 flags |= BUNDLE_IS_FRAGMENT;
00047 }
00048
00049 if (bundle->is_admin()) {
00050 flags |= BUNDLE_IS_ADMIN;
00051 }
00052
00053 if (bundle->do_not_fragment()) {
00054 flags |= BUNDLE_DO_NOT_FRAGMENT;
00055 }
00056
00057 if (bundle->custody_requested()) {
00058 flags |= BUNDLE_CUSTODY_XFER_REQUESTED;
00059 }
00060
00061 if (bundle->singleton_dest()) {
00062 flags |= BUNDLE_SINGLETON_DESTINATION;
00063 }
00064
00065 if (bundle->app_acked_rcpt()) {
00066 flags |= BUNDLE_ACK_BY_APP;
00067 }
00068
00069 return flags;
00070 }
00071
00072
00073 void
00074 PrimaryBlockProcessor::parse_bundle_flags(Bundle* bundle, u_int64_t flags)
00075 {
00076 if (flags & BUNDLE_IS_FRAGMENT) {
00077 bundle->set_is_fragment(true);
00078 } else {
00079 bundle->set_is_fragment(false);
00080 }
00081
00082 if (flags & BUNDLE_IS_ADMIN) {
00083 bundle->set_is_admin(true);
00084 } else {
00085 bundle->set_is_admin(false);
00086 }
00087
00088 if (flags & BUNDLE_DO_NOT_FRAGMENT) {
00089 bundle->set_do_not_fragment(true);
00090 } else {
00091 bundle->set_do_not_fragment(false);
00092 }
00093
00094 if (flags & BUNDLE_CUSTODY_XFER_REQUESTED) {
00095 bundle->set_custody_requested(true);
00096 } else {
00097 bundle->set_custody_requested(false);
00098 }
00099
00100 if (flags & BUNDLE_SINGLETON_DESTINATION) {
00101 bundle->set_singleton_dest(true);
00102 } else {
00103 bundle->set_singleton_dest(false);
00104 }
00105
00106 if (flags & BUNDLE_ACK_BY_APP) {
00107 bundle->set_app_acked_rcpt(true);
00108 } else {
00109 bundle->set_app_acked_rcpt(false);
00110 }
00111 }
00112
00113
00114 u_int64_t
00115 PrimaryBlockProcessor::format_cos_flags(const Bundle* b)
00116 {
00117 u_int64_t cos_flags = 0;
00118
00119 cos_flags = ((b->priority() & 0x3) << 7);
00120
00121 return cos_flags;
00122 }
00123
00124
00125 void
00126 PrimaryBlockProcessor::parse_cos_flags(Bundle* b, u_int64_t cos_flags)
00127 {
00128 b->set_priority((cos_flags >> 7) & 0x3);
00129 }
00130
00131
00132 u_int64_t
00133 PrimaryBlockProcessor::format_srr_flags(const Bundle* b)
00134 {
00135 u_int64_t srr_flags = 0;
00136
00137 if (b->receive_rcpt())
00138 srr_flags |= BundleProtocol::STATUS_RECEIVED;
00139
00140 if (b->custody_rcpt())
00141 srr_flags |= BundleProtocol::STATUS_CUSTODY_ACCEPTED;
00142
00143 if (b->forward_rcpt())
00144 srr_flags |= BundleProtocol::STATUS_FORWARDED;
00145
00146 if (b->delivery_rcpt())
00147 srr_flags |= BundleProtocol::STATUS_DELIVERED;
00148
00149 if (b->deletion_rcpt())
00150 srr_flags |= BundleProtocol::STATUS_DELETED;
00151
00152 return srr_flags;
00153 }
00154
00155
00156 void
00157 PrimaryBlockProcessor::parse_srr_flags(Bundle* b, u_int64_t srr_flags)
00158 {
00159 if (srr_flags & BundleProtocol::STATUS_RECEIVED)
00160 b->set_receive_rcpt(true);
00161
00162 if (srr_flags & BundleProtocol::STATUS_CUSTODY_ACCEPTED)
00163 b->set_custody_rcpt(true);
00164
00165 if (srr_flags & BundleProtocol::STATUS_FORWARDED)
00166 b->set_forward_rcpt(true);
00167
00168 if (srr_flags & BundleProtocol::STATUS_DELIVERED)
00169 b->set_delivery_rcpt(true);
00170
00171 if (srr_flags & BundleProtocol::STATUS_DELETED)
00172 b->set_deletion_rcpt(true);
00173 }
00174
00175
00176 size_t
00177 PrimaryBlockProcessor::get_primary_len(const Bundle* bundle,
00178 Dictionary* dict,
00179 PrimaryBlock* primary)
00180 {
00181 static const char* log = "/dtn/bundle/protocol";
00182 size_t primary_len = 0;
00183 primary->dictionary_length = 0;
00184 primary->block_length = 0;
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 dict->get_offsets(bundle->dest(),
00197 &primary->dest_scheme_offset,
00198 &primary->dest_ssp_offset);
00199 primary->block_length += SDNV::encoding_len(primary->dest_scheme_offset);
00200 primary->block_length += SDNV::encoding_len(primary->dest_ssp_offset);
00201
00202 dict->get_offsets(bundle->source(),
00203 &primary->source_scheme_offset,
00204 &primary->source_ssp_offset);
00205 primary->block_length += SDNV::encoding_len(primary->source_scheme_offset);
00206 primary->block_length += SDNV::encoding_len(primary->source_ssp_offset);
00207
00208 dict->get_offsets(bundle->replyto(),
00209 &primary->replyto_scheme_offset,
00210 &primary->replyto_ssp_offset);
00211 primary->block_length += SDNV::encoding_len(primary->replyto_scheme_offset);
00212 primary->block_length += SDNV::encoding_len(primary->replyto_ssp_offset);
00213
00214 dict->get_offsets(bundle->custodian(),
00215 &primary->custodian_scheme_offset,
00216 &primary->custodian_ssp_offset);
00217 primary->block_length += SDNV::encoding_len(primary->custodian_scheme_offset);
00218 primary->block_length += SDNV::encoding_len(primary->custodian_ssp_offset);
00219
00220 primary->dictionary_length = dict->length();
00221
00222 (void)log;
00223 log_debug_p(log, "generated dictionary length %llu",
00224 U64FMT(primary->dictionary_length));
00225
00226 primary->block_length += SDNV::encoding_len(bundle->creation_ts().seconds_);
00227 primary->block_length += SDNV::encoding_len(bundle->creation_ts().seqno_);
00228 primary->block_length += SDNV::encoding_len(bundle->expiration());
00229
00230 primary->block_length += SDNV::encoding_len(primary->dictionary_length);
00231 primary->block_length += primary->dictionary_length;
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 if (bundle->is_fragment()) {
00242 primary->block_length += SDNV::encoding_len(bundle->frag_offset());
00243 primary->block_length += SDNV::encoding_len(bundle->orig_length());
00244 }
00245
00246
00247 primary->processing_flags = format_bundle_flags(bundle);
00248 primary->processing_flags |= format_cos_flags(bundle);
00249 primary->processing_flags |= format_srr_flags(bundle);
00250
00251
00252
00253
00254
00255 primary_len = 1 + SDNV::encoding_len(primary->processing_flags) +
00256 SDNV::encoding_len(primary->block_length) +
00257 primary->block_length;
00258
00259 log_debug_p(log, "get_primary_len(bundle %d): %zu",
00260 bundle->bundleid(), primary_len);
00261
00262
00263
00264 primary->version = BundleProtocol::CURRENT_VERSION;
00265 primary->creation_time = bundle->creation_ts().seconds_;
00266 primary->creation_sequence = bundle->creation_ts().seqno_;
00267 primary->lifetime = bundle->expiration();
00268
00269 return primary_len;
00270 }
00271
00272
00273 int
00274 PrimaryBlockProcessor::prepare(const Bundle* bundle,
00275 BlockInfoVec* xmit_blocks,
00276 const BlockInfo* source,
00277 const LinkRef& link,
00278 list_owner_t list)
00279 {
00280 (void)bundle;
00281 (void)link;
00282 (void)list;
00283
00284
00285 ASSERT(xmit_blocks->size() == 0);
00286
00287
00288 xmit_blocks->dict()->add_eid(bundle->dest());
00289 xmit_blocks->dict()->add_eid(bundle->source());
00290 xmit_blocks->dict()->add_eid(bundle->replyto());
00291 xmit_blocks->dict()->add_eid(bundle->custodian());
00292
00293
00294 xmit_blocks->insert(xmit_blocks->begin(), BlockInfo(this, source));
00295
00296 return BP_SUCCESS;
00297 }
00298
00299
00300 int
00301 PrimaryBlockProcessor::consume(Bundle* bundle,
00302 BlockInfo* block,
00303 u_char* buf,
00304 size_t len)
00305 {
00306 static const char* log = "/dtn/bundle/protocol";
00307 size_t consumed = 0;
00308 PrimaryBlock primary;
00309
00310 ASSERT(! block->complete());
00311
00312 Dictionary* dict = bundle->mutable_recv_blocks()->dict();
00313 memset(&primary, 0, sizeof(primary));
00314
00315
00316
00317
00318
00319
00320 int cc = BlockProcessor::consume(bundle, block, buf, len);
00321
00322 if (cc == -1) {
00323 return -1;
00324 }
00325
00326 if (! block->complete()) {
00327 ASSERT(cc == (int)len);
00328 return consumed + cc;
00329 }
00330
00331
00332
00333
00334
00335
00336 consumed += cc;
00337
00338 size_t primary_len = block->full_length();
00339
00340 buf = block->writable_contents()->buf();
00341 len = block->writable_contents()->len();
00342
00343 ASSERT(primary_len == len);
00344
00345 primary.version = *(u_int8_t*)buf;
00346 buf += 1;
00347 len -= 1;
00348
00349 if (primary.version != BundleProtocol::CURRENT_VERSION) {
00350 log_warn_p(log, "protocol version mismatch %d != %d",
00351 primary.version, BundleProtocol::CURRENT_VERSION);
00352 return -1;
00353 }
00354
00355 #define PBP_READ_SDNV(location) { \
00356 int sdnv_len = SDNV::decode(buf, len, location); \
00357 if (sdnv_len < 0) \
00358 goto tooshort; \
00359 buf += sdnv_len; \
00360 len -= sdnv_len; }
00361
00362
00363 PBP_READ_SDNV(&primary.processing_flags);
00364 PBP_READ_SDNV(&primary.block_length);
00365
00366 log_debug_p(log, "parsed primary block: version %d length %u",
00367 primary.version, block->data_length());
00368
00369
00370 parse_bundle_flags(bundle, primary.processing_flags);
00371 parse_cos_flags(bundle, primary.processing_flags);
00372 parse_srr_flags(bundle, primary.processing_flags);
00373
00374
00375
00376 ASSERT(len == block->data_length());
00377
00378
00379 PBP_READ_SDNV(&primary.dest_scheme_offset);
00380 PBP_READ_SDNV(&primary.dest_ssp_offset);
00381 PBP_READ_SDNV(&primary.source_scheme_offset);
00382 PBP_READ_SDNV(&primary.source_ssp_offset);
00383 PBP_READ_SDNV(&primary.replyto_scheme_offset);
00384 PBP_READ_SDNV(&primary.replyto_ssp_offset);
00385 PBP_READ_SDNV(&primary.custodian_scheme_offset);
00386 PBP_READ_SDNV(&primary.custodian_ssp_offset);
00387 PBP_READ_SDNV(&primary.creation_time);
00388 PBP_READ_SDNV(&primary.creation_sequence);
00389 PBP_READ_SDNV(&primary.lifetime);
00390 PBP_READ_SDNV(&primary.dictionary_length);
00391
00392
00393
00394 if (primary.creation_time > 0xffffffff) {
00395 log_err_p(log, "creation timestamp time is too large: %llu",
00396 U64FMT(primary.creation_time));
00397 return -1;
00398 }
00399
00400 if (primary.creation_sequence > 0xffffffff) {
00401 log_err_p(log, "creation timestamp sequence is too large: %llu",
00402 U64FMT(primary.creation_sequence));
00403 return -1;
00404 }
00405
00406 if (primary.lifetime > 0xffffffff) {
00407 log_err_p(log, "lifetime is too large: %llu", U64FMT(primary.lifetime));
00408 return -1;
00409 }
00410
00411 bundle->set_creation_ts(BundleTimestamp(primary.creation_time,
00412 primary.creation_sequence));
00413 bundle->set_expiration(primary.lifetime);
00414
00415
00416
00417
00418 if (len < primary.dictionary_length) {
00419 tooshort:
00420 log_err_p(log, "primary block advertised incorrect length %u",
00421 block->data_length());
00422 return -1;
00423 }
00424
00425
00426
00427
00428 if (buf[primary.dictionary_length - 1] != '\0') {
00429 log_err_p(log, "dictionary does not end with a NULL character!");
00430 return -1;
00431 }
00432
00433
00434
00435
00436
00437
00438 u_char* dictionary = buf;
00439 buf += primary.dictionary_length;
00440 len -= primary.dictionary_length;
00441
00442 dict->set_dict(dictionary, primary.dictionary_length);
00443 dict->extract_eid(bundle->mutable_source(),
00444 primary.source_scheme_offset,
00445 primary.source_ssp_offset);
00446
00447 dict->extract_eid(bundle->mutable_dest(),
00448 primary.dest_scheme_offset,
00449 primary.dest_ssp_offset);
00450
00451 dict->extract_eid(bundle->mutable_replyto(),
00452 primary.replyto_scheme_offset,
00453 primary.replyto_ssp_offset);
00454
00455 dict->extract_eid(bundle->mutable_custodian(),
00456 primary.custodian_scheme_offset,
00457 primary.custodian_ssp_offset);
00458
00459
00460
00461 if (bundle->is_fragment()) {
00462 u_int64_t sdnv_buf = 0;
00463 PBP_READ_SDNV(&sdnv_buf);
00464 if (sdnv_buf > 0xffffffff) {
00465 log_err_p(log, "fragment offset is too large: %llu",
00466 U64FMT(sdnv_buf));
00467 return -1;
00468 }
00469
00470 bundle->set_frag_offset(sdnv_buf);
00471 sdnv_buf = 0;
00472
00473 PBP_READ_SDNV(&sdnv_buf);
00474 if (sdnv_buf > 0xffffffff) {
00475 log_err_p(log, "fragment original length is too large: %llu",
00476 U64FMT(sdnv_buf));
00477 return -1;
00478 }
00479
00480 bundle->set_orig_length(sdnv_buf);
00481
00482 log_debug_p(log, "parsed fragmentation info: offset %u orig_len %u",
00483 bundle->frag_offset(), bundle->orig_length());
00484 }
00485
00486 #undef PBP_READ_SDNV
00487
00488 return consumed;
00489 }
00490
00491
00492 bool
00493 PrimaryBlockProcessor::validate(const Bundle* bundle,
00494 BlockInfoVec* block_list,
00495 BlockInfo* block,
00496 status_report_reason_t* reception_reason,
00497 status_report_reason_t* deletion_reason)
00498 {
00499 (void)block_list;
00500 (void)block;
00501 (void)reception_reason;
00502 static const char* log = "/dtn/bundle/protocol";
00503
00504
00505 bool eids_valid = true;
00506 eids_valid &= bundle->source().valid();
00507 eids_valid &= bundle->dest().valid();
00508 eids_valid &= bundle->custodian().valid();
00509 eids_valid &= bundle->replyto().valid();
00510
00511 if (!eids_valid) {
00512 log_err_p(log, "bad value for one or more EIDs");
00513 *deletion_reason = BundleProtocol::REASON_BLOCK_UNINTELLIGIBLE;
00514 return false;
00515 }
00516
00517
00518
00519
00520 if (bundle->source() == EndpointID::NULL_EID()) {
00521 if (bundle->receipt_requested() || bundle->app_acked_rcpt()) {
00522 log_err_p(log,
00523 "bundle with null source eid has requested a "
00524 "report; reject it");
00525 *deletion_reason = BundleProtocol::REASON_BLOCK_UNINTELLIGIBLE;
00526 return false;
00527 }
00528
00529 if (bundle->custody_requested()) {
00530 log_err_p(log,
00531 "bundle with null source eid has requested custody "
00532 "transfer; reject it");
00533 *deletion_reason = BundleProtocol::REASON_BLOCK_UNINTELLIGIBLE;
00534 return false;
00535 }
00536
00537 if (!bundle->do_not_fragment()) {
00538 log_err_p(log,
00539 "bundle with null source eid has not set "
00540 "'do-not-fragment' flag; reject it");
00541 *deletion_reason = BundleProtocol::REASON_BLOCK_UNINTELLIGIBLE;
00542 return false;
00543 }
00544 }
00545
00546
00547 if (bundle->is_admin()) {
00548 if (bundle->custody_requested()) {
00549 log_err_p(log,
00550 "admin bundle requested custody transfer; "
00551 "reject it");
00552 *deletion_reason = BundleProtocol::REASON_BLOCK_UNINTELLIGIBLE;
00553 return false;
00554 }
00555
00556 if ( bundle->receive_rcpt() ||
00557 bundle->custody_rcpt() ||
00558 bundle->forward_rcpt() ||
00559 bundle->delivery_rcpt() ||
00560 bundle->deletion_rcpt() ||
00561 bundle->app_acked_rcpt() )
00562 {
00563 log_err_p(log, "admin bundle has requested a report; reject it");
00564 *deletion_reason = BundleProtocol::REASON_BLOCK_UNINTELLIGIBLE;
00565 return false;
00566 }
00567 }
00568
00569 return true;
00570 }
00571
00572
00573 int
00574 PrimaryBlockProcessor::generate(const Bundle* bundle,
00575 BlockInfoVec* xmit_blocks,
00576 BlockInfo* block,
00577 const LinkRef& link,
00578 bool last)
00579 {
00580 (void)bundle;
00581 (void)link;
00582 (void)xmit_blocks;
00583 (void)block;
00584
00585
00586
00587
00588 ASSERT(!last);
00589
00590 return BP_SUCCESS;
00591 }
00592
00593
00594 void
00595 PrimaryBlockProcessor::generate_primary(const Bundle* bundle,
00596 BlockInfoVec* xmit_blocks,
00597 BlockInfo* block)
00598 {
00599 static const char* log = "/dtn/bundle/protocol";
00600
00601 Dictionary* dict = xmit_blocks->dict();
00602 size_t primary_len = 0;
00603 PrimaryBlock primary;
00604
00605 memset(&primary, 0, sizeof(primary));
00606
00607
00608
00609
00610 primary_len = get_primary_len(bundle, dict, &primary);
00611 block->writable_contents()->reserve(primary_len);
00612 block->writable_contents()->set_len(primary_len);
00613 block->set_data_length(primary_len);
00614
00615
00616
00617
00618 u_char* buf = block->writable_contents()->buf();
00619 int len = primary_len;
00620
00621 (void)log;
00622 log_debug_p(log, "generating primary: length %zu", primary_len);
00623
00624
00625 *buf = BundleProtocol::CURRENT_VERSION;
00626 ++buf;
00627 --len;
00628
00629 #define PBP_WRITE_SDNV(value) { \
00630 int sdnv_len = SDNV::encode(value, buf, len); \
00631 ASSERT(sdnv_len > 0); \
00632 buf += sdnv_len; \
00633 len -= sdnv_len; }
00634
00635
00636 PBP_WRITE_SDNV(primary.processing_flags);
00637 PBP_WRITE_SDNV(primary.block_length);
00638 PBP_WRITE_SDNV(primary.dest_scheme_offset);
00639 PBP_WRITE_SDNV(primary.dest_ssp_offset);
00640 PBP_WRITE_SDNV(primary.source_scheme_offset);
00641 PBP_WRITE_SDNV(primary.source_ssp_offset);
00642 PBP_WRITE_SDNV(primary.replyto_scheme_offset);
00643 PBP_WRITE_SDNV(primary.replyto_ssp_offset);
00644 PBP_WRITE_SDNV(primary.custodian_scheme_offset);
00645 PBP_WRITE_SDNV(primary.custodian_ssp_offset);
00646 PBP_WRITE_SDNV(bundle->creation_ts().seconds_);
00647 PBP_WRITE_SDNV(bundle->creation_ts().seqno_);
00648 PBP_WRITE_SDNV(bundle->expiration());
00649 PBP_WRITE_SDNV(primary.dictionary_length);
00650
00651
00652 memcpy(buf, dict->dict(), dict->length());
00653 buf += dict->length();
00654 len -= dict->length();
00655
00656
00657
00658
00659
00660 if (bundle->is_fragment()) {
00661 PBP_WRITE_SDNV(bundle->frag_offset());
00662 PBP_WRITE_SDNV(bundle->orig_length());
00663 }
00664
00665 #undef PBP_WRITE_SDNV
00666
00667
00668
00669
00670
00671
00672 ASSERT(len == 0);
00673 }
00674
00675
00676 }