⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 _w3mux.c

📁 This directory contains source code for tcpdump, a tool for network monitoring and data acquisition
💻 C
字号:
/*
 * Copyright (c) 1992, 1993, 1994, 1995, 1996
 * The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
 * the University nor the names of its contributors may be used to endorse
 * or promote products derived from this software without specific prior
 * written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#if 0
static const char rcsid[] =
  "@(#) $Header: /ng/src/proto-analyser/tcpdump/RCS/print-w3mux.c,v 1.7 1998/06/27 03:12:45 janssen Exp $ (LBL)";
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <ctype.h>

#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>

#include "interfac.h"
#include "a2name.h"

struct w3mux_header {
       u_int32_t header;
       u_int32_t longlength;
     };

#define MUX_CONTROL             0x00800000
#define MUX_CONTROL_SHIFT	23
#define MUX_CONTROL_CODE	0x00780000
#define MUX_CONTROL_CODE_SHIFT	19
#define MUX_SYN                 0x00400000
#define MUX_SYN_SHIFT		22
#define MUX_FIN                 0x00200000
#define MUX_FIN_SHIFT		21
#define MUX_RST                 0x00100000
#define MUX_RST_SHIFT		20
#define MUX_PUSH                0x00080000
#define MUX_PUSH_SHIFT		19
#define MUX_LONG_LENGTH		0x00040000
#define MUX_LONG_LENGTH_SHIFT	18
#define MUX_SESSION             0xFF000000
#define MUX_SESSION_SHIFT	24
#define MUX_FRAGMENT_SIZE       0x0003FFFF
#define MUX_FRAGMENT_SIZE_SHIFT 0

#define HEADER_EXTENDED(ptr)		((((struct w3mux_header *)ptr)->header & MUX_LONG_LENGTH) != 0)
#define HEADER_FRAGMENT_SIZE(ptr)	(((struct w3mux_header *)ptr)->header & MUX_FRAGMENT_SIZE)
#define HEADER_CHUNK_SIZE(ptr)		(HEADER_EXTENDED(ptr)?(((struct w3mux_header *)ptr)->longlength):HEADER_FRAGMENT_SIZE(ptr))
#define HEADER_SESSION_ID(ptr)		((((struct w3mux_header *)ptr)->header & MUX_SESSION) >> MUX_SESSION_SHIFT)
#define HEADER_CHANNEL_ID(ptr)		(((struct w3mux_header *)ptr)->header & MUX_FRAGMENT_SIZE)
#define HEADER_MAX_FRAGMENT_SIZE(ptr)	(((struct w3mux_header *)ptr)->header & MUX_FRAGMENT_SIZE)
#define HEADER_CREDIT_SIZE(ptr)		(((struct w3mux_header *)ptr)->header & MUX_FRAGMENT_SIZE)
#define HEADER_DEFAULT_CREDIT_SIZE(ptr)	(((struct w3mux_header *)ptr)->header & MUX_FRAGMENT_SIZE)
#define HEADER_ATOM_STR_LENGTH(ptr)	(((struct w3mux_header *)ptr)->header & MUX_FRAGMENT_SIZE)
#define HEADER_ENDPOINT_LENGTH(ptr)	(((struct w3mux_header *)ptr)->header & MUX_FRAGMENT_SIZE)
#define HEADER_CONTROL_MSG(ptr)		((((struct w3mux_header *)ptr)->header & MUX_CONTROL) != 0)
#define HEADER_CONTROL_CODE(ptr)	((((struct w3mux_header *)ptr)->header & MUX_CONTROL_CODE) >> MUX_CONTROL_CODE_SHIFT)
#define HEADER_LAST_CHUNK(ptr)		((((struct w3mux_header *)ptr)->header & MUX_PUSH) != 0)
#define HEADER_NEW_SESSION(ptr)		((((struct w3mux_header *)ptr)->header & MUX_SYN) != 0)
#define HEADER_LAST_MSG(ptr)		((((struct w3mux_header *)ptr)->header & MUX_FIN) != 0)
#define HEADER_RESET(ptr)		((((struct w3mux_header *)ptr)->header & MUX_RST) != 0)

/* control codes
 */
#define MUX_InternAtom		0
#define MUX_DefineEndpoint	1
#define MUX_SetMSS		2
#define MUX_AddCredit		3
#define MUX_SetDefaultCredit	4
#define MUX_NoOp		5

#define MUX_ATOM_BASE		2000

struct w3mux_state {
       u_int32_t srcaddr, dstaddr;
       u_short   srcport, dstport;
       struct w3mux_header header;
       u_int32_t pending;             /* number of bytes still to be read in chunk */
       u_int     partial : 3;         /* number of bytes in pbytes so far, always less than 8 */
       u_int     initiated : 1;       /* 1 if "src" initiated connection, 0 otherwise */
       u_int     reading_header  : 1; /* 1 if reading header, 0 otherwise */
       u_int     reading_longlen : 1; /* 1 if reading long len, 0 otherwise */
       u_char   *msgbuf;              /* buffer to hold message */
       u_char    msgbufsize;          /* size of "msgbuf" */
       u_char    msgbufused;          /* number of bytes currently used in msgbuf */
       u_int     conn_id;             /* connection identifier */
     };

struct state_list {
       struct state_list *next;
       struct w3mux_state state;
     };

static struct state_list *connections = NULL;

static struct w3mux_state *add_state (u_int32_t saddr, u_short sport,
                                      u_int32_t daddr, u_int32_t dport)
{
  struct state_list *newstate = calloc (sizeof(*newstate), 1);

  if (!newstate)
     return (NULL);

  newstate->state.dstaddr = daddr;
  newstate->state.dstport = dport;
  newstate->state.srcaddr = saddr;
  newstate->state.srcport = sport;

  newstate->next = connections;
  connections    = newstate;
  return (&newstate->state);
}

static struct w3mux_state *find_state (u_int32_t saddr, u_short sport,
                                       u_int32_t daddr, u_int32_t dport)
{
  struct state_list *p;

  for (p = connections; p; p = p->next)
  {
    if (p->state.srcaddr == saddr && p->state.srcport == sport &&
        p->state.dstaddr == daddr && p->state.dstport == dport)
       return (&p->state);
  }
  return (NULL);
}

static struct state_list *remove_state (u_int32_t saddr, u_short sport,
                                        u_int32_t daddr, u_int32_t dport)
{
  struct state_list *p, **last;

  for (p = connections, last = &connections; p; last = &p->next, p = p->next)
  {
    if (p->state.srcaddr == saddr && p->state.srcport == sport &&
        p->state.dstaddr == daddr && p->state.dstport == dport)
    {
      *last = p->next;
      return (p);
    }
  }
  return (NULL);
}

static void free_state (struct state_list *s)
{
  if (s)
  {
    if (s->state.msgbuf)
       free (s->state.msgbuf);
    free (s);
  }
}

void w3mux_print (const u_char *bp, u_int length, const u_char *bp2,
                  const u_char *bp3)
{
  struct ip          *ip = (struct ip *) bp2;
  struct tcphdr      *tp = (struct tcphdr *) bp3;
  struct w3mux_state *s;
  struct state_list  *rm = NULL;

  u_char    flags;
  u_int     started = 0;
  u_int     dumped = 0;
  u_int     continued = 0;
  u_short   sport, dport;
  u_int32_t saddr, daddr;
  static    u_int conn_id = 0;

  saddr = ntohl (ip->ip_src.s_addr);
  sport = ntohs (tp->th_sport);
  daddr = ntohl (ip->ip_dst.s_addr);
  dport = ntohs (tp->th_dport);

  s = find_state (saddr, sport, daddr, dport);
  flags = tp->th_flags;
  if ((flags & (TH_FIN | TH_RST)) && s)
     rm = remove_state (saddr, sport, daddr, dport);
  else if (s == 0)
  {
    s = add_state (saddr, sport, daddr, dport);
    s->conn_id = (conn_id += 256);
    s->reading_header = 1;
  }

  if (flags & TH_SYN)
     s->initiated = 1;

#if 0
  PRINTF (" w3mux,s=%p,rm=%p,pending=%lu,initiated=%s,src=%8.8x:%lu,dst=%8.8x:%lu ",
          s, rm, s->pending, s->initiated ? "yes" : "no",
          saddr, sport, daddr, dport);
#endif

  while (length > 0)
  {
    if (s->reading_header)
    {
      continued = 0;

      /* partial header? */
      if (length < (4 - s->partial))
      {
        memcpy ((char*)&s->header.header + s->partial, bp, length);
        length = 0;
        s->partial += length;
        break;
      }
      if (s->partial > 0)
      {
        memcpy ((char*)&s->header.header + s->partial, bp, 4 - s->partial);
        length -= 4 - s->partial;
        bp     += 4 - s->partial;
        s->partial = 0;
        s->header.header = ntohl (s->header.header);
      }
      else
      {
        s->header.header = ntohl (*((u_int32_t*)bp));
        length -= 4;
        bp     += 4;
      }
      s->reading_header = 0;
      if (HEADER_EXTENDED (&s->header))
      {
        s->reading_longlen = 1;
        continue;
      }
      else
      {
        s->pending = HEADER_CHUNK_SIZE (&s->header);
      }
    }
    else if (s->reading_longlen)
    {
      continued = 0;
      if (length < (4 - s->partial))
      {
        memcpy ((char*)&s->header.longlength + s->partial, bp, length);
        length = 0;
        s->partial += length;
        break;
      }
      else if (s->partial > 0)
      {
        memcpy ((char*)&s->header.longlength + s->partial, bp, 4 - s->partial);
        length -= 4 - s->partial;
        bp     += 4 - s->partial;
        s->partial = 0;
        s->header.longlength = ntohl (s->header.longlength);
      }
      else
      {
        s->header.longlength = ntohl (*((u_int32_t*)bp));
        length -= 4;
        bp     += 4;
      }
      s->reading_longlen = 0;
      s->pending = HEADER_CHUNK_SIZE (&s->header);
    }
    else
      continued = 1;

    if (!started)
    {
      PUTS (" <w3mux");
      started = 1;
    }

    if (!continued)
    {
      if (Pflag)
         PUTS ("\n ");

      if (HEADER_CONTROL_MSG (&s->header))
      {
        switch (HEADER_CONTROL_CODE (&s->header))
        {
          case MUX_InternAtom:
               PRINTF (" c(InternAtom,atom=%lu,%luB)",
                       MUX_ATOM_BASE + HEADER_SESSION_ID (&s->header));
               break;

          case MUX_DefineEndpoint:
               PRINTF (" c(DefineEndpoint,%luB)", s->pending);
               break;

          case MUX_SetMSS:
               PRINTF (" c(SetMSS,%lu)", HEADER_MAX_FRAGMENT_SIZE (&s->header));
               s->pending = 0;
               break;

          case MUX_AddCredit:
               PRINTF (" c(AddCredit,sess=%lu,credit=%lu)",
                       HEADER_SESSION_ID (&s->header),
                       HEADER_CREDIT_SIZE (&s->header));
               s->pending = 0;
               break;

          case MUX_SetDefaultCredit:
               PRINTF (" c(SetDefaultCredit,%lu)",
                       HEADER_DEFAULT_CREDIT_SIZE (&s->header));
               s->pending = 0;
               break;

          case MUX_NoOp:
               PUTS (" c(NoOp)");
               break;

          default:
               PRINTF (" c(%lu)", HEADER_CONTROL_CODE (&s->header));
               break;
        }
      }
      else
      {
        PRINTF (" %s(sess=%lu",
                HEADER_EXTENDED (&s->header) ? "D" : "d",
                HEADER_SESSION_ID (&s->header));

        if (HEADER_NEW_SESSION (&s->header))
           PRINTF (",syn(channel=%lu)", HEADER_CHANNEL_ID (&s->header));

        if (HEADER_LAST_CHUNK (&s->header))
           PUTS (",push");

        if (HEADER_LAST_MSG (&s->header))
           PUTS (",fin");

        if (HEADER_RESET (&s->header))
           PUTS (",reset");

        PRINTF (",bytes=%lu)", HEADER_CHUNK_SIZE (&s->header));

        if (HEADER_CHUNK_SIZE (&s->header) > (s->msgbufsize - s->msgbufused))
        {
          if (s->msgbuf)
               s->msgbuf = realloc (s->msgbuf, s->msgbufsize + HEADER_CHUNK_SIZE (&s->header));
          else s->msgbuf = malloc (s->msgbufsize + HEADER_CHUNK_SIZE (&s->header));
          s->msgbufsize = s->msgbuf ? (s->msgbufsize + HEADER_CHUNK_SIZE (&s->header)) : 0;
        }
      }
    }

    if (Pflag)
    {
      if (!continued && vflag)
      {
        struct {
          u_int32_t f1;
          u_int32_t f2;
        } x;

        x.f1 = htonl (s->header.header);
        x.f2 = htonl (s->header.longlength);
        default_print ((const u_char*)&x, HEADER_EXTENDED (&s->header) ? 8 : 4);
      }
      if (s->pending > 0)
         default_print (bp, min (length, s->pending));
      dumped = ((!continued && vflag) || (s->pending > 0));
    }

    if (length < s->pending)
    {
      memcpy (s->msgbuf + s->msgbufused, bp, length);
      s->msgbufused += length;
      bp            += length;
      s->pending    -= length;
      length = 0;
    }
    else if (s->pending > 0)
    {
      memcpy (s->msgbuf + s->msgbufused, bp, s->pending);
      s->msgbufused += s->pending;
      bp            += s->pending;
      length        -= s->pending;
      s->pending = 0;
    }

    if (s->pending == 0)
    {
      if (HEADER_LAST_CHUNK (&s->header) && !HEADER_CONTROL_MSG (&s->header))
      {
        switch (messagetype)
        {
          case MT_W3NG:
               w3ng_print (s->conn_id + HEADER_SESSION_ID (&s->header), s->msgbuf, s->msgbufused);
               break;

          case MT_ONCRPC:
               oncrpc_print (s->conn_id + HEADER_SESSION_ID (&s->header), s->msgbuf, s->msgbufused);
               break;

          case MT_GIOP:
               giop_print (s->conn_id + HEADER_SESSION_ID (&s->header), s->msgbuf, s->msgbufused);
               break;
        }
        s->msgbufused = 0;
      }
      s->reading_header = 1;
    }
  }

  if (dumped)
     PUTCHAR ('\n');
  if (started)
     PUTCHAR ('>');
  free_state (rm);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -