示例#1
0
static void decode_icmp(const uint8_t *packet, size_t pk_len, int pk_layer) {
	union {
		const struct myicmphdr *i;
		const uint8_t *d;
	} ic_u; /* ;] */
	uint8_t type=0, code=0;
	uint16_t chksum=0;

	ic_u.d=packet;

	if (pk_len < 4) {
		ERR("short icmp header");
		return;
	}

	type=ic_u.i->type;
	code=ic_u.i->code;
	chksum=ntohs(ic_u.i->checksum);

	if (ISDBG(M_PKT) || GET_SNIFF()) {
		INF("ICMP: type %u code %u chksum %04x%s", type, code, chksum, "[?]");
	}

	if (type == 3 || type == 5 || type == 11) {
		/*
		 * dest unreachable, the packet that generated this error should be after the icmpheader
		 * redirect message, same as with unreachable
		 * time exceeded, same as with above
		 */

		if (pk_len > sizeof(struct myicmphdr)) { /* there _could_ be data there, try to process it */
			const uint8_t *newpacket=NULL;
			size_t newpk_len=0;

			newpacket=packet + sizeof(struct myicmphdr);
			newpk_len=pk_len - sizeof(struct myicmphdr);

			decode_ip(newpacket, newpk_len, (pk_layer + 1));
		}
	}
	else if (type == 0 || type == 8) {
		/* pings ignore */
		DBG(M_PKT, "Ignoring ping request or response");
	}

	if (pk_layer == 2) {
		r_u.i.type=type;
		r_u.i.subtype=code;

		report_push();
	}

	return;
}
示例#2
0
static void slice_icmp(const uint8_t *packet, size_t pk_len, packetlayers_t *plz, int pk_layer) {
	union {
		const struct myicmphdr *i;
		const uint8_t *d;
	} ic_u; /* ;] */
	uint8_t type=0, code=0;
	uint16_t chksum=0;

	assert(plz != NULL);
	assert(packet != NULL);
	ic_u.d=packet;

	if (pk_len < 4) {
		return;
	}

	type=ic_u.i->type;
	code=ic_u.i->code;
	chksum=ntohs(ic_u.i->checksum);

	if (type == 3 || type == 5 || type == 11) {
		/* dest unreachable, the packet that generated this error should be after the icmpheader	*/
		/* redirect message, same as with unreachable							*/
		/* time exceeded, same as with above								*/

		if (pk_len > sizeof(struct myicmphdr)) { /* there _could_ be data there, try to process it */
			const uint8_t *newpacket=NULL;
			size_t newpk_len=0;

			newpacket=packet + sizeof(struct myicmphdr);
			newpk_len=pk_len - sizeof(struct myicmphdr);

			decode_ip(newpacket, newpk_len, (pk_layer + 1));
		}
	}
	else if (type == 0 || type == 8) {
		/* pings ignore */
	}

	if (pk_layer == 2) {
		r_u.i.type=type;
		r_u.i.subtype=code;

		report_push();
	}

	return;
}
示例#3
0
static void decode_tcp (const uint8_t *packet, size_t pk_len, int pk_layer) {
	union {
		const struct mytcphdr *t;
		const uint8_t *d;
	} t_u;
	uint16_t sport=0, dport=0;
	uint32_t seq=0, ackseq=0;
	uint8_t doff=0, res1=0;
	uint16_t window=0, chksum=0, c_chksum=0, urgptr=0;
	size_t data_len=0, tcpopt_len=0;
	int bad_cksum=0;
	union {
		const ip_pseudo_t *ipph_ptr;
		const uint8_t *ptr;
	} ipph_u;
	struct chksumv c[2];

	t_u.d=packet;

	if (pk_layer == 4) { /* this is inside an icmp error reflection, check that */
		if (r_u.i.proto != IPPROTO_ICMP) {
			ERR("FIXME in TCP not inside an ICMP error?");
			return;
		}
		/*
		 * ok so why the special treatment? well the packet may be incomplete, so its ok if we dont have
		 * a full udp header, we really are only looking for the source and dest ports, we _need_ those
		 * everything else is optional at this point
		 */
		if (pk_len < 4) {
			ERR("TCP header too incomplete to get source and dest ports, halting processing");
			return;
		}
		if (pk_len >= 4 && pk_len < sizeof(struct mytcphdr)) {
			/*
			 * this is reversed from a response, the host never responded so flip src/dest ports
			 */
			r_u.i.sport=ntohs(t_u.t->dest);
			r_u.i.dport=ntohs(t_u.t->source);

			return;
		}
	}

	if (pk_len < sizeof(struct mytcphdr)) {
		ERR("short tcp header");
		return;
	}

	sport=ntohs(t_u.t->source);
	dport=ntohs(t_u.t->dest);
	seq=ntohl(t_u.t->seq);
	ackseq=ntohl(t_u.t->ack_seq);
	doff=t_u.t->doff; res1=t_u.t->res1;
	window=ntohs(t_u.t->window);
	chksum=ntohs(t_u.t->check);
	urgptr=ntohs(t_u.t->urg_ptr);

	if (pk_layer == 2) {
		uint32_t eackseq=0, high=0;

		TCPHASHTRACK(eackseq, r_u.i.host_addr, sport, dport, s->ss->syn_key);

		if (GET_LDOCONNECT()) {
			DBG(M_PKT, "window size is %u or whatever", s->ss->window_size);
			high=eackseq + s->ss->window_size;
		}
		else {
			high=eackseq + 2; /* should always be +1, but lets just accept someone who didnt inc th seq */
		}

		if (SEQ_WITHIN(ackseq, eackseq, high)) {
			DBG(M_PKT, "packet within my %08x-%08x window, with %08x expecting %08x", eackseq, high, ackseq, eackseq);
		}
		else if (! GET_SNIFF() && ! GET_IGNORESEQ() && ! (GET_IGNORERSEQ() && t_u.t->rst)) {
			DBG(M_PKT, "not my packet ackseq %08x expecting somewhere around %08x-%08x", ackseq, eackseq, high);
			return;
		}
	} /* layer 3 seq checking */

	if (doff && ((size_t)(doff * 4) > pk_len)) {
		ERR("datalength exceeds capture length, truncating to zero (doff %u bytes pk_len " STFMT ")", doff * 4, pk_len);
		doff=0;
	}

	if (doff && (size_t )(doff * 4) < sizeof(struct mytcphdr)) {
		ERR("doff is too small, increasing to min size and hoping for no tcpoptions");
		doff=sizeof(struct mytcphdr) / 4;
	}

	if (doff) {
		tcpopt_len=((doff * 4) -  sizeof(struct mytcphdr));
		data_len=pk_len - (doff * 4);
	}
	else {
		tcpopt_len=pk_len - sizeof(struct mytcphdr);
		data_len=0;
	}

	ipph_u.ipph_ptr=&ipph;
	/* its not natural to use _this_ size... */
	ipph.len=ntohs(pk_len);

	c[0].len=sizeof(ipph);
	c[0].ptr=ipph_u.ptr;

	c[1].len=pk_len;
	c[1].ptr=packet;

	c_chksum=do_ipchksumv((const struct chksumv *)&c[0], 2);
	if (c_chksum != 0) {
		DBG(M_PKT, "bad tcp checksum, ipchksumv returned 0x%04x", c_chksum);
		bad_cksum=1;
	}

	if (ISDBG(M_PKT) || GET_SNIFF()) {
		char tcpflags[16];

		memset(tcpflags, '-', sizeof(tcpflags));
		tcpflags[8]='\0';
		if (t_u.t->fin) tcpflags[0]='F';
		if (t_u.t->syn) tcpflags[1]='S';
		if (t_u.t->rst) tcpflags[2]='R';
		if (t_u.t->psh) tcpflags[3]='P';
		if (t_u.t->ack) tcpflags[4]='A';
		if (t_u.t->urg) tcpflags[5]='U';
		if (t_u.t->ece) tcpflags[6]='E';
		if (t_u.t->cwr) tcpflags[7]='C';

		INF("TCP : size " STFMT " sport %u dport %u seq 0x%08x ack_seq 0x%08x window %u",
		pk_len, sport, dport, seq, ackseq, window);
		INF("TCP : doff %u res1 %u flags `%s' chksum 0x%04x%s urgptr 0x%04x",
		doff, res1, tcpflags, chksum, (bad_cksum != 0 ? " [bad cksum]" : " [cksum ok]"), urgptr);
		INF("TCP : options length " STFMT " data length " STFMT, tcpopt_len, data_len);
	}

	packet += sizeof(struct mytcphdr);
	pk_len -= sizeof(struct mytcphdr);

	if (tcpopt_len && (ISDBG(M_PKT) || GET_SNIFF())) {
		decode_tcpopts(packet, tcpopt_len);
	}

	if (data_len && (ISDBG(M_PKT) || GET_SNIFF())) {
		INF("TCP : dumping packet data");
		hexdump(packet + tcpopt_len, data_len);
	}

	if (pk_layer == 2) {
		r_u.i.sport=sport;
		r_u.i.dport=dport;
		r_u.i.type=0;

		r_u.i.tseq=seq;
		r_u.i.mseq=ackseq;

		r_u.i.window_size=window;

		if (t_u.t->fin) r_u.i.type |= TH_FIN;
		if (t_u.t->syn) r_u.i.type |= TH_SYN;
		if (t_u.t->rst) r_u.i.type |= TH_RST;
		if (t_u.t->psh) r_u.i.type |= TH_PSH;
		if (t_u.t->ack) r_u.i.type |= TH_ACK;
		if (t_u.t->urg) r_u.i.type |= TH_URG;
		if (t_u.t->ece) r_u.i.type |= TH_ECE;
		if (t_u.t->cwr) r_u.i.type |= TH_CWR;

		r_u.i.subtype=0;

		if (bad_cksum) {
			r_u.i.flags |= REPORT_BADTRANSPORT_CKSUM;
		}

		if (GET_WATCHERRORS() || GET_LDOCONNECT()) {
			report_push();
		}
		else if (t_u.t->syn /* close enough */) {
			report_push();
		}
	}
	else if (pk_layer == 4) {
		r_u.i.sport=dport;
		r_u.i.dport=sport;
		r_u.i.mseq=ackseq;
		r_u.i.tseq=seq;
		r_u.i.window_size=0;
	}
	else {
		ERR("fixme");
		return;
	}

	return;
}
示例#4
0
static void decode_udp (const uint8_t *packet, size_t pk_len, int pk_layer) {
	union {
		const struct myudphdr *u;
		const uint8_t *d;
	} u_u;
	uint16_t sport=0, dport=0, len=0, chksum=0, c_chksum=0;
	int bad_cksum=0;
	union {
		const ip_pseudo_t *ipph_ptr;
		const uint8_t *ptr;
	} ipph_u;
	struct chksumv c[2];

	u_u.d=packet;

	if (pk_layer == 4) { /* this is inside an icmp error reflection, check that */
		if (r_u.i.proto != IPPROTO_ICMP) {
			ERR("FIXME in UDP not inside a ICMP error?");
			return;
		}
		/* see TCP comment above about special treatment */
		if (pk_len < 4) {
			ERR("UDP header too short to get source and dest ports");
			return;
		}
		if (pk_len >= 4 && pk_len < sizeof(struct myudphdr)) {
			/* this is reversed from a response, the host never responded so flip src/dest ports */
			r_u.i.sport=ntohs(u_u.u->dest);
			r_u.i.dport=ntohs(u_u.u->source);
			r_u.i.tseq=0;
			r_u.i.mseq=0;

			return;
		}
	}

	if (pk_len < sizeof(struct myudphdr)) {
		ERR("short udp header");
		return;
	}
	sport=ntohs(u_u.u->source);
	dport=ntohs(u_u.u->dest);
	len=ntohs(u_u.u->len);
	chksum=ntohs(u_u.u->check);

	ipph_u.ipph_ptr=&ipph;
	ipph.len=ntohs(pk_len);

	c[0].len=sizeof(ipph);
	c[0].ptr=ipph_u.ptr;

	c[1].len=pk_len;
	c[1].ptr=packet;

	c_chksum=do_ipchksumv((const struct chksumv *)&c[0], 2);
	if (c_chksum != 0) {
		DBG(M_PKT, "bad udp checksum, ipchksumv returned 0x%x", c_chksum);
		bad_cksum=1;
	}

	if (ISDBG(M_PKT) || GET_SNIFF()) {
		INF("UDP : pklen " STFMT " sport %u dport %u len %u checksum %04x%s",
		pk_len, sport, dport, len, chksum, bad_cksum == 0 ? " [bad cksum]" : " [cksum ok]");
	}

	if (pk_layer == 2) {
		r_u.i.sport=sport;
		r_u.i.dport=dport;
		r_u.i.type=0;
		r_u.i.subtype=0;
		r_u.i.tseq=0;
		r_u.i.mseq=0;

		report_push();
        }
	else if (pk_layer == 4) {
		/* this is reversed from a response, the host never responded so flip src/dest ports */
		r_u.i.sport=dport;
		r_u.i.dport=sport;
		r_u.i.tseq=0;
		r_u.i.mseq=0;
	}
	else {
		ERR("FIXME at decode UDP at layer %d", pk_layer);
		return;
	}

	pk_len -= sizeof(struct myudphdr);
	packet += sizeof(struct myudphdr);

	if (pk_len && (ISDBG(M_PKT) || GET_SNIFF())) {
		INF("UDP : dumping UDP payload");
		hexdump(packet, pk_len);
	}

	return;
}
示例#5
0
static void decode_arp (const uint8_t *packet, size_t pk_len, int pk_layer) {
	union {
		const struct myetherarphdr *a;
		const uint8_t *d;
	} a_u;
	uint16_t hwtype=0, opcode=0;

	a_u.d=packet;
	r_u.a.flags=0;

	if (pk_len < sizeof(struct myetherarphdr)) {
		ERR("short arp packet");
		return;
	}

	hwtype=ntohs(a_u.a->hw_type);
	opcode=ntohs(a_u.a->opcode);

	if (a_u.a->protosize != 4 || a_u.a->hwsize != 6) {
		DBG(M_PKT, "arp packet isnt 6:4, giving up");
		return;
	}

	if (opcode != ARPOP_REPLY) {
		return;
	}

	if (memcmp(s->vi[0]->hwaddr, a_u.a->smac, 6) == 0) {
		return; /* we sent this */
	}

	if (ISDBG(M_PKT) || GET_SNIFF()) {
		char srcip[32], srcmac[32];
		struct in_addr ia;

		ia.s_addr=a_u.a->sip;
		sprintf(srcip, "%s", inet_ntoa(ia));
		ia.s_addr=a_u.a->dip;
		sprintf(srcmac, "%s", decode_6mac(a_u.a->smac));

		INF("ARP : hw_type `%s' protocol `%s' hwsize %d protosize %d opcode `%s'",
		str_hwtype(hwtype), str_hwproto(a_u.a->protocol), a_u.a->hwsize, a_u.a->protosize, str_opcode(opcode));
		INF("ARP : SRC HW %s SRC IP -> %s DST HW %s DST IP %s",
		srcmac, srcip, decode_6mac(a_u.a->dmac), inet_ntoa(ia));
	}

	pk_len -= sizeof(struct myetherarphdr);

	memcpy(r_u.a.hwaddr, a_u.a->smac, THE_ONLY_SUPPORTED_HWADDR_LEN);
	memcpy(&r_u.a.ipaddr, &a_u.a->sip, sizeof(r_u.a.ipaddr));

	report_push();

	if (pk_len) {
		/* frame padding ;] */
		pk_layer++;
		packet += sizeof(struct myetherarphdr);
		decode_junk(packet, pk_len, pk_layer);
	}

	return;
}