`getifaddrs` "struct ifa_data"

The man page for getifaddrs states:

The ifa_data field references address family specific data. For AF_LINK addresses it contains a pointer to the struct if_data (as defined in include file <net/if.h>) which contains various interface attributes and statistics. For all other address families, it contains a pointer to the struct ifa_data (as defined in include file <net/if.h>) which contains per-address interface statistics.

I assume that "AF_LINK address" is the one that has AF_LINK in the p.ifa_addr.sa_family field.

However I do not see "struct ifa_data" anywehere. Is this a documentation bug and if so how do I read this documentation right?

Replies

I assume that "AF_LINK address" is the one that has AF_LINK in the p.ifa_addr.sa_family field.

Correct.

However I do not see struct ifa_data anywehere. Is this a documentation bug and if so how do I read this documentation right?

You’re misreading that quote. For AF_LINK the correct type is struct if_data (without the extra a) and that’s defined in <net/if_var.h>.

IMPORTANT If you’re plan to get interface statistics from this structure — like a count of bytes sent and received — be aware that it has significant limitations.

I’ve discussed these limitations many times here on DevForums. Today I took the time to write up my experience. See the Network Interface Statistics post linked to from Extra-ordinary Networking.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Right... I'm still curious though how to properly read this specific part of the documentation:

For all other address families, it contains a pointer to the struct ifa_data (as defined in include file <net/if.h>) which contains per-address interface statistics.

as I do not see "struct ifa_data" anywhere...

AFAICT this is a bug in the man page, a remnant from one of macOS’s ancestor platforms. Consider this code:

import Foundation

func test() {
    var addrList: UnsafeMutablePointer<ifaddrs>? = nil
    let err = getifaddrs(&addrList)
    // In theory we could check `errno` here but, honestly, what are gonna
    // do with that info?
    guard
        err >= 0,
        let first = addrList
    else { return }
    defer { freeifaddrs(addrList) }
    for addr in sequence(first: first, next: { $0.pointee.ifa_next }) {
        guard
            let name = addr.pointee.ifa_name.map({ String(cString: $0) }),
            let sa = addr.pointee.ifa_addr
        else { continue }
        print("\(name) \(sa.pointee.sa_family) \(addr.pointee.ifa_data != nil)")
    }
}

test()
% ./InterfaceTest | grep en0
en0 18 true
en0 30 false
en0 30 false
en0 2 false

Only the AF_LINK (18) entry has the ifa_data value populated. The AF_INET (2) and AF_INET6 (30) entries have ifa_data set to nil.

I’d appreciate you filing a bug against the man page. Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I see (and will file the bug). I was a bit nervous running a very similar code to yours on my computer and making far fetching conclusions about what to expect in the ifa_data field in the wild:

  • the doc is buggy, but because it's buggy it's hard to tell what is correct in it and what's not (what to trust and what not). The most conservative approach would be: "if it's buggy – don't second guess it and don't trust it at all".
  • different OS versions / or (Apple) platforms might do things differently, and what happens on my device might not be the whole story.
  • special conditions on user devices (wifi/cellular? p2p? network link conditioner? vpn tunnels? usb wifi dongles?) might mess things further.

Some (in fact strong [1]) reassurance I'll have when I see the actual source that populates ifa_data field. Could you please point me to the right place if that's publicly available?


[1] normally it's unwise to jump to conclusions based on what's in the source: normally the doc is king and implementation could be changed on a whim... In this particular case, though (1. doc is buggy, so definitely not king, 2. the API is ancient, so hardly ever change (significantly) 3. Hyrum's law is at play and it makes implementation changes even less likely) the source code deemed to be the best "source of truth".

Start here and then work backwards into the kernel.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"