/*
* 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 (c) 2001 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <sys/types.h>
#include <at.h>
#include <snoop.h>
char *print_macaddr(uint8_t *, int);
static char *zip_flags(char);
static char *zip_flags_long(char);
void
interpret_ddp_zip(int flags, struct zip_hdr *zip, int len)
{
int cnt;
uint16_t net;
uint16_t range;
uint8_t *p;
char zone[33];
char defzone[60] = "";
char mcast[50] = "";
uint8_t gniflags;
uint8_t *tail = (uint8_t *)zip + len;
if (flags & F_SUM) {
if (len < sizeof (struct zip_hdr))
goto out;
switch (zip->zip_func) {
case ZIP_QUERY:
cnt = zip->zip_netcnt;
(void) snprintf(get_sum_line(), MAXLINE,
"ZIP Query CNT = %d", cnt);
break;
case ZIP_REPLY:
case ZIP_EXT_REPLY:
cnt = zip->zip_netcnt;
(void) snprintf(get_sum_line(), MAXLINE,
"ZIP Reply CNT = %d", cnt);
break;
case ZIP_GET_NET_INFO:
p = &zip->zip_func;
if ((p+6 > tail) || (p+7+p[6] > tail))
goto out;
(void) snprintf(get_sum_line(), MAXLINE,
"ZIP GNI Zone = \"%.*s\"", p[6], &p[7]);
break;
case ZIP_GET_NET_INFO_REPLY:
p = &zip->zip_func;
gniflags = p[1];
(void) snprintf(get_sum_line(), MAXLINE,
"ZIP GNI Rep Flags 0x%x (%s)",
gniflags, zip_flags(gniflags));
break;
default:
(void) snprintf(get_sum_line(), MAXLINE,
"ZIP CMD = %d", zip->zip_func);
break;
}
}
if (flags & F_DTAIL) {
show_header("ZIP: ", "ZIP Header", len);
show_space();
(void) snprintf(get_line(0, 0), get_line_remain(),
"Length = %d", len);
if (len < sizeof (struct zip_hdr))
goto out;
switch (zip->zip_func) {
case ZIP_QUERY:
(void) snprintf(get_line(0, 0), get_line_remain(),
"Query, Network count = %d", zip->zip_netcnt);
cnt = zip->zip_netcnt;
p = (uint8_t *)(zip + 1);
while (cnt--) {
if (p+2 > tail)
goto out;
net = get_short(p);
p += 2;
(void) snprintf(get_line(0, 0),
get_line_remain(), "Net = %d", net);
}
break;
case ZIP_REPLY:
case ZIP_EXT_REPLY:
cnt = zip->zip_netcnt;
(void) snprintf(get_line(0, 0), get_line_remain(),
"Reply, Network count = %d", cnt);
p = (uint8_t *)(zip + 1);
while (cnt--) {
if (p+2 > tail)
goto out;
net = get_short(p);
p += 2;
if (p+1 > tail || (&p[1] + p[0]) > tail)
goto out;
(void) snprintf(get_line(0, 0),
get_line_remain(),
"Network = %d, Zone = \"%.*s\"",
net, p[0], &p[1]);
p += p[0] + 1;
}
break;
case ZIP_GET_NET_INFO:
p = &zip->zip_func;
if (p+1 > tail || (&p[1] + p[0]) > tail)
goto out;
(void) snprintf(get_line(0, 0), get_line_remain(),
"GetNetInfo Zone = \"%.*s\"", p[0], &p[1]);
break;
case ZIP_GET_NET_INFO_REPLY:
p = &zip->zip_func;
if (p+5 > tail)
goto out;
gniflags = p[1];
net = get_short(&p[2]);
range = get_short(&p[4]);
if (p+7 > tail || (&p[7] + p[6]) > tail)
goto out;
(void) snprintf(zone, sizeof (zone),
"%.*s", p[6], &p[7]);
p = &p[7] + p[6];
if ((gniflags & ZIP_FLG_USEBRC) == 0) {
if (p+1 > tail || (&p[1] + p[0]) > tail)
goto out;
(void) snprintf(mcast, sizeof (mcast),
"Multicast address = %s",
print_macaddr(&p[1], p[0]));
}
if (gniflags & ZIP_FLG_ZINV) {
p = &p[1] + p[0];
if (p+1 > tail || (&p[1] + p[0]) > tail)
goto out;
(void) snprintf(defzone, sizeof (defzone),
"Default Zone = \"%.*s\"",
p[0], &p[1]);
}
(void) snprintf(get_line(0, 0), get_line_remain(),
"GetNetInfo Reply, Flags 0x%x (%s)",
gniflags, zip_flags_long(gniflags));
(void) snprintf(get_line(0, 0), get_line_remain(),
"Network number = %d-%d", net, range);
(void) snprintf(get_line(0, 0), get_line_remain(),
"Zone = \"%s\"", zone);
if (mcast[0])
(void) snprintf(get_line(0, 0),
get_line_remain(),
"%s", mcast);
if (defzone[0])
(void) snprintf(get_line(0, 0),
get_line_remain(),
"%s", defzone);
break;
case ZIP_NOTIFY:
p = &zip->zip_func;
if (p+5 > tail)
goto out;
gniflags = p[1];
net = get_short(&p[2]);
range = get_short(&p[4]);
if (p+7 > tail || (&p[7] + p[6]) > tail)
goto out;
(void) snprintf(zone, sizeof (zone),
"%.*s", p[6], &p[7]);
p = &p[7] + p[6];
if ((gniflags & ZIP_FLG_USEBRC) == 0) {
if (p+1 > tail || (&p[1] + p[0]) > tail)
goto out;
(void) snprintf(mcast, sizeof (mcast),
"New Multicast address = %s",
print_macaddr(&p[1], p[0]));
}
if (p+1 > tail || (&p[1] + p[0]) > tail)
goto out;
p = &p[1] + p[0];
if (p+1 > tail || (&p[1] + p[0]) > tail)
goto out;
(void) snprintf(defzone, sizeof (defzone),
"New Default Zone = \"%.*s\"",
p[0], &p[1]);
(void) snprintf(get_line(0, 0), get_line_remain(),
"Notify, Flags 0x%x (%s)",
gniflags, zip_flags_long(gniflags));
(void) snprintf(get_line(0, 0), get_line_remain(),
"Old Zone = \"%s\"", zone);
if (mcast[0])
(void) snprintf(get_line(0, 0),
get_line_remain(), "%s", mcast);
if (defzone[0])
(void) snprintf(get_line(0, 0),
get_line_remain(), "%s", defzone);
break;
default:
(void) snprintf(get_line(0, 0), get_line_remain(),
"Op = %d", zip->zip_func);
break;
}
}
return;
out:
if (flags & F_SUM)
(void) snprintf(get_sum_line(), MAXLINE,
"ZIP (short packet)");
if (flags & F_DTAIL)
(void) snprintf(get_line(0, 0), get_line_remain(),
"ZIP (short packet)");
}
static char *
zip_flags(char flags)
{
static char buf[50];
char *p = buf;
char *tail = &buf[sizeof (buf)];
buf[0] = '\0';
if (flags & ZIP_FLG_ZINV)
p += snprintf(p, tail-p, "IZ");
if (flags & ZIP_FLG_USEBRC)
p += snprintf(p, tail-p, p == buf ? "UB" : " UB");
if (flags & ZIP_FLG_ONEZ)
(void) snprintf(p, tail-p, p == buf ? "OOZ" : " OOZ");
return (buf);
}
static char *
zip_flags_long(char flags)
{
static char buf[50];
char *p = buf;
char *tail = &buf[sizeof (buf)];
buf[0] = '\0';
if (flags & ZIP_FLG_ZINV)
p += snprintf(p, tail-p, "ZoneInvalid");
if (flags & ZIP_FLG_USEBRC)
p += snprintf(p, tail-p,
p == buf ? "UseBroadcast" : " UseBroadcast");
if (flags & ZIP_FLG_ONEZ)
(void) snprintf(p, tail-p,
p == buf ? "OnlyOneZone" : " OnlyOneZone");
return (buf);
}
void
interpret_atp_zip(int flags, struct atp_hdr *atp, int len)
{
int cnt;
uint8_t *data;
uint8_t *tail = (uint8_t *)(atp+1) + len;
if (flags & F_SUM) {
if (len < 0) {
(void) snprintf(get_sum_line(), MAXLINE,
"ZIP (short packet)");
return;
}
switch (atp_fun(atp->atp_ctrl)) {
case ATP_TREQ:
switch (atp->atp_user[0]) {
case ZIP_ATP_GETMYZONE:
(void) snprintf(get_sum_line(), MAXLINE,
"ZIP GetMyZone");
break;
case ZIP_ATP_GETZONELIST:
(void) snprintf(get_sum_line(), MAXLINE,
"ZIP GetZoneList");
break;
case ZIP_ATP_GETLOCALZONES:
(void) snprintf(get_sum_line(), MAXLINE,
"ZIP GetLocalZones");
break;
}
break;
case ATP_TRESP:
cnt = get_short(&atp->atp_user[2]);
(void) snprintf(get_sum_line(), MAXLINE,
"ZIP ZoneReply, Cnt = %d", cnt);
break;
}
}
if (flags & F_DTAIL) {
show_header("ZIP: ", "ZIP Header", len);
show_space();
if (len < 0) {
(void) snprintf(get_line(0, 0), get_line_remain(),
"ZIP (short packet)");
return;
}
switch (atp_fun(atp->atp_ctrl)) {
case ATP_TREQ:
switch (atp->atp_user[0]) {
case ZIP_ATP_GETMYZONE:
(void) snprintf(get_line(0, 0),
get_line_remain(),
"GetMyZone, Start Index = %d",
get_short(&atp->atp_user[2]));
break;
case ZIP_ATP_GETZONELIST:
(void) snprintf(get_line(0, 0),
get_line_remain(),
"GetZoneList, Start Index = %d",
get_short(&atp->atp_user[2]));
break;
case ZIP_ATP_GETLOCALZONES:
(void) snprintf(get_line(0, 0),
get_line_remain(),
"GetLocalZones, Start Index = %d",
get_short(&atp->atp_user[2]));
break;
}
break;
case ATP_TRESP:
cnt = get_short(&atp->atp_user[2]);
(void) snprintf(get_line(0, 0), get_line_remain(),
"ZoneReply, Number of Zones = %d, Length = %d",
cnt, len);
data = (uint8_t *)atp + DDPHDR_SIZE + ATPHDR_SIZE;
while (cnt--) {
if (data > tail ||
(&data[1] + data[0]) > tail) {
(void) snprintf(get_line(0, 0),
get_line_remain(),
"ZoneReply (short packet)");
return;
}
(void) snprintf(get_line(0, 0),
get_line_remain(),
"Zone = \"%.*s\"", data[0], &data[1]);
data += data[0] + 1;
}
break;
}
}
}