00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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,
00071 unsigned char *ip_dest_addr,
00072 unsigned short udp_src_port,
00073 unsigned short udp_dest_port,
00074 const unsigned char *data, size_t data_len,
00075
00076 struct timeval *ts) {
00077
00078 unsigned char pktbuf[MAX_PACKET];
00079 uint32_t llc_val = PF_INET;
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
00091 0x45,
00092 0x00,
00093 0x00, 0x00,
00094 0x1a, 0x62,
00095 0x00,
00096 0x00,
00097 0x40,
00098 0x11,
00099 0x00, 0x00,
00100 0x7f, 0x00, 0x00, 0x01,
00101 0x7f, 0x00, 0x00, 0x01
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,
00141 unsigned char *ip_dest_addr,
00142 unsigned short udp_src_port,
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
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,
00225 unsigned char *ip_dest_addr,
00226 unsigned short udp_src_port,
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
00282
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 }