From: Ben Pfaff Date: Mon, 19 Jan 2009 18:53:37 +0000 (-0800) Subject: Implement pcap file reader/writer library and use it in ofp_packet_to_string(). X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2e32142f07a09b10a2fbd10fb481b6438ad6238a;p=openvswitch Implement pcap file reader/writer library and use it in ofp_packet_to_string(). --- diff --git a/lib/automake.mk b/lib/automake.mk index c50384d8..bb9751a1 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -44,6 +44,8 @@ lib_libopenflow_a_SOURCES = \ lib/ofpbuf.c \ lib/ofpbuf.h \ lib/packets.h \ + lib/pcap.c \ + lib/pcap.h \ lib/poll-loop.c \ lib/poll-loop.h \ lib/port-array.c \ diff --git a/lib/ofp-print.c b/lib/ofp-print.c index f49aba43..6f989eae 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -50,6 +50,7 @@ #include "openflow/openflow.h" #include "openflow/nicira-ext.h" #include "packets.h" +#include "pcap.h" #include "util.h" static void ofp_print_port_name(struct ds *string, uint16_t port); @@ -65,29 +66,10 @@ static void ofp_print_match(struct ds *, const struct ofp_match *, * * This starts and kills a tcpdump subprocess so it's quite expensive. */ char * -ofp_packet_to_string(const void *data, size_t len, size_t total_len) +ofp_packet_to_string(const void *data, size_t len, size_t total_len UNUSED) { - struct pcap_hdr { - uint32_t magic_number; /* magic number */ - uint16_t version_major; /* major version number */ - uint16_t version_minor; /* minor version number */ - int32_t thiszone; /* GMT to local correction */ - uint32_t sigfigs; /* accuracy of timestamps */ - uint32_t snaplen; /* max length of captured packets */ - uint32_t network; /* data link type */ - } PACKED; - - struct pcaprec_hdr { - uint32_t ts_sec; /* timestamp seconds */ - uint32_t ts_usec; /* timestamp microseconds */ - uint32_t incl_len; /* number of octets of packet saved in file */ - uint32_t orig_len; /* actual length of packet */ - } PACKED; - - struct pcap_hdr ph; - struct pcaprec_hdr prh; - struct ds ds = DS_EMPTY_INITIALIZER; + struct ofpbuf buf; char command[128]; FILE *pcap; @@ -95,31 +77,16 @@ ofp_packet_to_string(const void *data, size_t len, size_t total_len) int status; int c; + buf.data = (void *) data; + buf.size = len; + pcap = tmpfile(); if (!pcap) { ofp_error(errno, "tmpfile"); return xstrdup(""); } - - /* The pcap reader is responsible for figuring out endianness based on the - * magic number, so the lack of htonX calls here is intentional. */ - ph.magic_number = 0xa1b2c3d4; - ph.version_major = 2; - ph.version_minor = 4; - ph.thiszone = 0; - ph.sigfigs = 0; - ph.snaplen = 1518; - ph.network = 1; /* Ethernet */ - - prh.ts_sec = 0; - prh.ts_usec = 0; - prh.incl_len = len; - prh.orig_len = total_len; - - fwrite(&ph, 1, sizeof ph, pcap); - fwrite(&prh, 1, sizeof prh, pcap); - fwrite(data, 1, len, pcap); - + pcap_write_header(pcap); + pcap_write(pcap, &buf); fflush(pcap); if (ferror(pcap)) { ofp_error(errno, "error writing temporary file"); diff --git a/lib/pcap.c b/lib/pcap.c new file mode 100644 index 00000000..d923f17f --- /dev/null +++ b/lib/pcap.c @@ -0,0 +1,180 @@ +/* Copyright (c) 2009 The Board of Trustees of The Leland Stanford + * Junior University + * + * We are making the OpenFlow specification and associated documentation + * (Software) available for public use and benefit with the expectation + * that others will use, modify and enhance the Software and contribute + * those enhancements back to the community. However, since we would + * like to make the Software available for broadest use, with as few + * restrictions as possible permission is hereby granted, free of + * charge, to any person obtaining a copy of this Software to deal in + * the Software under the copyrights without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The name and trademarks of copyright holder(s) may NOT be used in + * advertising or publicity pertaining to the Software or any + * derivatives without specific, written prior permission. + */ + +#include +#include "pcap.h" +#include +#include +#include +#include +#include "compiler.h" +#include "ofpbuf.h" + +#define THIS_MODULE VLM_pcap +#include "vlog.h" + +struct pcap_hdr { + uint32_t magic_number; /* magic number */ + uint16_t version_major; /* major version number */ + uint16_t version_minor; /* minor version number */ + int32_t thiszone; /* GMT to local correction */ + uint32_t sigfigs; /* accuracy of timestamps */ + uint32_t snaplen; /* max length of captured packets */ + uint32_t network; /* data link type */ +} PACKED; + +struct pcaprec_hdr { + uint32_t ts_sec; /* timestamp seconds */ + uint32_t ts_usec; /* timestamp microseconds */ + uint32_t incl_len; /* number of octets of packet saved in file */ + uint32_t orig_len; /* actual length of packet */ +} PACKED; + +FILE * +pcap_open(const char *file_name, const char *mode) +{ + FILE *file; + + assert(!strcmp(mode, "rb") || !strcmp(mode, "wb")); + + file = fopen(file_name, mode); + if (file == NULL) { + VLOG_WARN("%s: failed to open pcap file for %s", + file_name, mode[0] == 'r' ? "reading" : "writing"); + return NULL; + } + + if (mode[0] == 'r') { + if (!pcap_read_header(file)) { + fclose(file); + return NULL; + } + } else { + pcap_write_header(file); + } + return file; +} + +int +pcap_read_header(FILE *file) +{ + struct pcap_hdr ph; + if (fread(&ph, sizeof ph, 1, file) != 1) { + int error = ferror(file) ? errno : EOF; + VLOG_WARN("failed to read pcap header: %s", + error > 0 ? strerror(error) : "end of file"); + return error; + } + if (ph.magic_number != 0xa1b2c3d4 && ph.magic_number != 0xd4c3b2a1) { + VLOG_WARN("bad magic 0x%08"PRIx32" reading pcap file " + "(expected 0xa1b2c3d4 or 0xd4c3b2a1)", ph.magic_number); + return EPROTO; + } + return 0; +} + +void +pcap_write_header(FILE *file) +{ + /* The pcap reader is responsible for figuring out endianness based on the + * magic number, so the lack of htonX calls here is intentional. */ + struct pcap_hdr ph; + ph.magic_number = 0xa1b2c3d4; + ph.version_major = 2; + ph.version_minor = 4; + ph.thiszone = 0; + ph.sigfigs = 0; + ph.snaplen = 1518; + ph.network = 1; /* Ethernet */ + fwrite(&ph, sizeof ph, 1, file); +} + +int +pcap_read(FILE *file, struct ofpbuf **bufp) +{ + struct pcaprec_hdr prh; + struct ofpbuf *buf; + void *data; + size_t len; + + *bufp = NULL; + + /* Read header. */ + if (fread(&prh, sizeof prh, 1, file) != 1) { + int error = ferror(file) ? errno : EOF; + VLOG_WARN("failed to read pcap record header: %s", + error > 0 ? strerror(error) : "end of file"); + return error; + } + + /* Calculate length. */ + len = prh.incl_len; + if (len > 0xffff) { + uint32_t swapped_len = (((len & 0xff000000) >> 24) | + ((len & 0x00ff0000) >> 8) | + ((len & 0x0000ff00) << 8) | + ((len & 0x000000ff) << 24)); + if (swapped_len > 0xffff) { + VLOG_WARN("bad packet length %"PRIu32" or %"PRIu32" " + "reading pcap file", + len, swapped_len); + return EPROTO; + } + len = swapped_len; + } + + /* Read packet. */ + buf = ofpbuf_new(len); + data = ofpbuf_put_uninit(buf, len); + if (fread(data, len, 1, file) != 1) { + int error = ferror(file) ? errno : EOF; + VLOG_WARN("failed to read pcap packet: %s", + error > 0 ? strerror(error) : "end of file"); + ofpbuf_delete(buf); + return error; + } + *bufp = buf; + return 0; +} + +void +pcap_write(FILE *file, struct ofpbuf *buf) +{ + struct pcaprec_hdr prh; + prh.ts_sec = 0; + prh.ts_usec = 0; + prh.incl_len = buf->size; + prh.orig_len = buf->size; + fwrite(&prh, sizeof prh, 1, file); + fwrite(buf->data, buf->size, 1, file); +} diff --git a/lib/pcap.h b/lib/pcap.h new file mode 100644 index 00000000..f72708f9 --- /dev/null +++ b/lib/pcap.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2009 The Board of Trustees of The Leland Stanford + * Junior University + * + * We are making the OpenFlow specification and associated documentation + * (Software) available for public use and benefit with the expectation + * that others will use, modify and enhance the Software and contribute + * those enhancements back to the community. However, since we would + * like to make the Software available for broadest use, with as few + * restrictions as possible permission is hereby granted, free of + * charge, to any person obtaining a copy of this Software to deal in + * the Software under the copyrights without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The name and trademarks of copyright holder(s) may NOT be used in + * advertising or publicity pertaining to the Software or any + * derivatives without specific, written prior permission. + */ + +#ifndef PCAP_H +#define PCAP_H 1 + +#include + +struct ofpbuf; + +FILE *pcap_open(const char *file_name, const char *mode); +int pcap_read_header(FILE *); +void pcap_write_header(FILE *); +int pcap_read(FILE *, struct ofpbuf **); +void pcap_write(FILE *, struct ofpbuf *); + +#endif /* dhcp.h */ diff --git a/lib/vlog-modules.def b/lib/vlog-modules.def index a78b04e4..14d97e6b 100644 --- a/lib/vlog-modules.def +++ b/lib/vlog-modules.def @@ -24,6 +24,7 @@ VLOG_MODULE(mac_learning) VLOG_MODULE(netdev) VLOG_MODULE(netlink) VLOG_MODULE(ofp_discover) +VLOG_MODULE(pcap) VLOG_MODULE(poll_loop) VLOG_MODULE(port_watcher) VLOG_MODULE(process)