/* Print Bridge (Management) Packets */

#include <sys/param.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <netinet/in_systm.h>

#include <stdio.h>
#include <string.h>
#ifdef __STDC__
#include <stdlib.h>
#endif
#include <unistd.h>

#include "interface.h"
#include "addrtoname.h"
#include "bridge.h"
#include "extract.h"

/* according to Christian Claveleira of Universite' Rennes I
   Print 3Com TCP/IP Bridge Management frames */

void
br3com_print(const u_char *p, int length)
{
    register const struct br3com_alive *bp;
#ifdef TCPDUMP_ALIGN
    struct in_addr addr;
#endif

    bp = (const struct br3com_alive *)p;

    if ((length < sizeof(struct br3com_alive)) ||
	((u_char *)(bp + 1) > snapend)) {
	(void)printf("[|Bridge/3Com]");
	return;
    }

#ifdef TCPDUMP_ALIGN
    (void)bcopy((char *)&bp->ip_addr, (char *)&addr, sizeof(addr));
    printf("Bridge/3Com-station %s alive", ipaddr_string(&addr));
#else
    printf("Bridge/3Com-station %s alive",
	   ipaddr_string(&bp->ip_addr));
#endif

    if (vflag)
	(void)printf(" (%.24s)", bp->s);
}

/* According to Interconnections, Bridges and Routers by Radia Perlman
   Print 802.1d frames */

void
br8021d_print(const u_char *p, int length)
{
    register const struct br8021d_conf *bp;

    bp = (const struct br8021d_conf *)p;

    if ((length < 4) || ((p + 4) > snapend)) {
	(void)printf("[|801.1d|]");
	return;
    }

    printf("802.1d");

    if ((bp->pid[0] != BR8021D_PID) ||
	(bp->pid[1] != BR8021D_PID) ||
	(bp->ver != BR8021D_VER))
	return;

    switch (bp->type) {
      case BR8021D_CONF:
	printf(" Conf");
	if ((length < sizeof(struct br8021d_conf)) ||
	    ((u_char *)(bp + 1) > snapend))
	    return;
	switch (bp->flags) {
	  case 0:
	    break;
	  case BR8021D_TCA_F:
	    printf(" TCA");
	    break;
	  case BR8021D_TC_F:
	    printf(" TC");
	    break;
	  case (BR8021D_TCA_F|BR8021D_TC_F):
	    printf(" TC/TCA");
	    break;
	  default:
	    printf(" flags=%02x", bp->flags);
	    break;
	}
	printf(" root=%x-%s",
	       EXTRACT_SHORT(bp->rootID),
	       etheraddr_string(&bp->rootID[2]));
	printf(" cost=%ud", EXTRACT_LONG(bp->cost));
	printf(" bridge=%x-%s %x-%d",
	       EXTRACT_SHORT(bp->bridgeID),
	       etheraddr_string(&bp->bridgeID[2]),
	       bp->portID[0],
	       bp->portID[1]);
	return;
      case BR8021D_TCNOT:
	if (!vflag)
	    printf(" TC Not");
	else
	    printf(" Topology change notification");
	return;
      default:
	printf(" type=%02x", bp->type);
	return;
    }
}
