Esempio n. 1
0
File: udp.c Progetto: roccof/groink
static int decode_udp(packet_t *p, const _uint8 *bytes, size_t len)
{
  int status = DECODE_OK;
  udp_t *udp = NULL;

  if (UDP_HDR_LEN > len) {
    decoder_add_error(p, "invalid UDP header length");
    return call_decoder(PROTO_NAME_RAW, p, bytes, len);
  }

  udp = (udp_t *)bytes;

  packet_append_header(p, PROTO_NAME_UDP, (void *)udp, UDP_HDR_LEN);

  p->src_port = udp->src_port;
  p->dst_port = udp->dest_port;

  if ((len - UDP_HDR_LEN) > 0) {
    status += call_decoder_byport(ntohs(udp->src_port), p, (bytes + UDP_HDR_LEN), (len - UDP_HDR_LEN));
    
    if (status == DECODER_NOT_FOUND)
      status += call_decoder_byport(ntohs(udp->dest_port), p, (bytes + UDP_HDR_LEN), (len - UDP_HDR_LEN));
    
    if (status == DECODER_NOT_FOUND)
      status = call_decoder(PROTO_NAME_RAW, p, (bytes + UDP_HDR_LEN), (len - UDP_HDR_LEN));
  }
  
  return status;
}
Esempio n. 2
0
File: ftp.c Progetto: roccof/groink
static int decode_ftp(packet_t *p, const _uint8 *bytes, size_t len)
{
  header_t *h = packet_append_header(p, PROTO_NAME_FTP, (void *)bytes, len);
  packet_set_payload(p, h);

  return DECODE_OK;
}
Esempio n. 3
0
struct packet *new_udp_packet(int address_family,
			       enum direction_t direction,
			       u16 udp_payload_bytes,
			       char **error)
{
	struct packet *packet = NULL;  /* the newly-allocated result packet */
	struct header *udp_header = NULL;  /* the UDP header info */
	/* Calculate lengths in bytes of all sections of the packet */
	const int ip_option_bytes = 0;
	const int ip_header_bytes = (ip_header_min_len(address_family) +
				     ip_option_bytes);
	const int udp_header_bytes = sizeof(struct udp);
	const int ip_bytes =
		 ip_header_bytes + udp_header_bytes + udp_payload_bytes;

	/* Sanity-check all the various lengths */
	if (ip_option_bytes & 0x3) {
		asprintf(error, "IP options are not padded correctly "
			 "to ensure IP header is a multiple of 4 bytes: "
			 "%d excess bytes", ip_option_bytes & 0x3);
		return NULL;
	}
	assert((udp_header_bytes & 0x3) == 0);
	assert((ip_header_bytes & 0x3) == 0);

	if (ip_bytes > MAX_UDP_DATAGRAM_BYTES) {
		asprintf(error, "UDP datagram too large");
		return NULL;
	}

	/* Allocate and zero out a packet object of the desired size */
	packet = packet_new(ip_bytes);
	memset(packet->buffer, 0, ip_bytes);

	packet->direction = direction;
	packet->flags = 0;
	packet->ecn = ECN_NONE;

	/* Set IP header fields */
	set_packet_ip_header(packet, address_family, ip_bytes,
			     packet->ecn, IPPROTO_UDP);

	udp_header = packet_append_header(packet, HEADER_UDP,
					  sizeof(struct udp));
	udp_header->total_bytes = udp_header_bytes + udp_payload_bytes;

	/* Find the start of UDP section of the packet */
	packet->udp = (struct udp *) (ip_start(packet) + ip_header_bytes);

	/* Set UDP header fields */
	packet->udp->src_port	= htons(0);
	packet->udp->dst_port	= htons(0);
	packet->udp->len	= htons(udp_header_bytes + udp_payload_bytes);
	packet->udp->check	= 0;

	packet->ip_bytes = ip_bytes;
	return packet;
}
Esempio n. 4
0
/* Send ARP Reply packet */
void inject_arp_reply(char *eth_src, char *ip_src, char *eth_target, char *ip_target)
{
  packet_t *p = NULL;
  ether_t *ether = NULL;
  arp_t *arp;

  p = packet_new_empty();

  ether = build_ethernet(eth_src, eth_target, ETHER_TYPE_ARP);
  packet_append_header(p, PROTO_NAME_ETHER, (void *)ether, ETHER_HDR_LEN);

  arp = build_arp_ethip(ARP_OP_REPLY, eth_src, ip_src, eth_target, ip_target);
  packet_append_header(p, PROTO_NAME_ARP, (void *)arp, sizeof(arp_t) + sizeof(arp_ethip_t));

  inject(p);

  packet_free(p);
  free(ether);
  free(arp);
}
Esempio n. 5
0
/* Send custom ARP message */
void inject_arp(char *eth_src, char *eth_dst, _uint16 opcode, char *sha, char *spa, char *tha, char *tpa)
{
  packet_t *p = NULL;
  ether_t *ether = NULL;
  arp_t *arp;

  p = packet_new_empty();

  ether = build_ethernet(eth_src, eth_dst, ETHER_TYPE_ARP);
  packet_append_header(p, PROTO_NAME_ETHER, (void *)ether, ETHER_HDR_LEN);

  arp = build_arp_ethip(opcode, sha, spa, tha, tpa);
  packet_append_header(p, PROTO_NAME_ARP, (void *)arp, sizeof(arp_t) + sizeof(arp_ethip_t));

  inject(p);

  packet_free(p);
  free(ether);
  free(arp);
}
Esempio n. 6
0
/* Parse the GRE header. Return a packet_parse_result_t. */
static int parse_gre(struct packet *packet, u8 *layer4_start, int layer4_bytes,
		     u8 *packet_end, char **error)
{
	struct header *gre_header = NULL;
	u8 *p = layer4_start;
	struct gre *gre = (struct gre *) p;

	assert(layer4_bytes >= 0);
	if (layer4_bytes < sizeof(struct gre)) {
		asprintf(error, "Truncated GRE header");
		goto error_out;
	}
	if (gre->version != 0) {
		asprintf(error, "GRE header has unsupported version number");
		goto error_out;
	}
	if (gre->has_routing) {
		asprintf(error, "GRE header has unsupported routing info");
		goto error_out;
	}
	const int gre_header_len = gre_len(gre);
	if (gre_header_len < sizeof(struct gre)) {
		asprintf(error, "GRE header length too small for GRE header");
		goto error_out;
	}
	if (gre_header_len > layer4_bytes) {
		asprintf(error, "GRE header length too big");
		goto error_out;
	}

	assert(p + layer4_bytes <= packet_end);

	DEBUGP("GRE header len: %d\n", gre_header_len);

	gre_header = packet_append_header(packet, HEADER_GRE, gre_header_len);
	if (gre_header == NULL) {
		asprintf(error, "Too many nested headers at GRE header");
		goto error_out;
	}
	gre_header->total_bytes = layer4_bytes;

	p += gre_header_len;
	assert(p <= packet_end);
	return parse_layer3_packet_by_proto(packet, ntohs(gre->protocol),
					    p, packet_end, error);

error_out:
	return PACKET_BAD;
}
Esempio n. 7
0
/* Parse the UDP header. Return a packet_parse_result_t. */
static int parse_udp(struct packet *packet, u8 *layer4_start, int layer4_bytes,
		     u8 *packet_end, char **error)
{
	struct header *udp_header = NULL;
	u8 *p = layer4_start;

	assert(layer4_bytes >= 0);
	if (layer4_bytes < sizeof(struct udp)) {
		asprintf(error, "Truncated UDP header");
		goto error_out;
	}
	packet->udp = (struct udp *) p;
	const int udp_len = ntohs(packet->udp->len);
	const int udp_header_len = sizeof(struct udp);
	if (udp_len < udp_header_len) {
		asprintf(error, "UDP datagram length too small for UDP header");
		goto error_out;
	}
	if (udp_len < layer4_bytes) {
		asprintf(error, "UDP datagram length too small");
		goto error_out;
	}
	if (udp_len > layer4_bytes) {
		asprintf(error, "UDP datagram length too big");
		goto error_out;
	}

	udp_header = packet_append_header(packet, HEADER_UDP, udp_header_len);
	if (udp_header == NULL) {
		asprintf(error, "Too many nested headers at UDP header");
		goto error_out;
	}
	udp_header->total_bytes = layer4_bytes;

	p += layer4_bytes;
	assert(p <= packet_end);

	DEBUGP("UDP src port: %d\n", ntohs(packet->udp->src_port));
	DEBUGP("UDP dst port: %d\n", ntohs(packet->udp->dst_port));
	return PACKET_OK;

error_out:
	return PACKET_BAD;
}
Esempio n. 8
0
static int parse_mpls(struct packet *packet, u8 *header_start, u8 *packet_end,
		      char **error)
{
	struct header *mpls_header = NULL;
	u8 *p = header_start;
	int mpls_header_bytes = 0;
	int mpls_total_bytes = packet_end - p;
	bool is_stack_bottom = false;

	do {
		struct mpls *mpls_entry = (struct mpls *)(p);

		if (p + sizeof(struct mpls) > packet_end) {
			asprintf(error, "MPLS stack entry overflows packet");
			goto error_out;
		}

		is_stack_bottom = mpls_entry_stack(mpls_entry);

		p += sizeof(struct mpls);
		mpls_header_bytes += sizeof(struct mpls);
	} while (!is_stack_bottom && p < packet_end);

	assert(mpls_header_bytes <= mpls_total_bytes);

	mpls_header = packet_append_header(packet, HEADER_MPLS,
					   mpls_header_bytes);
	if (mpls_header == NULL) {
		asprintf(error, "Too many nested headers at MPLS header");
		goto error_out;
	}
	mpls_header->total_bytes = mpls_total_bytes;

	/* Move on to the header inside the MPLS label stack. */
	assert(p <= packet_end);
	return parse_layer3_packet(packet, p, packet_end, error);

error_out:
	return PACKET_BAD;
}
Esempio n. 9
0
File: tcp.c Progetto: roccof/groink
static int decode_tcp(packet_t *p, const _uint8 *bytes, size_t len)
{
  int status = DECODE_OK;
  unsigned int totlen = 0;
  tcp_t *tcp = NULL;

  if (sizeof(tcp_t) > len)
    goto err;

  tcp = (tcp_t *)bytes;
  totlen = TCP_HDR_LEN(tcp);

  if (totlen > len)
    goto err;

  packet_append_header(p, PROTO_NAME_TCP, (void *)tcp, totlen);

  p->src_port = tcp->src_port;
  p->dst_port = tcp->dest_port;

  /* If there is more data */
  if ((len - totlen) > 0) {
    status += call_decoder_byport(ntohs(tcp->src_port), p, (bytes + totlen), 
				  (len - totlen));
    
    if (status == DECODER_NOT_FOUND)
      status += call_decoder_byport(ntohs(tcp->dest_port), p, (bytes + totlen), 
				    (len - totlen));
    
    if (status == DECODER_NOT_FOUND)
      status += call_decoder(PROTO_NAME_RAW, p, (bytes + totlen), (len - totlen));
  }
  
  return status;

 err:
  decoder_add_error(p, "invalid TCP header length");
  return call_decoder(PROTO_NAME_RAW, p, bytes, len);
}
Esempio n. 10
0
/* Parse the TCP header. Return a packet_parse_result_t. */
static int parse_tcp(struct packet *packet, u8 *layer4_start, int layer4_bytes,
		     u8 *packet_end, char **error)
{
	struct header *tcp_header = NULL;
	u8 *p = layer4_start;

	assert(layer4_bytes >= 0);
	if (layer4_bytes < sizeof(struct tcp)) {
		asprintf(error, "Truncated TCP header");
		goto error_out;
	}
	packet->tcp = (struct tcp *) p;
	const int tcp_header_len = packet_tcp_header_len(packet);
	if (tcp_header_len < sizeof(struct tcp)) {
		asprintf(error, "TCP data offset too small");
		goto error_out;
	}
	if (tcp_header_len > layer4_bytes) {
		asprintf(error, "TCP data offset too big");
		goto error_out;
	}

	tcp_header = packet_append_header(packet, HEADER_TCP, tcp_header_len);
	if (tcp_header == NULL) {
		asprintf(error, "Too many nested headers at TCP header");
		goto error_out;
	}
	tcp_header->total_bytes = layer4_bytes;

	p += layer4_bytes;
	assert(p <= packet_end);

	DEBUGP("TCP src port: %d\n", ntohs(packet->tcp->src_port));
	DEBUGP("TCP dst port: %d\n", ntohs(packet->tcp->dst_port));
	return PACKET_OK;

error_out:
	return PACKET_BAD;
}
Esempio n. 11
0
/* Parse the ICMPv4 header. Return a packet_parse_result_t. */
static int parse_icmpv4(struct packet *packet, u8 *layer4_start,
			int layer4_bytes, u8 *packet_end, char **error)
{
	struct header *icmp_header = NULL;
	const int icmp_header_len = sizeof(struct icmpv4);
	u8 *p = layer4_start;

	assert(layer4_bytes >= 0);
	/* Make sure the immediately preceding header was IPv4. */
	if (packet_inner_header(packet)->type != HEADER_IPV4) {
		asprintf(error, "Bad IP version for IPPROTO_ICMP");
		goto error_out;
	}

	if (layer4_bytes < sizeof(struct icmpv4)) {
		asprintf(error, "Truncated ICMPv4 header");
		goto error_out;
	}

	packet->icmpv4 = (struct icmpv4 *) p;

	icmp_header = packet_append_header(packet, HEADER_ICMPV4,
					   icmp_header_len);
	if (icmp_header == NULL) {
		asprintf(error, "Too many nested headers at ICMPV4 header");
		goto error_out;
	}
	icmp_header->total_bytes = layer4_bytes;

	p += layer4_bytes;
	assert(p <= packet_end);

	return PACKET_OK;

error_out:
	return PACKET_BAD;
}
Esempio n. 12
0
File: raw.c Progetto: roccof/groink
static int decode_raw(packet_t *p, const _uint8 *bytes, size_t len)
{
    packet_append_header(p, PROTO_NAME_RAW, (void *)bytes, len);
    return DECODE_OK;
}
Esempio n. 13
0
/* Parse the IPv6 header and the TCP header inside. We do not
 * currently support parsing IPv6 extension headers or any layer 4
 * protocol other than TCP. Return a packet_parse_result_t.
 * Note that packet_end points to the byte beyond the end of packet.
 */
static int parse_ipv6(struct packet *packet, u8 *header_start, u8 *packet_end,
		      char **error)
{
	struct header *ip_header = NULL;
	u8 *p = header_start;
	const bool is_outer = (packet->ip_bytes == 0);
	bool is_inner = false;
	struct ipv6 *ipv6 = (struct ipv6 *) (p);
	enum packet_parse_result_t result = PACKET_BAD;

	/* Check that header fits in sniffed packet. */
	const int ip_header_bytes = sizeof(*ipv6);
	if (p + ip_header_bytes > packet_end) {
		asprintf(error, "IPv6 header overflows packet");
		goto error_out;
	}

	/* Check that payload fits in sniffed packet. */
	const int ip_total_bytes = (ip_header_bytes +
				    ntohs(ipv6->payload_len));

	if (p + ip_total_bytes > packet_end) {
		asprintf(error, "IPv6 payload overflows packet");
		goto error_out;
	}
	assert(ip_header_bytes <= ip_total_bytes);

	ip_header = packet_append_header(packet, HEADER_IPV6, ip_header_bytes);
	if (ip_header == NULL) {
		asprintf(error, "Too many nested headers at IPv6 header");
		goto error_out;
	}
	ip_header->total_bytes = ip_total_bytes;

	/* Move on to the header inside. */
	p += ip_header_bytes;
	assert(p <= packet_end);

	if (DEBUG_LOGGING) {
		char src_string[ADDR_STR_LEN];
		char dst_string[ADDR_STR_LEN];
		struct ip_address src_ip, dst_ip;
		ip_from_ipv6(&ipv6->src_ip, &src_ip);
		ip_from_ipv6(&ipv6->dst_ip, &dst_ip);
		DEBUGP("src IP: %s\n", ip_to_string(&src_ip, src_string));
		DEBUGP("dst IP: %s\n", ip_to_string(&dst_ip, dst_string));
	}

	/* Examine the L4 header. */
	const int layer4_bytes = ip_total_bytes - ip_header_bytes;
	const int layer4_protocol = ipv6->next_header;
	result = parse_layer4(packet, p, layer4_protocol, layer4_bytes,
			      packet_end, &is_inner, error);

	/* If this is the innermost IP header then this is the primary. */
	if (is_inner)
		packet->ipv6 = ipv6;
	/* If this is the outermost IP header then this is the packet length. */
	if (is_outer)
		packet->ip_bytes = ip_total_bytes;

	return result;

error_out:
	return PACKET_BAD;
}
Esempio n. 14
0
/* Parse the IPv4 header and the TCP header inside. Return a
 * packet_parse_result_t.
 * Note that packet_end points to the byte beyond the end of packet.
 */
static int parse_ipv4(struct packet *packet, u8 *header_start, u8 *packet_end,
		      char **error)
{
	struct header *ip_header = NULL;
	u8 *p = header_start;
	const bool is_outer = (packet->ip_bytes == 0);
	bool is_inner = false;
	enum packet_parse_result_t result = PACKET_BAD;
	struct ipv4 *ipv4 = (struct ipv4 *) (p);

	const int ip_header_bytes = ipv4_header_len(ipv4);
	assert(ip_header_bytes >= 0);
	if (ip_header_bytes < sizeof(*ipv4)) {
		asprintf(error, "IP header too short");
		goto error_out;
	}
	if (p + ip_header_bytes > packet_end) {
		asprintf(error, "Full IP header overflows packet");
		goto error_out;
	}
	const int ip_total_bytes = ntohs(ipv4->tot_len);

	if (p + ip_total_bytes > packet_end) {
		asprintf(error, "IP payload overflows packet");
		goto error_out;
	}
	if (ip_header_bytes > ip_total_bytes) {
		asprintf(error, "IP header bigger than datagram");
		goto error_out;
	}
	if (ntohs(ipv4->frag_off) & IP_MF) {	/* more fragments? */
		asprintf(error, "More fragments remaining");
		goto error_out;
	}
	if (ntohs(ipv4->frag_off) & IP_OFFMASK) {  /* fragment offset */
		asprintf(error, "Non-zero fragment offset");
		goto error_out;
	}
	const u16 checksum = ipv4_checksum(ipv4, ip_header_bytes);
	if (checksum != 0) {
		asprintf(error, "Bad IP checksum");
		goto error_out;
	}

	ip_header = packet_append_header(packet, HEADER_IPV4, ip_header_bytes);
	if (ip_header == NULL) {
		asprintf(error, "Too many nested headers at IPv4 header");
		goto error_out;
	}
	ip_header->total_bytes = ip_total_bytes;

	/* Move on to the header inside. */
	p += ip_header_bytes;
	assert(p <= packet_end);

	if (DEBUG_LOGGING) {
		char src_string[ADDR_STR_LEN];
		char dst_string[ADDR_STR_LEN];
		struct ip_address src_ip, dst_ip;
		ip_from_ipv4(&ipv4->src_ip, &src_ip);
		ip_from_ipv4(&ipv4->dst_ip, &dst_ip);
		DEBUGP("src IP: %s\n", ip_to_string(&src_ip, src_string));
		DEBUGP("dst IP: %s\n", ip_to_string(&dst_ip, dst_string));
	}

	/* Examine the L4 header. */
	const int layer4_bytes = ip_total_bytes - ip_header_bytes;
	const int layer4_protocol = ipv4->protocol;
	result = parse_layer4(packet, p, layer4_protocol, layer4_bytes,
			      packet_end, &is_inner, error);

	/* If this is the innermost IP header then this is the primary. */
	if (is_inner)
		packet->ipv4 = ipv4;
	/* If this is the outermost IP header then this is the packet length. */
	if (is_outer)
		packet->ip_bytes = ip_total_bytes;

	return result;

error_out:
	return PACKET_BAD;
}