Ejemplo n.º 1
0
int
add_signature(unsigned char *out, char *private_key_path,
              unsigned char *file, unsigned int fsize)
{
    int len;

    unsigned char sig[2048];
    unsigned int sig_len;

    len = ccnl_ccnb_mkHeader(out, CCN_DTAG_SIGNATURE, CCN_TT_DTAG);
    len += ccnl_ccnb_mkStrBlob(out + len, CCN_DTAG_NAME, CCN_TT_DTAG, "SHA256");
    len += ccnl_ccnb_mkStrBlob(out + len, CCN_DTAG_WITNESS, CCN_TT_DTAG, "");

    if(!sign(private_key_path, (unsigned char*)file, fsize, (unsigned char*)sig, &sig_len)) return 0;
    //printf("SIGLEN: %d\n",sig_len);
    sig[sig_len]=0;

    //add signaturebits bits...
    len += ccnl_ccnb_mkHeader(out + len, CCN_DTAG_SIGNATUREBITS, CCN_TT_DTAG);
    len += ccnl_ccnb_addBlob(out + len, (char*)sig, sig_len);
    out[len++] = 0; // end signaturebits

    out[len++] = 0; // end signature

    /*char *publickey = "/home/blacksheeep/.ssh/publickey.pem";
    int verified = verify(publickey, file, fsize, sig, sig_len);
    printf("Verified: %d\n", verified);*/

    return len;
}
Ejemplo n.º 2
0
int
mkEchoserverRequest(unsigned char *out, char *path, int suite,
                    char *private_key_path)
{
    int len = 0, len1 = 0, len2 = 0, len3 = 0;
    unsigned char out1[CCNL_MAX_PACKET_SIZE];
    unsigned char contentobj[2000];
    unsigned char fwdentry[2000];
    char suite_s[1];
    char *cp;

    DEBUGMSG(DEBUG, "mkEchoserverRequest uri=%s suite=%d\n", path, suite);

    len = ccnl_ccnb_mkHeader(out, CCN_DTAG_INTEREST, CCN_TT_DTAG);   // interest
    len += ccnl_ccnb_mkHeader(out+len, CCN_DTAG_NAME, CCN_TT_DTAG);  // name

    len1 += ccnl_ccnb_mkStrBlob(out1+len1, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "ccnx");
    len1 += ccnl_ccnb_mkStrBlob(out1+len1, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "");
    len1 += ccnl_ccnb_mkStrBlob(out1+len1, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "echoserver");

    // prepare FWDENTRY
    len3 = ccnl_ccnb_mkHeader(fwdentry, CCN_DTAG_FWDINGENTRY, CCN_TT_DTAG);
    len3 += ccnl_ccnb_mkStrBlob(fwdentry+len3, CCN_DTAG_ACTION, CCN_TT_DTAG, "echoserver");
    len3 += ccnl_ccnb_mkHeader(fwdentry+len3, CCN_DTAG_NAME, CCN_TT_DTAG); // prefix

    cp = strtok(path, "/");
    while (cp) {
        unsigned short cmplen = strlen(cp);
#ifdef USE_SUITE_CCNTLV
        if (suite == CCNL_SUITE_CCNTLV) {
            char* oldcp = cp;
            cp = malloc( (cmplen + 4) * (sizeof(char)) );
            cp[0] = CCNX_TLV_N_NameSegment >> 8;
            cp[1] = CCNX_TLV_N_NameSegment;
            cp[2] = cmplen >> 8;
            cp[3] = cmplen;
            memcpy(cp + 4, oldcp, cmplen);
            cmplen += 4;
        }
#endif
#ifdef USE_SUITE_CISTLV
        if (suite == CCNL_SUITE_CISTLV) {
            char* oldcp = cp;
            cp = malloc( (cmplen + 4) * (sizeof(char)) );
            cp[0] = CISCO_TLV_NameComponent >> 8;
            cp[1] = CISCO_TLV_NameComponent;
            cp[2] = cmplen >> 8;
            cp[3] = cmplen;
            memcpy(cp + 4, oldcp, cmplen);
            cmplen += 4;
        }
Ejemplo n.º 3
0
int
ccnl_ccnb_mkInterest(struct ccnl_prefix_s *name, char *minSuffix,
                     const char *maxSuffix, unsigned char *digest, int dlen,
                     unsigned char *publisher, int plen, char *scope,
                     uint32_t *nonce, unsigned char *out)
{
    int len, i, k;

    len = ccnl_ccnb_mkHeader(out, CCN_DTAG_INTEREST, CCN_TT_DTAG);   // interest

    len += ccnl_ccnb_mkHeader(out+len, CCN_DTAG_NAME, CCN_TT_DTAG);  // name
    for (i = 0; i < name->compcnt; i++) {
        len += ccnl_ccnb_mkHeader(out+len, CCN_DTAG_COMPONENT, CCN_TT_DTAG); // comp
        k = name->complen[i];
        len += ccnl_ccnb_mkHeader(out+len, k, CCN_TT_BLOB);
        memcpy(out+len, name->comp[i], k);
        len += k;
        out[len++] = 0; // end-of-component
    }
    if (digest) {
        len += ccnl_ccnb_mkField(out + len, CCN_DTAG_COMPONENT,
                                 CCN_TT_BLOB, digest, dlen);
        if (!maxSuffix)
            maxSuffix = "0";
    }
    out[len++] = 0; // end-of-name

    if (minSuffix)
        len += ccnl_ccnb_mkField(out + len, CCN_DTAG_MINSUFFCOMP,
                                 CCN_TT_UDATA, (unsigned char*) minSuffix,
                                 strlen(minSuffix));
    if (maxSuffix)
        len += ccnl_ccnb_mkField(out + len, CCN_DTAG_MAXSUFFCOMP,
                                 CCN_TT_UDATA, (unsigned char*) maxSuffix,
                                 strlen(maxSuffix));
    if (publisher)
        len += ccnl_ccnb_mkField(out + len, CCN_DTAG_PUBPUBKDIGEST,
                                 CCN_TT_BLOB, publisher, plen);
    if (scope)
        len += ccnl_ccnb_mkField(out + len, CCN_DTAG_SCOPE,
                                 CCN_TT_UDATA, (unsigned char*) scope,
                                 strlen(scope));
    if (nonce)
        len += ccnl_ccnb_mkField(out + len, CCN_DTAG_NONCE,
                                 CCN_TT_UDATA, (unsigned char*) nonce,
                                 sizeof(*nonce));

    out[len++] = 0; // end-of-interest

    return len;
}
Ejemplo n.º 4
0
int
mkNewEthDevRequest(unsigned char *out, char *devname, char *ethtype,
           char *frag, char *flags, char *private_key_path)
{
    int len = 0, len1 = 0, len2 = 0, len3 = 0;
    unsigned char out1[CCNL_MAX_PACKET_SIZE];
    unsigned char contentobj[2000];
    unsigned char faceinst[2000];

    len = ccnl_ccnb_mkHeader(out, CCN_DTAG_INTEREST, CCN_TT_DTAG);   // interest
    len += ccnl_ccnb_mkHeader(out+len, CCN_DTAG_NAME, CCN_TT_DTAG);  // name

    len1 += ccnl_ccnb_mkStrBlob(out1+len1, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "ccnx");
    len1 += ccnl_ccnb_mkStrBlob(out1+len1, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "");
    len1 += ccnl_ccnb_mkStrBlob(out1+len1, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "newdev");

    // prepare DEVINSTANCE
    len3 = ccnl_ccnb_mkHeader(faceinst, CCNL_DTAG_DEVINSTANCE, CCN_TT_DTAG);
    len3 += ccnl_ccnb_mkStrBlob(faceinst+len3, CCN_DTAG_ACTION, CCN_TT_DTAG, "newdev");
    if (devname)
        len3 += ccnl_ccnb_mkStrBlob(faceinst+len3, CCNL_DTAG_DEVNAME, CCN_TT_DTAG,
                          devname);
    if (ethtype)
        len3 += ccnl_ccnb_mkStrBlob(faceinst+len3, CCN_DTAG_PORT, CCN_TT_DTAG, ethtype);
    if (frag)
        len3 += ccnl_ccnb_mkStrBlob(faceinst+len3, CCNL_DTAG_FRAG, CCN_TT_DTAG, frag);
    if (flags)
        len3 += ccnl_ccnb_mkStrBlob(faceinst+len3, CCNL_DTAG_DEVFLAGS, CCN_TT_DTAG, flags);
    faceinst[len3++] = 0; // end-of-faceinst

    // prepare CONTENTOBJ with CONTENT
    len2 = ccnl_ccnb_mkHeader(contentobj, CCN_DTAG_CONTENTOBJ, CCN_TT_DTAG);   // contentobj
    len2 += ccnl_ccnb_mkBlob(contentobj+len2, CCN_DTAG_CONTENT, CCN_TT_DTAG,  // content
                   (char*) faceinst, len3);
    contentobj[len2++] = 0; // end-of-contentobj

    // add CONTENTOBJ as the final name component
    len1 += ccnl_ccnb_mkBlob(out1+len1, CCN_DTAG_COMPONENT, CCN_TT_DTAG,  // comp
                  (char*) contentobj, len2);

#ifdef USE_SIGNATURES
    if(private_key_path) len += add_signature(out+len, private_key_path, out1, len1);
#endif /*USE_SIGNATURES*/
    memcpy(out+len, out1, len1);
    len += len1;
    out[len++] = 0; // end-of-name
    out[len++] = 0; // end-of-interest

    return len;
}
Ejemplo n.º 5
0
static int
ccnl_crypto_create_ccnl_sign_verify_msg(char *typ, int txid, char *content, int content_len,
        char *sig, int sig_len, char *msg, char *callback)
{
    int len = 0, len2 = 0, len3 = 0;
    char *component_buf, *contentobj_buf;
    char h[100];

    component_buf = ccnl_malloc(sizeof(char)*(content_len)+2000);
    contentobj_buf = ccnl_malloc(sizeof(char)*(content_len)+1000);

    len = ccnl_ccnb_mkHeader(msg, CCN_DTAG_INTEREST, CCN_TT_DTAG);   // interest
    len += ccnl_ccnb_mkHeader(msg+len, CCN_DTAG_NAME, CCN_TT_DTAG);  // name

    len += ccnl_ccnb_mkStrBlob(msg+len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "ccnx");
    len += ccnl_ccnb_mkStrBlob(msg+len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "crypto");

    // prepare FACEINSTANCE
    len3 += ccnl_ccnb_mkStrBlob(component_buf+len3, CCNL_DTAG_CALLBACK, CCN_TT_DTAG, callback);
    len3 += ccnl_ccnb_mkStrBlob(component_buf+len3, CCN_DTAG_TYPE, CCN_TT_DTAG, typ);
    memset(h, 0, 100);
    sprintf(h, "%d", txid);
    len3 += ccnl_ccnb_mkStrBlob(component_buf+len3, CCN_DTAG_SEQNO, CCN_TT_DTAG, h);
    if(!strcmp(typ, "verify"))
        len3 += ccnl_ccnb_mkBlob(component_buf+len3, CCN_DTAG_SIGNATURE, CCN_TT_DTAG,  // content
                   (char*) sig, sig_len);
    len3 += ccnl_ccnb_mkBlob(component_buf+len3, CCN_DTAG_CONTENTDIGEST, CCN_TT_DTAG,  // content
                   (char*) content, content_len);

    // prepare CONTENTOBJ with CONTENT
    len2 = ccnl_ccnb_mkHeader(contentobj_buf, CCN_DTAG_CONTENTOBJ, CCN_TT_DTAG);   // contentobj
    len2 += ccnl_ccnb_mkBlob(contentobj_buf+len2, CCN_DTAG_CONTENT, CCN_TT_DTAG,  // content
                   (char*) component_buf, len3);
    contentobj_buf[len2++] = 0; // end-of-contentobj

    // add CONTENTOBJ as the final name component
    len += ccnl_ccnb_mkBlob(msg+len, CCN_DTAG_COMPONENT, CCN_TT_DTAG,  // comp
                  (char*) contentobj_buf, len2);

    msg[len++] = 0; // end-of-name
    msg[len++] = 0; // end-o

    ccnl_free(component_buf);
    ccnl_free(contentobj_buf);

    return len;
}
Ejemplo n.º 6
0
static int
ccnl_crypto_add_signature(unsigned char *out, char *sig, int siglen)
{
    int len;

    len = ccnl_ccnb_mkHeader(out, CCN_DTAG_SIGNATURE, CCN_TT_DTAG);
    len += ccnl_ccnb_mkStrBlob(out + len, CCN_DTAG_NAME, CCN_TT_DTAG, "SHA256");
    len += ccnl_ccnb_mkStrBlob(out + len, CCN_DTAG_WITNESS, CCN_TT_DTAG, "");

    //add signaturebits bits...
    len += ccnl_ccnb_mkHeader(out + len, CCN_DTAG_SIGNATUREBITS, CCN_TT_DTAG);
    len += ccnl_ccnb_addBlob(out + len, sig, siglen);
    out[len++] = 0; // end signaturebits

    out[len++] = 0; // end signature
    return len;
}
Ejemplo n.º 7
0
int
mkDebugRequest(unsigned char *out, char *dbg, char *private_key_path)
{
    int len = 0, len1 = 0, len2 = 0, len3 = 0;
    unsigned char out1[CCNL_MAX_PACKET_SIZE];
    unsigned char contentobj[2000];
    unsigned char stmt[1000];

    len = ccnl_ccnb_mkHeader(out, CCN_DTAG_INTEREST, CCN_TT_DTAG);   // interest
    len += ccnl_ccnb_mkHeader(out+len, CCN_DTAG_NAME, CCN_TT_DTAG);  // name

    len1 += ccnl_ccnb_mkStrBlob(out1+len1, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "ccnx");
    len1 += ccnl_ccnb_mkStrBlob(out1+len1, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "");
    len1 += ccnl_ccnb_mkStrBlob(out1+len1, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "debug");

    // prepare debug statement
    len3 = ccnl_ccnb_mkHeader(stmt, CCNL_DTAG_DEBUGREQUEST, CCN_TT_DTAG);
    len3 += ccnl_ccnb_mkStrBlob(stmt+len3, CCN_DTAG_ACTION, CCN_TT_DTAG, "debug");
    len3 += ccnl_ccnb_mkStrBlob(stmt+len3, CCNL_DTAG_DEBUGACTION, CCN_TT_DTAG, dbg);
    stmt[len3++] = 0; // end-of-debugstmt

    // prepare CONTENTOBJ with CONTENT
    len2 = ccnl_ccnb_mkHeader(contentobj, CCN_DTAG_CONTENTOBJ, CCN_TT_DTAG);   // contentobj
    len2 += ccnl_ccnb_mkBlob(contentobj+len2, CCN_DTAG_CONTENT, CCN_TT_DTAG,  // content
                             (char*) stmt, len3);
    contentobj[len2++] = 0; // end-of-contentobj

    // add CONTENTOBJ as the final name component
    len1 += ccnl_ccnb_mkBlob(out1+len1, CCN_DTAG_COMPONENT, CCN_TT_DTAG,  // comp
                  (char*) contentobj, len2);

#ifdef USE_SIGNATURES
    if(private_key_path) len += add_signature(out+len, private_key_path, out1, len1);
#endif /*USE_SIGNATURES*/
    memcpy(out+len, out1, len1);
    len += len1;
    out[len++] = 0; // end-of-name
    out[len++] = 0; // end-of-interest

//    ccnl_prefix_free(p);
    return len;
}
Ejemplo n.º 8
0
int
add_ccnl_name(unsigned char *out, char *ccn_path)
{
    char comp[256];
    int len = 0, len2 = 0;
    int h;
    memset(comp, 0 , 256);
    len += ccnl_ccnb_mkHeader(out + len, CCN_DTAG_NAME, CCN_TT_DTAG);
    while( (h = split_string(ccn_path + len2, '/', comp)) )
    {
        len2 += h;
        len += ccnl_ccnb_mkStrBlob(out + len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, comp);
        memset(comp, 0 , 256);
    }
    out[len++] = 0;
    return len;
}
Ejemplo n.º 9
0
int
ccnl_mgmt_crypto(struct ccnl_relay_s *ccnl, char *type, unsigned char *buf, int buflen)
{

   struct ccnl_face_s *from;
   DEBUGMSG(DEBUG,"ccnl_crypto type: %s\n", type);

   if(!strcmp(type, "verify")){
      int seqnum = 0;
      int verified = ccnl_crypto_extract_verify_reply(&buf, &buflen, &seqnum);
      unsigned char *msg, *msg2;
      char cmd[500];
      int len = ccnl_crypto_extract_msg(&buf, &buflen, &msg), len2 = 0;
      struct ccnl_face_s *from;
      //DEBUGMSG(DEBUG,"VERIFIED: %d, MSG_LEN: %d\n", verified, len);

      int scope=3, aok=3, minsfx=0, maxsfx=CCNL_MAX_NAME_COMP, contlen;
      struct ccnl_buf_s *buf1 = 0, *nonce=0, *ppkd=0;
      struct ccnl_prefix_s *p = 0;
      struct ccnl_buf_s *msg2_buf;
      unsigned char *content = 0;

      msg2 = (char *) ccnl_malloc(sizeof(char) * len + 200);
      len2 = ccnl_ccnb_mkHeader(msg2,CCN_DTAG_NAME, CCN_TT_DTAG);
      memcpy(msg2+len2, msg, len);
      len2 +=len;
      msg2[len2++] = 0;

      from = ccnl->faces;
      while(from){
          if(from->faceid == seqnum)
              break;
          from = from->next;
      }

      buf1 = ccnl_ccnb_extract(&msg2, &len2, &scope, &aok, &minsfx,
                         &maxsfx, &p, &nonce, &ppkd, &content, &contlen);

      if (p->complen[2] < sizeof(cmd)) {
            memcpy(cmd, p->comp[2], p->complen[2]);
            cmd[p->complen[2]] = '\0';
      } else
            strcpy(cmd, "cmd-is-too-long-to-display");
      msg2_buf = ccnl_buf_new((char *)msg2, len2);
      ccnl_mgmt_handle(ccnl, msg2_buf, p, from, cmd, verified);
      ccnl_free(msg2_buf);
   }else if(!strcmp(type, "sign")){
      char *sig = (char *) ccnl_malloc(sizeof(char)* CCNL_MAX_PACKET_SIZE);
      unsigned char *out;
      unsigned char *msg;
      int siglen = 0, seqnum = 0, len, len1;
      struct ccnl_buf_s *retbuf;

      ccnl_crypto_extract_sign_reply(&buf, &buflen, sig, &siglen, &seqnum);

      len = ccnl_crypto_extract_msg(&buf, &buflen, &msg);
      out = (char *) ccnl_malloc(sizeof(unsigned char)*len + sizeof(unsigned char)*siglen + 4096);

      len1 = ccnl_ccnb_mkHeader(out, CCN_DTAG_CONTENTOBJ, CCN_TT_DTAG);   // content
      if(siglen > 0) len1 += ccnl_crypto_add_signature(out+len1, sig, siglen);

      memcpy(out+len1, msg, len);
      len1 +=len;

      out[len1++] = 0; // end-of-interest
      from = ccnl->faces;
      while(from){
          if(from->faceid == seqnum)
              break;
          from = from->next;
      }

      retbuf = ccnl_buf_new((char *)out, len1);
      if(seqnum >= 0){
          ccnl_face_enqueue(ccnl, from, retbuf);
      }else{
          struct ccnl_prefix_s *prefix_a = 0;
          struct ccnl_content_s *c = 0;
          struct ccnl_buf_s *nonce=0, *ppkd=0, *pkt = 0;
          unsigned char *content = 0;
          char *ht = (char *) ccnl_malloc(sizeof(char)*20);
          int contlen;
          pkt = ccnl_ccnb_extract(&out, &len1, 0, 0, 0, 0,
                                  &prefix_a, &nonce, &ppkd, &content, &contlen);

          if (!pkt) {
               DEBUGMSG(WARNING, " parsing error\n"); goto Done;
          }
          if (prefix_a) {
              //DEBUGMSG(DEBUG, "%s", prefix_a->comp);
              //ccnl_free(prefix_a);
          }
          //prefix_a = (struct ccnl_prefix_s *)ccnl_malloc(sizeof(struct ccnl_prefix_s));
          prefix_a->compcnt = 2;
          prefix_a->comp = (unsigned char **) ccnl_malloc(sizeof(unsigned char*)*2);
          prefix_a->comp[0] = "mgmt";
          sprintf(ht, "seqnum-%d", -seqnum);
          prefix_a->comp[1] = ht;
          prefix_a->complen = (int *) ccnl_malloc(sizeof(int)*2);
          prefix_a->complen[0] = strlen("mgmt");
          prefix_a->complen[1] = strlen(ht);
          c = ccnl_content_new(ccnl, CCNL_SUITE_CCNB, &pkt, &prefix_a, &ppkd,
                                content, contlen);
          if (!c) goto Done;

          ccnl_content_serve_pending(ccnl, c);
          ccnl_content_add2cache(ccnl, c);
      }
      Done:
      ccnl_free(out);
   }
   return 0;
}
struct ccnl_buf_s*
ccnl_frag_getnextCCNx2013(struct ccnl_frag_s *fr, int *ifndx, sockunion *su)
{
    struct ccnl_buf_s *buf = 0;
    unsigned char header[256];
    int hdrlen, blobtaglen, flagoffs;
    unsigned int datalen;

    // switch among encodings of fragments here (ccnb, TLV, etc)

    hdrlen = ccnl_ccnb_mkHeader(header, CCNL_DTAG_FRAGMENT2013, CCN_TT_DTAG); // fragment

    hdrlen += ccnl_ccnb_mkHeader(header + hdrlen, CCNL_DTAG_FRAG2013_TYPE, CCN_TT_DTAG);
    hdrlen += ccnl_ccnb_mkHeader(header + hdrlen, 3, CCN_TT_BLOB);
    memcpy(header + hdrlen, CCNL_FRAG_TYPE_CCNx2013_VAL, 3); // "FHBH"
    header[hdrlen + 3] = '\0';
    hdrlen += 4;

    hdrlen += ccnl_ccnb_mkBinaryInt(header+hdrlen, CCNL_DTAG_FRAG2013_SEQNR, CCN_TT_DTAG,
                                    fr->sendseq, fr->sendseqwidth);

    hdrlen += ccnl_ccnb_mkBinaryInt(header+hdrlen, CCNL_DTAG_FRAG2013_FLAGS, CCN_TT_DTAG,
                                    0, fr->flagwidth);
    flagoffs = hdrlen - 2; // most significant byte of flag element

    // other optional fields would go here

    hdrlen += ccnl_ccnb_mkHeader(header+hdrlen, CCN_DTAG_CONTENT, CCN_TT_DTAG);

    blobtaglen = ccnl_ccnb_mkHeader(header + hdrlen, fr->mtu - hdrlen - 2, CCN_TT_BLOB);
    datalen = fr->mtu - hdrlen - blobtaglen - 2;
    if (datalen > (fr->bigpkt->datalen - fr->sendoffs))
        datalen = fr->bigpkt->datalen - fr->sendoffs;
    hdrlen += ccnl_ccnb_mkHeader(header + hdrlen, datalen, CCN_TT_BLOB);

    buf = ccnl_buf_new(NULL, hdrlen + datalen + 2);
    if (!buf)
        return NULL;
    memcpy(buf->data, header, hdrlen);
    memcpy(buf->data + hdrlen, fr->bigpkt->data + fr->sendoffs, datalen);
    buf->data[hdrlen + datalen] = '\0'; // end of content field
    buf->data[hdrlen + datalen + 1] = '\0'; // end of fragment

    // patch flag field:
    if (datalen >= fr->bigpkt->datalen) { // single
        buf->data[flagoffs] = CCNL_DTAG_FRAG_FLAG_SINGLE;
        ccnl_free(fr->bigpkt);
        fr->bigpkt = NULL;
    } else if (fr->sendoffs == 0) // start
        buf->data[flagoffs] = CCNL_DTAG_FRAG_FLAG_FIRST;
    else if(datalen >= (fr->bigpkt->datalen - fr->sendoffs)) { // end
        buf->data[flagoffs] = CCNL_DTAG_FRAG_FLAG_LAST;
        ccnl_free(fr->bigpkt);
        fr->bigpkt = NULL;
    } else
        buf->data[flagoffs] = CCNL_DTAG_FRAG_FLAG_MID;

    fr->sendoffs += datalen;
    fr->sendseq++;

    if (ifndx)
        *ifndx = fr->ifndx;
    if (su)
        memcpy(su, &fr->dest, sizeof(*su));

    return buf;
}
struct ccnl_buf_s*
ccnl_frag_getnextSEQD2012(struct ccnl_frag_s *e, int *ifndx, sockunion *su)
{
    struct ccnl_buf_s *buf = 0;
    unsigned char header[256];
    int hdrlen = 0, blobtaglen, flagoffs;
    unsigned int datalen;

    DEBUGMSG_EFRA(TRACE, "ccnl_frag_getnextSEQD2012 e=%p, mtu=%d\n", (void*)e, e->mtu);
    DEBUGMSG_EFRA(TRACE, "  %d bytes to fragment, offset=%d\n",
                  e->bigpkt->datalen, e->sendoffs);

    hdrlen = ccnl_ccnb_mkHeader(header, CCNL_DTAG_FRAGMENT2012, CCN_TT_DTAG);
    hdrlen += ccnl_ccnb_mkBinaryInt(header + hdrlen, CCNL_DTAG_FRAG2012_FLAGS,
                                    CCN_TT_DTAG, 0, e->flagwidth);
    flagoffs = hdrlen - 2;
    hdrlen += ccnl_ccnb_mkBinaryInt(header + hdrlen, CCNL_DTAG_FRAG2012_YSEQN,
                                    CCN_TT_DTAG, e->recvseq, e->recvseqwidth);
    hdrlen += ccnl_ccnb_mkBinaryInt(header+hdrlen, CCNL_DTAG_FRAG2012_OLOSS, CCN_TT_DTAG,
                                    e->losscount, e->losscountwidth);

    hdrlen += ccnl_ccnb_mkBinaryInt(header + hdrlen, CCNL_DTAG_FRAG2012_SEQNR,
                                    CCN_TT_DTAG, e->sendseq, e->sendseqwidth);
    hdrlen += ccnl_ccnb_mkHeader(header+hdrlen, CCN_DTAG_CONTENT, CCN_TT_DTAG);
    blobtaglen = ccnl_ccnb_mkHeader(header+hdrlen, e->mtu - hdrlen - 2, CCN_TT_BLOB);

    datalen = e->mtu - hdrlen - blobtaglen - 2;
    if (datalen > (e->bigpkt->datalen - e->sendoffs))
        datalen = e->bigpkt->datalen - e->sendoffs;
    hdrlen += ccnl_ccnb_mkHeader(header + hdrlen, datalen, CCN_TT_BLOB);

    buf = ccnl_buf_new(NULL, hdrlen + datalen + 2);
    if (!buf)
        return NULL;
    memcpy(buf->data, header, hdrlen);
    memcpy(buf->data + hdrlen, e->bigpkt->data + e->sendoffs, datalen);
    buf->data[hdrlen + datalen] = '\0'; // end of content/any field
    buf->data[hdrlen + datalen + 1] = '\0'; // end of fragment/pdu

    if (datalen >= e->bigpkt->datalen) { // fits in a single fragment
        buf->data[flagoffs + e->flagwidth - 1] =
            CCNL_DTAG_FRAG_FLAG_FIRST | CCNL_DTAG_FRAG_FLAG_LAST;
        ccnl_free(e->bigpkt);
        e->bigpkt = NULL;
    } else if (e->sendoffs == 0) // this is the start fragment
        buf->data[flagoffs + e->flagwidth - 1] = CCNL_DTAG_FRAG_FLAG_FIRST;
    else if(datalen >= (e->bigpkt->datalen - e->sendoffs)) { // the end
        buf->data[flagoffs + e->flagwidth - 1] = CCNL_DTAG_FRAG_FLAG_LAST;
        ccnl_free(e->bigpkt);
        e->bigpkt = NULL;
    } else // in the middle
        buf->data[flagoffs + e->flagwidth - 1] = 0x00;

    e->sendoffs += datalen;
    e->sendseq++;

    DEBUGMSG_EFRA(TRACE, "  e->offset now %d\n", e->sendoffs);

    if (ifndx)
        *ifndx = e->ifndx;
    if (su)
        memcpy(su, &e->dest, sizeof(*su));
    return buf;
}
int
ccnl_frag_getfragcount(struct ccnl_frag_s *e, int origlen, int *totallen)
{
    int cnt = 0, len = 0;

    if (!e)
        cnt = 1;
#ifdef OBSOLETE_BY_2015_06
#ifdef USE_SUITE_CCNB
    else if (e->protocol == CCNL_FRAG_SEQUENCED2012) {
        unsigned char dummy[256];
        int hdrlen, blobtaglen, datalen;
        int offs = 0;
        while (offs < origlen) { // we could do better than to simulate this:
            hdrlen = ccnl_ccnb_mkHeader(dummy, CCNL_DTAG_FRAGMENT2012, CCN_TT_DTAG);
            hdrlen += ccnl_ccnb_mkBinaryInt(dummy, CCNL_DTAG_FRAG2012_FLAGS, CCN_TT_DTAG,
                                            0, e->flagwidth);
            hdrlen += ccnl_ccnb_mkBinaryInt(dummy, CCNL_DTAG_FRAG2012_SEQNR, CCN_TT_DTAG,
                                            0, e->sendseqwidth);
            hdrlen += ccnl_ccnb_mkBinaryInt(dummy, CCNL_DTAG_FRAG2012_OLOSS, CCN_TT_DTAG,
                                            0, e->losscountwidth);
            hdrlen += ccnl_ccnb_mkBinaryInt(dummy, CCNL_DTAG_FRAG2012_YSEQN, CCN_TT_DTAG,
                                            0, e->recvseqwidth);

            hdrlen += ccnl_ccnb_mkHeader(dummy, CCN_DTAG_CONTENT, CCN_TT_DTAG);
            blobtaglen = ccnl_ccnb_mkHeader(dummy, e->mtu - hdrlen - 1, CCN_TT_BLOB);
            datalen = e->mtu - hdrlen - blobtaglen - 1;
            if (datalen > (origlen - offs))
                datalen = origlen - offs;
            hdrlen += ccnl_ccnb_mkHeader(dummy, datalen, CCN_TT_BLOB);
            len += hdrlen + datalen + 1;
            offs += datalen;
            cnt++;
        }
    } else if (e->protocol == CCNL_FRAG_CCNx2013) {
        unsigned char dummy[256];
        int hdrlen, blobtaglen, datalen;
        int offs = 0;
        while (offs < origlen) { // we could do better than to simulate this:
            hdrlen = ccnl_ccnb_mkHeader(dummy, CCNL_DTAG_FRAGMENT2013, CCN_TT_DTAG);
            hdrlen += ccnl_ccnb_mkHeader(dummy, CCNL_DTAG_FRAG2013_TYPE, CCN_TT_DTAG);
            hdrlen += 4; // three BLOB bytes plus end-of-entry
            hdrlen += ccnl_ccnb_mkBinaryInt(dummy, CCNL_DTAG_FRAG2013_SEQNR, CCN_TT_DTAG,
                                            0, e->sendseqwidth);
            hdrlen += ccnl_ccnb_mkBinaryInt(dummy, CCNL_DTAG_FRAG2013_FLAGS, CCN_TT_DTAG,
                                            0, e->flagwidth);
            hdrlen += ccnl_ccnb_mkBinaryInt(dummy, CCNL_DTAG_FRAG2013_OLOSS, CCN_TT_DTAG,
                                            0, e->losscountwidth);
            hdrlen += ccnl_ccnb_mkBinaryInt(dummy, CCNL_DTAG_FRAG2013_YSEQN, CCN_TT_DTAG,
                                            0, e->recvseqwidth);

            hdrlen += ccnl_ccnb_mkHeader(dummy, CCN_DTAG_CONTENT, CCN_TT_DTAG);
            blobtaglen = ccnl_ccnb_mkHeader(dummy, e->mtu - hdrlen - 1, CCN_TT_BLOB);
            datalen = e->mtu - hdrlen - blobtaglen - 1;
            if (datalen > (origlen - offs))
                datalen = origlen - offs;
            hdrlen += ccnl_ccnb_mkHeader(dummy, datalen, CCN_TT_BLOB);
            len += hdrlen + datalen + 1;
            offs += datalen;
            cnt++;
        }
    }
#endif
    else if (e->protocol == CCNL_FRAG_SEQUENCED2015) {
        // ...
        DEBUGMSG_EFRA(FATAL, "frag counting not implemented yet for SEQD2015!\n");
    }
#endif // OBSOLETE
    else {
        DEBUGMSG_EFRA(FATAL, "frag protocol %d not supported?\n", e->protocol);
    }

    if (totallen)
        *totallen = len;
    return cnt;
}