133965Sjdp/*
2218822Sdim * Copyright (c) 1990, 1993, 1994, 1995, 1996
3218822Sdim *	The Regents of the University of California.  All rights reserved.
433965Sjdp *
5218822Sdim * Redistribution and use in source and binary forms, with or without
633965Sjdp * modification, are permitted provided that: (1) source code distributions
7218822Sdim * retain the above copyright notice and this paragraph in its entirety, (2)
8218822Sdim * distributions including binary code include the above copyright notice and
9218822Sdim * this paragraph in its entirety in the documentation or other materials
10218822Sdim * provided with the distribution, and (3) all advertising materials mentioning
1133965Sjdp * features or use of this software display the following acknowledgement:
12218822Sdim * ``This product includes software developed by the University of California,
13218822Sdim * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14218822Sdim * the University nor the names of its contributors may be used to endorse
15218822Sdim * or promote products derived from this software without specific prior
1633965Sjdp * written permission.
17218822Sdim * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18218822Sdim * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19218822Sdim * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20218822Sdim */
2133965Sjdp
2277298Sobrien#ifdef HAVE_CONFIG_H
2338889Sjdp#include <config.h>
2438889Sjdp#endif
2538889Sjdp
2638889Sjdp#include <pcap-types.h>
2777298Sobrien
2833965Sjdp#include <ctype.h>
2933965Sjdp#include <memory.h>
3033965Sjdp#include <stdio.h>
3133965Sjdp#include <string.h>
3233965Sjdp
3377298Sobrien#include "pcap-int.h"
34218822Sdim
3533965Sjdp#include <pcap/namedb.h>
3633965Sjdp
3733965Sjdp#ifdef HAVE_OS_PROTO_H
3877298Sobrien#include "os-proto.h"
3933965Sjdp#endif
4033965Sjdp
4133965Sjdpstatic inline int skip_space(FILE *);
4233965Sjdpstatic inline int skip_line(FILE *);
4333965Sjdp
4477298Sobrien/* Hex digit to integer. */
4533965Sjdpstatic inline u_char
4633965Sjdpxdtoi(u_char c)
4733965Sjdp{
48218822Sdim	if (isdigit(c))
4933965Sjdp		return (u_char)(c - '0');
5033965Sjdp	else if (islower(c))
5133965Sjdp		return (u_char)(c - 'a' + 10);
5233965Sjdp	else
53218822Sdim		return (u_char)(c - 'A' + 10);
5433965Sjdp}
5533965Sjdp
5633965Sjdpstatic inline int
5733965Sjdpskip_space(FILE *f)
5833965Sjdp{
5933965Sjdp	int c;
6033965Sjdp
6133965Sjdp	do {
6233965Sjdp		c = getc(f);
6333965Sjdp	} while (isspace(c) && c != '\n');
6433965Sjdp
6533965Sjdp	return c;
66218822Sdim}
67218822Sdim
68218822Sdimstatic inline int
6933965Sjdpskip_line(FILE *f)
7033965Sjdp{
7133965Sjdp	int c;
7233965Sjdp
7333965Sjdp	do
7433965Sjdp		c = getc(f);
7533965Sjdp	while (c != '\n' && c != EOF);
7633965Sjdp
77130561Sobrien	return c;
78218822Sdim}
7933965Sjdp
8033965Sjdpstruct pcap_etherent *
8133965Sjdppcap_next_etherent(FILE *fp)
8233965Sjdp{
8333965Sjdp	register int c, i;
8433965Sjdp	u_char d;
8533965Sjdp	char *bp;
8633965Sjdp	size_t namesize;
8733965Sjdp	static struct pcap_etherent e;
8833965Sjdp
8933965Sjdp	memset((char *)&e, 0, sizeof(e));
9033965Sjdp	for (;;) {
91218822Sdim		/* Find addr */
9233965Sjdp		c = skip_space(fp);
9333965Sjdp		if (c == EOF)
9433965Sjdp			return (NULL);
9533965Sjdp		if (c == '\n')
9633965Sjdp			continue;
97218822Sdim
98218822Sdim		/* If this is a comment, or first thing on line
99218822Sdim		   cannot be Ethernet address, skip the line. */
100218822Sdim		if (!isxdigit(c)) {
101218822Sdim			c = skip_line(fp);
102218822Sdim			if (c == EOF)
103218822Sdim				return (NULL);
104218822Sdim			continue;
105218822Sdim		}
10633965Sjdp
10733965Sjdp		/* must be the start of an address */
10833965Sjdp		for (i = 0; i < 6; i += 1) {
10933965Sjdp			d = xdtoi((u_char)c);
11033965Sjdp			c = getc(fp);
11133965Sjdp			if (c == EOF)
11233965Sjdp				return (NULL);
11333965Sjdp			if (isxdigit(c)) {
11433965Sjdp				d <<= 4;
11533965Sjdp				d |= xdtoi((u_char)c);
116218822Sdim				c = getc(fp);
11733965Sjdp				if (c == EOF)
118130561Sobrien					return (NULL);
11933965Sjdp			}
120			e.addr[i] = d;
121			if (c != ':')
122				break;
123			c = getc(fp);
124			if (c == EOF)
125				return (NULL);
126		}
127
128		/* Must be whitespace */
129		if (!isspace(c)) {
130			c = skip_line(fp);
131			if (c == EOF)
132				return (NULL);
133			continue;
134		}
135		c = skip_space(fp);
136		if (c == EOF)
137			return (NULL);
138
139		/* hit end of line... */
140		if (c == '\n')
141			continue;
142
143		if (c == '#') {
144			c = skip_line(fp);
145			if (c == EOF)
146				return (NULL);
147			continue;
148		}
149
150		/* pick up name */
151		bp = e.name;
152		/* Use 'namesize' to prevent buffer overflow. */
153		namesize = sizeof(e.name) - 1;
154		do {
155			*bp++ = (u_char)c;
156			c = getc(fp);
157			if (c == EOF)
158				return (NULL);
159		} while (!isspace(c) && --namesize != 0);
160		*bp = '\0';
161
162		/* Eat trailing junk */
163		if (c != '\n')
164			(void)skip_line(fp);
165
166		return &e;
167	}
168}
169