Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for IPv6 traffic dump #53

Merged
merged 1 commit into from
Apr 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 101 additions & 42 deletions base/network.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,62 +107,104 @@ int network_handler_destroy(mod,handlerp)
return(0);
}

int network_process_packet(handler,timestamp,data,length)
int network_process_packet(handler,timestamp,data,length,af)
n_handler *handler;
struct timeval *timestamp;
UCHAR *data;
int length;
int af;
{
int r;
int hlen;
packet p;
u_short off;
int proto;

/*We can pretty much ignore all the options*/
memcpy(&p.ts,timestamp,sizeof(struct timeval));
p.base=data;
p._len=length;
p.data=data;
p.len=length;
p.ip=(struct ip *)data;
p.af=af;

if(p.len < 20) {
if(!(NET_print_flags & NET_PRINT_JSON))
printf("Malformed packet, packet too small to contain IP header, skipping ...\n");
return(0);
}

/*Handle, or rather mishandle, fragmentation*/
off=ntohs(p.ip->ip_off);

if((off & 0x1fff) || /*Later fragment*/
(off & 0x2000)){ /*More fragments*/
/* fprintf(stderr,"Fragmented packet! rejecting\n"); */
return(0);
}

hlen=p.ip->ip_hl * 4;
p.data += hlen;
p.len = ntohs(p.ip->ip_len);

if(p.len > length) {
if(!(NET_print_flags & NET_PRINT_JSON))
printf("Malformed packet, size from IP header is larger than size reported by libpcap, skipping ...\n");
return(0);
memset(&p.i_addr.so_st, 0x0, sizeof(struct sockaddr_storage));
memset(&p.r_addr.so_st, 0x0, sizeof(struct sockaddr_storage));

if(af == AF_INET) {
p.l3_hdr.ip=(struct ip *)data;
memcpy(&p.i_addr.so_in.sin_addr, &p.l3_hdr.ip->ip_src, sizeof(struct in_addr));
p.i_addr.so_in.sin_family = AF_INET;
memcpy(&p.r_addr.so_in.sin_addr, &p.l3_hdr.ip->ip_dst, sizeof(struct in_addr));
p.r_addr.so_in.sin_family = AF_INET;

/*Handle, or rather mishandle, fragmentation*/
off=ntohs(p.l3_hdr.ip->ip_off);

if((off & 0x1fff) || /*Later fragment*/
(off & 0x2000)){ /*More fragments*/
/* fprintf(stderr,"Fragmented packet! rejecting\n"); */
return(0);
}

hlen=p.l3_hdr.ip->ip_hl * 4;
p.data += hlen;
p.len = ntohs(p.l3_hdr.ip->ip_len);

if(p.len > length) {
if(!(NET_print_flags & NET_PRINT_JSON))
printf("Malformed packet, size from IP header is larger than size reported by libpcap, skipping ...\n");
return(0);
}

if (p.len == 0) {
DBG((0,"ip length reported as 0, presumed to be because of 'TCP segmentation offload' (TSO)\n"));
p.len = p._len;
}
p.len -= hlen;

proto = p.l3_hdr.ip->ip_p;
} else {
p.l3_hdr.ip6=(struct ip6_hdr *)data;
memcpy(&p.i_addr.so_in6.sin6_addr, &p.l3_hdr.ip6->ip6_src, sizeof(struct in6_addr));
p.i_addr.so_in6.sin6_family = AF_INET6;
memcpy(&p.r_addr.so_in6.sin6_addr, &p.l3_hdr.ip6->ip6_dst, sizeof(struct in6_addr));
p.r_addr.so_in6.sin6_family = AF_INET6;
// Skip packets with header extensions
if(p.l3_hdr.ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt != IPPROTO_TCP) {
return 0;
}

hlen=40; // Fixed header size with no extension
p.data += hlen;
p.len = ntohs(p.l3_hdr.ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
if(p.len > length) {
if(!(NET_print_flags & NET_PRINT_JSON))
printf("Malformed packet, size from IP header is larger than size reported by libpcap, skipping ...\n");
return(0);
}

if (p.len == 0) {
DBG((0,"ip length reported as 0, presumed to be because of 'TCP segmentation offload' (TSO)\n"));
p.len = p._len;
}

proto = p.l3_hdr.ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
}

if (p.len == 0) {
DBG((0,"ip length reported as 0, presumed to be because of 'TCP segmentation offload' (TSO)\n"));
p.len = p._len;
}
p.len -= hlen;

switch(p.ip->ip_p){
switch(proto){
case IPPROTO_TCP:
if((r=process_tcp_packet(handler->mod,handler->ctx,&p)))
ERETURN(r);
break;
if((r=process_tcp_packet(handler->mod,handler->ctx,&p)))
ERETURN(r);
break;
}

return(0);
}

Expand Down Expand Up @@ -238,26 +280,43 @@ int timestamp_diff(t1,t0,diff)



int lookuphostname(addr,namep)
struct in_addr *addr;
int lookuphostname(so_st,namep)
struct sockaddr_storage *so_st;
char **namep;
{
struct hostent *ne=0;
int r = 1;
*namep = calloc(1, NI_MAXHOST);
void *addr = NULL;

if(!(NET_print_flags & NET_PRINT_NO_RESOLVE)){
ne=gethostbyaddr((char *)addr,4,AF_INET);
if(!(NET_print_flags & NET_PRINT_NO_RESOLVE)) {
r = getnameinfo((struct sockaddr *) so_st, sizeof(struct sockaddr_storage), *namep, NI_MAXHOST, NULL, 0, 0);
}

if(!ne){
*namep=strdup((char *)inet_ntoa(*addr));
}
else{
*namep=strdup(ne->h_name);
if(r) {
if(so_st->ss_family == AF_INET) {
addr = &((struct sockaddr_in *) so_st)->sin_addr;
} else {
addr = &((struct sockaddr_in6 *) so_st)->sin6_addr;
}
inet_ntop(so_st->ss_family, addr, *namep, INET6_ADDRSTRLEN);
}

return(0);
}




int addrtotext(so_st,namep)
struct sockaddr_storage *so_st;
char **namep;
{
*namep = calloc(1, NI_MAXHOST);
void *addr = NULL;

if(so_st->ss_family == AF_INET) {
addr = &((struct sockaddr_in *) so_st)->sin_addr;
} else {
addr = &((struct sockaddr_in6 *) so_st)->sin6_addr;
}
inet_ntop(so_st->ss_family, addr, *namep, INET6_ADDRSTRLEN);

return(0);
}
21 changes: 19 additions & 2 deletions base/network.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
#endif
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <r_time.h>
#include <r_data.h>
Expand All @@ -77,12 +78,13 @@ int network_handler_create PROTO_LIST((proto_mod *mod,
n_handler **handlerp));
int network_handler_destroy PROTO_LIST((proto_mod *mod,n_handler **handlerp));
int network_process_packet PROTO_LIST((n_handler *handler,
struct timeval *timestamp,UCHAR *data,int length));
struct timeval *timestamp,UCHAR *data,int length,int af));
int packet_copy PROTO_LIST((packet *in,packet **out));
int packet_destroy PROTO_LIST((packet *p));
int timestamp_diff PROTO_LIST(( struct timeval *t1,struct timeval *t0,
struct timeval *diff));
int lookuphostname PROTO_LIST((struct in_addr *addr,char **name));
int lookuphostname PROTO_LIST((struct sockaddr_storage *addr,char **name));
int addrtotext PROTO_LIST((struct sockaddr_storage *addr,char **name));

struct packet_ {
struct timeval ts;
Expand All @@ -94,7 +96,22 @@ struct packet_ {
/*These just save us the effort of doing casts to the data
segments*/
struct ip *ip; /*The IP header*/
int af;
union {
struct ip *ip; /*The IP header*/
struct ip6_hdr *ip6; /*The IP header*/
} l3_hdr;
struct tcphdr *tcp; /*The TCP header*/
union {
struct sockaddr_storage so_st;
struct sockaddr_in so_in;
struct sockaddr_in6 so_in6;
} i_addr;
union {
struct sockaddr_storage so_st;
struct sockaddr_in so_in;
struct sockaddr_in6 so_in6;
} r_addr;
};

#include "tcpconn.h"
Expand Down
10 changes: 7 additions & 3 deletions base/pcap-snoop.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,9 @@ void pcap_cb(ptr,hdr,data)
len+=4;
}

if(type!=ETHERTYPE_IP)
if(type!=ETHERTYPE_IP && type!=ETHERTYPE_IPV6)
return;

break;
case DLT_IEEE802:
data+=22;
Expand Down Expand Up @@ -276,7 +276,11 @@ void pcap_cb(ptr,hdr,data)
break;
#endif
}
network_process_packet(n,(struct timeval *) &hdr->ts,(u_char *)data,len);

if(type == ETHERTYPE_IPV6)
network_process_packet(n,(struct timeval *) &hdr->ts,(u_char *)data,len, AF_INET6);
else
network_process_packet(n,(struct timeval *) &hdr->ts,(u_char *)data,len, AF_INET);

if(packet_cnt == conn_freq) {
packet_cnt = 0;
Expand Down
8 changes: 4 additions & 4 deletions base/proto_mod.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ struct proto_mod_vtbl_ {
int (*create) PROTO_LIST((void *handle,proto_ctx *ctx,
tcp_conn *conn,
proto_obj **objp,
struct in_addr *i_addr,u_short i_port,
struct in_addr *r_addr,u_short r_port,struct timeval *time_base));
struct sockaddr_storage *i_addr,u_short i_port,
struct sockaddr_storage *r_addr,u_short r_port,struct timeval *time_base));
int (*destroy_ctx) PROTO_LIST((void *handle,proto_ctx **ctxp));
int (*destroy) PROTO_LIST((proto_obj **objp));
int (*data) PROTO_LIST((proto_obj *obj,segment *data,int direction));
Expand Down Expand Up @@ -89,8 +89,8 @@ struct logger_mod_vtbl_ {
int (*init) PROTO_LIST((void *data));
//deinit must be async signal safe(!!!)
int (*deinit) PROTO_LIST(());
int (*create) PROTO_LIST((proto_obj **objp, struct in_addr *i_addr,u_short i_port,
struct in_addr *r_addr,u_short r_port,struct timeval *time_base));
int (*create) PROTO_LIST((proto_obj **objp, struct sockaddr_storage *i_addr,u_short i_port,
struct sockaddr_storage *r_addr,u_short r_port,struct timeval *time_base));
int (*destroy) PROTO_LIST((proto_obj **objp));
int (*data) PROTO_LIST((proto_obj *obj,unsigned char *data,unsigned int len,int direction));
int (*close) PROTO_LIST((proto_obj *obj,unsigned char *data,unsigned int len,int direction));
Expand Down
24 changes: 14 additions & 10 deletions base/tcpconn.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,16 @@ static int zero_conn(conn)
return(0);
}

int tcp_find_conn(tcp_conn **connp, int *directionp,struct in_addr *saddr,
u_short sport, struct in_addr *daddr, u_short dport)
int tcp_find_conn(tcp_conn **connp, int *directionp,struct sockaddr_storage *saddr,
u_short sport, struct sockaddr_storage *daddr, u_short dport)
{
conn_struct *conn;

for(conn=first_conn;conn;conn=conn->next){

if(sport == conn->conn.i_port && dport==conn->conn.r_port){
if(!memcmp(saddr,&conn->conn.i_addr,sizeof(struct in_addr))
&& !memcmp(daddr,&conn->conn.r_addr,sizeof(struct in_addr)))
if(!memcmp(saddr,&conn->conn.i_addr,sizeof(struct sockaddr_storage))
&& !memcmp(daddr,&conn->conn.r_addr,sizeof(struct sockaddr_storage)))
{
*directionp=DIR_I2R;
*connp=&(conn->conn);
Expand All @@ -88,8 +88,8 @@ int tcp_find_conn(tcp_conn **connp, int *directionp,struct in_addr *saddr,
}

if(dport == conn->conn.i_port && sport==conn->conn.r_port){
if(!memcmp(saddr,&conn->conn.r_addr,sizeof(struct in_addr))
&& !memcmp(daddr,&conn->conn.i_addr,sizeof(struct in_addr)))
if(!memcmp(saddr,&conn->conn.r_addr,sizeof(struct sockaddr_storage))
&& !memcmp(daddr,&conn->conn.i_addr,sizeof(struct sockaddr_storage)))
{
*directionp=DIR_R2I;
*connp=&(conn->conn);
Expand All @@ -101,8 +101,8 @@ int tcp_find_conn(tcp_conn **connp, int *directionp,struct in_addr *saddr,
return(R_NOT_FOUND);
}

int tcp_create_conn(tcp_conn **connp,struct in_addr *i_addr,
u_short i_port, struct in_addr *r_addr, u_short r_port)
int tcp_create_conn(tcp_conn **connp,struct sockaddr_storage *i_addr,
u_short i_port, struct sockaddr_storage *r_addr, u_short r_port)
{
conn_struct *conn=0;

Expand All @@ -115,9 +115,9 @@ int tcp_create_conn(tcp_conn **connp,struct in_addr *i_addr,
conn->conn.backptr=conn;
conn->conn.conn_number=conn_number++;

memcpy(&conn->conn.i_addr,i_addr,sizeof(struct in_addr));
memcpy(&conn->conn.i_addr,i_addr,sizeof(struct sockaddr_storage));
conn->conn.i_port=i_port;
memcpy(&conn->conn.r_addr,r_addr,sizeof(struct in_addr));
memcpy(&conn->conn.r_addr,r_addr,sizeof(struct sockaddr_storage));
conn->conn.r_port=r_port;
*connp=&(conn->conn);

Expand Down Expand Up @@ -150,6 +150,10 @@ int tcp_destroy_conn(conn)
destroy_proto_handler(&conn->analyzer);
free_tcp_segment_queue(conn->i2r.oo_queue);
free_tcp_segment_queue(conn->r2i.oo_queue);
free(conn->i_name);
free(conn->r_name);
free(conn->i_num);
free(conn->r_num);
zero_conn(conn);
free(conn->backptr);
free(conn);
Expand Down
16 changes: 10 additions & 6 deletions base/tcpconn.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,16 @@ typedef struct tcp_conn_ {
#define TCP_STATE_FIN1 5
#define TCP_STATE_CLOSED 6
/*The address which sent the first SYN*/
struct in_addr i_addr;
struct sockaddr_storage i_addr;
u_short i_port;
char *i_name;
char *i_num;

/*The address which sent the second SYN*/
struct in_addr r_addr;
struct sockaddr_storage r_addr;
u_short r_port;
char *r_name;
char *r_num;

stream_data i2r; /*The stream from initiator to responder*/
stream_data r2i; /*The stream from responder to initiator*/
Expand All @@ -90,12 +94,12 @@ typedef struct tcp_conn_ {

int tcp_find_conn PROTO_LIST((tcp_conn **connp,
int *directionp,
struct in_addr *src_addr, u_short src_port,
struct in_addr *dst_addr, u_short dst_port));
struct sockaddr_storage *src_addr, u_short src_port,
struct sockaddr_storage *dst_addr, u_short dst_port));

int tcp_create_conn PROTO_LIST((tcp_conn **connp,
struct in_addr *initiator_addr, u_short initiator_port,
struct in_addr *responder_addr, u_short responder_port));
struct sockaddr_storage *initiator_addr, u_short initiator_port,
struct sockaddr_storage *responder_addr, u_short responder_port));

int tcp_destroy_conn PROTO_LIST((tcp_conn *conn));
int free_tcp_segment_queue PROTO_LIST((segment *seg));
Expand Down
Loading