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