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

rx25.c

   /****************************************************************
    Copyright (C) 1986-2000 by

    F6FBB - Jean-Paul ROUBELAT
    6, rue George Sand
    31120 - Roquettes - France
      jpr@f6fbb.org

    This program 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.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Parts of code have been taken from many other softwares.
    Thanks for the help.
    ****************************************************************/

/*
 * RX25.C : Decodage de trames au format ROSE X25
 *
 * D'apres KD.BAS de F1EBN
 *
 * FC1OAT@F6ABJ - 920820
 */

#include <serv.h>

/******************************************************************************
 * Dump ASCII avec Filtrage des caracteres non affichables
 ******************************************************************************/

static int decode_x25 (unsigned char *, int, char *);

static void decode_X121 (uchar *, int, char *);
static void decode_digi (uchar *, int, char *);
static void dump_hexa (uchar *, int, char *);

void put_rose (uchar * texte, int attr, int nbcar)
{
      unsigned char chaine[400];
      unsigned char *ptr = chaine;

      int decode = 1;                     /* A patcher, au cas ou ... */

      if (decode)
      {

            if (nbcar > 256)
                  nbcar = 256;

            strcpy (ptr, "X25 : ");
            ptr += 6;

            nbcar = 6 + decode_x25 (texte, nbcar, ptr);
      }
      else
            memcpy (chaine, texte, nbcar);


      put_ui (chaine, attr, nbcar);

}

/******************************************************************************
 * Les Causes
 *****************************************************************************/

static char *ResetCause (int cause)
{
      static char hex_cause[3];

      /* From ISO 8208 page 48 */

      switch (cause)
      {
      case 0:
            return "DTE Originated";
      case 0xC1:
            return "Gateway-detected Procedure Error";
      case 0xC3:
            return "Gateway Congestion";
      case 0xC7:
            return "Gateway Operational";
      default:
            switch (cause & 0x7F)
            {
            case 0x01:
                  return "Out Of Order";
            case 0x03:
                  return "Remote Procedure Error";
            case 0x05:
                  return "Local Procedure Error";
            case 0x07:
                  return "Network Congestion";
            case 0x09:
                  return "Remote DTE Operational";
            case 0x0F:
                  return "Network Operational";
            case 0x11:
                  return "Incompatible Destination";
            case 0x1D:
                  return "Network Out Of Order";
            default:
                  sprintf (hex_cause, "%2.2X", cause);
                  return hex_cause;
            }
      }
}

static char *ClearCause (int cause)
{
      static char hex_cause[3];

      /* From ISO 8208 page 43 */

      switch (cause)
      {
      case 0:
            return "DTE Originated";
      case 0xC1:
            return "Gateway-detected Procedure Error";
      case 0xC3:
            return "Gateway Congestion";
      case 0xC7:
            return "Gateway Operational";
      default:
            switch (cause & 0x7F)
            {
            case 0x01:
                  return "Number Busy";
            case 0x09:
                  return "Out Of Order";
            case 0x11:
                  return "Remote Procedure Error";
            case 0x19:
                  return "Reverse Charging Acceptance Not Subscribed";
            case 0x21:
                  return "Incompatible Destination";
            case 0x29:
                  return "Fast Select Acceptance Not Subscribed";
            case 0x39:
                  return "Ship Absent";
            case 0x03:
                  return "Invalid Facility Requested";
            case 0x0B:
                  return "Access Barred";
            case 0x13:
                  return "Local Procedure Error";
            case 0x05:
                  return "Network Congestion";
            case 0x0D:
                  return "Not Obtainable";
            case 0x15:
                  return "RPOA Out Of Order";
            default:
                  sprintf (hex_cause, "%2.2X", cause);
                  return hex_cause;
            }
      }
}


static char *RestartCause (int cause)
{
      static char hex_cause[3];

      /* From ISO 8208 page 50 */

      switch (cause)
      {
      case 0:
            return "DTE Originated";
      case 1:
            return "Local Procedure Error";
      case 3:
            return "Network Congestion";
      case 7:
            return "Network Operational";
      case 0x7F:
            return "Registration/Cancellation Confirmed";
      default:
            sprintf (hex_cause, "%2.2X", cause);
            return hex_cause;
      }
}

/******************************************************************************
 * Decodage de trames X25
 *****************************************************************************/

/* Decodage d'une adresse X.121 */

static void decode_X121 (uchar * data, int lgaddr, char *result)
{
      char bcd;
      int pfo, pfa;

      while (lgaddr > 0)
      {
            pfo = (*data & 0xF0) >> 4;
            pfa = *data & 0x0F;
            bcd = pfo + '0';
            *result++ = bcd;
            if (--lgaddr == 0)
                  break;
            bcd = pfa + '0';
            *result++ = bcd;
            lgaddr--;
            data++;
      }

      *result = '\0';
}

/* Dump Hexa */

static void dump_hexa (uchar * data, int l_data, char *result)
{
      int i;

      i = 0;
      while (l_data-- > 0)
      {
            sprintf (result, "%2.2X ", *data++);
            result += 3;
            if (++i == 16)
            {
                  *result++ = '\r';
                  i = 0;
            }
      }

      *result = '\0';
}

static char *rs_addr(char *addr)
{
      static char str[20];
      
      strncpy(str, addr, 4);
      str[4] = ',';
      strncpy(str+5, addr+4, 6);
      str[11] = '\0';
      
      return str;
}

/* Decodage d'un champ digi */

static void decode_digi (uchar * data, int l_data, char *result)
{
      while (l_data-- > 1)
      {
            *result++ = *data++ >> 1;
      }

      *result++ = '-';
      *result++ = (*data & 0x7F) >> 1;
      *result = 0;
}

/* Decodage d'une suite de champs facilite */

static void decodage_facilite (uchar * data, char *result)
{
      int lgfac, lg, fct, lgdigi, lgaddcall;
      int lgad, lgaddr, lgadind;
      static char digis[10], digid[10], icd[10];
      static char indorig[10], inddest[10];
      static char addstorig[20], addstdest[20];

      lgfac = *data++;
      lg = lgfac;

      digid[0] = digis[0] = '\0';

      while (lg > 0)
      {
            fct = *data++;
            lg--;
            switch (fct)
            {
            case 0:
                  /* Marker=0 National Fac ou Marker=15 CCITT */
                  data++;
                  lg--;
                  break;
            case 0x3F:
                  /* Utilise si appel par call digi au lieu du call N3 */
                  sprintf (result, "\rFacility 3F%2.2X", *data++);
                  lg--;
                  break;
            case 0x7F:
                  /* Nombre aleatoire pour eviter les rebouclages */
                  sprintf (result, " NbAlea: %2.2X%2.2X",
                               *data, *(data + 1));
                  data += 2;
                  lg -= 2;
                  break;
            case 0xE9:
                  /* Digi destination */
                  lgdigi = *data++;
                  decode_digi (data, lgdigi, digid);
                  data += lgdigi;
                  lg -= 1 + lgdigi;
                  break;
            case 0xEB:
                  /* Digi origine */
                  lgdigi = *data++;
                  decode_digi (data, lgdigi, digis);
                  data += lgdigi;
                  lg -= 1 + lgdigi;
                  break;
            case 0xC9:
                  /* Adresse et indicatif du nodal destination */
            case 0xCB:
                  /* Adresse et indicatif du nodal origine */
                  lgaddcall = *data++;
                  data++;
                  dump_hexa (data, 3, icd);
                  data += 3;
                  lgad = *data++;
                  lg -= 6;
                  lgaddr = lgad;
                  if (fct == 0xCB)
                        decode_X121 (data, lgaddr, addstorig);
                  else
                        decode_X121 (data, lgaddr, addstdest);
                  data += (lgad + 1) / 2;
                  lg -= (lgad + 1) / 2;
                  lgadind = lgaddcall - (lgad + 1) / 2 - 5;
                  if (fct == 0xCB)
                        strncpy (indorig, data, lgadind);
                  else
                        strncpy (inddest, data, lgadind);
                  data += lgadind;
                  lg -= lgadind;
                  break;
            default:
                  sprintf (result, "\rUnknown Facility Type %2.2X", fct);
                  lg = 0;
                  break;
            }

            result += strlen (result);
      }

      sprintf (result, "\r%s@%s", indorig, rs_addr(addstorig));
      result += strlen (result);
      if (*digis)
            sprintf (result, " via %s", digis);
      strcat (result, " -> ");
      result += strlen (result);
      sprintf (result, "%s@%s", inddest, rs_addr(addstdest));
      result += strlen (result);
      if (*digid)
            sprintf (result, " via %s", digid);
}

/* Decodage des donnees accompagnant un CALL REQUEST */

static void decode_call_req (uchar * data, int l_data, char *result)
{
      int lgdest, lgorig, lgaddr;

      /* Decodage du champ adresse */

      lgdest = *(data + 3) & 0x0F;
      lgorig = (*(data + 3) & 0xF0) >> 4;
      lgaddr = lgorig + lgdest;
      /* 
      decode_X121 (data + 4 + (lgdest / 2), lgorig, result);
      strcat (result, " -> ");
      decode_X121 (data + 4, lgdest, result + strlen (result));
      */
      data += 4 + (lgaddr / 2);
      l_data -= 4 + (lgaddr / 2);
      /* result += strlen (result); */

      /* Decodage des champs facilite */

      decodage_facilite (data, result);
}

/* Point d'entree du decodage des trames X25 */

static int decode_x25 (uchar * data, int l_data, char *result)
{
      int tpaq, id_format, r, s, lci, lg;

      char *ptemp = result;


      lci = ((*data & 0x0f) << 4) | *(data + 1);
      id_format = *data;
      tpaq = *(data + 2);
      r = (tpaq & 0xE0) >> 5;
      s = (tpaq & 0x0E) >> 1;

      sprintf (result, "LCI %03d : ", lci);
      result += strlen (result);

      if (id_format & 0x80)
            strcat (result, "Q ");
      if (id_format & 0x40)
            strcat (result, "D ");

      if (tpaq & 1)
      {
            switch (tpaq)
            {
            case 0x0B:
                  sprintf (result, "CALL REQUEST ");
                  result += strlen (result);
                  decode_call_req (data, l_data, result);
                  break;
            case 0x0F:
                  sprintf (result, "CALL ACCEPTED");
                  break;
            case 0x13:
                  sprintf (result,
                               "CLEAR REQUEST - Cause %s - Diag %d",
                               ClearCause (*(data + 3)), *(data + 4));
                  break;
            case 0x17:
                  sprintf (result, "CLEAR CONFIRMATION");
                  break;
            case 0x23:
                  sprintf (result, "INTERRUPT");
                  break;
            case 0x27:
                  sprintf (result, "INTERRUPT CONFIRMATION");
                  break;
            case 0x1B:
                  sprintf (result,
                               "RESET REQUEST - Cause %s - Diag %d",
                               ResetCause (*(data + 3)), *(data + 4));
                  break;
            case 0x1F:
                  sprintf (result, "RESET CONFIRMATION");
                  break;
            case 0xF3:
                  sprintf (result, "REGISTRATION REQUEST");
                  break;
            case 0xF7:
                  sprintf (result, "REGISTRATION CONFIRMATION");
                  break;
            case 0xFB:
                  sprintf (result,
                               "RESTART REQUEST - Cause %s - Diag %d",
                               RestartCause (*(data + 3)), *(data + 4));
                  break;
            case 0xFF:
                  sprintf (result, "RESTART CONFIRMATION");
                  break;
            default:
                  switch (tpaq & 0x0F)
                  {
                  case 0x01:
                        sprintf (result, "RR R%d", r);
                        break;
                  case 0x05:
                        sprintf (result, "RNR R%d", r);
                        break;
                  case 0x09:
                        sprintf (result, "REJ R%d", r);
                        break;
                  }
                  break;
            }
            l_data = 0;
            lg = strlen (ptemp);
      }
      else
      {
            l_data -= 3;

            if (tpaq & 0x10)
                  strcat (result, "M ");
            sprintf (result, "DATA R%d S%d L=%d", r, s, l_data);
            strcat (result, "\r");
            lg = strlen (ptemp);

            result += strlen (result);
            if (l_data < 0)
                  l_data = 0;
            memcpy (result, data + 3, l_data);
      }

      return (lg + l_data);
}

Generated by  Doxygen 1.6.0   Back to index