Exemplo n.º 1
0
Arquivo: icmp.c Projeto: 0xcc/tapip
/* NOTE: icmp dont drop @ipkb */
void icmp_send(unsigned char type, unsigned char code,
		unsigned int data, struct pkbuf *pkb_in)
{
	struct pkbuf *pkb;
	struct ip *iphdr = pkb2ip(pkb_in);
	struct icmp *icmphdr;
	int paylen = _ntohs(iphdr->ip_len);	/* icmp payload length */
	if (paylen < iphlen(iphdr) + 8)
		return;
	/*
	 * RFC 1812 Section 4.3.2.7 for sanity check
	 * An ICMP error message MUST NOT be sent as the result of receiving:
	 * 1. A packet sent as a Link Layer broadcast or multicast
	 * 2. A packet destined to an IP broadcast or IP multicast address
	 *[3] A packet whose source address has a network prefix of zero or is an
	 *      invalid source address (as defined in Section [5.3.7])
	 * 4. Any fragment of a datagram other then the first fragment (i.e., a
	 *      packet for which the fragment offset in the IP header is nonzero).
	 * 5. An ICMP error message
	 */
	if (pkb_in->pk_type != PKT_LOCALHOST)
		return;
	if (MULTICAST(iphdr->ip_dst) || BROADCAST(iphdr->ip_dst))
		return;
	if (iphdr->ip_fragoff & _htons(IP_FRAG_OFF))
		return;

	if (icmp_type_error(type) && iphdr->ip_pro == IP_P_ICMP) {
		icmphdr = ip2icmp(iphdr);
		if (icmphdr->icmp_type > ICMP_T_MAXNUM || icmp_error(icmphdr))
			return;
	}
	/* build icmp packet and send */
	/* ip packet size must be smaller than 576 bytes */
	if (IP_HRD_SZ + ICMP_HRD_SZ + paylen > 576)
		paylen = 576 - IP_HRD_SZ - ICMP_HRD_SZ;
	pkb = alloc_pkb(ETH_HRD_SZ + IP_HRD_SZ + ICMP_HRD_SZ + paylen);
	icmphdr = (struct icmp *)(pkb2ip(pkb)->ip_data);
	icmphdr->icmp_type = type;
	icmphdr->icmp_code = code;
	icmphdr->icmp_cksum = 0;
	icmphdr->icmp_undata = data;
	memcpy(icmphdr->icmp_data, (unsigned char *)iphdr, paylen);
	icmphdr->icmp_cksum =
		icmp_chksum((unsigned short *)icmphdr, ICMP_HRD_SZ + paylen);
	icmpdbg("to "IPFMT"(payload %d) [type %d code %d]\n",
		ipfmt(iphdr->ip_src), paylen, type, code);
	ip_send_info(pkb, 0, IP_HRD_SZ + ICMP_HRD_SZ + paylen,
						0, IP_P_ICMP, iphdr->ip_src);
}
Exemplo n.º 2
0
Arquivo: tcp_out.c Projeto: 0xcc/tapip
/*
 * Reset algorithm is not stated directly in RFC 793,
 * but we can conclude it according to all reset generation.
 * NOTE: maybe @tsk is NULL
 */
void tcp_send_reset(struct tcp_sock *tsk, struct tcp_segment *seg)
{
	struct tcp *otcp, *tcphdr = seg->tcphdr;
	struct pkbuf *opkb;

	if (tcphdr->rst)
		return;
	opkb = alloc_pkb(ETH_HRD_SZ + IP_HRD_SZ + TCP_HRD_SZ);
	/* fill tcp head */
	otcp = (struct tcp *)pkb2ip(opkb)->ip_data;
	otcp->src = tcphdr->dst;
	otcp->dst = tcphdr->src;
	if (tcphdr->ack) {
		/*
		 * Should we set ack?
		 * -Yes for xinu, it always set ack to seq+len
		 * +No for Linux
		 * +No for tapip
		 */
		otcp->seq = tcphdr->ackn;
	} else {
		otcp->ackn = _htonl(seg->seq + seg->len);
		otcp->ack = 1;
	}
	otcp->doff = TCP_HRD_DOFF;
	otcp->rst = 1;
	tcpdbg("send RESET from "IPFMT":%d to "IPFMT":%d",
			ipfmt(seg->iphdr->ip_dst), _ntohs(otcp->src),
			ipfmt(seg->iphdr->ip_src), _ntohs(otcp->dst));
	tcp_send_out(NULL, opkb, seg);
}
Exemplo n.º 3
0
Arquivo: tcp_out.c Projeto: 0xcc/tapip
static int tcp_init_pkb(struct tcp_sock *tsk, struct pkbuf *pkb,
			unsigned int saddr, unsigned int daddr)
{
	struct ip *iphdr = pkb2ip(pkb);
	/* fill ip head */
	iphdr->ip_hlen = IP_HRD_SZ >> 2;
	iphdr->ip_ver = IP_VERSION_4;
	iphdr->ip_tos = 0;
	iphdr->ip_len = _htons(pkb->pk_len - ETH_HRD_SZ);
	iphdr->ip_id = _htons(tcp_id);
	iphdr->ip_fragoff = 0;
	iphdr->ip_ttl = TCP_DEFAULT_TTL;
	iphdr->ip_pro = IP_P_TCP;
	iphdr->ip_dst = daddr;
	/* NOTE: tsk maybe NULL, if connect doesnt exist */
	if (tsk && tsk->sk.sk_dst) {
		pkb->pk_rtdst = tsk->sk.sk_dst;
	} else {
		if (rt_output(pkb) < 0)
			return -1;
		if (tsk)
			tsk->sk.sk_dst = pkb->pk_rtdst;
	}
	iphdr->ip_src = saddr;
	return 0;
}
Exemplo n.º 4
0
Arquivo: tcp_out.c Projeto: 0xcc/tapip
void tcp_send_fin(struct tcp_sock *tsk)
{
	struct tcp *otcp;
	struct pkbuf *opkb;

	opkb = alloc_pkb(ETH_HRD_SZ + IP_HRD_SZ + TCP_HRD_SZ);
	/* fill tcp head */
	otcp = (struct tcp *)pkb2ip(opkb)->ip_data;
	otcp->src = tsk->sk.sk_sport;
	otcp->dst = tsk->sk.sk_dport;
	otcp->doff = TCP_HRD_DOFF;
	otcp->seq = _htonl(tsk->snd_nxt);
	otcp->window = _htons(tsk->rcv_wnd);
	otcp->fin = 1;
	/*
	 * Should we send an ACK?
	 * Yes, tcp stack will drop packet if it has no ACK bit
	 * according to RFC 793 #SEGMENT RECEIVE
	 */
	otcp->ackn = _htonl(tsk->rcv_nxt);
	otcp->ack = 1;
	tcpdbg("send FIN(%u)/ACK(%u) [WIN %d] to "IPFMT":%d",
			_ntohl(otcp->seq), _ntohl(otcp->ackn),
			_ntohs(otcp->window), ipfmt(tsk->sk.sk_daddr),
			_ntohs(otcp->dst));
	tcp_send_out(tsk, opkb, NULL);
}
Exemplo n.º 5
0
Arquivo: tcp_out.c Projeto: 0xcc/tapip
void tcp_send_synack(struct tcp_sock *tsk, struct tcp_segment *seg)
{
	/*
	 * LISTEN :
	 * SYN-SENT:
	 *         SEG: SYN, no ACK, no RST
	 *         <SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
	 *         (ISS == SND.NXT)
	 */
	struct tcp *otcp, *tcphdr = seg->tcphdr;
	struct pkbuf *opkb;

	if (tcphdr->rst)
		return;
	opkb = alloc_pkb(ETH_HRD_SZ + IP_HRD_SZ + TCP_HRD_SZ);
	/* fill tcp head */
	otcp = (struct tcp *)pkb2ip(opkb)->ip_data;
	otcp->src = tcphdr->dst;
	otcp->dst = tcphdr->src;
	otcp->doff = TCP_HRD_DOFF;
	otcp->seq = _htonl(tsk->iss);
	otcp->ackn = _htonl(tsk->rcv_nxt);
	otcp->syn = 1;
	otcp->ack = 1;
	otcp->window = _htons(tsk->rcv_wnd);
	tcpdbg("send SYN(%u)/ACK(%u) [WIN %d] to "IPFMT":%d",
			_ntohl(otcp->seq), _ntohs(otcp->window),
			_ntohl(otcp->ackn), ipfmt(seg->iphdr->ip_dst),
			_ntohs(otcp->dst));
	tcp_send_out(tsk, opkb, seg);
}
Exemplo n.º 6
0
static int udp_init_pkb(struct sock *sk, struct pkbuf *pkb,
		void *buf, int size, struct sock_addr *skaddr)
{
	struct ip *iphdr = pkb2ip(pkb);
	struct udp *udphdr = (struct udp *)iphdr->ip_data;
	/* fill ip head */
	iphdr->ip_hlen = IP_HRD_SZ >> 2;
	iphdr->ip_ver = IP_VERSION_4;
	iphdr->ip_tos = 0;
	iphdr->ip_len = _htons(pkb->pk_len - ETH_HRD_SZ);
	iphdr->ip_id = _htons(udp_id);
	iphdr->ip_fragoff = 0;
	iphdr->ip_ttl = UDP_DEFAULT_TTL;
	iphdr->ip_pro = sk->protocol;	/* IP_P_UDP */
	iphdr->ip_dst = skaddr->dst_addr;
	/* FIXME:use the sk->rt_dst */
	if (rt_output(pkb) < 0)		/* fill ip src */
		return -1;
	/* fill udp */
	udphdr->src = sk->sk_sport;	/* bound local address */
	udphdr->dst = skaddr->dst_port;
	udphdr->length = _htons(size + UDP_HRD_SZ);
	memcpy(udphdr->data, buf, size);
	udpdbg(IPFMT":%d" "->" IPFMT":%d(proto %d)",
			ipfmt(iphdr->ip_src), _ntohs(udphdr->src),
			ipfmt(iphdr->ip_dst), _ntohs(udphdr->dst),
			iphdr->ip_pro);
	udp_set_checksum(iphdr, udphdr);
	return 0;
}
Exemplo n.º 7
0
Arquivo: icmp.c Projeto: 0xcc/tapip
void icmp_in(struct pkbuf *pkb)
{
	struct ip *iphdr = pkb2ip(pkb);
	struct icmp *icmphdr = ip2icmp(iphdr);
	int icmplen, type;
	/* sanity check */
	icmplen = ipdlen(iphdr);
	icmpdbg("%d bytes", icmplen);
	if (icmplen < ICMP_HRD_SZ) {
		icmpdbg("icmp header is too small");
		goto drop_pkb;
	}

	if (icmp_chksum((unsigned short *)icmphdr, icmplen) != 0) {
		icmpdbg("icmp checksum is error");
		goto drop_pkb;
	}

	type = icmphdr->icmp_type;
	if (type > ICMP_T_MAXNUM) {
		icmpdbg("unknown icmp type %d code %d",
					type, icmphdr->icmp_code);
		goto drop_pkb;
	}
	/* handle icmp type */
	icmp_table[type].handler(&icmp_table[type], pkb);
	return;
drop_pkb:
	free_pkb(pkb);
}
Exemplo n.º 8
0
Arquivo: icmp.c Projeto: 0xcc/tapip
static void icmp_echo_request(struct icmp_desc *icmp_desc, struct pkbuf *pkb)
{
	struct ip *iphdr = pkb2ip(pkb);
	struct icmp *icmphdr = ip2icmp(iphdr);
	icmpdbg("echo request data %d bytes icmp_id %d icmp_seq %d",
			(int)(iphdr->ip_len - iphlen(iphdr) - ICMP_HRD_SZ),
			_ntohs(icmphdr->icmp_id),
			_ntohs(icmphdr->icmp_seq));
	if (icmphdr->icmp_code) {
		icmpdbg("echo request packet corrupted");
		free_pkb(pkb);
		return;
	}
	icmphdr->icmp_type = ICMP_T_ECHORLY;
	/*
	 * adjacent the checksum:
	 * If  ~ >>> (cksum + x + 8) >>> == 0
	 * let ~ >>> (cksum` + x ) >>> == 0
	 * then cksum` = cksum + 8
	 */
	if (icmphdr->icmp_cksum >= 0xffff - ICMP_T_ECHOREQ)
		icmphdr->icmp_cksum += ICMP_T_ECHOREQ + 1;
	else
		icmphdr->icmp_cksum += ICMP_T_ECHOREQ;
	iphdr->ip_dst = iphdr->ip_src;	/* ip_src is set by ip_send_out() */
	ip_hton(iphdr);
	/* init reused input packet */
	pkb->pk_rtdst = NULL;
	pkb->pk_indev = NULL;
	pkb->pk_type = PKT_NONE;
	ip_send_out(pkb);
}
Exemplo n.º 9
0
Arquivo: icmp.c Projeto: 0xcc/tapip
static void icmp_drop_reply(struct icmp_desc *icmp_desc, struct pkbuf *pkb)
{
	struct ip *iphdr = pkb2ip(pkb);
	struct icmp *icmphdr = ip2icmp(iphdr);
	icmpdbg("icmp type %d code %d (dropped)",
			icmphdr->icmp_type, icmphdr->icmp_code);
	if (icmp_desc->info)
		icmpdbg("%s", icmp_desc->info);
	free_pkb(pkb);
}
Exemplo n.º 10
0
Arquivo: icmp.c Projeto: 0xcc/tapip
static void icmp_echo_reply(struct icmp_desc *icmp_desc, struct pkbuf *pkb)
{
	struct ip *iphdr = pkb2ip(pkb);
	struct icmp *icmphdr = ip2icmp(iphdr);
	icmpdbg("from "IPFMT" id %d seq %d ttl %d",
			ipfmt(iphdr->ip_src),
			_ntohs(icmphdr->icmp_id),
			_ntohs(icmphdr->icmp_seq),
			iphdr->ip_ttl);
	free_pkb(pkb);
}
Exemplo n.º 11
0
Arquivo: icmp.c Projeto: 0xcc/tapip
static void icmp_redirect(struct icmp_desc *icmp_desc, struct pkbuf *pkb)
{
	struct ip *iphdr = pkb2ip(pkb);
	struct icmp *icmphdr = ip2icmp(iphdr);

	if (icmphdr->icmp_code > 4)
		icmpdbg("Redirect code %d is error", icmphdr->icmp_code);
	else
		icmpdbg("from " IPFMT " %s(new nexthop "IPFMT")",
					ipfmt(iphdr->ip_src),
					redirectstr[icmphdr->icmp_code],
					ipfmt(icmphdr->icmp_gw));
	free_pkb(pkb);
}
Exemplo n.º 12
0
Arquivo: tcp_out.c Projeto: 0xcc/tapip
void tcp_send_out(struct tcp_sock *tsk, struct pkbuf *pkb, struct tcp_segment *seg)
{
	struct ip *iphdr = pkb2ip(pkb);
	struct tcp *tcphdr = (struct tcp *)iphdr->ip_data;
	unsigned int saddr, daddr;

	if (seg) {
		daddr = seg->iphdr->ip_src;
		saddr = seg->iphdr->ip_dst;
	} else if (tsk) {
		daddr = tsk->sk.sk_daddr;
		saddr = tsk->sk.sk_saddr;
	} else	/* This shouldnt happen. */
		assert(0);

	if (tcp_init_pkb(tsk, pkb, saddr, daddr) < 0) {
		free_pkb(pkb);
		return;
	}
	tcp_set_checksum(iphdr, tcphdr);
	ip_send_out(pkb);
}
Exemplo n.º 13
0
Arquivo: tcp_out.c Projeto: 0xcc/tapip
void tcp_send_syn(struct tcp_sock *tsk, struct tcp_segment *seg)
{
	/*
	 * SYN-SENT:
	 */
	struct tcp *otcp;
	struct pkbuf *opkb;

	opkb = alloc_pkb(ETH_HRD_SZ + IP_HRD_SZ + TCP_HRD_SZ);
	/* fill tcp head */
	otcp = (struct tcp *)pkb2ip(opkb)->ip_data;
	otcp->src = tsk->sk.sk_sport;
	otcp->dst = tsk->sk.sk_dport;
	otcp->doff = TCP_HRD_DOFF;
	otcp->seq = _htonl(tsk->iss);
	otcp->syn = 1;
	otcp->window = _htons(tsk->rcv_wnd);
	tcpdbg("send SYN(%u) [WIN %d] to "IPFMT":%d",
			_ntohl(otcp->seq), _ntohs(otcp->window),
			ipfmt(tsk->sk.sk_daddr), _ntohs(otcp->dst));
	tcp_send_out(tsk, opkb, seg);
}
Exemplo n.º 14
0
static void recv_packet(void)
{
	struct pkbuf *pkb;
	struct ip *iphdr;
	struct icmp *icmphdr;
	while (!finite || recv > 0) {
		pkb = _recv(sock);
		if (!pkb)
			break;
		iphdr = pkb2ip(pkb);
		icmphdr = ip2icmp(iphdr);
		if (iphdr->ip_pro == IP_P_ICMP &&
			_ntohs(icmphdr->icmp_id) == id &&
			icmphdr->icmp_type == ICMP_T_ECHORLY) {
			recv--;
			printf("%d bytes from " IPFMT ": icmp_seq=%d ttl=%d\n",
				ipdlen(iphdr), ipfmt(iphdr->ip_src),
				_ntohs(icmphdr->icmp_seq), iphdr->ip_ttl);
			precv++;
		}
		free_pkb(pkb);
	}
}
Exemplo n.º 15
0
Arquivo: tcp_out.c Projeto: 0xcc/tapip
/*
 * Acknowledgment algorithm is not stated directly in RFC 793,
 * but we can conclude it from all acknowledgment situation.
 */
void tcp_send_ack(struct tcp_sock *tsk, struct tcp_segment *seg)
{
	/*
	 * SYN-SENT :
	 *         SEG: SYN, acceptable ACK, no RST   (SND.NXT = SEG.SEQ+1)
	 *         <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
	 * SYN-RECEIVED / ESTABLISHED  / FIN-WAIT-1   / FIN-WAIT-2   /
	 * CLOSE-WAIT   / CLOSING      / LAST-ACK     / TIME-WAIT    :
	 *         SEG: no RST, ??ACK, ??SYN        (segment is not acceptable)
	 *         <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
	 * ESTABLISHED  / FIN-WAIT-1  / FIN-WAIT-2  / process the segment text:
	 *         SEG: ACK, no RST
	 *         <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
	 *         (This acknowledgment should be piggybacked on a segment being
	 *          transmitted if possible without incurring undue delay.)
	 */
	struct tcp *otcp, *tcphdr = seg->tcphdr;
	struct pkbuf *opkb;

	if (tcphdr->rst)
		return;
	opkb = alloc_pkb(ETH_HRD_SZ + IP_HRD_SZ + TCP_HRD_SZ);
	/* fill tcp head */
	otcp = (struct tcp *)pkb2ip(opkb)->ip_data;
	otcp->src = tcphdr->dst;
	otcp->dst = tcphdr->src;
	otcp->doff = TCP_HRD_DOFF;
	otcp->seq = _htonl(tsk->snd_nxt);
	otcp->ackn = _htonl(tsk->rcv_nxt);
	otcp->ack = 1;
	otcp->window = _htons(tsk->rcv_wnd);
	tcpdbg("send ACK(%u) [WIN %d] to "IPFMT":%d",
			_ntohl(otcp->ackn), _ntohs(otcp->window),
			ipfmt(seg->iphdr->ip_src), _ntohs(otcp->dst));
	tcp_send_out(tsk, opkb, seg);
}