17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * Copyright (C) 1993-2001 by Darren Reed.
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * See the IPFILTER.LICENCE file for details on licencing.
57c478bdstevel@tonic-gate *
67c478bdstevel@tonic-gate * $Id: ipft_sn.c,v 1.7 2003/02/16 02:32:36 darrenr Exp $
77c478bdstevel@tonic-gate */
87c478bdstevel@tonic-gate
97c478bdstevel@tonic-gate/*
107c478bdstevel@tonic-gate * Written to comply with the recent RFC 1761 from Sun.
117c478bdstevel@tonic-gate */
127c478bdstevel@tonic-gate#include "ipf.h"
137c478bdstevel@tonic-gate#include "snoop.h"
147c478bdstevel@tonic-gate#include "ipt.h"
157c478bdstevel@tonic-gate
167c478bdstevel@tonic-gate#if !defined(lint)
177c478bdstevel@tonic-gatestatic const char rcsid[] = "@(#)$Id: ipft_sn.c,v 1.7 2003/02/16 02:32:36 darrenr Exp $";
187c478bdstevel@tonic-gate#endif
197c478bdstevel@tonic-gate
207c478bdstevel@tonic-gatestruct	llc	{
217c478bdstevel@tonic-gate	int	lc_sz;	/* LLC header length */
227c478bdstevel@tonic-gate	int	lc_to;	/* LLC Type offset */
237c478bdstevel@tonic-gate	int	lc_tl;	/* LLC Type length */
247c478bdstevel@tonic-gate};
257c478bdstevel@tonic-gate
267c478bdstevel@tonic-gate/*
277c478bdstevel@tonic-gate * While many of these maybe the same, some do have different header formats
287c478bdstevel@tonic-gate * which make this useful.
297c478bdstevel@tonic-gate */
307c478bdstevel@tonic-gatestatic	struct	llc	llcs[SDL_MAX+1] = {
317c478bdstevel@tonic-gate	{ 0, 0, 0 },	/* SDL_8023 */
327c478bdstevel@tonic-gate	{ 0, 0, 0 },	/* SDL_8024 */
337c478bdstevel@tonic-gate	{ 0, 0, 0 },	/* SDL_8025 */
347c478bdstevel@tonic-gate	{ 0, 0, 0 },	/* SDL_8026 */
357c478bdstevel@tonic-gate	{ 14, 12, 2 },	/* SDL_ETHER */
367c478bdstevel@tonic-gate	{ 0, 0, 0 },	/* SDL_HDLC */
377c478bdstevel@tonic-gate	{ 0, 0, 0 },	/* SDL_CHSYNC */
387c478bdstevel@tonic-gate	{ 0, 0, 0 },	/* SDL_IBMCC */
397c478bdstevel@tonic-gate	{ 0, 0, 0 },	/* SDL_FDDI */
407c478bdstevel@tonic-gate	{ 0, 0, 0 },	/* SDL_OTHER */
417c478bdstevel@tonic-gate};
427c478bdstevel@tonic-gate
437c478bdstevel@tonic-gatestatic	int	snoop_open __P((char *));
447c478bdstevel@tonic-gatestatic	int	snoop_close __P((void));
457c478bdstevel@tonic-gatestatic	int	snoop_readip __P((char *, int, char **, int *));
467c478bdstevel@tonic-gate
477c478bdstevel@tonic-gatestatic	int	sfd = -1, s_type = -1;
487c478bdstevel@tonic-gatestatic	int	snoop_read_rec __P((struct snooppkt *));
497c478bdstevel@tonic-gate
507c478bdstevel@tonic-gatestruct	ipread	snoop = { snoop_open, snoop_close, snoop_readip, 0 };
517c478bdstevel@tonic-gate
527c478bdstevel@tonic-gate
537c478bdstevel@tonic-gatestatic	int	snoop_open(fname)
547c478bdstevel@tonic-gatechar	*fname;
557c478bdstevel@tonic-gate{
567c478bdstevel@tonic-gate	struct	snoophdr sh;
577c478bdstevel@tonic-gate	int	fd;
587c478bdstevel@tonic-gate	int s_v;
597c478bdstevel@tonic-gate
607c478bdstevel@tonic-gate	if (sfd != -1)
617c478bdstevel@tonic-gate		return sfd;
627c478bdstevel@tonic-gate
637c478bdstevel@tonic-gate	if (!strcmp(fname, "-"))
647c478bdstevel@tonic-gate		fd = 0;
657c478bdstevel@tonic-gate	else if ((fd = open(fname, O_RDONLY)) == -1)
667c478bdstevel@tonic-gate		return -1;
677c478bdstevel@tonic-gate
687c478bdstevel@tonic-gate	if (read(fd, (char *)&sh, sizeof(sh)) != sizeof(sh))
697c478bdstevel@tonic-gate		return -2;
707c478bdstevel@tonic-gate
717c478bdstevel@tonic-gate	s_v = (int)ntohl(sh.s_v);
727c478bdstevel@tonic-gate	s_type = (int)ntohl(sh.s_type);
737c478bdstevel@tonic-gate
747c478bdstevel@tonic-gate	if (s_v != SNOOP_VERSION ||
757c478bdstevel@tonic-gate	    s_type < 0 || s_type > SDL_MAX) {
767c478bdstevel@tonic-gate		(void) close(fd);
777c478bdstevel@tonic-gate		return -2;
787c478bdstevel@tonic-gate	}
797c478bdstevel@tonic-gate
807c478bdstevel@tonic-gate	sfd = fd;
817c478bdstevel@tonic-gate	printf("opened snoop file %s:\n", fname);
827c478bdstevel@tonic-gate	printf("\tid: %8.8s version: %d type: %d\n", sh.s_id, s_v, s_type);
837c478bdstevel@tonic-gate
847c478bdstevel@tonic-gate	return fd;
857c478bdstevel@tonic-gate}
867c478bdstevel@tonic-gate
877c478bdstevel@tonic-gate
887c478bdstevel@tonic-gatestatic	int	snoop_close()
897c478bdstevel@tonic-gate{
907c478bdstevel@tonic-gate	return close(sfd);
917c478bdstevel@tonic-gate}
927c478bdstevel@tonic-gate
937c478bdstevel@tonic-gate
947c478bdstevel@tonic-gate/*
957c478bdstevel@tonic-gate * read in the header (and validate) which should be the first record
967c478bdstevel@tonic-gate * in a snoop file.
977c478bdstevel@tonic-gate */
987c478bdstevel@tonic-gatestatic	int	snoop_read_rec(rec)
997c478bdstevel@tonic-gatestruct	snooppkt *rec;
1007c478bdstevel@tonic-gate{
1017c478bdstevel@tonic-gate	int	n, plen, ilen;
1027c478bdstevel@tonic-gate
1037c478bdstevel@tonic-gate	if (read(sfd, (char *)rec, sizeof(*rec)) != sizeof(*rec))
1047c478bdstevel@tonic-gate		return -2;
1057c478bdstevel@tonic-gate
1067c478bdstevel@tonic-gate	ilen = (int)ntohl(rec->sp_ilen);
1077c478bdstevel@tonic-gate	plen = (int)ntohl(rec->sp_plen);
1087c478bdstevel@tonic-gate	if (ilen > plen || plen < sizeof(*rec))
1097c478bdstevel@tonic-gate		return -2;
1107c478bdstevel@tonic-gate
1117c478bdstevel@tonic-gate	plen -= sizeof(*rec);
1127c478bdstevel@tonic-gate	n = MIN(plen, ilen);
1137c478bdstevel@tonic-gate	if (!n || n < 0)
1147c478bdstevel@tonic-gate		return -3;
1157c478bdstevel@tonic-gate
1167c478bdstevel@tonic-gate	return plen;
1177c478bdstevel@tonic-gate}
1187c478bdstevel@tonic-gate
1197c478bdstevel@tonic-gate
1207c478bdstevel@tonic-gate#ifdef	notyet
1217c478bdstevel@tonic-gate/*
1227c478bdstevel@tonic-gate * read an entire snoop packet record.  only the data part is copied into
1237c478bdstevel@tonic-gate * the available buffer, with the number of bytes copied returned.
1247c478bdstevel@tonic-gate */
1257c478bdstevel@tonic-gatestatic	int	snoop_read(buf, cnt)
1267c478bdstevel@tonic-gatechar	*buf;
1277c478bdstevel@tonic-gateint	cnt;
1287c478bdstevel@tonic-gate{
1297c478bdstevel@tonic-gate	struct	snooppkt rec;
1307c478bdstevel@tonic-gate	static	char	*bufp = NULL;
1317c478bdstevel@tonic-gate	int	i, n;
1327c478bdstevel@tonic-gate
1337c478bdstevel@tonic-gate	if ((i = snoop_read_rec(&rec)) <= 0)
1347c478bdstevel@tonic-gate		return i;
1357c478bdstevel@tonic-gate
1367c478bdstevel@tonic-gate	if (!bufp)
1377c478bdstevel@tonic-gate		bufp = malloc(i);
1387c478bdstevel@tonic-gate	else
1397c478bdstevel@tonic-gate		bufp = realloc(bufp, i);
1407c478bdstevel@tonic-gate
1417c478bdstevel@tonic-gate	if (read(sfd, bufp, i) != i)
1427c478bdstevel@tonic-gate		return -2;
1437c478bdstevel@tonic-gate
1447c478bdstevel@tonic-gate	n = MIN(i, cnt);
1457c478bdstevel@tonic-gate	bcopy(bufp, buf, n);
1467c478bdstevel@tonic-gate	return n;
1477c478bdstevel@tonic-gate}
1487c478bdstevel@tonic-gate#endif
1497c478bdstevel@tonic-gate
1507c478bdstevel@tonic-gate
1517c478bdstevel@tonic-gate/*
1527c478bdstevel@tonic-gate * return only an IP packet read into buf
1537c478bdstevel@tonic-gate */
1547c478bdstevel@tonic-gatestatic	int	snoop_readip(buf, cnt, ifn, dir)
1557c478bdstevel@tonic-gatechar	*buf, **ifn;
1567c478bdstevel@tonic-gateint	cnt, *dir;
1577c478bdstevel@tonic-gate{
1587c478bdstevel@tonic-gate	static	char	*bufp = NULL;
1597c478bdstevel@tonic-gate	struct	snooppkt rec;
1607c478bdstevel@tonic-gate	struct	llc	*l;
1617c478bdstevel@tonic-gate	char	ty[4], *s;
1627c478bdstevel@tonic-gate	int	i, n;
1637c478bdstevel@tonic-gate
1647c478bdstevel@tonic-gate	do {
1657c478bdstevel@tonic-gate		if ((i = snoop_read_rec(&rec)) <= 0)
1667c478bdstevel@tonic-gate			return i;
1677c478bdstevel@tonic-gate
1687c478bdstevel@tonic-gate		if (!bufp)
1697c478bdstevel@tonic-gate			bufp = malloc(i);
1707c478bdstevel@tonic-gate		else
1717c478bdstevel@tonic-gate			bufp = realloc(bufp, i);
1727c478bdstevel@tonic-gate		s = bufp;
1737c478bdstevel@tonic-gate
1747c478bdstevel@tonic-gate		if (read(sfd, s, i) != i)
1757c478bdstevel@tonic-gate			return -2;
1767c478bdstevel@tonic-gate
1777c478bdstevel@tonic-gate		l = &llcs[s_type];
1787c478bdstevel@tonic-gate		i -= l->lc_to;
1797c478bdstevel@tonic-gate		s += l->lc_to;
1807c478bdstevel@tonic-gate		/*
1817c478bdstevel@tonic-gate		 * XXX - bogus assumption here on the part of the time field
1827c478bdstevel@tonic-gate		 * that it won't be greater than 4 bytes and the 1st two will
1837c478bdstevel@tonic-gate		 * have the values 8 and 0 for IP.  Should be a table of
1847c478bdstevel@tonic-gate		 * these too somewhere.  Really only works for SDL_ETHER.
1857c478bdstevel@tonic-gate		 */
1867c478bdstevel@tonic-gate		bcopy(s, ty, l->lc_tl);
1877c478bdstevel@tonic-gate	} while (ty[0] != 0x8 && ty[1] != 0);
1887c478bdstevel@tonic-gate
1897c478bdstevel@tonic-gate	i -= l->lc_tl;
1907c478bdstevel@tonic-gate	s += l->lc_tl;
1917c478bdstevel@tonic-gate	n = MIN(i, cnt);
1927c478bdstevel@tonic-gate	bcopy(s, buf, n);
1937c478bdstevel@tonic-gate
1947c478bdstevel@tonic-gate	return n;
1957c478bdstevel@tonic-gate}
196