3 * $Id: snoop.c,v 1.46 2002/04/30 08:48:27 guy Exp $
6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include "file_wrappers.h"
32 #ifdef HAVE_NETINET_IN_H
33 #include <netinet/in.h>
36 /* See RFC 1761 for a description of the "snoop" file format. */
38 /* Magic number in "snoop" files. */
39 static const char snoop_magic[] = {
40 's', 'n', 'o', 'o', 'p', '\0', '\0', '\0'
43 /* "snoop" file header (minus magic number). */
45 guint32 version; /* version number (should be 2) */
46 guint32 network; /* network type */
49 /* "snoop" record header. */
51 guint32 orig_len; /* actual length of packet */
52 guint32 incl_len; /* number of octets captured in file */
53 guint32 rec_len; /* length of record */
54 guint32 cum_drops; /* cumulative number of dropped packets */
55 guint32 ts_sec; /* timestamp seconds */
56 guint32 ts_usec; /* timestamp microseconds */
59 static gboolean snoop_read(wtap *wth, int *err, long *data_offset);
60 static gboolean snoop_seek_read(wtap *wth, long seek_off,
61 union wtap_pseudo_header *pseudo_header, u_char *pd, int length, int *err);
62 static gboolean snoop_read_atm_pseudoheader(FILE_T fh,
63 union wtap_pseudo_header *pseudo_header, int *err);
64 static gboolean snoop_read_rec_data(FILE_T fh, u_char *pd, int length,
66 static gboolean snoop_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
67 const union wtap_pseudo_header *pseudo_header, const u_char *pd, int *err);
72 * http://www.opengroup.org/onlinepubs/9638599/apdxf.htm
74 * for the "dlpi.h" header file specified by The Open Group, which lists
75 * the DL_ values for various protocols; Solaris 7 uses the same values.
79 * http://mrpink.lerc.nasa.gov/118x/support.html
81 * has links to modified versions of "tcpdump" and "libpcap" for SUNatm
82 * DLPI support; they suggest the 3.0 verson of SUNatm uses those
85 * It also has a link to "convert.c", which is a program to convert files
86 * from the format written by the "atmsnoop" program that comes with the
87 * SunATM package to regular "snoop" format, claims that "SunATM 2.1 claimed
88 * to be DL_FDDI (don't ask why). SunATM 3.0 claims to be DL_IPATM, which
91 * It also says that "ATM Mac header is 12 bytes long.", and seems to imply
92 * that in an "atmsnoop" file, the header contains 2 bytes (direction and
93 * VPI?), 2 bytes of VCI, 6 bytes of something, and 2 bytes of Ethernet
94 * type; if those 6 bytes are 2 bytes of DSAP, 2 bytes of LSAP, 1 byte
95 * of LLC control, and 3 bytes of SNAP OUI, that'd mean that an ATM
96 * pseudo-header in an "atmsnoop" file is probably 1 byte of direction,
97 * 1 byte of VPI, and 2 bytes of VCI.
99 * The aforementioned page also has a link to some capture files from
100 * "atmsnoop"; this version of "snoop.c" appears to be able to read them.
102 * Source to an "atmdump" package, which includes a modified version of
103 * "libpcap" to handle SunATM DLPI and an ATM driver for FreeBSD, and
104 * also includes "atmdump", which is a modified "tcpdump", says that an
105 * ATM packet handed up from the Sun driver for the Sun SBus ATM card on
106 * Solaris 2.5.1 has 1 byte of direction, 1 byte of VPI, 2 bytes of VCI,
107 * and then the ATM PDU, and suggests that the direction byte is 0x80 for
108 * "transmitted" (presumably meaning DTE->DCE) and presumably not 0x80 for
109 * "received" (presumably meaning DCE->DTE).
111 * In fact, the "direction" byte appears to have some other stuff, perhaps
112 * a traffic type, in the lower 7 bits, with the 8th bit indicating the
115 * I don't know what the encapsulation of any of the other types is, so I
116 * leave them all as WTAP_ENCAP_UNKNOWN. I also don't know whether "snoop"
117 * can handle any of them (it presumably can't handle ATM, otherwise Sun
118 * wouldn't have supplied "atmsnoop"; even if it can't, this may be useful
119 * reference information for anybody doing code to use DLPI to do raw packet
120 * captures on those network types.
124 * http://www.shomiti.com/support/TNCapFileFormat.htm
126 * for information on Shomiti's mutant flavor of snoop. For some unknown
127 * unknown reason, they decided not to just Go With The DLPI Flow, and
128 * instead used the types unspecified in RFC 1461 for their own nefarious
129 * purposes, such as distinguishing 10MB from 100MB from 1000MB Ethernet
130 * and distinguishing 4MB from 16MB Token Ring, and distinguishing both
131 * of them from the "Shomiti" versions of same.
133 int snoop_open(wtap *wth, int *err)
136 char magic[sizeof snoop_magic];
137 struct snoop_hdr hdr;
138 static const int snoop_encap[] = {
139 WTAP_ENCAP_ETHERNET, /* IEEE 802.3 */
140 WTAP_ENCAP_UNKNOWN, /* IEEE 802.4 Token Bus */
141 WTAP_ENCAP_TOKEN_RING,
142 WTAP_ENCAP_UNKNOWN, /* IEEE 802.6 Metro Net */
144 WTAP_ENCAP_UNKNOWN, /* HDLC */
145 WTAP_ENCAP_UNKNOWN, /* Character Synchronous, e.g. bisync */
146 WTAP_ENCAP_UNKNOWN, /* IBM Channel-to-Channel */
147 WTAP_ENCAP_FDDI_BITSWAPPED,
148 WTAP_ENCAP_UNKNOWN, /* Other */
149 WTAP_ENCAP_UNKNOWN, /* Frame Relay LAPF */
150 WTAP_ENCAP_UNKNOWN, /* Multi-protocol over Frame Relay */
151 WTAP_ENCAP_UNKNOWN, /* Character Async (e.g., SLIP and PPP?) */
152 WTAP_ENCAP_UNKNOWN, /* X.25 Classical IP */
153 WTAP_ENCAP_UNKNOWN, /* software loopback */
154 WTAP_ENCAP_UNKNOWN, /* not defined in "dlpi.h" */
155 WTAP_ENCAP_UNKNOWN, /* Fibre Channel */
156 WTAP_ENCAP_UNKNOWN, /* ATM */
157 WTAP_ENCAP_ATM_SNIFFER, /* ATM Classical IP */
158 WTAP_ENCAP_UNKNOWN, /* X.25 LAPB */
159 WTAP_ENCAP_UNKNOWN, /* ISDN */
160 WTAP_ENCAP_UNKNOWN, /* HIPPI */
161 WTAP_ENCAP_UNKNOWN, /* 100VG-AnyLAN Ethernet */
162 WTAP_ENCAP_UNKNOWN, /* 100VG-AnyLAN Token Ring */
163 WTAP_ENCAP_UNKNOWN, /* "ISO 8802/3 and Ethernet" */
164 WTAP_ENCAP_UNKNOWN, /* 100BaseT (but that's just Ethernet) */
166 #define NUM_SNOOP_ENCAPS (sizeof snoop_encap / sizeof snoop_encap[0])
167 static const int shomiti_encap[] = {
168 WTAP_ENCAP_ETHERNET, /* IEEE 802.3 */
169 WTAP_ENCAP_UNKNOWN, /* IEEE 802.4 Token Bus */
170 WTAP_ENCAP_TOKEN_RING,
171 WTAP_ENCAP_UNKNOWN, /* IEEE 802.6 Metro Net */
173 WTAP_ENCAP_UNKNOWN, /* HDLC */
174 WTAP_ENCAP_UNKNOWN, /* Character Synchronous, e.g. bisync */
175 WTAP_ENCAP_UNKNOWN, /* IBM Channel-to-Channel */
176 WTAP_ENCAP_FDDI_BITSWAPPED,
177 WTAP_ENCAP_UNKNOWN, /* Other */
178 WTAP_ENCAP_ETHERNET, /* Fast Ethernet */
179 WTAP_ENCAP_TOKEN_RING, /* 4MB 802.5 token ring */
180 WTAP_ENCAP_ETHERNET, /* Gigabit Ethernet */
181 WTAP_ENCAP_TOKEN_RING, /* "IEEE 802.5 Shomiti" */
182 WTAP_ENCAP_TOKEN_RING, /* "4MB IEEE 802.5 Shomiti" */
184 #define NUM_SHOMITI_ENCAPS (sizeof shomiti_encap / sizeof shomiti_encap[0])
187 /* Read in the string that should be at the start of a "snoop" file */
188 errno = WTAP_ERR_CANT_READ;
189 bytes_read = file_read(magic, 1, sizeof magic, wth->fh);
190 if (bytes_read != sizeof magic) {
191 *err = file_error(wth->fh);
196 wth->data_offset += sizeof magic;
198 if (memcmp(magic, snoop_magic, sizeof snoop_magic) != 0) {
202 /* Read the rest of the header. */
203 errno = WTAP_ERR_CANT_READ;
204 bytes_read = file_read(&hdr, 1, sizeof hdr, wth->fh);
205 if (bytes_read != sizeof hdr) {
206 *err = file_error(wth->fh);
211 wth->data_offset += sizeof hdr;
214 * Oh, this is lovely.
216 * I suppose Shomiti could give a bunch of lawyerly noise about
217 * how "well, RFC 1761 said they were unassigned, and that's
218 * the standard, not the DLPI header file, so it's perfectly OK
219 * for us to use them, blah blah blah", but it's still irritating
220 * as hell that they used the unassigned-in-RFC-1761 values for
221 * their own purposes - especially given that Sun also used
222 * one of them in atmsnoop.
224 * For now, we treat a version number of 2 as indicating that
225 * this is a Sun snoop file, and version numbers of 3, 4, and 5
226 * as indicating that this is a Shomiti file, even though
227 * their capture file format documentation claims that they
228 * use 2 if the data "was captured using an NDIS card", which
229 * presumably means "captured with an ordinary boring network
230 * card via NDIS" as opposed to "captured with our whizzo
231 * special capture hardware".
233 * This runs the risk that we may misinterpret the network
234 * type of Shomiti captures not done using their hardware.
235 * Currently, the only not-in-RFC-1761 type we interpret in
236 * Sun snoop files is 18, for atmsnoop, and that's not used
237 * by Shomiti, but if any of the types used by Shomiti are
238 * also used by Snoop or a variant thereof - e.g.:
240 * value snoop Shomiti
241 * 10 Frame Relay 100MB Ethernet
242 * 11 MP over Frame Relay 4MB 802.5
243 * 12 "Character Async" 1000MB Ethernet
244 * 13 X.25 Classical IP "IEEE 802.5 Shomiti"
245 * 14 "software loopback" "4MB IEEE 802.5 Shomiti"
247 * then we have a problem that may be resolvable only by checking
248 * how much padding there is in the first packet - if there're 3
249 * bytes or less, it's probably Sun snoop, which uses the padding
250 * only for padding, but if there's more, it's probably a Shomiti
251 * tool, which uses the padding for additional information.
253 hdr.version = ntohl(hdr.version);
254 hdr.network = ntohl(hdr.network);
255 switch (hdr.version) {
257 case 2: /* Solaris 2.x and later snoop, and Shomiti
258 Surveyor prior to 3.0 (or 3.x with NDIS card?) */
259 if (hdr.network >= NUM_SNOOP_ENCAPS
260 || snoop_encap[hdr.network] == WTAP_ENCAP_UNKNOWN) {
261 g_message("snoop: network type %u unknown or unsupported",
263 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
266 file_encap = snoop_encap[hdr.network];
269 case 3: /* Surveyor 3.0 and later, with Shomiti CMM2 hardware */
270 case 4: /* Surveyor 3.0 and later, with Shomiti GAM hardware */
271 case 5: /* Surveyor 3.0 and later, with Shomiti THG hardware */
272 if (hdr.network >= NUM_SHOMITI_ENCAPS
273 || shomiti_encap[hdr.network] == WTAP_ENCAP_UNKNOWN) {
274 g_message("snoop: Shomiti network type %u unknown or unsupported",
276 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
279 file_encap = shomiti_encap[hdr.network];
283 g_message("snoop: version %u unsupported", hdr.version);
284 *err = WTAP_ERR_UNSUPPORTED;
288 /* This is a snoop file */
289 wth->file_type = WTAP_FILE_SNOOP;
290 wth->subtype_read = snoop_read;
291 wth->subtype_seek_read = snoop_seek_read;
292 wth->file_encap = file_encap;
293 wth->snapshot_length = 0; /* not available in header */
297 /* Read the next packet */
298 static gboolean snoop_read(wtap *wth, int *err, long *data_offset)
304 struct snooprec_hdr hdr;
309 /* Read record header. */
310 errno = WTAP_ERR_CANT_READ;
311 bytes_read = file_read(&hdr, 1, sizeof hdr, wth->fh);
312 if (bytes_read != sizeof hdr) {
313 *err = file_error(wth->fh);
314 if (*err == 0 && bytes_read != 0) {
315 *err = WTAP_ERR_SHORT_READ;
319 wth->data_offset += sizeof hdr;
321 rec_size = ntohl(hdr.rec_len);
322 orig_size = ntohl(hdr.orig_len);
323 packet_size = ntohl(hdr.incl_len);
324 if (packet_size > WTAP_MAX_PACKET_SIZE) {
326 * Probably a corrupt capture file; don't blow up trying
327 * to allocate space for an immensely-large packet.
329 g_message("snoop: File has %u-byte packet, bigger than maximum of %u",
330 packet_size, WTAP_MAX_PACKET_SIZE);
331 *err = WTAP_ERR_BAD_RECORD;
335 *data_offset = wth->data_offset;
338 * If this is an ATM packet, the first four bytes are the
339 * direction of the packet (transmit/receive), the VPI, and
340 * the VCI; read them and generate the pseudo-header from
343 if (wth->file_encap == WTAP_ENCAP_ATM_SNIFFER) {
344 if (packet_size < 4) {
346 * Uh-oh, the packet isn't big enough to even
347 * have a pseudo-header.
349 g_message("snoop: atmsnoop file has a %u-byte packet, too small to have even an ATM pseudo-header\n",
351 *err = WTAP_ERR_BAD_RECORD;
354 if (!snoop_read_atm_pseudoheader(wth->fh, &wth->pseudo_header,
356 return FALSE; /* Read error */
359 * Don't count the pseudo-header as part of the packet.
364 wth->data_offset += 4;
367 buffer_assure_space(wth->frame_buffer, packet_size);
368 if (!snoop_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer),
370 return FALSE; /* Read error */
371 wth->data_offset += packet_size;
373 wth->phdr.ts.tv_sec = ntohl(hdr.ts_sec);
374 wth->phdr.ts.tv_usec = ntohl(hdr.ts_usec);
375 wth->phdr.caplen = packet_size;
376 wth->phdr.len = orig_size;
377 wth->phdr.pkt_encap = wth->file_encap;
380 * Skip over the padding (don't "fseek()", as the standard
381 * I/O library on some platforms discards buffered data if
382 * you do that, which means it does a lot more reads).
383 * There's probably not much padding (it's probably padded only
384 * to a 4-byte boundary), so we probably need only do one read.
386 padbytes = rec_size - (sizeof hdr + packet_size);
387 while (padbytes != 0) {
388 bytes_to_read = padbytes;
389 if ((unsigned)bytes_to_read > sizeof padbuf)
390 bytes_to_read = sizeof padbuf;
391 errno = WTAP_ERR_CANT_READ;
392 bytes_read = file_read(padbuf, 1, bytes_to_read, wth->fh);
393 if (bytes_read != bytes_to_read) {
394 *err = file_error(wth->fh);
396 *err = WTAP_ERR_SHORT_READ;
399 wth->data_offset += bytes_read;
400 padbytes -= bytes_read;
407 snoop_seek_read(wtap *wth, long seek_off,
408 union wtap_pseudo_header *pseudo_header, u_char *pd, int length, int *err)
410 if (file_seek(wth->random_fh, seek_off, SEEK_SET) == -1) {
411 *err = file_error(wth->random_fh);
415 if (wth->file_encap == WTAP_ENCAP_ATM_SNIFFER) {
416 if (!snoop_read_atm_pseudoheader(wth->random_fh, pseudo_header,
424 * Read the packet data.
426 return snoop_read_rec_data(wth->random_fh, pd, length, err);
430 snoop_read_atm_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
438 errno = WTAP_ERR_CANT_READ;
439 bytes_read = file_read(atm_phdr, 1, 4, fh);
440 if (bytes_read != 4) {
441 *err = file_error(fh);
443 *err = WTAP_ERR_SHORT_READ;
448 vci = pntohs(&atm_phdr[2]);
451 * The lower 4 bits of the first byte of the header indicate
452 * the type of traffic, as per the "atmioctl.h" header in
455 switch (atm_phdr[0] & 0x0F) {
457 case 0x01: /* LANE */
458 pseudo_header->atm.aal = AAL_5;
459 pseudo_header->atm.type = TRAF_LANE;
462 case 0x02: /* RFC 1483 LLC multiplexed traffic */
463 pseudo_header->atm.aal = AAL_5;
464 pseudo_header->atm.type = TRAF_LLCMX;
467 case 0x05: /* ILMI */
468 pseudo_header->atm.aal = AAL_5;
469 pseudo_header->atm.type = TRAF_ILMI;
472 case 0x06: /* Q.2931 */
473 pseudo_header->atm.aal = AAL_SIGNALLING;
474 pseudo_header->atm.type = TRAF_UNKNOWN;
477 case 0x03: /* MARS (RFC 2022) */
478 pseudo_header->atm.aal = AAL_5;
479 pseudo_header->atm.type = TRAF_ILMI;
482 case 0x04: /* IFMP (Ipsilon Flow Management Protocol; see RFC 1954) */
483 pseudo_header->atm.aal = AAL_5;
484 pseudo_header->atm.type = TRAF_UNKNOWN; /* XXX - TRAF_IPSILON? */
489 * Assume it's AAL5, unless it's VPI 0 and VCI 5, in which
490 * case assume it's AAL_SIGNALLING; we know nothing more
493 * XXX - is this necessary? Or are we guaranteed that
494 * all signalling traffic has a type of 0x06?
496 * XXX - is this guaranteed to be AAL5? Or, if the type is
497 * 0x00 ("raw"), might it be non-AAL5 traffic?
499 if (vpi == 0 && vci == 5)
500 pseudo_header->atm.aal = AAL_SIGNALLING;
502 pseudo_header->atm.aal = AAL_5;
503 pseudo_header->atm.type = TRAF_UNKNOWN;
506 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
508 pseudo_header->atm.vpi = vpi;
509 pseudo_header->atm.vci = vci;
510 pseudo_header->atm.channel = (atm_phdr[0] & 0x80) ? 1 : 0;
512 /* We don't have this information */
513 pseudo_header->atm.cells = 0;
514 pseudo_header->atm.aal5t_u2u = 0;
515 pseudo_header->atm.aal5t_len = 0;
516 pseudo_header->atm.aal5t_chksum = 0;
522 snoop_read_rec_data(FILE_T fh, u_char *pd, int length, int *err)
526 errno = WTAP_ERR_CANT_READ;
527 bytes_read = file_read(pd, 1, length, fh);
529 if (bytes_read != length) {
530 *err = file_error(fh);
532 *err = WTAP_ERR_SHORT_READ;
538 static const int wtap_encap[] = {
539 -1, /* WTAP_ENCAP_UNKNOWN -> unsupported */
540 0x04, /* WTAP_ENCAP_ETHERNET -> DL_ETHER */
541 0x02, /* WTAP_ENCAP_TOKEN_RING -> DL_TPR */
542 -1, /* WTAP_ENCAP_SLIP -> unsupported */
543 -1, /* WTAP_ENCAP_PPP -> unsupported */
544 0x08, /* WTAP_ENCAP_FDDI -> DL_FDDI */
545 0x08, /* WTAP_ENCAP_FDDI_BITSWAPPED -> DL_FDDI */
546 -1, /* WTAP_ENCAP_RAW_IP -> unsupported */
547 -1, /* WTAP_ENCAP_ARCNET -> unsupported */
548 -1, /* WTAP_ENCAP_ATM_RFC1483 -> unsupported */
549 -1, /* WTAP_ENCAP_LINUX_ATM_CLIP -> unsupported */
550 -1, /* WTAP_ENCAP_LAPB -> unsupported*/
551 -1, /* WTAP_ENCAP_ATM_SNIFFER -> unsupported */
552 0 /* WTAP_ENCAP_NULL -> DLT_NULL */
554 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
556 /* Returns 0 if we could write the specified encapsulation type,
557 an error indication otherwise. */
558 int snoop_dump_can_write_encap(int encap)
560 /* Per-packet encapsulations aren't supported. */
561 if (encap == WTAP_ENCAP_PER_PACKET)
562 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
564 if (encap < 0 || (unsigned)encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
565 return WTAP_ERR_UNSUPPORTED_ENCAP;
570 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
572 gboolean snoop_dump_open(wtap_dumper *wdh, int *err)
574 struct snoop_hdr file_hdr;
577 /* This is a snoop file */
578 wdh->subtype_write = snoop_dump;
579 wdh->subtype_close = NULL;
581 /* Write the file header. */
582 nwritten = fwrite(&snoop_magic, 1, sizeof snoop_magic, wdh->fh);
583 if (nwritten != sizeof snoop_magic) {
584 if (nwritten == 0 && ferror(wdh->fh))
587 *err = WTAP_ERR_SHORT_WRITE;
591 /* current "snoop" format is 2 */
592 file_hdr.version = htonl(2);
593 file_hdr.network = htonl(wtap_encap[wdh->encap]);
594 nwritten = fwrite(&file_hdr, 1, sizeof file_hdr, wdh->fh);
595 if (nwritten != sizeof file_hdr) {
596 if (nwritten == 0 && ferror(wdh->fh))
599 *err = WTAP_ERR_SHORT_WRITE;
606 /* Write a record for a packet to a dump file.
607 Returns TRUE on success, FALSE on failure. */
608 static gboolean snoop_dump(wtap_dumper *wdh,
609 const struct wtap_pkthdr *phdr,
610 const union wtap_pseudo_header *pseudo_header _U_,
611 const u_char *pd, int *err)
613 struct snooprec_hdr rec_hdr;
617 static char zeroes[4];
619 /* Record length = header length plus data length... */
620 reclen = sizeof rec_hdr + phdr->caplen;
622 /* ... plus enough bytes to pad it to a 4-byte boundary. */
623 padlen = ((reclen + 3) & ~3) - reclen;
626 rec_hdr.orig_len = htonl(phdr->len);
627 rec_hdr.incl_len = htonl(phdr->caplen);
628 rec_hdr.rec_len = htonl(reclen);
629 rec_hdr.cum_drops = 0;
630 rec_hdr.ts_sec = htonl(phdr->ts.tv_sec);
631 rec_hdr.ts_usec = htonl(phdr->ts.tv_usec);
632 nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, wdh->fh);
633 if (nwritten != sizeof rec_hdr) {
634 if (nwritten == 0 && ferror(wdh->fh))
637 *err = WTAP_ERR_SHORT_WRITE;
640 nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
641 if (nwritten != phdr->caplen) {
642 if (nwritten == 0 && ferror(wdh->fh))
645 *err = WTAP_ERR_SHORT_WRITE;
649 /* Now write the padding. */
650 nwritten = fwrite(zeroes, 1, padlen, wdh->fh);
651 if (nwritten != padlen) {
652 if (nwritten == 0 && ferror(wdh->fh))
655 *err = WTAP_ERR_SHORT_WRITE;