Esempio n. 1
0
static int overlay_frame_build_header(int packet_version, struct decode_context *context, 
			       struct overlay_buffer *buff, 
			       int queue, int type, int modifiers, int ttl, int sequence,
			       struct broadcast *broadcast, struct subscriber *next_hop,
			       struct subscriber *destination, struct subscriber *source)
{
  if (ttl < 0 || ttl > PAYLOAD_TTL_MAX)
    return WHYF("invalid ttl=%d", ttl);

  int flags = modifiers & (PAYLOAD_FLAG_CIPHERED | PAYLOAD_FLAG_SIGNED);
  
  if (ttl==1 && !broadcast)
    flags |= PAYLOAD_FLAG_ONE_HOP;
  if (destination && destination==next_hop)
    flags |= PAYLOAD_FLAG_ONE_HOP;
  
  if (source == context->sender)
    flags |= PAYLOAD_FLAG_SENDER_SAME;
  
  if (!destination)
    flags |= PAYLOAD_FLAG_TO_BROADCAST;
  
  if (type!=OF_TYPE_DATA)
    flags |= PAYLOAD_FLAG_LEGACY_TYPE;
  
  if (ob_append_byte(buff, flags)) return -1;
  
  if (!(flags & PAYLOAD_FLAG_SENDER_SAME)){
    if (overlay_address_append(context, buff, source)) return -1;
  }
  
  if (flags & PAYLOAD_FLAG_TO_BROADCAST){
    if (!(flags & PAYLOAD_FLAG_ONE_HOP)){
      if (overlay_broadcast_append(buff, broadcast)) return -1;
    }
  }else{
    if (overlay_address_append(context, buff, destination)) return -1;
    if (!(flags & PAYLOAD_FLAG_ONE_HOP)){
      if (overlay_address_append(context, buff, next_hop)) return -1;
    }
  }
  
  if (!(flags & PAYLOAD_FLAG_ONE_HOP)){
    if (ob_append_byte(buff, ttl | ((queue&3)<<5))) return -1;
  }
  
  if (flags & PAYLOAD_FLAG_LEGACY_TYPE){
    if (ob_append_byte(buff, type)) return -1;
  }

  if (packet_version >= 1)
    if (ob_append_byte(buff, sequence))
      return -1;
  
  return 0;
}
int overlay_add_selfannouncement(int interface,struct overlay_buffer *b)
{

  /* Pull the first record from the HLR database and turn it into a
     self-announcment. These are shorter than regular Subscriber Observation
     Notices (SON) because they are just single-hop announcments of presence.

     Do we really need to push the whole SID (32 bytes), or will just, say, 
     8 do so that we use a prefix of the SID which is still very hard to forge?
     
     A hearer of a self-announcement who has not previously seen the sender might
     like to get some authentication to prevent naughty people from spoofing routes.

     We can do this by having ourselves, the sender, keep track of the last few frames
     we have sent, so that we can be asked to sign them.  Actually, we won't sign them, 
     as that is too slow/energy intensive, but we could use a D-H exchange with the neighbour,
     performed once to get a shared secret that can be used to feed a stream cipher to
     produce some sort of verification.

     XXX - But this functionality really needs to move up a level to whole frame composition.
  */

  time_ms_t now = gettime_ms();

  /* Header byte */
  if (ob_append_byte(b, OF_TYPE_SELFANNOUNCE))
    return WHY("Could not add self-announcement header");

  /* A TTL for this frame.
     XXX - BATMAN uses various TTLs, but I think that it may just be better to have all TTL=1,
     and have the onward nodes selectively choose which nodes to on-announce.  If we prioritise
     newly arrived nodes somewhat (or at least reserve some slots for them), then we can still
     get the good news travels fast property of BATMAN, but without having to flood in the formal
     sense. */
  if (ob_append_byte(b,1))
    return WHY("Could not add TTL to self-announcement");
  
  /* Add space for Remaining Frame Size field.  This will always be a single byte
     for self-announcments as they are always <256 bytes. */
  if (ob_append_rfs(b,1+8+1+SID_SIZE+4+4+1))
    return WHY("Could not add RFS for self-announcement frame");

  /* Add next-hop address.  Always link-local broadcast for self-announcements */
  struct broadcast broadcast_id;
  overlay_broadcast_generate_address(&broadcast_id);
  if (overlay_broadcast_append(b, &broadcast_id))
    return WHY("Could not write broadcast address to self-announcement");

  /* Add final destination.  Always broadcast for self-announcments. */
  if (ob_append_byte(b, OA_CODE_PREVIOUS))
    return WHY("Could not add self-announcement header");

  /* Add our SID to the announcement as sender */
  if (overlay_address_append_self(&overlay_interfaces[interface], b))
    return -1;
  
  overlay_address_set_sender(my_subscriber);
  
  /* Sequence number range.  Based on one tick per millisecond. */
  time_ms_t last_ms = overlay_interfaces[interface].last_tick_ms;
  // If this interface has not been ticked yet (no selfannounce sent) then invent the prior sequence
  // number: one millisecond ago.
  if (last_ms == -1)
    last_ms = now - 1;
  if (ob_append_ui32(b, last_ms))
    return WHY("Could not add low sequence number to self-announcement");
  if (ob_append_ui32(b, now))
    return WHY("Could not add high sequence number to self-announcement");
  if (debug&DEBUG_OVERLAYINTERFACES)
    DEBUGF("interface #%d: last_tick_ms=%lld, now=%lld (delta=%lld)",
	interface,
	(long long)overlay_interfaces[interface].last_tick_ms,
	(long long)now,
	(long long)(now - last_ms)
      );
  overlay_interfaces[interface].last_tick_ms = now;

  /* A byte that indicates which interface we are sending over */
  if (ob_append_byte(b,interface))
    return WHY("Could not add interface number to self-announcement");

  ob_patch_rfs(b, COMPUTE_RFS_LENGTH);
  
  return 0;
}