etheraddr.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2000,2002 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "etheraddr.h"
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <strings.h>
#include <libdevinfo.h>
#include <stropts.h>
#include <unistd.h>
#include <netdb.h>
/*
* debugging flag
*/
static int debug = 0;
/* Timeout for DLPI acks */
static int dlpi_timeout = DLPI_TIMEOUT;
/*
* Global functions
*/
int dlpi_get_address(char *, struct ether_addr *);
int get_net_if_names(char ***);
void free_net_if_names(char **);
/*
* local functions
*/
static int dlpi_info_req(int, dl_info_ack_t *);
static int timed_getmsg(int, struct strbuf *, int *, int, char *, char *);
static int ifrm_num(char *, unsigned int *);
static void pf_dev_att(dev_att_t *);
static void parse_ifname(dev_att_t *);
static int ifname_open(char *, dev_att_t *);
static int dlpi_open_attach(char *);
static int dlpi_attach(int, int, int);
static int dlpi_get_phys(int, uchar_t *);
static int dlpi_info_req(int, dl_info_ack_t *);
static int timed_getmsg(int, struct strbuf *, int *, int, char *, char *);
/*
* get an individual arp entry
*/
int
{
struct sockaddr_in *sin;
int s;
return (-1);
}
/* LINTED pointer */
return (-1);
}
}
if (s < 0) {
return (-1);
}
(void) close(s);
return (-1);
}
(void) close(s);
} else
return (-1);
return (0);
}
/* Get all interface names. This will include IPv6 names. */
int
get_net_if_names(char ***names)
{
char *buf; /* buffer for socket info */
int sd; /* socket descriptor */
int ifn; /* interface count structure */
int numifs;
char **tmpnames;
int n;
char *tmpname;
if (sd < 0)
return (-1);
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
break;
}
return (0);
}
/*
* frees previously-allocated array from get_net_if_names
*/
void
free_net_if_names(char **ifnames)
{
int i;
i = 0;
i++;
}
}
/*
* attempt to remove ppa from end of file name
* return -1 if none found
* return ppa if found and remove the ppa from the filename
*/
static int
{
int i;
uint_t p = 0;
unsigned int m = 1;
p += (fname[i] - '0')*m;
m *= 10;
i--;
}
if (m == 1) {
return (-1);
}
*ppa = p;
return (0);
}
/*
* Open the device defined in dev_att with the given mode starting with
* the module indicated by mod_cnt (1 indexed). If mod_cnt > 0, fd must
* contain the file descriptor that modules are to be pushed on.
* Returns -1 if device could not be opened, the index of
* the module that could not be pushed or 0 on success.
*/
static int
{
int cnt;
int local_fd;
if (debug)
(void) printf("open_dev: ifname: %s : dev %s fd %d "
" mod_cnt %d\n",
/*
* if no module count is given, try and open the device
*/
if (mod_cnt == 0) {
if (debug)
(void) printf("open_dev: opening %s\n",
if (debug) {
perror("open_dev: device");
(void) printf("\n");
}
return (-1);
}
cnt = 1;
} else {
}
/*
* Try and push modules (if any) onto the device stream
*/
if (debug)
(void) printf(" pushing: mod %s",
if (debug) {
perror("open_dev: push");
(void) printf("\n");
}
return (cnt);
}
}
if (debug)
(void) printf("\n");
return (0);
}
/*
* Debug routine to print out dev_att_t structure
*/
static void
{
int cnt;
}
}
/*
* This function parses a '.' delimited interface name of the form
* dev[.module[.module...]][:lun]
* and places the device and module name into dev_att
*/
static void
{
char *lunstr;
int cnt = 0; /* number of modules to push */
char *nxtmod;
/*
* check for specified lun at end of interface and
* strip it off.
*/
if (lunstr) {
char *endptr;
*lunstr = '\0';
lunstr++;
exit(-1);
}
} else {
}
/* parse '.' delmited module list */
if (modlist) {
/* null-terminate interface name (device) */
*modlist = '\0';
modlist++;
if (nxtmod) {
*nxtmod = '\0';
nxtmod++;
}
cnt++;
}
}
}
/*
* given a interface name (with possible modules to push)
* interface name must have the format of
* dev[ppa][.module[.module...][ppa]][:lun]
*/
static int
{
int fd;
int res;
int style;
int mod_id;
if (debug)
return (-1);
}
/* save copy of original device name */
/* parse modules */
/* try DLPI style 1 device first */
if (debug) {
}
if (mod_id != 0) {
if (debug) {
(void) printf("Error on open_dev style 1 mod_id: %d"
" attemping style 2\n", mod_id);
}
if (mod_id == -1) {
mod_id = 0;
if (res < 0) {
if (debug)
"%s: No such file or directory\n",
return (-1);
}
/*
* ensure that it's the last module
* in the list to extract
* ppa
*/
&ppa)) < 0) {
if (debug) {
"Error on open_dev style 2 mod_id: %d \n",
mod_id);
}
"locate ppa in %s\n",
return (-1);
}
goto style2;
}
goto dl_info_chk;
if (mod_id != 0) {
if (debug) {
"Error on open_dev style 2 mod_id: %d \n",
mod_id);
if (mod_id > 0) {
}
}
return (-1);
}
return (-1);
}
if (debug) {
"expected style %s got style %s (0x%lx)\n",
}
return (-1);
}
if (debug) {
(void) printf("pars_dev_att() success\n");
}
return (fd);
}
static int
dlpi_open_attach(char *ifname)
{
int fd;
if (debug)
/* if lun is specified fail (backwards compat) */
return (-1);
}
/* Not found */
return (-1);
}
return (-1);
}
return (fd);
}
static int
{
union DL_primitives *dlp;
char *buf;
int flags;
if (style != 2)
return (0);
/* Allocate required buffers */
return (-1);
}
/* Issue DL_ATTACH_REQ */
/* LINTED: malloc returns a pointer aligned for any use */
perror("libuuid: putmsg");
return (-1);
}
/* read reply */
flags = 0;
/* start timeout for DL_OK_ACK reply */
"DL_OK_ACK", "DL_ATTACH_REQ") == 0) {
return (-1);
}
if (debug) {
flags);
}
/* Validate DL_OK_ACK reply. */
"libuuid: attach failed: short reply to attach request\n");
return (-1);
}
if (debug)
"attach failed: dl_errno %lu errno %lu\n",
return (-1);
}
"libuuid: attach failed: "
"unrecognizable dl_primitive %lu received",
dlp->dl_primitive);
return (-1);
}
"libuuid: attach failed: "
"short attach acknowledgement received\n");
return (-1);
}
"libuuid: attach failed: "
"returned prim %lu != requested prim %lu\n",
return (-1);
}
if (debug)
(void) printf("attach done\n");
return (0);
}
static int
{
union DL_primitives *dlp;
char *buf;
int flags;
/* Allocate required buffers */
return (-1);
}
/* Issue DL_PHYS_ADDR_REQ */
/* LINTED: malloc returns a pointer aligned for any use */
perror("libuuid: putmsg");
return (-1);
}
/* read reply */
flags = 0;
"DL_PHYS_ADDR_ACK", "DL_PHYS_ADDR_REQ (DL_CURR_PHYS_ADDR)") == 0) {
return (-1);
}
if (debug) {
flags);
}
/* Validate DL_PHYS_ADDR_ACK reply. */
"short reply to phys_addr request\n");
return (-1);
}
/*
* Do not print errors for DL_UNSUPPORTED and DL_NOTSUPPORTED
*/
"dl_errno %lu errno %lu\n",
}
return (-1);
}
"unrecognizable dl_primitive %lu received\n",
dlp->dl_primitive);
return (-1);
}
"short phys_addr acknowledgement received\n");
return (-1);
}
/* Check length of address. */
return (-1);
}
/* copy Ethernet address */
return (0);
}
static int
{
int flags;
perror("libuuid: putmsg");
return (-1);
}
/* read reply */
flags = 0;
/* start timeout for DL_BIND_ACK reply */
"DL_INFO_ACK") == 0) {
return (-1);
}
if (debug) {
flags);
}
/* Validate DL_BIND_ACK reply. */
"libuuid: info req failed: short reply to info request\n");
return (-1);
}
"libuuid: info req failed: dl_errno %lu errno %lu\n",
return (-1);
}
"libuuid: info req failed: "
"unrecognizable dl_primitive %lu received\n",
dlp->dl_primitive);
return (-1);
}
"libuuid: info req failed: "
"short info acknowledgement received\n");
return (-1);
}
return (0);
}
/*
* interface called from libuuid to get the ethernet address - jhf
*/
int
{
int fd;
if (debug)
(void) printf("dlpi_get_address: dlpi_open_attach\t");
if (fd < 0) {
/* Do not report an error */
return (-1);
}
if (debug)
return (-1);
}
return (0);
}
static int
char *request)
{
int ret;
return (0);
} else if (ret == -1) {
return (0);
}
/* poll returned > 0 for this fd so getmsg should not block */
return (0);
}
return (1);
}
/*
* Name: get_ethernet_address
*
* Description: Obtains the system ethernet address.
*
* Returns: 0 on success, non-zero otherwise. The system ethernet
* address is copied into the passed-in variable.
*/
int
{
char **ifnames;
char *ifname;
int i;
struct ether_addr addr;
int found;
return (0);
/*
* go get all interface names
*/
if (get_net_if_names(&ifnames) == 0) {
return (0);
}
/*
* Assume failure
*/
found = -1;
/*
* for each interface, query it through dlpi to get its physical
* (ethernet) address
*/
i = 0;
/*
* found one, set result to successful
*/
found = 0;
continue;
}
}
i++;
}
}
/*
* Couldn't get ethernet address from any interfaces...
*/
return (found);
}