On Jan 22, 2009, at 4:05 PM, Chris Morgan wrote:
Hello.
I wasn't sure if this question was answered anywhere, I've searched
via google and looked on the mailing lists but haven't seen any
answers.
How does one get a ipv6 address from the sockaddr struct pointed to by
pcap_addr?
Welcome to the wonderful world of C, the programming language that
combines the power of assembly language with the convenience of
assembly language....
"struct sockaddr" is a sort of place-holder structure. There are few,
if any, real "struct sockaddr" structures out there; instead, there
are "struct sockaddr_XXX" structures, for various values of XXX.
"struct sockaddr" is an abstraction that covers all of them; all
"struct sockaddr_XXX" structures begin with members that are the same
as the non-"sa_data" members of "struct sockaddr", and with the same
structure offsets as those members, and have, following that, the
address-type-specific data, starting at the same offset as the
"sa_data" member of "struct sockaddr", but not necessarily having the
same *length* as the "sa_data" member of that structure - it could be
longer (and possibly shorter).
Once you've determined the address family of an address structure by
dereferencing a "struct sockaddr *" that you've been handed, you
should cast the "struct sockaddr *" to the appropriate "struct
sockaddr_XXX *" type - "struct sockaddr_un" for UNIX-domain socket
addresses, "struct sockaddr_in" for IPv4 addresses, "struct
sockaddr_in6" for IPv6 addresses, etc. - and get the address family-
specific information from the "struct sockaddr_XXX" pointed to by the
result of that cast.
I have devices with addresses of type AF_INET6 but since
the sockaddr struct is defined to have only 14 bytes of protocol
address how does one get a 16 byte ipv6 address out of this 14 byte
structure?
By realizing that, in fact, what you've been handed is a pointer to a
"struct sockaddr_in6", cast to a pointer to a "struct sockaddr",
because the address family is AF_INET6.
For a bit more detailed discussion of this, go to
http://www.unix.org/
go to the Single UNIX Specification Version 3 (you'll have to
register, but don't worry about it - it's free, just a nuisance), and
go to the page for <sys/sockets.h>, which says:
The <sys/socket.h> header shall define the unsigned integer type
sa_family_t.
The <sys/socket.h> header shall define the sockaddr structure that
includes at least the following members:
sa_family_t sa_family Address family.
char sa_data[] Socket address (variable-length data).
The sockaddr structure is used to define a socket address which is
used in the bind(), connect(), getpeername(), getsockname(),
recvfrom(), and sendto() functions.
The <sys/socket.h> header shall define the sockaddr_storage
structure. This structure shall be:
o Large enough to accommodate all supported protocol-specific
address structures
o Aligned at an appropriate boundary so that pointers to it can
be cast as pointers to protocol-specific address structures and used
to access the fields of those structures without alignment problems
The sockaddr_storage structure shall contain at least the following
members:
sa_family_t ss_family
When a sockaddr_storage structure is cast as a sockaddr structure,
the ss_family field of the sockaddr_storage structure shall map onto
the sa_family field of the sockaddr structure. When a sockaddr_storage
structure is cast as a protocol-specific address structure, the
ss_family field shall map onto a field of that structure that is of
type sa_family_t and that identifies the protocol's address family.
These conventions aren't libpcap-isms; other APIs, such as
getaddrinfo(), use those conventions - for example, the "struct
addrinfo"s handed back by getaddrinfo() have "struct sockaddr *"
pointers in them.
-
This is the tcpdump-workers list.
Visit https://cod.sandelman.ca/ to unsubscribe.