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