Date: Mon, 19 May 2008 22:25:38 GMT From: Ryan French <rfrench@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 141879 for review Message-ID: <200805192225.m4JMPc9Y025995@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=141879 Change 141879 by rfrench@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; +} +
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200805192225.m4JMPc9Y025995>