bool InterpretSockaddrField()

in Interpret.cpp [90:235]


bool InterpretSockaddrField(std::string& out, const EventRecord& record, const EventRecordField& field) {
    // It is assumed that a sockaddr will never exceed 1024 bytes
    std::array<uint8_t, 1024> _buf;
    if (!decode_hex(_buf.data(), _buf.size(), field.RawValuePtr(), field.RawValueSize())) {
        out = "malformed-host(";
        out.append(field.RawValue());
        out.append(")");
        return false;
    }
    size_t bsize = field.RawValueSize()/2;

    const struct sockaddr *saddr = reinterpret_cast<struct sockaddr *>(_buf.data());
    out.append("{ fam=");
    auto fam = s_fam_table.ToString(saddr->sa_family);
    if (!fam.empty()) {
        out.append(fam);
    } else {
        out.append("unknown-family(");
        out.append(std::to_string(saddr->sa_family));
        out.append(")");
    }
    out.append(" ");

    switch (saddr->sa_family) {
        case AF_LOCAL: {
            auto addr = reinterpret_cast<struct sockaddr_un *>(_buf.data());
            // Calculate the sun_path size based on what was actually provided by the kernel
            // What the kernel emits may be smaller than sizeof(addr->sun_path) and may not be null terminated.
            size_t path_size = bsize-offsetof(struct sockaddr_un, sun_path);
            out.append("path=");
            if (addr->sun_path[0] != 0) {
                // The sun_path might not be NUL terminated, so limit strlen to the minimum of path_size or sizeof(addr->sun_path)
                out.append(addr->sun_path, strnlen(addr->sun_path, std::min(path_size, sizeof(addr->sun_path))));
            } else {
                out.push_back('@');
                if (path_size > 1) {
                    out.append(&addr->sun_path[1], path_size - 1);
                }
            }
            out.append(" }");
            break;
        }
        case AF_INET: {
            std::array<char, INET_ADDRSTRLEN+1> _abuf;
            auto addr = reinterpret_cast<struct sockaddr_in *>(_buf.data());
            if (bsize < sizeof(struct sockaddr_in)) {
                out.append("sockaddr len too short }");
                break;
            }
            if (inet_ntop(AF_INET, &addr->sin_addr, _abuf.data(), _abuf.size()) != nullptr) {
                out.append("laddr=");
                out.append(_abuf.data());
            } else {
                out.append("(error resolving addr) }");
                break;
            }
            out.append(" lport=");
            append_int(out, addr->sin_port);
            out.append(" }");
            break;
        }
        case AF_AX25: {
            auto addr = reinterpret_cast<struct sockaddr_ax25 *>(_buf.data());
            if (bsize < sizeof(struct sockaddr_ax25)) {
                out.append("ax25 len too short }");
                break;
            }
            out.append("call=");
            tty_escape_string_append(out, addr->sax25_call.ax25_call, sizeof(addr->sax25_call.ax25_call));
            out.append(" }");
            break;
        }
        case AF_IPX: {
            auto addr = reinterpret_cast<struct sockaddr_ipx *>(_buf.data());
            if (bsize < sizeof(struct sockaddr_ipx)) {
                out.append("ipx len too short }");
                break;
            }
            out.append("lport=");
            append_int(out, addr->sipx_port);
            out.append("ipx-net=");
            append_uint(out, addr->sipx_network);
            out.append(" }");
            break;
        }
        case AF_ATMPVC: {
            auto addr = reinterpret_cast<struct sockaddr_atmpvc *>(_buf.data());
            if (bsize < sizeof(struct sockaddr_atmpvc)) {
                out.append("atmpvc len too short }");
                break;
            }
            out.append("int=");
            append_uint(out, addr->sap_addr.itf);
            out.append(" }");
            break;
        }
        case AF_X25: {
            auto addr = reinterpret_cast<struct sockaddr_x25 *>(_buf.data());
            if (bsize < sizeof(struct sockaddr_x25)) {
                out.append("x25 len too short }");
                break;
            }
            out.append("laddr=");
            // Valid X25 address is null terminated and only decimal digits (0-9).
            addr->sx25_addr.x25_addr[15] = 0;
            out.append(addr->sx25_addr.x25_addr);
            break;
        }
        case AF_INET6: {
            std::array<char, INET6_ADDRSTRLEN+1> _abuf;
            auto addr = reinterpret_cast<struct sockaddr_in6 *>(_buf.data());
            if (bsize < sizeof(struct sockaddr_in6)) {
                out.append("sockaddr6 len too short }");
                break;
            }
            if (inet_ntop(AF_INET6, &addr->sin6_addr, _abuf.data(), _abuf.size()) != nullptr) {
                out.append("laddr=");
                out.append(_abuf.data());
            } else {
                out.append("(error resolving addr) }");
                break;
            }
            out.append(" lport=");
            append_int(out, addr->sin6_port);
            out.append(" }");
            break;
        }
        case AF_NETLINK: {
            auto addr = reinterpret_cast<struct sockaddr_nl *>(_buf.data());
            if (bsize < sizeof(struct sockaddr_nl)) {
                out.append("netlink len too short }");
                break;
            }
            out.append("nlnk-fam=");
            append_uint(out, addr->nl_family);
            out.append("nlnk-pid=");
            append_uint(out, addr->nl_pid);
            out.append(" }");
            break;
        }
        default:
            out.append("(unsupported) }");
            break;
    }
    return true;
}