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__ */
41 #include <libdabba/pcap.h>
45 * \brief Write the PCAP file header on a file descriptor
46 * \param[in] fd PCAP file descriptor
47 * \param[in] linktype PCAP link type
48 * \param[in] thiszone Timezone where the PCAP is created
49 * \param[in] snaplen Maximum length of a captured packet
50 * \return 0 on success, -1 if PCAP file header could not be written
53 static int pcap_file_header_write(const int fd
, const int linktype
,
54 const int thiszone
, const int snaplen
)
56 struct pcap_file_header hdr
;
60 memset(&hdr
, 0, sizeof(hdr
));
62 hdr
.magic
= TCPDUMP_MAGIC
;
63 hdr
.version_major
= PCAP_VERSION_MAJOR
;
64 hdr
.version_minor
= PCAP_VERSION_MINOR
;
65 hdr
.thiszone
= thiszone
;
66 hdr
.snaplen
= snaplen
;
68 hdr
.linktype
= linktype
;
70 if (write(fd
, (char *)&hdr
, sizeof(hdr
)) != sizeof(hdr
)) {
78 * \brief Get PCAP link type from NIC ARP type
79 * \param[in] arp_type ARP type value
80 * \param[out] pcap_link_type Pointer to the PCAP link type
81 * \return 0 on success, \c EINVAL when the ARP type is not supported
84 int pcap_link_type_get(int arp_type
, enum pcap_linktype
*pcap_link_type
)
88 assert(pcap_link_type
);
93 *pcap_link_type
= LINKTYPE_EN10MB
;
104 * \brief Validate PCAP file header
105 * Every PCAP file has a file header which contains:
106 * - the PCAP magic (\c 0xa1b2c3d4)
107 * - the PCAP version major/minor
108 * - the PCAP linktype
110 * - the maximum packet length
111 * \param[in] fd PCAP file descriptor
112 * \return 0 if the PCAP file header is not valid \n
114 * If PCAP file header is invalid, \c errno is set to \n
115 * \c EINVAL if PCAP file descriptor or file header is invalid \n
116 * \c EIO if PCAP file header could not be read
119 int pcap_is_valid(const int fd
)
121 struct pcap_file_header hdr
;
128 if (read(fd
, (char *)&hdr
, sizeof(hdr
)) != sizeof(hdr
)) {
133 if (hdr
.magic
!= TCPDUMP_MAGIC
134 || hdr
.version_major
!= PCAP_VERSION_MAJOR
135 || hdr
.version_minor
!= PCAP_VERSION_MINOR
136 || !is_linktype_valid(hdr
.linktype
)) {
145 * \brief Create a PCAP file
146 * \param[in] pcap_path PCAP file path
147 * \param[in] linktype PCAP link type
148 * \return PCAP file descriptor on success, -1 on failure
149 * \note It creates a PCAP file with default permissions
150 * \note A created PCAP will have by default a snapshot length of 65535 bytes.
153 int pcap_create(const char *const pcap_path
, const enum pcap_linktype linktype
)
159 if ((fd
= creat(pcap_path
, DEFFILEMODE
)) < 0) {
163 /* TODO make it configurable instead of using default values */
164 if (pcap_file_header_write(fd
, linktype
, 0, PCAP_DEFAULT_SNAPSHOT_LEN
)) {
165 /* When the PCAP header cannot be written the file
166 * must be closed and then deleted
168 pcap_destroy(fd
, pcap_path
);
176 * \brief Destroy a PCAP file
177 * \param[in] fd PCAP file descriptor
178 * \param[in] pcap_path PCAP file path
181 void pcap_destroy(const int fd
, const char *const pcap_path
)
191 * \brief Open a PCAP file
192 * \param[in] pcap_path PCAP file path
193 * \param[in] flags flags for \c open(2)
194 * \return PCAP file descriptor on success, -1 on failure
195 * \note The flags given as parameter are directly given to \c open(2)
198 int pcap_open(const char *const pcap_path
, int flags
)
205 /* Deactivate append to be able to check pcap validity */
206 if ((flags
& O_APPEND
) == O_APPEND
) {
211 if ((fd
= open(pcap_path
, flags
)) < 0) {
215 if (pcap_is_valid(fd
) == 0) {
222 if (lseek(fd
, 0, SEEK_END
) < 0) {
232 * \brief Close a PCAP file
233 * \param[in] fd PCAP file descriptor
234 * \return same error values as \c close(2)
237 int pcap_close(const int fd
)
243 * \brief Write the packet payload on a file descriptor
244 * \param[in] fd PCAP file descriptor
245 * \param[in] pkt Pointer to the packet to write
246 * \param[in] pkt_len Valid length of the packet
247 * \param[in] pkt_snaplen Total length of the packet
248 * \param[in] tv_sec Seconds after Epoch
249 * \param[in] tv_usec Microseconds after Epoch
250 * \return Length of written packet on success,
251 * -1 if either the packet header or packet payload could not be written
254 ssize_t
pcap_write(const int fd
, const uint8_t * const pkt
,
255 const size_t pkt_len
, const size_t pkt_snaplen
,
256 const uint64_t tv_sec
, const uint64_t tv_usec
)
258 struct pcap_sf_pkthdr sf_hdr
;
265 memset(&sf_hdr
, 0, sizeof(sf_hdr
));
267 sf_hdr
.ts
.tv_sec
= tv_sec
;
268 sf_hdr
.ts
.tv_usec
= tv_usec
;
269 sf_hdr
.caplen
= pkt_snaplen
;
270 sf_hdr
.len
= pkt_len
;
272 if ((written
= write(fd
, &sf_hdr
, sizeof(sf_hdr
))) != sizeof(sf_hdr
)) {
276 if ((written
= write(fd
, pkt
, sf_hdr
.len
)) != sf_hdr
.len
) {