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