Home | History | Annotate | Line # | Download | only in dist
      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