Ejemplo n.º 1
0
int icmp_send(struct iphdr * __ip, struct icmp * __icp, int __len)
{
	struct route * rt;
	uint32_t saddr;
	uint32_t daddr;
	int ret;

	ICMP_PROTO_STAT_ADD(tx_ok, 1);

	__len += ICMP_MINLEN;
	saddr = __ip->daddr;
	daddr = __ip->saddr;

	/* build the ip header (swap addresses) */
	iph_template(__ip, IPPROTO_ICMP, ip_defttl, ip_deftos);
	mk_iphdr(__ip, saddr, daddr, __len);

	__icp->icmp_chksum = 0;
	__icp->icmp_chksum = ~in_chksum(0, (uint8_t *)__icp, __len);

	DCC_LOG3(LOG_INFO, "ICMP %I > %I (%d)", 
			 __ip->saddr, __ip->daddr, __len); 

	if ((rt = __route_lookup(daddr)) == NULL) {
		ICMP_PROTO_STAT_ADD(tx_drop, 1);
		DCC_LOG1(LOG_WARNING, "no route to host: %I", daddr);
		return -1;
	}

	if ((ret = ip_output(rt->rt_ifn, rt, __ip)) < 0) {
		DCC_LOG(LOG_ERROR, "ip_output() fail!");
		/* XXX:  */
		ICMP_PROTO_STAT_ADD(tx_drop, 1);

		if (ret == -EAGAIN) {
			/* FIXME: non ethernet type interfaces */
			etharp_query_pending();
		}
		return -1;
	}

	return 0;
}
Ejemplo n.º 2
0
int raw_sendto(struct raw_pcb * __raw, void * __buf, int __len, 
			   const struct sockaddr_in * __sin)
{
	struct iphdr * ip;
	in_addr_t daddr;
	in_addr_t saddr;
	struct route * rt;
	uint8_t * ptr;
	int mtu;
	struct ifnet * ifn;

	DCC_LOG2(LOG_TRACE, "<%05x> len=%d", (int)__raw, __len);
	
	tcpip_net_lock();

	DCC_LOG2(LOG_INFO, "<%05x> lock [%d]", (int)__raw, net_mutex);
	
	if (__raw == NULL) {
		DCC_LOG(LOG_WARNING, "invalid pcb");
		tcpip_net_unlock();
		return -EFAULT;
	}

	if (__buf == NULL) {
		DCC_LOG(LOG_WARNING, "invalid buffer");
		tcpip_net_unlock();
		return -EFAULT;
	}

	daddr = __sin->sin_addr.s_addr;

	if ((rt = __route_lookup(daddr)) == NULL) {
		DCC_LOG1(LOG_WARNING, "no route to host: %I", daddr);
		tcpip_net_unlock();
		return -1;
	}

	ifn = (struct ifnet *)rt->rt_ifn;
	mtu = ifn->if_mtu - sizeof(struct iphdr);

	if ((__len <= 0) || (__len > mtu)) {
		DCC_LOG3(LOG_WARNING, "<%05x> invalid length %d (max: %d)", (int)__raw, 
			__len, __raw->r_mtu);
		tcpip_net_unlock();
		return 0;
	}


	/* get the source address */
	if ((saddr = __raw->r_laddr) == INADDR_ANY) {
		saddr = ifn->if_ipv4_addr;
	}

	ip = (struct iphdr *)ifn_mmap(ifn, sizeof(struct iphdr) + __len);

	iph_template(ip, __raw->r_protocol, ip_defttl, __raw->r_tos);
	ptr = (uint8_t *)ip->opt;
	
	/* build the ip header */
	mk_iphdr(ip, saddr, daddr, __len);

	memcpy(ptr, __buf, __len);

	DCC_LOG3(LOG_TRACE, "IP %I > %I (%d)", ip->saddr, ip->daddr, __len); 

	if (ip_output(rt, ip) < 0) {
		DCC_LOG1(LOG_ERROR, "<%05x> ip_output() fail!", (int)__raw);
		/* if the reason to fail was an arp failure
		   try query an address pending for resolution ... */
		etharp_query_pending();
		tcpip_net_unlock();
		return -1;
	}

	tcpip_net_unlock();

	return __len;
}
Ejemplo n.º 3
0
int udp_sendto(struct udp_pcb * __up, void * __buf, int __len, 
			   const struct sockaddr_in * __sin)
{
	struct iphdr * ip;
	struct udphdr * uh;
	in_addr_t daddr;
	int dport;
	in_addr_t saddr;
	struct route * rt;
#if (ENABLE_NET_UDP_CHECKSUM)
	unsigned int sum;
#endif
	uint8_t * ptr;
	int mtu;
	struct ifnet * ifn;
	int ret;
	int retry = 0;

	DCC_LOG2(LOG_INFO, "<%05x> len=%d", (int)__up, __len);
	
	if (__up == NULL) {
		DCC_LOG1(LOG_WARNING, "<%05x> invalid pcb", (int)__up);
		return -EFAULT;
	}

	if (__buf == NULL) {
		DCC_LOG1(LOG_WARNING, "<%05x> invalid buffer", (int)__up);
		return -EFAULT;
	}

	tcpip_net_lock();

#if (ENABLE_NET_SANITY_CHECK)
	if (pcb_find((struct pcb *)__up, &__udp__.pcb) < 0) {
		DCC_LOG1(LOG_ERROR, "<%05x> pcb_find()", (int)__up);
		tcpip_net_unlock();
		/* TODO: errno */
		return -1;
	}
#endif

	if ((__up->u_lport) == 0) {
		DCC_LOG1(LOG_WARNING, "<%05x> not bound", (int)__up);
		tcpip_net_unlock();
		/* TODO: errno */
		return -3;
	}

	if (__sin == NULL) {
		if ((dport = __up->u_fport) == 0) {
			DCC_LOG1(LOG_WARNING, "<%05x> connection refused", (int)__up);
			tcpip_net_unlock();
			return -ECONNREFUSED;
		}

		if ((daddr = __up->u_faddr) == INADDR_ANY) {
			DCC_LOG1(LOG_WARNING, "<%05x> not connected", (int)__up);
			tcpip_net_unlock();
			return -ENOTCONN;
		}
	} else {
		if ((dport = __sin->sin_port) == 0) {
			DCC_LOG1(LOG_WARNING, "<%05x> invalid port", (int)__up);
			tcpip_net_unlock();
			return -ECONNREFUSED;
		}

		if ((daddr = __sin->sin_addr.s_addr) == INADDR_ANY) {
			DCC_LOG1(LOG_WARNING, "<%05x> invalid address", (int)__up);
			tcpip_net_unlock();
			return -EDESTADDRREQ;
		}
	}

	if ((rt = __route_lookup(daddr)) == NULL) {
		DCC_LOG2(LOG_WARNING, "<%05x> no route to host: %I", (int)__up, daddr);
		tcpip_net_unlock();
		UDP_PROTO_STAT_ADD(tx_drop, 1);
		UDP_PROTO_STAT_ADD(tx_err, 1);
		return -EHOSTUNREACH;
	}

	ifn = (struct ifnet *)rt->rt_ifn;
	mtu = ifn->if_mtu - sizeof(struct iphdr);

	if ((__len <= 0) || (__len > mtu)) {
		DCC_LOG3(LOG_WARNING, "<%04x> invalid length %d (max: %d)", 
				 (int)__up, __len, mtu);
		tcpip_net_unlock();
		/* TODO: errno */
		return -7;
	}

	/* get the source address */
	if ((saddr = __up->u_laddr) == INADDR_ANY) {
		saddr = ifn->if_ipv4_addr;
	}

again:
	ip = (struct iphdr *)ifn_mmap(ifn, sizeof(struct iphdr) + 
								  sizeof(struct udphdr) + __len);

	if (ip == NULL) {
		DCC_LOG1(LOG_WARNING, "<%04x> ifn_mmap() fail", (int)__up);
		tcpip_net_unlock();
		/* TODO: errno */
		return -1;
	}
	DCC_LOG2(LOG_TRACE, "<%05x> ip=%p", (int)__up, ip);

	iph_template(ip, IPPROTO_UDP, udp_def_ttl, udp_def_tos);
	uh = (struct udphdr *)ip->opt;
	
	/* build the ip header */
	ip = mk_iphdr(ip, saddr, daddr, sizeof(struct udphdr) + __len);

	/* fill the udp header fields */
	uh = (struct udphdr *)ip->opt;
	uh->dport = dport;
	uh->sport = __up->u_lport;
	uh->len = htons(__len + sizeof(struct udphdr));
#if (ENABLE_NET_UDP_CHECKSUM)
	/* initialize the udp checksum */
	sum = uh->len << 1;
	sum += uh->dport;
	sum += uh->sport;
	sum += (IPPROTO_UDP << 8);
	sum += ((uint16_t *)(void *)&(ip->saddr))[0] + 
		((uint16_t *)(void *)&(ip->saddr))[1];
	sum += ((uint16_t *)(void *)&(ip->daddr))[0] + 
		((uint16_t *)(void *)&(ip->daddr))[1];
#endif
	
	ptr = (uint8_t *)uh + sizeof(struct udphdr);
	memcpy(ptr, __buf, __len);

#if (ENABLE_NET_UDP_CHECKSUM)
	if (__len) {
		sum = in_chksum(sum, ptr, __len);
	}
	uh->chksum = ~sum;
#else
	uh->chksum = 0;
#endif

#if 0
	DCC_LOG(LOG_INFO, "IP %d.%d.%d.%d:%d > %d.%d.%d.%d:%d: %d", 
		IP4_ADDR1(ip->saddr), IP4_ADDR2(ip->saddr), IP4_ADDR3(ip->saddr), 
		IP4_ADDR4(ip->saddr), ntohs(uh->sport), IP4_ADDR1(ip->daddr), 
		IP4_ADDR2(ip->daddr), IP4_ADDR3(ip->daddr), IP4_ADDR4(ip->daddr), 
		ntohs(uh->dport), ntohs(uh->len)); 
#endif

	if ((ret = ip_output(ifn, rt, ip)) < 0) {
		ifn_munmap(ifn, ip);
		/* if the reason to fail was an arp failure
		   try query an address pending for resolution ... */
		if ((ret == -EAGAIN) && (retry < 10)) {
			etharp_query_pending();
			tcpip_net_unlock();
			DCC_LOG2(LOG_WARNING, "<%05x> again, retry=%d!", (int)__up, retry);
			thinkos_sleep(10 + retry * 10);
			retry++;
			tcpip_net_lock();
			goto again;
		}
		DCC_LOG1(LOG_ERROR, "<%05x> ip_output() fail!", (int)__up);
		UDP_PROTO_STAT_ADD(tx_drop, 1);
	} else {
		UDP_PROTO_STAT_ADD(tx_ok, 1);
		DCC_LOG5(LOG_INFO, "IP %I:%d > %I:%d: %d", 
				 ip->saddr, ntohs(uh->sport), ip->daddr, 
				 ntohs(uh->dport), ntohs(uh->len)); 
#if (LOG_LEVEL < LOG_INFO)
		DCC_LOG(LOG_INFO, "sent.");
#endif
		ret = __len;
	}

	tcpip_net_unlock();

	return ret;
}