Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / asn1 / z3950 / packet-z3950-template.c
blob2dceb7020b02d9a595248d6ea8c313ee97c6e157
1 /* packet-z3950.c
2 * Routines for dissection of the NISO Z39.50 Information Retrieval protocol
3 * Also contains a dissector for the MARC Machine Readable Cataloging file
4 * format. The general format is specified by ISO 2709 and the specific
5 * instance is MARC21.
7 * Copyright 2018, Craig Jackson <cejackson51@gmail.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
15 * References:
16 * ISO 2709: https://www.iso.org/standard/41319.html
17 * MARC21: https://www.loc.gov/marc/bibliographic/
18 * Z39.50 Maintenance Agency: https://www.loc.gov/z3950/agency/
19 * Z39.50 2003 standard: https://www.loc.gov/z3950/agency/Z39-50-2003.pdf
20 * Z39.50 1995 ASN.1: https://www.loc.gov/z3950/agency/asn1.html
21 * Registered Z39.50 Object Identifiers:
22 * https://www.loc.gov/z3950/agency/defns/oids.html
23 * Bib-1 Attribute Set: https://www.loc.gov/z3950/agency/defns/bib1.html
24 * Bib-1 Diagnostics: https://www.loc.gov/z3950/agency/defns/bib1diag.html
25 * RFC for Z39.50 over TCP/IP: https://tools.ietf.org/html/rfc1729
29 #include "config.h"
31 #include <epan/packet.h>
32 #include <epan/conversation.h>
33 #include <epan/exceptions.h>
34 #include <epan/expert.h>
35 #include <epan/oids.h>
36 #include <epan/proto_data.h>
37 #include <wsutil/str_util.h>
40 #include <string.h>
42 #include "packet-ber.h"
43 #include "packet-tcp.h"
45 typedef struct z3950_atinfo_t {
46 int atsetidx;
47 int attype;
48 } z3950_atinfo_t;
50 typedef struct z3950_diaginfo_t {
51 int diagsetidx;
52 int diagcondition;
53 } z3950_diaginfo_t;
55 #define PNAME "Z39.50 Protocol"
56 #define PSNAME "Z39.50"
57 #define PFNAME "z3950"
58 #define Z3950_PORT 210 /* UDP port */
60 /* Known attribute set ids */
61 #define Z3950_ATSET_BIB1_OID "1.2.840.10003.3.1"
63 /* Known diagnostic set ids */
64 #define Z3950_DIAGSET_BIB1_OID "1.2.840.10003.4.1"
66 /* Known record syntax ids */
67 #define Z3950_RECORDSYNTAX_MARC21_OID "1.2.840.10003.5.10"
69 /* Indexes of known attribute set ids */
70 #define Z3950_ATSET_UNKNOWN 0
71 #define Z3950_ATSET_BIB1 1
73 /* bib-1 Attribute Types */
74 #define Z3950_BIB1_AT_USE 1
75 #define Z3950_BIB1_AT_RELATION 2
76 #define Z3950_BIB1_AT_POSITION 3
77 #define Z3950_BIB1_AT_STRUCTURE 4
78 #define Z3950_BIB1_AT_TRUNCATION 5
79 #define Z3950_BIB1_AT_COMPLETENESS 6
81 /* Indexes of known diagnostic set ids */
82 #define Z3950_DIAGSET_UNKNOWN 0
83 #define Z3950_DIAGSET_BIB1 1
85 /* Per-packet data keys */
86 #define Z3950_ATINFO_KEY 1
87 #define Z3950_DIAGSET_KEY 2
89 /* MARC defines */
90 #define MARC_SUBFIELD_INDICATOR '\x1f'
91 #define MARC_LEADER_LENGTH 24
92 #define MARC_CHAR_UNINITIALIZED 256
94 #define marc_isdigit(x) (((x) >='0') && ((x) <= '9'))
95 #define marc_char_to_int(x) ((x) - '0')
97 typedef struct marc_directory_entry {
98 uint32_t tag;
99 uint32_t length;
100 uint32_t starting_character;
101 } marc_directory_entry;
103 static dissector_handle_t z3950_handle;
105 void proto_reg_handoff_z3950(void);
106 void proto_register_z3950(void);
108 /* Initialize the protocol and registered fields */
109 static int proto_z3950;
110 static int global_z3950_port = Z3950_PORT;
111 static bool z3950_desegment = true;
113 static const value_string z3950_bib1_att_types[] = {
114 { Z3950_BIB1_AT_USE, "Use" },
115 { Z3950_BIB1_AT_RELATION, "Relation" },
116 { Z3950_BIB1_AT_POSITION, "Position" },
117 { Z3950_BIB1_AT_STRUCTURE, "Structure" },
118 { Z3950_BIB1_AT_TRUNCATION, "Truncation" },
119 { Z3950_BIB1_AT_COMPLETENESS, "Completeness"},
120 { 0, NULL}
123 static const value_string z3950_bib1_at_use[] = {
124 { 1, "Personal name" },
125 { 2, "Corporate name" },
126 { 3, "Conference name" },
127 { 4, "Title" },
128 { 5, "Title series" },
129 { 6, "Title uniform" },
130 { 7, "ISBN" },
131 { 8, "ISSN" },
132 { 9, "LC card number" },
133 { 10, "BNB card number" },
134 { 11, "BGF card number" },
135 { 12, "Local number" },
136 { 13, "Dewey classification" },
137 { 14, "UDC classification" },
138 { 15, "Bliss classification" },
139 { 16, "LC call number" },
140 { 17, "NLM call number" },
141 { 18, "NAL call number" },
142 { 19, "MOS call number" },
143 { 20, "Local classification" },
144 { 21, "Subject heading" },
145 { 22, "Subject Rameau" },
146 { 23, "BDI index subject" },
147 { 24, "INSPEC subject" },
148 { 25, "MESH subject" },
149 { 26, "PA subject" },
150 { 27, "LC subject heading" },
151 { 28, "RVM subject heading" },
152 { 29, "Local subject index" },
153 { 30, "Date" },
154 { 31, "Date of publication" },
155 { 32, "Date of acquisition" },
156 { 33, "Title key" },
157 { 34, "Title collective" },
158 { 35, "Title parallel" },
159 { 36, "Title cover" },
160 { 37, "Title added title pagw" },
161 { 38, "Title caption" },
162 { 39, "Title running" },
163 { 40, "Title spine" },
164 { 41, "Title other variant" },
165 { 42, "Title former" },
166 { 43, "Title abbreviated" },
167 { 44, "Title expanded" },
168 { 45, "Subject precis" },
169 { 46, "Subject rswk" },
170 { 47, "Subject subdivision" },
171 { 48, "No. nat'l biblio." },
172 { 49, "No. legal deposit" },
173 { 50, "No. govt pub." },
174 { 51, "No. music publisher" },
175 { 52, "Number db" },
176 { 53, "Number local call" },
177 { 54, "Code-language" },
178 { 55, "Code-geographic area" },
179 { 56, "Code-institution" },
180 { 57, "Name and title *" },
181 { 58, "Name geographic" },
182 { 59, "Place publication" },
183 { 60, "CODEN" },
184 { 61, "Microform generation" },
185 { 62, "Abstract" },
186 { 63, "Note" },
187 { 1000, "Author-title" },
188 { 1001, "Record type" },
189 { 1002, "Name" },
190 { 1003, "Author" },
191 { 1004, "Author-name personal" },
192 { 1005, "Author-name corporate" },
193 { 1006, "Author-name conference" },
194 { 1007, "Identifier-standard" },
195 { 1008, "Subject-LC children's" },
196 { 1009, "Subject name-personal" },
197 { 1010, "Body of text" },
198 { 1011, "Date/time added to db" },
199 { 1012, "Date/time last modified" },
200 { 1013, "Authority/format id" },
201 { 1014, "Concept-text" },
202 { 1015, "Concept-reference" },
203 { 1016, "Any" },
204 { 1017, "Server-choice" },
205 { 1018, "Publisher" },
206 { 1019, "Record-source" },
207 { 1020, "Editor" },
208 { 1021, "Bib-level" },
209 { 1022, "Geographic class" },
210 { 1023, "Indexed-by" },
211 { 1024, "Map-scale" },
212 { 1025, "Music-key" },
213 { 1026, "Related-periodical" },
214 { 1027, "Report-number" },
215 { 1028, "Stock-number" },
216 { 1030, "Thematic-number" },
217 { 1031, "Material-type" },
218 { 1032, "Doc-id" },
219 { 1033, "Host-item" },
220 { 1034, "Content-type" },
221 { 1035, "Anywhere" },
222 { 1036, "Author-Title-Subject" },
223 { 1037, "Serial Item and Contribution Identifier (SICI)" },
224 { 1038, "Abstract-language" },
225 { 1039, "Application-kind" },
226 { 1040, "Classification" },
227 { 1041, "Classification-basic" },
228 { 1042, "Classification-local-record" },
229 { 1043, "Enzyme" },
230 { 1044, "Possessing-institution" },
231 { 1045, "Record-linking" },
232 { 1046, "Record-status" },
233 { 1047, "Treatment" },
234 { 1048, "Control-number-GKD" },
235 { 1049, "Control-number-linking" },
236 { 1050, "Control-number-PND" },
237 { 1051, "Control-number-SWD" },
238 { 1052, "Control-number-ZDB" },
239 { 1053, "Country-publication" },
240 { 1054, "Date-conference" },
241 { 1055, "Date-record-status" },
242 { 1056, "Dissertation-information" },
243 { 1057, "Meeting-organizer" },
244 { 1058, "Note-availability" },
245 { 1059, "Number-CAS-registry" },
246 { 1060, "Number-document" },
247 { 1061, "Number-local-accounting" },
248 { 1062, "Number-local-acquisition" },
249 { 1063, "Number-local-call-copy-specific" },
250 { 1064, "Number-of-reference" },
251 { 1065, "Number-norm" },
252 { 1066, "Number-volume" },
253 { 1067, "Place-conference (meeting location)" },
254 { 1068, "Reference (references and footnotes)" },
255 { 1069, "Referenced-journal" },
256 { 1070, "Section-code" },
257 { 1071, "Section-heading" },
258 { 1072, "Subject-GOO" },
259 { 1073, "Subject-name-conference" },
260 { 1074, "Subject-name-corporate" },
261 { 1075, "Subject-genre/form" },
262 { 1076, "Subject-name-geographical" },
263 { 1077, "Subject-chronological" },
264 { 1078, "Subject-title" },
265 { 1079, "Subject-topical" },
266 { 1080, "Subject-uncontrolled" },
267 { 1081, "Terminology-chemical" },
268 { 1082, "Title-translated" },
269 { 1083, "Year-of-beginning" },
270 { 1084, "Year-of-ending" },
271 { 1085, "Subject-AGROVOC" },
272 { 1086, "Subject-COMPASS" },
273 { 1087, "Subject-EPT" },
274 { 1088, "Subject-NAL" },
275 { 1089, "Classification-BCM" },
276 { 1090, "Classification-DB" },
277 { 1091, "Identifier-ISRC" },
278 { 1092, "Identifier-ISMN" },
279 { 1093, "Identifier-ISRN" },
280 { 1094, "Identifier-DOI" },
281 { 1095, "Code-language-original" },
282 { 1096, "Title-later" },
283 { 1097, "DC-Title" },
284 { 1098, "DC-Creator" },
285 { 1099, "DC-Subject" },
286 { 1100, "DC-Description" },
287 { 1101, "DC-Publisher" },
288 { 1102, "DC-Date" },
289 { 1103, "DC-ResourceType" },
290 { 1104, "DC-ResourceIdentifier" },
291 { 1105, "DC-Language" },
292 { 1106, "DC-OtherContributor" },
293 { 1107, "DC-Format" },
294 { 1108, "DC-Source" },
295 { 1109, "DC-Relation" },
296 { 1110, "DC-Coverage" },
297 { 1111, "DC-RightsManagement" },
298 { 1112, "GILS Controlled Subject Index" },
299 { 1113, "GILS Subject Thesaurus" },
300 { 1114, "GILS Index Terms -- Controlled" },
301 { 1115, "GILS Controlled Term" },
302 { 1116, "GILS Spacial Domain" },
303 { 1117, "GILS Bounding Coordinates" },
304 { 1118, "GILS West Bounding Coordinate" },
305 { 1119, "GILS East Bounding Coordinate" },
306 { 1120, "GILS North Bounding Coordinate" },
307 { 1121, "GILS South Bounding Coordinate" },
308 { 1122, "GILS Place" },
309 { 1123, "GILS Place Keyword Thesaurus" },
310 { 1124, "GILS Place Keyword" },
311 { 1125, "GILS Time Period" },
312 { 1126, "GILS Time Period Textual" },
313 { 1127, "GILS Time Period Structured" },
314 { 1128, "GILS Beginning Date" },
315 { 1129, "GILS Ending Date" },
316 { 1130, "GILS Availability" },
317 { 1131, "GILS Distributor" },
318 { 1132, "GILS Distributor Name" },
319 { 1133, "GILS Distributor Organization" },
320 { 1134, "GILS Distributor Street Address" },
321 { 1135, "GILS Distributor City" },
322 { 1136, "GILS Distributor State or Province" },
323 { 1137, "GILS Distributor Zip or Postal Code" },
324 { 1138, "GILS Distributor Country" },
325 { 1139, "GILS Distributor Network Address" },
326 { 1140, "GILS Distributor Hours of Service" },
327 { 1141, "GILS Distributor Telephone" },
328 { 1142, "GILS Distributor Fax" },
329 { 1143, "GILS Resource Description" },
330 { 1144, "GILS Order Process" },
331 { 1145, "GILS Order Information" },
332 { 1146, "GILS Cost" },
333 { 1147, "GILS Cost Information" },
334 { 1148, "GILS Technical Prerequisites" },
335 { 1149, "GILS Available Time Period" },
336 { 1150, "GILS Available Time Textual" },
337 { 1151, "GILS Available Time Structured" },
338 { 1152, "GILS Available Linkage" },
339 { 1153, "GILS Linkage Type" },
340 { 1154, "GILS Linkage" },
341 { 1155, "GILS Sources of Data" },
342 { 1156, "GILS Methodology" },
343 { 1157, "GILS Access Constraints" },
344 { 1158, "GILS General Access Constraints" },
345 { 1159, "GILS Originator Dissemination Control" },
346 { 1160, "GILS Security Classification Control" },
347 { 1161, "GILS Use Constraints" },
348 { 1162, "GILS Point of Contact" },
349 { 1163, "GILS Contact Name" },
350 { 1164, "GILS Contact Organization" },
351 { 1165, "GILS Contact Street Address" },
352 { 1166, "GILS Contact City" },
353 { 1167, "GILS Contact State or Province" },
354 { 1168, "GILS Contact Zip or Postal Code" },
355 { 1169, "GILS Contact Country" },
356 { 1170, "GILS Contact Network Address" },
357 { 1171, "GILS Contact Hours of Service" },
358 { 1172, "GILS Contact Telephone" },
359 { 1173, "GILS Contact Fax" },
360 { 1174, "GILS Supplemental Information" },
361 { 1175, "GILS Purpose" },
362 { 1176, "GILS Agency Program" },
363 { 1177, "GILS Cross Reference" },
364 { 1178, "GILS Cross Reference Title" },
365 { 1179, "GILS Cross Reference Relationship" },
366 { 1180, "GILS Cross Reference Linkage" },
367 { 1181, "GILS Schedule Number" },
368 { 1182, "GILS Original Control Identifier" },
369 { 1183, "GILS Language of Record" },
370 { 1184, "GILS Record Review Date" },
371 { 1185, "Performer" },
372 { 1186, "Performer-Individual" },
373 { 1187, "Performer-Group" },
374 { 1188, "Instrumentation" },
375 { 1189, "Instrumentation-Original" },
376 { 1190, "Instrumentation-Current" },
377 { 1191, "Arrangement" },
378 { 1192, "Arrangement-Original" },
379 { 1193, "Arrangement-Current" },
380 { 1194, "Musical Key-Original" },
381 { 1195, "Musical Key-Current" },
382 { 1196, "Date-Composition" },
383 { 1197, "Date-Recording" },
384 { 1198, "Place-Recording" },
385 { 1199, "Country-Recording" },
386 { 1200, "Number-ISWC" },
387 { 1201, "Number-Matrix" },
388 { 1202, "Number-Plate" },
389 { 1203, "Classification-McColvin" },
390 { 1204, "Duration" },
391 { 1205, "Number-Copies" },
392 { 1206, "Musical Theme" },
393 { 1207, "Instruments - total number" },
394 { 1208, "Instruments - distinct number" },
395 { 1209, "Identifier - URN" },
396 { 1210, "Sears Subject Heading" },
397 { 1211, "OCLC Number" },
398 { 1212, "NORZIG Composition" },
399 { 1213, "NORZIG Intellectual level" },
400 { 1214, "NORZIG EAN" },
401 { 1215, "NORZIG NLC" },
402 { 1216, "NORZIG CRCS" },
403 { 1217, "NORZIG Nationality" },
404 { 1218, "NORZIG Equinox" },
405 { 1219, "NORZIG Compression" },
406 { 1220, "NORZIG Format" },
407 { 1221, "NORZIG Subject - occupation" },
408 { 1222, "NORZIG Subject - function" },
409 { 1223, "NORZIG Edition" },
410 { 1224, "GPO Item Number" },
411 { 1225, "Provider" },
412 { 0, NULL}
415 static const value_string z3950_bib1_at_relation[] = {
416 { 1, "Less than" },
417 { 2, "Less than or equal" },
418 { 3, "Equal" },
419 { 4, "Greater than or equal" },
420 { 5, "Greater than" },
421 { 6, "Not equal" },
422 { 100, "Phonetic" },
423 { 101, "Stem" },
424 { 102, "Relevance" },
425 { 103, "Always Matches" },
426 { 0, NULL}
429 static const value_string z3950_bib1_at_position[] = {
430 { 1, "First in field" },
431 { 2, "First in subfield" },
432 { 3, "Any position in field" },
433 { 0, NULL}
436 static const value_string z3950_bib1_at_structure[] = {
437 { 1, "Phrase" },
438 { 2, "Word" },
439 { 3, "Key" },
440 { 4, "Year" },
441 { 5, "Date (normalized)" },
442 { 6, "Word list" },
443 { 100, "Date (un-normalized)" },
444 { 101, "Name (normalized)" },
445 { 102, "Name (un-normalized)" },
446 { 103, "Structure" },
447 { 104, "Urx" },
448 { 105, "Free-form-text" },
449 { 106, "Document-text" },
450 { 107, "Local" },
451 { 108, "String" },
452 { 109, "Numeric" },
453 { 0, NULL}
456 static const value_string z3950_bib1_at_truncation[] = {
457 { 1, "Right truncation" },
458 { 2, "Left truncation" },
459 { 3, "Left and right truncation" },
460 { 100, "Do not truncate" },
461 { 101, "Process # in search term" },
462 { 102, "regExpr-1" },
463 { 103, "regExpr-2" },
464 { 104, "Z39.58-1992 Character masking" },
465 { 0, NULL}
468 static const value_string z3950_bib1_at_completeness[] = {
469 { 1, "Incomplete subfield" },
470 { 2, "Complete subfield" },
471 { 3, "Complete field" },
472 { 0, NULL}
475 static const value_string z3950_bib1_diagconditions[] = {
476 { 1, "Permanent system error" },
477 { 2, "Temporary system error" },
478 { 3, "Unsupported search" },
479 { 4, "Terms only exclusion (stop) words" },
480 { 5, "Too many argument words" },
481 { 6, "Too many boolean operators" },
482 { 7, "Too many truncated words" },
483 { 8, "Too many incomplete subfields" },
484 { 9, "Truncated words too short" },
485 { 10, "Invalid format for record number (search term)" },
486 { 11, "Too many characters in search statement" },
487 { 12, "Too many records retrieved" },
488 { 13, "Present request out of range" },
489 { 14, "System error in presenting records" },
490 { 15, "Record no authorized to be sent intersystem" },
491 { 16, "Record exceeds Preferred-message-size" },
492 { 17, "Record exceeds Maximum-record-size" },
493 { 18, "Result set not supported as a search term" },
494 { 19, "Only single result set as search term supported" },
495 { 20, "Only ANDing of a single result set as search term supported" },
496 { 21, "Result set exists and replace indicator off" },
497 { 22, "Result set naming not supported" },
498 { 23, "Combination of specified databases not supported" },
499 { 24, "Element set names not supported" },
500 { 25, "Specified element set name not valid for specified database" },
501 { 26, "Only a single element set name supported" },
502 { 27, "Result set no longer exists - unilaterally deleted by target" },
503 { 28, "Result set is in use" },
504 { 29, "One of the specified databases is locked" },
505 { 30, "Specified result set does not exist" },
506 { 31, "Resources exhausted - no results available" },
507 { 32, "Resources exhausted - unpredictable partial results available" },
508 { 33, "Resources exhausted - valid subset of results available" },
509 { 100, "Unspecified error" },
510 { 101, "Access-control failure" },
511 { 102, "Security challenge required but could not be issued - request terminated" },
512 { 103, "Security challenge required but could not be issued - record not included" },
513 { 104, "Security challenge failed - record not included" },
514 { 105, "Terminated by negative continue response" },
515 { 106, "No abstract syntaxes agreed to for this record" },
516 { 107, "Query type not supported" },
517 { 108, "Malformed query" },
518 { 109, "Database unavailable" },
519 { 110, "Operator unsupported" },
520 { 111, "Too many databases specified" },
521 { 112, "Too many result sets created" },
522 { 113, "Unsupported attribute type" },
523 { 114, "Unsupported Use attribute" },
524 { 115, "Unsupported value for Use attribute" },
525 { 116, "Use attribute required but not supplied" },
526 { 117, "Unsupported Relation attribute" },
527 { 118, "Unsupported Structure attribute" },
528 { 119, "Unsupported Position attribute" },
529 { 120, "Unsupported Truncation attribute" },
530 { 121, "Unsupported Attribute Set" },
531 { 122, "Unsupported Completeness attribute" },
532 { 123, "Unsupported attribute combination" },
533 { 124, "Unsupported coded value for term" },
534 { 125, "Malformed search term" },
535 { 126, "Illegal term value for attribute" },
536 { 127, "Unparsable format for un-normalized value" },
537 { 128, "Illegal result set name" },
538 { 129, "Proximity search of sets not supported" },
539 { 130, "Illegal result set in proximity search" },
540 { 131, "Unsupported proximity relation" },
541 { 132, "Unsupported proximity unit code" },
542 { 201, "Proximity not supported with this attribute combination" },
543 { 202, "Unsupported distance for proximity" },
544 { 203, "Ordered flag not supported for proximity" },
545 { 205, "Only zero step size supported for Scan" },
546 { 206, "Specified step size not supported for Scan" },
547 { 207, "Cannot sort according to sequence" },
548 { 208, "No result set name supplied on Sort" },
549 { 209, "Generic sort not supported (database-specific sort only supported)" },
550 { 210, "Database specific sort not supported" },
551 { 211, "Too many sort keys" },
552 { 212, "Duplicate sort keys" },
553 { 213, "Unsupported missing data action" },
554 { 214, "Illegal sort relation" },
555 { 215, "Illegal case value" },
556 { 216, "Illegal missing data action" },
557 { 217, "Segmentation: Cannot guarantee records will fit in specified segments" },
558 { 218, "ES: Package name already in use" },
559 { 219, "ES: no such package, on modify/delete" },
560 { 220, "ES: quota exceeded" },
561 { 221, "ES: extended service type not supported" },
562 { 222, "ES: permission denied on ES - id not authorized" },
563 { 223, "ES: permission denied on ES - cannot modify or delete" },
564 { 224, "ES: immediate execution failed" },
565 { 225, "ES: immediate execution not supported for this service" },
566 { 226, "ES: immediate execution not supported for these parameters" },
567 { 227, "No data available in requested record syntax" },
568 { 228, "Scan: malformed scan" },
569 { 229, "Term type not supported" },
570 { 230, "Sort: too many input results" },
571 { 231, "Sort: incompatible record formats" },
572 { 232, "Scan: term list not supported" },
573 { 233, "Scan: unsupported value of position-in-response" },
574 { 234, "Too many index terms processed" },
575 { 235, "Database does not exist" },
576 { 236, "Access to specified database denied" },
577 { 237, "Sort: illegal sort" },
578 { 238, "Record not available in requested syntax" },
579 { 239, "Record syntax not supported" },
580 { 240, "Scan: Resources exhausted looking for satisfying terms" },
581 { 241, "Scan: Beginning or end of term list" },
582 { 242, "Segmentation: max-segment-size too small to segment record" },
583 { 243, "Present: additional-ranges parameter not supported" },
584 { 244, "Present: comp-spec parameter not supported" },
585 { 245, "Type-1 query: restriction ('resultAttr') operand not supported" },
586 { 246, "Type-1 query: 'complex' attributeValue not supported" },
587 { 247, "Type-1 query: 'attributeSet' as part of AttributeElement not supported" },
588 { 1001, "Malformed APDU" },
589 { 1002, "ES: EXTERNAL form of Item Order request not supported" },
590 { 1003, "ES: Result set item form of Item Order request not supported" },
591 { 1004, "ES: Extended services not supported unless access control is in effect" },
592 { 1005, "Response records in Search response not supported" },
593 { 1006, "Response records in Search response not possible for specified database (or database combination)" },
594 { 1007, "No Explain server. Addinfo: pointers to servers that have a surrogate Explain database for this server" },
595 { 1008, "ES: missing mandatory parameter for specified function. Addinfo: parameter" },
596 { 1009, "ES: Item Order, unsupported OID in itemRequest. Addinfo: OID" },
597 { 1010, "Init/AC: Bad Userid" },
598 { 1011, "Init/AC: Bad Userid and/or Password" },
599 { 1012, "Init/AC: No searches remaining (pre-purchased searches exhausted)" },
600 { 1013, "Init/AC: Incorrect interface type (specified id valid only when used with a particular access method or client)" },
601 { 1014, "Init/AC: Authentication System error" },
602 { 1015, "Init/AC: Maximum number of simultaneous sessions for Userid" },
603 { 1016, "Init/AC: Blocked network address" },
604 { 1017, "Init/AC: No databases available for specified userId" },
605 { 1018, "Init/AC: System temporarily out of resources" },
606 { 1019, "Init/AC: System not available due to maintenance" },
607 { 1020, "Init/AC: System temporarily unavailable (Addinfo: when it's expected back up)" },
608 { 1021, "Init/AC: Account has expired" },
609 { 1022, "Init/AC: Password has expired so a new one must be supplied" },
610 { 1023, "Init/AC: Password has been changed by an administrator so a new one must be supplied" },
611 { 1024, "Unsupported Attribute" },
612 { 1025, "Service not supported for this database" },
613 { 1026, "Record cannot be opened because it is locked" },
614 { 1027, "SQL error" },
615 { 1028, "Record deleted" },
616 { 1029, "Scan: too many terms requested. Addinfo: max terms supported" },
617 { 1040, "ES: Invalid function" },
618 { 1041, "ES: Error in retention time" },
619 { 1042, "ES: Permissions data not understood" },
620 { 1043, "ES: Invalid OID for task specific parameters" },
621 { 1044, "ES: Invalid action" },
622 { 1045, "ES: Unknown schema" },
623 { 1046, "ES: Too many records in package" },
624 { 1047, "ES: Invalid wait action" },
625 { 1048, "ES: Cannot create task package -- exceeds maximum permissible size" },
626 { 1049, "ES: Cannot return task package -- exceeds maximum permissible size" },
627 { 1050, "ES: Extended services request too large" },
628 { 1051, "Scan: Attribute set id required -- not supplied" },
629 { 1052, "ES: Cannot process task package record -- exceeds maximum permissible record size for ES" },
630 { 1053, "ES: Cannot return task package record -- exceeds maximum permissible record size for ES response" },
631 { 1054, "Init: Required negotiation record not included" },
632 { 1055, "Init: negotiation option required" },
633 { 1056, "Attribute not supported for database" },
634 { 1057, "ES: Unsupported value of task package parameter" },
635 { 1058, "Duplicate Detection: Cannot dedup on requested record portion" },
636 { 1059, "Duplicate Detection: Requested detection criterion not supported" },
637 { 1060, "Duplicate Detection: Requested level of match not supported" },
638 { 1061, "Duplicate Detection: Requested regular expression not supported" },
639 { 1062, "Duplicate Detection: Cannot do clustering" },
640 { 1063, "Duplicate Detection: Retention criterion not supported" },
641 { 1064, "Duplicate Detection: Requested number (or percentage) of entries for retention too large" },
642 { 1065, "Duplicate Detection: Requested sort criterion not supported" },
643 { 1066, "CompSpec: Unknown schema, or schema not supported." },
644 { 1067, "Encapsulation: Encapsulated sequence of PDUs not supported" },
645 { 1068, "Encapsulation: Base operation (and encapsulated PDUs) not executed based on pre-screening analysis" },
646 { 1069, "No syntaxes available for this request" },
647 { 1070, "User not authorized to receive record(s) in requested syntax" },
648 { 1071, "preferredRecordSyntax not supplied" },
649 { 1072, "Query term includes characters that do not translate into the target character set" },
650 { 1073, "Database records do not contain data associated with access point" },
651 { 1074, "Proxy failure" },
652 { 0, NULL}
655 #include "packet-z3950-hf.c"
657 static int hf_z3950_referenceId_printable;
658 static int hf_z3950_general_printable;
660 /* Initialize the subtree pointers */
661 static int ett_z3950;
663 #include "packet-z3950-ett.c"
665 /* MARC variables and forwards */
667 static int dissect_marc_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_);
669 /* MARC fields */
670 static int hf_marc_record;
671 static int hf_marc_record_terminator;
672 static int hf_marc_leader;
673 static int hf_marc_leader_length;
674 static int hf_marc_leader_status;
675 static int hf_marc_leader_type;
676 static int hf_marc_leader_biblevel;
677 static int hf_marc_leader_control;
678 static int hf_marc_leader_encoding;
679 static int hf_marc_leader_indicator_count;
680 static int hf_marc_leader_subfield_count;
681 static int hf_marc_leader_data_offset;
682 static int hf_marc_leader_encoding_level;
683 static int hf_marc_leader_descriptive_cataloging;
684 static int hf_marc_leader_multipart_level;
685 static int hf_marc_leader_length_of_field_length;
686 static int hf_marc_leader_starting_character_position_length;
687 static int hf_marc_leader_implementation_defined_length;
688 static int hf_marc_directory;
689 static int hf_marc_directory_entry;
690 static int hf_marc_directory_entry_tag;
691 static int hf_marc_directory_entry_length;
692 static int hf_marc_directory_entry_starting_position;
693 static int hf_marc_directory_terminator;
694 static int hf_marc_fields;
695 static int hf_marc_field;
696 static int hf_marc_field_control;
697 static int hf_marc_field_terminator;
698 static int hf_marc_field_indicator1;
699 static int hf_marc_field_indicator2;
700 static int hf_marc_field_subfield_indicator;
701 static int hf_marc_field_subfield_tag;
702 static int hf_marc_field_subfield;
704 /* MARC subtree pointers */
705 static int ett_marc_record;
706 static int ett_marc_leader;
707 static int ett_marc_directory;
708 static int ett_marc_directory_entry;
709 static int ett_marc_fields;
710 static int ett_marc_field;
712 /* MARC expert fields */
713 static expert_field ei_marc_invalid_length;
714 static expert_field ei_marc_invalid_value;
715 static expert_field ei_marc_invalid_record_length;
717 /* MARC value strings */
719 static const value_string marc_tag_names[] = {
720 { 1, "Control Number" },
721 { 3, "Control Number Identifier" },
722 { 5, "Date and Time of Latest Transaction" },
723 { 6, "Fixed-length Data Elements - Additional Material Characteristics" },
724 { 8, "Fixed-length Data Elements" },
725 { 7, "Physical Description Fixed Field" },
726 { 10, "Library of Congress Control Number" },
727 { 15, "National Bibliography Number" },
728 { 16, "National Bibliographic Agency Control Number" },
729 { 17, "Copyright or Legal Deposit Number" },
730 { 20, "International Standard Book Number (ISBN)" },
731 { 22, "International Standard Serial Number (ISSN)" },
732 { 24, "Other Standard Identifier" },
733 { 25, "Overseas Acquisition Number" },
734 { 26, "Fingerprint Identifier" },
735 { 27, "Standard Technical Report Number" },
736 { 28, "Publisher or Distributor Number" },
737 { 30, "CODEN Designation" },
738 { 32, "Postal Registration Number" },
739 { 33, "Date/Time and Place of an Event" },
740 { 35, "System Control Number" },
741 { 37, "Source of Acquisition" },
742 { 38, "Record Content Licensor" },
743 { 40, "Cataloging Source" },
744 { 41, "Language Code" },
745 { 42, "Authentication Code" },
746 { 43, "Geographic Area Code" },
747 { 44, "Country of Publishing/Producing Entity Code" },
748 { 45, "Time Period of Content" },
749 { 47, "Form of Musical Composition Code" },
750 { 50, "Library of Congress Call Number" },
751 { 51, "Library of Congress Copy, Issue, Offprint Statement" },
752 { 60, "National Library of Medicine Call Number" },
753 { 66, "Character Sets Present" },
754 { 80, "Universal Decimal Classification Number" },
755 { 82, "Dewey Decimal Classification Number" },
756 { 83, "Additional Dewey Decimal Classification Number" },
757 { 84, "Other Classification Number" },
758 { 100, "Main Entry - Personal Name" },
759 { 110, "Main Entry - Corporate Name" },
760 { 111, "Main Entry - Meeting Name" },
761 { 130, "Main Entry - Uniform Title" },
762 { 210, "Abbreviated Title" },
763 { 222, "Key Title" },
764 { 240, "Uniform Title" },
765 { 242, "Translation of Title by Cataloging Agency" },
766 { 243, "Collective Uniform Title" },
767 { 245, "Title Statement" },
768 { 246, "Varying Form of Title" },
769 { 247, "Former Title" },
770 { 249, "Local LoC Varying Form of Title" },
771 { 250, "Edition Statement" },
772 { 260, "Publication, Distribution, etc. (Imprint)" },
773 { 264, "Production, Publication, Distribution, Manufacture, and Copyright Notice" },
774 { 300, "Physical Description" },
775 { 310, "Current Publication Frequency" },
776 { 321, "former Publication Frequency" },
777 { 336, "Content Type" },
778 { 337, "Media Type" },
779 { 338, "Carrier Type" },
780 { 340, "Physical Medium" },
781 { 362, "Dates of Publication and/or Sequential Designation" },
782 { 400, "Series Statement/Added Entry-Personal Name" },
783 { 410, "Series Statement/Added Entry-Corporate Name" },
784 { 411, "Series Statement/Added Entry-Meeting Name" },
785 { 440, "Series Statement/Added Entry-Title" },
786 { 490, "Series Statement" },
787 { 500, "General Note" },
788 { 504, "Bibliography, etc. Note" },
789 { 505, "Formatted Contents Note" },
790 { 506, "Restrictions on Access Note" },
791 { 508, "Creation/Production Credits Note" },
792 { 510, "Citation/References Note" },
793 { 511, "Participant or Performer Note" },
794 { 515, "Numbering Peculiarities Note" },
795 { 518, "Date/Time and Place of an Event Note" },
796 { 520, "Summary, etc." },
797 { 521, "Target Audience Note" },
798 { 522, "Geographic Coverage Note" },
799 { 524, "Preferred Citation of Described Materials Note" },
800 { 525, "Supplement Note" },
801 { 530, "Additional Physical Form available Note" },
802 { 532, "Accessibility Note" },
803 { 533, "Reproduction Note" },
804 { 534, "Original Version Note" },
805 { 538, "System Details Note" },
806 { 540, "Terms Governing Use and Reproduction Note" },
807 { 541, "Immediate Source of Acquisition Note" },
808 { 542, "Information Relating to Copyright Status" },
809 { 546, "Language Note" },
810 { 550, "Issuing Body Note" },
811 { 555, "Cumulative Index/Finding Aids Note" },
812 { 583, "Action Note" },
813 { 588, "Source of Description, Etc. Note" },
814 { 590, "Local LoC Note" },
815 { 591, "Local LoC \"With\" Note" },
816 { 592, "Local LoC Acquisition Note" },
817 { 600, "Subject Added Entry - Personal Name" },
818 { 610, "Subject Added Entry - Corporate Name" },
819 { 611, "Subject Added Entry - Meeting Name" },
820 { 630, "Subject Added Entry - Uniform Title" },
821 { 647, "Subject Added Entry - Named Event" },
822 { 648, "Subject Added Entry - Chronological Term" },
823 { 650, "Subject Added Entry - Topical Term" },
824 { 651, "Subject Added Entry - Geographic Name" },
825 { 653, "Index Term - Uncontrolled" },
826 { 654, "Subject Added Entry - Faceted Topical Terms" },
827 { 655, "Index Term - Genre/Form" },
828 { 656, "Index Term - Occupation" },
829 { 657, "Index Term - Function" },
830 { 658, "Index Term - Curriculum Objective" },
831 { 662, "Subject Added Entry - Hierarchical Place Name" },
832 { 700, "Added Entry - Personal Name" },
833 { 710, "Added Entry - Corporate Name" },
834 { 711, "Added Entry - Meeting Name" },
835 { 720, "Added Entry - Uncontrolled Name" },
836 { 730, "Added Entry - Uniform Title" },
837 { 740, "Added Entry - Uncontrolled Related/Analytical Title" },
838 { 751, "Added Entry - Geographic Name" },
839 { 752, "Added Entry - Hierarchical Place Name" },
840 { 753, "System Details Access to Computer Files" },
841 { 754, "Added Entry - Taxonomic Identification" },
842 { 758, "Resource Identifier" },
843 { 760, "Main Series Entry" },
844 { 762, "Subseries Entry" },
845 { 765, "Original Language Entry" },
846 { 767, "Translation Entry" },
847 { 770, "Supplement/Special Issue Entry" },
848 { 772, "Supplement Parent Entry" },
849 { 773, "Host Item Entry" },
850 { 774, "Constituent Unit Entry" },
851 { 775, "Other Edition Entry" },
852 { 776, "Additional Physical Form Entry" },
853 { 777, "Issued With Entry" },
854 { 780, "Preceding Entry" },
855 { 785, "Succeeding Entry" },
856 { 786, "Data Source Entry" },
857 { 787, "Other Relationship Entry" },
858 { 800, "Series Added Entry - Personal Name" },
859 { 810, "Series Added Entry - Corporate Name" },
860 { 811, "Series Added Entry - Meeting Name" },
861 { 830, "Series Added Entry - Uniform Title" },
862 { 850, "Holding Institution" },
863 { 852, "Location" },
864 { 853, "Captions and Pattern - Basic Bibliographic Unit" },
865 { 856, "Electronic Location and Access" },
866 { 859, "Local LoC Electronic Location and Access" },
867 { 863, "Enumeration and Chronology - Basic Bibliographic Unit" },
868 { 880, "Alternate Graphic Representation" },
869 { 890, "Local LoC Visible File Entry" },
870 { 906, "Local LoC Processing Data" },
871 { 920, "Local LoC Selection Decision" },
872 { 922, "Local LoC Book Source" },
873 { 923, "Local LoC Supplier Invoice or Shipment Id" },
874 { 925, "Local LoC Selection Decision" },
875 { 952, "Local LoC Cataloger's Permanent Note" },
876 { 955, "Local LoC Functional Identifying Information" },
877 { 984, "Local LoC Shelflist Compare Status" },
878 { 985, "Local LoC Record History" },
879 { 987, "Local LoC Conversation History" },
880 { 991, "Local LoC Location Information" },
881 { 992, "Local LoC Location Information" },
882 { 0, NULL}
885 static int
886 dissect_z3950_printable_OCTET_STRING(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
887 tvbuff_t *next_tvb = NULL;
888 int hf_alternate = 0;
889 unsigned old_offset = offset;
891 if (hf_index == hf_z3950_referenceId) {
892 hf_alternate = hf_z3950_referenceId_printable;
894 else if ( hf_index == hf_z3950_general) {
895 hf_alternate = hf_z3950_general_printable;
898 if (hf_alternate > 0) {
899 /* extract the value of the octet string so we can look at it. */
900 /* This does not display anything because tree is NULL. */
901 offset = dissect_ber_octet_string(implicit_tag, actx, NULL, tvb, offset, hf_index, &next_tvb);
903 if (next_tvb &&
904 tvb_ascii_isprint(next_tvb, 0, tvb_reported_length(next_tvb))) {
905 proto_tree_add_item(tree, hf_alternate, next_tvb,
906 0, tvb_reported_length(next_tvb), ENC_ASCII|ENC_NA);
908 else {
909 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb,
910 old_offset, hf_index, NULL);
913 else {
914 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb,
915 old_offset, hf_index, NULL);
918 return offset;
921 #include "packet-z3950-fn.c"
923 static int
924 dissect_z3950(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
926 proto_item *z3950_item = NULL;
927 proto_tree *z3950_tree = NULL;
928 int offset = 0;
929 asn1_ctx_t asn1_ctx;
930 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, true, pinfo);
933 /* make entry in the Protocol column on summary display */
934 col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
936 /* create the z3950 protocol tree */
937 z3950_item = proto_tree_add_item(tree, proto_z3950, tvb, 0, -1, ENC_NA);
938 z3950_tree = proto_item_add_subtree(z3950_item, ett_z3950);
940 return dissect_z3950_PDU(false, tvb, offset, &asn1_ctx, z3950_tree, -1);
943 static unsigned
944 get_z3950_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
946 unsigned plen;
947 unsigned ber_offset;
948 TRY {
949 /* Skip past identifier */
950 ber_offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
951 ber_offset = get_ber_length(tvb, ber_offset, &plen, NULL);
952 plen += (ber_offset - offset);
954 CATCH(ReportedBoundsError) {
955 plen = 0;
957 ENDTRY;
959 return plen;
962 static int
963 dissect_z3950_segment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
966 /* Min length of 8 assumes 3 for identifier and 5 for length. */
967 tcp_dissect_pdus(tvb, pinfo, tree, z3950_desegment, 8, get_z3950_pdu_len, dissect_z3950, data);
968 return tvb_captured_length(tvb);
971 /*--- proto_register_z3950 -------------------------------------------*/
972 void proto_register_z3950(void) {
974 /* List of fields */
975 static hf_register_info hf[] = {
977 #include "packet-z3950-hfarr.c"
979 { &hf_z3950_referenceId_printable,
980 { "referenceId", "z3950.referenceId.printable",
981 FT_STRING, BASE_NONE, NULL, 0,
982 NULL, HFILL }},
983 { &hf_z3950_general_printable,
984 { "general", "z3950.general.printable",
985 FT_STRING, BASE_NONE, NULL, 0,
986 NULL, HFILL }},
988 /* MARC hf definitions */
989 { &hf_marc_record,
990 { "MARC record", "marc",
991 FT_NONE, BASE_NONE, NULL, 0,
992 NULL, HFILL }},
993 { &hf_marc_record_terminator,
994 { "MARC record terminator", "marc.terminator",
995 FT_CHAR, BASE_HEX, NULL, 0,
996 NULL, HFILL }},
997 { &hf_marc_leader,
998 { "MARC leader", "marc.leader",
999 FT_NONE, BASE_NONE, NULL, 0,
1000 NULL, HFILL }},
1001 { &hf_marc_leader_length,
1002 { "MARC leader length", "marc.leader.length",
1003 FT_STRING, BASE_NONE, NULL, 0,
1004 NULL, HFILL }},
1005 { &hf_marc_leader_status,
1006 { "MARC leader status", "marc.leader.status",
1007 FT_CHAR, BASE_HEX, NULL, 0,
1008 NULL, HFILL }},
1009 { &hf_marc_leader_type,
1010 { "MARC leader type", "marc.leader.type",
1011 FT_CHAR, BASE_HEX, NULL, 0,
1012 NULL, HFILL }},
1013 { &hf_marc_leader_biblevel,
1014 { "MARC leader biblevel", "marc.leader.biblevel",
1015 FT_CHAR, BASE_HEX, NULL, 0,
1016 NULL, HFILL }},
1017 { &hf_marc_leader_control,
1018 { "MARC leader control", "marc.leader.control",
1019 FT_CHAR, BASE_HEX, NULL, 0,
1020 NULL, HFILL }},
1021 { &hf_marc_leader_encoding,
1022 { "MARC leader encoding", "marc.leader.encoding",
1023 FT_CHAR, BASE_HEX, NULL, 0,
1024 NULL, HFILL }},
1025 { &hf_marc_leader_indicator_count,
1026 { "MARC leader indicator count", "marc.leader.indicator_count",
1027 FT_CHAR, BASE_HEX, NULL, 0,
1028 NULL, HFILL }},
1029 { &hf_marc_leader_subfield_count,
1030 { "MARC leader subfield count", "marc.leader.subfield_count",
1031 FT_CHAR, BASE_HEX, NULL, 0,
1032 NULL, HFILL }},
1033 { &hf_marc_leader_data_offset,
1034 { "MARC leader data offset", "marc.leader.data_offset",
1035 FT_STRING, BASE_NONE, NULL, 0,
1036 NULL, HFILL }},
1037 { &hf_marc_leader_encoding_level,
1038 { "MARC leader encoding level", "marc.leader.encoding_level",
1039 FT_CHAR, BASE_HEX, NULL, 0,
1040 NULL, HFILL }},
1041 { &hf_marc_leader_descriptive_cataloging,
1042 { "MARC leader descriptive cataloging", "marc.leader.descriptive_cataloging",
1043 FT_CHAR, BASE_HEX, NULL, 0,
1044 NULL, HFILL }},
1045 { &hf_marc_leader_multipart_level,
1046 { "MARC leader multipart level", "marc.leader.multipart_level",
1047 FT_CHAR, BASE_HEX, NULL, 0,
1048 NULL, HFILL }},
1049 { &hf_marc_leader_length_of_field_length,
1050 { "MARC leader length-of-field length", "marc.leader.length_of_field_length",
1051 FT_CHAR, BASE_HEX, NULL, 0,
1052 NULL, HFILL }},
1053 { &hf_marc_leader_starting_character_position_length,
1054 { "MARC leader starting-character-position length", "marc.leader.starting_character_position_length",
1055 FT_CHAR, BASE_HEX, NULL, 0,
1056 NULL, HFILL }},
1057 { &hf_marc_leader_implementation_defined_length,
1058 { "MARC leader implementation-defined length", "marc.leader.implementation_defined_length",
1059 FT_CHAR, BASE_HEX, NULL, 0,
1060 NULL, HFILL }},
1061 { &hf_marc_directory,
1062 { "MARC directory", "marc.directory",
1063 FT_NONE, BASE_NONE, NULL, 0,
1064 NULL, HFILL }},
1065 { &hf_marc_directory_entry,
1066 { "MARC directory entry", "marc.directory.entry",
1067 FT_NONE, BASE_NONE, NULL, 0,
1068 NULL, HFILL }},
1069 { &hf_marc_directory_entry_tag,
1070 { "tag", "marc.directory.entry.tag",
1071 FT_STRING, BASE_NONE, NULL, 0,
1072 NULL, HFILL }},
1073 { &hf_marc_directory_entry_length,
1074 { "length", "marc.directory.entry.length",
1075 FT_STRING, BASE_NONE, NULL, 0,
1076 NULL, HFILL }},
1077 { &hf_marc_directory_entry_starting_position,
1078 { "starting position", "marc.directory.entry.starting_position",
1079 FT_STRING, BASE_NONE, NULL, 0,
1080 NULL, HFILL }},
1081 { &hf_marc_directory_terminator,
1082 { "MARC directory terminator", "marc.directory.terminator",
1083 FT_CHAR, BASE_HEX, NULL, 0,
1084 NULL, HFILL }},
1085 { &hf_marc_fields,
1086 { "MARC data fields", "marc.fields",
1087 FT_NONE, BASE_NONE, NULL, 0,
1088 NULL, HFILL }},
1089 { &hf_marc_field,
1090 { "MARC field", "marc.field",
1091 FT_NONE, BASE_NONE, NULL, 0,
1092 NULL, HFILL }},
1093 { &hf_marc_field_control,
1094 { "Control field", "marc.field.control",
1095 FT_STRING, BASE_NONE, NULL, 0,
1096 NULL, HFILL }},
1097 { &hf_marc_field_terminator,
1098 { "MARC field terminator", "marc.field.terminator",
1099 FT_CHAR, BASE_HEX, NULL, 0,
1100 NULL, HFILL }},
1101 { &hf_marc_field_indicator1,
1102 { "MARC field indicator1", "marc.field.indicator1",
1103 FT_CHAR, BASE_HEX, NULL, 0,
1104 NULL, HFILL }},
1105 { &hf_marc_field_indicator2,
1106 { "MARC field indicator2", "marc.field.indicator2",
1107 FT_CHAR, BASE_HEX, NULL, 0,
1108 NULL, HFILL }},
1109 { &hf_marc_field_subfield_indicator,
1110 { "MARC field subfield indicator", "marc.field.subfield.indicator",
1111 FT_CHAR, BASE_HEX, NULL, 0,
1112 NULL, HFILL }},
1113 { &hf_marc_field_subfield_tag,
1114 { "MARC field subfield tag", "marc.field.subfield.tag",
1115 FT_CHAR, BASE_HEX, NULL, 0,
1116 NULL, HFILL }},
1117 { &hf_marc_field_subfield,
1118 { "MARC Subfield", "marc.field.subfield",
1119 FT_STRING, BASE_NONE, NULL, 0,
1120 NULL, HFILL }},
1124 /* List of subtrees */
1125 static int *ett[] = {
1126 &ett_z3950,
1127 /* MARC etts */
1128 &ett_marc_record,
1129 &ett_marc_leader,
1130 &ett_marc_directory,
1131 &ett_marc_directory_entry,
1132 &ett_marc_fields,
1133 &ett_marc_field,
1134 #include "packet-z3950-ettarr.c"
1137 module_t *z3950_module;
1139 /* Expert info */
1140 static ei_register_info ei[] = {
1141 /* Z39.50 expert info */
1143 /* MARC expert info */
1144 { &ei_marc_invalid_length, { "marc.invalid_length", PI_MALFORMED, PI_ERROR,
1145 "MARC record too short", EXPFILL }},
1146 { &ei_marc_invalid_value, { "marc.invalid_value", PI_MALFORMED, PI_ERROR,
1147 "MARC field has invalid value", EXPFILL }},
1148 { &ei_marc_invalid_record_length, { "marc.invalid_record_length", PI_MALFORMED, PI_ERROR,
1149 "MARC length field has invalid value", EXPFILL }},
1152 expert_module_t* expert_z3950;
1155 /* Register protocol */
1156 proto_z3950 = proto_register_protocol(PNAME, PSNAME, PFNAME);
1157 /* Register fields and subtrees */
1158 proto_register_field_array(proto_z3950, hf, array_length(hf));
1159 proto_register_subtree_array(ett, array_length(ett));
1160 expert_z3950 = expert_register_protocol(proto_z3950);
1161 expert_register_field_array(expert_z3950, ei, array_length(ei));
1163 /* Register preferences */
1164 z3950_module = prefs_register_protocol(proto_z3950, NULL);
1165 prefs_register_bool_preference(z3950_module, "desegment_buffers",
1166 "Reassemble Z39.50 buffers spanning multiple TCP segments",
1167 "Whether the Z39.50 dissector should reassemble TDS buffers spanning multiple TCP segments. "
1168 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1169 &z3950_desegment);
1171 /* Allow dissector to be found by name. */
1172 z3950_handle = register_dissector(PSNAME, dissect_z3950_segment,
1173 proto_z3950);
1177 /*--- proto_reg_handoff_z3950 ---------------------------------------*/
1178 void
1179 proto_reg_handoff_z3950(void)
1182 dissector_add_uint_with_preference("tcp.port",
1183 global_z3950_port, z3950_handle);
1185 #include "packet-z3950-dis-tab.c"
1187 register_ber_oid_dissector(Z3950_RECORDSYNTAX_MARC21_OID, dissect_marc_record, proto_z3950, "MARC21");
1189 oid_add_from_string("Z39.50", "1.2.840.10003");
1190 oid_add_from_string("Z39.50-APDU", "1.2.840.10003.2");
1191 oid_add_from_string("Z39.50-attributeSet", "1.2.840.10003.3");
1192 oid_add_from_string("Z39.50-diagnostic", "1.2.840.10003.4");
1193 oid_add_from_string("Z39.50-recordSyntax", "1.2.840.10003.5");
1194 oid_add_from_string("Z39.50-resourceReport", "1.2.840.10003.7");
1195 oid_add_from_string("Z39.50-accessControl", "1.2.840.10003.8");
1196 oid_add_from_string("Z39.50-extendedService", "1.2.840.10003.9");
1197 oid_add_from_string("Z39.50-userinfoFormat", "1.2.840.10003.10");
1198 oid_add_from_string("Z39.50-elementSpec", "1.2.840.10003.11");
1199 oid_add_from_string("Z39.50-variantSet", "1.2.840.10003.12");
1200 oid_add_from_string("Z39.50-schema", "1.2.840.10003.13");
1201 oid_add_from_string("Z39.50-tagSet", "1.2.840.10003.14");
1202 oid_add_from_string("Z39.50-negotiation", "1.2.840.10003.15");
1203 oid_add_from_string("Z39.50-query", "1.2.840.10003.16");
1204 /* MARC Record Syntaxes */
1205 oid_add_from_string("UNIMARC","1.2.840.10003.5.1");
1206 oid_add_from_string("INTERMARC","1.2.840.10003.5.2");
1207 oid_add_from_string("CCF","1.2.840.10003.5.3");
1208 oid_add_from_string("MARC21 (formerly USMARC)",Z3950_RECORDSYNTAX_MARC21_OID);
1209 oid_add_from_string("UKMARC","1.2.840.10003.5.11");
1210 oid_add_from_string("NORMARC","1.2.840.10003.5.12");
1211 oid_add_from_string("Librismarc","1.2.840.10003.5.13");
1212 oid_add_from_string("danMARC2","1.2.840.10003.5.14");
1213 oid_add_from_string("Finmarc","1.2.840.10003.5.15");
1214 oid_add_from_string("MAB","1.2.840.10003.5.16");
1215 oid_add_from_string("Canmarc","1.2.840.10003.5.17");
1216 oid_add_from_string("SBN","1.2.840.10003.5.18");
1217 oid_add_from_string("Picamarc","1.2.840.10003.5.19");
1218 oid_add_from_string("Ausmarc","1.2.840.10003.5.20");
1219 oid_add_from_string("Ibermarc","1.2.840.10003.5.21");
1220 oid_add_from_string("Catmarc","1.2.840.10003.5.22");
1221 oid_add_from_string("Malmarc","1.2.840.10003.5.23");
1222 oid_add_from_string("JPmarc","1.2.840.10003.5.24");
1223 oid_add_from_string("SWEMarc","1.2.840.10003.5.25");
1224 oid_add_from_string("SIGLEmarc","1.2.840.10003.5.26");
1225 oid_add_from_string("ISDS/ISSNmarc","1.2.840.10003.5.27");
1226 oid_add_from_string("RUSMarc","1.2.840.10003.5.28");
1227 oid_add_from_string("Hunmarc","1.2.840.10003.5.29");
1228 oid_add_from_string("NACSIS-CATP","1.2.840.10003.5.30");
1229 oid_add_from_string("FINMARC2000","1.2.840.10003.5.31");
1230 oid_add_from_string("MARC21-fin","1.2.840.10003.5.32");
1231 oid_add_from_string("COMARC","1.2.840.10003.5.33");
1232 /* Non-MARC record syntaxes */
1233 oid_add_from_string("Explain","1.2.840.10003.5.100");
1234 oid_add_from_string("Explain with ZSQL","1.2.840.10003.5.100.1");
1235 oid_add_from_string("SUTRS","1.2.840.10003.5.101");
1236 oid_add_from_string("OPAC","1.2.840.10003.5.102");
1237 oid_add_from_string("Summary","1.2.840.10003.5.103");
1238 oid_add_from_string("GRS-0","1.2.840.10003.5.104");
1239 oid_add_from_string("GRS-1","1.2.840.10003.5.105");
1240 oid_add_from_string("ESTaskPackage","1.2.840.10003.5.106");
1241 oid_add_from_string("fragment","1.2.840.10003.5.108");
1242 /* Attribute sets */
1243 oid_add_from_string("bib-1",Z3950_ATSET_BIB1_OID);
1244 oid_add_from_string("exp-1","1.2.840.10003.3.2");
1245 oid_add_from_string("ext-1","1.2.840.10003.3.3");
1246 oid_add_from_string("ccl-1","1.2.840.10003.3.4");
1247 oid_add_from_string("gils","1.2.840.10003.3.5");
1248 oid_add_from_string("stas","1.2.840.10003.3.6");
1249 oid_add_from_string("collections-1","1.2.840.10003.3.7");
1250 oid_add_from_string("cimi-1","1.2.840.10003.3.8");
1251 oid_add_from_string("geo-1","1.2.840.10003.3.9");
1252 oid_add_from_string("ZBIG","1.2.840.10003.3.10");
1253 oid_add_from_string("util","1.2.840.10003.3.11");
1254 oid_add_from_string("xd-1","1.2.840.10003.3.12");
1255 oid_add_from_string("Zthes","1.2.840.10003.3.13");
1256 oid_add_from_string("Fin-1","1.2.840.10003.3.14");
1257 oid_add_from_string("Dan-1","1.2.840.10003.3.15");
1258 oid_add_from_string("Holdings","1.2.840.10003.3.16");
1259 oid_add_from_string("MARC","1.2.840.10003.3.17");
1260 oid_add_from_string("bib-2","1.2.840.10003.3.18");
1261 oid_add_from_string("ZeeRex","1.2.840.10003.3.19");
1262 /* Diagnostic sets */
1263 oid_add_from_string("bib-1-diagnostics",Z3950_DIAGSET_BIB1_OID);
1267 /* MARC routines */
1269 static int
1270 dissect_marc_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
1272 proto_item *record_item, *leader_item,
1273 *directory_item,
1274 *fields_item,
1275 *item;
1276 proto_tree *marc_tree, *leader_tree,
1277 *directory_tree,
1278 *fields_tree;
1279 marc_directory_entry *marc_directory;
1280 unsigned len = tvb_reported_length(tvb);
1281 const uint8_t *marc_value_str;
1282 unsigned record_length = 0,
1283 data_offset = 0,
1284 length_of_field_size,
1285 starting_character_position_size,
1286 directory_entry_len,
1287 directory_entry_count,
1288 dir_index,
1289 offset = 0;
1290 uint32_t marc_value_char;
1292 record_item = proto_tree_add_item(tree, hf_marc_record,
1293 tvb, 0, len, ENC_NA);
1294 marc_tree = proto_item_add_subtree(record_item, ett_marc_record);
1295 if (len < MARC_LEADER_LENGTH) {
1296 expert_add_info_format(pinfo, record_item,
1297 &ei_marc_invalid_record_length,
1298 "MARC record length %d is shorter than leader", len);
1300 leader_item = proto_tree_add_item(marc_tree, hf_marc_leader, tvb, 0,
1301 MARC_LEADER_LENGTH, ENC_NA);
1302 leader_tree = proto_item_add_subtree(leader_item, ett_marc_leader);
1304 marc_value_str = NULL;
1305 item = proto_tree_add_item_ret_string(leader_tree,
1306 hf_marc_leader_length, tvb, offset, 5, ENC_ASCII|ENC_NA,
1307 pinfo->pool,&marc_value_str);
1308 offset += 5;
1310 if (marc_value_str) {
1311 if (isdigit_string(marc_value_str)) {
1312 record_length = (unsigned)strtoul(marc_value_str, NULL, 10);
1314 else {
1315 expert_add_info_format(pinfo, item,
1316 &ei_marc_invalid_value,
1317 "MARC length field '%s' contains invalid characters",
1318 marc_value_str );
1320 if (record_length != len) {
1321 expert_add_info_format(pinfo, item,
1322 &ei_marc_invalid_length,
1323 "MARC length field value %d does not match reported length %d",
1324 record_length, len);
1328 proto_tree_add_item(leader_tree, hf_marc_leader_status, tvb, offset, 1, ENC_ASCII);
1329 offset += 1;
1330 proto_tree_add_item(leader_tree, hf_marc_leader_type, tvb, offset, 1, ENC_ASCII);
1331 offset += 1;
1332 proto_tree_add_item(leader_tree, hf_marc_leader_biblevel, tvb, offset, 1, ENC_ASCII);
1333 offset += 1;
1334 proto_tree_add_item(leader_tree, hf_marc_leader_control, tvb, offset, 1, ENC_ASCII);
1335 offset += 1;
1336 proto_tree_add_item(leader_tree, hf_marc_leader_encoding, tvb, offset, 1, ENC_ASCII);
1337 offset += 1;
1338 marc_value_char = MARC_CHAR_UNINITIALIZED;
1339 item = proto_tree_add_item_ret_uint(leader_tree, hf_marc_leader_indicator_count,
1340 tvb, offset, 1, ENC_ASCII, &marc_value_char);
1341 offset += 1;
1342 if (marc_value_char != MARC_CHAR_UNINITIALIZED) {
1343 if (!marc_isdigit(marc_value_char)) {
1344 expert_add_info_format(pinfo, item, &ei_marc_invalid_value,
1345 "Indicator count '%c' is invalid", marc_value_char);
1347 else {
1348 if (marc_char_to_int(marc_value_char) != 2) {
1349 expert_add_info_format(pinfo, item, &ei_marc_invalid_length,
1350 "MARC21 requires indicator count equal 2, not %d",
1351 marc_char_to_int(marc_value_char));
1356 marc_value_char = MARC_CHAR_UNINITIALIZED;
1357 item = proto_tree_add_item_ret_uint(leader_tree, hf_marc_leader_subfield_count,
1358 tvb, offset, 1, ENC_ASCII, &marc_value_char);
1359 offset += 1;
1360 if (marc_value_char != MARC_CHAR_UNINITIALIZED) {
1361 if (!marc_isdigit(marc_value_char)) {
1362 expert_add_info_format(pinfo, item, &ei_marc_invalid_value,
1363 "Subfield count '%c' is invalid", marc_value_char);
1365 else {
1366 if (marc_char_to_int(marc_value_char) != 2) {
1367 expert_add_info_format(pinfo, item, &ei_marc_invalid_length,
1368 "MARC21 requires subfield count equal 2, not %d",
1369 marc_char_to_int(marc_value_char));
1374 item = proto_tree_add_item_ret_string(leader_tree, hf_marc_leader_data_offset,
1375 tvb, offset, 5, ENC_ASCII|ENC_NA,
1376 pinfo->pool,&marc_value_str);
1377 offset += 5;
1378 if (marc_value_str) {
1379 if (isdigit_string(marc_value_str)) {
1380 data_offset = (unsigned)strtoul(marc_value_str, NULL, 10);
1382 else {
1383 expert_add_info_format(pinfo, item,
1384 &ei_marc_invalid_value,
1385 "MARC data offset field '%s' contains invalid characters",
1386 marc_value_str );
1388 if (data_offset < MARC_LEADER_LENGTH ||
1389 data_offset > record_length) {
1390 expert_add_info_format(pinfo, item,
1391 &ei_marc_invalid_length,
1392 "MARC data offset %d does not lie within record (length %d)",
1393 data_offset, len);
1396 proto_tree_add_item(leader_tree, hf_marc_leader_encoding_level, tvb, offset, 1, ENC_ASCII);
1397 offset += 1;
1398 proto_tree_add_item(leader_tree, hf_marc_leader_descriptive_cataloging, tvb, offset, 1, ENC_ASCII);
1399 offset += 1;
1400 proto_tree_add_item(leader_tree, hf_marc_leader_multipart_level, tvb, offset, 1, ENC_ASCII);
1401 offset += 1;
1402 marc_value_char = MARC_CHAR_UNINITIALIZED;
1403 item = proto_tree_add_item_ret_uint(leader_tree, hf_marc_leader_length_of_field_length,
1404 tvb, offset, 1, ENC_ASCII, &marc_value_char);
1405 offset += 1;
1406 length_of_field_size = 4;
1407 if (marc_value_char != MARC_CHAR_UNINITIALIZED) {
1408 if (!marc_isdigit(marc_value_char)) {
1409 expert_add_info_format(pinfo, item, &ei_marc_invalid_value,
1410 "Length-of field-length '%c' is invalid", marc_value_char);
1412 else {
1413 if (marc_char_to_int(marc_value_char) != 4) {
1414 expert_add_info_format(pinfo, item, &ei_marc_invalid_length,
1415 "MARC21 requires length-of-field equal 4, not %d",
1416 marc_char_to_int(marc_value_char));
1421 marc_value_char = MARC_CHAR_UNINITIALIZED;
1422 item = proto_tree_add_item_ret_uint(leader_tree, hf_marc_leader_starting_character_position_length,
1423 tvb, offset, 1, ENC_ASCII, &marc_value_char);
1424 offset += 1;
1425 starting_character_position_size = 5;
1426 if (marc_value_char != MARC_CHAR_UNINITIALIZED) {
1427 if (!marc_isdigit(marc_value_char)) {
1428 expert_add_info_format(pinfo, item, &ei_marc_invalid_value,
1429 "Starting-character-position length '%c' is invalid", marc_value_char);
1431 else {
1432 if (marc_char_to_int(marc_value_char) != 5) {
1433 expert_add_info_format(pinfo, item, &ei_marc_invalid_length,
1434 "MARC21 requires starting-character-position equal 5, not %d",
1435 marc_char_to_int(marc_value_char));
1440 proto_tree_add_item(leader_tree, hf_marc_leader_implementation_defined_length, tvb, offset, 1, ENC_ASCII);
1441 offset += 1;
1443 /* One position is defined as unused-must-be-zero.
1444 * Don't bother displaying or checking it. */
1445 offset += 1;
1447 /* Process the directory */
1449 directory_entry_len = 3 + length_of_field_size
1450 + starting_character_position_size;
1451 directory_entry_count = ((data_offset - 1) - MARC_LEADER_LENGTH) / directory_entry_len;
1453 marc_directory = (marc_directory_entry *)wmem_alloc0(pinfo->pool,
1454 directory_entry_count * sizeof(marc_directory_entry));
1456 directory_item = proto_tree_add_item(marc_tree, hf_marc_directory,
1457 tvb, offset, data_offset - offset, ENC_NA);
1458 directory_tree = proto_item_add_subtree(directory_item, ett_marc_directory);
1460 dir_index = 0;
1461 /* Minus one for the terminator character */
1462 while (offset < (data_offset - 1)) {
1463 uint32_t tag_value = 0,
1464 length_value = 0,
1465 starting_char_value = 0;
1466 proto_item *length_item;
1467 proto_item *directory_entry_item;
1468 proto_tree *directory_entry_tree;
1470 directory_entry_item = proto_tree_add_item(directory_tree, hf_marc_directory_entry,
1471 tvb, offset, directory_entry_len, ENC_NA);
1472 directory_entry_tree = proto_item_add_subtree(directory_entry_item, ett_marc_directory_entry);
1474 marc_value_str = NULL;
1475 item = proto_tree_add_item_ret_string(directory_entry_tree, hf_marc_directory_entry_tag,
1476 tvb, offset, 3, ENC_ASCII,
1477 pinfo->pool, &marc_value_str);
1478 offset += 3;
1479 if (marc_value_str) {
1480 if (isdigit_string(marc_value_str)) {
1481 tag_value = (unsigned)strtoul(marc_value_str, NULL, 10);
1483 else {
1484 expert_add_info_format(pinfo, item,
1485 &ei_marc_invalid_value,
1486 "MARC directory tag value %d ('%s') contains invalid characters",
1487 dir_index, marc_value_str );
1490 marc_value_str = NULL;
1491 length_item = proto_tree_add_item_ret_string(directory_entry_tree,
1492 hf_marc_directory_entry_length,
1493 tvb, offset, length_of_field_size, ENC_ASCII,
1494 pinfo->pool, &marc_value_str);
1495 offset += length_of_field_size;
1496 if (marc_value_str) {
1497 if (isdigit_string(marc_value_str)) {
1498 length_value = (unsigned)strtoul(marc_value_str, NULL, 10);
1500 else {
1501 expert_add_info_format(pinfo, length_item,
1502 &ei_marc_invalid_value,
1503 "MARC directory length value %d ('%s') contains invalid characters",
1504 dir_index, marc_value_str );
1507 marc_value_str = NULL;
1508 item = proto_tree_add_item_ret_string(directory_entry_tree, hf_marc_directory_entry_starting_position,
1509 tvb, offset, starting_character_position_size, ENC_ASCII,
1510 pinfo->pool, &marc_value_str);
1511 offset += starting_character_position_size;
1512 if (marc_value_str) {
1513 if (isdigit_string(marc_value_str)) {
1514 starting_char_value = (unsigned)strtoul(marc_value_str, NULL, 10);
1516 else {
1517 expert_add_info_format(pinfo, item,
1518 &ei_marc_invalid_value,
1519 "MARC directory entry %d starting char value '%s' contains invalid characters",
1520 dir_index, marc_value_str );
1524 if (starting_char_value >= (record_length - data_offset)) {
1525 expert_add_info_format(pinfo, item,
1526 &ei_marc_invalid_value,
1527 "MARC directory entry %d starting char value %d is outside record size %d",
1528 dir_index, starting_char_value, (record_length - data_offset));
1530 if ((starting_char_value + length_value) >= (record_length - data_offset)) {
1531 expert_add_info_format(pinfo, length_item,
1532 &ei_marc_invalid_value,
1533 "MARC directory entry %d length value %d goes outside record size %d",
1534 dir_index, length_value, (record_length - data_offset));
1536 marc_directory[dir_index].tag = tag_value;
1537 marc_directory[dir_index].length = length_value;
1538 marc_directory[dir_index].starting_character = starting_char_value;
1539 dir_index++;
1541 proto_tree_add_item(directory_tree, hf_marc_directory_terminator,
1542 tvb, offset, 1, ENC_ASCII);
1543 offset += 1;
1545 fields_item = proto_tree_add_item(marc_tree, hf_marc_fields,
1546 tvb, offset, record_length - offset, ENC_NA);
1547 fields_tree = proto_item_add_subtree(fields_item, ett_marc_fields);
1549 for (dir_index = 0; dir_index < directory_entry_count; dir_index++) {
1550 const char *tag_str;
1551 proto_item *field_item;
1552 proto_tree *field_tree;
1554 field_item = proto_tree_add_item(fields_tree, hf_marc_field,
1555 tvb, offset, marc_directory[dir_index].length, ENC_NA);
1556 field_tree = proto_item_add_subtree(field_item, ett_marc_field);
1558 tag_str = try_val_to_str(marc_directory[dir_index].tag, marc_tag_names);
1559 if (tag_str) {
1560 proto_item_append_text(field_item," Tag %03d (%s)",
1561 marc_directory[dir_index].tag, tag_str);
1563 else {
1564 proto_item_append_text(field_item," Tag %03d",
1565 marc_directory[dir_index].tag);
1568 if (marc_directory[dir_index].tag < 10) {
1569 proto_tree_add_item(field_tree, hf_marc_field_control,
1570 tvb, offset, marc_directory[dir_index].length - 1, ENC_ASCII);
1571 offset += marc_directory[dir_index].length - 1;
1572 proto_tree_add_item(field_tree, hf_marc_field_terminator,
1573 tvb, offset, 1, ENC_ASCII);
1574 offset += 1;
1576 else {
1577 unsigned next_offset = offset + marc_directory[dir_index].length - 1;
1578 proto_tree_add_item(field_tree, hf_marc_field_indicator1,
1579 tvb, offset, 1, ENC_ASCII);
1580 offset += 1;
1581 proto_tree_add_item(field_tree, hf_marc_field_indicator2,
1582 tvb, offset, 1, ENC_ASCII);
1583 offset += 1;
1584 do {
1585 int next_subfield;
1586 proto_tree_add_item(field_tree, hf_marc_field_subfield_indicator,
1587 tvb, offset, 1, ENC_ASCII);
1588 offset += 1;
1589 proto_tree_add_item(field_tree, hf_marc_field_subfield_tag,
1590 tvb, offset, 1, ENC_ASCII);
1591 offset += 1;
1592 next_subfield = tvb_find_uint8(tvb, offset, next_offset - offset,
1593 MARC_SUBFIELD_INDICATOR);
1594 if (next_subfield >= 0) {
1595 proto_tree_add_item(field_tree, hf_marc_field_subfield,
1596 tvb, offset, next_subfield - offset, ENC_ASCII);
1597 offset += (next_subfield - offset);
1599 else {
1600 proto_tree_add_item(field_tree, hf_marc_field_subfield,
1601 tvb, offset, next_offset - offset, ENC_ASCII);
1602 offset = next_offset;
1604 } while (offset < next_offset);
1605 proto_tree_add_item(field_tree, hf_marc_field_terminator,
1606 tvb, offset, 1, ENC_ASCII);
1607 offset += 1;
1611 proto_tree_add_item(marc_tree, hf_marc_record_terminator,
1612 tvb, offset, 1, ENC_ASCII);
1613 offset += 1;
1615 if (offset != len) {
1616 expert_add_info_format(pinfo, record_item,
1617 &ei_marc_invalid_record_length,
1618 "MARC record component length %d does not match record length %d",
1619 offset, len);
1622 return len;
1626 * Editor modelines
1628 * Local Variables:
1629 * c-basic-offset: 4
1630 * tab-width: 8
1631 * indent-tabs-mode: nil
1632 * End:
1634 * ex: set shiftwidth=4 tabstop=8 expandtab:
1635 * :indentSize=4:tabSize=8:noTabs=true: