1
0
Files
irix-657m-src/irix/cmd/tokenring/mtr/mtr_common.c
2022-09-29 17:59:04 +03:00

987 lines
23 KiB
C

/*
* Library for mtr/cmd
*/
#undef ONLY_6_3 /* code only for 6.3, IP32, release */
typedef struct {
short junk;
} SCB;
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/types.h>
#include <net/raw.h>
#include <sys/stream.h>
#include <sys/tr.h>
#include <sys/llc.h>
#include <sys/tr_user.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <net/if_arp.h>
#include <sys/utsname.h>
#include <arpa/inet.h>
#include <mtr.h>
int GotSignal = 0; /* sig_handler() reports the received signal */
int DebugMode = 0; /* debugging mode or not */
int DumpMode = 0; /* control dump, DUMP_... in mtr.h */
char *MyName = NULL; /* program name */
char *Interface = NULL; /* interface name */
int DumpSize = DEFAULT_DUMP_SIZE; /* default hex dump size */
/*
* Log the 'msg' with the given 'log_leve'.
*
* MyName must be defined.
*/
void
Log(int log_level, char *msg)
{
char *log_level_msg;
switch( log_level ){
case LOG_ERR:
log_level_msg = "ERR ";
break;
case LOG_WARNING:
log_level_msg = "Warn";
break;
case LOG_INFO:
log_level_msg = "info";
break;
case LOG_DEBUG:
if( !DebugMode )goto done;
log_level_msg = "debug";
break;
default:
goto done;
}
fprintf(stderr, "%s: %s: %s\n", MyName, log_level_msg, msg);
done:
return;
} /* Log() */
/*
* Common statements for all the programs.
*/
int
Begin(int argc, char **argv, int root_required)
{
int error = NO_ERROR;
char *ptr;
char msg[MAX_MSG_SIZE];
struct utsname utsname;
/* No buffering output, kind of real time. */
setbuf(stderr, NULL);
setbuf(stdout, NULL);
/* Only get the program name. */
MyName=argv[0];
for(ptr = MyName; (ptr = strstr(ptr, "/")) != NULL; MyName = ++ptr ){};
/* If real root is required, only real root is allowed. */
if( root_required == REAL_ROOT_REQUIRED){
if( (error = getuid()) ) {
/* Sorry, _REAL_ uid must be root. */
sprintf(msg, "permssion denied for %d.", error);
Log(LOG_ERR, msg);
error = 1;
goto done;
}
} /* if root_required */
#ifdef ONLY_6_3
/* Must be executed in IP32 with 6.3 release. */
if( uname(&utsname) < 0 ){
Perror("uname()");
error = 1;
goto done;
}
if( strcmp(utsname.machine, "IP32") ||
strncmp(utsname.release, "6.3", 3) ){
/* Not the right platform for ... */
Log(LOG_ERR, "must be IP32 with 6.3.");
error = 1;
goto done;
}
#endif /* ONLY_6_3 */
done:
return( error );
} /* Begin() */
/*
* Default signal handler: just record the received signal in 'GotSignal'.
*
* The program which uses this handler is responsible for the actions
* taken after receiving the signal.
*/
void
sig_handler(int sig)
{
char msg[MAX_MSG_SIZE];
GotSignal = sig;
sprintf(msg, "got signal %d.", sig);
Log(LOG_INFO, msg);
return;
} /* sig_handler() */
/*
* A better version of perror(), with name, error string, and error no.
*/
void
Perror(char *string)
{
char msg[MAX_MSG_SIZE];
sprintf(msg, "%s %s[%d].", string, strerror(errno), errno);
Log(LOG_ERR, msg);
return;
} /* Perror() */
/*
* Convert the MAC address from numeric format to ascii format.
*
* 'n': numeric format.
* 'a': acsii format.
*/
void
tr_ntoa(u_char *n, char *a)
{
sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x",
n[0], n[1], n[2], n[3], n[4], n[5]);
return;
} /* tr_ntoa() */
/*
* Convert the MAC address from ascii format to numberic format.
*
* 'a': ascii format.
* 'n': numeric format.
*/
int
tr_aton(char *a, char *n)
{
int cnt, idx;
u_int tmp[TR_MAC_ADDR_SIZE];
cnt = sscanf(a, " %x:%x:%x:%x:%x:%x",
&tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
if( cnt != TR_MAC_ADDR_SIZE ){
cnt = sscanf(a, " %x.%x.%x.%x.%x.%x",
&tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
}
if( cnt == TR_MAC_ADDR_SIZE ) {
for(idx=0; idx<TR_MAC_ADDR_SIZE; idx++)
n[idx] = (char)(tmp[idx] & 0xff);
} else {
memset(n, 0x0, TR_MAC_ADDR_SIZE );
}
return(cnt);
} /* tr_aton() */
/*
* MACRO to seach the tables defined by symtable_t which
* has 'type' and 'string' two elements. The search is
* done by the given 'type'.
*
* '_lim': the number of elements in the tables.
* '_ptr': the pointer to the table.
* '_type': the "seacrhed" value for 'type' in symtable_t.
* '_string': the result of the seach.
*/
#define GET_NAME_FROM_SYMTABLE(_lim, _ptr, _type, _string ) \
{ \
int idx; \
string = "???"; \
for( idx = 0; idx < _lim; idx++, (_ptr)++ ){ \
if( (_ptr)->type == (_type) ){ \
(_string) = (_ptr)->string; \
break; \
} /* if */ \
} /* for */ \
}
/*
* Symtable_t for FC value in TR frame.
*/
static symtable_t
mac_fcs[] = {
TR_FC_PCF_EXP, "exp buf, remove ring station, dup addr test",
TR_FC_PCF_BCN, "beacon",
TR_FC_PCF_CLM, "claim",
TR_FC_PCF_PURGE,"ring purge",
TR_FC_PCF_AMP, "AMP",
TR_FC_PCF_SMP, "SMP",
0, " "
};
/*
* Symtable_t for major vector in TR MAC frame.
*/
static symtable_t
mac_mv_classes[] = {
TR_CLASS_STA, "ring station",
TR_CLASS_MGR, "LLC manager",
TR_CLASS_CRS, "Network Manager(CRS)",
TR_CLASS_RPS, "Ring Parameter Server(RPS)",
TR_CLASS_REM, "Ring Error Monitor(REM)"
};
/*
* Symtable_t for command in TR MAC frame.
*/
static symtable_t
mac_mv_cmds[] = {
TR_MVC_RESPONSE, "response",
TR_MVC_BEACON, "BEACON",
TR_MVC_CLAIM, "CLAIM TOKEN",
TR_MVC_PURGE, "RING PURGE",
TR_MVC_AMP, "AMP",
TR_MVC_SMP, "SMP",
TR_MVC_DAT, "dup addr test",
TR_MVC_LOBE, "Lobe test",
TR_MVC_FORWARD, "transmit forward",
TR_MVC_REMOVE, "REMOVE RING STATION",
TR_MVC_CHANGE, "change parameters",
TR_MVC_INIT, "init ring station",
TR_MVC_REQADDR, "req ring station addr",
TR_MVC_REQSTATE, "req ring station state",
TR_MVC_REQATACH, "req ring station attach",
TR_MVC_REQINIT, "req initialization",
TR_MVC_RESADDR, "report ring station addr",
TR_MVC_RESSTATE, "report ring station state",
TR_MVC_RESATACH, "report ring station attach",
TR_MVC_REPNAM, "REPORT NEW AM",
TR_MVC_REPUNA, "REPORT NAUN CHANGE",
TR_MVC_REPNNI, "REPORT POLL ERROR",
TR_MVC_REPAME, "REPORT AM ERROR",
TR_MVC_REPSE, "REPORT SOFT ERROR",
TR_MVC_REPFRWD, "report transmit forward"
};
/*
* Symtable_t for sub-vector in TR MAC frame.
*/
static symtable_t
mac_sv_types[] = {
TR_SVC_BCNTYPE, "beacon type",
TR_SVC_UNA, "UNA",
TR_SVC_RINGNUM, "local ring number",
TR_SVC_ASIGNLOC, "assign physical drop number",
TR_SVC_SETIMO, "soft error report time out",
TR_SVC_EFC, "enable function classes",
TR_SVC_AAP, "allowed access priority",
TR_SVC_COREL, "corelator?",
TR_SVC_LASTUNA, "address of last ring poll",
TR_SVC_PHYLOC, "physical location",
TR_SVC_RESPONSE, "response code",
TR_SVC_RESERVE, "reserved",
TR_SVC_PID, "product instance ID",
TR_SVC_VERS, "adapter s/w level",
TR_SVC_WRAPDATA, "wrap data",
TR_SVC_FRMFWD, "frame forward",
TR_SVC_SID, "station ID",
TR_SVC_STATUS, "adapter status word",
TR_SVC_XMITSTAT, "xmitstat?",
TR_SVC_GRPADDR, "group addr",
TR_SVC_FCNADDR, "func addr",
TR_SVC_IERRCNT, "isolating err cnt",
TR_SVC_ERRCNT, "non-isolating err cnt",
TR_SVC_ERRCODE, "err code"
};
/*
* Get the string for the given FC value.
*/
static char *
mac_fc_type( u_char fc_type )
{
symtable_t *ptr = mac_fcs;
char *string;
GET_NAME_FROM_SYMTABLE( (sizeof(mac_fcs) / sizeof(*ptr)),
ptr, fc_type, string);
return(string);
} /* mac_fc_type() */
/*
* Get the string for the given major vector value.
*/
static char *
mac_mv_class( u_char class )
{
symtable_t *ptr = mac_mv_classes;
char *string;
class &= 0x0f;
GET_NAME_FROM_SYMTABLE((sizeof(mac_mv_classes) / sizeof(*ptr)),
ptr, class, string);
return(string);
} /* mac_mv_class() */
/*
* Get the string for the given command value.
*/
static char *
mac_mv_cmd( u_char cmd )
{
symtable_t *ptr = mac_mv_cmds;
char *string;
GET_NAME_FROM_SYMTABLE((sizeof(mac_mv_cmds) / sizeof(*ptr)),
ptr, cmd, string);
return(string);
} /* mac_mv_cmd() */
/*
* Get the string for the given sub-vector value.
*/
static char *
mac_sv_type(u_char type )
{
symtable_t *ptr = mac_sv_types;
char *string;
GET_NAME_FROM_SYMTABLE((sizeof(mac_sv_types) / sizeof(*ptr)),
ptr, type, string);
return(string);
} /* mac_sv_type() */
/*
* dump 'cnt' bytes of data pointed by 'cp'.
* the dumped data starts from 'offset' from the original buffer.
* When offset < 0, no banner.
*/
void
dump_hex(caddr_t cp, int cnt, int offset)
{
int idx;
if( cnt < 0 )goto done;
if( cnt > DumpSize )cnt = DumpSize;
for( idx = 0; idx < cnt ; idx++ , cp++){
if( offset >= 0 && !(idx & 0x0f) ) {
if( idx )fprintf(stdout, "\n");
fprintf(stdout,"%s%05d: ", IDENT, (offset+idx));
}
fprintf(stdout, "%02x ", *cp);
}
if( idx )fprintf(stdout,"\n");
done:
return;
} /* dump_hex() */
/*
* Dump MAC header part of the given frame, pointed by 'pkt_p'.
*
* That includes AC, FC, src MAC addr, dst MAC addr and RI (source routing
* information), if any.
*/
void
dump_mac_hdr( TR_MAC *pkt_p )
{
int idx, len;
u_short *ptr;
if( pkt_p == NULL )goto done;
fprintf(stdout, "%sAC: 0x%x, FC: 0x%x, "
"dst MAC: 0x%02x:%02x:%02x:%02x:%02x:%02x, "
"src MAC: 0x%02x:%02x:%02x:%02x:%02x:%02x.\n",
IDENT,
pkt_p->mac_ac,
pkt_p->mac_fc,
pkt_p->mac_da[0], pkt_p->mac_da[1],
pkt_p->mac_da[2], pkt_p->mac_da[3],
pkt_p->mac_da[4], pkt_p->mac_da[5],
pkt_p->mac_sa[0], pkt_p->mac_sa[1],
pkt_p->mac_sa[2], pkt_p->mac_sa[3],
pkt_p->mac_sa[4], pkt_p->mac_sa[5]);
if( pkt_p->mac_sa[0] & TR_MACADR_RII ){
tr_packet_t *pkt2_p = (tr_packet_t *)pkt_p;
/* Source routing! */
len = pkt2_p->rii.rii & TR_RIF_LENGTH >> 8;
fprintf(stdout, "%sRII: 0x%04x",
IDENT, (u_short) pkt2_p->rii.rii);
ptr = (u_short *)&(pkt2_p->rii.sgt_nos[0]);
for(idx = 2; idx < len; idx += sizeof(*ptr), ptr++){
fprintf(stdout, ".%04x", *ptr);
} /* for */
fprintf(stdout, "\n");
}
done:
return;
} /* dump_mac_hdr() */
/*
* Dump the given MAC frame, pointed by pkt_p.
*
* pkt_p: pointer to MAC header part, including RI, of the MAC frame.
* tr_mac_mv_p: pointer to MAC info part.
* pkt_size: size of the frame, including MAC header.
* hdr_size: size of the header, including other junk to skip.
* interface: ascii string of the interface where the frame is received.
* pkt_cnt: calling routing's frame counter for the received frame.
*
*/
void
dump_mac_pkt( TR_MAC *pkt_p,
TR_MACMV *tr_mac_mv_p,
int pkt_size,
int hdr_size,
char *interface,
int pkt_cnt )
{
int offset;
char msg[MAX_MSG_SIZE];
if( DebugMode ) dump_hex((caddr_t) pkt_p, pkt_size, 0);
if( !(DumpMode & DUMP_TR_ALL_EVENTS) ){
/*
* Not all the MAC frame so do not report SMP and AMP.
*/
if( pkt_p->mac_da[0] == 0xc0 &&
pkt_p->mac_da[1] == 0x00 &&
pkt_p->mac_da[2] == 0xff &&
pkt_p->mac_da[3] == 0xff ){
/* No AMP and SMP */
switch( pkt_p->mac_fc & TR_FC_PCF ){
case TR_FC_PCF_AMP:
case TR_FC_PCF_SMP:
goto done;
default:
break;
} /* switch */
} /* if */
}
/*
* Dump MAC header if we really have it.
*/
if( pkt_p == NULL || pkt_size < sizeof(TR_MAC) || tr_mac_mv_p == NULL)goto done;
dump_mac_hdr( pkt_p );
offset = hdr_size;
/*
* We should never need to skip any data starting from
* tr_mac_mv_p. Just in case we have bug in other places.
*/
while( tr_mac_mv_p->len == 0 && offset < pkt_size ){
sprintf(msg, "dump_mac_pkt(): tr_mac_mv_p: %d %d %d!",
tr_mac_mv_p->len, offset, pkt_size);
Log(LOG_WARNING, msg);
tr_mac_mv_p = (TR_MACMV *)((caddr_t)tr_mac_mv_p +
sizeof(tr_mac_mv_p->len));
offset += sizeof(tr_mac_mv_p->len);
}
if( pkt_size == offset ){
goto done;
} else if( pkt_size < offset + sizeof(tr_mac_mv_p) ){
fprintf(stdout, "%sillega size: %d %d %d.\n",
IDENT, pkt_size, offset, sizeof(tr_mac_mv_p));
goto done;
}
/*
* Report the major vector in the MAC frame.
*/
fprintf(stdout,
"%sMV.length: %d, class: 0x%x[%s.%s], cmd: 0x%x[%s]",
IDENT,
tr_mac_mv_p->len,
tr_mac_mv_p->vclass,
mac_mv_class( (tr_mac_mv_p->vclass >> 4) & 0x0f),
mac_mv_class( tr_mac_mv_p->vclass & 0x0f),
tr_mac_mv_p->cmd,
mac_mv_cmd( tr_mac_mv_p->cmd ));
/*
* Skip the major vector and process each subvector, if any.
*/
offset += sizeof(TR_MACMV);
if( pkt_size <= offset ){
fprintf(stdout, ".\n");
goto done;
} else {
caddr_t ptr;
TR_MACSV1 *tr_mac_sv_p;
u_char sv_len, sv_type;
fprintf(stdout, ",\n");
ptr = (caddr_t)(pkt_p) + offset;
/*
* for each subvector.
*/
for ( ; offset < pkt_size; ptr += sv_len, offset += sv_len ){
tr_mac_sv_p = (TR_MACSV1 *)ptr;
sv_len = tr_mac_sv_p->len;
if( sv_len == 0 ){
sv_len = 1;
} else if( sv_len <= sizeof(TR_MACSV1) ){
fprintf(stdout, "%sSV.length: %d \n",
IDENT, sv_len);
} else {
sv_type= tr_mac_sv_p->svid;
fprintf(stdout,
"%sSV.length: %02d, type: 0x%02x[%s] ",
IDENT,
sv_len,
sv_type,
mac_sv_type(sv_type));
dump_hex( ptr + sizeof(TR_MACSV1),
(sv_len - 2), -1);
} /* if_sv_len */
} /* for */
} /* if */
fprintf(stdout, "\n");
done:
return;
} /* dump_mac_pkt() */
/*
* Dump the snoop information, if any.
*/
void
dump_snoop_hdr( int pkt_cnt, int pkt_size,
char *who, char *interface,
struct snoopheader *sh_p)
{
struct tm *tm;
if( sh_p == NULL )goto done;
tm = localtime( &sh_p->snoop_timestamp.tv_sec );
fprintf(stdout, "%s%s: %s %d.%d-th pkt: flags: 0x%x, "
"len: %d.%d: time: %02d:%02d:%02d.%06d.\n",
IDENT, who, interface,
pkt_cnt,
sh_p->snoop_seq,
sh_p->snoop_flags,
sh_p->snoop_packetlen,
pkt_size,
tm->tm_hour, tm->tm_min, tm->tm_sec,
sh_p->snoop_timestamp.tv_usec);
done:
return;
} /* dump_snoop_hdr() */
/*
* Symtable_t for upper layer type in the IP header.
*/
static symtable_t
ip_uppers[] = {
#ifdef IPPROTO_ST
IPPROTO_ST, "st",
#endif /* IPPROTO_ST */
#ifdef IPPROTO_IPIP
IPPROTO_IPIP, "multi tunnel",
#endif /* IPPROTO_IPIP */
#ifdef IPPROTO_OSPF
IPPROTO_OSPF, "ospf",
#endif /* IPPROTO_OSPF */
IPPROTO_ICMP, "icmp",
IPPROTO_IGMP, "igmp",
IPPROTO_GGP, "ggp",
IPPROTO_TCP, "tcp",
IPPROTO_EGP, "egp",
IPPROTO_PUP, "pup",
IPPROTO_UDP, "udp",
IPPROTO_IDP, "idp",
IPPROTO_TP, "tp",
IPPROTO_XTP, "xtp",
#ifdef IPPROTO_RSVP
IPPROTO_RSVP, "rsvp",
#endif /* IPPROTO_RSVP */
IPPROTO_HELLO, "hello",
IPPROTO_RAW, "raw"
};
/*
* Symtable_t for ICMP type.
*/
static symtable_t
icmps[] = {
ICMP_ECHOREPLY, "echo reply",
ICMP_UNREACH, "unreach",
ICMP_SOURCEQUENCH, "source quench",
ICMP_REDIRECT, "redirect",
ICMP_ECHO, "echo",
ICMP_ROUTERADVERT, "router adv",
ICMP_ROUTERSOLICIT, "router solicit",
ICMP_TIMXCEED, "time exceed",
ICMP_PARAMPROB, "bad ip hdr",
ICMP_TSTAMP, "timestamp req",
ICMP_TSTAMPREPLY, "timestamp reply",
ICMP_MASKREQ, "mask req",
ICMP_MASKREPLY, "mask reply"
};
static char *
icmp_type( u_char icmp_type )
{
symtable_t *ptr = icmps;
char *string;
GET_NAME_FROM_SYMTABLE( (sizeof(icmps) / sizeof(*ptr)), ptr, icmp_type, string);
return(string);
} /* icmp_type() */
static char *
ip_up_type( u_char ip_p )
{
symtable_t *ptr = ip_uppers;
char *string = " ";
struct protoent *pp;
static char s_buf[80];
if( (pp = getprotobynumber( (int) ip_p )) != NULL ) {
strcpy(s_buf, pp->p_name);
} else {
GET_NAME_FROM_SYMTABLE( (sizeof(ip_uppers) / sizeof(*ptr)), ptr,
ip_p, string);
}
return(s_buf);
} /* ip_up_type() */
/*
* Dump the standard IPV4 header part.
*/
static void
dump_std_ip_hdr( struct ip *ip_p )
{
struct hostent *hp;
char tmp[IP_ADDR_STRING_SIZE], tmp2[IP_ADDR_STRING_SIZE];
char src_host[80], dst_host[80];
hp = gethostbyaddr( (char *)&ip_p->ip_src.s_addr,
sizeof(ip_p->ip_src.s_addr), AF_INET);
if( hp != NULL )
strncpy(src_host, hp->h_name, sizeof(src_host));
else
strcpy(src_host, " ");
hp = gethostbyaddr( (char *)&ip_p->ip_dst.s_addr,
sizeof(ip_p->ip_dst.s_addr), AF_INET);
if( hp != NULL )
strncpy(dst_host, hp->h_name, sizeof(dst_host));
else
strcpy(dst_host, " ");
fprintf(stdout, "%sIP: 0x%x, hlen: %d, tos: %d, "
"len: %d, id: %d,\n"
"%soff: %d, ttl: %d, prot: %d[%s],\n",
IDENT,
ip_p->ip_v, ip_p->ip_hl,
ip_p->ip_tos, ip_p->ip_len,
ip_p->ip_id,
IDENT,
ip_p->ip_off,
ip_p->ip_ttl,
ip_p->ip_p,
ip_up_type(ip_p->ip_p));
strncpy(tmp, inet_ntoa(ip_p->ip_src), sizeof(tmp));
strncpy(tmp2, inet_ntoa(ip_p->ip_dst), sizeof(tmp2));
fprintf(stdout, "%ssrc IP: %s[%s], dst IP: %s[%s].\n",
IDENT, tmp, src_host, tmp2, dst_host);
return;
} /* dump_std_ip_hdr() */
/*
* Dump the given ICMP packet.
*
* hex_ptr points the begining of the LLC1 frame, no MAC, LLC and SNAP header,
* hex_off gives the offset to access the ICMP header.
*
*/
void
dump_icmp_pkt( caddr_t hex_ptr, int hex_off)
{
int hex_cnt;
char gw_host[80];
struct hostent *hp;
struct icmp *icmp_p;
icmp_p = (struct icmp *)(hex_ptr + hex_off);
fprintf(stdout, "%sICMP: type: %d[%s], code: %d, ",
IDENT,
icmp_p->icmp_type,
icmp_type(icmp_p->icmp_type),
icmp_p->icmp_code);
switch( icmp_p->icmp_type ){
case ICMP_ECHOREPLY:
case ICMP_ECHO:
fprintf(stdout, "id: %04d, seq: %d.\n",
icmp_p->icmp_id,
icmp_p->icmp_seq);
break;
case ICMP_REDIRECT:
hp = gethostbyaddr( (char *)&icmp_p->icmp_gwaddr.s_addr,
sizeof(icmp_p->icmp_gwaddr.s_addr), AF_INET);
if( hp != NULL )
strncpy(gw_host, hp->h_name, sizeof(gw_host));
else
strcpy(gw_host, " ");
fprintf(stdout,"gateway: 0x%x[%s], \n",
inet_ntoa(icmp_p->icmp_gwaddr), gw_host);
dump_std_ip_hdr( &icmp_p->icmp_ip );
hex_off += (4 + sizeof(icmp_p->icmp_ip) +
sizeof(icmp_p->icmp_gwaddr));
hex_ptr += hex_off;
hex_cnt = 64 - (4 + sizeof(icmp_p->icmp_ip) +
sizeof(icmp_p->icmp_gwaddr));
dump_hex( hex_ptr, hex_cnt, hex_off);
break;
case ICMP_UNREACH:
case ICMP_SOURCEQUENCH:
case ICMP_TIMXCEED:
case ICMP_PARAMPROB:
hex_off += 4; /* skip icmp hdr part */
hex_ptr += hex_off;
hex_cnt = 64 + 4;
fprintf(stdout,"\n");
dump_hex( hex_ptr, hex_cnt, hex_off);
break;
case ICMP_MASKREQ:
case ICMP_MASKREPLY:
fprintf(stdout, "id: %04d, seq: %d, mask: 0x%x.\n",
icmp_p->icmp_id,
icmp_p->icmp_seq,
icmp_p->icmp_mask);
break;
case ICMP_TSTAMP:
case ICMP_TSTAMPREPLY:
fprintf(stdout, "id: %04d, seq: %d, \n"
"%sotime: 0x%x, rtime: 0x%x, ttime: 0x%x.\n",
icmp_p->icmp_id,
icmp_p->icmp_seq,
IDENT,
icmp_p->icmp_otime,
icmp_p->icmp_rtime,
icmp_p->icmp_ttime);
break;
case ICMP_ROUTERADVERT:
case ICMP_ROUTERSOLICIT:
default:
fprintf(stdout, ".\n");
break;
}
return;
} /* dump_icmp_pkt() */
/*
* Dump the given ARP packet, pointed by arp_p.
*/
void
dump_arp_pkt( struct arphdr *arp_p )
{
struct hostent *hp;
caddr_t ptr;
uchar_t src_mac[TR_MAC_ADDR_SIZE];
uchar_t dst_mac[TR_MAC_ADDR_SIZE];
struct in_addr src_ip;
struct in_addr dst_ip;
char tmp[IP_ADDR_STRING_SIZE], tmp2[IP_ADDR_STRING_SIZE];
fprintf(stdout,
"%sARP: hrd: 0x%x[%s], pro: 0x%x[%s], hlen: %d, "
"plen: %d, op: %d[%s].\n",
IDENT,
arp_p->ar_hrd,
(arp_p->ar_hrd == ARPHRD_802 ? "802" :
(arp_p->ar_hrd == ARPHRD_ETHER ? "ether" : "???")),
arp_p->ar_pro,
(arp_p->ar_pro == ETHERTYPE_IP ? "ip" : "???"),
arp_p->ar_hln,
arp_p->ar_pln,
arp_p->ar_op,
(arp_p->ar_op == ARPOP_REQUEST ? "arp-req" :
(arp_p->ar_op == ARPOP_REPLY ? "arp-reply" : "???"))
);
switch( arp_p->ar_pro ){
case ETHERTYPE_IP:
ptr = (caddr_t)(arp_p);
ptr += 8;
memcpy(src_mac, ptr, sizeof(src_mac));
ptr += sizeof(src_mac);
memcpy(&src_ip.s_addr, ptr, sizeof(src_ip));
ptr += sizeof(src_ip);
memcpy(dst_mac, ptr, sizeof(dst_mac));
ptr += sizeof(dst_mac);
memcpy(&dst_ip.s_addr, ptr, sizeof(dst_ip));
strncpy(tmp, inet_ntoa(src_ip), sizeof(tmp));
strncpy(tmp2, inet_ntoa(dst_ip), sizeof(tmp2));
fprintf(stdout,
"%ssrc ha: 0x%02x:%02x:%02x:%02x:%02x:%02x, "
"src ip: 0x%08x,\n"
"%sdst ha: 0x%02x:%02x:%02x:%02x:%02x:%02x, "
"dst ip: 0x%08x.\n",
IDENT,
src_mac[0], src_mac[1], src_mac[2],
src_mac[3], src_mac[4], src_mac[5],
tmp,
IDENT,
dst_mac[0], dst_mac[1], dst_mac[2],
dst_mac[3], dst_mac[4], dst_mac[5],
tmp2);
break;
default:
break;
}
return;
} /* dump_arp_pkt() */
/*
* Dump the given IP packet.
*
* hex_ptr points the begining of the LLC1 frame, no MAC, LLC and SNAP header,
* hex_off gives the offset to access the IP header.
*/
void
dump_ip_pkt( caddr_t hex_ptr, int hex_off)
{
struct ip *ip_p;
struct udphdr *udp_p;
struct tcphdr *tcp_p;
struct servent *sp;
char src_port[80], dst_port[80];
u_int ip_hlen, tcp_hlen;
ip_p = (struct ip *)(hex_ptr + hex_off);
if( DumpMode & DUMP_IP_HDR ){
dump_std_ip_hdr( ip_p );
ip_hlen = (u_int)ip_p->ip_hl;
ip_hlen <<= 2;
if( ip_hlen > DEAULT_IP_HDR_SIZE){
dump_hex( (hex_ptr + hex_off +
DEAULT_IP_HDR_SIZE),
(ip_hlen - DEAULT_IP_HDR_SIZE),
hex_off + DEAULT_IP_HDR_SIZE);
}
hex_off += ip_hlen;
} else {
ip_hlen = (u_int)ip_p->ip_hl;
ip_hlen <<= 2;
hex_off += ip_hlen;
}
switch( ip_p->ip_p ){
case IPPROTO_UDP:
udp_p = (struct udphdr *) ((caddr_t)ip_p + ip_hlen);
if( DumpMode & DUMP_UDP_HDR ) {
sp = getservbyport( udp_p->uh_sport, "udp");
if( sp != NULL )
strcpy(src_port, sp->s_name);
else
strcpy( src_port, " ");
sp = getservbyport( udp_p->uh_dport, "udp");
if( sp != NULL )
strcpy(dst_port, sp->s_name);
else
strcpy( dst_port, " ");
fprintf(stdout,
"%sUDP: src UDP port: %d[%s], dst UDP port: %d[%s], "
"len: %d.\n",
IDENT,
udp_p->uh_sport, src_port,
udp_p->uh_dport, dst_port,
udp_p->uh_ulen);
}
hex_off += sizeof(*udp_p);
break;
case IPPROTO_TCP:
tcp_p = (struct tcphdr *) ((caddr_t)ip_p + ip_hlen);
if( DumpMode & DUMP_TCP_HDR) {
sp = getservbyport( tcp_p->th_sport, src_port);
if( sp != NULL )
strcpy(src_port, sp->s_name);
else
strcpy( src_port, " ");
sp = getservbyport( tcp_p->th_dport, dst_port);
if( sp != NULL )
strcpy(dst_port, sp->s_name);
else
strcpy( dst_port, " ");
fprintf(stdout,
"%sTCP: src TCP port: %d[%s], dst TCP port: %d[%s], "
"seq: 0x%x, ack: 0x%x"
"flags: 0x%x, win: 0x%x, sum: 0x%x.\n",
IDENT,
tcp_p->th_sport, src_port,
tcp_p->th_dport, dst_port,
tcp_p->th_seq,
tcp_p->th_ack,
tcp_p->th_flags,
tcp_p->th_win,
tcp_p->th_sum);
}
tcp_hlen = (u_int)tcp_p->th_off;
tcp_hlen <<= 2;
hex_off += tcp_hlen;
break;
case IPPROTO_ICMP:
if( DumpMode & DUMP_ICMP ){
dump_icmp_pkt( hex_ptr, hex_off );
}
break;
default:
break;
} /* switch */
return;
} /* dump_ip_pkt() */