1 /* $NetBSD: etherent.c,v 1.6 2024/09/02 15:33:36 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.6 2024/09/02 15:33:36 christos Exp $"); 26 27 #include <config.h> 28 29 #include <pcap-types.h> 30 31 #include <memory.h> 32 #include <stdio.h> 33 #include <string.h> 34 35 #include "pcap-int.h" 36 37 #include <pcap/namedb.h> 38 39 #include "thread-local.h" 40 41 #ifdef HAVE_OS_PROTO_H 42 #include "os-proto.h" 43 #endif 44 45 static inline int skip_space(FILE *); 46 static inline int skip_line(FILE *); 47 48 /* Hex digit to integer. */ 49 static inline u_char 50 xdtoi(u_char c) 51 { 52 if (c >= '0' && c <= '9') 53 return (u_char)(c - '0'); 54 else if (c >= 'a' && c <= 'f') 55 return (u_char)(c - 'a' + 10); 56 else 57 return (u_char)(c - 'A' + 10); 58 } 59 60 /* 61 * Skip linear white space (space and tab) and any CRs before LF. 62 * Stop when we hit a non-white-space character or an end-of-line LF. 63 */ 64 static inline int 65 skip_space(FILE *f) 66 { 67 int c; 68 69 do { 70 c = getc(f); 71 } while (c == ' ' || c == '\t' || c == '\r'); 72 73 return c; 74 } 75 76 static inline int 77 skip_line(FILE *f) 78 { 79 int c; 80 81 do 82 c = getc(f); 83 while (c != '\n' && c != EOF); 84 85 return c; 86 } 87 88 struct pcap_etherent * 89 pcap_next_etherent(FILE *fp) 90 { 91 register int c, i; 92 u_char d; 93 char *bp; 94 size_t namesize; 95 static thread_local struct pcap_etherent e; 96 97 memset((char *)&e, 0, sizeof(e)); 98 for (;;) { 99 /* Find addr */ 100 c = skip_space(fp); 101 if (c == EOF) 102 return (NULL); 103 if (c == '\n') 104 continue; 105 106 /* If this is a comment, or first thing on line 107 cannot be Ethernet address, skip the line. */ 108 if (!PCAP_ISXDIGIT(c)) { 109 c = skip_line(fp); 110 if (c == EOF) 111 return (NULL); 112 continue; 113 } 114 115 /* must be the start of an address */ 116 for (i = 0; i < 6; i += 1) { 117 d = xdtoi((u_char)c); 118 c = getc(fp); 119 if (c == EOF) 120 return (NULL); 121 if (PCAP_ISXDIGIT(c)) { 122 d <<= 4; 123 d |= xdtoi((u_char)c); 124 c = getc(fp); 125 if (c == EOF) 126 return (NULL); 127 } 128 e.addr[i] = d; 129 if (c != ':') 130 break; 131 c = getc(fp); 132 if (c == EOF) 133 return (NULL); 134 } 135 136 /* Must be whitespace */ 137 if (c != ' ' && c != '\t' && c != '\r' && c != '\n') { 138 c = skip_line(fp); 139 if (c == EOF) 140 return (NULL); 141 continue; 142 } 143 c = skip_space(fp); 144 if (c == EOF) 145 return (NULL); 146 147 /* hit end of line... */ 148 if (c == '\n') 149 continue; 150 151 if (c == '#') { 152 c = skip_line(fp); 153 if (c == EOF) 154 return (NULL); 155 continue; 156 } 157 158 /* pick up name */ 159 bp = e.name; 160 /* Use 'namesize' to prevent buffer overflow. */ 161 namesize = sizeof(e.name) - 1; 162 do { 163 *bp++ = (u_char)c; 164 c = getc(fp); 165 if (c == EOF) 166 return (NULL); 167 } while (c != ' ' && c != '\t' && c != '\r' && c != '\n' 168 && --namesize != 0); 169 *bp = '\0'; 170 171 /* Eat trailing junk */ 172 if (c != '\n') 173 (void)skip_line(fp); 174 175 return &e; 176 } 177 } 178