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
46 static inline int skip_space(FILE *);
47 static inline int skip_line(FILE *);
48
49 /* Hex digit to integer. */
50 static inline u_char
xdtoi(u_char c)51 xdtoi(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
61 static inline int
skip_space(FILE * f)62 skip_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
73 static inline int
skip_line(FILE * f)74 skip_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
85 struct pcap_etherent *
pcap_next_etherent(FILE * fp)86 pcap_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