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