From owner-p4-projects@FreeBSD.ORG Tue May 20 13:05:29 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id D28D9106566B; Tue, 20 May 2008 13:05:28 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 943801065676 for ; Tue, 20 May 2008 13:05:28 +0000 (UTC) (envelope-from rfrench@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 830BA8FC23 for ; Tue, 20 May 2008 13:05:28 +0000 (UTC) (envelope-from rfrench@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m4KD5SUv034440 for ; Tue, 20 May 2008 13:05:28 GMT (envelope-from rfrench@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m4KD5Shw034433 for perforce@freebsd.org; Tue, 20 May 2008 13:05:28 GMT (envelope-from rfrench@FreeBSD.org) Date: Tue, 20 May 2008 13:05:28 GMT Message-Id: <200805201305.m4KD5Shw034433@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to rfrench@FreeBSD.org using -f From: Ryan French To: Perforce Change Reviews Cc: Subject: PERFORCE change 141914 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 May 2008 13:05:29 -0000 http://perforce.freebsd.org/chv.cgi?CH=141914 Change 141914 by rfrench@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 -#include -#include -#include -#include #include #include #include #include -#include - #include #include #include - #include #include #include #include #include +#include + +#include +#include +#include +#include +#include #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 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;