Logcat: Add support for conversion from Exported PDU

Exported PDU may contains (Binary) Logcat, so it is possible to
"export" logcat binary from it.

Change-Id: Ic6607126e739ea3972b46c2bf19f064597d4e970
Reviewed-on: https://code.wireshark.org/review/3001
Petri-Dish: Michal Labedzki <michal.labedzki@tieto.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michal Labedzki <michal.labedzki@tieto.com>
Tested-by: Michal Labedzki <michal.labedzki@tieto.com>
This commit is contained in:
Michal Labedzki 2014-07-10 13:11:41 +02:00
parent a760a7db66
commit ccbf373e49
1 changed files with 115 additions and 8 deletions

View File

@ -228,6 +228,82 @@ static gint detect_version(wtap *wth, int *err, gchar **err_info)
return -1;
}
static gint buffered_detect_version(const guint8 *pd)
{
struct logger_entry *log_entry;
struct logger_entry_v2 *log_entry_v2;
gint version;
guint8 *msg_payload;
guint8 *msg_part;
guint8 *msg_end;
guint16 msg_len;
log_entry_v2 = (struct logger_entry_v2 *) pd;
log_entry = (struct logger_entry *) pd;
/* must contain at least priority and two nulls as separator */
if (log_entry->len < 3)
return -1;
/* payload length may not exceed the maximum payload size */
if (log_entry->len > LOGGER_ENTRY_MAX_PAYLOAD)
return -1;
/* cannot rely on __pad being 0 for v1, use heuristics to find out what
* version is in use. First assume the smallest msg. */
for (version = 1; version <= 2; ++version) {
if (version == 1) {
msg_payload = log_entry->msg;
} else if (version == 2) {
/* v2 is 4 bytes longer */
msg_payload = log_entry_v2->msg;
if (log_entry_v2->hdr_size != sizeof(*log_entry_v2))
continue;
}
/* A v2 msg has a 32-bit userid instead of v1 priority */
if (get_priority(msg_payload[0]) == '?')
continue;
/* Is there a terminating '\0' for the tag? */
msg_part = (guint8 *) memchr(msg_payload, '\0', log_entry->len - 1);
if (msg_part == NULL)
continue;
/* if msg is '\0'-terminated, is it equal to the payload len? */
++msg_part;
msg_len = log_entry->len - (msg_part - msg_payload);
msg_end = (guint8 *) memchr(msg_part, '\0', msg_len);
/* is the end of the buffer (-1) equal to the end of msg? */
if (msg_end && (msg_payload + log_entry->len - 1 != msg_end))
continue;
return version;
}
return -1;
}
static gint exported_pdu_length(const guint8 *pd) {
guint16 *tag;
guint16 *tag_length;
gint length = 0;
tag = (guint16 *) pd;
while(GINT16_FROM_BE(*tag)) {
tag_length = (guint16 *) (pd + 2);
length += 2 + 2 + GINT16_FROM_BE(*tag_length);
pd += 2 + 2 + GINT16_FROM_BE(*tag_length);
tag = (guint16 *) pd;
}
length += 2 + 2;
return length;
}
static gboolean logcat_read_packet(struct logcat_phdr *logcat, FILE_T fh,
struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
{
@ -357,7 +433,7 @@ int logcat_dump_can_write_encap(int encap)
if (encap == WTAP_ENCAP_PER_PACKET)
return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
if (encap != WTAP_ENCAP_LOGCAT)
if (encap != WTAP_ENCAP_LOGCAT && encap != WTAP_ENCAP_WIRESHARK_UPPER_PDU)
return WTAP_ERR_UNSUPPORTED_ENCAP;
return 0;
@ -367,16 +443,29 @@ static gboolean logcat_binary_dump(wtap_dumper *wdh,
const struct wtap_pkthdr *phdr,
const guint8 *pd, int *err)
{
int caplen;
/* We can only write packet records. */
if (phdr->rec_type != REC_TYPE_PACKET) {
*err = WTAP_ERR_REC_TYPE_UNSUPPORTED;
return FALSE;
}
if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
caplen = phdr->caplen;
/* Skip EXPORTED_PDU*/
if (wdh->encap == WTAP_ENCAP_WIRESHARK_UPPER_PDU) {
gint skipped_length;
skipped_length = exported_pdu_length(pd);
pd += skipped_length;
caplen -= skipped_length;
}
if (!wtap_dump_file_write(wdh, pd, caplen, err))
return FALSE;
wdh->bytes_dumped += phdr->caplen;
wdh->bytes_dumped += caplen;
return TRUE;
}
@ -388,6 +477,7 @@ gboolean logcat_binary_dump_open(wtap_dumper *wdh, int *err)
switch (wdh->encap) {
case WTAP_ENCAP_LOGCAT:
case WTAP_ENCAP_WIRESHARK_UPPER_PDU:
wdh->tsprecision = WTAP_FILE_TSPREC_USEC;
break;
@ -406,8 +496,8 @@ static gboolean logcat_dump_text(wtap_dumper *wdh,
gchar *buf;
gint length;
gchar priority;
const struct logger_entry *log_entry = (struct logger_entry *) pd;
const struct logger_entry_v2 *log_entry_v2 = (struct logger_entry_v2 *) pd;
const struct logger_entry *log_entry;
const struct logger_entry_v2 *log_entry_v2;
gint payload_length;
const gchar *tag;
gint32 pid;
@ -419,7 +509,7 @@ static gboolean logcat_dump_text(wtap_dumper *wdh,
gchar *log;
gchar *log_part;
gchar *log_next;
const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
gint logcat_version;
const struct dumper_t *dumper = (const struct dumper_t *) wdh->priv;
/* We can only write packet records. */
@ -428,6 +518,23 @@ static gboolean logcat_dump_text(wtap_dumper *wdh,
return FALSE;
}
/* Skip EXPORTED_PDU*/
if (wdh->encap == WTAP_ENCAP_WIRESHARK_UPPER_PDU) {
gint skipped_length;
skipped_length = exported_pdu_length(pd);
pd += skipped_length;
logcat_version = buffered_detect_version(pd);
} else {
const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
logcat_version = pseudo_header->logcat.version;
}
log_entry = (struct logger_entry *) pd;
log_entry_v2 = (struct logger_entry_v2 *) pd;
payload_length = GINT32_FROM_LE(log_entry->len);
pid = GINT32_FROM_LE(log_entry->pid);
tid = GINT32_FROM_LE(log_entry->tid);
@ -435,12 +542,12 @@ static gboolean logcat_dump_text(wtap_dumper *wdh,
milliseconds = GINT32_FROM_LE(log_entry->nsec) / 1000000;
/* msg: <prio:1><tag:N>\0<msg:N>\0 with N >= 0, last \0 can be missing */
if (pseudo_header->logcat.version == 1) {
if (logcat_version == 1) {
priority = get_priority(log_entry->msg[0]);
tag = log_entry->msg + 1;
msg_pre_skip = 1 + (gint) strlen(tag) + 1;
msg_begin = log_entry->msg + msg_pre_skip;
} else if (pseudo_header->logcat.version == 2) {
} else if (logcat_version == 2) {
priority = get_priority(log_entry_v2->msg[0]);
tag = log_entry_v2->msg + 1;
msg_pre_skip = 1 + (gint) strlen(tag) + 1;