Example #1
0
File: tcp_out.c Project: 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);
}
Example #2
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;
}
Example #3
0
File: icmp.c Project: 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);
}
Example #4
0
File: tcp_out.c Project: 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);
}
Example #5
0
File: tcp_out.c Project: 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);
}
Example #6
0
static void send_packet(void)
{
	if (!buf)
		buf = xmalloc(size + ICMP_HRD_SZ);
	struct icmp *icmphdr = (struct icmp *)buf;
	static int first = 1;
	if (first) {
		printf("PING "IPFMT" %d(%d) bytes of data\n",
			ipfmt(ipaddr),
			size,
			size + ICMP_HRD_SZ + IP_HRD_SZ);
		first = 0;
	}

	/* fill icmp data */
	memset(icmphdr->icmp_data, 'x', size);
	icmphdr->icmp_type = ICMP_T_ECHOREQ;
	icmphdr->icmp_code = 0;
	icmphdr->icmp_id = _htons(id);
	icmphdr->icmp_seq = _htons(seq);
	icmphdr->icmp_cksum = 0;
	icmphdr->icmp_cksum = icmp_chksum((unsigned short *)icmphdr,
			ICMP_HRD_SZ + size);
	seq++;
	/* socket apis */
	_send(sock, buf, ICMP_HRD_SZ + size, &skaddr);
	psend++;
}
Example #7
0
static void ping_stat(void)
{
	printf(
		"\n"
		"--- " IPFMT " ping statistics ---\n"
		"%d packets transmitted, %d received, %d%% packet loss\n",
		ipfmt(ipaddr), psend, precv, (psend - precv) * 100 / psend);
}
Example #8
0
File: icmp.c Project: 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);
}
Example #9
0
File: tap.c Project: pacepi/tapip
void getipaddr_tap(unsigned char *name, unsigned int *ipaddr)
{
    struct ifreq ifr = {};
    struct sockaddr_in *saddr;

    strcpy(ifr.ifr_name, (char *)name);
    if (ioctl(skfd, SIOCGIFADDR, (void *)&ifr) < 0) {
        close(skfd);
        perrx("socket SIOCGIFADDR");
    }
    saddr = (struct sockaddr_in *)&ifr.ifr_addr;
    *ipaddr = saddr->sin_addr.s_addr;
    dbg("get IPaddr: "IPFMT, ipfmt(*ipaddr));
}
Example #10
0
File: icmp.c Project: 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);
}
Example #11
0
File: tap.c Project: pacepi/tapip
void setipaddr_tap(unsigned char *name, unsigned int ipaddr)
{
    struct ifreq ifr = {};
    struct sockaddr_in *saddr;

    strcpy(ifr.ifr_name, (char *)name);
    saddr = (struct sockaddr_in *)&ifr.ifr_addr;
    saddr->sin_family = AF_INET;
    saddr->sin_addr.s_addr = ipaddr;
    if (ioctl(skfd, SIOCSIFADDR, (void *)&ifr) < 0) {
        close(skfd);
        perrx("socket SIOCSIFADDR");
    }
    dbg("set IPaddr: "IPFMT, ipfmt(ipaddr));
}
Example #12
0
File: tap.c Project: pacepi/tapip
void setnetmask_tap(unsigned char *name, unsigned int netmask)
{
    struct ifreq ifr = {};
    struct sockaddr_in *saddr;

    strcpy(ifr.ifr_name, (char *)name);
    saddr = (struct sockaddr_in *)&ifr.ifr_netmask;
    saddr->sin_family = AF_INET;
    saddr->sin_addr.s_addr = netmask;
    if (ioctl(skfd, SIOCSIFNETMASK, (void *)&ifr) < 0) {
        close(skfd);
        perrx("socket SIOCSIFNETMASK");
    }
    dbg("set Netmask: "IPFMT, ipfmt(netmask));
}
Example #13
0
struct arpentry *arp_lookup(unsigned short pro, unsigned int ipaddr)
{
	struct arpentry *ae, *ret = NULL;
	arp_cache_lock();
	arpdbg("pro:%d "IPFMT, pro, ipfmt(ipaddr));
	for (ae = arp_cache_head; ae < arp_cache_end; ae++) {
		if (ae->ae_state == ARP_FREE)
			continue;
		if (ae->ae_pro == pro && ae->ae_ipaddr == ipaddr) {
			ret = ae;
			break;
		}
	}
	arp_cache_unlock();
	return ret;
}
Example #14
0
File: veth.c Project: 0xcc/tapip
static int veth_dev_init(struct netdev *dev)
{
	/* init tap: out network nic */
	if (tap_dev_init() < 0)
		perrx("Cannot init tap device");

	/* init veth: information for our netstack */
	dev->net_mtu = tap->dev.net_mtu;
	dev->net_ipaddr = FAKE_IPADDR;
	dev->net_mask = FAKE_NETMASK;
	hwacpy(dev->net_hwaddr, FAKE_HWADDR);
	dbg("%s ip address: " IPFMT, dev->net_name, ipfmt(dev->net_ipaddr));
	dbg("%s hw address: " MACFMT, dev->net_name, macfmt(dev->net_hwaddr));
	/* net stats have been zero */
	return 0;
}
Example #15
0
static void tcp_init_text(struct tcp_sock *tsk, struct pkbuf *pkb,
		void *buf, int size)
{
	struct tcp *tcphdr = pkb2tcp(pkb);
	tcphdr->src = tsk->sk.sk_sport;
	tcphdr->dst = tsk->sk.sk_dport;
	tcphdr->doff = TCP_HRD_DOFF;
	tcphdr->seq = _htonl(tsk->snd_nxt);
	tcphdr->ackn = _htonl(tsk->rcv_nxt);
	tcphdr->ack = 1;
	tcphdr->window = _htons(tsk->rcv_wnd);
	memcpy(tcphdr->data, buf, size);
	tsk->snd_nxt += size;
	tsk->snd_wnd -= size;
	tcpsdbg("send TEXT(%u:%d) [WIN %d] to "IPFMT":%d",
			_ntohl(tcphdr->seq), size, _ntohs(tcphdr->window),
			ipfmt(tsk->sk.sk_daddr), _ntohs(tcphdr->dst));
}
Example #16
0
void ifinfo(struct netdev *dev)
{
	printf("%-10sHWaddr "MACFMT"\n"
		"          IPaddr "IPFMT"\n"
		"          mtu %d\n"
		"          RX packet:%u bytes:%u errors:%u\n"
		"          TX packet:%u bytes:%u errors:%u\n",
		dev->net_name,
		macfmt(dev->net_hwaddr),
		ipfmt(dev->net_ipaddr),
		dev->net_mtu,
		dev->net_stats.rx_packets,
		dev->net_stats.rx_bytes,
		dev->net_stats.rx_errors,
		dev->net_stats.tx_packets,
		dev->net_stats.tx_bytes,
		dev->net_stats.tx_errors);
}
Example #17
0
File: tcp_out.c Project: 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);
}
Example #18
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);
	}
}
Example #19
0
File: tcp_out.c Project: 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);
}
Example #20
0
char *ipnfmt(unsigned int ipaddr)
{
	static char ipbuf[16];
	snprintf(ipbuf, 16, IPFMT, ipfmt(ipaddr));
	return ipbuf;
}
Example #21
0
int cl_setup_promisc(struct netdev *nd)
{
	char buf[1024]={0};
	struct ifconf ifc;
	struct ifreq *ifr;
	int if_cnt;
	int yes;
	struct sockaddr_ll sll;

	/* set netlink socket */
	nd->nd_fd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
	if(nd->nd_fd == -1) {
		perrx("socket:PF_PACKET");
		return -1;
	}
	
	memset(&ifc,0,sizeof(ifc));
	memset(&ifr,0,sizeof(ifr));
	
	ifc.ifc_len = sizeof(buf);
	ifc.ifc_buf = buf;
	
	if(ioctl(nd->nd_fd,SIOCGIFCONF,&ifc) < 0) {
		perrx("ioctl:SIOCGIFCONF");
		return -1;
	}
	/* list all network interfaces 
	   then look for the desired one */
	ifr = ifc.ifc_req;
	if_cnt =ifc.ifc_len / sizeof(struct ifreq);

	ifr = lookup_dev(ifr,&if_cnt,nd);
	if(ifr == NULL) {
		perrx("Couldn't get device name \n");
		return -1;
	}
#ifdef IFCONF
	printfd(2,"interface index : %d\n",ifr->ifr_ifindex);
	printfd(2,"interface address : "IPFMT"\n",
	       ipfmt((int)(((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr)));
	printfd(2,"interface netmask : "IPFMT"\n",
		ipfmt((int)(((struct sockaddr_in *)&ifr->ifr_netmask)->sin_addr.s_addr)));
#endif
	/* make sure that the interface is UP & RUNNING */
	ifr->ifr_flags |= IFF_PROMISC;
	ifr->ifr_flags |= IFF_UP |IFF_RUNNING;
	if(ioctl(nd->nd_fd, SIOCSIFFLAGS, ifr) < 0) {
		perrx("ioctl:SIOCGIFCONF");
		return -1;
	}
	
	/* get interface index */
	if (ioctl(nd->nd_fd,SIOCGIFINDEX,ifr)==-1) {
		perrx("SIOCGIFINDEX");
	}
	
	if (setsockopt(nd->nd_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {
		perrx("setsockopt:SO_REUSEADDR");
		return -1;
	}
	/* No need for this
	if (setsockopt(nd->nd_fd, SOL_SOCKET, SO_BINDTODEVICE, ifr->ifr_name, IFNAMSIZ-1) == -1)	{
		perrx("SO_BINDTODEVICE");
		return -1;
	}
	*/
	
	memset(&sll,0,sizeof(sll));
	sll.sll_family = AF_PACKET;
	sll.sll_ifindex = ifr->ifr_ifindex;
	sll.sll_protocol = htons(ETH_P_ALL);
	
	if(bind(nd->nd_fd,(struct sockaddr*)&sll,sizeof(sll)) == -1) {
		perrx("bind");
		return -1;
	}
	
	nd->nd_ops->xmit(nd,NULL);
	
	return 0;
}