From owner-p4-projects@FreeBSD.ORG Mon May 19 22:25:39 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id E0E521065688; Mon, 19 May 2008 22:25:38 +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 8A6501065684 for ; Mon, 19 May 2008 22:25:38 +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 801378FC16 for ; Mon, 19 May 2008 22:25:38 +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 m4JMPcXA025997 for ; Mon, 19 May 2008 22:25:38 GMT (envelope-from rfrench@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m4JMPc9Y025995 for perforce@freebsd.org; Mon, 19 May 2008 22:25:38 GMT (envelope-from rfrench@FreeBSD.org) Date: Mon, 19 May 2008 22:25:38 GMT Message-Id: <200805192225.m4JMPc9Y025995@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 141879 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: Mon, 19 May 2008 22:25:39 -0000 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 +#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[]) { - 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 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; +} +