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 |
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 |
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 |
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 * |
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 | |