root/usr/src/cmd/cmd-inet/usr.lib/in.ndpd/trace.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#include "defs.h"
#include "tables.h"

static void     print_opt(struct nd_opt_hdr *opt, int len);

void
print_route_sol(char *str, struct phyint *pi,
    struct nd_router_solicit *rs, int len, struct sockaddr_in6 *addr)
{
        struct nd_opt_hdr *opt;
        char abuf[INET6_ADDRSTRLEN];

        logmsg(LOG_DEBUG, "%s %s (%d bytes) on %s\n", str,
            inet_ntop(addr->sin6_family, (void *)&addr->sin6_addr,
            abuf, sizeof (abuf)),
            len, pi->pi_name);

        len -= sizeof (*rs);
        opt = (struct nd_opt_hdr *)&rs[1];
        print_opt(opt, len);
}

void
print_route_adv(char *str, struct phyint *pi,
    struct nd_router_advert *ra, int len, struct sockaddr_in6 *addr)
{
        struct nd_opt_hdr *opt;
        char abuf[INET6_ADDRSTRLEN];

        logmsg(LOG_DEBUG, "%s %s (%d bytes) on %s\n", str,
            inet_ntop(addr->sin6_family, (void *)&addr->sin6_addr,
            abuf, sizeof (abuf)),
            len, pi->pi_name);
        logmsg(LOG_DEBUG, "\tMax hop limit: %u\n", ra->nd_ra_curhoplimit);
        logmsg(LOG_DEBUG, "\tManaged address configuration: %s\n",
            (ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) ?
            "Set" : "Not set");
        logmsg(LOG_DEBUG, "\tOther configuration flag: %s\n",
            (ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) ?
            "Set" : "Not set");
        logmsg(LOG_DEBUG, "\tRouter lifetime: %u\n",
            ntohs(ra->nd_ra_router_lifetime));
        logmsg(LOG_DEBUG, "\tReachable timer: %u\n",
            ntohl(ra->nd_ra_reachable));
        logmsg(LOG_DEBUG, "\tReachable retrans timer: %u\n",
            ntohl(ra->nd_ra_retransmit));

        len -= sizeof (*ra);
        opt = (struct nd_opt_hdr *)&ra[1];
        print_opt(opt, len);
}

static void
print_opt(struct nd_opt_hdr *opt, int len)
{
        struct nd_opt_prefix_info *po;
        struct nd_opt_mtu *mo;
        struct nd_opt_lla *lo;
        int optlen;
        char abuf[INET6_ADDRSTRLEN];
        char llabuf[BUFSIZ];

        while (len >= sizeof (struct nd_opt_hdr)) {
                optlen = opt->nd_opt_len * 8;
                if (optlen == 0) {
                        logmsg(LOG_DEBUG, "Zero length option!\n");
                        break;
                }
                switch (opt->nd_opt_type) {
                case ND_OPT_PREFIX_INFORMATION:
                        po = (struct nd_opt_prefix_info *)opt;
                        if (optlen != sizeof (*po) ||
                            optlen > len)
                                break;

                        logmsg(LOG_DEBUG, "\tPrefix: %s/%u\n",
                            inet_ntop(AF_INET6, (void *)&po->nd_opt_pi_prefix,
                            abuf, sizeof (abuf)),
                            po->nd_opt_pi_prefix_len);
                        logmsg(LOG_DEBUG, "\t\tOn link flag:%s\n",
                            (po->nd_opt_pi_flags_reserved &
                            ND_OPT_PI_FLAG_ONLINK) ?
                            "Set" : "Not set");
                        logmsg(LOG_DEBUG, "\t\tAuto addrconf flag:%s\n",
                            (po->nd_opt_pi_flags_reserved &
                            ND_OPT_PI_FLAG_AUTO) ?
                            "Set" : "Not set");
                        logmsg(LOG_DEBUG, "\t\tValid time: %u\n",
                            ntohl(po->nd_opt_pi_valid_time));
                        logmsg(LOG_DEBUG, "\t\tPreferred time: %u\n",
                            ntohl(po->nd_opt_pi_preferred_time));
                        break;
                case ND_OPT_MTU:
                        mo = (struct nd_opt_mtu *)opt;
                        if (optlen != sizeof (*mo) ||
                            optlen > len)
                                break;
                        logmsg(LOG_DEBUG, "\tMTU: %d\n",
                            ntohl(mo->nd_opt_mtu_mtu));
                        break;
                case ND_OPT_SOURCE_LINKADDR:
                        lo = (struct nd_opt_lla *)opt;
                        if (optlen < 8 ||
                            optlen > len)
                                break;
                        (void) fmt_lla(llabuf, sizeof (llabuf),
                            lo->nd_opt_lla_hdw_addr,
                            optlen - sizeof (nd_opt_hdr_t));
                        logmsg(LOG_DEBUG, "\tSource LLA: len %d <%s>\n",
                            optlen - sizeof (nd_opt_hdr_t),
                            llabuf);
                        break;
                case ND_OPT_TARGET_LINKADDR:
                        lo = (struct nd_opt_lla *)opt;
                        if (optlen < 8||
                            optlen > len)
                                break;
                        (void) fmt_lla(llabuf, sizeof (llabuf),
                            lo->nd_opt_lla_hdw_addr,
                            optlen - sizeof (nd_opt_hdr_t));
                        logmsg(LOG_DEBUG, "\tTarget LLA: len %d <%s>\n",
                            optlen - sizeof (nd_opt_hdr_t),
                            llabuf);
                        break;
                case ND_OPT_REDIRECTED_HEADER:
                        logmsg(LOG_DEBUG, "\tRedirected header option!\n");
                        break;
                default:
                        logmsg(LOG_DEBUG, "Unknown option %d (0x%x)\n",
                            opt->nd_opt_type, opt->nd_opt_type);
                        break;
                }
                opt = (struct nd_opt_hdr *)((char *)opt + optlen);
                len -= optlen;
        }
}

char *
fmt_lla(char *llabuf, int bufsize, uchar_t *lla, int llalen)
{
        int i;
        char *cp = llabuf;

        for (i = 0; i < llalen; i++) {
                if (i == llalen - 1) /* Last byte? */
                        (void) snprintf(cp, bufsize, "%02x", lla[i] & 0xFF);
                else
                        (void) snprintf(cp, bufsize, "%02x:", lla[i] & 0xFF);
                bufsize -= strlen(cp);
                cp += strlen(cp);
        }
        return (llabuf);
}