PERFORCE change 141879 for review

Ryan French rfrench at FreeBSD.org
Mon May 19 22:25:39 UTC 2008


http://perforce.freebsd.org/chv.cgi?CH=141879

Change 141879 by rfrench at rfrench_mpls on 2008/05/19 22:24:41

	Almost working, just have to debug a few things and check that the packet is making it onto the stack succesfully.	
	Submitted by: Ryan French	

Affected files ...

.. //depot/projects/soc2008/rfrench_mpls/mpls-needle/mpls-needle.c#2 edit

Differences ...

==== //depot/projects/soc2008/rfrench_mpls/mpls-needle/mpls-needle.c#2 (text+ko) ====

@@ -1,12 +1,516 @@
+/*-
+* Copyright (c) 2008 Ryan James French
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+* 1. Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+* SUCH DAMAGE.
+*
+* $FreeBSD$
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
 #include <sys/types.h>
-#include <sysioctl.h>
-#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+
+#include <arpa/inet.h>
+
 #include <net/bpf.h>
-#include <net/libnet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/if_ether.h>
+
+#include "in_cksum.c"
 
 int main(int argc, char *argv[])
 {
-	net_init();
+	char *config_name;
+	char *if_name;
+	char line[128];
+	uint32_t i;
+	
+	char dev[16];
+	size_t len = 16;
+	
+	uint8_t *buf;
+	ssize_t wb;
+	
+	//datagram data
+	uint8_t datagram[1500];
+	
+	//check for incorrect arguments
+	if (argc < 5) 
+	{
+		fprintf(stderr,"incorrect usage of program - refer to documentation\n");
+		return 1;
+	}
+	
+	dl_bpf_open(&if_name);
+	
+	for(i=1; i<argc; i++)
+	{
+		if(strcmp(argv[i], "-i") == 0)
+		{
+			i++;
+			if_name = argv[i];
+		}
+		else if(strcmp(argv[i], "-c") == 0)
+		{
+			i++;
+			config_name = argv[i];
+		}
+	}
+	
+	printf("if_name = %s\n", if_name);
+	printf("config_name = %s\n", config_name);
+	
+	FILE *config = fopen(config_name, "r");
+	if(config == NULL)
+	{
+		fprintf(stderr, "unable to open config file '%s'\n", config_name);
+		return 2;
+	}
+	
+	while(!(feof(config)))
+	{
+		fgets(line, 128, config);
+		build_packets(line, datagram, if_name);
+		if((wb = write(dev, datagram, len)) < (ssize_t)len)
+		{
+			if(wb == -1)
+			{
+				fprintf(stderr, "%d bytes failed", len);
+			}
+			else
+			{
+				printf("%d bytes sent of %d total", wb, len);
+			}
+
+			return -1;
+		}
+	}
+	
+	//close config file
+	fclose(config);
+	
+	return 0;	
+}
+
+int parse_ip4(char *str, struct in_addr *src, struct in_addr *dst, uint8_t *ttl, uint8_t *tos)
+{
+	char *cur, *next;
+	int field = 0;
+
+	cur = str;
+	while((next = strchr(cur, '/')) != NULL)
+	{
+		*next = '\0'; /* change the / to a terminating null byte */
+
+		if(field == 0)
+		{
+			if(inet_pton(AF_INET, cur, src) != 1)
+			{
+				fprintf(stderr, "ip4_src '%s' invalid: %s\n", cur, strerror(errno));
+				return -1;
+			}
+		}
+		else if(field == 1)
+		{
+			if(inet_pton(AF_INET, cur, dst) != 1)
+			{
+				fprintf(stderr, "ip4_dst '%s' invalid: %s\n", cur, strerror(errno));
+				return -1;
+			}
+		}
+		else if(field == 2)
+		{
+			*ttl = atoi(cur);
+		}
+
+		field++;
+		cur = next + 1;
+	}
+
+	if(field != 3)
+	{
+		fprintf(stderr, "field %d\n", field);
+		return -1;
+	}
+	
+	*tos = atoi(cur);
+	
+	printf("ip4_src = %s\n", inet_ntoa(*src));
+	printf("ip4_dst = %s\n", inet_ntoa(*dst));
+	printf("ip4_ttl = %d\n", *ttl);
+	printf("ip4_tos = %d\n", *tos);
+	
+	return 0;
+}
+
+int parse_icmp4(char *str, uint8_t *type, uint8_t *code)
+{
+	char *cur, *next;
+	int field = 0;
+	
+	cur = str;
+	while((next = strchr(cur, '/')) != NULL)
+	{
+		*next = '\0';
+		
+		if(field == 0)
+		{
+			if(atoi(cur) < 0 || atoi(cur) > 255)
+			{
+				fprintf(stderr, "cur = %s\n", cur);
+				return -1;
+			}
+			else
+			{
+				*type = atoi(cur);
+			}
+		}
+		
+		field++;
+		cur = next+1;
+	}
+	
+	if(field != 1)
+	{
+		fprintf(stderr, "field = %s\n", field);
+		return -2;
+	}
+	
+	if(atoi(cur) < 0 || atoi(cur) > 255)
+	{
+		fprintf(stderr, "cur = %s\n", cur);
+		return -1;
+	}
+	*code = atoi(cur);
+	
+	return 0;
+}
+
+int parse_mpls(char *str, uint32_t *label, uint8_t *qos, uint8_t *bos_flag, uint8_t *ttl)
+{
+	char *cur, *next;
+	int field = 0;
+	
+	cur = str;
+	
+	while((next = strchr(cur, '/')) != NULL)
+	{
+		*next = '\0';
+		
+		if(field == 0)
+		{
+			*label = atoi(cur);
+		}
+		else if(field == 1)
+		{
+			if(atoi(cur) < 0 || atoi(cur) > 255)
+			{
+				fprintf(stderr, "cur = %s\n", cur);
+				return -1;
+			}
+			else
+			{
+				*qos = atoi(cur);
+			}
+		}
+		else if(field == 2)
+		{	
+			if(atoi(cur) < 0 || atoi(cur) > 255)
+			{
+				fprintf(stderr, "cur = %s\n", cur);
+				return -1;
+			}
+			else 
+			{
+				*bos_flag = atoi(cur);
+			}
+		}
+		
+		field++;
+		cur = next+1;
+	}
+	
+	if(field != 3)
+	{
+		fprintf(stderr, "field = %d\n", field);
+		return -2;
+	}
+	
+	if(atoi(cur) < 0 || atoi(cur) > 255)
+	{
+		fprintf(stderr, "cur = %s\n", cur);
+		return -1;
+	}
+	*ttl = atoi(cur);
+	
+	return 0;
+}
+
+int build_packets(char *line, uint8_t *datagram, char *if_name)
+{
+	uint32_t if_index;
+	
+	//destination/source packet data
+	
+	//mac addresses
+	struct ether_addr src_mac, dst_mac;
+	
+	//ip4 header data
+	struct in_addr ip4_src, ip4_dst;
+	uint8_t ip4_ttl, ip4_tos;
+	
+	//icmp header data
+	uint8_t icmp_type, icmp_code;
+	uint16_t icmp_checksum;
+	
+	//mpls header data
+	uint32_t mpls_label;
+	uint8_t mpls_qos, mpls_bos_flag, mpls_ttl;
+	
+	//random variables
+	char *cur, *next;
+	
+	struct ether_header *eth = (struct ether_header *)(datagram);
+	struct ip *iph = (struct ip *)(datagram + sizeof(uint32_t) + sizeof(struct ether_header));
+	struct icmphdr *icmph = (struct icmphdr *)(datagram + sizeof(struct ip) + sizeof(uint32_t) + sizeof(struct ether_header));
+	
+	//zero out the buffer
+	memset(datagram, 0, 1500);
+	
+	if_index = if_nametoindex(if_name);
+	printf("if_index = %d\n", if_index);
+	if_getmac(if_index, &src_mac);
+	//printf("got mac address = %d\n", temp_mac);
+//  	src_mac = ether_aton(temp_mac);
+	
+	cur = strdup(line);	
+	while((next = strchr(cur, ' ')) != NULL)
+	{
+		*next = '\0';
+		if(strcmp(cur, "dst_mac") == 0)
+		{
+			printf("\nextracting dst_mac\n");
+			cur = next + 1;
+			next = strchr(cur, ' ');
+			*next = '\0';
+			memcpy(&dst_mac, ether_aton(cur), sizeof(dst_mac));
+			printf("dst_mac = %s\n", ether_ntoa(&dst_mac));
+		}
+		else if(strcmp(cur, "icmp") == 0)
+		{
+			printf("\nextracting icmp data\n");
+			cur = next + 1;
+			next = strchr(cur, ' ');
+			*next = '\0';
+			parse_icmp4(cur, &icmp_type, &icmp_code);
+			printf("icmp_type = %d\n", icmp_type);
+			printf("icmp_code = %d\n", icmp_code);
+		}
+		else if(strcmp(cur, "ip4") == 0)
+		{
+			printf("\nextracting ip4 data\n");
+			cur = next + 1;
+			next = strchr(cur, ' ');
+			*next = '\0';
+			parse_ip4(cur, &ip4_src, &ip4_dst, &ip4_ttl, &ip4_tos);
+		}
+		else if(strcmp(cur, "mpls") == 0)
+		{
+			printf("\nextracting mpls data\n");
+			cur = next + 1;
+			next = strchr(cur, ' ');
+			*next = '\0';
+			parse_mpls(cur, &mpls_label, &mpls_qos, &mpls_bos_flag, &mpls_ttl);
+			printf("mpls_label = %d\n", mpls_label);
+			printf("mpls_qos = %d\n", mpls_qos);
+			printf("mpls_bos_flag = %d\n", mpls_bos_flag);
+			printf("mpls_ttl = %d\n", mpls_ttl);
+		}
+		
+		cur = next + 1;
+	}
+	
+	//set values in ethernet header
+	memcpy(eth->ether_dhost, &dst_mac, sizeof(dst_mac));
+	memcpy(eth->ether_shost, &src_mac, sizeof(src_mac));
+	eth->ether_type = htons(ETHERTYPE_MPLS);
+	
+	//set values in ip header
+	iph->ip_hl = 5;
+	iph->ip_v = 4;
+	iph->ip_tos = ip4_tos;
+	iph->ip_len = (sizeof(struct ip) + sizeof(struct icmphdr));
+	iph->ip_id = htonl (54321);
+	iph->ip_off = 0;
+	iph->ip_ttl = ip4_ttl;
+	iph->ip_p = 1;
+	iph->ip_sum = 0;
+	iph->ip_sum = in_cksum((unsigned short *)iph, sizeof(iph));
+	iph->ip_src.s_addr = inet_addr(inet_ntoa(ip4_src));
+	iph->ip_dst.s_addr = inet_addr(inet_ntoa(ip4_dst));
+	
+	//set values in icmp header
+	icmph->icmp_type = icmp_type;
+	icmph->icmp_code = icmp_code;
+	icmph->icmp_cksum = 0;
+	icmph->icmp_cksum = in_cksum((unsigned short *)icmph, sizeof(icmph));
+	
+	//set values in mpls header	
+	uint32_t mplsh = htonl(mpls_label << 12 | mpls_qos << 9 | mpls_bos_flag << 8 | mpls_ttl);
+	memcpy(&datagram[14], &mplsh, 4);
+	
+	printf("\nbuilt packets values\n");
+	
+	printf("dst_mac = %s\n", ether_ntoa(&dst_mac));
+	printf("src_mac = %s\n", ether_ntoa(&src_mac));
+	
+	printf("ip_hl = %d\n", iph->ip_hl);
+	printf("ip_v = %d\n", iph->ip_v);
+	printf("ip_tos = %d\n", iph->ip_tos);
+	printf("ip_len = %d\n", iph->ip_len);
+	printf("ip_id = %d\n", iph->ip_id);
+	printf("ip_off = %d\n", iph->ip_off);
+	printf("ip_ttl = %d\n", iph->ip_ttl);
+	printf("ip_p = %d\n", iph->ip_p);
+	printf("ip_sum = %d\n", iph->ip_sum);
+	printf("ip_src = %s\n", inet_ntoa(iph->ip_src));
+	printf("ip_dst = %s\n", inet_ntoa(iph->ip_dst));
+	
+	printf("icmp_type = %d\n", icmph->icmp_type);
+	printf("icmp_code = %d\n", icmph->icmp_code);
+	printf("icmp_cksum = %d\n", icmph->icmp_cksum);
+	
+	printf("mpls_label = %d\n", mpls_label);
+	printf("mpls_qos = %d\n", mpls_qos);
+	printf("mpls_bos_flag = %d\n", mpls_bos_flag);
+	printf("mpls_ttl = %d\n", mpls_ttl);
+	
+	return 0;
+}
 
+int if_getmac(const int ifindex, struct ether_addr *mac)
+{
+	struct if_msghdr *ifm;
+	struct sockaddr_dl *sdl;
+	int mib[6];
+	size_t len;
+	uint8_t *buf;
+	
+	mib[0] = CTL_NET;
+	mib[1] = AF_ROUTE;
+	mib[2] = 0;
+	mib[3] = AF_LINK;
+	mib[4] = NET_RT_IFLIST;
+	mib[5] = ifindex;
+	
+	if(sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
+	{
+		fprintf(stderr, "could not get sysctl bufflen\n");
+		return -1;
+	}
+	
+	if((buf = malloc(len)) == NULL)
+	{
+		fprintf(stderr, "could not make malloc buf\n");
+		return -1;
+	}
+	
+	if(sysctl(mib, 6, buf, &len, NULL, 0) < 0)
+	{
+		fprintf(stderr, "could not sysctl data\n");
+		return -1;
+	}
+	
+	ifm = (struct if_msghdr *)buf;
+	sdl = (struct sockaddr_dl *)(buf + sizeof(struct if_msghdr));
+	memcpy(mac, LLADDR(sdl), 6);
 	
-} 
+	free(buf);
+	return 0;
+}
+
+int dl_bpf_open_dev(char *dev, const size_t len)
+{
+	int i=0, fd;
+
+	do
+	{
+		snprintf(dev, len, "/dev/bpf%d\n", i);
+		if((fd = open(dev, O_RDWR)) == -1)
+		{
+			if(errno == EBUSY)
+			{
+				continue;
+			}
+			else
+			{
+				fprintf(stderr, "could not open %s\n", dev);
+				return -1;
+			}
+		}
+		else break;
+	}
+	while(++i < 32768);
+
+	return fd;
+}
+
+int dl_bpf_open(const char *ifname)
+{
+	struct ifreq ifreq;
+	char dev[16];
+	int  fd;
+
+	/* work out the name corresponding to the ifindex */
+	memset(&ifreq, 0, sizeof(ifreq));
+	strcpy(ifreq.ifr_name, ifname);
+
+	if((fd = dl_bpf_open_dev(dev, sizeof(dev))) == -1)
+	{
+		return -1;
+	}
+
+	/* set the interface that will be sniffed */
+	if(ioctl(fd, BIOCSETIF, &ifreq) == -1)
+	{
+		fprintf(stderr, "%s BIOCSETIF %s failed\n", dev, ifreq.ifr_name);
+		close(fd);
+		return -1;
+	}
+
+	return fd;
+}
+


More information about the p4-projects mailing list