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 <ctype.h>
29#include <memory.h>
30#include <stdio.h>
31#include <string.h>
32
33#include "pcap-int.h"
34
35#include <pcap/namedb.h>
36
37#ifdef HAVE_OS_PROTO_H
38#include "os-proto.h"
39#endif
40
41static inline int skip_space(FILE *);
42static inline int skip_line(FILE *);
43
44/* Hex digit to integer. */
45static inline u_char
46xdtoi(u_char c)
47{
48	if (isdigit(c))
49		return (u_char)(c - '0');
50	else if (islower(c))
51		return (u_char)(c - 'a' + 10);
52	else
53		return (u_char)(c - 'A' + 10);
54}
55
56static inline int
57skip_space(FILE *f)
58{
59	int c;
60
61	do {
62		c = getc(f);
63	} while (isspace(c) && c != '\n');
64
65	return c;
66}
67
68static inline int
69skip_line(FILE *f)
70{
71	int c;
72
73	do
74		c = getc(f);
75	while (c != '\n' && c != EOF);
76
77	return c;
78}
79
80struct pcap_etherent *
81pcap_next_etherent(FILE *fp)
82{
83	register int c, i;
84	u_char d;
85	char *bp;
86	size_t namesize;
87	static struct pcap_etherent e;
88
89	memset((char *)&e, 0, sizeof(e));
90	for (;;) {
91		/* Find addr */
92		c = skip_space(fp);
93		if (c == EOF)
94			return (NULL);
95		if (c == '\n')
96			continue;
97
98		/* If this is a comment, or first thing on line
99		   cannot be Ethernet address, skip the line. */
100		if (!isxdigit(c)) {
101			c = skip_line(fp);
102			if (c == EOF)
103				return (NULL);
104			continue;
105		}
106
107		/* must be the start of an address */
108		for (i = 0; i < 6; i += 1) {
109			d = xdtoi((u_char)c);
110			c = getc(fp);
111			if (c == EOF)
112				return (NULL);
113			if (isxdigit(c)) {
114				d <<= 4;
115				d |= xdtoi((u_char)c);
116				c = getc(fp);
117				if (c == EOF)
118					return (NULL);
119			}
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