xref: /openbsd-src/lib/libpcap/etherent.c (revision 19fef81560be48509a81878548a6da7da6687cb4)
1 /*	$OpenBSD: etherent.c,v 1.10 2024/04/05 18:01:56 deraadt 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/types.h>
25 
26 #include <ctype.h>
27 #include <stdio.h>
28 #include <string.h>
29 
30 #include "pcap-int.h"
31 
32 #include <pcap-namedb.h>
33 #ifdef HAVE_OS_PROTO_H
34 #include "os-proto.h"
35 #endif
36 
37 static __inline int xdtoi(int);
38 static __inline int skip_space(FILE *);
39 static __inline int skip_line(FILE *);
40 
41 /* Hex digit to integer. */
42 static __inline int
xdtoi(int c)43 xdtoi(int c)
44 {
45 	if (isdigit(c))
46 		return c - '0';
47 	else if (islower(c))
48 		return c - 'a' + 10;
49 	else
50 		return c - 'A' + 10;
51 }
52 
53 static __inline int
skip_space(FILE * f)54 skip_space(FILE *f)
55 {
56 	int c;
57 
58 	do {
59 		c = getc(f);
60 	} while (isspace(c) && c != '\n');
61 
62 	return c;
63 }
64 
65 static __inline int
skip_line(FILE * f)66 skip_line(FILE *f)
67 {
68 	int c;
69 
70 	do
71 		c = getc(f);
72 	while (c != '\n' && c != EOF);
73 
74 	return c;
75 }
76 
77 struct pcap_etherent *
pcap_next_etherent(FILE * fp)78 pcap_next_etherent(FILE *fp)
79 {
80 	int c, d, i;
81 	char *bp;
82 	static struct pcap_etherent e;
83 
84 	memset((char *)&e, 0, sizeof(e));
85 	do {
86 		/* Find addr */
87 		c = skip_space(fp);
88 		if (c == '\n')
89 			continue;
90 
91 		/* If this is a comment, or first thing on line
92 		   cannot be etehrnet address, skip the line. */
93 		if (!isxdigit(c)) {
94 			c = skip_line(fp);
95 			continue;
96 		}
97 
98 		/* must be the start of an address */
99 		for (i = 0; i < 6; i += 1) {
100 			d = xdtoi(c);
101 			c = getc(fp);
102 			if (isxdigit(c)) {
103 				d <<= 4;
104 				d |= xdtoi(c);
105 				c = getc(fp);
106 			}
107 			e.addr[i] = d;
108 			if (c != ':')
109 				break;
110 			c = getc(fp);
111 		}
112 		if (c == EOF)
113 			break;
114 
115 		/* Must be whitespace */
116 		if (!isspace(c)) {
117 			c = skip_line(fp);
118 			continue;
119 		}
120 		c = skip_space(fp);
121 
122 		/* hit end of line... */
123 		if (c == '\n')
124 			continue;
125 
126 		if (c == '#') {
127 			c = skip_line(fp);
128 			continue;
129 		}
130 
131 		/* pick up name */
132 		bp = e.name;
133 		/* Use 'd' to prevent buffer overflow. */
134 		d = sizeof(e.name) - 1;
135 		do {
136 			*bp++ = c;
137 			c = getc(fp);
138 		} while (!isspace(c) && c != EOF && --d > 0);
139 		*bp = '\0';
140 
141 		/* Eat trailing junk */
142 		if (c != '\n')
143 			(void)skip_line(fp);
144 
145 		return &e;
146 
147 	} while (c != EOF);
148 
149 	return (NULL);
150 }
151