1 /* $NetBSD: etherent.c,v 1.6 2024/09/02 15:33:36 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.6 2024/09/02 15:33:36 christos Exp $");
26
27 #include <config.h>
28
29 #include <pcap-types.h>
30
31 #include <memory.h>
32 #include <stdio.h>
33 #include <string.h>
34
35 #include "pcap-int.h"
36
37 #include <pcap/namedb.h>
38
39 #include "thread-local.h"
40
41 #ifdef HAVE_OS_PROTO_H
42 #include "os-proto.h"
43 #endif
44
45 static inline int skip_space(FILE *);
46 static inline int skip_line(FILE *);
47
48 /* Hex digit to integer. */
49 static inline u_char
xdtoi(u_char c)50 xdtoi(u_char c)
51 {
52 if (c >= '0' && c <= '9')
53 return (u_char)(c - '0');
54 else if (c >= 'a' && c <= 'f')
55 return (u_char)(c - 'a' + 10);
56 else
57 return (u_char)(c - 'A' + 10);
58 }
59
60 /*
61 * Skip linear white space (space and tab) and any CRs before LF.
62 * Stop when we hit a non-white-space character or an end-of-line LF.
63 */
64 static inline int
skip_space(FILE * f)65 skip_space(FILE *f)
66 {
67 int c;
68
69 do {
70 c = getc(f);
71 } while (c == ' ' || c == '\t' || c == '\r');
72
73 return c;
74 }
75
76 static inline int
skip_line(FILE * f)77 skip_line(FILE *f)
78 {
79 int c;
80
81 do
82 c = getc(f);
83 while (c != '\n' && c != EOF);
84
85 return c;
86 }
87
88 struct pcap_etherent *
pcap_next_etherent(FILE * fp)89 pcap_next_etherent(FILE *fp)
90 {
91 register int c, i;
92 u_char d;
93 char *bp;
94 size_t namesize;
95 static thread_local struct pcap_etherent e;
96
97 memset((char *)&e, 0, sizeof(e));
98 for (;;) {
99 /* Find addr */
100 c = skip_space(fp);
101 if (c == EOF)
102 return (NULL);
103 if (c == '\n')
104 continue;
105
106 /* If this is a comment, or first thing on line
107 cannot be Ethernet address, skip the line. */
108 if (!PCAP_ISXDIGIT(c)) {
109 c = skip_line(fp);
110 if (c == EOF)
111 return (NULL);
112 continue;
113 }
114
115 /* must be the start of an address */
116 for (i = 0; i < 6; i += 1) {
117 d = xdtoi((u_char)c);
118 c = getc(fp);
119 if (c == EOF)
120 return (NULL);
121 if (PCAP_ISXDIGIT(c)) {
122 d <<= 4;
123 d |= xdtoi((u_char)c);
124 c = getc(fp);
125 if (c == EOF)
126 return (NULL);
127 }
128 e.addr[i] = d;
129 if (c != ':')
130 break;
131 c = getc(fp);
132 if (c == EOF)
133 return (NULL);
134 }
135
136 /* Must be whitespace */
137 if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
138 c = skip_line(fp);
139 if (c == EOF)
140 return (NULL);
141 continue;
142 }
143 c = skip_space(fp);
144 if (c == EOF)
145 return (NULL);
146
147 /* hit end of line... */
148 if (c == '\n')
149 continue;
150
151 if (c == '#') {
152 c = skip_line(fp);
153 if (c == EOF)
154 return (NULL);
155 continue;
156 }
157
158 /* pick up name */
159 bp = e.name;
160 /* Use 'namesize' to prevent buffer overflow. */
161 namesize = sizeof(e.name) - 1;
162 do {
163 *bp++ = (u_char)c;
164 c = getc(fp);
165 if (c == EOF)
166 return (NULL);
167 } while (c != ' ' && c != '\t' && c != '\r' && c != '\n'
168 && --namesize != 0);
169 *bp = '\0';
170
171 /* Eat trailing junk */
172 if (c != '\n')
173 (void)skip_line(fp);
174
175 return &e;
176 }
177 }
178