Code to change MAC address in Tru64 4.0f

Code to change MAC address in Tru64 4.0f

Post by d0 » Sun, 15 Sep 2002 04:58:54



From the man page on "tu" the interface for our nics.
------------------------------------------------------------------------
" You can use the SIOCSPHYSADDR    ioctl to change    the physical address of    the
 interface; use the ifreq structure.  You can also use    the SIOCRPHYSADDR
 ioctl    to read    the physical address of    the interface.    See the    "Examples"
 section." - OSF 4.0f tu 7 manpage.

NOTE: They say use ifreq. yet see below...

From ioctl.h
-------------------
#define SIOCRPHYSADDR   _IOWR('i', 62, struct ifdevea)  /* Read Phys addr */
#define SIOCSPHYSADDR   _IOWR('i', 63, struct ifdevea)  /* Set addr */

From if.h
---------------
/*
* structure used to query de and qe for physical addresses
*/
struct ifdevea {
       char    ifr_name[IFNAMSIZ];             /* if name, e.g. "en0" */
       u_char default_pa[6];                   /* default hardware address */
       u_char current_pa[6];                   /* current physical address */

Quote:};

struct  ifreq {
#define IFNAMSIZ        16
       char    ifr_name[IFNAMSIZ];             /* if name, e.g. "en0" */
       union {
               struct  sockaddr ifru_addr;
               struct  sockaddr ifru_dstaddr;
               struct  sockaddr ifru_broadaddr;
               int     ifru_flags;
               int     ifru_metric;
               caddr_t ifru_data;
               int     ifru_value;             /* any generic value */
               u_int   ifru_index;
       } ifr_ifru;
#define ifr_addr        ifr_ifru.ifru_addr      /* address */
#define ifr_dstaddr     ifr_ifru.ifru_dstaddr   /* other end of p-to-p link */
#define ifr_broadaddr   ifr_ifru.ifru_broadaddr /* broadcast address */
#define ifr_flags       ifr_ifru.ifru_flags     /* flags */
#define ifr_metric      ifr_ifru.ifru_metric    /* metric */
#define ifr_data        ifr_ifru.ifru_data      /* for use by interface */
#define ifr_value       ifr_ifru.ifru_value     /* for use by interface */
#define ifr_index       ifr_ifru.ifru_index     /* interface index */

Quote:};

Call me nuts or clear up my confusion but it seems either the man page is
incorrect or their header files are incorrect.  Or perhaps there is some
substantial documentation I have yet to find.  Anyone have a clue?

Basically I am trying to change the MAC address of cards under Tru64 4.0.
 It's been mentioned to me to use ifconfig yet I find nothing under it to
do so. I assume this is only available under 5.x.

Below is the code I have written thus far.  (NOTE IT DOES NOT WORK).  I
can read and even write to the eeprom.  But apparently there is
something severely wrong with how or what is being written.

When I attempt the command line: ./nic tu4 00 6 2B 1 67 37    Which
specifies the nic tu4 with that MAC addy what gets set is the following:
Current MOD PHY Address is: 2B 1 67 37 0 6

Now I have learned about the serial nature of the eeprom (or at least Im
pretty sure its serial).  Also I found out these cards (21143) probably
have a 256 byte eeprom.  I can only assume ioctl is writting to the
correct spot since I haven't a clue what its doing behind the scenes. I
also think there is an issue with a ckecksum that needs to be calculated.

Does anyone have example code out there for doing this. Fixes for the
following code or anything that might help?

Thanks, d0

PS. Yes I am aware of the dire consequences of hosing the card doing
this.

CODE
---------
#include <stdio.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <errno.h>

void
main(int argc, char *argv[])
{
 struct  ifdevea  dev;
 int sock_in01=0,i=0;
 char *cp;

 strcpy(dev.ifr_name,argv[1]);

 sock_in01 = socket(AF_INET,SOCK_DGRAM,0);
 if (sock_in01 < 0)
  {
   perror(argv[0]);
   exit(1);
  }
 if (ioctl(sock_in01,SIOCRPHYSADDR,&dev) < 0)
  {
   perror(argv[0]);
   exit(1);
  }

 printf("\nDefault HDW Address is: ");
 for (i=0; i<6; i++)
  {
   printf("%X ", dev.default_pa[i]);
  }
 printf("\nCurrent PHY Address is: ");
 for (i=0; i<6; i++)
  {
   printf("%X ", dev.current_pa[i]);
  }

 for (i=0; i<6; i++)
  {
   printf("\n%d = %X",i ,strtol(argv[i+2], &cp, 16) & 0xff);
   sprintf(&dev.current_pa[i],"%c",(uchar)(strtol(argv[i+2], &cp, 16) & 0xff));
  }

 if (ioctl(sock_in01,SIOCSPHYSADDR,&dev) < 0)
  {
   perror(argv[0]);
   exit(1);
  }
 if (ioctl(sock_in01,SIOCRPHYSADDR,&dev) < 0)
  {
   perror(argv[0]);
   exit(1);
  }

 printf("\nCurrent MOD PHY Address is: ");
 for (i=0; i<6; i++)
  {
   printf("%X ", dev.current_pa[i]);
  }

 close(sock_in01);

Quote:}

 
 
 

Code to change MAC address in Tru64 4.0f

Post by Brian Hale » Sun, 15 Sep 2002 06:17:29



> Call me nuts or clear up my confusion but it seems either the man page is
> incorrect or their header files are incorrect.  Or perhaps there is some
> substantial documentation I have yet to find.  Anyone have a clue?

I have a clue :)

The man page and header files are correct, see the example code below.

-Brian

HP Tru64 UNIX Networking

/*
 * sphyaddr - set a network adapter's physical Ethernet hardware address
 *
 * to compile: cc sphyaddr.c -o sphyaddr
 *
 * usage: sphyaddr tu0 08-00-2b-ff-ff-ff
 */

#define _SOCKADDR_LEN

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/if_ether.h>

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <errno.h>

/* function prototype */
void ether_aton(char *, u_char *);

int
main (int argc, char **argv)
{
    int s, n;
    u_char *cp;
    static struct ifdevea devea;
    static struct ifreq newaddress;

    if (argc < 3) {
        fprintf(stderr, "usage: %s: interface address\n", argv[0]);
        fprintf(stderr, "for example: %s tu0 08-00-2b-ff-ff-ff\n", argv[0]);
        exit(1);
    }

    s = socket(AF_INET, SOCK_DGRAM, 0);

    strcpy(devea.ifr_name, argv[1]);
    strcpy(newaddress.ifr_name, argv[1]);

    /*
     * get current address from driver
     */
    if ((ioctl(s, SIOCRPHYSADDR, &devea) < 0))  {
        perror("couldn't get devea from driver");
    } else {
        /*
         * print the current address
         */
        cp = (u_char *)devea.current_pa;
        n = 0;
        printf("Current: ");
        do {
            printf("%02X-", cp[n++]);
        } while (n < sizeof(devea.current_pa) - 1);
        printf("%02X\n", cp[n++]);

        /*
         * print the target address
         */
        printf("Target : %s\n", argv[2]);

        /* convert it */
        cp = (u_char *)argv[2];
        ether_aton((char *)cp, (u_char *)newaddress.ifr_addr.sa_data);

        newaddress.ifr_addr.sa_family = AF_LINK;
        newaddress.ifr_addr.sa_len = sizeof(newaddress.ifr_addr);

        /* set it */
        if ((ioctl(s, SIOCSPHYSADDR, &newaddress) < 0)) {
            perror("couldn't set devea");
        }

        exit(0);
    }
    exit(1);

Quote:}

/*
 * Convert an ASCII Ethernet address to a numeric address
 */
void
ether_aton(char *a,
           u_char *n)
{
    int i, o[6];

    i = sscanf(a, "%x-%x-%x-%x-%x-%x", &o[0], &o[1], &o[2],
                                       &o[3], &o[4], &o[5]);
    if (i != 6) {
        fprintf(stderr, "invalid Ethernet address '%s'\n", a);
        exit(1);
    }

    for (i = 0; i < 6; i++)
        n[i] = o[i];

    return;

Quote:}


 
 
 

Code to change MAC address in Tru64 4.0f

Post by d0 » Sun, 15 Sep 2002 06:21:36





>> Call me nuts or clear up my confusion but it seems either the man page
>> is incorrect or their header files are incorrect.  Or perhaps there is
>> some substantial documentation I have yet to find.  Anyone have a clue?

> I have a clue :)

> The man page and header files are correct, see the example code below.

> -Brian

> HP Tru64 UNIX Networking

w00t!

Thank you!

My confusion was that in the ioctl.h file they showed SIOCSPHYADDR using
ifdevea yet in the man page they say use ifreq for that function.

Thanks again!