1/*
2 * Copyright (c) 1990, 1993, 1994, 1995, 1996
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
25
26#include <pcap-types.h>
27
28#include <memory.h>
29#include <stdio.h>
30#include <string.h>
31
32#include "pcap-int.h"
33
34#include <pcap/namedb.h>
35
36#ifdef HAVE_OS_PROTO_H
37#include "os-proto.h"
38#endif
39
40static inline int skip_space(FILE *);
41static inline int skip_line(FILE *);
42
43/* Hex digit to integer. */
44static inline u_char
45xdtoi(u_char c)
46{
47	if (c >= '0' && c <= '9')
48		return (u_char)(c - '0');
49	else if (c >= 'a' && c <= 'f')
50		return (u_char)(c - 'a' + 10);
51	else
52		return (u_char)(c - 'A' + 10);
53}
54
55/*
56 * Skip linear white space (space and tab) and any CRs before LF.
57 * Stop when we hit a non-white-space character or an end-of-line LF.
58 */
59static inline int
60skip_space(FILE *f)
61{
62	int c;
63
64	do {
65		c = getc(f);
66	} while (c == ' ' || c == '\t' || c == '\r');
67
68	return c;
69}
70
71static inline int
72skip_line(FILE *f)
73{
74	int c;
75
76	do
77		c = getc(f);
78	while (c != '\n' && c != EOF);
79
80	return c;
81}
82
83struct pcap_etherent *
84pcap_next_etherent(FILE *fp)
85{
86	register int c, i;
87	u_char d;
88	char *bp;
89	size_t namesize;
90	static struct pcap_etherent e;
91
92	memset((char *)&e, 0, sizeof(e));
93	for (;;) {
94		/* Find addr */
95		c = skip_space(fp);
96		if (c == EOF)
97			return (NULL);
98		if (c == '\n')
99			continue;
100
101		/* If this is a comment, or first thing on line
102		   cannot be Ethernet address, skip the line. */
103		if (!PCAP_ISXDIGIT(c)) {
104			c = skip_line(fp);
105			if (c == EOF)
106				return (NULL);
107			continue;
108		}
109
110		/* must be the start of an address */
111		for (i = 0; i < 6; i += 1) {
112			d = xdtoi((u_char)c);
113			c = getc(fp);
114			if (c == EOF)
115				return (NULL);
116			if (PCAP_ISXDIGIT(c)) {
117				d <<= 4;
118				d |= xdtoi((u_char)c);
119				c = getc(fp);
120				if (c == EOF)
121					return (NULL);
122			}
123			e.addr[i] = d;
124			if (c != ':')
125				break;
126			c = getc(fp);
127			if (c == EOF)
128				return (NULL);
129		}
130
131		/* Must be whitespace */
132		if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
133			c = skip_line(fp);
134			if (c == EOF)
135				return (NULL);
136			continue;
137		}
138		c = skip_space(fp);
139		if (c == EOF)
140			return (NULL);
141
142		/* hit end of line... */
143		if (c == '\n')
144			continue;
145
146		if (c == '#') {
147			c = skip_line(fp);
148			if (c == EOF)
149				return (NULL);
150			continue;
151		}
152
153		/* pick up name */
154		bp = e.name;
155		/* Use 'namesize' to prevent buffer overflow. */
156		namesize = sizeof(e.name) - 1;
157		do {
158			*bp++ = (u_char)c;
159			c = getc(fp);
160			if (c == EOF)
161				return (NULL);
162		} while (c != ' ' && c != '\t' && c != '\r' && c != '\n'
163		    && --namesize != 0);
164		*bp = '\0';
165
166		/* Eat trailing junk */
167		if (c != '\n')
168			(void)skip_line(fp);
169
170		return &e;
171	}
172}
173