On Fri, 2007-08-17 at 22:36 +0530, Anil Gulecha wrote:
> On 8/17/07, Garrett D'Amore <[EMAIL PROTECTED]> wrote:
> > Can you figure out a way to use the unique serial number of the CPU?  Or
> > perhaps the factory MAC address of one of the NICs?
> >
> > On SPARC, we have hostids that are unique, but unforutnately I don't
> > believe that x86 has that ability.
> >
> 
> I've considered both of these.
> 
> 1) CPU serial number - x86 cpus do not have unique ids.. sparc does!

* actually most CPUs do have this, though it may be disabled by default
in the system BIOS

> 2) i considered using the 48bit mac id of the Ethernet card.. however
> ifconfig doesn't o/p the details that early in the boot process. If
> there another method to get the card detials, I could use it.

There is a DLPI method to achieve this.  I've attached a C file that can
query the MAC address of an ethernet device, even one that isn't plumbed
by IP.  (You need to know the name of the ethernet device, though.)  If
you need a routine to query for ethernet devices (walking libdevinfo),
let me know.  I can probably write without too much difficulty, though
there should be code if ifconfig -a plumb or you could use dladm to find
one.

Anyway, to use my "apmacid" utility, use "apmacid <device>".  The code
is old code (a utility I wrote for my own testing purposes back in
1999), but it still works.  If you want to include it verbatim, I'll
probably need to mark it with the CDDL.

        -- Garrett

> 
> If there isnt one, i'll write a small hashing utility in C and use the
> o/p of scanpci.
> 
> Anil
#pragma ident	"%W%	%E% SMI"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#include <stropts.h>
#include <sys/dlpi.h>

static int  ppa;
static char buffer [1024];

void
usage()
{
	fprintf(stderr, "usage: apmacid [-acfl] interface ...\n");
	exit(1);
}

int
dlpi_open_attach(char *interface, int *ppa)
{
	int		index;
	int		fd = -1;
	dl_attach_req_t	*attach_req;
	dl_ok_ack_t	*ok_ack;
	int		flags;
	struct strbuf	ctl;

	chdir("/dev");

	if ((!interface) || !(strlen(interface))) {
		perror("invalid NULL interface name!\n");
		return (-1);
	}

	if ((fd = open(interface, O_RDWR)) == -1) {
		if (errno != ENOENT) {
			perror(interface);
			return (-1);
		}
	} else {
		/* no attach required; its style 1 */
		return (fd);
	}
	
	/* style 2, determine name and ppa */
	for (;;) {
		index = strcspn(interface, "0123456789");
		if (strlen(interface + index) ==
		    strspn(interface + index, "0123456789")) {
			break;
		}
		index += strspn(interface + index, "0123456789");
	}

	*ppa = atoi(interface + index);
	interface[index] = 0;

	if ((fd = open(interface, O_RDWR)) == -1) {
		perror(interface);
		return (-1);
	}

	attach_req = (dl_attach_req_t *) buffer;
	attach_req->dl_primitive = DL_ATTACH_REQ;
	attach_req->dl_ppa = *ppa;
	ctl.len = sizeof (dl_attach_req_t);
	ctl.buf = buffer;

	if (putmsg(fd, &ctl, NULL, 0) < 0) {
		perror("apmacid: putmsg");
		(void) close(fd);
		return (-1);
	}

	flags = 0;
	ctl.maxlen = sizeof (buffer);
	ctl.buf = (void *) buffer;
	ok_ack = (dl_ok_ack_t *) buffer;

	/* wait for DL_OK_ACK, if none arrives program will hang */
	if (getmsg(fd, &ctl, NULL, &flags) < 0) {
		perror("apmacid: getmsg");
		(void) close(fd);
		return (-1);
	}

	if ((ok_ack->dl_primitive != DL_OK_ACK) ||
	    (ok_ack->dl_correct_primitive != DL_ATTACH_REQ)) {
		switch (ok_ack->dl_primitive) {
			case DL_OK_ACK:
				printf ("DL_OK_ACK goodprim %d\n",
					ok_ack->dl_correct_primitive);
				break;
			case DL_ERROR_ACK:
				{
				dl_error_ack_t *errack = 
					(dl_error_ack_t *)ok_ack;
				printf ("DL_ERROR_ACK badprim %d, err %d, unixerr %d\n",
					errack->dl_error_primitive,
					errack->dl_errno,
					errack->dl_unix_errno);
				break;
			default:
				printf("Unxpected primitive %d\n",
					ok_ack->dl_primitive);
				break;
			}
		}
		perror("apmacid: dlpi error\n");
		(void) close(fd);
		return (-1);
	}

	return (fd);
}

int
dlpi_get_phys_addr(int fd, t_uscalar_t addr_type, char **addr, int *len)
{
	dl_phys_addr_req_t	*phys_addr_req;
	dl_phys_addr_ack_t	*phys_addr_ack;
	struct strbuf		ctl;
	int			flags = 0;

	phys_addr_req = (dl_phys_addr_req_t *) buffer;
	phys_addr_req->dl_primitive = DL_PHYS_ADDR_REQ;
	phys_addr_req->dl_addr_type = addr_type;

	ctl.buf = buffer;
	ctl.len = sizeof (dl_phys_addr_req_t);

	if (putmsg(fd, &ctl, NULL, 0) < 0) {
		perror("putmsg");
		return (-1);
	}

	ctl.maxlen = sizeof (buffer);
	ctl.buf = buffer;
	phys_addr_ack = (dl_phys_addr_ack_t *) buffer;

	if (getmsg(fd, &ctl, NULL, &flags) < 0) {
		perror("getmsg");
	}

	if (phys_addr_ack->dl_primitive != DL_PHYS_ADDR_ACK) {
		perror("DLPI error: expected DL_PHYS_ADDR_ACK");
		return (-1);
	}

	*len = phys_addr_ack->dl_addr_length;
	*addr = buffer + phys_addr_ack->dl_addr_offset;
	return (0);
}

int
dlpi_get_brdcast_addr(int fd, char **addr, int *len)
{
	dl_info_req_t	*info_req;
	dl_info_ack_t	*info_ack;
	struct strbuf	ctl;
	int		flags = 0;

	info_req = (dl_info_req_t *) buffer;
	info_req->dl_primitive = DL_INFO_REQ;

	ctl.buf = buffer;
	ctl.len = sizeof (dl_info_req_t);

	if (putmsg(fd, &ctl, NULL, 0) < 0) {
		perror("putmsg");
		return (-1);
	}

	ctl.maxlen = sizeof (buffer);
	ctl.buf = buffer;
	info_ack = (dl_info_ack_t *) buffer;

	if (getmsg(fd, &ctl, NULL, &flags) < 0) {
		perror("getmsg");
	}

	if (info_ack->dl_primitive != DL_INFO_ACK) {
		perror("DLPI error");
		return (-1);
	}

	*len = info_ack->dl_brdcst_addr_length;
	*addr = buffer + info_ack->dl_brdcst_addr_offset;
	return (0);
}

void
printaddr(char *addr, int len)
{
	int idx = 0;
	while (idx < len) {
		printf("%x", (unsigned char) addr[idx]);
		idx++;
		if (idx < len) {
			printf(":");
		}
	}
	printf("\n");
}

int
main(int argc, char **argv)
{
	int			fd;
	int			optc;
	int			num_opts = 0;
	int			do_all = 0;
	int			do_factory = 0;
	int			do_current = 0;
	int			do_local = 0;
	int			do_brdcast = 0;
	int			do_multiple = 0;
	char			*iface = NULL;
	int			ppa;
	char			*addr;
	int			len;

	while ((optc = getopt(argc, argv, "afclb")) != EOF) {
		switch (optc) {
		case 'a':
			do_all = 1;
			num_opts += 2;	/* enable labelling */
			break;
		case 'f':
			do_factory = 1;
			num_opts++;
			break;
		case 'c':
			do_current = 1;
			num_opts++;
			break;
		case 'l':
			do_local = 1;
			num_opts++;
			break;
		case 'b':
			do_brdcast = 1;
			num_opts++;
			break;
		case '?':
			usage();
			break;
		}
	}

	/* a reasonable default */
	if (!num_opts) {
		do_current = 1;
	}

	if (optind >= argc) {
		usage();
		return (0);
	}

	if ((optind + 1) < argc) {
		/* multiple interfaces */
		do_multiple = 1;
	}

	while (optind < argc) {
		iface = argv[optind++];
		ppa = -1;

		if (do_multiple) {
			printf("%s:%s", iface, num_opts > 1 ? "\n" : " ");
		}

		fd = dlpi_open_attach(iface, &ppa);
		if (fd == -1) {
			continue;
		}

		if (do_all || do_current) {
			if (dlpi_get_phys_addr(fd, DL_CURR_PHYS_ADDR,
			    &addr, &len)) {
				(void) close(fd);
				continue;
			}

			if (num_opts > 1) {
				printf("%scurrent: ", do_multiple ? "\t" : "");
			}
			printaddr(addr, len);
		}

		if (do_all || do_factory) {
			if (dlpi_get_phys_addr(fd, DL_FACT_PHYS_ADDR,
			    &addr, &len)) {
				(void) close(fd);
				continue;
			}
			if (num_opts > 1) {
				printf("%sfactory: ", do_multiple ? "\t" : "");
			}
			printaddr(addr, len);
		}

		if (do_all || do_local) {
			if (dlpi_get_phys_addr(fd, DL_FACT_PHYS_ADDR,
			    &addr, &len)) {
				(void) close(fd);
				continue;
			}

			/*
			 * this rule only works for 6-byte ULAs, taken
			 * from IEEE Std. 802-1990.
			 */
			if (len == 6) {
				addr[2] |= 2;
			}
			if (num_opts > 1) {
				printf("%slocally-administered: ",
				do_multiple ? "\t" : "");
			}
			printaddr(addr, len);
		}

		if (do_all || do_brdcast) {
			if (dlpi_get_brdcast_addr(fd, &addr, &len)) {
				(void) close(fd);
				continue;
			}

			if (num_opts > 1) {
				printf("%sbroadcast: ",
				do_multiple ? "\t" : "");
			}
			printaddr(addr, len);
		}

		close(fd);
	}

	return (0);
}
_______________________________________________
opensolaris-code mailing list
opensolaris-code@opensolaris.org
http://mail.opensolaris.org/mailman/listinfo/opensolaris-code

Reply via email to