3 * Basic Encoding Rules (BER) file reading
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #ifdef HAVE_SYS_STAT_H
31 #include "file_wrappers.h"
36 #define BER_CLASS_UNI 0
37 #define BER_CLASS_APP 1
38 #define BER_CLASS_CON 2
40 #define BER_UNI_TAG_SEQ 16 /* SEQUENCE, SEQUENCE OF */
41 #define BER_UNI_TAG_SET 17 /* SET, SET OF */
43 static gboolean
ber_read_file(wtap
*wth
, FILE_T fh
, struct wtap_pkthdr
*phdr
,
44 Buffer
*buf
, int *err
, gchar
**err_info
)
49 if ((file_size
= wtap_file_size(wth
, err
)) == -1)
52 if (file_size
> WTAP_MAX_PACKET_SIZE
) {
54 * Probably a corrupt capture file; don't blow up trying
55 * to allocate space for an immensely-large packet.
57 *err
= WTAP_ERR_BAD_FILE
;
58 *err_info
= g_strdup_printf("ber: File has %" G_GINT64_MODIFIER
"d-byte packet, bigger than maximum of %u",
59 file_size
, WTAP_MAX_PACKET_SIZE
);
62 packet_size
= (int)file_size
;
64 phdr
->presence_flags
= 0; /* yes, we have no bananas^Wtime stamp */
66 phdr
->caplen
= packet_size
;
67 phdr
->len
= packet_size
;
72 return wtap_read_packet_bytes(fh
, buf
, packet_size
, err
, err_info
);
75 static gboolean
ber_read(wtap
*wth
, int *err
, gchar
**err_info
, gint64
*data_offset
)
81 offset
= file_tell(wth
->fh
);
83 /* there is only ever one packet */
87 *data_offset
= offset
;
89 return ber_read_file(wth
, wth
->fh
, &wth
->phdr
, wth
->frame_buffer
, err
, err_info
);
92 static gboolean
ber_seek_read(wtap
*wth
, gint64 seek_off
, struct wtap_pkthdr
*phdr _U_
,
93 Buffer
*buf
, int length _U_
, int *err
, gchar
**err_info
)
95 /* there is only one packet */
101 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
104 return ber_read_file(wth
, wth
->random_fh
, phdr
, buf
, err
, err_info
);
107 int ber_open(wtap
*wth
, int *err
, gchar
**err_info
)
109 #define BER_BYTES_TO_CHECK 8
110 guint8 bytes
[BER_BYTES_TO_CHECK
];
121 bytes_read
= file_read(&bytes
, BER_BYTES_TO_CHECK
, wth
->fh
);
122 if (bytes_read
!= BER_BYTES_TO_CHECK
) {
123 *err
= file_error(wth
->fh
, err_info
);
124 if (*err
!= 0 && *err
!= WTAP_ERR_SHORT_READ
)
129 ber_id
= bytes
[offset
++];
131 ber_class
= (ber_id
>>6) & 0x03;
132 ber_pc
= (ber_id
>>5) & 0x01;
133 ber_tag
= ber_id
& 0x1F;
135 /* it must be constructed and either a SET or a SEQUENCE */
136 /* or a CONTEXT less than 32 (arbitrary) */
137 /* XXX: do we also want to allow APPLICATION */
139 (((ber_class
== BER_CLASS_UNI
) && ((ber_tag
== BER_UNI_TAG_SET
) || (ber_tag
== BER_UNI_TAG_SEQ
))) ||
140 ((ber_class
== BER_CLASS_CON
) && (ber_tag
< 32)))))
143 /* now check the length */
144 oct
= bytes
[offset
++];
147 /* not indefinite length encoded */
150 /* length fits into a single byte */
153 nlb
= oct
& 0x7F; /* number of length bytes */
155 if((nlb
> 0) && (nlb
<= (BER_BYTES_TO_CHECK
- 2))) {
156 /* not indefinite length and we have read enough bytes to compute the length */
159 oct
= bytes
[offset
++];
160 len
= (len
<<8) + oct
;
165 len
+= (2 + nlb
); /* add back Tag and Length bytes */
166 file_size
= wtap_file_size(wth
, err
);
168 if(len
!= file_size
) {
169 return 0; /* not ASN.1 */
172 /* Indefinite length encoded - assume it is BER */
175 /* seek back to the start of the file */
176 if (file_seek(wth
->fh
, 0, SEEK_SET
, err
) == -1)
179 wth
->file_type_subtype
= WTAP_FILE_TYPE_SUBTYPE_BER
;
180 wth
->file_encap
= WTAP_ENCAP_BER
;
181 wth
->snapshot_length
= 0;
183 wth
->subtype_read
= ber_read
;
184 wth
->subtype_seek_read
= ber_seek_read
;
185 wth
->tsprecision
= WTAP_FILE_TSPREC_SEC
;