3 * \author written by Emmanuel Roullit emmanuel.roullit@gmail.com (c) 2011
7 /* __LICENSE_HEADER_BEGIN__ */
10 * Copyright (C) 2011 Emmanuel Roullit <emmanuel.roullit@gmail.com>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or (at
15 * your option) any later version.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
28 /* __LICENSE_HEADER_END__ */
42 #include <libdabba/pcap.h>
46 * \brief Write the PCAP file header on a file descriptor
47 * \param[in] fd PCAP file descriptor
48 * \param[in] linktype PCAP link type
49 * \param[in] thiszone Timezone where the PCAP is created
50 * \param[in] snaplen Maximum length of a captured packet
51 * \return 0 on success, -1 if PCAP file header could not be written
55 pcap_file_header_write(const int fd
, const int linktype
,
56 const int thiszone
, const int snaplen
)
58 struct pcap_file_header hdr
;
62 memset(&hdr
, 0, sizeof(hdr
));
64 hdr
.magic
= TCPDUMP_MAGIC
;
65 hdr
.version_major
= PCAP_VERSION_MAJOR
;
66 hdr
.version_minor
= PCAP_VERSION_MINOR
;
67 hdr
.thiszone
= thiszone
;
68 hdr
.snaplen
= snaplen
;
70 hdr
.linktype
= linktype
;
72 if (write(fd
, (char *)&hdr
, sizeof(hdr
)) != sizeof(hdr
)) {
80 * \brief Get PCAP link type from NIC ARP type
81 * \param[in] arp_type ARP type value
82 * \param[out] pcap_link_type Pointer to the PCAP link type
83 * \return 0 on success, \c EINVAL when the ARP type is not supported
86 int pcap_link_type_get(int arp_type
, enum pcap_linktype
*pcap_link_type
)
90 assert(pcap_link_type
);
95 *pcap_link_type
= LINKTYPE_EN10MB
;
107 * \brief Tells if the input linktype is valid
108 * \param[in] linktype Linktype to validate
109 * \return 1 if the linktype is valid, 0 if invalid
112 static int pcap_linktype_is_valid(const uint32_t linktype
)
114 return (linktype
== LINKTYPE_EN10MB
);
119 * \brief Validate PCAP file header
120 * Every PCAP file has a file header which contains:
121 * - the PCAP magic (\c 0xa1b2c3d4)
122 * - the PCAP version major/minor
123 * - the PCAP linktype
125 * - the maximum packet length
126 * \param[in] fd PCAP file descriptor
127 * \return 0 if the PCAP file header is not valid \n
129 * If PCAP file header is invalid, \c errno is set to \n
130 * \c EINVAL if PCAP file descriptor or file header is invalid \n
131 * \c EIO if PCAP file header could not be read
134 static int pcap_is_valid(const int fd
)
136 struct pcap_file_header hdr
;
143 if (read(fd
, (char *)&hdr
, sizeof(hdr
)) != sizeof(hdr
)) {
148 /* PCAP might have been created on a system with another endianness */
149 if (hdr
.magic
!= TCPDUMP_MAGIC
) {
150 hdr
.magic
= bswap_32(hdr
.magic
);
151 hdr
.linktype
= bswap_32(hdr
.linktype
);
152 hdr
.version_major
= bswap_16(hdr
.version_major
);
153 hdr
.version_minor
= bswap_16(hdr
.version_minor
);
156 if (hdr
.magic
!= TCPDUMP_MAGIC
157 || hdr
.version_major
!= PCAP_VERSION_MAJOR
158 || hdr
.version_minor
!= PCAP_VERSION_MINOR
159 || !pcap_linktype_is_valid(hdr
.linktype
)) {
168 * \brief Create a PCAP file
169 * \param[in] pcap_path PCAP file path
170 * \param[in] linktype PCAP link type
171 * \return PCAP file descriptor on success, -1 on failure
172 * \note It creates a PCAP file with default permissions
173 * \note A created PCAP will have by default a snapshot length of 65535 bytes.
176 int pcap_create(const char *const pcap_path
, const enum pcap_linktype linktype
)
182 if ((fd
= creat(pcap_path
, DEFFILEMODE
)) < 0) {
186 /* TODO make it configurable instead of using default values */
187 if (pcap_file_header_write(fd
, linktype
, 0, PCAP_DEFAULT_SNAPSHOT_LEN
)) {
188 /* When the PCAP header cannot be written the file
189 * must be closed and then deleted
191 pcap_destroy(fd
, pcap_path
);
199 * \brief Destroy a PCAP file
200 * \param[in] fd PCAP file descriptor
201 * \param[in] pcap_path PCAP file path
204 void pcap_destroy(const int fd
, const char *const pcap_path
)
214 * \brief Open a PCAP file
215 * \param[in] pcap_path PCAP file path
216 * \param[in] flags flags for \c open(2)
217 * \return PCAP file descriptor on success, -1 on failure
218 * \note The flags given as parameter are directly given to \c open(2)
221 int pcap_open(const char *const pcap_path
, int flags
)
228 /* Deactivate append to be able to check pcap validity */
229 if ((flags
& O_APPEND
) == O_APPEND
) {
234 if ((fd
= open(pcap_path
, flags
)) < 0) {
238 if (pcap_is_valid(fd
) == 0) {
245 if (lseek(fd
, 0, SEEK_END
) < 0) {
255 * \brief Close a PCAP file
256 * \param[in] fd PCAP file descriptor
257 * \return same error values as \c close(2)
260 int pcap_close(const int fd
)
266 * \brief Write the packet payload on a file descriptor
267 * \param[in] fd PCAP file descriptor
268 * \param[in] pkt Pointer to the packet to write
269 * \param[in] pkt_len Valid length of the packet
270 * \param[in] pkt_snaplen Total length of the packet
271 * \param[in] tv_sec Seconds after Epoch
272 * \param[in] tv_usec Microseconds after Epoch
273 * \return Length of written packet on success,
274 * -1 if either the packet header or packet payload could not be written
278 pcap_write(const int fd
, const uint8_t * const pkt
,
279 const size_t pkt_len
, const size_t pkt_snaplen
,
280 const uint64_t tv_sec
, const uint64_t tv_usec
)
282 struct pcap_sf_pkthdr sf_hdr
;
289 memset(&sf_hdr
, 0, sizeof(sf_hdr
));
291 sf_hdr
.ts
.tv_sec
= tv_sec
;
292 sf_hdr
.ts
.tv_usec
= tv_usec
;
293 sf_hdr
.caplen
= pkt_snaplen
;
294 sf_hdr
.len
= pkt_len
;
296 written
= write(fd
, &sf_hdr
, sizeof(sf_hdr
));
298 if (written
!= sizeof(sf_hdr
)) {
302 written
= write(fd
, pkt
, sf_hdr
.caplen
);
304 if (written
!= (ssize_t
) sf_hdr
.caplen
) {