int overlay_mdp_service_stun_req(overlay_mdp_frame *mdp) { if (config.debug.overlayrouting) DEBUGF("Processing STUN request from %s", alloca_tohex_sid(mdp->out.src.sid)); struct overlay_buffer *payload = ob_static(mdp->out.payload, mdp->out.payload_length); ob_limitsize(payload, mdp->out.payload_length); overlay_mdp_frame reply; bzero(&reply, sizeof(reply)); reply.packetTypeAndFlags=MDP_TX; bcopy(mdp->out.src.sid, reply.out.dst.sid, SID_SIZE); bcopy(mdp->out.dst.sid, reply.out.src.sid, SID_SIZE); reply.out.src.port=MDP_PORT_STUNREQ; reply.out.dst.port=MDP_PORT_STUN; reply.out.queue=OQ_MESH_MANAGEMENT; struct overlay_buffer *replypayload = ob_static(reply.out.payload, sizeof(reply.out.payload)); ob_checkpoint(replypayload); while(ob_remaining(payload)>0){ struct subscriber *subscriber=NULL; if (overlay_address_parse(NULL, payload, &subscriber)) break; if (!subscriber){ if (config.debug.overlayrouting) DEBUGF("Unknown subscriber"); continue; } if (overlay_append_unicast_address(subscriber, replypayload)) break; } ob_rewind(replypayload); reply.out.payload_length=ob_position(replypayload); if (reply.out.payload_length){ if (config.debug.overlayrouting) DEBUGF("Sending reply"); overlay_mdp_dispatch(&reply,0 /* system generated */, NULL,0); } ob_free(replypayload); ob_free(payload); return 0; }
int overlay_payload_package_fmt1(overlay_payload *p,overlay_buffer *b) { /* Convert a payload structure into a series of bytes. Also select next-hop address to help payload get to its' destination */ unsigned char nexthop[SIDDIDFIELD_LEN+1]; int nexthoplen=0; overlay_buffer *headers=ob_new(256); if (!headers) return -1; if (!p) return -1; if (!b) return -1; /* Build header */ int fail=0; if (overlay_get_nexthop(p,nexthop,&nexthoplen)) fail++; if (ob_append_bytes(headers,nexthop,nexthoplen)) fail++; /* XXX Can use shorter fields for different address types */ if (ob_append_bytes(headers,(unsigned char *)p->src,SIDDIDFIELD_LEN)) fail++; if (ob_append_bytes(headers,(unsigned char *)p->dst,SIDDIDFIELD_LEN)) fail++; if (fail) { ob_free(headers); return -1; } /* Write payload format plus total length of header bits */ if (ob_makespace(b,2+headers->length+p->payloadLength)) { /* Not enough space free in output buffer */ ob_free(headers); return -1; } /* Package up headers and payload */ ob_checkpoint(b); if (ob_append_short(b,0x1000|(p->payloadLength+headers->length))) fail++; if (ob_append_bytes(b,headers->bytes,headers->length)) fail++; if (ob_append_bytes(b,p->payload,p->payloadLength)) fail++; /* XXX SIGNATURE! */ ob_free(headers); if (fail) { ob_rewind(b); return -1; } else return 0; }
int overlay_frame_append_payload(struct decode_context *context, overlay_interface *interface, struct overlay_frame *p, struct overlay_buffer *b) { /* Convert a payload (frame) structure into a series of bytes. Assumes that any encryption etc has already been done. Will pick a next hop if one has not been chosen. */ ob_checkpoint(b); if (config.debug.packetconstruction){ DEBUGF( "+++++\nFrame from %s to %s of type 0x%02x %s:", alloca_tohex_sid(p->source->sid), alloca_tohex_sid(p->destination->sid),p->type, "append_payload stuffing into packet"); if (p->payload) dump("payload contents", &p->payload->bytes[0],p->payload->position); } struct broadcast *broadcast=NULL; if ((!p->destination) && !is_all_matching(p->broadcast_id.id,BROADCAST_LEN,0)){ broadcast = &p->broadcast_id; } if (overlay_frame_build_header(p->packet_version, context, b, p->queue, p->type, p->modifiers, p->ttl, p->mdp_sequence&0xFF, broadcast, p->next_hop, p->destination, p->source)) goto cleanup; if (ob_append_ui16(b, ob_position(p->payload))) goto cleanup; if (ob_append_bytes(b, ob_ptr(p->payload), ob_position(p->payload))) { WHY("could not append payload"); goto cleanup; } return 0; cleanup: ob_rewind(b); return -1; }
int overlay_frame_package_fmt1(overlay_frame *p,overlay_buffer *b) { /* Convert a payload (frame) structure into a series of bytes. Assumes that any encryption etc has already been done. Will pick a next hop if one has not been chosen. */ int nexthoplen=0; overlay_buffer *headers=ob_new(256); if (!headers) return WHY("could not allocate overlay buffer for headers"); if (!p) return WHY("p is NULL"); if (!b) return WHY("b is NULL"); /* Build header */ int fail=0; if (p->nexthop_address_status!=OA_RESOLVED) { if (overlay_get_nexthop((unsigned char *)p->destination,p->nexthop,&nexthoplen,&p->nexthop_interface)) fail++; else p->nexthop_address_status=OA_RESOLVED; } if (p->source[0]<0x10) { // Make sure that addresses do not overload the special address spaces of 0x00*-0x0f* fail++; return WHY("packet source address begins with reserved value 0x00-0x0f"); } if (p->destination[0]<0x10) { // Make sure that addresses do not overload the special address spaces of 0x00*-0x0f* fail++; return WHY("packet destination address begins with reserved value 0x00-0x0f"); } if (p->nexthop[0]<0x10) { // Make sure that addresses do not overload the special address spaces of 0x00*-0x0f* fail++; return WHY("packet nexthop address begins with reserved value 0x00-0x0f"); } /* XXX Write fields in correct order */ /* Write out type field byte(s) */ if (!fail) if (op_append_type(headers,p)) fail++; /* Write out TTL */ if (!fail) if (ob_append_byte(headers,p->ttl)) fail++; /* Length. This is the fun part, because we cannot calculate how many bytes we need until we have abbreviated the addresses, and the length encoding we use varies according to the length encoded. The simple option of running the abbreviations twice won't work because we rely on context for abbreviating the addresses. So we write it initially and then patch it after. */ if (!fail) { int max_len=((SID_SIZE+3)*3+headers->length+p->payload->length); ob_append_rfs(headers,max_len); int addrs_start=headers->length; /* Write out addresses as abbreviated as possible */ overlay_abbreviate_append_address(headers,p->nexthop); overlay_abbreviate_set_most_recent_address(p->nexthop); overlay_abbreviate_append_address(headers,p->destination); overlay_abbreviate_set_most_recent_address(p->destination); overlay_abbreviate_append_address(headers,p->source); overlay_abbreviate_set_most_recent_address(p->source); int addrs_len=headers->length-addrs_start; int actual_len=addrs_len+p->payload->length; ob_patch_rfs(headers,actual_len); } if (fail) { ob_free(headers); return WHY("failure count was non-zero"); } /* Write payload format plus total length of header bits */ if (ob_makespace(b,2+headers->length+p->payload->length)) { /* Not enough space free in output buffer */ ob_free(headers); if (debug&DEBUG_PACKETFORMATS) WHY("Could not make enough space free in output buffer"); return -1; } /* Package up headers and payload */ ob_checkpoint(b); if (ob_append_bytes(b,headers->bytes,headers->length)) { fail++; WHY("could not append header"); } if (ob_append_bytes(b,p->payload->bytes,p->payload->length)) { fail++; WHY("could not append payload"); } /* XXX SIGN &/or ENCRYPT */ ob_free(headers); if (fail) { ob_rewind(b); return WHY("failure count was non-zero"); } else return 0; }