Logo Search packages:      
Sourcecode: tcptrace version File versions  Download package

print.c

/*
 * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
 *               2002, 2003, 2004
 *
 * ---
 * 
 * Starting with the release of tcptrace version 6 in 2001, tcptrace
 * is licensed under the GNU General Public License (GPL).  We believe
 * that, among the available licenses, the GPL will do the best job of
 * allowing tcptrace to continue to be a valuable, freely-available
 * and well-maintained tool for the networking community.
 *
 * Previous versions of tcptrace were released under a license that
 * was much less restrictive with respect to how tcptrace could be
 * used in commercial products.  Because of this, I am willing to
 * consider alternate license arrangements as allowed in Section 10 of
 * the GNU GPL.  Before I would consider licensing tcptrace under an
 * alternate agreement with a particular individual or company,
 * however, I would have to be convinced that such an alternative
 * would be to the greater benefit of the networking community.
 * 
 * ---
 *
 * This file is part of Tcptrace.
 *
 * Tcptrace was originally written and continues to be maintained by
 * Shawn Ostermann with the help of a group of devoted students and
 * users (see the file 'THANKS').  The work on tcptrace has been made
 * possible over the years through the generous support of NASA GRC,
 * the National Science Foundation, and Sun Microsystems.
 *
 * Tcptrace is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Tcptrace is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Tcptrace (in the file 'COPYING'); if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 * 
 * Author:  Shawn Ostermann
 *          School of Electrical Engineering and Computer Science
 *          Ohio University
 *          Athens, OH
 *          ostermann@cs.ohiou.edu
 *          http://www.tcptrace.org/
 */
#include "tcptrace.h"
static char const GCC_UNUSED copyright[] =
    "@(#)Copyright (c) 2004 -- Ohio University.\n";
static char const GCC_UNUSED rcsid[] =
    "@(#)$Header: /usr/local/cvs/tcptrace/print.c,v 5.27 2003/11/19 14:38:05 sdo Exp $";


/* 
 * print.c -- packet printing routines
 */



/* local routines */
static void printeth_packet(struct ether_header *);
static void printip_packet(struct ip *, void *plast);
static void printtcp_packet(struct ip *, void *plast, tcb *tcb);
static void printudp_packet(struct ip *, void *plast);
static char *ParenServiceName(portnum);
static char *ParenHostName(struct ipaddr addr);
static void printipv4(struct ip *pip, void *plast);
static void printipv6(struct ipv6 *pipv6, void *plast);
static char *ipv6addr2str(struct in6_addr addr);
static void printipv4_opt_addrs(char *popt, int ptr, int len);
static char *PrintSeqRep(tcb *ptcb, u_long seq);



/* Resulting string format: "Fri Sep 13 00:00:00.123456 1986" */
/*                               1         2         3   */
/*                       0123456789012345678901234567890 */
char *
ts2ascii(
    struct timeval      *ptime)
{
      static char buf[32];
      struct tm *ptm;
      char *now;
      int decimal;

      if (ZERO_TIME(ptime))
          return("        <the epoch>       ");

      ptm = localtime((time_t *)&ptime->tv_sec);
      now = asctime(ptm);

      /* splice in the microseconds */
      now[19] = '\00';
/*    decimal = (ptime->tv_usec + 50) / 100;*/  /* for 4 digits */
      decimal = ptime->tv_usec;  /* for 6 digits */

      now[24] = '\00';  /* nuke the newline */
      snprintf(buf,sizeof(buf), "%s.%06d %s", now, decimal, &now[20]);

      return(buf);
}

/* same as ts2ascii, but no year */
char *
ts2ascii_date(
    struct timeval      *ptime)
{
      static char buf[30];
      struct tm *ptm;
      char *now;
      int decimal;

      if (ZERO_TIME(ptime))
          return("        <the epoch>       ");

      ptm = localtime((time_t *)&ptime->tv_sec);
      now = asctime(ptm);
      now[24] = '\00';

/*    decimal = (ptime->tv_usec + 50) / 100;*/  /* for 4 digits */
      decimal = ptime->tv_usec;  /* for 6 digits */
      snprintf(buf,sizeof(buf), "%s.%06d", now, decimal);

      return(buf);
}


static void
printeth_packet(
    struct ether_header *pep)
{
    printf("\tETH Srce: %s\n", Ether_Ntoa((struct ether_addr *)&pep->ether_shost));
    printf("\tETH Dest: %s\n", Ether_Ntoa((struct ether_addr *)&pep->ether_dhost));

    printf(
      hex?"\t    Type: 0x%x %s\n":"\t    Type: %d %s\n",
      ntohs(pep->ether_type),
      (ntohs(pep->ether_type) == ETHERTYPE_IP)?"(IP)":
      (ntohs(pep->ether_type) == ETHERTYPE_IPV6)?"(IPv6)":
      (ntohs(pep->ether_type) == ETHERTYPE_ARP)?"(ARP)":
      (ntohs(pep->ether_type) == ETHERTYPE_REVARP)?"(RARP)":
      "");
}


static void
printip_packet(
    struct ip *pip,
    void *plast)
{
    /* print an ipv6 header */
    if (PIP_ISV6(pip)) {
      if ((char *)pip+sizeof(struct ipv6)-1 > (char *)plast) {
          if (warn_printtrunc)
            printf("\t[packet truncated too short for IP details]\n");
          ++ctrunc;
          return;
      }
      printipv6((struct ipv6 *)pip, plast);
      return;
    }

    if (PIP_ISV4(pip)) {
      /* make sure we have enough of the packet */
      if ((char *)pip+sizeof(struct ip)-1 > (char *)plast) {
          if (warn_printtrunc)
            printf("\t[packet truncated too short for IP details]\n");
          ++ctrunc;
          return;
      }
      printipv4(pip, plast);
      return;
    }

    /* unknown type */
    printf("Unknown IP version %d\n", PIP_VERS(pip));
}



static void
printipv4(
    struct ip *pip,
    void *plast)
{
    u_short offset;
    Bool mf;
    
    /* make sure we have enough of the packet */
    if ((char *)pip+sizeof(struct ip)-1 > (char *)plast) {
      if (warn_printtrunc)
          printf("\t[packet truncated too short for IP details]\n");
      ++ctrunc;
      return;
    }

    printf("\tIP  VERS: %d\n", IP_V(pip));
    printf("\tIP  Srce: %s %s\n",
         inet_ntoa(pip->ip_src),
         ParenHostName(*IPV4ADDR2ADDR(&pip->ip_src)));
    printf("\tIP  Dest: %s %s\n",
         inet_ntoa(pip->ip_dst),
         ParenHostName(*IPV4ADDR2ADDR(&pip->ip_dst)));

    printf(
      hex?"\t    Type: 0x%x %s\n":"\t    Type: %d %s\n",
      pip->ip_p, 
      (pip->ip_p == IPPROTO_UDP)?"(UDP)":
      (pip->ip_p == IPPROTO_TCP)?"(TCP)":
      (pip->ip_p == IPPROTO_ICMP)?"(ICMP)":
      (pip->ip_p == IPPROTO_IGMP)?"(IGMP)":
      (pip->ip_p == IPPROTO_EGP)?"(EGP)":
      "");

    printf("\t    HLEN: %d\n", IP_HL(pip)*4);
    printf("\t     TTL: %d\n", pip->ip_ttl);
    printf("\t     LEN: %d\n", ntohs(pip->ip_len));
    printf("\t      ID: %d\n", ntohs(pip->ip_id));
    printf("\t   CKSUM: 0x%04x", ntohs(pip->ip_sum));
    if (verify_checksums)
      printf(" (%s)", ip_cksum_valid(pip,plast)?"CORRECT":"WRONG");
    printf("\n");

    /* fragmentation stuff */
    offset = ntohs(pip->ip_off) << 3;
    mf = (ntohs(pip->ip_off) & IP_MF) != 0;
    if ((offset == 0) && (!mf)) {
      printf("\t  OFFSET: 0x%04x", ntohs(pip->ip_off));
    } else {
      printf("\t  OFFSET: 0x%04x (frag: %d bytes at offset %u - %s)",
             ntohs(pip->ip_off),
             ntohs(pip->ip_len)-IP_HL(pip)*4,
             offset,
             mf?"More Frags":"Last Frag");
    }
    if ((ntohs(pip->ip_off) & IP_DF) != 0)
      printf("  Don't Fragment\n"); /* don't fragment */

    /* print IP options if there are any */
    if (IP_HL(pip) != 5) {
      char *popt = (char *)pip + 20;
      void *plast_option;

      /* find the last option in the file */
      plast_option = (char *)pip+4*IP_HL(pip)-1;
      if (plast_option > plast)
          plast_option = plast; /* truncated shorter than that */

      printf("\t Options: %d bytes\n", 4*IP_HL(pip)-20);
      while ((char *)popt <= (char *)plast_option) {
          u_int opt = *popt;
          u_int len = *(popt+1);
          u_int ptr = *(popt+2);
          int optcopy = (opt&0x80);
          int optclass = (opt&0x60)>>5;
          int optnum = (opt&0x1f);

          /* check for truncated option */
          if ((void *)(popt+len-1) > plast) {
            printf("\t    IP option (truncated)\n");
            break;
          }

          printf("\t    IP option %d (copy:%c  class:%s  number:%d)\n",
               opt,
               optcopy==0?'N':'Y',
               optclass==0?"ctrl":
               optclass==1?"reserved1":
               optclass==2?"debug":
               optclass==3?"reserved3":"unknown",
               optnum);


          switch(opt) {
            case 3:
            printf("\t      Loose source route:  len: %d  ptr:%d\n",
                   len, ptr);
            printipv4_opt_addrs(popt, ptr, len);
            break;
            case 7:
            printf("\t      Record Route:  len: %d  ptr:%d\n",
                   len, ptr);
            printipv4_opt_addrs(popt, ptr, len);
            break;
            case 9:
            printf("\t      Strict source route:  len: %d  ptr:%d\n",
                   len, ptr);
            printipv4_opt_addrs(popt, ptr, len);
            break;
            case 4:
            printf("\t      Timestamps:  len: %d  ptr:%d\n",
                   len, ptr);
            break;
            case 0:
            printf("\t      EOL\n");
            len = 1;
            break;
            case 1:
            printf("\t      PADDING\n");
            len = 1;
            break;
            default:
            printf("\t      Unknown Option %d, len: %d\n", opt, len);
            break;
          }
          if (len <= 0)
            break;
          popt += len;
      }
    }

    printf("\n");
}


/* print out the little table in the source route and record route options */
static void
printipv4_opt_addrs(
    char *popt,
    int ptr,
    int len)
{
    struct in_addr ina;
    int nptr;
    int i;

    for (nptr=4,i=1;nptr < len; nptr += 4,++i) {
      memcpy(&ina.s_addr,popt+nptr-1,4);
      if (nptr < ptr)
          printf("\t        %d: %-15s  %s\n",
               i, inet_ntoa(ina),
               HostName(*IPV4ADDR2ADDR(&ina)));
      else
          printf("\t        %d: xxxxxxxxxxx\n", i);
    }
}


static void
printtcp_packet(
    struct ip *pip,
    void *plast,
    tcb *thisdir)
{
    unsigned tcp_length;
    unsigned tcp_data_length;
    struct tcphdr *ptcp;
    int i;
    u_char *pdata;
    struct ipv6 *pipv6;
    tcb *otherdir = NULL;

    /* find the tcp header */
    if (gettcp(pip, &ptcp, &plast))
      return;           /* not TCP or bad TCP packet */

    /* make sure we have enough of the packet */
    if ((char *)ptcp+sizeof(struct tcphdr)-1 > (char *)plast) {
      if (warn_printtrunc)
          printf("\t[packet truncated too short for TCP details]\n");
      ++ctrunc;
      return;
    }

    /* calculate data length */
    if (PIP_ISV6(pip)) {
      pipv6 = (struct ipv6 *) pip;
      tcp_length = ntohs(pipv6->ip6_lngth);
    } else {
      tcp_length = ntohs(pip->ip_len) - (4 * IP_HL(pip));
    }
    tcp_data_length = tcp_length - (4 * TH_OFF(ptcp));

    /* find the tcb's (if available) */
    if (thisdir)
      otherdir = thisdir->ptwin;

    printf("\tTCP SPRT: %u %s\n",
         ntohs(ptcp->th_sport),
         ParenServiceName(ntohs(ptcp->th_sport)));
    printf("\t    DPRT: %u %s\n",
         ntohs(ptcp->th_dport),
         ParenServiceName(ntohs(ptcp->th_dport)));
    printf("\t     FLG: %c%c%c%c%c%c%c%c (0x%02x)\n",
         FLAG6_SET(ptcp)? '?':' ',
         FLAG7_SET(ptcp)? '?':' ',
         URGENT_SET(ptcp)?'U':'-',
         ACK_SET(ptcp)?   'A':'-',
         PUSH_SET(ptcp)?  'P':'-',
         RESET_SET(ptcp)? 'R':'-',
         SYN_SET(ptcp)?   'S':'-',
         FIN_SET(ptcp)?   'F':'-',
         ptcp->th_flags);
    printf("\t     SEQ: %s\n", PrintSeqRep(thisdir,  ntohl(ptcp->th_seq)));
    printf("\t     ACK: %s\n", PrintSeqRep(otherdir, ntohl(ptcp->th_ack)));
    printf("\t     WIN: %u\n", ntohs(ptcp->th_win));
    printf("\t    HLEN: %u", TH_OFF(ptcp)*4);
    if ((char *)ptcp + TH_OFF(ptcp)*4 - 1 > (char *)plast) {
      /* not all there */
      printf(" (only %lu bytes in dump file)",
             (u_long)((char *)plast - (char *)ptcp + 1));
    }
    printf("\n");
    
    if (TH_X2(ptcp) != 0) {
      printf("\t    MBZ: 0x%01x (these are supposed to be zero!)\n",
             TH_X2(ptcp));
    }
    printf("\t   CKSUM: 0x%04x", ntohs(ptcp->th_sum));
    pdata = (u_char *)ptcp + TH_OFF(ptcp)*4;
    if (verify_checksums) {
      if ((char *)pdata + tcp_data_length > ((char *)plast+1))
          printf(" (too short to verify)");
      else
          printf(" (%s)", tcp_cksum_valid(pip,ptcp,plast)?"CORRECT":"WRONG");
    }
    printf("\n");


    printf("\t    DLEN: %u", tcp_data_length);
    if ((tcp_data_length != 0) &&
      ((char *)pdata + tcp_data_length > ((char *)plast+1))) {
      int available =  (char *)plast - (char *)pdata + 1;
      if (available > 1)
          printf(" (only %lu bytes in dump file)",
               (u_long)((char *)plast - (char *)pdata + 1));
      else
          printf(" (none of it in dump file)");
    }
    printf("\n");
    if (TH_OFF(ptcp) != 5) {
      struct tcp_options *ptcpo;

        printf("\t    OPTS: %lu bytes",
             (unsigned long)(TH_OFF(ptcp)*4) - sizeof(struct tcphdr));
      if ((char *)ptcp + TH_OFF(ptcp)*4 - 1 > (char *)plast) {
          /* not all opts were stored */
          u_long available = 1 + (char *)plast -
            ((char *)ptcp + sizeof(struct tcphdr));
          if (available > 1)
            printf(" (%lu bytes in file)", available);
          else
            printf(" (none of it in dump file)");
      }

      printf("\t");

      ptcpo = ParseOptions(ptcp,plast);

      if (ptcpo->mss != -1)
          printf(" MSS(%d)", ptcpo->mss);
      if (ptcpo->ws != -1)
          printf(" WS(%d)", ptcpo->ws);
      if (ptcpo->tsval != -1) {
          printf(" TS(%ld,%ld)", ptcpo->tsval, ptcpo->tsecr);
      }
      if (ptcpo->sack_req) {
          printf(" SACKREQ");
      }
      if (ptcpo->sack_count >= 0) {
          printf(" SACKS(%d)", ptcpo->sack_count);
          for (i=0; i < ptcpo->sack_count; ++i) {
            printf("[%s-",
                   PrintSeqRep(otherdir,
                           (u_long)ptcpo->sacks[i].sack_left));
            printf("%s]",
                   PrintSeqRep(otherdir,
                           (u_long)ptcpo->sacks[i].sack_right));
          }
      }
      if (ptcpo->echo_req != -1)
          printf(" ECHO(%lu)", ptcpo->echo_req);
      if (ptcpo->echo_repl != -1)
          printf(" ECHOREPL(%lu)", ptcpo->echo_repl);
      if (ptcpo->cc != -1)
          printf(" CC(%lu)", ptcpo->cc);
      if (ptcpo->ccnew != -1)
          printf(" CCNEW(%lu)", ptcpo->ccnew);
      if (ptcpo->ccecho != -1)
          printf(" CCECHO(%lu)", ptcpo->ccecho);
      for (i=0; i < ptcpo->unknown_count; ++i) {
          if (i < MAX_UNKNOWN) {
            printf(" UNKN(op:%d,len:%d)",
                   ptcpo->unknowns[i].unkn_opt,
                   ptcpo->unknowns[i].unkn_len);
          } else {
            printf("... more unsaved unknowns\n");
            break;
          }
      }
        printf("\n");
    }
    if (tcp_data_length > 0) {
      if (dump_packet_data) {
          char *ptcp_data = (char *)ptcp + (4 * TH_OFF(ptcp));
          PrintRawData("   data", ptcp_data, plast, TRUE);
      } else {
          printf("\t    data: %u bytes\n", tcp_data_length);
      }
    }
}


static void
printudp_packet(
    struct ip *pip,
    void *plast)
{
    struct udphdr *pudp;
    unsigned udp_length;
    unsigned udp_data_length;
    u_char *pdata;

    /* find the udp header */
    if (getudp(pip, &pudp, &plast))
      return;       /* not UDP  or bad UDP packet */

    /* make sure we have enough of the packet */
    if ((char *)pudp+sizeof(struct udphdr)-1 > (char *)plast) {
      if (warn_printtrunc)
          printf("\t[packet truncated too short for UDP details]\n");
      ++ctrunc;
      return;
    }

    printf("\tUDP SPRT: %u %s\n",
         ntohs(pudp->uh_sport),
         ParenServiceName(ntohs(pudp->uh_sport)));
    printf("\t    DPRT: %u %s\n",
         ntohs(pudp->uh_dport),
         ParenServiceName(ntohs(pudp->uh_dport)));
    pdata = (u_char *)pudp + sizeof(struct udphdr);
    udp_length = ntohs(pudp->uh_ulen);
    udp_data_length = udp_length - sizeof(struct udphdr);
    printf("\t  UCKSUM: 0x%04x", ntohs(pudp->uh_sum));
    pdata = (u_char *)pudp + sizeof(struct udphdr);
    if (verify_checksums) {
      if ((char *)pdata + udp_data_length > ((char *)plast+1))
          printf(" (too short to verify)");
      else
          printf(" (%s)", udp_cksum_valid(pip,pudp,plast)?"CORRECT":"WRONG");
    }
    printf("\n");
    printf("\t    DLEN: %u", ntohs(pudp->uh_ulen));
    if ((char *)pdata + ntohs(pudp->uh_ulen) > ((char *)plast+1))
      printf(" (only %lu bytes in dump file)\n",
             (u_long)((char *)plast - (char *)pdata + 1));
    if (ntohs(pudp->uh_ulen) > 0) {
      if (dump_packet_data)
          PrintRawData("   data", pdata, plast, TRUE);
    }
}



void
printpacket(
     int          len,
     int          tlen,
     void         *phys,
     int          phystype,
     struct ip          *pip,
     void         *plast,
     tcb          *tcb)
{
    if (len == 0)
      /* original length unknown */
        printf("\tSaved Length: %d\n", tlen);
    else if (len == tlen)
        printf("\tPacket Length: %d\n", len);
    else
        printf("\tPacket Length: %d (saved length %d)\n", len,tlen);

    printf("\tCollected: %s\n", ts2ascii(&current_time));

    if (phys) {
      switch(phystype) {
        case PHYS_ETHER:
          printeth_packet(phys);
          break;
        default:
          printf("\tPhysical layer: %d (not understood)\n", phystype);
          break;
      }
    }

    /* it's always supposed to be an IP packet */
    printip_packet(pip,plast);


    /* this will fail if it's not TCP */
    printtcp_packet(pip,plast,tcb);

    /* this will fail if it's not UDP */
    printudp_packet(pip,plast);
}


static char *
ParenServiceName(
     portnum port)
{
    char *pname;
    static char buf[80];

    pname = ServiceName(port);
    if (!pname || isdigit((int)(*pname)))
      return("");

    snprintf(buf,sizeof(buf),"(%s)",pname);
    return(buf);
}


static char *
ParenHostName(
     struct ipaddr addr)
{
    char *pname;
    static char buf[80];

    pname = HostName(addr);
    if (!pname || isdigit((int)(*pname)))
      return("");

    snprintf(buf,sizeof(buf),"(%s)",pname);
    return(buf);
}


void
PrintRawData(
    char *label,
    void *pfirst,
    void *plast,
    Bool octal)               /* hex or octal? */
{
    int lcount = 0;
    int count = (char *)plast - (char *)pfirst + 1;
    u_char *pch = pfirst;

    if (count <= 0)
      return;

    printf("========================================\n");
    printf("%s (%d bytes):\n", label, count);

    while (pch <= (u_char *) plast) {
      if ((*pch == '\r') && (*(pch+1) == '\n')) {
          printf("\n");
          ++pch;
          lcount = 0;
      } else if (isprint(*pch)) {
          putchar(*pch);
          lcount+=1;
      } else {
          if (octal) {
            printf("\\%03o", *pch);
            lcount+=4;
          } else {
            printf("0x%02x", *pch);
            lcount+=4;
          }
      }
      if (lcount > 70) {
          printf("\\\n");
          lcount = 0;
      }
      ++pch;
    }
    if (lcount != 0)
      printf("\\\n");
    printf("========================================\n");
}


void
PrintRawDataHex(
    char *label,
    void *pfirst,
    void *plast)
{
    PrintRawData(label,pfirst,plast,FALSE);
}


static void
printipv6(
    struct ipv6 *pipv6,
    void *plast)
{
    int ver = (ntohl(pipv6->ip6_ver_tc_flabel) & 0xF0000000) >> 28;
    int tc  = (ntohl(pipv6->ip6_ver_tc_flabel) & 0x0F000000) >> 24;
    struct ipv6_ext *pheader;
    u_char nextheader;

    printf("\tIP  Vers: %d\n", ver);
    printf("\tIP  Srce: %s\n", ipv6addr2str(pipv6->ip6_saddr));
    printf("\tIP  Dest: %s\n", ipv6addr2str(pipv6->ip6_daddr));
    printf("\t   Class: %d\n", tc);
    printf("\t    Flow: %d\n", (ntohl(pipv6->ip6_ver_tc_flabel) & 0x00FFFFFF));
    printf("\t    PLEN: %d\n", ntohs(pipv6->ip6_lngth));
    printf("\t    NXTH: %u (%s)\n",
         pipv6->ip6_nheader,
         ipv6_header_name(pipv6->ip6_nheader));
    printf("\t    HLIM: %u\n", pipv6->ip6_hlimit);

    /* walk the extension headers */
    nextheader = pipv6->ip6_nheader;
    pheader = (struct ipv6_ext *)(pipv6+1);

    while (pheader) {
      u_char old_nextheader = nextheader;

      pheader = ipv6_nextheader(pheader,&nextheader);

      /* if there isn't a "next", then this isn't an extension header */
      if (pheader) {
          printf("\tIPv6 Extension Header Type %d (%s)\n",
               old_nextheader,
               ipv6_header_name(old_nextheader));
          /* FIXME - want to give details, but I need some examples first! */
          /* (hint to users!!!...) */
      }
    }
}


/*
 * ipv6addr2str: return the string rep. of an ipv6 address
 */
static char *
ipv6addr2str(
    struct in6_addr addr)
{
    static char adr[INET6_ADDRSTRLEN];
    my_inet_ntop(AF_INET6, (char *)&addr, (char *)adr, INET6_ADDRSTRLEN);
    return(adr);
}


/* Shawn's version... */
/* Lots of machines HAVE this, but they give slightly different formats */
/* and it messes up my cross-platform testing.  I'll just do it the */
/* "one true" way!  :-)  */
char *
Ether_Ntoa (struct ether_addr *e)
{
    unsigned char *pe;
    static char buf[30];

    pe = (unsigned char *) e;
    snprintf(buf,sizeof(buf),"%02x:%02x:%02x:%02x:%02x:%02x",
          pe[0], pe[1], pe[2], pe[3], pe[4], pe[5]);
    return(buf);
}



/* represent the sequence numbers absolute or relative to 0 */
/* N.B.: will fail will sequence space wraps around more than once */
static char *
PrintSeqRep(
    tcb *ptcb,
    u_long seq)
{
    static char buf[20];
    
    if (ptcb && print_seq_zero && (ptcb->syn_count>0)) {
      /* Relative form */
      sprintf(buf,hex?"0x%08lx(R)":"%lu(R)",
            seq - ptcb->syn);
    } else {
      /* Absolute form */
      sprintf(buf,hex?"0x%08lx":"%lu",seq);
    }
    return(buf);
}

Generated by  Doxygen 1.6.0   Back to index