ccndumppcap.c

Go to the documentation of this file.
00001 /**
00002  * @file ccndumppcap.c
00003  * Reads in a one or more ccnbs from stdin (e.g. as dumped
00004  * by ccndump), and writes them to a pcap file. Uses the splitting
00005  * code from ccn_splitccnb.
00006  *
00007  * A CCNx command-line utility.
00008  *
00009  * Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
00010  *
00011  * This work is free software; you can redistribute it and/or modify it under
00012  * the terms of the GNU General Public License version 2 as published by the
00013  * Free Software Foundation.
00014  * This work is distributed in the hope that it will be useful, but WITHOUT ANY
00015  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00016  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00017  * for more details. You should have received a copy of the GNU General Public
00018  * License along with this program; if not, write to the
00019  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020  * Boston, MA 02110-1301, USA.
00021  */
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <sys/mman.h>
00025 #include <sys/socket.h>
00026 #include <sys/time.h>
00027 #include <fcntl.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <stdint.h>
00032 #include <arpa/inet.h>
00033 
00034 #include <pcap.h>
00035 #include <ccn/ccn.h>
00036 #include <ccn/ccnd.h>
00037 
00038 #define LLC_LENGTH 4
00039 #define IP_OFFSET LLC_LENGTH
00040 #define IP_ADDR_LENGTH 4
00041 #define IP_HDR_LENGTH 20
00042 #define IP_LENGTH_OFFSET IP_OFFSET + 2
00043 #define IP_CHKSUM_OFFSET IP_OFFSET + 10
00044 #define IP_SRC_ADDR_OFFSET IP_CHKSUM_OFFSET + 2
00045 #define IP_DEST_ADDR_OFFSET IP_CHKSUM_OFFSET + IP_ADDR_LENGTH
00046 
00047 #define UDP_OFFSET IP_OFFSET + IP_HDR_LENGTH
00048 #define UDP_HDR_LENGTH 8
00049 #define UDP_LENGTH_OFFSET UDP_OFFSET + 4
00050 #define UDP_CHKSUM_OFFSET UDP_OFFSET + 6
00051 #define DATA_OFFSET UDP_OFFSET + UDP_HDR_LENGTH
00052 #define MAX_PACKET 65536
00053 #define DEFAULT_SRC_PORT 55555
00054 #define DEFAULT_DEST_PORT CCN_DEFAULT_UNICAST_PORT_NUMBER
00055 
00056 static void
00057 usage(const char *progname)
00058 {
00059     fprintf(stderr,
00060             "%s <infile> [<infile> ...]\n"
00061             "   Reads ccnb blocks from one or more files, and writes them in pcap format\n"
00062             "   to stdout.\n"
00063             "   ccnb blocks can be generated by any of the other utility programs.\n",
00064             progname);
00065     exit(1);
00066 }
00067 
00068 static int
00069 dump_udp_packet(pcap_dumper_t *dump_file, 
00070                 unsigned char *ip_src_addr, /*  ipv4, localhost if NULL */
00071                 unsigned char *ip_dest_addr, /* localhost if NULL */
00072                 unsigned short udp_src_port, /* 55555 if 0 */
00073                 unsigned short udp_dest_port,
00074                 const unsigned char *data, size_t data_len,  /* data; could be whole ccnb, could
00075                                                            just be contents */
00076                 struct timeval *ts) { /* timing info */
00077 
00078     unsigned char pktbuf[MAX_PACKET];
00079     uint32_t llc_val = PF_INET; // in host byte order
00080 
00081     uint16_t nsrc_port = htons((0 == udp_src_port) ? DEFAULT_SRC_PORT : udp_src_port);
00082     uint16_t ndest_port = htons((0 == udp_dest_port) ? DEFAULT_DEST_PORT : udp_dest_port);
00083     uint16_t nudp_len = htons(data_len + UDP_HDR_LENGTH);
00084     uint16_t nip_len = htons(data_len + UDP_HDR_LENGTH + IP_HDR_LENGTH);
00085 
00086     size_t frame_len = data_len + UDP_HDR_LENGTH + IP_HDR_LENGTH + LLC_LENGTH;
00087     struct pcap_pkthdr pcap_header;
00088     
00089     const unsigned char ipHdr[] = {
00090         // IP header, localhost to localhost
00091         0x45, // IPv4, 20 byte header
00092         0x00, // diff serv field
00093         0x00, 0x00, // length -- UDP length + 20
00094         0x1a, 0x62, // identification
00095         0x00, // flags
00096         0x00, // fragment offset
00097         0x40, // TTL (64)
00098         0x11, // proto (UDP=11)
00099         0x00, 0x00, // ip checksum (calculate, or leave 0 for validation disabled)
00100         0x7f, 0x00, 0x00, 0x01, // source, localhost if not overwritten
00101         0x7f, 0x00, 0x00, 0x01 // dest, localhost if not overwritten
00102     };
00103 
00104     unsigned char udpHdr[UDP_HDR_LENGTH];
00105     memset(udpHdr, 0, UDP_HDR_LENGTH);
00106     
00107     memcpy(&pktbuf[0], (unsigned char *)&llc_val, LLC_LENGTH);
00108     memcpy(&pktbuf[IP_OFFSET], ipHdr, IP_HDR_LENGTH);
00109     memcpy(&pktbuf[IP_LENGTH_OFFSET], &nip_len, 2);
00110     if (NULL != ip_src_addr) {
00111         memcpy(&pktbuf[IP_SRC_ADDR_OFFSET], ip_src_addr, IP_ADDR_LENGTH);
00112     }
00113     if (NULL != ip_dest_addr) {
00114         memcpy(&pktbuf[IP_DEST_ADDR_OFFSET], ip_dest_addr, IP_ADDR_LENGTH);
00115     }
00116 
00117     memcpy(&pktbuf[UDP_OFFSET], &nsrc_port, sizeof(unsigned short));
00118     memcpy(&pktbuf[UDP_OFFSET + sizeof(unsigned short)], &ndest_port, sizeof(unsigned short));
00119     memcpy(&pktbuf[UDP_LENGTH_OFFSET], &nudp_len, sizeof(unsigned short));
00120 
00121     memcpy(&pktbuf[DATA_OFFSET], data, data_len);
00122 
00123     pcap_header.len = pcap_header.caplen = frame_len;
00124     if (NULL != ts) {
00125         pcap_header.ts.tv_sec = ts->tv_sec;
00126         pcap_header.ts.tv_usec = ts->tv_usec;
00127     }
00128 
00129     pcap_dump((unsigned char *)dump_file, &pcap_header, &pktbuf[0]);
00130 
00131     if (0 != pcap_dump_flush(dump_file)) {
00132         fprintf(stderr, "Error flushing pcap dump...\n");
00133         return -1;
00134     }
00135     return 0;
00136 }
00137 
00138 static int
00139 process_test(pcap_dumper_t *pcap_out, int content_only,
00140              unsigned char *ip_src_addr, /*  ipv4, localhost if NULL */
00141              unsigned char *ip_dest_addr, /* localhost if NULL */
00142              unsigned short udp_src_port, /* 55555 if 0 */
00143              unsigned short udp_dest_port,
00144              unsigned char *data, size_t n)
00145 {
00146     struct ccn_skeleton_decoder skel_decoder = {0};
00147     struct ccn_skeleton_decoder *d = &skel_decoder;
00148     struct ccn_parsed_ContentObject content;
00149     struct ccn_indexbuf *comps = ccn_indexbuf_create();
00150     const unsigned char * content_value;
00151     size_t content_length;
00152     int res = 0;
00153     size_t s;
00154 
00155 retry:
00156     s = ccn_skeleton_decode(d, data, n);
00157     if (d->state < 0) {
00158         res = 1;
00159         fprintf(stderr, "error state %d after %d of %d chars\n",
00160                 (int)d->state, (int)s, (int)n);
00161     } else if (s == 0) {
00162         fprintf(stderr, "nothing to do\n");
00163     } else {
00164         if (s < n) {
00165             if (!content_only) {
00166                 if (dump_udp_packet(pcap_out, ip_src_addr, ip_dest_addr, 
00167                                     udp_src_port, udp_dest_port, data, s, NULL) != 0) {
00168                     res = 2;
00169                 }
00170             } else {
00171                 if (ccn_parse_ContentObject(data, s, &content, comps) != 0) {
00172                     fprintf(stderr, "unable to parse content object\n");
00173                     res = 1;
00174                 } else if (ccn_content_get_value(data, s, &content, &content_value, &content_length) != 0) {
00175                     fprintf(stderr, "unable to retrieve content value\n");
00176                     res = 1;
00177                 } else if (dump_udp_packet(pcap_out, ip_src_addr, ip_dest_addr, 
00178                                            udp_src_port, udp_dest_port, 
00179                                            content_value, content_length, NULL) != 0) {
00180                     res = 2;
00181                 }
00182             }
00183             /* fprintf(stderr, "resuming at index %d\n", (int)d->index); */
00184             data += s;
00185             n -= s;
00186             if (res != 0) {
00187                 fprintf(stderr, "Error dumping content.\n");
00188                 return res;
00189             }
00190             goto retry;
00191         }
00192         fprintf(stderr, "\n");
00193     }
00194     if (!CCN_FINAL_DSTATE(d->state)) {
00195         res = 1;
00196         fprintf(stderr, "incomplete state %d after %d of %d chars\n",
00197                 (int)d->state, (int)s, (int)n);
00198     } else {
00199         if (!content_only) {
00200             if (dump_udp_packet(pcap_out, ip_src_addr, ip_dest_addr, 
00201                                 udp_src_port, udp_dest_port, data, s, NULL) != 0) {
00202                 res = 2;
00203             }
00204         } else {
00205             if (ccn_parse_ContentObject(data, s, &content, comps) != 0) {
00206                 fprintf(stderr, "unable to parse content object\n");
00207                 res = 1;
00208             } else if (ccn_content_get_value(data, s, &content, &content_value, &content_length) != 0) {
00209                 fprintf(stderr, "unable to retrieve content value\n");
00210                 res = 1;
00211             } else if (dump_udp_packet(pcap_out, ip_src_addr, ip_dest_addr, 
00212                                        udp_src_port, udp_dest_port, content_value, content_length, NULL) != 0) {
00213                 res = 2;
00214             }
00215         }
00216 
00217         res = 1;
00218     }
00219     return(res);
00220 }
00221 
00222 static int
00223 process_fd(pcap_dumper_t *pcap_out, int fd, int content_only,
00224            unsigned char *ip_src_addr, /*  ipv4, localhost if NULL */
00225            unsigned char *ip_dest_addr, /* localhost if NULL */
00226            unsigned short udp_src_port, /* 55555 if 0 */
00227            unsigned short udp_dest_port
00228     )
00229 {
00230     unsigned char *buf;
00231     ssize_t len;
00232     struct stat s;
00233     int res = 0;
00234 
00235     res = fstat(fd, &s);
00236     len = s.st_size;
00237     buf = (unsigned char *)mmap((void *)NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
00238     if (buf == (void *)-1) return (1);
00239     fprintf(stderr, " <!-- input is %6lu bytes -->\n", (unsigned long)len);
00240     res |= process_test(pcap_out, content_only,
00241                         ip_src_addr, ip_dest_addr, udp_src_port, udp_dest_port,
00242                         buf, len);
00243     munmap((void *)buf, len);
00244     return(res);
00245 }
00246 
00247 int
00248 main(int argc, char **argv)
00249 {
00250     pcap_t *pcap = NULL;
00251     pcap_dumper_t *pcap_out = NULL;
00252     int fd;
00253     int i;
00254     int res = 0;
00255     
00256     if (argc < 2) {
00257         usage(argv[0]);
00258     }
00259 
00260     pcap = pcap_open_dead(DLT_NULL, MAX_PACKET);
00261     if (NULL == pcap) {
00262         fprintf(stderr, "Cannot open pcap descriptor!\n");
00263         exit(-1);
00264     }
00265 
00266     pcap_out = pcap_dump_open(pcap, "-");
00267     if (NULL == pcap_out) {
00268         fprintf(stderr, "Cannot open output stdout!\n");
00269         usage(argv[0]);
00270     }
00271 
00272     for (i = 1; argv[i] != 0; i++) {
00273         fprintf(stderr, "<!-- Processing %s -->\n", argv[i]);
00274 
00275         fd = open(argv[i], O_RDONLY);
00276         if (-1 == fd) {
00277             perror(argv[i]);
00278             return(1);
00279         }
00280 
00281         /* DKS -- eventually take IP addresses and ports from command line,
00282            as well as whether to dump only the ccn content. */
00283         res |= process_fd(pcap_out, fd, 0, NULL, NULL, 0, 0);
00284     }
00285 
00286     pcap_dump_close(pcap_out);
00287     pcap_close(pcap);
00288     return res;
00289 }

Generated on Thu Feb 16 00:43:59 2012 for Content-Centric Networking in C by  doxygen 1.5.6