SunScreen 3.x Log File Format Specification

Abstract

This document describes the format of SunScreen firewall log files. These files are created by the ssadm log get and ssadm log get_and_clear commands, which exctract the data from the internal SunScreen log being generated by the firewall.

Scope

The log file format changed with the SunScreen EFS 3.0 release. Earlier SunScreen products use a slightly different format. The format described in this document is used by SunScreen EFS 3.0 and i-Planet SunScreen 3.1.

Future SunScreen products may use different file formats for log data.

WARNING The detailed format of SunScreen log files and any methods of interpreting these files other than the ssadm logdump command are NOT supported interfaces of any SunScreen product. Use of the information in this document is at your own risk and there is NO guarantee that future SunScreen products will provide backward compatibility with this information.

File Structure

The data stream output by ssadm log get or ssadm log get_and_clear has the following structure.

SunScreen Log File structure
file header 24 bytes
log record
log record
...

File Header

The file header is 24 bytes long and consists of two fields.

file header
magic: "SunScreen new log\x0A\x0A\x00" 20 bytes
version number 4 bytes*

* Note: all multi-byte integer fields described in this document are unsigned and stored in network byte order.

Log Record

Each log record has the following form.

log record
record header 24 bytes
record body

Each record header is 24 bytes long:

record header
magic: 54 86 95 23 4 bytes
type 2 bytes*
length 2 bytes*
sequence 4 bytes*
flags 4 bytes*
time seconds 4 bytes*
time microseconds 4 bytes*

The format of the record body varies depending on the record type indicated in the record header. These record types are defined:

record types
type code
LOG_TYPE_PACKET 1
LOG_TYPE_TCP_SESSION 2
LOG_TYPE_UDP_SESSION 3
LOG_TYPE_IP_SESSION 4
LOG_TYPE_XTND 8

PACKET record body

A PACKET record body has a 24 byte header followed by an actual packet:

PACKET record body
packet length 4 bytes*
saved length 4 bytes*
time seconds 4 bytes*
time microseconds 4 bytes*
receive interface name 16 bytes
MAC type 4 bytes*
MAC header length 4 bytes*
log reason 4 bytes*
actual packet (or truncated portion) saved length bytes*

TCP_SESSION record body

A TCP_SESSION record body is 44 bytes long:

TCP_SESSION record body
src address 4 bytes
dst address 4 bytes
src port 2 bytes*
dst port 2 bytes*
session_id 4 bytes*
bytes fwd 4 bytes*
bytes rev 4 bytes*
pkts fwd 4 bytes*
pkts rev 4 bytes*
start time seconds 4 bytes*
end time seconds 4 bytes*
state 4 bytes*

UDP_SESSION record body

A UDP_SESSION record body is 40 bytes long:

UDP_SESSION record body
src address 4 bytes
dst address 4 bytes
src port 2 bytes*
dst port 2 bytes*
session_id 4 bytes*
bytes fwd 4 bytes*
bytes rev 4 bytes*
pkts fwd 4 bytes*
pkts rev 4 bytes*
start time seconds 4 bytes*
end time seconds 4 bytes*

IP_SESSION record body

An IP_SESSION record body is 40 bytes long:

IP_SESSION record body
src address 4 bytes
dst address 4 bytes
protocol 4 bytes*
session_id 4 bytes*
bytes fwd 4 bytes*
bytes rev 4 bytes*
pkts fwd 4 bytes*
pkts rev 4 bytes*
start time seconds 4 bytes*
end time seconds 4 bytes*

XTND record body

An XTND record body has a 64 byte header followed by variable length data:

XTND record body
src address 4 bytes
dst address 4 bytes
src port 2 bytes*
dst port 2 bytes*
session_id 4 bytes*
protocol 1 byte
level 1 byte
priority 1 byte
flags 1 byte
reserved 12 bytes
application name 32 bytes
extended log data

Sample program

Here is a very simple piece of code which will parse a SunScreen 3.x log file.

#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <inttypes.h>

#define LOGMAGIC	"SunScreen new log\n\n"	/* 20 bytes including NUL */
#define LOGMAGICLEN	(sizeof LOGMAGIC)

#define SCREEN_LOG_MARKER	0x54869523

#define LOG_TYPE_PACKET		1
#define LOG_TYPE_TCP_SESSION	2
#define LOG_TYPE_UDP_SESSION	3
#define LOG_TYPE_IP_SESSION	4
#define	LOG_TYPE_XTND		8	/* auth/app level extensions */

struct screen_logfile_header
{
	char filemagic[20];
	uint32_t version;
};

struct screen_log_header
{
	uint32_t marker;
	uint16_t type;
	uint16_t length;
	uint32_t sequence;
	uint32_t flags;
	uint32_t time_sec;
	uint32_t time_usec;
};

struct screen_packet
{
	uint32_t pktlen;
	uint32_t savelen;
	uint32_t time_sec;
	uint32_t time_usec;
	char intfc[16];
	uint32_t mac_type;
	uint32_t mac_length;
	uint32_t why;
};

struct screen_tcp_session
{
	struct in_addr ip_src;
	struct in_addr ip_dst;
	uint16_t srcport;
	uint16_t dstport;
 	uint32_t session_id;
	uint32_t bytes_fwd;
        uint32_t bytes_rev;
        uint32_t pkts_fwd;
        uint32_t pkts_rev;
        uint32_t time_start;
        uint32_t time_last;
	uint32_t state;
};

struct screen_udp_session
{
	struct in_addr ip_src;
	struct in_addr ip_dst;
	uint16_t srcport;
	uint16_t dstport;
	uint32_t session_id;
        uint32_t bytes_fwd;
        uint32_t bytes_rev;
        uint32_t pkts_fwd;
        uint32_t pkts_rev;
        uint32_t time_start;
        uint32_t time_last;
};

struct screen_ip_session
{
	struct in_addr ip_src;
	struct in_addr ip_dst;
	uint32_t  protocol;
 	uint32_t session_id;
	uint32_t bytes_fwd;
        uint32_t bytes_rev;
        uint32_t pkts_fwd;
        uint32_t pkts_rev;
        uint32_t time_start;
        uint32_t time_last;
};

struct screen_xtnd
{
	struct in_addr ip_src;
	struct in_addr ip_dst;
	uint16_t srcport;
	uint16_t dstport;
	uint32_t session_id;
	u_char ip_proto;
	u_char level;
	u_char prio;
	u_char xflgs;
	u_char res[12];
	char appname[32];
};

static const char * const screen_error_table[] =
{
	"deny rule or no pass rule",
	"no connection",
	"out of memory",
	"too many conns",
	"invalid port",
	"bad format",
	"bad direction",
	"too many rsps",
	"too short",
	"bad protocol",
	"no port map",
	"bad port map",
	"bad NIS proto",
	"bad interface",
	"bad policy",
	"bad identity",
	"bad source addr",
	"stale policy",
	"frag too big",
	"illegal frag overlap",
	"src cert not in group",
	"cert not in rule",
	"attempt to encrypt a decrypted packet",
	"no state associated with policy",
	"stale skip policy",
};

static const char *log_reason_string(unsigned int why)
{
	static char why_string[128];

	if (why >= 256)
	{
		why -= 256;
		if (why <= (sizeof(screen_error_table) / sizeof(int)))
			return screen_error_table[why];
		else
		{
			sprintf(why_string, "reason=%d", why + 256);
			return why_string;
		}
	}
	else
	{
		return "pass";
	}
}

static void dump_packet(unsigned char *packetbuf, size_t len,
			struct screen_packet *pr)
{
	struct ip *ip = (struct ip *)(packetbuf + ntohl(pr->mac_length));
	char proto[64];
	if (ip->ip_p == IPPROTO_TCP)
		strcpy(proto, "TCP");
	else if (ip->ip_p == IPPROTO_UDP)
		strcpy(proto, "UDP");
	else
		sprintf(proto, "IP protocol %u", ip->ip_p);

	printf("%-4.16s %-20.20s %15s %-15s %s\n",
	       pr->intfc,
	       log_reason_string(ntohl(pr->why)),
	       strdup(inet_ntoa(ip->ip_src)),
	       strdup(inet_ntoa(ip->ip_dst)),
	       proto);
}

int main(int argc, char *argv[])
{
	struct screen_logfile_header fh;	/* file header */
	struct screen_log_header rh;		/* record header */
	struct screen_packet pr;		/* packet record */
	struct screen_tcp_session tsr;		/* TCP session record */
	struct screen_udp_session usr;		/* UDP session record */
	struct screen_ip_session isr;		/* IP session record */
	struct screen_xtnd xr;			/* XTND record */
	unsigned char packetbuf[65536];
	off_t off;
	int n;

	n = read(0, &fh, sizeof fh);
	if (n != sizeof fh ||
	    memcmp(fh.filemagic, LOGMAGIC, LOGMAGICLEN) != 0 ||
	    ntohl(fh.version) != 300)
	{
		fprintf(stderr, "Not a SunScreen 3.x log file\n");
		return 1;
	}

	while (1)
	{
		time_t t;
		size_t len;
		off = lseek(0, 0L, SEEK_CUR);
		n = read(0, &rh, sizeof rh);
		if (n == 0)
		{
			puts("End of file");
			return 0;
		}
		if (n != sizeof rh ||
		    ntohl(rh.marker) != SCREEN_LOG_MARKER)
		{
			fprintf(stderr, "Invalid log file record at 0x%X\n",
				off);
			return 1;
		}
		t = ntohl(rh.time_sec);
		fprintf(stdout, "%06lX %.24s ", off, ctime(&t));
		switch (ntohs(rh.type))
		{
		case LOG_TYPE_PACKET:
			read(0, &pr, sizeof pr);
			len = htonl(pr.savelen);
			read(0, packetbuf, len);
			dump_packet(packetbuf, len, &pr);
			len += sizeof pr;
			if (len < ntohl(rh.length))
				lseek(0, (off_t)ntohl(rh.length)-len, SEEK_CUR);
			break;
		case LOG_TYPE_TCP_SESSION:
			read(0, &tsr, sizeof tsr);
			puts("TCP session record");
			break;
		case LOG_TYPE_UDP_SESSION:
			read(0, &usr, sizeof usr);
			puts("UDP session record");
			break;
		case LOG_TYPE_IP_SESSION:
			read(0, &isr, sizeof isr);
			puts("IP session record");
			break;
		case LOG_TYPE_XTND:
			lseek(0, (off_t)ntohl(rh.length), SEEK_CUR);
			puts("XTND record");
			break;
		default:
			lseek(0, (off_t)ntohl(rh.length), SEEK_CUR);
			printf("Unknown record type %u\n",
			       (unsigned int)ntohs(rh.type));
			break;
		}
	}
}
Hosted by www.Geocities.ws

1