krb5 commit: Refactor libapputils handling of socket addresses

ghudson at mit.edu ghudson at mit.edu
Wed Dec 11 17:02:51 EST 2024


https://github.com/krb5/krb5/commit/c67b17a17985db291931babb31bece9bd287fbb5
commit c67b17a17985db291931babb31bece9bd287fbb5
Author: Greg Hudson <ghudson at mit.edu>
Date:   Wed Nov 13 22:51:20 2024 -0500

    Refactor libapputils handling of socket addresses
    
    Add private libkrb5 APIs for sockaddr-to-krb5-address conversion and
    for printing socket addresses.  Use them in the KDC, kadmind,
    kprop/kpropd, and trace logging.
    
    In net-server.c, do not convert the local and remote socket addresses
    to krb5_address; instead pass them directly to dispatch().  Convert
    the addresses where needed in the KDC and kadmind.

 src/include/k5-int.h             |  16 ++++
 src/include/net-server.h         |  12 +--
 src/kadmin/server/schpw.c        |  50 ++---------
 src/kadmin/server/server_stubs.c |   8 +-
 src/kdc/dispatch.c               |   7 +-
 src/kdc/do_as_req.c              |   8 +-
 src/kdc/do_tgs_req.c             |   6 +-
 src/kdc/kdc_audit.c              |  25 ++++--
 src/kdc/kdc_audit.h              |   2 +-
 src/kdc/kdc_log.c                |  32 +++----
 src/kdc/kdc_util.c               |  12 ++-
 src/kdc/kdc_util.h               |  18 ++--
 src/kprop/kprop.c                |  10 ++-
 src/kprop/kprop.h                |   3 -
 src/kprop/kprop_util.c           |  37 --------
 src/kprop/kpropd.c               |  10 ++-
 src/lib/apputils/net-server.c    | 189 +++++++++------------------------------
 src/lib/krb5/libkrb5.exports     |   3 +
 src/lib/krb5/os/Makefile.in      |   3 +
 src/lib/krb5/os/addr.c           |  91 +++++++++++++++++++
 src/lib/krb5/os/deps             |  10 +++
 src/lib/krb5/os/t_trace.ref      |   4 +-
 src/lib/krb5/os/trace.c          |  13 +--
 23 files changed, 253 insertions(+), 316 deletions(-)

diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 8143dbba7..12eb114a4 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -2409,4 +2409,20 @@ krb5_error_code
 k5_hmac_md5(const krb5_data *key, const krb5_crypto_iov *data, size_t num_data,
             krb5_data *output);
 
+/*
+ * Translate sa to a krb5_address, putting the result in *out with contents
+ * aliased from *sa.  Return KRB5_PROG_ATYPE_NOSUPP if sa is not an IPv4 or
+ * IPv6 address.
+ */
+krb5_error_code
+k5_sockaddr_to_address(const struct sockaddr *sa, krb5_address *out);
+
+/* Place a printable representation of sa (without port) into buf. */
+void
+k5_print_addr(const struct sockaddr *sa, char *buf, size_t len);
+
+/* Place a printable representation of sa (with port) into buf. */
+void
+k5_print_addr_port(const struct sockaddr *sa, char *buf, size_t len);
+
 #endif /* _KRB5_INT_H */
diff --git a/src/include/net-server.h b/src/include/net-server.h
index 29b235eeb..14fc23a43 100644
--- a/src/include/net-server.h
+++ b/src/include/net-server.h
@@ -35,14 +35,6 @@
 /* The delimiter characters supported by the addresses string. */
 #define ADDRESSES_DELIM ",; "
 
-typedef struct _krb5_fulladdr {
-    krb5_address *      address;
-    krb5_ui_4           port;
-} krb5_fulladdr;
-
-/* exported from network.c */
-void init_addr(krb5_fulladdr *, struct sockaddr *);
-
 /* exported from net-server.c */
 verto_ctx *loop_init(verto_ev_type types);
 
@@ -88,8 +80,8 @@ void loop_free(verto_ctx *ctx);
  */
 typedef void (*loop_respond_fn)(void *arg, krb5_error_code code,
                                 krb5_data *response);
-void dispatch(void *handle, const krb5_fulladdr *local_addr,
-              const krb5_fulladdr *remote_addr, krb5_data *request,
+void dispatch(void *handle, const struct sockaddr *local_addr,
+              const struct sockaddr *remote_addr, krb5_data *request,
               int is_tcp, verto_ctx *vctx, loop_respond_fn respond, void *arg);
 krb5_error_code make_toolong_error (void *handle, krb5_data **);
 
diff --git a/src/kadmin/server/schpw.c b/src/kadmin/server/schpw.c
index 00465657a..d366c050a 100644
--- a/src/kadmin/server/schpw.c
+++ b/src/kadmin/server/schpw.c
@@ -18,8 +18,8 @@
 
 static krb5_error_code
 process_chpw_request(krb5_context context, void *server_handle, char *realm,
-                     krb5_keytab keytab, const krb5_fulladdr *local_addr,
-                     const krb5_fulladdr *remote_addr, krb5_data *req,
+                     krb5_keytab keytab, const struct sockaddr *local_addr,
+                     const struct sockaddr *remote_addr, krb5_data *req,
                      krb5_data *rep)
 {
     krb5_error_code ret;
@@ -33,16 +33,14 @@ process_chpw_request(krb5_context context, void *server_handle, char *realm,
     krb5_ticket *ticket = NULL;
     krb5_replay_data replay;
     krb5_error krberror;
+    krb5_address laddr;
     int numresult;
     char strresult[1024];
     char *clientstr = NULL, *targetstr = NULL;
     const char *errmsg = NULL;
     size_t clen;
     char *cdots;
-    struct sockaddr_storage ss;
-    socklen_t salen;
     char addrbuf[100];
-    krb5_address *addr = remote_addr->address;
 
     *rep = empty_data();
 
@@ -222,38 +220,7 @@ process_chpw_request(krb5_context context, void *server_handle, char *realm,
     clen = strlen(clientstr);
     trunc_name(&clen, &cdots);
 
-    switch (addr->addrtype) {
-    case ADDRTYPE_INET: {
-        struct sockaddr_in *sin = ss2sin(&ss);
-
-        sin->sin_family = AF_INET;
-        memcpy(&sin->sin_addr, addr->contents, addr->length);
-        sin->sin_port = htons(remote_addr->port);
-        salen = sizeof(*sin);
-        break;
-    }
-    case ADDRTYPE_INET6: {
-        struct sockaddr_in6 *sin6 = ss2sin6(&ss);
-
-        sin6->sin6_family = AF_INET6;
-        memcpy(&sin6->sin6_addr, addr->contents, addr->length);
-        sin6->sin6_port = htons(remote_addr->port);
-        salen = sizeof(*sin6);
-        break;
-    }
-    default: {
-        struct sockaddr *sa = ss2sa(&ss);
-
-        sa->sa_family = AF_UNSPEC;
-        salen = sizeof(*sa);
-        break;
-    }
-    }
-
-    if (getnameinfo(ss2sa(&ss), salen,
-                    addrbuf, sizeof(addrbuf), NULL, 0,
-                    NI_NUMERICHOST | NI_NUMERICSERV) != 0)
-        strlcpy(addrbuf, "<unprintable>", sizeof(addrbuf));
+    k5_print_addr(remote_addr, addrbuf, sizeof(addrbuf));
 
     if (vno == RFC3244_VERSION) {
         size_t tlen;
@@ -319,8 +286,9 @@ chpwfail:
     cipher = empty_data();
 
     if (ap_rep.length) {
-        ret = krb5_auth_con_setaddrs(context, auth_context,
-                                     local_addr->address, NULL);
+        if (k5_sockaddr_to_address(local_addr, &laddr) != 0)
+            abort();
+        ret = krb5_auth_con_setaddrs(context, auth_context, &laddr, NULL);
         if (ret) {
             numresult = KRB5_KPASSWD_HARDERROR;
             strlcpy(strresult,
@@ -430,8 +398,8 @@ bailout:
 
 /* Dispatch routine for set/change password */
 void
-dispatch(void *handle, const krb5_fulladdr *local_addr,
-         const krb5_fulladdr *remote_addr, krb5_data *request, int is_tcp,
+dispatch(void *handle, const struct sockaddr *local_addr,
+         const struct sockaddr *remote_addr, krb5_data *request, int is_tcp,
          verto_ctx *vctx, loop_respond_fn respond, void *arg)
 {
     krb5_error_code ret;
diff --git a/src/kadmin/server/server_stubs.c b/src/kadmin/server/server_stubs.c
index ef7e809b9..87f67874a 100644
--- a/src/kadmin/server/server_stubs.c
+++ b/src/kadmin/server/server_stubs.c
@@ -150,15 +150,11 @@ client_addr(SVCXPRT *xprt)
     static char abuf[128];
     struct sockaddr_storage ss;
     socklen_t len = sizeof(ss);
-    const char *p = NULL;
 
     if (getpeername(xprt->xp_sock, ss2sa(&ss), &len) != 0)
         return "(unknown)";
-    if (ss2sa(&ss)->sa_family == AF_INET)
-        p = inet_ntop(AF_INET, &ss2sin(&ss)->sin_addr, abuf, sizeof(abuf));
-    else if (ss2sa(&ss)->sa_family == AF_INET6)
-        p = inet_ntop(AF_INET6, &ss2sin6(&ss)->sin6_addr, abuf, sizeof(abuf));
-    return (p == NULL) ? "(unknown)" : p;
+    k5_print_addr(ss2sa(&ss), abuf, sizeof(abuf));
+    return abuf;
 }
 
 /*
diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c
index 28def3be4..13d17b6d3 100644
--- a/src/kdc/dispatch.c
+++ b/src/kdc/dispatch.c
@@ -87,8 +87,8 @@ finish_dispatch_cache(void *arg, krb5_error_code code, krb5_data *response)
 }
 
 void
-dispatch(void *cb, const krb5_fulladdr *local_addr,
-         const krb5_fulladdr *remote_addr, krb5_data *pkt, int is_tcp,
+dispatch(void *cb, const struct sockaddr *local_addr,
+         const struct sockaddr *remote_addr, krb5_data *pkt, int is_tcp,
          verto_ctx *vctx, loop_respond_fn respond, void *arg)
 {
     krb5_error_code retval;
@@ -118,8 +118,7 @@ dispatch(void *cb, const krb5_fulladdr *local_addr,
         const char *name = 0;
         char buf[46];
 
-        name = inet_ntop(ADDRTYPE2FAMILY(remote_addr->address->addrtype),
-                         remote_addr->address->contents, buf, sizeof(buf));
+        k5_print_addr(remote_addr, buf, sizeof(buf));
         if (name == 0)
             name = "[unknown address type]";
         if (response)
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index 6fb214b77..5d588e5be 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -180,8 +180,8 @@ struct as_req_state {
     struct kdc_request_state *rstate;
     char *sname, *cname;
     void *pa_context;
-    const krb5_fulladdr *local_addr;
-    const krb5_fulladdr *remote_addr;
+    const struct sockaddr *local_addr;
+    const struct sockaddr *remote_addr;
     krb5_data **auth_indicators;
 
     krb5_error_code preauth_err;
@@ -468,8 +468,8 @@ finish_preauth(void *arg, krb5_error_code code)
 /*ARGSUSED*/
 void
 process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
-               const krb5_fulladdr *local_addr,
-               const krb5_fulladdr *remote_addr, kdc_realm_t *realm,
+               const struct sockaddr *local_addr,
+               const struct sockaddr *remote_addr, kdc_realm_t *realm,
                verto_ctx *vctx, loop_respond_fn respond, void *arg)
 {
     krb5_context context = realm->realm_context;
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index 0acc45850..f74e0c5e7 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -590,7 +590,7 @@ cleanup:
  */
 static krb5_error_code
 gather_tgs_req_info(kdc_realm_t *realm, krb5_kdc_req **reqptr, krb5_data *pkt,
-                    const krb5_fulladdr *from,
+                    const struct sockaddr *from,
                     struct kdc_request_state *fast_state,
                     krb5_audit_state *au_state, struct tgs_req_info *t,
                     const char **status)
@@ -955,7 +955,7 @@ check_tgs_req(kdc_realm_t *realm, struct tgs_req_info *t,
 static krb5_error_code
 tgs_issue_ticket(kdc_realm_t *realm, struct tgs_req_info *t,
                  krb5_flags tktflags, krb5_ticket_times *times, krb5_data *pkt,
-                 const krb5_fulladdr *from,
+                 const struct sockaddr *from,
                  struct kdc_request_state *fast_state,
                  krb5_audit_state *au_state, const char **status,
                  krb5_data **response)
@@ -1162,7 +1162,7 @@ free_req_info(krb5_context context, struct tgs_req_info *t)
 
 krb5_error_code
 process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
-                const krb5_fulladdr *from, kdc_realm_t *realm,
+                const struct sockaddr *from, kdc_realm_t *realm,
                 krb5_data **response)
 {
     krb5_context context = realm->realm_context;
diff --git a/src/kdc/kdc_audit.c b/src/kdc/kdc_audit.c
index 2333171d7..a5e022489 100644
--- a/src/kdc/kdc_audit.c
+++ b/src/kdc/kdc_audit.c
@@ -176,29 +176,37 @@ kau_make_tkt_id(krb5_context context,
  */
 krb5_error_code
 kau_init_kdc_req(krb5_context context,
-                 krb5_kdc_req *request, const krb5_fulladdr *from,
+                 krb5_kdc_req *request, const struct sockaddr *from,
                  krb5_audit_state **state_out)
 {
     krb5_error_code ret = 0;
     krb5_audit_state *state = NULL;
+    krb5_address addr;
+    const krb5_address unknown_addr = { KV5M_ADDRESS, 0, 0, NULL };
 
     state = k5calloc(1, sizeof(*state), &ret);
     if (state == NULL)
         return ret;
 
+    ret = k5_sockaddr_to_address(from, &addr);
+    if (ret)
+        addr = unknown_addr;
+    ret = krb5_copy_addr(context, &addr, &state->cl_addr);
+    if (ret)
+        goto cleanup;
     state->request = request;
-    state->cl_addr = from->address;
-    state->cl_port = from->port;
+    state->cl_port = sa_getport(from);
     state->stage = AUTHN_REQ_CL;
     ret = krb5int_random_string(context, state->req_id,
                                 sizeof(state->req_id));
-    if (ret) {
-        free(state);
-        return ret;
-    }
+    if (ret)
+        goto cleanup;
     *state_out = state;
+    state = NULL;
 
-    return 0;
+cleanup:
+    kau_free_kdc_req(state);
+    return ret;
 }
 
 /* Free resources allocated by kau_init_kdc_req() and kau_make_tkt_id()
@@ -211,6 +219,7 @@ kau_free_kdc_req(krb5_audit_state *state)
     free(state->tkt_in_id);
     free(state->tkt_out_id);
     free(state->evid_tkt_id);
+    krb5_free_address(NULL, state->cl_addr);
     free(state);
 }
 
diff --git a/src/kdc/kdc_audit.h b/src/kdc/kdc_audit.h
index c2f2e2177..41ddb389d 100644
--- a/src/kdc/kdc_audit.h
+++ b/src/kdc/kdc_audit.h
@@ -47,7 +47,7 @@ kau_make_tkt_id(krb5_context context,
 
 krb5_error_code
 kau_init_kdc_req(krb5_context context, krb5_kdc_req *request,
-                 const krb5_fulladdr *from, krb5_audit_state **au_state);
+                 const struct sockaddr *from, krb5_audit_state **au_state);
 
 void kau_free_kdc_req(krb5_audit_state *state);
 
diff --git a/src/kdc/kdc_log.c b/src/kdc/kdc_log.c
index 9a8894c9a..6278d645a 100644
--- a/src/kdc/kdc_log.c
+++ b/src/kdc/kdc_log.c
@@ -55,25 +55,21 @@
 /* Currently no info about name canonicalization is logged.  */
 void
 log_as_req(krb5_context context,
-           const krb5_fulladdr *local_addr,
-           const krb5_fulladdr *remote_addr,
+           const struct sockaddr *local_addr,
+           const struct sockaddr *remote_addr,
            krb5_kdc_req *request, krb5_kdc_rep *reply,
            krb5_db_entry *client, const char *cname,
            krb5_db_entry *server, const char *sname,
            krb5_timestamp authtime,
            const char *status, krb5_error_code errcode, const char *emsg)
 {
-    const char *fromstring = 0;
-    char fromstringbuf[70];
+    char fromstring[70];
     char *ktypestr = NULL;
     const char *cname2 = cname ? cname : "<unknown client>";
     const char *sname2 = sname ? sname : "<unknown server>";
+    krb5_address laddr = { 0 }, raddr = { 0 };
 
-    fromstring = inet_ntop(ADDRTYPE2FAMILY(remote_addr->address->addrtype),
-                           remote_addr->address->contents,
-                           fromstringbuf, sizeof(fromstringbuf));
-    if (!fromstring)
-        fromstring = "<unknown>";
+    k5_print_addr(remote_addr, fromstring, sizeof(fromstring));
 
     ktypestr = ktypes2str(request->ktype, request->nktypes);
 
@@ -92,9 +88,10 @@ log_as_req(krb5_context context,
                          ktypestr ? ktypestr : "", fromstring, status, cname2,
                          sname2, emsg ? ", " : "", emsg ? emsg : "");
     }
-    krb5_db_audit_as_req(context, request,
-                         local_addr->address, remote_addr->address,
-                         client, server, authtime, errcode);
+    (void)k5_sockaddr_to_address(local_addr, &laddr);
+    (void)k5_sockaddr_to_address(remote_addr, &raddr);
+    krb5_db_audit_as_req(context, request, &laddr, &raddr, client, server,
+                         authtime, errcode);
 
     free(ktypestr);
 }
@@ -117,7 +114,7 @@ unparse_and_limit(krb5_context ctx, krb5_principal princ, char **str)
 
    Currently no info about name canonicalization is logged.  */
 void
-log_tgs_req(krb5_context ctx, const krb5_fulladdr *from,
+log_tgs_req(krb5_context ctx, const struct sockaddr *from,
             krb5_kdc_req *request, krb5_kdc_rep *reply,
             krb5_principal cprinc, krb5_principal sprinc,
             krb5_principal altcprinc,
@@ -126,16 +123,11 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from,
             const char *status, krb5_error_code errcode, const char *emsg)
 {
     char *ktypestr = NULL, *rep_etypestr = NULL;
-    const char *fromstring = 0;
-    char fromstringbuf[70];
+    char fromstring[70];
     char *cname = NULL, *sname = NULL, *altcname = NULL;
     char *logcname = NULL, *logsname = NULL, *logaltcname = NULL;
 
-    fromstring = inet_ntop(ADDRTYPE2FAMILY(from->address->addrtype),
-                           from->address->contents,
-                           fromstringbuf, sizeof(fromstringbuf));
-    if (!fromstring)
-        fromstring = "<unknown>";
+    k5_print_addr(from, fromstring, sizeof(fromstring));
 
     unparse_and_limit(ctx, cprinc, &cname);
     logcname = (cname != NULL) ? cname : "<unknown client>";
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index e54cc751f..b7249c083 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -142,7 +142,7 @@ comp_cksum(krb5_context kcontext, krb5_data *source, krb5_ticket *ticket,
 /* If a header ticket is decrypted, *ticket_out is filled in even on error. */
 krb5_error_code
 kdc_process_tgs_req(kdc_realm_t *realm, krb5_kdc_req *request,
-                    const krb5_fulladdr *from, krb5_data *pkt,
+                    const struct sockaddr *from, krb5_data *pkt,
                     krb5_ticket **ticket_out, krb5_db_entry **krbtgt_ptr,
                     krb5_keyblock **tgskey, krb5_keyblock **subkey,
                     krb5_pa_data **pa_tgs_req)
@@ -159,6 +159,8 @@ kdc_process_tgs_req(kdc_realm_t *realm, krb5_kdc_req *request,
     krb5_checksum       * his_cksum = NULL;
     krb5_db_entry       * krbtgt = NULL;
     krb5_ticket         * ticket;
+    krb5_address          from_addr;
+    const krb5_address    nomatch_addr = { KV5M_ADDRESS, 0, 0, NULL };
 
     *ticket_out = NULL;
     *krbtgt_ptr = NULL;
@@ -190,8 +192,12 @@ kdc_process_tgs_req(kdc_realm_t *realm, krb5_kdc_req *request,
     if (retval)
         goto cleanup;
 
-    retval = krb5_auth_con_setaddrs(context, auth_context, NULL,
-                                    from->address);
+    /* If from_addr isn't IPv4 or IPv6, fake up an address that won't be
+     * matched if the ticket has an address list. */
+    retval = k5_sockaddr_to_address(from, &from_addr);
+    if (retval)
+        from_addr = nomatch_addr;
+    retval = krb5_auth_con_setaddrs(context, auth_context, NULL, &from_addr);
     if (retval)
         goto cleanup_auth_context;
 
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index 58b2f74de..3b361e4a4 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -56,7 +56,7 @@ krb5_error_code
 kdc_convert_key (krb5_keyblock *, krb5_keyblock *, int);
 krb5_error_code
 kdc_process_tgs_req (kdc_realm_t *, krb5_kdc_req *,
-                     const krb5_fulladdr *,
+                     const struct sockaddr *,
                      krb5_data *,
                      krb5_ticket **,
                      krb5_db_entry **krbtgt_ptr,
@@ -148,18 +148,18 @@ cammac_check_kdcver(krb5_context context, krb5_cammac *cammac,
 /* do_as_req.c */
 void
 process_as_req (krb5_kdc_req *, krb5_data *,
-                const krb5_fulladdr *, const krb5_fulladdr *, kdc_realm_t *,
-                verto_ctx *, loop_respond_fn, void *);
+                const struct sockaddr *, const struct sockaddr *,
+                kdc_realm_t *, verto_ctx *, loop_respond_fn, void *);
 
 /* do_tgs_req.c */
 krb5_error_code
-process_tgs_req (krb5_kdc_req *, krb5_data *, const krb5_fulladdr *,
+process_tgs_req (krb5_kdc_req *, krb5_data *, const struct sockaddr *,
                  kdc_realm_t *, krb5_data ** );
 /* dispatch.c */
 void
 dispatch (void *,
-          const krb5_fulladdr *,
-          const krb5_fulladdr *,
+          const struct sockaddr *,
+          const struct sockaddr *,
           krb5_data *,
           int,
           verto_ctx *,
@@ -315,15 +315,15 @@ kdc_get_ticket_renewtime(kdc_realm_t *realm, krb5_kdc_req *request,
 
 void
 log_as_req(krb5_context context,
-           const krb5_fulladdr *local_addr,
-           const krb5_fulladdr *remote_addr,
+           const struct sockaddr *local_addr,
+           const struct sockaddr *remote_addr,
            krb5_kdc_req *request, krb5_kdc_rep *reply,
            krb5_db_entry *client, const char *cname,
            krb5_db_entry *server, const char *sname,
            krb5_timestamp authtime,
            const char *status, krb5_error_code errcode, const char *emsg);
 void
-log_tgs_req(krb5_context ctx, const krb5_fulladdr *from,
+log_tgs_req(krb5_context ctx, const struct sockaddr *from,
             krb5_kdc_req *request, krb5_kdc_rep *reply,
             krb5_principal cprinc, krb5_principal sprinc,
             krb5_principal altcprinc,
diff --git a/src/kprop/kprop.c b/src/kprop/kprop.c
index e8f7feb69..cb5c5267a 100644
--- a/src/kprop/kprop.c
+++ b/src/kprop/kprop.c
@@ -217,9 +217,9 @@ static void
 open_connection(krb5_context context, char *host, int *fd_out)
 {
     krb5_error_code retval;
+    krb5_address addr;
     GETSOCKNAME_ARG3_TYPE socket_length;
     struct addrinfo hints, *res, *answers;
-    struct sockaddr *sa;
     struct sockaddr_storage my_sin;
     int s, error;
 
@@ -269,9 +269,11 @@ open_connection(krb5_context context, char *host, int *fd_out)
         com_err(progname, errno, _("while getting local socket address"));
         exit(1);
     }
-    sa = (struct sockaddr *)&my_sin;
-    if (sockaddr2krbaddr(context, sa->sa_family, sa, &sender_addr) != 0) {
-        com_err(progname, errno, _("while converting local address"));
+    if (k5_sockaddr_to_address(ss2sa(&my_sin), &addr) != 0)
+        abort();
+    retval = krb5_copy_addr(context, &addr, &sender_addr);
+    if (retval) {
+        com_err(progname, retval, _("while converting local address"));
         exit(1);
     }
 }
diff --git a/src/kprop/kprop.h b/src/kprop/kprop.h
index 3a319b535..5330227fe 100644
--- a/src/kprop/kprop.h
+++ b/src/kprop/kprop.h
@@ -36,9 +36,6 @@
 
 /* pathnames are in osconf.h, included via k5-int.h */
 
-int sockaddr2krbaddr(krb5_context context, int family, struct sockaddr *sa,
-                     krb5_address **dest);
-
 krb5_error_code
 sn2princ_realm(krb5_context context, const char *hostname, const char *sname,
                const char *realm, krb5_principal *princ_out);
diff --git a/src/kprop/kprop_util.c b/src/kprop/kprop_util.c
index 795c67648..94c623a69 100644
--- a/src/kprop/kprop_util.c
+++ b/src/kprop/kprop_util.c
@@ -29,43 +29,6 @@
 #include "k5-int.h"
 #include "kprop.h"
 
-#include <sys/types.h>
-#include <sys/socket.h>
-
-/*
- * Convert an IPv4 or IPv6 socket address to a newly allocated krb5_address.
- * There is similar code elsewhere in the tree, so this should possibly become
- * a libkrb5 API in the future.
- */
-krb5_error_code
-sockaddr2krbaddr(krb5_context context, int family, struct sockaddr *sa,
-                 krb5_address **dest)
-{
-    krb5_address addr;
-
-    addr.magic = KV5M_ADDRESS;
-    if (family == AF_INET) {
-        const struct sockaddr_in *sa4 = sa2sin(sa);
-        addr.addrtype = ADDRTYPE_INET;
-        addr.length = sizeof(sa4->sin_addr);
-        addr.contents = (krb5_octet *) &sa4->sin_addr;
-    } else if (family == AF_INET6) {
-        const struct sockaddr_in6 *sa6 = sa2sin6(sa);
-        if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) {
-            addr.addrtype = ADDRTYPE_INET;
-            addr.contents = (krb5_octet *) &sa6->sin6_addr + 12;
-            addr.length = 4;
-        } else {
-            addr.addrtype = ADDRTYPE_INET6;
-            addr.length = sizeof(sa6->sin6_addr);
-            addr.contents = (krb5_octet *) &sa6->sin6_addr;
-        }
-    } else
-        return KRB5_PROG_ATYPE_NOSUPP;
-
-    return krb5_copy_addr(context, &addr, dest);
-}
-
 /* Construct a host-based principal, similar to krb5_sname_to_principal() but
  * with a specified realm. */
 krb5_error_code
diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c
index be48062ff..d6deb4738 100644
--- a/src/kprop/kpropd.c
+++ b/src/kprop/kpropd.c
@@ -1186,6 +1186,7 @@ kerberos_authenticate(krb5_context context, int fd, krb5_principal *clientp,
                       krb5_enctype *etype, struct sockaddr_storage *my_sin)
 {
     krb5_error_code retval;
+    krb5_address addr;
     krb5_ticket *ticket;
     struct sockaddr_storage r_sin;
     GETSOCKNAME_ARG3_TYPE sin_length;
@@ -1198,8 +1199,13 @@ kerberos_authenticate(krb5_context context, int fd, krb5_principal *clientp,
         exit(1);
     }
 
-    sockaddr2krbaddr(context, r_sin.ss_family, (struct sockaddr *)&r_sin,
-                     &receiver_addr);
+    if (k5_sockaddr_to_address(ss2sa(my_sin), &addr) != 0)
+        abort();
+    retval = krb5_copy_addr(context, &addr, &receiver_addr);
+    if (retval) {
+        com_err(progname, retval, _("while converting local address"));
+        exit(1);
+    }
 
     if (debug) {
         retval = krb5_unparse_name(context, server, &name);
diff --git a/src/lib/apputils/net-server.c b/src/lib/apputils/net-server.c
index 18a3392f9..3713b5026 100644
--- a/src/lib/apputils/net-server.c
+++ b/src/lib/apputils/net-server.c
@@ -94,27 +94,6 @@ setv6only(int sock, int value)
 }
 #endif
 
-static const char *
-paddr(struct sockaddr *sa)
-{
-    static char buf[100];
-    char portbuf[10];
-    if (getnameinfo(sa, sa_socklen(sa),
-                    buf, sizeof(buf), portbuf, sizeof(portbuf),
-                    NI_NUMERICHOST|NI_NUMERICSERV))
-        strlcpy(buf, "<unprintable>", sizeof(buf));
-    else {
-        unsigned int len = sizeof(buf) - strlen(buf);
-        char *p = buf + strlen(buf);
-        if (len > 2+strlen(portbuf)) {
-            *p++ = '.';
-            len--;
-            strncpy(p, portbuf, len);
-        }
-    }
-    return buf;
-}
-
 /* KDC data.  */
 
 enum conn_type {
@@ -141,8 +120,6 @@ struct connection {
     struct sockaddr_storage addr_s;
     socklen_t addrlen;
     char addrbuf[56];
-    krb5_address remote_addr_buf;
-    krb5_fulladdr remote_addr;
 
     /* Incoming data (TCP) */
     size_t bufsiz;
@@ -587,14 +564,15 @@ create_server_socket(struct sockaddr *addr, int type, const char *prog,
                      int *fd_out)
 {
     int sock, e;
+    char addrbuf[128];
 
     *fd_out = -1;
 
     sock = socket(addr->sa_family, type, 0);
     if (sock == -1) {
         e = errno;
-        com_err(prog, e, _("Cannot create TCP server socket on %s"),
-                paddr(addr));
+        k5_print_addr_port(addr, addrbuf, sizeof(addrbuf));
+        com_err(prog, e, _("Cannot create TCP server socket on %s"), addrbuf);
         return e;
     }
     set_cloexec_fd(sock);
@@ -602,8 +580,9 @@ create_server_socket(struct sockaddr *addr, int type, const char *prog,
 #ifndef _WIN32                  /* Windows FD_SETSIZE is a count. */
     if (sock >= FD_SETSIZE) {
         close(sock);
+        k5_print_addr_port(addr, addrbuf, sizeof(addrbuf));
         com_err(prog, 0, _("TCP socket fd number %d (for %s) too high"),
-                sock, paddr(addr));
+                sock, addrbuf);
         return EMFILE;
     }
 #endif
@@ -626,7 +605,8 @@ create_server_socket(struct sockaddr *addr, int type, const char *prog,
 
     if (bind(sock, addr, sa_socklen(addr)) == -1) {
         e = errno;
-        com_err(prog, e, _("Cannot bind server socket on %s"), paddr(addr));
+        k5_print_addr_port(addr, addrbuf, sizeof(addrbuf));
+        com_err(prog, e, _("Cannot bind server socket on %s"), addrbuf);
         close(sock);
         return e;
     }
@@ -695,9 +675,11 @@ setup_socket(struct bind_address *ba, struct sockaddr *sock_address,
     verto_ev_flag flags;
     verto_ev *ev = NULL;
     int sock = -1;
+    char addrbuf[128];
 
+    k5_print_addr_port(sock_address, addrbuf, sizeof(addrbuf));
     krb5_klog_syslog(LOG_DEBUG, _("Setting up %s socket for address %s"),
-                     bind_type_names[ba->type], paddr(sock_address));
+                     bind_type_names[ba->type], addrbuf);
 
     /* Create the socket. */
     ret = create_server_socket(sock_address, bind_socktypes[ba->type], prog,
@@ -710,7 +692,7 @@ setup_socket(struct bind_address *ba, struct sockaddr *sock_address,
     if (ba->type == TCP && listen(sock, tcp_listen_backlog) != 0) {
         ret = errno;
         com_err(prog, errno, _("Cannot listen on %s server socket on %s"),
-                bind_type_names[ba->type], paddr(sock_address));
+                bind_type_names[ba->type], addrbuf);
         goto cleanup;
     }
 
@@ -719,7 +701,7 @@ setup_socket(struct bind_address *ba, struct sockaddr *sock_address,
         ret = errno;
         com_err(prog, errno,
                 _("cannot set listening %s socket on %s non-blocking"),
-                bind_type_names[ba->type], paddr(sock_address));
+                bind_type_names[ba->type], addrbuf);
         goto cleanup;
     }
 
@@ -727,19 +709,19 @@ setup_socket(struct bind_address *ba, struct sockaddr *sock_address,
     if (ba->type == TCP && setnolinger(sock) != 0) {
         ret = errno;
         com_err(prog, errno, _("cannot set SO_LINGER on %s socket on %s"),
-                bind_type_names[ba->type], paddr(sock_address));
+                bind_type_names[ba->type], addrbuf);
         goto cleanup;
     }
 
     /* Try to turn on pktinfo for UDP wildcard sockets. */
     if (ba->type == UDP && sa_is_wildcard(sock_address)) {
         krb5_klog_syslog(LOG_DEBUG, _("Setting pktinfo on socket %s"),
-                         paddr(sock_address));
+                         addrbuf);
         ret = set_pktinfo(sock, sock_address->sa_family);
         if (ret) {
             com_err(prog, ret,
                     _("Cannot request packet info for UDP socket address "
-                      "%s port %d"), paddr(sock_address), ba->port);
+                      "%s port %d"), addrbuf, ba->port);
             krb5_klog_syslog(LOG_INFO, _("System does not support pktinfo yet "
                                          "binding to a wildcard address.  "
                                          "Packets are not guaranteed to "
@@ -812,6 +794,7 @@ setup_addresses(verto_ctx *ctx, void *handle, const char *prog,
     struct bind_address addr;
     struct addrinfo hints, *ai_list = NULL, *ai = NULL;
     verto_callback vcb;
+    char addrbuf[128];
 
     /* Check to make sure addresses were added to the server. */
     if (bind_addresses.n == 0) {
@@ -866,10 +849,10 @@ setup_addresses(verto_ctx *ctx, void *handle, const char *prog,
                                tcp_listen_backlog, verto_callbacks[addr.type],
                                bind_conn_types[addr.type]);
             if (ret) {
+                k5_print_addr(ai->ai_addr, addrbuf, sizeof(addrbuf));
                 krb5_klog_syslog(LOG_ERR,
                                  _("Failed setting up a %s socket (for %s)"),
-                                 bind_type_names[addr.type],
-                                 paddr(ai->ai_addr));
+                                 bind_type_names[addr.type], addrbuf);
                 if (ret != EAFNOSUPPORT)
                     goto cleanup;
             } else {
@@ -924,45 +907,10 @@ loop_setup_network(verto_ctx *ctx, void *handle, const char *prog,
     return 0;
 }
 
-void
-init_addr(krb5_fulladdr *faddr, struct sockaddr *sa)
-{
-    switch (sa->sa_family) {
-    case AF_INET:
-        faddr->address->addrtype = ADDRTYPE_INET;
-        faddr->address->length = 4;
-        faddr->address->contents = (krb5_octet *) &sa2sin(sa)->sin_addr;
-        faddr->port = ntohs(sa2sin(sa)->sin_port);
-        break;
-    case AF_INET6:
-        if (IN6_IS_ADDR_V4MAPPED(&sa2sin6(sa)->sin6_addr)) {
-            faddr->address->addrtype = ADDRTYPE_INET;
-            faddr->address->length = 4;
-            faddr->address->contents = 12 + (krb5_octet *) &sa2sin6(sa)->sin6_addr;
-        } else {
-            faddr->address->addrtype = ADDRTYPE_INET6;
-            faddr->address->length = 16;
-            faddr->address->contents = (krb5_octet *) &sa2sin6(sa)->sin6_addr;
-        }
-        faddr->port = ntohs(sa2sin6(sa)->sin6_port);
-        break;
-    default:
-        faddr->address->addrtype = -1;
-        faddr->address->length = 0;
-        faddr->address->contents = 0;
-        faddr->port = 0;
-        break;
-    }
-}
-
 struct udp_dispatch_state {
     void *handle;
     const char *prog;
     int port_fd;
-    krb5_address remote_addr_buf;
-    krb5_fulladdr remote_addr;
-    krb5_address local_addr_buf;
-    krb5_fulladdr local_addr;
     struct sockaddr_storage saddr;
     struct sockaddr_storage daddr;
     aux_addressing_info auxaddr;
@@ -988,25 +936,13 @@ process_packet_response(void *arg, krb5_error_code code, krb5_data *response)
     if (cc == -1) {
         /* Note that the local address (daddr*) has no port number
          * info associated with it. */
-        char saddrbuf[NI_MAXHOST], sportbuf[NI_MAXSERV];
-        char daddrbuf[NI_MAXHOST];
+        char sbuf[128], dbuf[128];
         int e = errno;
 
-        if (getnameinfo(ss2sa(&state->daddr), sa_socklen(ss2sa(&state->daddr)),
-                        daddrbuf, sizeof(daddrbuf), 0, 0,
-                        NI_NUMERICHOST) != 0) {
-            strlcpy(daddrbuf, "?", sizeof(daddrbuf));
-        }
-
-        if (getnameinfo(ss2sa(&state->saddr), sa_socklen(ss2sa(&state->saddr)),
-                        saddrbuf, sizeof(saddrbuf), sportbuf, sizeof(sportbuf),
-                        NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
-            strlcpy(saddrbuf, "?", sizeof(saddrbuf));
-            strlcpy(sportbuf, "?", sizeof(sportbuf));
-        }
-
-        com_err(state->prog, e, _("while sending reply to %s/%s from %s"),
-                saddrbuf, sportbuf, daddrbuf);
+        k5_print_addr_port(ss2sa(&state->saddr), sbuf, sizeof(sbuf));
+        k5_print_addr(ss2sa(&state->daddr), dbuf, sizeof(dbuf));
+        com_err(state->prog, e, _("while sending reply to %s from %s"),
+                sbuf, dbuf);
         goto out;
     }
     if ((size_t)cc != response->length) {
@@ -1074,14 +1010,7 @@ process_packet(verto_ctx *ctx, verto_ev *ev)
     state->request.length = cc;
     state->request.data = state->pktbuf;
 
-    state->remote_addr.address = &state->remote_addr_buf;
-    init_addr(&state->remote_addr, ss2sa(&state->saddr));
-
-    state->local_addr.address = &state->local_addr_buf;
-    init_addr(&state->local_addr, ss2sa(&state->daddr));
-
-    /* This address is in net order. */
-    dispatch(state->handle, &state->local_addr, &state->remote_addr,
+    dispatch(state->handle, ss2sa(&state->daddr), ss2sa(&state->saddr),
              &state->request, 0, ctx, process_packet_response, state);
 }
 
@@ -1124,16 +1053,14 @@ static void
 accept_tcp_connection(verto_ctx *ctx, verto_ev *ev)
 {
     int s;
-    struct sockaddr_storage addr_s;
-    struct sockaddr *addr = (struct sockaddr *)&addr_s;
-    socklen_t addrlen = sizeof(addr_s);
+    struct sockaddr_storage addr;
+    socklen_t addrlen = sizeof(addr);
     struct connection *newconn, *conn;
-    char tmpbuf[10];
     verto_ev_flag flags;
     verto_ev *newev;
 
     conn = verto_get_private(ev);
-    s = accept(verto_get_fd(ev), addr, &addrlen);
+    s = accept(verto_get_fd(ev), ss2sa(&addr), &addrlen);
     if (s < 0)
         return;
     set_cloexec_fd(s);
@@ -1153,23 +1080,9 @@ accept_tcp_connection(verto_ctx *ctx, verto_ev *ev)
     }
     newconn = verto_get_private(newev);
 
-    if (getnameinfo((struct sockaddr *)&addr_s, addrlen,
-                    newconn->addrbuf, sizeof(newconn->addrbuf),
-                    tmpbuf, sizeof(tmpbuf),
-                    NI_NUMERICHOST | NI_NUMERICSERV))
-        strlcpy(newconn->addrbuf, "???", sizeof(newconn->addrbuf));
-    else {
-        char *p, *end;
-        p = newconn->addrbuf;
-        end = p + sizeof(newconn->addrbuf);
-        p += strlen(p);
-        if ((size_t)(end - p) > 2 + strlen(tmpbuf)) {
-            *p++ = '.';
-            strlcpy(p, tmpbuf, end - p);
-        }
-    }
-
-    newconn->addr_s = addr_s;
+    k5_print_addr_port(ss2sa(&addr), newconn->addrbuf,
+                       sizeof(newconn->addrbuf));
+    newconn->addr_s = addr;
     newconn->addrlen = addrlen;
     newconn->bufsiz = 1024 * 1024;
     newconn->buffer = malloc(newconn->bufsiz);
@@ -1186,16 +1099,12 @@ accept_tcp_connection(verto_ctx *ctx, verto_ev *ev)
         return;
     }
     newconn->offset = 0;
-    newconn->remote_addr.address = &newconn->remote_addr_buf;
-    init_addr(&newconn->remote_addr, ss2sa(&newconn->addr_s));
     SG_SET(&newconn->sgbuf[0], newconn->lenbuf, 4);
     SG_SET(&newconn->sgbuf[1], 0, 0);
 }
 
 struct tcp_dispatch_state {
     struct sockaddr_storage local_saddr;
-    krb5_address local_addr_buf;
-    krb5_fulladdr local_addr;
     struct connection *conn;
     krb5_data request;
     verto_ctx *ctx;
@@ -1342,10 +1251,9 @@ process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev)
                              error_message(errno));
             goto kill_tcp_connection;
         }
-        state->local_addr.address = &state->local_addr_buf;
-        init_addr(&state->local_addr, ss2sa(&state->local_saddr));
-        dispatch(state->conn->handle, &state->local_addr, &conn->remote_addr,
-                 &state->request, 1, ctx, process_tcp_response, state);
+        dispatch(state->conn->handle, ss2sa(&state->local_saddr),
+                 ss2sa(&conn->addr_s), &state->request, 1, ctx,
+                 process_tcp_response, state);
     }
 
     return;
@@ -1441,11 +1349,9 @@ accept_rpc_connection(verto_ctx *ctx, verto_ev *ev)
 
     /* Scan svc_fdset for any new connections. */
     for (s = 0; s < FD_SETSIZE; s++) {
-        struct sockaddr_storage addr_s;
-        struct sockaddr *addr = (struct sockaddr *) &addr_s;
-        socklen_t addrlen = sizeof(addr_s);
+        struct sockaddr_storage addr;
+        socklen_t addrlen = sizeof(addr);
         struct connection *newconn;
-        char tmpbuf[10];
         verto_ev *newev;
 
         /* If we already have this fd, continue. */
@@ -1460,34 +1366,19 @@ accept_rpc_connection(verto_ctx *ctx, verto_ev *ev)
 
         set_cloexec_fd(s);
 
-        if (getpeername(s, addr, &addrlen) ||
-            getnameinfo(addr, addrlen,
-                        newconn->addrbuf,
-                        sizeof(newconn->addrbuf),
-                        tmpbuf, sizeof(tmpbuf),
-                        NI_NUMERICHOST | NI_NUMERICSERV)) {
-            strlcpy(newconn->addrbuf, "???",
-                    sizeof(newconn->addrbuf));
+        if (getpeername(s, ss2sa(&addr), &addrlen) != 0) {
+            strlcpy(newconn->addrbuf, "<unknown>", sizeof(newconn->addrbuf));
         } else {
-            char *p, *end;
-            p = newconn->addrbuf;
-            end = p + sizeof(newconn->addrbuf);
-            p += strlen(p);
-            if ((size_t)(end - p) > 2 + strlen(tmpbuf)) {
-                *p++ = '.';
-                strlcpy(p, tmpbuf, end - p);
-            }
+            k5_print_addr_port(ss2sa(&addr), newconn->addrbuf,
+                               sizeof(newconn->addrbuf));
         }
 
-        newconn->addr_s = addr_s;
+        newconn->addr_s = addr;
         newconn->addrlen = addrlen;
         newconn->start_time = time(0);
 
         if (++tcp_or_rpc_data_counter > max_tcp_or_rpc_data_connections)
             kill_lru_tcp_or_rpc_connection(newconn->handle, newev);
-
-        newconn->remote_addr.address = &newconn->remote_addr_buf;
-        init_addr(&newconn->remote_addr, ss2sa(&newconn->addr_s));
     }
 }
 
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
index 4c50e935a..63bc7a86c 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -169,6 +169,8 @@ k5_plugin_load
 k5_plugin_load_all
 k5_plugin_register
 k5_plugin_register_dyn
+k5_print_addr
+k5_print_addr_port
 k5_rc_close
 k5_rc_get_name
 k5_rc_resolve
@@ -180,6 +182,7 @@ k5_size_context
 k5_size_keyblock
 k5_size_principal
 k5_sname_compare
+k5_sockaddr_to_address
 k5_unmarshal_cred
 k5_unmarshal_princ
 k5_unwrap_cammac_svc
diff --git a/src/lib/krb5/os/Makefile.in b/src/lib/krb5/os/Makefile.in
index e84b5b747..9a0d286c3 100644
--- a/src/lib/krb5/os/Makefile.in
+++ b/src/lib/krb5/os/Makefile.in
@@ -13,6 +13,7 @@ RUN_TEST_LOCAL_CONF=$(RUN_SETUP) KRB5_CONFIG=$(srcdir)/td_krb5.conf LC_ALL=C \
 
 STLIBOBJS= \
 	accessor.o	\
+	addr.o		\
 	c_ustime.o	\
 	ccdefname.o	\
 	changepw.o	\
@@ -60,6 +61,7 @@ STLIBOBJS= \
 
 OBJS= \
 	$(OUTPRE)accessor.$(OBJEXT)	\
+	$(OUTPRE)addr.$(OBJEXT)		\
 	$(OUTPRE)c_ustime.$(OBJEXT)	\
 	$(OUTPRE)ccdefname.$(OBJEXT)	\
 	$(OUTPRE)changepw.$(OBJEXT)	\
@@ -107,6 +109,7 @@ OBJS= \
 
 SRCS= \
 	$(srcdir)/accessor.c    \
+	$(srcdir)/addr.c	\
 	$(srcdir)/c_ustime.c	\
 	$(srcdir)/ccdefname.c	\
 	$(srcdir)/changepw.c	\
diff --git a/src/lib/krb5/os/addr.c b/src/lib/krb5/os/addr.c
new file mode 100644
index 000000000..1d8ae7501
--- /dev/null
+++ b/src/lib/krb5/os/addr.c
@@ -0,0 +1,91 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/krb5/os/addr.c - socket address utilities */
+/*
+ * Copyright (C) 2024 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "k5-int.h"
+#include "socket-utils.h"
+
+krb5_error_code
+k5_sockaddr_to_address(const struct sockaddr *sa, krb5_address *out)
+{
+    if (sa->sa_family == AF_INET) {
+        const struct sockaddr_in *sin = sa2sin(sa);
+        out->addrtype = ADDRTYPE_INET;
+        out->length = sizeof(sin->sin_addr);
+        out->contents = (uint8_t *)&sin->sin_addr;
+    } else if (sa->sa_family == AF_INET6) {
+        const struct sockaddr_in6 *sin6 = sa2sin6(sa);
+        if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+            out->addrtype = ADDRTYPE_INET;
+            out->contents = (uint8_t *)&sin6->sin6_addr + 12;
+            out->length = 4;
+        } else {
+            out->addrtype = ADDRTYPE_INET6;
+            out->length = sizeof(sin6->sin6_addr);
+            out->contents = (uint8_t *)&sin6->sin6_addr;
+        }
+    } else {
+        return KRB5_PROG_ATYPE_NOSUPP;
+    }
+    out->magic = KV5M_ADDRESS;
+    return 0;
+}
+
+void
+k5_print_addr(const struct sockaddr *sa, char *buf, size_t len)
+{
+    if (sa_is_inet(sa)) {
+        if (getnameinfo(sa, sa_socklen(sa), buf, len, NULL, 0,
+                        NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+            strlcpy(buf, "<unknown>", len);
+    } else {
+        strlcpy(buf, "<unknown>", len);
+    }
+}
+
+void
+k5_print_addr_port(const struct sockaddr *sa, char *buf, size_t len)
+{
+    char addr[64], port[10];
+
+    if (sa_is_inet(sa)) {
+        if (getnameinfo(sa, sa_socklen(sa), addr, sizeof(addr), port,
+                        sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
+            strlcpy(buf, "<unknown>", len);
+        } else if (sa->sa_family == AF_INET) {
+            (void)snprintf(buf, len, "%s:%s", addr, port);
+        } else {
+            (void)snprintf(buf, len, "[%s]:%s", addr, port);
+        }
+    } else {
+        k5_print_addr(sa, buf, len);
+    }
+}
diff --git a/src/lib/krb5/os/deps b/src/lib/krb5/os/deps
index 9add6eca9..4c052d550 100644
--- a/src/lib/krb5/os/deps
+++ b/src/lib/krb5/os/deps
@@ -13,6 +13,16 @@ accessor.so accessor.po $(OUTPRE)accessor.$(OBJEXT): \
   $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \
   $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
   accessor.c os-proto.h
+addr.so addr.po $(OUTPRE)addr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
+  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h addr.c
 c_ustime.so c_ustime.po $(OUTPRE)c_ustime.$(OBJEXT): \
   $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
   $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
diff --git a/src/lib/krb5/os/t_trace.ref b/src/lib/krb5/os/t_trace.ref
index 044a66999..79d3b7a99 100644
--- a/src/lib/krb5/os/t_trace.ref
+++ b/src/lib/krb5/os/t_trace.ref
@@ -10,8 +10,8 @@ size_t and const char *, as four-character hex hash: 7B9A
 size_t and const char *, as four-character hex hash: (null)
 struct remote_address *, show socket type, address, port: stream 0.0.0.0:88
 struct remote_address *, show socket type, address, port: dgram 0.0.0.0:88
-struct remote_address *, show socket type, address, port: transport1234 AF_UNSPEC
-struct remote_address *, show socket type, address, port: transport1234 af5678
+struct remote_address *, show socket type, address, port: transport1234 <unknown>
+struct remote_address *, show socket type, address, port: transport1234 <unknown>
 krb5_data *, display as counted string: example.data
 krb5_data *, display as counted string: (null)
 krb5_data *, display as hex bytes: 6578616D706C652E64617461
diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
index cc6d3982b..89e796f69 100644
--- a/src/lib/krb5/os/trace.c
+++ b/src/lib/krb5/os/trace.c
@@ -180,7 +180,7 @@ trace_format(krb5_context context, const char *fmt, va_list ap)
     struct remote_address *ra;
     const krb5_data *d;
     krb5_data data;
-    char addrbuf[NI_MAXHOST], portbuf[NI_MAXSERV], tmpbuf[200], *str;
+    char addrbuf[128], tmpbuf[200], *str;
     const char *p;
     krb5_const_principal princ;
     const krb5_keyblock *keyblock;
@@ -255,15 +255,8 @@ trace_format(krb5_context context, const char *fmt, va_list ap)
             else
                 k5_buf_add_fmt(&buf, "transport%d", ra->transport);
 
-            if (getnameinfo((struct sockaddr *)&ra->saddr, ra->len,
-                            addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf),
-                            NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
-                if (ra->family == AF_UNSPEC)
-                    k5_buf_add(&buf, " AF_UNSPEC");
-                else
-                    k5_buf_add_fmt(&buf, " af%d", ra->family);
-            } else
-                k5_buf_add_fmt(&buf, " %s:%s", addrbuf, portbuf);
+            k5_print_addr_port(ss2sa(&ra->saddr), addrbuf, sizeof(addrbuf));
+            k5_buf_add_fmt(&buf, " %s", addrbuf);
         } else if (strcmp(tmpbuf, "data") == 0) {
             d = va_arg(ap, krb5_data *);
             if (d == NULL || (d->length != 0 && d->data == NULL))


More information about the cvs-krb5 mailing list