kerberos: remember account details from dissect_krb5_PAC_UPN_DNS_INFO on EncTicketPar...
[wireshark-sm.git] / wiretap / log3gpp.c
blob3fad6390bafc2fd9d64823539ce8d604d345db94
1 /* log3gpp.c
2 * Routines encapsulating/dumping 3gpp protocol logs.
3 * The purpose of this format is to be able to log the 3GPP protocol stack on a mobile phone.
4 * Copyright 2008, Vincent Helfre
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 #define WS_LOG_DOMAIN LOG_DOMAIN_WIRETAP
17 #include <errno.h>
18 #include <string.h>
19 #include <stdlib.h>
21 #include "wtap-int.h"
22 #include "file_wrappers.h"
24 #include "log3gpp.h"
26 #define MAX_FIRST_LINE_LENGTH 200
27 #define MAX_TIMESTAMP_LINE_LENGTH 100
28 #define MAX_LINE_LENGTH 65536
29 #define MAX_TIMESTAMP_LEN 32
30 #define MAX_SECONDS_CHARS 16
31 #define MAX_SUBSECOND_DECIMALS 4
32 #define MAX_PROTOCOL_NAME 64
33 #define MAX_PROTOCOL_PAR_STRING 64
35 /* 'u' or 'd' of a packet as read from file */
36 typedef enum packet_direction_t
38 uplink,
39 downlink
40 } packet_direction_t;
42 typedef struct {
43 time_t start_secs;
44 uint32_t start_usecs;
45 } log3gpp_t;
47 int first_packet_offset;
48 char firstline[MAX_FIRST_LINE_LENGTH];
49 char secondline[MAX_TIMESTAMP_LINE_LENGTH];
50 int secondline_length;
52 /***********************************************************/
53 /* Transient data used for parsing */
55 /* 'Magic number' at start of 3gpp log files. */
56 static const char log3gpp_magic[] = "3GPP protocols transcript";
58 /* Protocol name of the packet that the packet was captured at */
59 static char protocol_name[MAX_PROTOCOL_NAME+1];
61 /* Optional string parameter giving info required for the protocol dissector */
62 static char protocol_parameters[MAX_PROTOCOL_PAR_STRING+1];
63 /************************************************************/
64 /* Functions called from wiretap core */
65 static bool log3gpp_read( wtap* wth, wtap_rec* rec, Buffer* buf,
66 int* err, char** err_info, int64_t* data_offset);
67 static bool log3gpp_seek_read(struct wtap *wth, int64_t seek_off,
68 wtap_rec *rec,
69 Buffer *buf,
70 int *err, char **err_info);
72 /************************************************************/
73 /* Private helper functions */
74 static bool read_new_line(FILE_T fh, int* length,
75 char* buf, size_t bufsize, int* err,
76 char** err_info);
78 static bool parse_line(char* linebuff, int line_length, int *seconds, int *useconds,
79 long *data_offset,
80 int *data_chars,
81 packet_direction_t *direction,
82 bool *is_text_data);
83 static int write_stub_header(unsigned char *frame_buffer, char *timestamp_string,
84 packet_direction_t direction);
85 static unsigned char hex_from_char(char c);
86 /*not used static char char_from_hex(unsigned char hex);*/
88 static bool get_file_time_stamp(const char* linebuff, time_t *secs, uint32_t *usecs);
91 static int log3gpp_file_type_subtype = -1;
93 void register_log3gpp(void);
95 /***************************************************************************/
96 /* Free log3gpp-specific capture info from file that was open for reading */
97 /***************************************************************************/
98 static void log3gpp_close(wtap* wth)
100 log3gpp_t* log3gpp = (log3gpp_t*)wth->priv;
101 /* Also free this capture info */
102 g_free(log3gpp);
103 wth->priv = NULL;
106 /********************************************/
107 /* Open file (for reading) */
108 /********************************************/
109 wtap_open_return_val
110 log3gpp_open(wtap *wth, int *err, char **err_info _U_)
112 time_t timestamp;
113 uint32_t usecs;
114 log3gpp_t *log3gpp;
115 wtap_open_return_val retval;
116 /* Buffer to hold a single text line read from the file */
117 static char linebuff[MAX_LINE_LENGTH];
118 int firstline_length = 0;
120 /* Clear errno before reading from the file */
121 errno = 0;
123 /********************************************************************/
124 /* First line needs to contain at least as many characters as magic */
126 /*ws_warning("Open file"); */
128 if (!read_new_line(wth->fh, &firstline_length, linebuff,
129 sizeof linebuff, err, err_info)) {
130 if (*err != 0 && *err != WTAP_ERR_SHORT_READ) {
131 return WTAP_OPEN_ERROR;
133 else {
134 return WTAP_OPEN_NOT_MINE;
138 if (((size_t)firstline_length < strlen(log3gpp_magic)) ||
139 firstline_length >= MAX_FIRST_LINE_LENGTH)
141 retval = WTAP_OPEN_NOT_MINE;
142 return retval;
145 /* This file is not for us if it doesn't match our signature */
146 if (memcmp(log3gpp_magic, linebuff, strlen(log3gpp_magic)) != 0)
148 retval = WTAP_OPEN_NOT_MINE;
149 return retval;
152 /***********************************************************/
153 /* Second line contains file timestamp */
154 if (!read_new_line(wth->fh, &secondline_length,
155 linebuff, sizeof linebuff, err, err_info)) {
156 if (*err != 0 && *err != WTAP_ERR_SHORT_READ) {
157 return WTAP_OPEN_ERROR;
159 else {
160 return WTAP_OPEN_NOT_MINE;
164 first_packet_offset = firstline_length + secondline_length;
166 if ((secondline_length >= MAX_TIMESTAMP_LINE_LENGTH) ||
167 (!get_file_time_stamp(linebuff, &timestamp, &usecs)))
169 /* Give up if file time line wasn't valid */
170 retval = WTAP_OPEN_NOT_MINE;
171 return retval;
174 /* Allocate struct and fill in timestamp (netmon re used)*/
175 log3gpp = g_new(log3gpp_t, 1);
176 log3gpp->start_secs = timestamp;
177 log3gpp->start_usecs = usecs;
178 wth->priv = (void *)log3gpp;
180 /************************************************************/
181 /* File is for us. Fill in details so packets can be read */
183 /* Set our file type */
184 wth->file_type_subtype = log3gpp_file_type_subtype;
186 /* Use our own encapsulation to send all packets to our stub dissector */
187 wth->file_encap = WTAP_ENCAP_LOG_3GPP;
189 /* Callbacks for reading operations */
190 wth->subtype_read = log3gpp_read;
191 wth->subtype_seek_read = log3gpp_seek_read;
192 wth->subtype_close = log3gpp_close;
194 /* Choose microseconds (have 4 decimal places...) */
195 wth->file_tsprec = WTAP_TSPREC_USEC;
197 *err = errno;
200 * Add an IDB; we don't know how many interfaces were
201 * involved, so we just say one interface, about which
202 * we only know the link-layer type, snapshot length,
203 * and time stamp resolution.
205 wtap_add_generated_idb(wth);
207 retval = WTAP_OPEN_MINE;
208 return retval;
212 /**************************************************/
213 /* Read packet function. */
214 /* Look for and read the next usable packet */
215 /* - return true and details if found */
216 /**************************************************/
217 bool log3gpp_read(wtap* wth, wtap_rec* rec, Buffer* buf,
218 int* err, char** err_info, int64_t* data_offset)
220 int64_t offset = file_tell(wth->fh);
221 static char linebuff[MAX_LINE_LENGTH + 1];
222 long dollar_offset;
223 packet_direction_t direction;
224 bool is_text_data;
225 log3gpp_t *log3gpp = (log3gpp_t *)wth->priv;
227 /* Search for a line containing a usable packet */
228 while (1)
230 int line_length, seconds, useconds, data_chars;
231 int64_t this_offset = offset;
233 /* Are looking for first packet after 2nd line */
234 if (file_tell(wth->fh) == 0)
236 this_offset += (int64_t)first_packet_offset +1+1;
239 /* Clear errno before reading from the file */
240 errno = 0;
242 /* Read a new line from file into linebuff */
243 if (!read_new_line(wth->fh, &line_length, linebuff,
244 sizeof linebuff, err, err_info)) {
245 if (*err != 0) {
246 return false; /* error */
248 /* No more lines can be read, so quit. */
249 break;
252 /* Try to parse the line as a frame record */
253 if (parse_line(linebuff, line_length, &seconds, &useconds,
254 &dollar_offset,
255 &data_chars,
256 &direction,
257 &is_text_data))
259 unsigned char *frame_buffer;
260 int n;
261 int stub_offset = 0;
262 char timestamp_string[MAX_TIMESTAMP_LEN+1];
263 /*not used int64_t *pkey = NULL;*/
265 snprintf(timestamp_string, 32, "%d.%04d", seconds, useconds/100);
267 /* All packets go to 3GPP protocol stub dissector */
268 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_LOG_3GPP;
269 rec->rec_type = REC_TYPE_PACKET;
270 rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
271 rec->presence_flags = WTAP_HAS_TS;
273 /* Set data_offset to the beginning of the line we're returning.
274 This will be the seek_off parameter when this frame is re-read.
276 *data_offset = this_offset;
278 /* Fill in timestamp (capture base + packet offset) */
279 rec->ts.secs = log3gpp->start_secs + seconds;
280 if ((log3gpp->start_usecs + useconds) >= 1000000)
282 rec->ts.secs++;
284 rec->ts.nsecs =
285 ((log3gpp->start_usecs + useconds) % 1000000) *1000;
287 if (!is_text_data)
289 /* Get buffer pointer ready */
290 ws_buffer_assure_space(buf,
291 strlen(timestamp_string)+1 + /* timestamp */
292 strlen(protocol_name)+1 + /* Protocol name */
293 1 + /* direction */
294 (size_t)(data_chars/2));
296 frame_buffer = ws_buffer_start_ptr(buf);
297 /*********************/
298 /* Write stub header */
299 stub_offset = write_stub_header(frame_buffer, timestamp_string,
300 direction);
302 /* Binary data length is half bytestring length + stub header */
303 rec->rec_header.packet_header.len = data_chars/2 + stub_offset;
304 rec->rec_header.packet_header.caplen = data_chars/2 + stub_offset;
305 /********************************/
306 /* Copy packet data into buffer */
307 for (n=0; n <= data_chars; n+=2)
309 frame_buffer[stub_offset + n/2] = (hex_from_char(linebuff[dollar_offset+n]) << 4) |
310 hex_from_char(linebuff[dollar_offset+n+1]);
312 *err = errno = 0;
313 return true;
315 else
317 /* Get buffer pointer ready */
318 ws_buffer_assure_space(buf,
319 strlen(timestamp_string)+1 + /* timestamp */
320 strlen(protocol_name)+1 + /* Protocol name */
321 1 + /* direction */
322 data_chars);
323 frame_buffer = ws_buffer_start_ptr(buf);
325 /*********************/
326 /* Write stub header */
327 stub_offset = write_stub_header(frame_buffer, timestamp_string,
328 direction);
330 /* Binary data length is bytestring length + stub header */
331 rec->rec_header.packet_header.len = data_chars + stub_offset;
332 rec->rec_header.packet_header.caplen = data_chars + stub_offset;
334 /* do not convert the ascii char */
335 memcpy(&frame_buffer[stub_offset],&linebuff[dollar_offset],data_chars);
336 frame_buffer[stub_offset+data_chars-1]= '\0';
337 *err = errno = 0;
338 return true;
343 /* No packet details to return... */
344 *err = errno;
345 return false;
349 /**************************************************/
350 /* Read & seek function. */
351 /**************************************************/
352 static bool
353 log3gpp_seek_read(wtap *wth, int64_t seek_off,
354 wtap_rec *rec _U_ , Buffer *buf,
355 int *err, char **err_info)
357 long dollar_offset;
358 static char linebuff[MAX_LINE_LENGTH + 1];
359 packet_direction_t direction;
360 int seconds, useconds, data_chars;
361 bool is_text_data;
362 log3gpp_t* log3gpp = (log3gpp_t*)wth->priv;
363 int length = 0;
364 unsigned char *frame_buffer;
366 /* Reset errno */
367 *err = errno = 0;
369 /* Seek to beginning of packet */
370 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
372 return false;
375 /* Re-read whole line (this really should succeed) */
376 if (!read_new_line(wth->random_fh, &length, linebuff,
377 sizeof linebuff, err, err_info)) {
378 return false;
381 /* Try to parse this line again (should succeed as re-reading...) */
382 if (parse_line(linebuff, length, &seconds, &useconds,
383 &dollar_offset,
384 &data_chars,
385 &direction,
386 &is_text_data))
388 int n;
389 int stub_offset = 0;
390 char timestamp_string[32];
391 snprintf(timestamp_string, 32, "%d.%04d", seconds, useconds/100);
393 /* Make sure all packets go to log3gpp dissector */
394 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_LOG_3GPP;
395 rec->rec_type = REC_TYPE_PACKET;
396 rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
397 rec->presence_flags = WTAP_HAS_TS;
399 /* Fill in timestamp (capture base + packet offset) */
400 rec->ts.secs = log3gpp->start_secs + seconds;
401 if ((log3gpp->start_usecs + useconds) >= 1000000)
403 rec->ts.secs++;
405 rec->ts.nsecs =
406 ((log3gpp->start_usecs + useconds) % 1000000) * 1000;
408 /*********************/
409 /* Write stub header */
410 ws_buffer_assure_space(buf,
411 strlen(timestamp_string)+1 + /* timestamp */
412 strlen(protocol_name)+1 + /* Protocol name */
413 1 + /* direction */
414 data_chars);
415 frame_buffer = ws_buffer_start_ptr(buf);
416 stub_offset = write_stub_header(frame_buffer, timestamp_string,
417 direction);
419 if (!is_text_data)
421 /********************************/
422 /* Copy packet data into buffer */
423 for (n=0; n <= data_chars; n+=2)
425 frame_buffer[stub_offset + n/2] = (hex_from_char(linebuff[dollar_offset+n]) << 4) |
426 hex_from_char(linebuff[dollar_offset+n+1]);
428 *err = errno = 0;
429 return true;
431 else
433 /* do not convert the ascii char */
434 memcpy(&frame_buffer[stub_offset],&linebuff[dollar_offset],data_chars);
435 frame_buffer[stub_offset+data_chars-1] = '\0';
436 *err = errno = 0;
437 return true;
441 /* If get here, must have failed */
442 *err = errno;
443 *err_info = ws_strdup_printf("prot 3gpp: seek_read failed to read/parse "
444 "line at position %" PRId64,
445 seek_off);
446 return false;
449 /****************************/
450 /* Private helper functions */
451 /****************************/
453 /**********************************************************************/
454 /* Read a new line from the file, starting at offset. */
455 /* - writes data to static var linebuff */
456 /* - on return 'offset' will point to the next position to read from */
457 /* - return true if this read is successful */
458 /**********************************************************************/
459 static bool
460 read_new_line(FILE_T fh, int* length,
461 char* linebuff, size_t linebuffsize, int* err, char** err_info)
463 /* Read in a line */
464 int64_t pos_before = file_tell(fh);
466 if (file_gets(linebuff, (int)linebuffsize - 1, fh) == NULL) {
467 /* No characters found, or error */
468 *err = file_error(fh, err_info);
469 return false;
472 /* Set length (avoiding strlen()) and offset.. */
473 *length = (int)(file_tell(fh) - pos_before);
475 /* ...but don't want to include newline in line length */
476 if (*length > 0 && linebuff[*length - 1] == '\n') {
477 linebuff[*length - 1] = '\0';
478 *length = *length - 1;
480 /* Nor do we want '\r' (as will be written when log is created on windows) */
481 if (*length > 0 && linebuff[*length - 1] == '\r') {
482 linebuff[*length - 1] = '\0';
483 *length = *length - 1;
486 return true;
490 /**********************************************************************/
491 /* Parse a line from buffer, by identifying: */
492 /* - timestamp */
493 /* - data position and length */
494 /* Return true if this packet looks valid and can be displayed */
495 /**********************************************************************/
496 bool parse_line(char* linebuff, int line_length, int *seconds, int *useconds,
497 long *data_offset, int *data_chars,
498 packet_direction_t *direction,
499 bool *is_text_data)
501 int n = 0;
502 int protocol_chars = 0;
503 int prot_option_chars = 0;
504 char seconds_buff[MAX_SECONDS_CHARS+1];
505 int seconds_chars;
506 char subsecond_decimals_buff[MAX_SUBSECOND_DECIMALS+1];
507 int subsecond_decimals_chars;
509 /*********************************************************************/
510 /* Find and read the timestamp */
511 /*********************************************************************/
512 /* Now scan to the next digit, which should be the start of the timestamp */
513 for (; !g_ascii_isdigit((unsigned char)linebuff[n]) && (n < line_length); n++);
514 if (n >= line_length)
516 return false;
519 /* Seconds */
520 for (seconds_chars = 0;
521 (linebuff[n] != '.') &&
522 (seconds_chars <= MAX_SECONDS_CHARS) &&
523 (n < line_length);
524 n++, seconds_chars++)
526 if (!g_ascii_isdigit((unsigned char)linebuff[n]))
528 /* Found a non-digit before decimal point. Fail */
529 return false;
531 seconds_buff[seconds_chars] = linebuff[n];
533 if (seconds_chars > MAX_SECONDS_CHARS || n >= line_length)
535 /* Didn't fit in buffer. Fail rather than use truncated */
536 return false;
539 /* Convert found value into number */
540 seconds_buff[seconds_chars] = '\0';
542 /* Already know they are digits, so avoid expense of ws_strtoi32() */
543 int multiplier = 1;
544 *seconds = 0;
545 for (int d = seconds_chars - 1; d >= 0; d--) {
546 *seconds += ((seconds_buff[d] - '0') * multiplier);
547 multiplier *= 10;
550 /* The decimal point must follow the last of the seconds digits */
551 if (linebuff[n] != '.')
553 return false;
555 /* Skip it */
556 n++;
558 /* Subsecond decimal digits (expect 4-digit accuracy) */
559 for (subsecond_decimals_chars = 0;
560 (linebuff[n] != ' ') && (subsecond_decimals_chars < MAX_SUBSECOND_DECIMALS) && (n < line_length);
561 n++, subsecond_decimals_chars++)
563 if (!g_ascii_isdigit((unsigned char)linebuff[n]))
565 return false;
567 subsecond_decimals_buff[subsecond_decimals_chars] = linebuff[n];
570 if (subsecond_decimals_chars > MAX_SUBSECOND_DECIMALS || n >= line_length)
572 /* More numbers than expected - give up */
573 return false;
576 /* Convert found value into microseconds */
577 subsecond_decimals_buff[subsecond_decimals_chars] = '\0';
578 /* Already know they are digits, so avoid expense of ws_strtoi32() */
579 *useconds = ((subsecond_decimals_buff[0] - '0') * 100000) +
580 ((subsecond_decimals_buff[1] - '0') * 10000) +
581 ((subsecond_decimals_buff[2] - '0') * 1000) +
582 ((subsecond_decimals_buff[3] - '0') * 100);
584 /* Space character must follow end of timestamp */
585 if (linebuff[n] != ' ')
587 return false;
589 n++;
591 /*********************************************************************/
592 /* Find and read protocol name */
593 /*********************************************************************/
594 for (protocol_chars = 0;
595 (linebuff[n] != ' ') && (protocol_chars < MAX_PROTOCOL_NAME) && (n < line_length);
596 n++, protocol_chars++)
598 if (!g_ascii_isalnum((unsigned char)linebuff[n]) && linebuff[n] != '_' && linebuff[n] != '.' && linebuff[n] != '-')
600 return false;
602 protocol_name[protocol_chars] = linebuff[n];
604 if (protocol_chars == MAX_PROTOCOL_NAME || n >= line_length)
606 /* If doesn't fit, fail rather than truncate */
607 return false;
609 protocol_name[protocol_chars] = '\0';
611 /* Space char must follow protocol name */
612 if (linebuff[n] != ' ')
614 return false;
616 /* Skip it */
617 n++;
619 /* Scan ahead to the next space */
620 for (; (!g_ascii_isalnum((unsigned char)linebuff[n])) && (n < line_length); n++);
621 if (n >= line_length)
623 return false;
627 if (strcmp(protocol_name,"TXT") == 0)
629 *direction = uplink;
630 *data_offset = n;
631 *data_chars = line_length - n;
632 *is_text_data = true;
634 else
636 /* Next character gives direction of message (must be 'u' or 'd') */
637 if (linebuff[n] == 'u')
639 *direction = uplink;
641 else if (linebuff[n] == 'd')
643 *direction = downlink;
645 else
647 return false;
649 n++;
651 /* Now skip ahead to find start of data (marked by '$') */
652 for (; (n <= line_length) && (linebuff[n] != '$') && (prot_option_chars <= MAX_PROTOCOL_PAR_STRING);
653 n++,prot_option_chars++)
655 protocol_parameters[prot_option_chars] = linebuff[n];
657 protocol_parameters[prot_option_chars] = '\0';
658 if (prot_option_chars == MAX_PROTOCOL_PAR_STRING || n >= line_length)
660 /* If doesn't fit, fail rather than truncate */
661 return false;
664 /* Skip it */
665 n++;
667 /* Set offset to data start within line */
668 *data_offset = n;
670 /* Set number of chars that comprise the hex string protocol data */
671 *data_chars = line_length - n;
673 *is_text_data = false;
675 return true;
678 /*****************************************************************/
679 /* Write the stub info to the data buffer while reading a packet */
680 /*****************************************************************/
681 int write_stub_header(unsigned char *frame_buffer, char *timestamp_string,
682 packet_direction_t direction)
684 int stub_offset = 0;
686 /* Timestamp within file */
687 (void) g_strlcpy((char*)&frame_buffer[stub_offset], timestamp_string, MAX_TIMESTAMP_LEN+1);
688 stub_offset += (int)(strlen(timestamp_string) + 1);
690 /* Protocol name */
691 (void) g_strlcpy((char*)&frame_buffer[stub_offset], protocol_name, MAX_PROTOCOL_NAME+1);
692 stub_offset += (int)(strlen(protocol_name) + 1);
694 /* Direction */
695 frame_buffer[stub_offset] = direction;
696 stub_offset++;
698 /* Option string (might be string of length 0) */
699 (void) g_strlcpy((char*)&frame_buffer[stub_offset], protocol_parameters,MAX_PROTOCOL_PAR_STRING+1);
700 stub_offset += (int)(strlen(protocol_parameters) + 1);
701 return stub_offset;
705 /********************************************************/
706 /* Return hex nibble equivalent of hex string character */
707 /********************************************************/
708 unsigned char hex_from_char(char c)
710 if ((c >= '0') && (c <= '9'))
712 return c - '0';
715 if ((c >= 'a') && (c <= 'f'))
717 return 0x0a + (c - 'a');
720 if ((c >= 'A') && (c <= 'F'))
722 return 0x0a + (c - 'A');
724 /* Not a valid hex string character */
725 return 0xff;
729 /********************************************************/
730 /* Return character corresponding to hex nibble value */
731 /********************************************************/
732 /*char char_from_hex(unsigned char hex)
734 static char hex_lookup[16] =
735 { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
737 if (hex > 15)
739 return '?';
742 return hex_lookup[hex];
745 /************************************************************************/
746 /* Parse year, month, day, hour, minute, seconds out of formatted line. */
747 /* Set secs and usecs as output */
748 /* Return false if no valid time can be read */
749 /************************************************************************/
750 bool get_file_time_stamp(const char* linebuff, time_t *secs, uint32_t *usecs)
752 int n;
753 struct tm tm;
754 #define MAX_MONTH_LETTERS 9
755 char month[MAX_MONTH_LETTERS+1];
757 int day, year, hour, minute, second;
758 int scan_found;
760 /* If line longer than expected, file is probably not correctly formatted */
761 if (strlen(linebuff) > MAX_TIMESTAMP_LINE_LENGTH)
763 return false;
766 /**************************************************************/
767 /* First is month. Read until get a space following the month */
768 for (n=0; (n < MAX_MONTH_LETTERS) && (linebuff[n] != ' '); n++)
770 month[n] = linebuff[n];
772 month[n] = '\0';
774 if (strcmp(month, "January" ) == 0) tm.tm_mon = 0;
775 else if (strcmp(month, "February" ) == 0) tm.tm_mon = 1;
776 else if (strcmp(month, "March" ) == 0) tm.tm_mon = 2;
777 else if (strcmp(month, "April" ) == 0) tm.tm_mon = 3;
778 else if (strcmp(month, "May" ) == 0) tm.tm_mon = 4;
779 else if (strcmp(month, "June" ) == 0) tm.tm_mon = 5;
780 else if (strcmp(month, "July" ) == 0) tm.tm_mon = 6;
781 else if (strcmp(month, "August" ) == 0) tm.tm_mon = 7;
782 else if (strcmp(month, "September") == 0) tm.tm_mon = 8;
783 else if (strcmp(month, "October" ) == 0) tm.tm_mon = 9;
784 else if (strcmp(month, "November" ) == 0) tm.tm_mon = 10;
785 else if (strcmp(month, "December" ) == 0) tm.tm_mon = 11;
786 else
788 /* Give up if not found a properly-formatted date */
789 return false;
791 /* Skip space char */
792 n++;
794 /********************************************************/
795 /* Scan for remaining numerical fields */
796 scan_found = sscanf(linebuff+n, "%d, %d %d:%d:%d.%u",
797 &day, &year, &hour, &minute, &second, usecs);
798 if (scan_found != 6)
800 /* Give up if not all found */
801 return false;
804 /******************************************************/
805 /* Fill in remaining fields and return it in a time_t */
806 tm.tm_year = year - 1900;
807 tm.tm_mday = day;
808 tm.tm_hour = hour;
809 tm.tm_min = minute;
810 tm.tm_sec = second;
811 tm.tm_isdst = -1; /* daylight saving time info not known */
813 /* Get seconds from this time */
814 *secs = mktime(&tm);
816 /* Multiply 4 digits given to get micro-seconds */
817 *usecs = *usecs * 100;
819 return true;
822 static const struct supported_block_type log3gpp_blocks_supported[] = {
824 * We support packet blocks, with no comments or other options.
826 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
829 static const struct file_type_subtype_info log3gpp_info = {
830 "3GPP Log", "3gpp_log", "*.log", NULL,
831 true, BLOCKS_SUPPORTED(log3gpp_blocks_supported),
832 NULL, NULL, NULL
835 void register_log3gpp(void)
837 log3gpp_file_type_subtype = wtap_register_file_type_subtype(&log3gpp_info);
840 * Register name for backwards compatibility with the
841 * wtap_filetypes table in Lua.
843 wtap_register_backwards_compatibility_lua_name("LOG_3GPP",
844 log3gpp_file_type_subtype);
848 * Editor modelines - https://www.wireshark.org/tools/modelines.html
850 * Local variables:
851 * c-basic-offset: 4
852 * tab-width: 8
853 * indent-tabs-mode: nil
854 * End:
856 * vi: set shiftwidth=4 tabstop=8 expandtab:
857 * :indentSize=4:tabSize=8:noTabs=true: