14 byte array (MAC address) to 48 bits (6 bytes)...

J

James Vanns

First,

Sorry for the cross-post :p OK, in Linux I can obtain the MAC address
using socket(), ioctl() etc. and a few data structures. No problem.
However, the resulting MAC is stored in a 14 byte char array
(sockaddr.sa_data). However, a MAC address is 48-bits! The MAC (as in
the char array) is obviously the printable form of:

00efc8346b72

or whatever. So that last '7' and '2' is in fact meant to be the 1 byte
72 right? How is this array shifted down to a 6 byte array or even
better, what I really want is the least significant 32-bits to stick in
an unsigned int!

Any help appreciated!

Jim
 
S

spibou

James said:
First,

Sorry for the cross-post :p OK, in Linux I can obtain the MAC address
using socket(), ioctl() etc. and a few data structures. No problem.
However, the resulting MAC is stored in a 14 byte char array
(sockaddr.sa_data). However, a MAC address is 48-bits! The MAC (as in
the char array) is obviously the printable form of:

00efc8346b72

or whatever. So that last '7' and '2' is in fact meant to be the 1 byte
72 right? How is this array shifted down to a 6 byte array or even
better, what I really want is the least significant 32-bits to stick in
an unsigned int!

Any help appreciated!

I'd love to help but I have no idea what you're talking about !
Could you express in abstract terms what you're trying to achieve
without mentioning MAC's , Linux , ioctl etc. ?
 
D

David Resnick

James said:
First,

Sorry for the cross-post :p OK, in Linux I can obtain the MAC address
using socket(), ioctl() etc. and a few data structures. No problem.
However, the resulting MAC is stored in a 14 byte char array
(sockaddr.sa_data). However, a MAC address is 48-bits! The MAC (as in
the char array) is obviously the printable form of:

00efc8346b72

or whatever. So that last '7' and '2' is in fact meant to be the 1 byte
72 right? How is this array shifted down to a 6 byte array or even
better, what I really want is the least significant 32-bits to stick in
an unsigned int!

Any help appreciated!

Jim

Hi,

I think you probably want code like this, probably with some added
error
checking...

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

int main(void)
{
char *pMac = "00efc8346b72";
unsigned long iMac = strtoul(&pMac[4], NULL, 16);

printf("pMac '%s' -> iMac '%lu' (=%lx)\n",
pMac, iMac, iMac);

return 0;
}

-David
 
S

Stephen Sprunk

I'd love to help but I have no idea what you're talking about !
Could you express in abstract terms what you're trying to achieve
without mentioning MAC's , Linux , ioctl etc. ?

He wants to turn this:

char printablemac[14] = "00efc8346b72";

into this:

unsigned char binarymac[6] = { 0x00, 0xef, 0xc8, 0x34, 0x6b, 0x72 };

or this:

unsigned long longmac = 0xc8346b72;

or this:

unsigned long long longlongmac = 0x00efc8346b72;

The answers for the first and the latter two are rather different, but
David Resnick provided a reasonable answer to the middle option.

S
 
J

James Vanns

OK, I've come up with this code. I know it's C++ (sorry wrong news
group) but I *was* going to use just C. However, do you think I'm on
the right track?

static const uint32_t mac2int (const string &p_nic, const string
&p_mac) {
uint32_t imac = 0;
string mac (p_mac); // 00:02:B3:14:03:D7
mac.erase (remove (mac.begin (), mac.end (), ':'), mac.end ()); //
0002B31403D7

for (uint i = 0 ; i < sizeof (uint) * 2 ; i += 2) {
char b[3];
b[2] = '\0';
b[1] = *(mac.end () - (i + 1)); // 7
b[0] = *(mac.end () - (i + 2)); // D
imac = (imac << 8) | strtoul (b, NULL, 16); // The important bit!
}

return imac;
}

Ta,

Jim

David said:
James said:
First,

Sorry for the cross-post :p OK, in Linux I can obtain the MAC address
using socket(), ioctl() etc. and a few data structures. No problem.
However, the resulting MAC is stored in a 14 byte char array
(sockaddr.sa_data). However, a MAC address is 48-bits! The MAC (as in
the char array) is obviously the printable form of:

00efc8346b72

or whatever. So that last '7' and '2' is in fact meant to be the 1 byte
72 right? How is this array shifted down to a 6 byte array or even
better, what I really want is the least significant 32-bits to stick in
an unsigned int!

Any help appreciated!

Jim

Hi,

I think you probably want code like this, probably with some added
error
checking...

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

int main(void)
{
char *pMac = "00efc8346b72";
unsigned long iMac = strtoul(&pMac[4], NULL, 16);

printf("pMac '%s' -> iMac '%lu' (=%lx)\n",
pMac, iMac, iMac);

return 0;
}

-David
 
W

Walter Roberson

OK, I've come up with this code. I know it's C++ (sorry wrong news
group) but I *was* going to use just C. However, do you think I'm on
the right track?
static const uint32_t mac2int (const string &p_nic, const string
&p_mac) {
uint32_t imac = 0;
string mac (p_mac); // 00:02:B3:14:03:D7
mac.erase (remove (mac.begin (), mac.end (), ':'), mac.end ()); //
0002B31403D7

That code violates the initialy stated condition that the MAC
was stored in a 14 byte array and therefore is not suitable
for the original purpose.

If you are going to work with the human-readable textual form of MACs,
then you need to be concerned with the possibility that leading
zeroes have been supressed, such as 0:2:B3:14:3:D7 .
 
D

David Resnick

James said:
OK, I've come up with this code. I know it's C++ (sorry wrong news
group) but I *was* going to use just C. However, do you think I'm on
the right track?

static const uint32_t mac2int (const string &p_nic, const string
&p_mac) {
uint32_t imac = 0;
string mac (p_mac); // 00:02:B3:14:03:D7
mac.erase (remove (mac.begin (), mac.end (), ':'), mac.end ()); //
0002B31403D7

for (uint i = 0 ; i < sizeof (uint) * 2 ; i += 2) {
char b[3];
b[2] = '\0';
b[1] = *(mac.end () - (i + 1)); // 7
b[0] = *(mac.end () - (i + 2)); // D
imac = (imac << 8) | strtoul (b, NULL, 16); // The important bit!
}

return imac;
}

Ta,

Jim

People frown on C++ code (off topic) and on top-posting (bad practice)
in comp.lang.c, just FYI. Anyway, I won't comment specifically on C++
aspects of the code in comp.lang.c (followups set to comp.lang.c++ and
comp.unix.programmer).

It seems to me that you might as well convert the whole thing (starting
at the 5th character) at once after removing the ':' characters rather
than do the convert two characters/shift thing unless you somehow think
the format of a MAC address will change.

-David
 
J

James Vanns

I thought that someone may have noticed this. The array is defined in
the linux socket.h header file as being 14 bytes in size. However, you
only need 12 for a hex rep of a 48-bit number which is what the MAC
address is. I'm only working with what I've got ;) Basically I built
the std::string from the 14 byte char array taking only bytes 12 -> 0.
This seems to work fine on the ~1000 linux machines I've tried. I'm not
bothered with portability at the moment. The colons are never use at
this level of the api.

Have anything else to add?

Jim
 
J

James Vanns

I think Stephen and David have hit the nail on the head. I'm close to
getting what I want so I'm sure I'll crack it now.

Ta,

Jim
 
S

spibou

Stephen said:
I'd love to help but I have no idea what you're talking about !
Could you express in abstract terms what you're trying to achieve
without mentioning MAC's , Linux , ioctl etc. ?

He wants to turn this:

char printablemac[14] = "00efc8346b72";

into this:

unsigned char binarymac[6] = { 0x00, 0xef, 0xc8, 0x34, 0x6b, 0x72 };

or this:

unsigned long longmac = 0xc8346b72;

or this:

unsigned long long longlongmac = 0x00efc8346b72;

The answers for the first and the latter two are rather different, but
David Resnick provided a reasonable answer to the middle option.

Thank you. This not only makes sense but is actually on topic.

But my charitable mood has left me plus the opening poster says he
has solved the problem anyway.

Spiros Bousbouras
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top