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