xref: /illumos-gate/usr/src/uts/common/io/etheraddr.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 /*
2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
7 /*	  All Rights Reserved  	*/
8 
9 /*
10  * Copyright (c) 1982, 1986 Regents of the University of California.
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms are permitted
14  * provided that this notice is preserved and that due credit is given
15  * to the University of California at Berkeley. The name of the University
16  * may not be used to endorse or promote products derived from this
17  * software without specific prior written permission.  This software
18  * is provided ``as is'' without express or implied warranty.
19  */
20 
21 #pragma ident	"%Z%%M%	%I%	%E% SMI"
22 
23 #include <sys/types.h>
24 #include <sys/sysmacros.h>
25 #include <sys/ethernet.h>
26 #include <sys/cmn_err.h>
27 #include <sys/ksynch.h>
28 
29 /*
30  * Store and retrieve local individual ethernet address.
31  * This is typically initialized (called with 'hint' nonnull)
32  * by the boot code.
33  */
34 
35 static kmutex_t localetheraddr_lock;   /* Perimeter lock for localetheraddr */
36 
37 int
38 localetheraddr(struct ether_addr *hint, struct ether_addr *result)
39 {
40 	static int found = 0;
41 	static	struct	ether_addr	addr;
42 
43 	mutex_enter(&localetheraddr_lock);
44 	if (!found) {
45 		if (hint == NULL) {
46 			mutex_exit(&localetheraddr_lock);
47 			return (0);
48 		}
49 		found = 1;
50 		addr = *hint;
51 		cmn_err(CE_CONT, "?Ethernet address = %s\n",
52 		    ether_sprintf(&addr));
53 	}
54 	if (result != NULL)
55 		*result = addr;
56 	mutex_exit(&localetheraddr_lock);
57 	return (1);
58 }
59 
60 /*
61  * Convert Ethernet address to printable (loggable) representation.
62  *
63  * XXX This is not MT-safe, but its only race is for the "etherbuf".
64  */
65 char *
66 ether_sprintf(struct ether_addr *addr)
67 {
68 	static char etherbuf[18];
69 
70 	(void) snprintf(etherbuf, sizeof (etherbuf), "%x:%x:%x:%x:%x:%x",
71 	    addr->ether_addr_octet[0], addr->ether_addr_octet[1],
72 	    addr->ether_addr_octet[2], addr->ether_addr_octet[3],
73 	    addr->ether_addr_octet[4], addr->ether_addr_octet[5]);
74 	return (etherbuf);
75 }
76 
77 static int
78 hexval(char dig)
79 {
80 	if ('0' <= dig && dig <= '9') {
81 		return (dig - '0');
82 	} else if ('a' <= dig && dig <= 'f') {
83 		return (dig - 'a' + 10);
84 	} else if ('A' <= dig && dig <= 'F') {
85 		return (dig - 'A' + 10);
86 	} else {
87 		return (-1);
88 	}
89 }
90 
91 /*
92  * Convert Ethernet address from ascii to binary form.
93  * Return number of bytes written.
94  */
95 int
96 ether_aton(char *addr, uchar_t *macaddr)
97 {
98 	int i = 0;
99 	uint_t val = 0;
100 	char *cp = addr;
101 
102 	while (*cp != 0 && i < 6) {
103 		if (*cp == ':') {
104 			macaddr[i++] = val;
105 			val = 0;
106 			cp++;
107 			continue;
108 		}
109 
110 		val = (val << 4) | hexval(*cp++);
111 	}
112 	macaddr[i] = val;
113 	return (i + 1);
114 }
115