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
localetheraddr(struct ether_addr * hint,struct ether_addr * result)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 *
ether_sprintf(struct ether_addr * addr)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
hexval(char dig)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
ether_aton(char * addr,uchar_t * macaddr)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