PERFORCE change 141914 for review

Ryan French rfrench at FreeBSD.org
Tue May 20 13:05:29 UTC 2008


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

Change 141914 by rfrench at rfrench_mpls on 2008/05/20 13:04:59

	Thank you to all those who emailed me about my submission. This is a 
	new version of mpls-needle that is (I hope) more style(9) compatible.
	Good to see the community helping out those of us who are new to
	this FreeBSD thing with GSoC, any other hints and tips are greatly
	appreciated, even if they are to tell me this is not an appropriate
	medium to say these things.

Affected files ...

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

Differences ...

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

@@ -26,32 +26,37 @@
 * $FreeBSD$
 */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
 
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <sys/sysctl.h>
 
-#include <arpa/inet.h>
-
 #include <net/bpf.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 <arpa/inet.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
 
 #include "in_cksum.c"
 
-int main(int argc, char *argv[])
+/*
+ * This program will read in a configuration file, and will create datagrams based on this 
+ * configuration file. It then will find and open a spare BPF device and write the packet
+ * to the device. It will write a packet for each line in the configuration file.
+ */
+int
+main(int argc, char *argv[])
 {
 	char *config_name;
 	char *if_name;
@@ -63,318 +68,276 @@
 	
 	ssize_t wb;
 	
-	//datagram data
+	/* 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;
+	/* check for incorrect arguments */
+	if (argc < 5) {
+	    fprintf(stderr,"incorrect usage of program - refer to documentation\n");
+	    return -1;
 	}
 	
-	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];
-		}
+	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);
 	
-	if((fd = dl_bpf_open(if_name)) == -1)
-	{
-		fprintf(stderr, "unable to open bpf device on interface %s\n", if_name);
-		return -1;
+	/* find and open an unused bpf device */
+	if ((fd = dl_bpf_open(if_name)) == -1) {
+	    fprintf(stderr, "unable to open bpf device on interface %s\n", if_name);
+	    return -1;
 	}
 	
+	/* open the config file */
 	FILE *config = fopen(config_name, "r");
-	if(config == NULL)
-	{
-		fprintf(stderr, "unable to open config file '%s'\n", config_name);
-		return -1;
+	if (config == NULL) {
+	    fprintf(stderr, "unable to open config file '%s'\n", config_name);
+	    return -1;
 	}
 	
-	while(!(feof(config)))
-	{
-		fgets(line, 128, config);
-		build_packets(line, datagram, if_name, &len);
-		if((wb = write(fd, datagram, len)) < (ssize_t)len)
-		{
-			if(wb == -1)
-			{
-				fprintf(stderr, "%d bytes failed\n", len);
-			}
-			else
-			{
-				printf("%d bytes sent of %d total\n", wb, len);
-			}
-
-			return -1;
-		}
+	/* read the lines from the config file, building each packet, then writing the packet 
+	 * to the bpf device 
+	 */
+	while (!(feof(config))) {
+	    fgets(line, 128, config);
+	    build_packets(line, datagram, if_name, &len);
+	    if ((wb = write(fd, datagram, len)) < (ssize_t)len) {
+		if (wb == -1)
+		    fprintf(stderr, "%d bytes failed\n", len);
+		else
+		    printf("%d bytes sent of %d total\n", wb, len);
+		return -1;
+	    }
 	}
 	
-	//close config file
+	/* close config file */
 	fclose(config);
-	//close the bpf device
+	/* close the bpf device */
 	close(fd);
 	
 	return 0;	
 }
 
-int parse_ip4(char *str, struct in_addr *src, struct in_addr *dst, uint8_t *ttl, uint8_t *tos)
+/*
+ * Parse the IPv4 arguments from the configuration file
+ */
+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 */
+	while ((next = strchr(cur, '/')) != NULL) {
+	    /* change the / to a terminating null byte */
+	    *next = '\0'; 
 
-		if(field == 0)
-		{
-			if(inet_pton(AF_INET, cur, src) != 1)
-			{
-				fprintf(stderr, "ip4_src '%s' invalid: %s\n", cur, strerror(errno));
-				return -1;
-			}
+	    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 == 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;
+	    }
+	    else if (field == 2)
+		*ttl = atoi(cur);
+	
+	field++;
+	cur = next + 1;
 	}
 
-	if(field != 3)
-	{
-		fprintf(stderr, "field %d\n", field);
-		return -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)
+/*
+ * Parse the ICMP arguments from the configuration file
+ */
+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';
+	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);
-			}
+	    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;
+	    field++;
+	    cur = next+1;
 	}
 	
-	if(field != 1)
-	{
-		fprintf(stderr, "field = %s\n", field);
-		return -2;
+	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;
+	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)
+/*
+ * Parse the MPLS arguments from the configuration file
+ */
+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);
+	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 if(field == 1)
-		{
-			if(atoi(cur) < 0 || atoi(cur) > 255)
-			{
-				fprintf(stderr, "cur = %s\n", cur);
-				return -1;
-			}
-			else
-			{
-				*qos = atoi(cur);
-			}
+		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);
-			}
+	    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;
+	    field++;
+	    cur = next+1;
 	}
 	
-	if(field != 3)
-	{
-		fprintf(stderr, "field = %d\n", field);
-		return -2;
+	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;
+	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, size_t *len)
+/*
+ * Build the packet given the line taken from the configuratione file. Insert these values into
+ * the headers, assemble them into the datagram. Uses the interface name to find the source
+ * hosts mac address as well. Programatically determines the size of the created packet with
+ * a 20 byte payload.
+ */
+int
+build_packets(char *line, uint8_t *datagram, char *if_name, size_t *len)
 {
 	uint32_t if_index;
-	
-	//destination/source packet data
-	
-	//mac addresses
+	/* mac addresses */
 	struct ether_addr src_mac, dst_mac;
 	
-	//ip4 header data
+	/* ip4 header data */
 	struct in_addr ip4_src, ip4_dst;
 	uint8_t ip4_ttl, ip4_tos;
 	
-	//icmp header data
+	/* icmp header data */
 	uint8_t icmp_type, icmp_code;
 	uint16_t icmp_checksum;
 	
-	//mpls header data
+	/*mpls header data */
 	uint32_t mpls_label;
 	uint8_t mpls_qos, mpls_bos_flag, mpls_ttl;
 	
-	//random variables
+	/* 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));
+	struct icmphdr *icmph = (struct icmphdr *)(datagram + sizeof(struct ip) + sizeof(uint32_t) +
+		sizeof(struct ether_header));
 	uint32_t mplsh;
 	
-	//zero out the buffer
-	memset(datagram, 0, 1500);
+	/* 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)
-	{
+	while ((next = strchr(cur, ' ')) != NULL) {
+	    *next = '\0';
+	    if (strcmp(cur, "dst_mac") == 0) {
+		cur = next + 1;
+		next = strchr(cur, ' ');
+		*next = '\0';
+		memcpy(&dst_mac, ether_aton(cur), sizeof(dst_mac));
+	    }
+	    else if (strcmp(cur, "icmp") == 0) {
+		cur = next + 1;
+		next = strchr(cur, ' ');
+		*next = '\0';
+		parse_icmp4(cur, &icmp_type, &icmp_code);
+	    }
+	    else if (strcmp(cur, "ip4") == 0) {
+		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) {
+		cur = next + 1;
+		next = strchr(cur, ' ');
 		*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);
-		}
+		parse_mpls(cur, &mpls_label, &mpls_qos, &mpls_bos_flag, &mpls_ttl);
+	    }
 		
-		cur = next + 1;
+	    cur = next + 1;
 	}
 	
-	//set values in ethernet header
+	/* 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
+	/* set values in ip header */
 	iph->ip_hl = 5;
 	iph->ip_v = 4;
 	iph->ip_tos = ip4_tos;
@@ -388,48 +351,56 @@
 	iph->ip_dst.s_addr = inet_addr(inet_ntoa(ip4_dst));
 	iph->ip_sum = in_cksum((unsigned short *)iph, iph->ip_hl<<2);
 	
-	//set values in icmp header
+	/* 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, 4);
 	
-	//set values in mpls header	
+	/* set values in mpls header */
 	mplsh = htonl(mpls_label << 12 | mpls_qos << 9 | mpls_bos_flag << 8 | mpls_ttl);
 	memcpy(&datagram[14], &mplsh, 4);
 	
 	*len = (14 + (sizeof(mplsh)) + (iph->ip_hl<<2) + 8 + 20);
 	
-	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);
+	/*
+	 * The following lines are used during debugging to check the values extracted from the
+	 * config file are correct. Uncomment these when debugging.
+	 * 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);
+	 */
 	
-	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)
+/*
+ * Get the hosts source mac address based on the interface that the packets will be sent out.
+ */
+int
+if_getmac(const int ifindex, struct ether_addr *mac)
 {
 	struct if_msghdr *ifm;
 	struct sockaddr_dl *sdl;
@@ -444,19 +415,19 @@
 	mib[4] = NET_RT_IFLIST;
 	mib[5] = ifindex;
 	
-	if(sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
+	if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
 	{
 		fprintf(stderr, "could not get sysctl bufflen\n");
 		return -1;
 	}
 	
-	if((buf = malloc(len)) == NULL)
+	if ((buf = malloc(len)) == NULL)
 	{
 		fprintf(stderr, "could not make malloc buf\n");
 		return -1;
 	}
 	
-	if(sysctl(mib, 6, buf, &len, NULL, 0) < 0)
+	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
 	{
 		fprintf(stderr, "could not sysctl data\n");
 		return -1;
@@ -469,34 +440,36 @@
 	free(buf);
 	return 0;
 }
-
-int dl_bpf_open_dev(char *dev, const size_t len)
+/*
+ * Poll for a free bpf device and open up the bpf device.
+ */
+int
+dl_bpf_open_dev(char *dev, const size_t len)
 {
 	int i=0, fd;
 
-	do
-	{
-		snprintf(dev, len, "/dev/bpf%d", i);
-		if((fd = open(dev, O_RDWR)) == -1)
-		{
-			if(errno == EBUSY)
-			{
-				continue;
-			}
-			else
-			{
-				fprintf(stderr, "could not open %s\n", dev);
-				return -1;
-			}
+	do {
+	    snprintf(dev, len, "/dev/bpf%d", 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;
+	    }
+	    else break;
 	}
-	while(++i < 32768);
+	while (++i < 32768);
 
 	return fd;
 }
 
-int dl_bpf_open(const char *ifname)
+/*
+ * Attempt to open a spare BPF device and return a file descriptor to that device.
+ */
+int
+dl_bpf_open(const char *ifname)
 {
 	struct ifreq ifreq;
 	char dev[16];
@@ -506,17 +479,15 @@
 	memset(&ifreq, 0, sizeof(ifreq));
 	strcpy(ifreq.ifr_name, ifname);
 
-	if((fd = dl_bpf_open_dev(dev, sizeof(dev))) == -1)
-	{
-		return -1;
-	}
+	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)
+	if (ioctl(fd, BIOCSETIF, &ifreq) == -1)
 	{
-		fprintf(stderr, "%s BIOCSETIF %s failed\n", dev, ifreq.ifr_name);
-		close(fd);
-		return -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