Exemple #1
0
ipsec_cache_entry_t *find_ipsec_cache_entry_in(uint32_t src_ip,
					       uint32_t dst_ip,
					       odph_ahhdr_t *ah,
					       odph_esphdr_t *esp)
{
	ipsec_cache_entry_t *entry = ipsec_cache->in_list;

	/* Look for a hit */
	for (; NULL != entry; entry = entry->next) {
		if ((entry->src_ip != src_ip) || (entry->dst_ip != dst_ip))
			if ((entry->tun_src_ip != src_ip) ||
			    (entry->tun_dst_ip != dst_ip))
				continue;
		if (ah &&
		    ((!entry->ah.alg) ||
		     (entry->ah.spi != odp_be_to_cpu_32(ah->spi))))
			continue;
		if (esp &&
		    ((!entry->esp.alg) ||
		     (entry->esp.spi != odp_be_to_cpu_32(esp->spi))))
			continue;
		break;
	}

	return entry;
}
Exemple #2
0
static enum ofp_return_code ofp_ip_output_add_eth(odp_packet_t pkt,
						  struct ip_out *odata)
{
	uint8_t l2_size = 0;
	void *l2_addr;

	if (!odata->gw) /* link local */
		odata->gw = odata->ip->ip_dst.s_addr;

	if (ETH_WITHOUT_VLAN(odata->vlan, odata->out_port))
		l2_size = sizeof(struct ofp_ether_header);
	else
		l2_size = sizeof(struct ofp_ether_vlan_header);

	if (odp_packet_l2_offset(pkt) + l2_size == odp_packet_l3_offset(pkt)) {
		l2_addr = odp_packet_l2_ptr(pkt, NULL);
	} else if (odp_packet_l3_offset(pkt) >= l2_size) {
		odp_packet_l2_offset_set(pkt,
					odp_packet_l3_offset(pkt) - l2_size);
		l2_addr = odp_packet_l2_ptr(pkt, NULL);
	} else {
		l2_addr = odp_packet_push_head(pkt,
					l2_size - odp_packet_l3_offset(pkt));
		odp_packet_l2_offset_set(pkt, 0);
		odp_packet_l3_offset_set(pkt, l2_size);
		odp_packet_l4_offset_set(pkt, l2_size + (odata->ip->ip_hl<<2));
	}

	if (odp_unlikely(l2_addr == NULL)) {
		OFP_DBG("l2_addr == NULL");
		return OFP_PKT_DROP;
	}

	if (ETH_WITHOUT_VLAN(odata->vlan, odata->out_port)) {
		struct ofp_ether_header *eth =
				(struct ofp_ether_header *)l2_addr;
		uint32_t addr = odp_be_to_cpu_32(odata->ip->ip_dst.s_addr);

		if (OFP_IN_MULTICAST(addr)) {
			eth->ether_dhost[0] = 0x01;
			eth->ether_dhost[1] = 0x00;
			eth->ether_dhost[2] = 0x5e;
			eth->ether_dhost[3] = (addr >> 16) & 0x7f;
			eth->ether_dhost[4] = (addr >> 8) & 0xff;
			eth->ether_dhost[5] = addr & 0xff;
		} else if (odata->dev_out->ip_addr == odata->ip->ip_dst.s_addr) {
			odata->is_local_address = 1;
			ofp_copy_mac(eth->ether_dhost, &(odata->dev_out->mac[0]));
		} else if (ofp_get_mac(odata->dev_out, odata->gw, eth->ether_dhost) < 0) {
			send_arp_request(odata->dev_out, odata->gw);
			return ofp_arp_save_ipv4_pkt(pkt, odata->nh,
						     odata->gw, odata->dev_out);
		}

		ofp_copy_mac(eth->ether_shost, odata->dev_out->mac);
		eth->ether_type = odp_cpu_to_be_16(OFP_ETHERTYPE_IP);
	} else {
Exemple #3
0
void ofp_rt_rule_print(int fd, uint16_t vrf,
		       void (*func)(int fd, uint32_t key, int level, struct ofp_nh_entry *data))
{
	uint32_t index;

	for (index = 0; index < ROUTE_LIST_SIZE; index++)
		if (shm->rules[index].used && shm->rules[index].vrf == vrf)
			func(fd, odp_be_to_cpu_32(shm->rules[index].addr),
			     shm->rules[index].masklen,
			     &shm->rules[index].data[0]);
}
Exemple #4
0
/**
 * Helper function to print IP address.
 */
char *ofp_print_ip_addr(uint32_t addr)
{
	static char buf[4][24];
	static int sel = 0;
	uint32_t ip = odp_be_to_cpu_32(addr);

	sel++;
	if (sel > 3)
		sel = 0;
	sprintf(buf[sel], "%d.%d.%d.%d",
		ip>>24, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff);

	return buf[sel];
}
Exemple #5
0
struct ofp_nh_entry *ofp_rtl_search(struct ofp_rtl_tree *tree, uint32_t addr_be)
{
	struct ofp_nh_entry *nh = NULL;
	struct ofp_rtl_node *elem, *node = tree->root;
	uint32_t addr = odp_be_to_cpu_32(addr_be);
	uint32_t low = 0, high = IPV4_FIRST_LEVEL;

	for (; high <= IPV4_LENGTH ; low = high, high += IPV4_LEVEL) {
		elem = find_node(node, addr, low, high);

		if (elem->masklen == 0)
			return nh;
		else if (elem->masklen <= high)
			nh = &elem->data[0];

		if ((node = elem->next) == NULL)
			return nh;
	}

	return nh;
}
static enum ofp_return_code ofp_ip_output_add_eth(odp_packet_t pkt,
						  struct ip_out *odata)
{
	uint32_t l2_size;
	void *l2_addr;
	struct ofp_ether_header *eth;
	uint32_t addr;
	uint32_t is_link_local = 0;

	trim_tail(pkt, odp_be_to_cpu_16(odata->ip->ip_len));

	if (!odata->gw) { /* link local */
		odata->gw = odata->ip->ip_dst.s_addr;
		is_link_local = 1;
	}

	if (!ETH_WITH_VLAN(odata->dev_out))
		l2_size = sizeof(struct ofp_ether_header);
	else
		l2_size = sizeof(struct ofp_ether_vlan_header);

	l2_addr = trim_for_output(pkt, l2_size, odata->ip->ip_hl * 4);
	if (odp_unlikely(l2_addr == NULL)) {
		OFP_DBG("l2_addr == NULL");
		return OFP_PKT_DROP;
	}

	eth = l2_addr;
	addr = odp_be_to_cpu_32(odata->ip->ip_dst.s_addr);

	if (OFP_IN_MULTICAST(addr)) {
		eth->ether_dhost[0] = 0x01;
		eth->ether_dhost[1] = 0x00;
		eth->ether_dhost[2] = 0x5e;
		eth->ether_dhost[3] = (addr >> 16) & 0x7f;
		eth->ether_dhost[4] = (addr >> 8) & 0xff;
		eth->ether_dhost[5] = addr & 0xff;
	} else if (odata->dev_out->ip_addr == odata->ip->ip_dst.s_addr ||
Exemple #7
0
odp_bool_t verify_ipv4_packet(stream_db_entry_t *stream,
			      odp_packet_t pkt)
{
	ipsec_cache_entry_t *entry = NULL;
	uint8_t *data;
	odph_ipv4hdr_t *ip;
	odph_ahhdr_t *ah = NULL;
	odph_esphdr_t *esp = NULL;
	int hdr_len;
	odph_icmphdr_t *icmp;
	stream_pkt_hdr_t *test;
	uint32_t src_ip, dst_ip;

	if (stream->input.entry)
		entry = stream->input.entry;
	else if (stream->output.entry)
		entry = stream->output.entry;

	/* Basic IPv4 verify (add checksum verification) */
	data = odp_packet_l3_ptr(pkt, NULL);
	ip = (odph_ipv4hdr_t *)data;
	data += sizeof(*ip);
	if (0x45 != ip->ver_ihl)
		return FALSE;

	src_ip = odp_be_to_cpu_32(ip->src_addr);
	dst_ip = odp_be_to_cpu_32(ip->dst_addr);
	if ((stream->src_ip != src_ip) && stream->output.entry &&
	    (stream->output.entry->tun_src_ip != src_ip))
		return FALSE;
	if ((stream->dst_ip != dst_ip) && stream->output.entry &&
	    (stream->output.entry->tun_dst_ip != dst_ip))
		return FALSE;

	if ((stream->src_ip != src_ip) && stream->input.entry &&
	    (stream->input.entry->tun_src_ip != src_ip))
		return FALSE;
	if ((stream->dst_ip != dst_ip) && stream->input.entry &&
	    (stream->input.entry->tun_dst_ip != dst_ip))
		return FALSE;

	/* Find IPsec headers if any and compare against entry */
	hdr_len = locate_ipsec_headers(ip, &ah, &esp);

	/* Cleartext packet */
	if (!ah && !esp)
		goto clear_packet;
	if (ah) {
		if (!entry)
			return FALSE;
		if (ODP_AUTH_ALG_NULL == entry->ah.alg)
			return FALSE;
		if (odp_be_to_cpu_32(ah->spi) != entry->ah.spi)
			return FALSE;
		if (ODP_AUTH_ALG_MD5_96 != entry->ah.alg)
			abort();
	} else {
		if (entry && (ODP_AUTH_ALG_NULL != entry->ah.alg))
			return FALSE;
	}
	if (esp) {
		if (!entry)
			return FALSE;
		if (ODP_CIPHER_ALG_NULL == entry->esp.alg)
			return FALSE;
		if (odp_be_to_cpu_32(esp->spi) != entry->esp.spi)
			return FALSE;
		if (ODP_CIPHER_ALG_3DES_CBC != entry->esp.alg)
			abort();
		hdr_len += entry->esp.iv_len;
	} else {
		if (entry && (ODP_CIPHER_ALG_NULL != entry->esp.alg))
			return FALSE;
	}
	data += hdr_len;

	/* Verify authentication (if present) */
	if (ah) {
		uint8_t  ip_tos;
		uint8_t  ip_ttl;
		uint16_t ip_frag_offset;
		uint8_t  icv[12];
		uint8_t  hash[EVP_MAX_MD_SIZE];

		/* Save/clear mutable fields */
		ip_tos = ip->tos;
		ip_ttl = ip->ttl;
		ip_frag_offset = odp_be_to_cpu_16(ip->frag_offset);
		ip->tos = 0;
		ip->ttl = 0;
		ip->frag_offset = 0;
		ip->chksum = 0;
		memcpy(icv, ah->icv, 12);
		memset(ah->icv, 0, 12);

		/* Calculate HMAC and compare */
		HMAC(EVP_md5(),
		     entry->ah.key.data,
		     entry->ah.key.length,
		     (uint8_t *)ip,
		     odp_be_to_cpu_16(ip->tot_len),
		     hash,
		     NULL);

		if (0 != memcmp(icv, hash, sizeof(icv)))
			return FALSE;

		ip->proto = ah->next_header;
		ip->tos = ip_tos;
		ip->ttl = ip_ttl;
		ip->frag_offset = odp_cpu_to_be_16(ip_frag_offset);
	}

	/* Decipher if present */
	if (esp) {
		odph_esptrl_t *esp_t;
		DES_key_schedule ks1, ks2, ks3;
		uint8_t iv[8];
		int encrypt_len = ipv4_data_len(ip) - hdr_len;

		memcpy(iv, esp->iv, sizeof(iv));

		DES_set_key((DES_cblock *)&entry->esp.key.data[0], &ks1);
		DES_set_key((DES_cblock *)&entry->esp.key.data[8], &ks2);
		DES_set_key((DES_cblock *)&entry->esp.key.data[16], &ks3);

		DES_ede3_cbc_encrypt((uint8_t *)data,
				     (uint8_t *)data,
				     encrypt_len,
				     &ks1,
				     &ks2,
				     &ks3,
				     (DES_cblock *)iv,
				     0);

		esp_t = (odph_esptrl_t *)(data + encrypt_len) - 1;
		ip->proto = esp_t->next_header;
	}

clear_packet:
	/* Verify IP/ICMP packet */
	if (entry && (entry->mode == IPSEC_SA_MODE_TUNNEL) && (ah || esp)) {
		if (ODPH_IPV4 != ip->proto)
			return FALSE;
		odph_ipv4hdr_t *inner_ip = (odph_ipv4hdr_t *)data;

		icmp = (odph_icmphdr_t *)(inner_ip + 1);
		data = (uint8_t *)icmp;
	} else {
		if (ODPH_IPPROTO_ICMP != ip->proto)
			return FALSE;
		icmp = (odph_icmphdr_t *)data;
	}

	/* Verify ICMP header */
	data += sizeof(*icmp);
	if (ICMP_ECHO != icmp->type)
		return FALSE;
	if (0x1234 != odp_be_to_cpu_16(icmp->un.echo.id))
		return FALSE;

	/* Now check our packet */
	test = (stream_pkt_hdr_t *)data;
	if (STREAM_MAGIC != odp_be_to_cpu_64(test->magic))
		return FALSE;

	return TRUE;
}
enum ofp_return_code ofp_ipv4_processing(odp_packet_t *pkt)
{
	int frag_res = 0, res;
	int protocol = IS_IPV4;
	uint32_t flags;
	struct ofp_ip *ip;
	struct ofp_nh_entry *nh;
	struct ofp_ifnet *dev = odp_packet_user_ptr(*pkt);
	uint32_t is_ours;

	ip = (struct ofp_ip *)odp_packet_l3_ptr(*pkt, NULL);

	if (odp_unlikely(ip == NULL)) {
		OFP_DBG("ip is NULL");
		return OFP_PKT_DROP;
	}

	if (odp_unlikely(ofp_if_type(dev) == OFP_IFT_VXLAN)) {
		struct ofp_packet_user_area *ua;

		/* Look for the correct device. */
		ua = ofp_packet_user_area(*pkt);
		dev = ofp_get_ifnet(VXLAN_PORTS, ua->vxlan.vni);
		if (!dev)
			return OFP_PKT_DROP;
	}

	if (odp_unlikely(ip->ip_v != OFP_IPVERSION))
		return OFP_PKT_DROP;

	if (ofp_packet_user_area(*pkt)->chksum_flags
		& OFP_L3_CHKSUM_STATUS_VALID) {
		switch (odp_packet_l3_chksum_status(*pkt)) {
		case ODP_PACKET_CHKSUM_OK:
			break;
		case ODP_PACKET_CHKSUM_UNKNOWN:
			/* Checksum was not validated by HW */
			if (odp_unlikely(ofp_cksum_iph(ip, ip->ip_hl)))
				return OFP_PKT_DROP;
			break;
		case ODP_PACKET_CHKSUM_BAD:
			return OFP_PKT_DROP;
			break;
		}
		ofp_packet_user_area(*pkt)->chksum_flags &=
			~OFP_L3_CHKSUM_STATUS_VALID;
	} else if (odp_unlikely(ofp_cksum_iph(ip, ip->ip_hl)))
		return OFP_PKT_DROP;

	/* TODO: handle broadcast */
	if (dev->bcast_addr == ip->ip_dst.s_addr)
		return OFP_PKT_DROP;

	OFP_DBG("Device IP: %s, Packet Dest IP: %s",
		ofp_print_ip_addr(dev->ip_addr),
		ofp_print_ip_addr(ip->ip_dst.s_addr));

	is_ours = dev->ip_addr == ip->ip_dst.s_addr ||
		OFP_IN_MULTICAST(odp_be_to_cpu_32(ip->ip_dst.s_addr));

	if (!is_ours) {
		/* This may be for some other local interface. */
		nh = ofp_get_next_hop(dev->vrf, ip->ip_dst.s_addr, &flags);
		if (nh)
			is_ours = nh->flags & OFP_RTF_LOCAL;
	}

	if (is_ours) {
		if (odp_be_to_cpu_16(ip->ip_off) & 0x3fff) {
			frag_res = pkt_reassembly(pkt);
			if (frag_res != OFP_PKT_CONTINUE)
				return frag_res;

			ip = (struct ofp_ip *)odp_packet_l3_ptr(*pkt, NULL);
		}

		OFP_HOOK(OFP_HOOK_LOCAL, *pkt, &protocol, &res);
		if (res != OFP_PKT_CONTINUE) {
			OFP_DBG("OFP_HOOK_LOCAL returned %d", res);
			return res;
		}

		OFP_HOOK(OFP_HOOK_LOCAL_IPv4, *pkt, NULL, &res);
		if (res != OFP_PKT_CONTINUE) {
			OFP_DBG("OFP_HOOK_LOCAL_IPv4 returned %d", res);
			return res;
		}

		return ipv4_transport_classifier(pkt, ip->ip_p);

	}

	OFP_HOOK(OFP_HOOK_FWD_IPv4, *pkt, nh, &res);
	if (res != OFP_PKT_CONTINUE) {
		OFP_DBG("OFP_HOOK_FWD_IPv4 returned %d", res);
		return res;
	}

	if (nh == NULL) {
		OFP_DBG("nh is NULL, vrf=%d dest=%x", dev->vrf, ip->ip_dst.s_addr);
		return OFP_PKT_CONTINUE;
	}

	if (ip->ip_ttl <= 1) {
		OFP_DBG("OFP_ICMP_TIMXCEED");
		ofp_icmp_error(*pkt, OFP_ICMP_TIMXCEED,
				OFP_ICMP_TIMXCEED_INTRANS, 0, 0);
		return OFP_PKT_DROP;
	}

	/*
	 * Decrement TTL and incrementally change the IP header checksum.
	 */
	ip->ip_ttl--;
	uint16_t a = ~odp_cpu_to_be_16(1 << 8);
	if (ip->ip_sum >= a)
		ip->ip_sum -= a;
	else
		ip->ip_sum += odp_cpu_to_be_16(1 << 8);

#ifdef OFP_SEND_ICMP_REDIRECT
	/* 1. The interface on which the packet comes into the router is the
	 * same interface on which the packet gets routed out.
	 * 2. The subnet or network of the source IP address is on the same
	 * subnet or network of the next-hop IP address of the routed packet.
	 * 3. Stack configured to send redirects.
	 */
#define INET_SUBNET_PREFIX(addr)				\
	(odp_be_to_cpu_32(addr) & ((~0) << (32 - dev->masklen)))

	if (nh->port == dev->port &&
		(INET_SUBNET_PREFIX(ip->ip_src.s_addr) ==
		INET_SUBNET_PREFIX(nh->gw))) {

		OFP_DBG("send OFP_ICMP_REDIRECT");
		ofp_icmp_error(*pkt, OFP_ICMP_REDIRECT,
				OFP_ICMP_REDIRECT_HOST, nh->gw, 0);
	}
#endif

	return ofp_ip_output_common_inline(*pkt, nh, 0);
}
Exemple #9
0
static inline uint32_t to_network_prefix(uint32_t addr_be, uint32_t masklen)
{
	return (odp_be_to_cpu_32(addr_be)) & ((~0) << (32 - masklen));
}
Exemple #10
0
int ofp_ioctl(int sockfd, int request, ...)
{
	va_list ap;
	void *data;
	struct ofp_ifnet *iface = NULL;
	struct socket  *so = ofp_get_sock_by_fd(sockfd);
	if (!so) {
		ofp_errno = OFP_EBADF;
		return -1;
	}

	va_start(ap, request);
	data = va_arg(ap, void *);
	va_end(ap);

	if (request == (int)(OFP_SIOCGIFCONF)) {
		ofp_errno = ((*so->so_proto->pr_usrreqs->pru_control)
			       (so, request, data, NULL, NULL));
	} else if (OFP_IOCGROUP(request) == 'i') {
		/* All the interface requests start with interface name */
		int port, vlan = 0;
		char *name = data;

		if (get_port_vlan_by_name(name, &port, &vlan) < 0) {
			ofp_errno = OFP_EBADF;
			return -1;
		}

		if (request == (int)(OFP_SIOCSIFTUN)) {
			struct ofp_in_tunreq *treq = data;
			const char *retstr =
				ofp_config_interface_up_tun
				(port, vlan, treq->iftun_vrf,
				 treq->iftun_local_addr.sin_addr.s_addr,
				 treq->iftun_remote_addr.sin_addr.s_addr,
				 treq->iftun_p2p_addr.sin_addr.s_addr,
				 treq->iftun_addr.sin_addr.s_addr, 30);
			if (!retstr)
				ofp_errno = 0;
			else
				ofp_errno = OFP_EBADMSG;
		} else {
			iface = ofp_get_ifnet(port, vlan);

			if (so->so_proto->pr_usrreqs->pru_control)
				ofp_errno = ((*so->so_proto->pr_usrreqs->pru_control)
					       (so, request, data, iface, NULL));
			else
				ofp_errno = OFP_EOPNOTSUPP;
		}
	} else if (OFP_IOCGROUP(request) == 'r') {
		int port = 0, vlan = 0;
		struct ofp_rtentry *rt = data;
		uint32_t dst  = ((struct ofp_sockaddr_in *)&rt->rt_dst)->sin_addr.s_addr;
		uint32_t mask = ((struct ofp_sockaddr_in *)&rt->rt_genmask)->sin_addr.s_addr;
		uint32_t gw   = ((struct ofp_sockaddr_in *)&rt->rt_gateway)->sin_addr.s_addr;
		uint32_t maskcpu = odp_be_to_cpu_32(mask);
		uint32_t mlen = 0;

		if (request != (int)OFP_SIOCADDRT &&
		    request != (int)OFP_SIOCDELRT) {
			ofp_errno = OFP_EBADF;
			return -1;
		}

		if (request == (int)OFP_SIOCADDRT) {
			if (rt->rt_dev) {
				if (get_port_vlan_by_name(rt->rt_dev, &port, &vlan) < 0) {
					ofp_errno = OFP_EBADF;
					return -1;
				}
			} else {
				uint32_t flags;
				struct ofp_nh_entry *nh =
					ofp_get_next_hop(rt->rt_vrf, gw, &flags);
				if (!nh) {
					ofp_errno = OFP_EBADF;
					return -1;
				}
				port = nh->port;
				vlan = nh->vlan;
			}
		}

		while (maskcpu) {
			mlen++;
			maskcpu <<= 1;
		}

		ofp_set_route_params((request == (int) OFP_SIOCADDRT) ? OFP_ROUTE_ADD : OFP_ROUTE_DEL,
				     rt->rt_vrf, vlan, port,
				     dst, mlen, gw,
				     (request == (int) OFP_SIOCADDRT) ?
				     (gw ? OFP_RTF_GATEWAY : OFP_RTF_NET) : 0);
	} else {
		ofp_errno = ofp_soo_ioctl(so, request, data, NULL, NULL);
	}

	if (ofp_errno)
		return -1;

	return 0;
}
Exemple #11
0
static void print_ipv4(FILE *f, char *p)
{
	struct ofp_ip *iphdr = (struct ofp_ip *)p;
	struct ofp_icmp *icmp;
	struct ofp_udphdr *uh;
	struct ofp_tcphdr *th;

	/* if it's a non-first fragment, print only IPv4 information */
	if ((odp_be_to_cpu_16(iphdr->ip_off) & 0x1fff) != 0) {
		ofp_printf(f, "IP fragment PKT len=%d  %s -> %s ",
			   odp_be_to_cpu_16(iphdr->ip_len),
			   ofp_print_ip_addr(iphdr->ip_src.s_addr),
			   ofp_print_ip_addr(iphdr->ip_dst.s_addr));
		return;
	}

	if (iphdr->ip_p == OFP_IPPROTO_UDP) {
		uh = (struct ofp_udphdr *)(((uint8_t *)iphdr) +
					     (iphdr->ip_hl<<2));

		ofp_printf(f, "IP UDP PKT len=%d  %s:%d -> %s:%d ",
			odp_be_to_cpu_16(uh->uh_ulen),
			ofp_print_ip_addr(iphdr->ip_src.s_addr),
			odp_be_to_cpu_16(uh->uh_sport),
			ofp_print_ip_addr(iphdr->ip_dst.s_addr),
			odp_be_to_cpu_16(uh->uh_dport));

	} else if (iphdr->ip_p == OFP_IPPROTO_TCP) {
		th = (struct ofp_tcphdr *)(((uint8_t *)iphdr) +
					     (iphdr->ip_hl<<2));
		ofp_printf(f, "IP len=%d TCP %s:%d -> %s:%d\n"
			"   seq=0x%x ack=0x%x off=%d\n   flags=",
			odp_be_to_cpu_16(iphdr->ip_len),
			ofp_print_ip_addr(iphdr->ip_src.s_addr),
			odp_be_to_cpu_16(th->th_sport),
			ofp_print_ip_addr(iphdr->ip_dst.s_addr),
			odp_be_to_cpu_16(th->th_dport),
			odp_be_to_cpu_32(th->th_seq),
			odp_be_to_cpu_32(th->th_ack),
			th->th_off);
		if (th->th_flags & OFP_TH_FIN)
			ofp_printf(f, "F");
		if (th->th_flags & OFP_TH_SYN)
			ofp_printf(f, "S");
		if (th->th_flags & OFP_TH_RST)
			ofp_printf(f, "R");
		if (th->th_flags & OFP_TH_PUSH)
			ofp_printf(f, "P");
		if (th->th_flags & OFP_TH_ACK)
			ofp_printf(f, "A");
		if (th->th_flags & OFP_TH_URG)
			ofp_printf(f, "U");
		if (th->th_flags & OFP_TH_ECE)
			ofp_printf(f, "E");
		if (th->th_flags & OFP_TH_CWR)
			ofp_printf(f, "C");
		ofp_printf(f, " win=%u sum=0x%x urp=%u",
			odp_be_to_cpu_16(th->th_win),
			odp_be_to_cpu_16(th->th_sum),
			odp_be_to_cpu_16(th->th_urp));
		int i;
		int len = odp_be_to_cpu_16(iphdr->ip_len);
#if 0
		if (odp_be_to_cpu_16(th->th_win) == 0) {
			/* wrong value */
			ofp_printf(f, "\n---- th_win == 0, quit\n");
			fflush(NULL);
			int *a = 0;
			*a = 8;
		}
#endif
		if (len > 2000) {
			ofp_printf(f, "\nToo long data!\n");
			int *a = 0, b = 8, c = 9;
			*a = b + c;
		} else if (0) {
			for (i = 0; i < len; i++) {
				if ((i & 0xf) == 0)
					ofp_printf(f, "\n");
				ofp_printf(f, " %02x", (uint8_t)p[i]);
			}
		}
	} else if (iphdr->ip_p == OFP_IPPROTO_ICMP) {
		icmp = (struct ofp_icmp *)(((uint8_t *)iphdr) +
					     (iphdr->ip_hl<<2));

		switch (icmp->icmp_type) {
		case OFP_ICMP_ECHOREPLY:
			ofp_printf(f,
				"IP ICMP: echo reply  %s -> %s  id=%d seq=%d",
				ofp_print_ip_addr(iphdr->ip_src.s_addr),
				ofp_print_ip_addr(iphdr->ip_dst.s_addr),
				icmp->ofp_icmp_id, icmp->ofp_icmp_seq);
			break;
		case OFP_ICMP_UNREACH:
			ofp_printf(f, "IP ICMP: dest unreachable  %s -> %s ",
				ofp_print_ip_addr(iphdr->ip_src.s_addr),
				ofp_print_ip_addr(iphdr->ip_dst.s_addr));
			break;
		case OFP_ICMP_ECHO:
			ofp_printf(f, "IP ICMP: echo  %s -> %s  id=%d seq=%d",
				ofp_print_ip_addr(iphdr->ip_src.s_addr),
				ofp_print_ip_addr(iphdr->ip_dst.s_addr),
				icmp->ofp_icmp_id, icmp->ofp_icmp_seq);
			break;
		default:
			ofp_printf(f, "IP ICMP %d: code=%d  %s -> %s ",
				icmp->icmp_type, icmp->icmp_code,
				ofp_print_ip_addr(iphdr->ip_src.s_addr),
				ofp_print_ip_addr(iphdr->ip_dst.s_addr));
		}
	} else {
		ofp_printf(f, "IP PKT len=%d proto=%d  %s -> %s ",
			odp_be_to_cpu_16(iphdr->ip_len),
			iphdr->ip_p,
			ofp_print_ip_addr(iphdr->ip_src.s_addr),
			ofp_print_ip_addr(iphdr->ip_dst.s_addr));
	}
}
Exemple #12
0
static void *mcasttest(void *arg)
{
	int fd;
	struct ofp_sockaddr_in my_addr;
	struct ofp_ip_mreq mreq;
	(void)arg;

	logprint("Multicast thread started\n");

	if (odp_init_local(ODP_THREAD_CONTROL)) {
		OFP_ERR("Error: ODP local init failed.\n");
		return NULL;
	}
	if (ofp_init_local()) {
		OFP_ERR("Error: OFP local init failed.\n");
		return NULL;
	}
	sleep(1);

	while (myaddr == 0) {
		myaddr = ofp_port_get_ipv4_addr(0, 0, OFP_PORTCONF_IP_TYPE_IP_ADDR);
		sleep(1);
	}

	if ((fd = ofp_socket(OFP_AF_INET, OFP_SOCK_DGRAM, OFP_IPPROTO_UDP)) < 0) {
		perror("socket");
		logprint("Cannot open socket!\n");
		return NULL;
	}

	memset(&my_addr, 0, sizeof(my_addr));
	my_addr.sin_family = OFP_AF_INET;
	my_addr.sin_port = odp_cpu_to_be_16(2048);
	my_addr.sin_addr.s_addr = 0;
	my_addr.sin_len = sizeof(my_addr);

	if (ofp_bind(fd, (struct ofp_sockaddr *)&my_addr,
		       sizeof(struct ofp_sockaddr)) < 0) {
		logprint("Cannot bind socket (%s)!\n", ofp_strerror(ofp_errno));
		return NULL;
	}

	memset(&mreq, 0, sizeof(mreq));
        mreq.imr_multiaddr.s_addr = IP4(234,5,5,5);
        mreq.imr_interface.s_addr = myaddr;
        if (ofp_setsockopt(fd, OFP_IPPROTO_IP, OFP_IP_ADD_MEMBERSHIP,
			   &mreq, sizeof(mreq)) == -1) {
		perror("setsockopt");
        }

	memset(&mreq, 0, sizeof(mreq));
        mreq.imr_multiaddr.s_addr = IP4(234,7,7,7);
        mreq.imr_interface.s_addr = myaddr;
        if (ofp_setsockopt(fd, OFP_IPPROTO_IP, OFP_IP_ADD_MEMBERSHIP,
			   &mreq, sizeof(mreq)) == -1) {
		perror("setsockopt");
        }

	for (;;) {
		char buf[100];
		int len = sizeof(buf);
		struct ofp_sockaddr_in addr = {0};
		ofp_socklen_t addr_len = 0;

		len = ofp_recvfrom(fd, buf, len, 0,
				   (struct ofp_sockaddr *)&addr, &addr_len);
		if (len == -1) {
			OFP_ERR("Faild to rcv data(errno = %d)\n", ofp_errno);
			continue;
		}

		buf[len] = 0;
		OFP_INFO("Data (%s, len = %d) was received.\n", buf, len);

		if (addr_len != sizeof(addr)) {
			OFP_ERR("Faild to rcv source address: %d (errno = %d)\n",
				addr_len, ofp_errno);
			continue;
		}

		if (strstr(buf, "add")) {
			OFP_INFO("Add membership to 234.7.7.7\n");
			memset(&mreq, 0, sizeof(mreq));
			mreq.imr_multiaddr.s_addr = IP4(234,7,7,7);
			mreq.imr_interface.s_addr = myaddr;
			if (ofp_setsockopt(fd, OFP_IPPROTO_IP, OFP_IP_ADD_MEMBERSHIP,
					   &mreq, sizeof(mreq)) == -1) {
				perror("setsockopt");
			}
		} else if (strstr(buf, "drop")) {
			OFP_INFO("Drop membership from 234.7.7.7\n");
			memset(&mreq, 0, sizeof(mreq));
			mreq.imr_multiaddr.s_addr = IP4(234,7,7,7);
			mreq.imr_interface.s_addr = myaddr;
			if (ofp_setsockopt(fd, OFP_IPPROTO_IP, OFP_IP_DROP_MEMBERSHIP,
					   &mreq, sizeof(mreq)) == -1) {
				perror("setsockopt");
			}
		} else if (strstr(buf, "quit")) {
			exit(0);
		}

		OFP_INFO("Data was received from address 0x%x, port = %d.\n",
			 odp_be_to_cpu_32(addr.sin_addr.s_addr),
			 odp_be_to_cpu_16(addr.sin_port));

		sprintf(buf, "%d bytes\n", len);

		if (ofp_sendto(fd, buf, strlen(buf), 0,
			       (struct ofp_sockaddr *)&addr,
			       sizeof(addr)) == -1) {
			OFP_ERR("Faild to send data (errno = %d)\n", ofp_errno);
		}
	}

	logprint("mcast exit\n");
	return NULL;
}
Exemple #13
0
enum ofp_return_code ofp_ipv4_processing(odp_packet_t pkt)
{
	int res;
	int protocol = IS_IPV4;
	uint32_t flags;
	struct ofp_ip *ip;
	struct ofp_nh_entry *nh;
	struct ofp_ifnet *dev = odp_packet_user_ptr(pkt);
	uint32_t is_ours;

	ip = (struct ofp_ip *)odp_packet_l3_ptr(pkt, NULL);

	if (odp_unlikely(ip == NULL)) {
		OFP_DBG("ip is NULL");
		return OFP_PKT_DROP;
	}

	if (odp_unlikely(!PHYS_PORT(dev->port))) {
		switch (dev->port) {
		case GRE_PORTS:
			/* Doesn't happen. */
			break;
		case VXLAN_PORTS: {
			/* Look for the correct device. */
			struct vxlan_user_data *saved = odp_packet_user_area(pkt);
			dev = ofp_get_ifnet(VXLAN_PORTS, saved->vni);
			if (!dev)
				return OFP_PKT_DROP;
			break;
		}
		}
	}

#ifndef OFP_PERFORMANCE
	if (odp_unlikely(ip->ip_v != 4))
		return OFP_PKT_DROP;
	if (odp_unlikely(ofp_cksum_buffer((uint16_t *) ip, ip->ip_hl<<2)))
		return OFP_PKT_DROP;

	/* TODO: handle broadcast */
	if (dev->bcast_addr == ip->ip_dst.s_addr)
		return OFP_PKT_DROP;
#endif

	OFP_DBG("Device IP: %s, Packet Dest IP: %s",
		ofp_print_ip_addr(dev->ip_addr),
		ofp_print_ip_addr(ip->ip_dst.s_addr));

	is_ours = dev->ip_addr == ip->ip_dst.s_addr ||
		OFP_IN_MULTICAST(odp_be_to_cpu_32(ip->ip_dst.s_addr));

	if (!is_ours) {
		/* This may be for some other local interface. */
		nh = ofp_get_next_hop(dev->vrf, ip->ip_dst.s_addr, &flags);
		if (nh)
			is_ours = nh->flags & OFP_RTF_LOCAL;
	}

	if (is_ours) {
		if (odp_be_to_cpu_16(ip->ip_off) & 0x3fff) {
			OFP_UPDATE_PACKET_STAT(rx_ip_frag, 1);

			pkt = ofp_ip_reass(pkt);
			if (pkt == ODP_PACKET_INVALID)
				return OFP_PKT_ON_HOLD;

			OFP_UPDATE_PACKET_STAT(rx_ip_reass, 1);

			ip = (struct ofp_ip *)odp_packet_l3_ptr(pkt, NULL);
		}

		OFP_HOOK(OFP_HOOK_LOCAL, pkt, &protocol, &res);
		if (res != OFP_PKT_CONTINUE) {
			OFP_DBG("OFP_HOOK_LOCAL returned %d", res);
			return res;
		}

		OFP_HOOK(OFP_HOOK_LOCAL_IPv4, pkt, NULL, &res);
		if (res != OFP_PKT_CONTINUE) {
			OFP_DBG("OFP_HOOK_LOCAL_IPv4 returned %d", res);
			return res;
		}

		return ipv4_transport_classifier(pkt, ip->ip_p);
	}

	OFP_HOOK(OFP_HOOK_FWD_IPv4, pkt, nh, &res);
	if (res != OFP_PKT_CONTINUE) {
		OFP_DBG("OFP_HOOK_FWD_IPv4 returned %d", res);
		return res;
	}

	if (nh == NULL) {
		OFP_DBG("nh is NULL, vrf=%d dest=%x", dev->vrf, ip->ip_dst.s_addr);
		return OFP_PKT_CONTINUE;
	}

	if (ip->ip_ttl <= 1) {
		OFP_DBG("OFP_ICMP_TIMXCEED");
		ofp_icmp_error(pkt, OFP_ICMP_TIMXCEED,
				OFP_ICMP_TIMXCEED_INTRANS, 0, 0);
		return OFP_PKT_DROP;
	}

	/*
	 * Decrement TTL and incrementally change the IP header checksum.
	 */
	ip->ip_ttl--;
	uint16_t a = ~odp_cpu_to_be_16(1 << 8);
	if (ip->ip_sum >= a)
		ip->ip_sum -= a;
	else
		ip->ip_sum += odp_cpu_to_be_16(1 << 8);

#ifdef OFP_SEND_ICMP_REDIRECT
	/* 1. The interface on which the packet comes into the router is the
	 * same interface on which the packet gets routed out.
	 * 2. The subnet or network of the source IP address is on the same
	 * subnet or network of the next-hop IP address of the routed packet.
	 * 3. Stack configured to send redirects.
	 */
#define INET_SUBNET_PREFIX(addr)				\
	(odp_be_to_cpu_32(addr) & ((~0) << (32 - dev->masklen)))

	if (nh->port == dev->port &&
		(INET_SUBNET_PREFIX(ip->ip_src.s_addr) ==
		INET_SUBNET_PREFIX(nh->gw))) {

		OFP_DBG("send OFP_ICMP_REDIRECT");
		ofp_icmp_error(pkt, OFP_ICMP_REDIRECT,
				OFP_ICMP_REDIRECT_HOST, nh->gw, 0);
	}
#endif

	return ofp_ip_output(pkt, nh);
}