Prep for 6-in-6, 4-in-6, 6-in-4
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
|
|
||||||
int process_icmp_rloc_update( struct rlocs *reg, struct packet *packet )
|
int process_icmpv4_rloc_update( struct rlocs *reg, struct packet *packet )
|
||||||
{
|
{
|
||||||
uint16_t hdr_len = packet->hdr.ip.ihl * 4;
|
uint16_t hdr_len = packet->hdr.ip.ihl * 4;
|
||||||
uint16_t inner_ip_hdr_offset = hdr_len + sizeof( struct icmphdr );
|
uint16_t inner_ip_hdr_offset = hdr_len + sizeof( struct icmphdr );
|
||||||
@@ -46,40 +46,35 @@ int process_icmp_rloc_update( struct rlocs *reg, struct packet *packet )
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int process_ipv4_packet( struct rlocs *reg, struct packet *packet, struct rsp_data *frag1, struct rsp_data *frag2 )
|
|
||||||
|
int process_icmpv6_rloc_update( struct rlocs *reg, struct packet *packet )
|
||||||
{
|
{
|
||||||
int result, updated;
|
warn( "STUB: process_icmpv6_rloc_update" );
|
||||||
|
return 0;
|
||||||
switch ( packet->hdr.ip.protocol ) {
|
|
||||||
case IPPROTO_HIDE_EID:
|
|
||||||
// doesn't need fragmenting, or if it does, tough
|
|
||||||
result = unwrap_ipv4_packet( reg, packet, frag1 );
|
|
||||||
break;
|
|
||||||
case IPPROTO_ICMP:
|
|
||||||
if ( ( updated = process_icmp_rloc_update( reg, packet ) ) != 0 ) {
|
|
||||||
result = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// intentional fallthrough for ICMP not addressed to us.
|
|
||||||
// -1 (error) and 1 ( dealt with ) don't need to respond.
|
|
||||||
default:
|
|
||||||
result = wrap_ipv4_packet( reg, packet, frag1, frag2 );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int process_packet( struct rlocs *reg, struct packet *pkt, struct rsp_data *frag1, struct rsp_data *frag2 )
|
||||||
int process_packet( struct rlocs *reg, struct packet *packet, struct rsp_data *frag1, struct rsp_data *frag2 )
|
|
||||||
{
|
{
|
||||||
if ( packet->hdr.ip.version == 0x04 ) {
|
int protocol = packet_find_protocol( pkt );
|
||||||
return process_ipv4_packet( reg, packet, frag1, frag2 );
|
|
||||||
|
if ( protocol == -1 ) {
|
||||||
|
warn( "Couldn't work out version / protocol of received packet, discarding" );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
warn( "Can't process IP protocol version %i yet; dropping packet", packet->hdr.ip.version );
|
if ( protocol == IPPROTO_HIDE_EID ) {
|
||||||
|
return unwrap_packet( reg, pkt, frag1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( protocol == IPPROTO_ICMP && process_icmpv4_rloc_update( reg, pkt ) ) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( protocol == IPPROTO_ICMPV6 && process_icmpv6_rloc_update( reg, pkt ) ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wrap_packet( reg, pkt, frag1, frag2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
185
pass-1/packet.c
185
pass-1/packet.c
@@ -39,8 +39,7 @@ void compute_ip_checksum(struct iphdr *pkt)
|
|||||||
pkt->check = compute_checksum( (unsigned short*) pkt, pkt->ihl * 4 );
|
pkt->check = compute_checksum( (unsigned short*) pkt, pkt->ihl * 4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int build_wrapped_ipv4_packet( struct peer_context *pctx, struct packet *pkt, struct rsp_data *out )
|
||||||
int build_wrapped_ipv4_packet(struct rlocs *reg, struct rloc * s_rloc, struct rloc *d_rloc, struct packet *pkt, struct rsp_data *out)
|
|
||||||
{
|
{
|
||||||
struct iphdr *wrap_hdr = (struct iphdr *) out->scratch;
|
struct iphdr *wrap_hdr = (struct iphdr *) out->scratch;
|
||||||
uint16_t wrap_hdr_size = sizeof( struct iphdr );
|
uint16_t wrap_hdr_size = sizeof( struct iphdr );
|
||||||
@@ -69,8 +68,8 @@ int build_wrapped_ipv4_packet(struct rlocs *reg, struct rloc * s_rloc, struct rl
|
|||||||
wrap_hdr->ttl = IPDEFTTL;
|
wrap_hdr->ttl = IPDEFTTL;
|
||||||
wrap_hdr->protocol = IPPROTO_HIDE_EID;
|
wrap_hdr->protocol = IPPROTO_HIDE_EID;
|
||||||
wrap_hdr->frag_off = htons( IP_DF ); // DF bit set
|
wrap_hdr->frag_off = htons( IP_DF ); // DF bit set
|
||||||
wrap_hdr->saddr = s_rloc->addr.ip4.s_addr;
|
wrap_hdr->saddr = pctx->x->addr.ip4.s_addr;
|
||||||
wrap_hdr->daddr = d_rloc->addr.ip4.s_addr;
|
wrap_hdr->daddr = pctx->y->addr.ip4.s_addr;
|
||||||
// FIXME: Do we need to set an ID ?
|
// FIXME: Do we need to set an ID ?
|
||||||
|
|
||||||
// iovec 0: encapsulating IP header.
|
// iovec 0: encapsulating IP header.
|
||||||
@@ -84,7 +83,7 @@ int build_wrapped_ipv4_packet(struct rlocs *reg, struct rloc * s_rloc, struct rl
|
|||||||
// calculate exactly how many bytes for TCP, UDP, etc. to do as little work
|
// calculate exactly how many bytes for TCP, UDP, etc. to do as little work
|
||||||
// as we can get away with, here. fragments > 0 don't need encrypting at all
|
// as we can get away with, here. fragments > 0 don't need encrypting at all
|
||||||
enc_size = rlocs_encrypt(
|
enc_size = rlocs_encrypt(
|
||||||
reg, s_rloc, d_rloc,
|
pctx,
|
||||||
(unsigned char *)&pkt->hdr, bytes_to_encrypt,
|
(unsigned char *)&pkt->hdr, bytes_to_encrypt,
|
||||||
pkt_enc_data, IP_MAXPACKET - wrap_hdr_size - 2
|
pkt_enc_data, IP_MAXPACKET - wrap_hdr_size - 2
|
||||||
);
|
);
|
||||||
@@ -161,21 +160,62 @@ void build_icmp_too_big( uint16_t max_mtu, struct in_addr *rloc_src, struct pack
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wrap_ipv4_packet( struct rlocs *reg, struct packet *pkt, struct rsp_data *frag1, struct rsp_data *frag2 )
|
struct peer_context *packet_peer_context( struct rlocs *reg, struct packet *pkt, int wrapping )
|
||||||
{
|
{
|
||||||
struct rloc *s_rloc, *d_rloc;
|
char bad_eid_txt[128] = {0};
|
||||||
|
struct rloc *src_rloc = NULL, *dst_rloc = NULL;
|
||||||
|
struct in_addr *ip4_src = (struct in_addr*) &pkt->hdr.ip.saddr;
|
||||||
|
struct in_addr *ip4_dst = (struct in_addr*) &pkt->hdr.ip.daddr;
|
||||||
|
|
||||||
if ( ( s_rloc = rloc_find_for_ipv4( reg, (struct in_addr *)&pkt->hdr.ip.saddr ) ) == NULL ) {
|
|
||||||
debug( "Couldn't find source RLOC for (TODO), dropping packet" );
|
switch( pkt->hdr.ip.version ) {
|
||||||
return 0;
|
case 0x04: // ipv4
|
||||||
|
src_rloc = rloc_find_for_ipv4( reg, ip4_src );
|
||||||
|
if ( src_rloc == NULL ) {
|
||||||
|
inet_ntop( AF_INET, ip4_src, bad_eid_txt, 128 );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ( d_rloc = rloc_find_for_ipv4( reg, (struct in_addr *)&pkt->hdr.ip.daddr ) ) == NULL ) {
|
dst_rloc = rloc_find_for_ipv4( reg, (struct in_addr *)&pkt->hdr.ip.daddr );
|
||||||
debug( "Couldn't find destination RLOC for (TODO), dropping packet" );
|
if ( dst_rloc == NULL ) {
|
||||||
return 0;
|
inet_ntop( AF_INET, ip4_dst, bad_eid_txt, 128 );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x06: // ipv6
|
||||||
|
src_rloc = rloc_find_for_ipv6( reg, &pkt->hdr.ip6.ip6_src );
|
||||||
|
if ( src_rloc == NULL) {
|
||||||
|
inet_ntop( AF_INET6, &pkt->hdr.ip6.ip6_src, bad_eid_txt, 128 );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t max_size = rlocs_get_path_mtu( reg, s_rloc, d_rloc );
|
dst_rloc = rloc_find_for_ipv6( reg, &pkt->hdr.ip6.ip6_dst );
|
||||||
|
if (dst_rloc == NULL ) {
|
||||||
|
inet_ntop( AF_INET6, &pkt->hdr.ip6.ip6_dst, bad_eid_txt, 128 );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( src_rloc == NULL ) {
|
||||||
|
warn( "Couldn't find source RLOC for %s, discarding packet", bad_eid_txt );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( dst_rloc == NULL ) {
|
||||||
|
warn( "Couldn't find destination RLOC for %s, discarding packet", bad_eid_txt );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( wrapping ) { // when wrapping, src=x, dst=y
|
||||||
|
return rlocs_get_peer_ctx( reg, src_rloc, dst_rloc );
|
||||||
|
} else { // when unwrapping, src=y, dst=x
|
||||||
|
return rlocs_get_peer_ctx( reg, dst_rloc, src_rloc );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int wrap_ipv4_packet_in_ipv4( struct peer_context *pctx, struct packet *pkt, struct rsp_data *frag1, struct rsp_data *frag2 )
|
||||||
|
{
|
||||||
|
|
||||||
|
uint16_t max_size = pctx->path_mtu;
|
||||||
uint16_t pkt_tot_len = ntohs( pkt->hdr.ip.tot_len );
|
uint16_t pkt_tot_len = ntohs( pkt->hdr.ip.tot_len );
|
||||||
uint16_t pkt_hdr_len = pkt->hdr.ip.ihl * 4;
|
uint16_t pkt_hdr_len = pkt->hdr.ip.ihl * 4;
|
||||||
|
|
||||||
@@ -186,7 +226,7 @@ int wrap_ipv4_packet( struct rlocs *reg, struct packet *pkt, struct rsp_data *fr
|
|||||||
debug( "Packet needs fragmenting" );
|
debug( "Packet needs fragmenting" );
|
||||||
// DF bit set, so return ICMP Too Big
|
// DF bit set, so return ICMP Too Big
|
||||||
if ( ntohs( pkt->hdr.ip.frag_off ) & IP_DF ) {
|
if ( ntohs( pkt->hdr.ip.frag_off ) & IP_DF ) {
|
||||||
build_icmp_too_big( max_size, &s_rloc->addr.ip4, pkt, frag1 );
|
build_icmp_too_big( max_size, &pctx->x->addr.ip4, pkt, frag1 );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,13 +263,13 @@ int wrap_ipv4_packet( struct rlocs *reg, struct packet *pkt, struct rsp_data *fr
|
|||||||
compute_ip_checksum( &pkt->hdr.ip );
|
compute_ip_checksum( &pkt->hdr.ip );
|
||||||
compute_ip_checksum( &pkt2->hdr.ip );
|
compute_ip_checksum( &pkt2->hdr.ip );
|
||||||
|
|
||||||
if ( !build_wrapped_ipv4_packet( reg, s_rloc, d_rloc, pkt2, frag2 ) ) {
|
if ( !build_wrapped_ipv4_packet( pctx, pkt2, frag2 ) ) {
|
||||||
debug( "Couldn't wrap packet 2 of 2 ");
|
debug( "Couldn't wrap packet 2 of 2 ");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !build_wrapped_ipv4_packet( reg, s_rloc, d_rloc, pkt, frag1 ) ) {
|
if ( !build_wrapped_ipv4_packet( pctx, pkt, frag1 ) ) {
|
||||||
debug( "Couldn't wrap packet 1 of %i", num_packets );
|
debug( "Couldn't wrap packet 1 of %i", num_packets );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -237,15 +277,65 @@ int wrap_ipv4_packet( struct rlocs *reg, struct packet *pkt, struct rsp_data *fr
|
|||||||
return num_packets;
|
return num_packets;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wrap_ipv6_packet(struct rlocs *reg, struct packet *pkt, struct rsp_data *out)
|
int wrap_ipv6_packet_in_ipv4(struct peer_context *pctx, struct packet *pkt, struct rsp_data *frag1, struct rsp_data *frag2)
|
||||||
{
|
{
|
||||||
warn( "STUB: wrap_ipv6_packet" );
|
warn( "STUB: wrap_ipv6_packet_in_ipv4" );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int wrap_ipv4_packet_in_ipv6(struct peer_context *pctx, struct packet *pkt, struct rsp_data *frag1, struct rsp_data *frag2)
|
||||||
|
{
|
||||||
|
warn( "STUB: wrap_ipv4_packet_in_ipv6" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wrap_ipv6_packet_in_ipv6(struct peer_context *pctx, struct packet *pkt, struct rsp_data *frag1, struct rsp_data *frag2)
|
||||||
|
{
|
||||||
|
warn( "STUB: wrap_ipv6_packet_in_ipv6" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wrap_packet( struct rlocs *reg, struct packet *pkt, struct rsp_data *frag1, struct rsp_data *frag2 )
|
||||||
|
{
|
||||||
|
struct peer_context *pctx = packet_peer_context( reg, pkt, 1 );
|
||||||
|
|
||||||
|
if ( pctx == NULL ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
switch ( pctx->x->family ) {
|
||||||
|
case AF_INET:
|
||||||
|
switch ( pkt->hdr.ip.version ) {
|
||||||
|
case 0x04: // ipv4
|
||||||
|
result = wrap_ipv4_packet_in_ipv4( pctx, pkt, frag1, frag2 );
|
||||||
|
break;
|
||||||
|
case 0x06: // ipv6
|
||||||
|
result = wrap_ipv6_packet_in_ipv4( pctx, pkt, frag1, frag2 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
switch ( pkt->hdr.ip.version ) {
|
||||||
|
case 0x04: // ipv4
|
||||||
|
result = wrap_ipv4_packet_in_ipv6( pctx, pkt, frag1, frag2 );
|
||||||
|
break;
|
||||||
|
case 0x06: // ipv6
|
||||||
|
result = wrap_ipv6_packet_in_ipv6( pctx, pkt, frag1, frag2 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
warn( "Unknown family of peer context: %i", pctx->x->family );
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int unwrap_ipv4_packet(struct rlocs* reg, struct packet *pkt, struct rsp_data *out)
|
int unwrap_ipv4_packet( struct peer_context *pctx, struct packet *pkt, struct rsp_data *out )
|
||||||
{
|
{
|
||||||
out->count = 2;
|
out->count = 2;
|
||||||
assert( out->count < MAX_IOVS );
|
assert( out->count < MAX_IOVS );
|
||||||
@@ -256,24 +346,6 @@ int unwrap_ipv4_packet(struct rlocs* reg, struct packet *pkt, struct rsp_data *o
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to know source and destination rloc to decrypt the packet
|
|
||||||
struct rloc *s_rloc, *d_rloc;
|
|
||||||
struct in_addr tmp;
|
|
||||||
|
|
||||||
tmp.s_addr = pkt->hdr.ip.saddr;
|
|
||||||
if ( ( s_rloc = rloc_find_by_address( reg, &tmp, NULL ) ) == NULL ) {
|
|
||||||
warn( "Couldn't find rloc from source IP, dropping packet" );
|
|
||||||
// TODO: we should be able to specify we need it to have a private key
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp.s_addr = pkt->hdr.ip.daddr;
|
|
||||||
if ( ( d_rloc = rloc_find_by_address( reg, &tmp, NULL ) ) == NULL ) {
|
|
||||||
warn( "Couldn't find rloc from destination IP, dropping packet" );
|
|
||||||
// TODO: we should be able to specify we need it to have a private key
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t hdr_size = pkt->hdr.ip.ihl * 4;
|
uint16_t hdr_size = pkt->hdr.ip.ihl * 4;
|
||||||
uint16_t encrypted_size = ntohs( *((uint16_t*)pkt + ( hdr_size / 2 )) );
|
uint16_t encrypted_size = ntohs( *((uint16_t*)pkt + ( hdr_size / 2 )) );
|
||||||
info( "encrypted_size: %u", encrypted_size );
|
info( "encrypted_size: %u", encrypted_size );
|
||||||
@@ -282,10 +354,7 @@ int unwrap_ipv4_packet(struct rlocs* reg, struct packet *pkt, struct rsp_data *o
|
|||||||
unsigned char *encrypted_data = ((unsigned char *)pkt) + hdr_size + 2;
|
unsigned char *encrypted_data = ((unsigned char *)pkt) + hdr_size + 2;
|
||||||
unsigned char *scratch = &out->scratch[0];
|
unsigned char *scratch = &out->scratch[0];
|
||||||
|
|
||||||
int decrypted_size = rlocs_decrypt(
|
int decrypted_size = rlocs_decrypt( pctx, encrypted_data, encrypted_size, scratch, IP_MAXPACKET );
|
||||||
reg, d_rloc, s_rloc,
|
|
||||||
encrypted_data, encrypted_size, scratch, IP_MAXPACKET
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( decrypted_size < 0 ) {
|
if ( decrypted_size < 0 ) {
|
||||||
warn( "Failed to decrypt packet!" );
|
warn( "Failed to decrypt packet!" );
|
||||||
@@ -307,14 +376,40 @@ int unwrap_ipv4_packet(struct rlocs* reg, struct packet *pkt, struct rsp_data *o
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug( "Finished unwrapping IPv4 packet" );
|
||||||
info( "Finished unwrapping IPv4 packet" );
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int unwrap_ipv6_packet(struct rlocs *reg, struct packet *pkt, struct rsp_data *out)
|
int unwrap_ipv6_packet(struct peer_context *pctx, struct packet *pkt, struct rsp_data *out)
|
||||||
{
|
{
|
||||||
warn( "STUB: unwrap_ipv6_packet" );
|
warn( "STUB: unwrap_ipv6_packet" );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int unwrap_packet( struct rlocs *reg, struct packet *pkt, struct rsp_data *out )
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
struct peer_context *pctx = packet_peer_context( reg, pkt, 0 );
|
||||||
|
|
||||||
|
if ( pctx == NULL ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( pkt->hdr.ip.version ) {
|
||||||
|
case 0x04:
|
||||||
|
result = unwrap_ipv4_packet( pctx, pkt, out );
|
||||||
|
break;
|
||||||
|
case 0x06:
|
||||||
|
result = unwrap_ipv6_packet( pctx, pkt, out );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
warn( "Couldn't unwrap packet with version %i, discarding", pkt->hdr.ip.version );
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@ struct packet {
|
|||||||
// 0 - wrapping ip header, including enc_size
|
// 0 - wrapping ip header, including enc_size
|
||||||
// 1 - encrypted portion of payload, in scratch.
|
// 1 - encrypted portion of payload, in scratch.
|
||||||
// 2 - unencrypted portion of payload, in recv_pkt
|
// 2 - unencrypted portion of payload, in recv_pkt
|
||||||
#define MAX_IOVS 12
|
#define MAX_IOVS 3
|
||||||
struct rsp_data {
|
struct rsp_data {
|
||||||
int count;
|
int count;
|
||||||
struct iovec iovs[MAX_IOVS];
|
struct iovec iovs[MAX_IOVS];
|
||||||
@@ -42,19 +42,25 @@ struct rsp_data {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline int packet_find_protocol( struct packet *pkt )
|
||||||
|
{
|
||||||
|
if ( pkt->hdr.ip.version == 0x04 ) {
|
||||||
|
return pkt->hdr.ip.protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pkt->hdr.ip.version == 0x06 ) {
|
||||||
|
return pkt->hdr.ip6.ip6_nxt;
|
||||||
|
}
|
||||||
|
|
||||||
// If we need more fragments than this, I am a sad person
|
return -1;
|
||||||
#define MAX_PACKET_FRAGMENTS 4
|
}
|
||||||
|
|
||||||
void compute_ip_checksum( struct iphdr* pkt );
|
void compute_ip_checksum( struct iphdr* pkt );
|
||||||
|
|
||||||
int wrap_ipv4_packet( struct rlocs *reg, struct packet *pkt, struct rsp_data *frag1, struct rsp_data *frag2 );
|
int wrap_packet( struct rlocs *reg, struct packet *pkt, struct rsp_data *frag1, struct rsp_data *frag2 );
|
||||||
int wrap_ipv6_packet(struct rlocs* reg, struct packet *pkt, struct rsp_data *out);
|
int unwrap_packet( struct rlocs *reg, struct packet *pkt, struct rsp_data *out );
|
||||||
|
|
||||||
int unwrap_ipv4_packet(struct rlocs* reg, struct packet *pkt, struct rsp_data *out);
|
|
||||||
int unwrap_ipv6_packet(struct rlocs* reg, struct packet *pkt, struct rsp_data *out);
|
|
||||||
|
|
||||||
|
struct peer_context *packet_peer_context( struct rlocs *reg, struct packet *pkt, int direction );
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -558,6 +558,10 @@ int rlocs_update_peer_context(struct rlocs *reg, struct rloc *x, struct rloc *y)
|
|||||||
* decrypt packet data. */
|
* decrypt packet data. */
|
||||||
|
|
||||||
EVP_CIPHER_CTX_init( &entry->ctx );
|
EVP_CIPHER_CTX_init( &entry->ctx );
|
||||||
|
|
||||||
|
entry->reg = reg;
|
||||||
|
entry->x = x;
|
||||||
|
entry->y = y;
|
||||||
entry->path_mtu = DEFAULT_PATH_MTU;
|
entry->path_mtu = DEFAULT_PATH_MTU;
|
||||||
entry->in_use = 1;
|
entry->in_use = 1;
|
||||||
|
|
||||||
@@ -573,16 +577,14 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline struct peer_context *rlocs_get_peer_ctx( struct rlocs *reg, struct rloc *x, struct rloc *y )
|
struct peer_context *rlocs_get_peer_ctx( struct rlocs *reg, struct rloc *x, struct rloc *y )
|
||||||
{
|
{
|
||||||
return ®->peer_contexts[x->context_id][y->context_id];
|
return ®->peer_contexts[x->context_id][y->context_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t rlocs_encrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len )
|
ssize_t rlocs_encrypt( struct peer_context *pctx, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len )
|
||||||
{
|
{
|
||||||
struct peer_context *entry = rlocs_get_peer_ctx( reg, x, y );
|
if ( !pctx->in_use && !rlocs_update_peer_context( pctx->reg, pctx->x, pctx->y ) ) {
|
||||||
|
|
||||||
if ( !entry->in_use && !rlocs_update_peer_context( reg, x, y ) ) {
|
|
||||||
warn( "Couldn't build an encryption context for these rlocs" );
|
warn( "Couldn't build an encryption context for these rlocs" );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -596,29 +598,29 @@ ssize_t rlocs_encrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsign
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *iv = dest;
|
unsigned char *iv = dest;
|
||||||
unsigned char *secret = (unsigned char *)&entry->secret[0];
|
unsigned char *secret = (unsigned char *)&pctx->secret[0];
|
||||||
|
|
||||||
size_t written = 16;
|
size_t written = 16;
|
||||||
int outl = dest_len - written;
|
int outl = dest_len - written;
|
||||||
|
|
||||||
RAND_pseudo_bytes( iv, 16 );
|
RAND_pseudo_bytes( iv, 16 );
|
||||||
|
|
||||||
if ( !EVP_EncryptInit_ex( &entry->ctx, EVP_aes_256_gcm(), NULL, NULL, NULL ) ) {
|
if ( !EVP_EncryptInit_ex( &pctx->ctx, EVP_aes_256_gcm(), NULL, NULL, NULL ) ) {
|
||||||
warn( "EVP_EncryptInit_ex() (1) failed" );
|
warn( "EVP_EncryptInit_ex() (1) failed" );
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !EVP_CIPHER_CTX_ctrl( &entry->ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) {
|
if ( !EVP_CIPHER_CTX_ctrl( &pctx->ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) {
|
||||||
warn ("Setting IV len to 16 failed" );
|
warn ("Setting IV len to 16 failed" );
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !EVP_EncryptInit_ex( &entry->ctx, NULL, NULL, secret, iv ) ) {
|
if ( !EVP_EncryptInit_ex( &pctx->ctx, NULL, NULL, secret, iv ) ) {
|
||||||
warn( "EVP_EncryptInit_ex() (2) failed" );
|
warn( "EVP_EncryptInit_ex() (2) failed" );
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !EVP_EncryptUpdate( &entry->ctx, dest + written, &outl, data, data_len ) ) {
|
if ( !EVP_EncryptUpdate( &pctx->ctx, dest + written, &outl, data, data_len ) ) {
|
||||||
warn( "EVP_EncryptUpdate() failed" );
|
warn( "EVP_EncryptUpdate() failed" );
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -628,7 +630,7 @@ ssize_t rlocs_encrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsign
|
|||||||
written += outl;
|
written += outl;
|
||||||
outl = dest_len - written;
|
outl = dest_len - written;
|
||||||
|
|
||||||
if ( !EVP_EncryptFinal_ex( &entry->ctx, dest + written, &outl ) ) {
|
if ( !EVP_EncryptFinal_ex( &pctx->ctx, dest + written, &outl ) ) {
|
||||||
warn( "EVP_EncryptFinal_ex() failed" );
|
warn( "EVP_EncryptFinal_ex() failed" );
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -636,7 +638,7 @@ ssize_t rlocs_encrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsign
|
|||||||
written += outl;
|
written += outl;
|
||||||
|
|
||||||
/* Get the tag */
|
/* Get the tag */
|
||||||
if( !EVP_CIPHER_CTX_ctrl( &entry->ctx, EVP_CTRL_GCM_GET_TAG, 16, dest + written ) ) {
|
if( !EVP_CIPHER_CTX_ctrl( &pctx->ctx, EVP_CTRL_GCM_GET_TAG, 16, dest + written ) ) {
|
||||||
warn( "Getting GCM tag for our encrypted data failed" );
|
warn( "Getting GCM tag for our encrypted data failed" );
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -648,17 +650,15 @@ fail:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t rlocs_decrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len )
|
ssize_t rlocs_decrypt( struct peer_context *pctx, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len )
|
||||||
{
|
{
|
||||||
struct peer_context *entry = rlocs_get_peer_ctx( reg, x, y );
|
if ( !pctx->in_use && !rlocs_update_peer_context( pctx->reg, pctx->x, pctx->y ) ) {
|
||||||
|
|
||||||
if ( !entry->in_use && !rlocs_update_peer_context( reg, x, y ) ) {
|
|
||||||
warn( "Couldn't build a decryption context for these rlocs" );
|
warn( "Couldn't build a decryption context for these rlocs" );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *iv = data;
|
unsigned char *iv = data;
|
||||||
unsigned char *secret = (unsigned char *)&entry->secret[0];
|
unsigned char *secret = (unsigned char *)&pctx->secret[0];
|
||||||
|
|
||||||
size_t written = 0;
|
size_t written = 0;
|
||||||
int outl = dest_len;
|
int outl = dest_len;
|
||||||
@@ -668,22 +668,22 @@ ssize_t rlocs_decrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsign
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !EVP_DecryptInit_ex( &entry->ctx, EVP_aes_256_gcm(), NULL, NULL, NULL ) ) {
|
if ( !EVP_DecryptInit_ex( &pctx->ctx, EVP_aes_256_gcm(), NULL, NULL, NULL ) ) {
|
||||||
warn( "EVP_DecryptInit_ex() (1) failed" );
|
warn( "EVP_DecryptInit_ex() (1) failed" );
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !EVP_CIPHER_CTX_ctrl(&entry->ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) {
|
if ( !EVP_CIPHER_CTX_ctrl(&pctx->ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) {
|
||||||
warn ("Setting IV len to 16 failed" );
|
warn ("Setting IV len to 16 failed" );
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !EVP_DecryptInit_ex( &entry->ctx, NULL, NULL, secret, iv ) ) {
|
if ( !EVP_DecryptInit_ex( &pctx->ctx, NULL, NULL, secret, iv ) ) {
|
||||||
warn( "EVP_DecryptInit_ex() (2) failed" );
|
warn( "EVP_DecryptInit_ex() (2) failed" );
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !EVP_DecryptUpdate( &entry->ctx, dest, &outl, data + 16, data_len - 32 ) ) {
|
if ( !EVP_DecryptUpdate( &pctx->ctx, dest, &outl, data + 16, data_len - 32 ) ) {
|
||||||
warn( "EVP_DecryptUpdate() failed" );
|
warn( "EVP_DecryptUpdate() failed" );
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -691,12 +691,12 @@ ssize_t rlocs_decrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsign
|
|||||||
written += outl;
|
written += outl;
|
||||||
outl = dest_len - written;
|
outl = dest_len - written;
|
||||||
|
|
||||||
if( !EVP_CIPHER_CTX_ctrl(&entry->ctx, EVP_CTRL_GCM_SET_TAG, 16, data + (data_len - 16 ) ) ) {
|
if( !EVP_CIPHER_CTX_ctrl(&pctx->ctx, EVP_CTRL_GCM_SET_TAG, 16, data + (data_len - 16 ) ) ) {
|
||||||
warn( "Failed to provide GCM tag to decrypt routine" );
|
warn( "Failed to provide GCM tag to decrypt routine" );
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !EVP_DecryptFinal_ex( &entry->ctx, dest + written, &outl ) ) {
|
if ( !EVP_DecryptFinal_ex( &pctx->ctx, dest + written, &outl ) ) {
|
||||||
warn( "EVP_DecryptFinal_ex() failed - bad tag?" );
|
warn( "EVP_DecryptFinal_ex() failed - bad tag?" );
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@@ -23,12 +23,13 @@ struct peer_context {
|
|||||||
|
|
||||||
unsigned int path_mtu;
|
unsigned int path_mtu;
|
||||||
|
|
||||||
/* Probably don't need these
|
struct rlocs *reg;
|
||||||
struct rloc *rloc_x;
|
struct rloc *x;
|
||||||
struct rloc *rloc_y;
|
struct rloc *y;
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct peer_context PeerCtx;
|
||||||
|
|
||||||
struct rloc {
|
struct rloc {
|
||||||
short family;
|
short family;
|
||||||
union {
|
union {
|
||||||
@@ -95,13 +96,15 @@ int rlocs_find_two_ipv4(
|
|||||||
struct rloc **d_rloc_ptr, struct in_addr *d_rloc_addr
|
struct rloc **d_rloc_ptr, struct in_addr *d_rloc_addr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
struct peer_context *rlocs_get_peer_ctx( struct rlocs *reg, struct rloc *x, struct rloc *y );
|
||||||
|
|
||||||
int rloc_add_private_key( struct rloc *rloc, char *filename );
|
int rloc_add_private_key( struct rloc *rloc, char *filename );
|
||||||
|
|
||||||
void rlocs_debug_output( struct rlocs *reg );
|
void rlocs_debug_output( struct rlocs *reg );
|
||||||
|
|
||||||
/* Returns -1 on error, or number of bytes written */
|
/* Returns -1 on error, or number of bytes written */
|
||||||
ssize_t rlocs_encrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len );
|
ssize_t rlocs_encrypt( struct peer_context *pctx, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len );
|
||||||
ssize_t rlocs_decrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len );
|
ssize_t rlocs_decrypt( struct peer_context *pctx, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len );
|
||||||
|
|
||||||
unsigned short rlocs_get_path_mtu( struct rlocs *reg, struct rloc *x, struct rloc *y );
|
unsigned short rlocs_get_path_mtu( struct rlocs *reg, struct rloc *x, struct rloc *y );
|
||||||
void rlocs_set_path_mtu( struct rlocs *reg, struct rloc *x, struct rloc *y, unsigned short new_mtu );
|
void rlocs_set_path_mtu( struct rlocs *reg, struct rloc *x, struct rloc *y, unsigned short new_mtu );
|
||||||
|
Reference in New Issue
Block a user