static uint8_t *swrap_marshall_packet(struct socket_info *si, const struct sockaddr *addr, enum swrap_packet_type type, const void *buf, size_t len, size_t *packet_len) { const struct sockaddr *src_addr; const struct sockaddr *dest_addr; unsigned long tcp_seqno = 0; unsigned long tcp_ack = 0; unsigned char tcp_ctl = 0; int unreachable = 0; struct timeval tv; switch (si->family) { case AF_INET: break; #ifdef HAVE_IPV6 case AF_INET6: break; #endif default: return NULL; } switch (type) { case SWRAP_CONNECT_SEND: if (si->type != SOCK_STREAM) return NULL; src_addr = si->myname; dest_addr = addr; tcp_seqno = si->io.pck_snd; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x02; /* SYN */ si->io.pck_snd += 1; break; case SWRAP_CONNECT_RECV: if (si->type != SOCK_STREAM) return NULL; dest_addr = si->myname; src_addr = addr; tcp_seqno = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x12; /** SYN,ACK */ si->io.pck_rcv += 1; break; case SWRAP_CONNECT_UNREACH: if (si->type != SOCK_STREAM) return NULL; dest_addr = si->myname; src_addr = addr; /* Unreachable: resend the data of SWRAP_CONNECT_SEND */ tcp_seqno = si->io.pck_snd - 1; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x02; /* SYN */ unreachable = 1; break; case SWRAP_CONNECT_ACK: if (si->type != SOCK_STREAM) return NULL; src_addr = si->myname; dest_addr = addr; tcp_seqno = si->io.pck_snd; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x10; /* ACK */ break; case SWRAP_ACCEPT_SEND: if (si->type != SOCK_STREAM) return NULL; dest_addr = si->myname; src_addr = addr; tcp_seqno = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x02; /* SYN */ si->io.pck_rcv += 1; break; case SWRAP_ACCEPT_RECV: if (si->type != SOCK_STREAM) return NULL; src_addr = si->myname; dest_addr = addr; tcp_seqno = si->io.pck_snd; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x12; /* SYN,ACK */ si->io.pck_snd += 1; break; case SWRAP_ACCEPT_ACK: if (si->type != SOCK_STREAM) return NULL; dest_addr = si->myname; src_addr = addr; tcp_seqno = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x10; /* ACK */ break; case SWRAP_SEND: src_addr = si->myname; dest_addr = si->peername; tcp_seqno = si->io.pck_snd; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x18; /* PSH,ACK */ si->io.pck_snd += len; break; case SWRAP_SEND_RST: dest_addr = si->myname; src_addr = si->peername; if (si->type == SOCK_DGRAM) { return swrap_marshall_packet(si, si->peername, SWRAP_SENDTO_UNREACH, buf, len, packet_len); } tcp_seqno = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x14; /** RST,ACK */ break; case SWRAP_PENDING_RST: dest_addr = si->myname; src_addr = si->peername; if (si->type == SOCK_DGRAM) { return NULL; } tcp_seqno = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x14; /* RST,ACK */ break; case SWRAP_RECV: dest_addr = si->myname; src_addr = si->peername; tcp_seqno = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x18; /* PSH,ACK */ si->io.pck_rcv += len; break; case SWRAP_RECV_RST: dest_addr = si->myname; src_addr = si->peername; if (si->type == SOCK_DGRAM) { return NULL; } tcp_seqno = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x14; /* RST,ACK */ break; case SWRAP_SENDTO: src_addr = si->myname; dest_addr = addr; si->io.pck_snd += len; break; case SWRAP_SENDTO_UNREACH: dest_addr = si->myname; src_addr = addr; unreachable = 1; break; case SWRAP_RECVFROM: dest_addr = si->myname; src_addr = addr; si->io.pck_rcv += len; break; case SWRAP_CLOSE_SEND: if (si->type != SOCK_STREAM) return NULL; src_addr = si->myname; dest_addr = si->peername; tcp_seqno = si->io.pck_snd; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x11; /* FIN, ACK */ si->io.pck_snd += 1; break; case SWRAP_CLOSE_RECV: if (si->type != SOCK_STREAM) return NULL; dest_addr = si->myname; src_addr = si->peername; tcp_seqno = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x11; /* FIN,ACK */ si->io.pck_rcv += 1; break; case SWRAP_CLOSE_ACK: if (si->type != SOCK_STREAM) return NULL; src_addr = si->myname; dest_addr = si->peername; tcp_seqno = si->io.pck_snd; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x10; /* ACK */ break; default: return NULL; } swrapGetTimeOfDay(&tv); return swrap_packet_init(&tv, src_addr, dest_addr, si->type, (const uint8_t *)buf, len, tcp_seqno, tcp_ack, tcp_ctl, unreachable, packet_len); }
static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr, enum swrap_packet_type type, const void *buf, size_t len) { const struct sockaddr_in *src_addr; const struct sockaddr_in *dest_addr; const char *file_name; unsigned long tcp_seq = 0; unsigned long tcp_ack = 0; unsigned char tcp_ctl = 0; int unreachable = 0; struct timeval tv; struct swrap_packet *packet; size_t packet_len = 0; int fd; file_name = socket_wrapper_pcap_file(); if (!file_name) { return; } switch (si->family) { case AF_INET: #ifdef HAVE_IPV6 case AF_INET6: #endif break; default: return; } switch (type) { case SWRAP_CONNECT_SEND: if (si->type != SOCK_STREAM) return; src_addr = (const struct sockaddr_in *)si->myname; dest_addr = (const struct sockaddr_in *)addr; tcp_seq = si->io.pck_snd; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x02; /* SYN */ si->io.pck_snd += 1; break; case SWRAP_CONNECT_RECV: if (si->type != SOCK_STREAM) return; dest_addr = (const struct sockaddr_in *)si->myname; src_addr = (const struct sockaddr_in *)addr; tcp_seq = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x12; /** SYN,ACK */ si->io.pck_rcv += 1; break; case SWRAP_CONNECT_UNREACH: if (si->type != SOCK_STREAM) return; dest_addr = (const struct sockaddr_in *)si->myname; src_addr = (const struct sockaddr_in *)addr; /* Unreachable: resend the data of SWRAP_CONNECT_SEND */ tcp_seq = si->io.pck_snd - 1; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x02; /* SYN */ unreachable = 1; break; case SWRAP_CONNECT_ACK: if (si->type != SOCK_STREAM) return; src_addr = (const struct sockaddr_in *)si->myname; dest_addr = (const struct sockaddr_in *)addr; tcp_seq = si->io.pck_snd; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x10; /* ACK */ break; case SWRAP_ACCEPT_SEND: if (si->type != SOCK_STREAM) return; dest_addr = (const struct sockaddr_in *)si->myname; src_addr = (const struct sockaddr_in *)addr; tcp_seq = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x02; /* SYN */ si->io.pck_rcv += 1; break; case SWRAP_ACCEPT_RECV: if (si->type != SOCK_STREAM) return; src_addr = (const struct sockaddr_in *)si->myname; dest_addr = (const struct sockaddr_in *)addr; tcp_seq = si->io.pck_snd; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x12; /* SYN,ACK */ si->io.pck_snd += 1; break; case SWRAP_ACCEPT_ACK: if (si->type != SOCK_STREAM) return; dest_addr = (const struct sockaddr_in *)si->myname; src_addr = (const struct sockaddr_in *)addr; tcp_seq = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x10; /* ACK */ break; case SWRAP_SEND: src_addr = (const struct sockaddr_in *)si->myname; dest_addr = (const struct sockaddr_in *)si->peername; tcp_seq = si->io.pck_snd; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x18; /* PSH,ACK */ si->io.pck_snd += len; break; case SWRAP_SEND_RST: dest_addr = (const struct sockaddr_in *)si->myname; src_addr = (const struct sockaddr_in *)si->peername; if (si->type == SOCK_DGRAM) { swrap_dump_packet(si, si->peername, SWRAP_SENDTO_UNREACH, buf, len); return; } tcp_seq = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x14; /** RST,ACK */ break; case SWRAP_PENDING_RST: dest_addr = (const struct sockaddr_in *)si->myname; src_addr = (const struct sockaddr_in *)si->peername; if (si->type == SOCK_DGRAM) { return; } tcp_seq = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x14; /* RST,ACK */ break; case SWRAP_RECV: dest_addr = (const struct sockaddr_in *)si->myname; src_addr = (const struct sockaddr_in *)si->peername; tcp_seq = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x18; /* PSH,ACK */ si->io.pck_rcv += len; break; case SWRAP_RECV_RST: dest_addr = (const struct sockaddr_in *)si->myname; src_addr = (const struct sockaddr_in *)si->peername; if (si->type == SOCK_DGRAM) { return; } tcp_seq = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x14; /* RST,ACK */ break; case SWRAP_SENDTO: src_addr = (const struct sockaddr_in *)si->myname; dest_addr = (const struct sockaddr_in *)addr; si->io.pck_snd += len; break; case SWRAP_SENDTO_UNREACH: dest_addr = (const struct sockaddr_in *)si->myname; src_addr = (const struct sockaddr_in *)addr; unreachable = 1; break; case SWRAP_RECVFROM: dest_addr = (const struct sockaddr_in *)si->myname; src_addr = (const struct sockaddr_in *)addr; si->io.pck_rcv += len; break; case SWRAP_CLOSE_SEND: if (si->type != SOCK_STREAM) return; src_addr = (const struct sockaddr_in *)si->myname; dest_addr = (const struct sockaddr_in *)si->peername; tcp_seq = si->io.pck_snd; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x11; /* FIN, ACK */ si->io.pck_snd += 1; break; case SWRAP_CLOSE_RECV: if (si->type != SOCK_STREAM) return; dest_addr = (const struct sockaddr_in *)si->myname; src_addr = (const struct sockaddr_in *)si->peername; tcp_seq = si->io.pck_rcv; tcp_ack = si->io.pck_snd; tcp_ctl = 0x11; /* FIN,ACK */ si->io.pck_rcv += 1; break; case SWRAP_CLOSE_ACK: if (si->type != SOCK_STREAM) return; src_addr = (const struct sockaddr_in *)si->myname; dest_addr = (const struct sockaddr_in *)si->peername; tcp_seq = si->io.pck_snd; tcp_ack = si->io.pck_rcv; tcp_ctl = 0x10; /* ACK */ break; default: return; } swrapGetTimeOfDay(&tv); packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type, (const unsigned char *)buf, len, tcp_seq, tcp_ack, tcp_ctl, unreachable, &packet_len); if (!packet) { return; } fd = swrap_get_pcap_fd(file_name); if (fd != -1) { write(fd, packet, packet_len); } free(packet); }