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
35static kmutex_t localetheraddr_lock;   /* Perimeter lock for localetheraddr */
36
37int
38localetheraddr(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 */
65char *
66ether_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
77static int
78hexval(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 */
95int
96ether_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