xref: /netbsd/external/bsd/libpcap/dist/etherent.c (revision e1375535)
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