home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-386-Vol-2of3.iso / c / c-niftp.zip / unix-niftp-5.6 / lib / x25b / x25b.c < prev    next >
C/C++ Source or Header  |  1990-08-01  |  21KB  |  786 lines

  1. /* X25 over a boring stream (in this case TCP) */
  2.  
  3. /*
  4.  *    an implementation of X.25 over a boring stream (e.g. tcp/ip)
  5.  *
  6.  *    Copyright (c) Piete Brooks 1987
  7.  */
  8.  
  9. #ifndef    lint
  10. static char RCSid[]="$Header: /Nfs/heaton/glob/src/usr.lib/niftp/src/lib/x25b/x25b.c,v 5.5 90/08/01 13:39:25 pb Exp $";
  11. static char *_versions    = "$Revision: 5.5 $";
  12. static char *_dates    = "$Date: 90/08/01 13:39:25 $";
  13. #endif    lint
  14.  
  15. /*
  16.  *    This implements the x25bridge protocol (x25 over TCP/IP)
  17.  *
  18.  *    The client process should provide two routines:
  19.  *
  20.  *    x25b_logit(mask, format, arg1, arg2, arg3, arg4);
  21.  *    int    mask;
  22.  *    char    *format;
  23.  *    {    fprintf(stderr, format, arg1, arg2, arg3, arg4);
  24.  *    }
  25.  *
  26.  *    x25b_perror(mask, format, arg1, arg2, arg3, arg4);
  27.  *    int    mask;
  28.  *    char    *format;
  29.  *    {    fprintf(stderr, format, arg1, arg2, arg3, arg4);
  30.  *        fflush(stderr);
  31.  *        perror("");
  32.  *    }
  33.  *
  34.  *    Note that perror will need some sort of newline added at the end.
  35.  *
  36.  *    The bits in n are:
  37.  *    
  38.  *    X25B_L_STAMP        this is a continuation of the previous msg
  39.  *    X25B_L_STAMP        if possible, datestamp this message
  40.  *    X25B_L_DEBUG        this is a debug message (may be ignored)
  41.  *
  42.  *
  43.  *    The interface is
  44.  *    bytes = x25b_read_data(fd, p_send_type, buff, len)
  45.  *    bytes = x25b_read_data2(fd, p_send_type, buff, len,
  46.  *        p_flags, p_tspad, p_x25io)
  47.  *    char *p_send_type;
  48.  *    char *buff;
  49.  *
  50.  *    Read up to len bytes into buff, and put the X25 QMD bits into
  51.  *    *p_send_type.
  52.  *    If no data is read, *p_send_type is set to 0xff.
  53.  *    If p_send_type is NULL, it is not used.
  54.  *    *** Excess data is DISCARDED ***
  55.  *    if buff == p_x25io->x_buf then p_x25io is used directly,
  56.  *    otherwise the data is copied into an internal structure.
  57.  *
  58.  *
  59.  *    bytes = x25b_write_data2(fd, p_send_type, buff, len,
  60.  *        p_flags, p_tspad, p_x25io)
  61.  *    bytes = x25b_write_data(fd, p_send_type, buff, len)
  62.  *    char *p_send_type;
  63.  *    char *buff;
  64.  *    char *p_flags;
  65.  *    char *p_tspad;
  66.  *    char *p_x25io;
  67.  *
  68.  *    Write len bytes from buff, using *p_send_type as the QMD bits.
  69.  *    If flags is NULL, the bits are assumed to be zero.
  70.  *
  71.  *
  72.  *    x25b_open_server(server, port)
  73.  *    char *server;
  74.  *    char *port;
  75.  *    server is a comma separated list of gateways to try.
  76.  *    If NULL or a null string, use the compiled in default (x25-serv)
  77.  *    port is the tcp port number (numeric or as in /etc/services)
  78.  *    defaulting to spad (yuck!)
  79.  *    These are overridden by environment variables X25SERVER and X25PORT.
  80.  *
  81.  *
  82.  *    x25b_open_ybts4(dte, ybts, callingdte, callingname, callingybts,
  83.  *            server, port, user, facil, x25iop)
  84.  *    char *dte;
  85.  *    char *ybts;
  86.  *    char *callingdte;    [ 1+ ]
  87.  *    char *callingname;    [ 3+ ]
  88.  *    char *callingybts;
  89.  *    char *server;
  90.  *    char *port;
  91.  *    char *user;        [ 4+ ]
  92.  *    struct facilities *facil;
  93.  *    struct x25io *x25iop;
  94.  *
  95.  *    x25b_open_x29_2(dte, xcudf, callingdte, server, port,
  96.  *        user, facil, x25iop)
  97.  *    char *dte;
  98.  *    char *xcudf;
  99.  *    char *callingdte;
  100.  *    char *server;
  101.  *    char *port;
  102.  *    char *user;        [ 2+ ]
  103.  *    struct facilities *facil;
  104.  *    struct x25io *x25iop;
  105.  *
  106.  *    The third form of open .....
  107.  *    the first two specify the address to be called.
  108.  *    cudf may be:
  109.  *        <text>
  110.  *        :<hex>
  111.  *        ::<pid><hex>
  112.  */
  113.  
  114. #define    FULL_X25STR
  115. #include "x25b.h"
  116. #include <errno.h>        /* EWOULDBLOCK */
  117. #include <sys/types.h>
  118. #include <sys/socket.h>
  119. #include <netinet/in.h>
  120. #include <netdb.h>
  121. #include <ctype.h>
  122.  
  123. struct x25io _x25io;
  124. struct servent *getservbyname();
  125. char *getenv();
  126. char *index();
  127. struct hostent *gethostbyname();
  128.  
  129. x25b_read_data(fd, p_send_type, buff, len)
  130. char *p_send_type;
  131. char *buff;
  132. {    return x25b_read_data2(fd, p_send_type, buff, len, 0, 0, 0);
  133. }
  134.  
  135. x25b_read_data2(fd, p_send_type, buff, len, p_flags, p_tspad, p_x25io)
  136. char *p_send_type;
  137. char *buff;
  138. char *p_flags;
  139. char *p_tspad;
  140. struct x25io *p_x25io;
  141. {    int n;
  142.  
  143.     if (! p_x25io) p_x25io = &_x25io;
  144.  
  145.     if ((n = _x25b_readpkt(fd, p_x25io)) <= 0)
  146.     {    if (p_send_type) *p_send_type = 0xff;
  147.         return n;
  148.     }
  149.  
  150.     if (p_x25io->x_flags == X25F_SBUF ||
  151.         p_x25io->x_flags == 0xd2 || p_x25io->x_flags == 0x61)
  152.     {    if (p_x25io->x_flags == 0x61)
  153.         {    p_x25io->x_flags = 0xd2;
  154.         }
  155.         _x25b_log_buff(fd, (char *) p_x25io, n+6, 0);
  156.         send(fd, (char *) p_x25io, n+6, 0);
  157.         n -= (((char *) (&p_x25io->x_sbuf)) -  (char *) p_x25io);
  158. #define    STRUCT_FUDGE    (-2)
  159.         if (p_x25io->x_flags == 0xd2 || p_x25io->x_flags == 0x61)
  160.         {    x25b_logit(X25B_L_STAMP,
  161.                 "Sigh -- spad set flags wrong\n");
  162.             p_x25io->x_flags = X25F_SBUF;
  163.             p_x25io->x_send_type = 0;
  164.         }
  165.         if (n > len)
  166.         {    x25b_logit(X25B_L_STAMP,
  167.                 "I had %d was only asked for %d\n",
  168.                 n, len);
  169.             n = len;
  170.         }
  171.         x25b_logit(0, "[OffSet: %d, %d]",
  172.             ((char *)  p_x25io->x_buf) - (char *) p_x25io,
  173.             ((char *) (&p_x25io->x_sbuf)) - (char *) p_x25io);
  174.  
  175.         _x25b_print_facil(p_x25io->x_facil);
  176.         if (p_send_type) *p_send_type = p_x25io->x_send_type;
  177.         bcopy(&((char *)(&p_x25io->x_sbuf))[STRUCT_FUDGE], buff, n);
  178.         return n;
  179.     }
  180.     if (p_send_type) *p_send_type = p_x25io->x_send_type;
  181.     if (p_tspad) *p_tspad = p_x25io->x_tspad;
  182.     if (p_flags) (*p_flags = p_x25io->x_flags);
  183.     if (buff == p_x25io->x_buf)
  184.         ;
  185.     else if (p_x25io->x_flags & X25F_TSPAD)
  186.     {    *buff = p_x25io->x_tspad;
  187.         bcopy(p_x25io->x_buf, buff+1, n);
  188.         n++;
  189.     }
  190.     else bcopy(p_x25io->x_buf, buff, n);
  191.     return n;
  192. }
  193.  
  194. x25b_write_data(fd, p_send_type, buff, len)
  195. char *p_send_type;
  196. char *buff;
  197. {    return x25b_write_data2(fd, p_send_type, buff, len, 0, 0, 0);
  198. }
  199.  
  200. x25b_write_data2(fd, p_send_type, buff, len, p_flags, p_tspad, p_x25io)
  201. char *p_send_type;
  202. char *buff;
  203. char *p_flags;
  204. char *p_tspad;
  205. struct x25io *p_x25io;
  206. {    static int skip = 0;
  207.     int slen = x25hdrsize + len + 1 + TS29_BYTES;
  208.     char *data;
  209.     int rc;
  210.     extern errno;
  211.  
  212.     if (!p_x25io) p_x25io = &_x25io;
  213.  
  214.     data = (char *) p_x25io;
  215.     if (buff != p_x25io->x_buf)    bcopy(buff, p_x25io->x_buf, len);
  216.  
  217.     if (p_x25io->x_version != X25IO_VER)
  218.     {    x25b_logit(X25B_L_STAMP, "write data: version was %d (%d)\n",
  219.                  p_x25io->x_version, X25IO_VER);
  220.         p_x25io->x_version = X25IO_VER;
  221.     }
  222.     p_x25io->x_tspad    = (p_tspad) ? *p_tspad : 0;
  223.     p_x25io->x_flags    = (p_flags) ? *p_flags : 0;
  224.     p_x25io->x_send_type    = (p_send_type) ? *p_send_type : 0;
  225.     p_x25io->x_count_ms    = len / 256;
  226.     p_x25io->x_count_ls    = len % 256;
  227.  
  228.     if (x25b_debug & 2) x25b_logit(1, "wd%3d [%08x %08x %08x]\n",
  229.         len,
  230.         ((long *) p_x25io)[0],
  231.         ((long *) p_x25io)[1],
  232.         ((long *) p_x25io)[2]);
  233.     _x25b_log_buff(fd, (char *) p_x25io, slen, 0);
  234.     if (skip)
  235.     {    data += skip, slen -= skip;
  236.         x25b_logit(1, "Skip %d on %08x %08x %08x\n",
  237.             skip,
  238.             ((long *) p_x25io)[0],
  239.             ((long *) p_x25io)[1],
  240.             ((long *) p_x25io)[2]);
  241.     }
  242.     errno = -1;
  243.     rc=send(fd, data, slen, 0);
  244.     if (rc != slen)
  245.     {    x25b_logit(1, "Old  %d on %08x %08x %08x ",
  246.             skip,
  247.             ((long *) p_x25io)[0],
  248.             ((long *) p_x25io)[1],
  249.             ((long *) p_x25io)[2]);
  250.         skip += (rc < 0) ? 0 : rc;
  251.         x25b_logit(1, "%d -> %d so %d (%d)\n", rc, slen, skip, errno);
  252.         errno = EWOULDBLOCK;
  253.         return -1;
  254.     }
  255.     else skip = 0;
  256.  
  257.     return (rc <= 0) ? -1 : len;
  258. }
  259.  
  260. x25b_open_server(servers, port)
  261. char *servers;
  262. char *port;
  263. {    struct sockaddr_in to;
  264.     struct hostent *gethostent(), *host;
  265.     int portn;
  266.     char *next;
  267.     char *env;
  268.     int fd = -1;
  269.  
  270.     if (env = getenv("X25PORT")) port = env;
  271.     if (!port || !*port) port = "spad";
  272.  
  273.     if (env = getenv("X25SERVER")) servers = env;
  274.     if (!servers || !*servers) servers = SERVERNAME;
  275.  
  276.     if (isdigit(*port)) portn = htons(atoi(port));
  277.     else
  278.     {    struct servent *sp = getservbyname(port, "tcp");
  279.         if (!sp)
  280.         {    x25b_logit(X25B_L_STAMP, "no %s/tcp service\n", port);
  281.             return -1;
  282.         }
  283.         portn = sp->s_port;
  284.     }
  285.  
  286.     /* loop to try multiple servers */
  287.     for(next=servers; next; )
  288.     {    char server[128];
  289.         char *this = next;
  290.  
  291.         next = index(this, ',');
  292.         strcpy(server, this);
  293.         if (next) server[next++ - this] = '\0';
  294.         if (x25b_debug & 4) x25b_logit(X25B_L_STAMP, "Try %s (%s|%s)",
  295.             server, this, servers);
  296.  
  297.         host = gethostbyname(server);
  298.         if (!host) {
  299.             x25b_logit(X25B_L_STAMP,
  300.                 " +++- can't find the server %s\r\n", server);
  301.             continue;
  302.         }
  303.         bzero((char *)&to, sizeof(to));
  304.         bcopy(host->h_addr, (char *)&to.sin_addr, host->h_length);
  305.         to.sin_family = host->h_addrtype;
  306.         to.sin_port = portn;
  307.         fd = socket(AF_INET, SOCK_STREAM, 0);
  308.         if (fd < 0)
  309.         {    x25b_logit(X25B_L_STAMP, " +++- %s: ", server);
  310.             x25b_perror(X25B_L_STAMP, "client socket");
  311.             continue;
  312.         }
  313.         if (connect(fd, (struct sockaddr *) &to, sizeof(to)) < 0)
  314.         {    x25b_logit(X25B_L_STAMP, " +++- %s: (%s/%s=%d): ",
  315.                 server, port, port, portn);
  316.             x25b_perror(X25B_L_STAMP, "client connect");
  317.             close(fd);
  318.             fd = -1;
  319.             continue;
  320.         }
  321.         if (x25b_debug & 4) x25b_logit(X25B_L_STAMP | X25B_L_DEBUG,
  322.                 "++ call %s on port 0x%x\n", server, portn);
  323.         break;
  324.     }
  325.     if (!host)
  326.     {    x25b_logit(X25B_L_STAMP,
  327.             " +++- can't find the servers (%s)\n", servers);
  328.         return -1;
  329.     }
  330.     if (fd < 0)
  331.     {    x25b_perror(X25B_L_STAMP, "cant find a respondng server");
  332.         return -1;
  333.     }
  334.  
  335.     if (x25b_debug & 4) x25b_logit(X25B_L_STAMP | X25B_L_DEBUG,
  336.         "Returning %d\n", fd);
  337.     return fd;
  338. }
  339.  
  340. _x25b_init_x25io(x25io)
  341. struct x25io *x25io;
  342. {    bzero((char *)x25io, sizeof(struct x25io));
  343.     x25io->x_version    = X25IO_VER;
  344. }
  345.  
  346. _x25b_make_connection(fd, x25iop)
  347. struct x25io *x25iop;
  348. {
  349.     if (!x25iop)    x25iop = &_x25io;
  350.  
  351.     /* Now make up the data part of the packet */
  352.     x25iop->x_tspad        = 0;
  353.     x25iop->x_ssize        = x25sbuf_size;
  354.     x25iop->x_flags        = X25F_SBUF;
  355.     x25iop->x_send_type    = 0;
  356.     x25iop->x_count_ms    = x25SBUF_size / 256;
  357.     x25iop->x_count_ls    = x25SBUF_size % 256;
  358.  
  359.     _x25b_log_buff(fd, (char *) &_x25io, x25hdrsize + x25SBUF_size+1+TS29_BYTES, 0);
  360.     if (send(fd, (char *) x25iop,
  361.         x25hdrsize + x25SBUF_size + 1 + TS29_BYTES, 0) < 0)
  362.     {    close(fd);
  363.         x25b_perror(X25B_L_STAMP, "Initial send failed");
  364.         return -1;
  365.     }
  366.  
  367.     while(1)
  368.     {    int count;
  369.         count = _x25b_readpkt(fd, x25iop);
  370.         if (x25b_debug & 4) x25b_logit(X25B_L_STAMP | X25B_L_DEBUG,
  371.            "read_pkt(%d) gave %d %02x\n", fd, count, x25iop->x_flags);
  372.         if(x25iop->x_flags &    X25F_SBUF && count == x25SBUF_size)
  373.                                     break;
  374.         if(x25iop->x_flags &    X25F_GATE_MSG)
  375.         {    x25b_logit(X25B_L_STAMP,
  376.                 "\r\n ++no call yet-- %s\r\n", x25iop->x_buf);
  377.             if (x25iop->x_flags &    X25F_CLOSING)
  378.             {    close(fd);
  379.                 return -1;
  380.             }
  381.             continue;
  382.         }
  383.         x25b_perror(X25B_L_STAMP, "client readback of setup info");
  384.         close(fd);
  385.         return -1;
  386.     }
  387.     if (x25b_debug & 4) x25b_logit(X25B_L_STAMP | X25B_L_DEBUG,
  388.         "Return %d\n", fd);
  389.     return fd;
  390. }
  391.  
  392. _x25b_readpkt(fd, x25iop)
  393. struct x25io *x25iop;
  394. {    int count, acount;
  395.  
  396.     count = _x25b_recvfill(fd, (char *)x25iop, x25hdrsize, 0);
  397.     if (count != x25hdrsize)
  398.     {    if (count <= 0)        return count;
  399.         else
  400.         {    x25b_logit(X25B_L_STAMP,
  401.               "client recv: short delivery - wanted %d, got %d\n",
  402.                  x25hdrsize, count);
  403.             return TTY_NODATA;
  404.         }
  405.     }
  406.  
  407.     if (x25iop->x_version != X25IO_VER)
  408.     {    x25b_logit(X25B_L_STAMP,
  409.                 "client recv: Invalid version %d/%x (%d)\r\n",
  410.                 x25iop->x_version, 
  411.                 *((long *) x25iop),
  412.                 X25IO_VER);
  413.         return -1;
  414.     }
  415.  
  416.     count = (x25iop->x_count_ms << 8) + x25iop->x_count_ls +1+TS29_BYTES;
  417.     acount = _x25b_recvfill(fd, x25iop->x_rawbuf, count, 0);
  418.  
  419.     if (count != acount)
  420.     {    if (acount <= 0)    return count;
  421.         else
  422.         {    x25b_logit(X25B_L_STAMP,
  423.               "client recv B: short delivery - wanted %d, got %d\r\n",
  424.              count, acount);
  425.             return -1;
  426.         }
  427.     }
  428.         
  429.     return count-1-TS29_BYTES;
  430. }
  431.  
  432.  
  433. _x25b_recvfill(sock, buf, count, flags) /* recv as <count> bytes from sock */
  434.      char *buf;
  435. {
  436.     int acount, total;
  437.     char *bufp = buf;
  438.     total = 0;
  439.     if (x25b_debug & 2) x25b_logit(1, "rf%3d ", count);
  440.     while (total < count) {
  441.         acount = recv(sock, bufp, (count - total), flags);
  442.         if (x25b_debug & 2) if (acount != count)
  443.                 x25b_logit(1, "%3d ", acount);
  444.         _x25b_log_buff(~sock, bufp, acount, flags);
  445.         if (acount <= 0)
  446.         {    if (x25b_debug & 2) x25b_logit(1, "=%3d %3d [%08x %08x %08x]\n",
  447.                 count, acount,
  448.                 ((long *)buf)[0],
  449.                 ((long *)buf)[1],
  450.                 ((long *)buf)[2]);
  451.             return(acount);        /* report any anomoly */
  452.         }
  453.         bufp += acount;
  454.         total += acount;
  455.     }
  456.     if (x25b_debug & 2) if (acount != count) x25b_logit(1, "=%3d ",count);
  457.     if (x25b_debug & 2) x25b_logit(1, "[%08x %08x %08x]\n",
  458.         ((long *)buf)[0],
  459.         ((long *)buf)[1],
  460.         ((long *)buf)[2]);
  461.     return(count);
  462. }
  463.  
  464. #define FAC_x4_fflags    ntohs(facil->x4_fflags)
  465. _x25b_print_facil(facil)
  466. struct facilities *facil;
  467. {    x25b_logit(X25B_L_STAMP, " +++- ");
  468.     if (FAC_x4_fflags & (FACIL_F_REVERSE_CHARGE))
  469.         x25b_logit(0, "%srev chge, ",
  470.             (facil->x4_reverse_charge) ? "no " : "");
  471.     if (FAC_x4_fflags & (FACIL_F_RECVPKTSIZE | FACIL_F_SENDPKTSIZE))
  472.         x25b_logit(0, "pkt=%d/%d, ",
  473.         ntohs(facil->x4_recvpktsize), ntohs(facil->x4_sendpktsize));
  474.     if (FAC_x4_fflags & (FACIL_F_RECVWNDSIZE | FACIL_F_SENDWNDSIZE))
  475.         x25b_logit(0, "wnd=%d/%d, ",
  476.             facil->x4_recvwndsize,    facil->x4_sendwndsize);
  477.     if (FAC_x4_fflags & (FACIL_F_RECVTHRUPUT | FACIL_F_SENDTHRUPUT))
  478.         x25b_logit(0, "thru=%d/%d, ",
  479.             facil->x4_recvthruput, facil->x4_sendthruput);
  480.     if (FAC_x4_fflags & FACIL_F_CUG_INDEX)
  481.         x25b_logit(0, "cug=%x, ", facil->x4_cug_index);
  482.     if (FAC_x4_fflags & FACIL_F_FAST_SELECT) x25b_logit(0, "%s, ",
  483.         (facil->x4_fast_select == FACIL_NO)    ? "FS off" :
  484.         (facil->x4_fast_select == FACIL_FCS_CLR)? "FS CLR" :
  485.         (facil->x4_fast_select == FACIL_YES)    ? "FS ACC" : "??");
  486.     if (FAC_x4_fflags & FACIL_F_RPOA)
  487.         x25b_logit(0, "rpoa %04x, ", ntohs(facil->x4_rpoa));
  488.     x25b_logit(0, "\r\n");
  489. }
  490.  
  491. /* The first interface (of many) to open an outgoing Yellow-Book call */
  492.  
  493. x25b_open_ybts(dte, ybts, callingybts, server, port, facil, x25iop)
  494. char *dte;
  495. char *ybts;
  496. char *callingybts;
  497. char *server;
  498. char *port;
  499. struct facilities *facil;
  500. struct x25io *x25iop;
  501. {    return x25b_open_ybts4(dte, ybts, (char *) 0, (char *) 0, callingybts,
  502.         server, port, (char *) 0, facil, x25iop);
  503. }
  504.  
  505. x25b_open_ybts2(dte, ybts, callingdte, callingybts, server, port, facil, x25iop)
  506. char *dte;
  507. char *ybts;
  508. char *callingdte;
  509. char *callingybts;
  510. char *server;
  511. char *port;
  512. struct facilities *facil;
  513. struct x25io *x25iop;
  514. {    return x25b_open_ybts4(dte, ybts, callingdte, (char *) 0, callingybts,
  515.         server, port, (char *) 0, facil, x25iop);
  516. }
  517.  
  518. x25b_open_ybts3(dte, ybts, callingdte, callingybts, server, port, user, facil, x25iop)
  519. char *dte;
  520. char *ybts;
  521. char *callingdte;
  522. char *callingybts;
  523. char *server;
  524. char *port;
  525. char *user;
  526. struct facilities *facil;
  527. struct x25io *x25iop;
  528. {    return x25b_open_ybts4(dte, ybts, callingdte, (char *) 0, callingybts,
  529.         server, port, user, facil, x25iop);
  530. }
  531.  
  532. x25b_open_ybts4(dte, ybts, callingdte, callingname, callingybts,
  533.         server, port, user, facil, x25iop)
  534. char *dte;
  535. char *ybts;
  536. char *callingdte;
  537. char *callingname;
  538. char *callingybts;
  539. char *server;
  540. char *port;
  541. char *user;
  542. struct facilities *facil;
  543. struct x25io *x25iop;
  544. {    int fd;
  545.     char *slash = (dte) ? index(dte, '/') : (char *) 0;
  546.  
  547.     if (!x25iop)    x25iop = &_x25io;
  548.  
  549.     if ((fd = x25b_open_server(server, port)) < 0)
  550.     {    x25b_logit(X25B_L_STAMP, "open_server failed\n");
  551.         return fd;
  552.     }
  553.  
  554.     /* Reset the buffer */
  555.     _x25b_init_x25io(x25iop);
  556.  
  557.     if (slash)
  558.     {    *slash = '\0';
  559.         if (!ybts || !*ybts) ybts = slash+1;
  560.     }
  561.  
  562.     if (!ybts) ybts = DEF_YBTS;
  563.     if (!callingybts) callingybts = DEF_YBTS;
  564.  
  565.     /* Put in the YBTS string */
  566.     bcopy(TS_CUDF, x25iop->x_cudf, TS_CUDFLEN);
  567.     sprintf(x25iop->x_cudf + TS_CUDFLEN, "%c%s%c%s",
  568.         0x80 | strlen(ybts), ybts,
  569.         0x80 | strlen(callingybts), callingybts);
  570.     x25iop->x_cudflen = strlen(x25iop->x_cudf + TS_CUDFLEN) +
  571.             TS_CUDFLEN;
  572.  
  573.     /* Called address */
  574.     if (callingname || callingdte || !dte)
  575.         sprintf(x25iop->x_destination, "%c%s%c%s%c%s",
  576.         0x80 + ((dte) ? strlen(dte) : 0), dte ? dte : "",
  577.         0x80 + ((callingdte) ? strlen(callingdte) : 0),
  578.             callingdte ? callingdte : "",
  579.         0x80 + ((callingname) ? strlen(callingname) : 0),
  580.             callingname ? callingname : "");
  581.     else
  582.         sprintf(x25iop->x_destination, dte);
  583.     strcpy(x25iop->x_username, (user && *user) ? user : "unix-nif");
  584.  
  585.     /* I assume we want fast call select ... */
  586.     if (facil) bcopy(facil, &(x25iop->x_facil), sizeof (x25iop->x_facil));
  587.     else
  588.     {    bzero(&(x25iop->x_facil), sizeof (x25iop->x_facil));
  589.         x25iop->x_fast_select    = FACIL_FCS;
  590.         x25iop->x_flags        |= FACIL_F_FAST_SELECT;
  591.     }
  592.  
  593.     if (slash) *slash = '/';
  594.  
  595.     return _x25b_make_connection(fd, x25iop);
  596. }
  597.  
  598. x25b_open_x29(dte, xcudf, callingdte, server, port, user, facil, x25iop)
  599. char *dte;
  600. char *xcudf;
  601. char *callingdte;
  602. char *server;
  603. char *port;
  604. char *user;
  605. struct facilities *facil;
  606. struct x25io *x25iop;
  607. {    return x25b_open_x29_2(dte, xcudf, callingdte, (char *) 0,
  608.         server, port, user, facil, x25iop);
  609. }
  610.  
  611. x25b_open_x29_2(dte, xcudf, callingdte, callingname,
  612.     server, port, user, facil, x25iop)
  613. char *dte;
  614. char *xcudf;
  615. char *callingdte;
  616. char *callingname;
  617. char *server;
  618. char *port;
  619. char *user;
  620. struct facilities *facil;
  621. struct x25io *x25iop;
  622. {    int fd;
  623.     int base = 0;
  624.     char *colon = (char *) 0;
  625.  
  626.     if (!x25iop)    x25iop = &_x25io;
  627.  
  628.     if ((fd = x25b_open_server(server, port)) < 0)
  629.     {    x25b_logit(X25B_L_STAMP, "open_server failed\n");
  630.         return fd;
  631.     }
  632.  
  633.     /* Reset the buffer */
  634.     _x25b_init_x25io(x25iop);
  635.  
  636.     if (dte && (colon = index(dte, ':')))
  637.     {    *colon = '\0';
  638.         if (!xcudf || !*xcudf || !strcmp(xcudf, ":"))
  639.             xcudf = colon+1;
  640.     }
  641.  
  642.     if (xcudf && *xcudf != ':')    /* Is this really hex or text ? */
  643.     {    bcopy(PRE_CUDF, x25iop->x_cudf, PRE_CUDFLEN);
  644.         base += PRE_CUDFLEN;
  645.         strcpy(x25iop->x_cudf + base, xcudf);
  646.         base += strlen(xcudf);
  647.     }
  648.     else if (xcudf)    /* need to prefix CUDF with PID ? */
  649.     {    if (*++xcudf == ':') xcudf++;
  650.         else if (strncmp(xcudf, "01", 2))
  651.         {    bcopy(PRE_CUDF, x25iop->x_cudf, PRE_CUDFLEN);
  652.             base += PRE_CUDFLEN;
  653.         }
  654.         _x25b_chartohex(x25iop->x_cudf + base, xcudf);
  655.         base += strlen(xcudf)/2;
  656.     }
  657.     x25iop->x_cudflen = base;
  658.  
  659.     /* Called address */
  660.     if (callingname || callingdte || !dte)
  661.         sprintf(x25iop->x_destination, "%c%s%c%s%c%s",
  662.         0x80 + ((dte) ? strlen(dte) : 0), dte ? dte : "",
  663.         0x80 + ((callingdte) ? strlen(callingdte) : 0),
  664.             callingdte ? callingdte : "",
  665.         0x80 + ((callingname) ? strlen(callingname) : 0),
  666.             callingname ? callingname : "");
  667.     else
  668.         sprintf(x25iop->x_destination, dte);
  669.     strncpy(x25iop->x_username, (user) ? user : "unix-nifp",
  670.         sizeof x25iop->x_username);
  671.     x25iop->x_username[sizeof x25iop->x_username -1] = '\0';
  672.  
  673.     /* I assume we want fast call select ... */
  674.     if (facil) bcopy(facil, &(x25iop->x_facil), sizeof (x25iop->x_facil));
  675.     else
  676.     {    bzero(&(x25iop->x_facil), sizeof (x25iop->x_facil));
  677.         x25iop->x_fast_select    = FACIL_FCS;
  678.         x25iop->x_flags        |= FACIL_F_FAST_SELECT;
  679.     }
  680.  
  681.     if (colon) *colon = ':';
  682.  
  683.     return _x25b_make_connection(fd, x25iop);
  684. }
  685.  
  686. x25b_receive_call(fd, x25iop)
  687. struct x25io *x25iop;
  688. {    int n;
  689.     _x25b_init_x25io(&_x25io);
  690.     _x25b_init_x25io(x25iop);
  691.  
  692.     if ((n = _x25b_readpkt(fd, x25iop)) <= 0) return n;
  693.  
  694.     if (x25iop->x_flags == X25F_SBUF ||
  695.         x25iop->x_flags == 0xd2 || x25iop->x_flags == 0x61)
  696.     {    if (x25iop->x_flags == 0x61)
  697.         {    x25iop->x_flags = 0xd2;
  698.         }
  699.         x25iop->x_version    = X25IO_VER;
  700.         _x25b_log_buff(fd, (char *) x25iop, n+6, 0);
  701.         send(fd, (char *) x25iop, n+6, 0);
  702.         n -= (((char *) &x25iop->x_sbuf) - (char *) x25iop);
  703. #define    STRUCT_FUDGE    (-2)
  704.         if (x25iop->x_flags == 0xd2 || x25iop->x_flags == 0x61)
  705.         {    x25b_logit(X25B_L_STAMP,
  706.                 "Sigh -- spad set flags wrong\n");
  707.             x25iop->x_flags = X25F_SBUF;
  708.             x25iop->x_send_type = 0;
  709.         }
  710.         x25b_logit(0, "[Offset: %d, %d]",
  711.             ((char *)  x25iop->x_buf) - (char *) x25iop,
  712.             ((char *) &x25iop->x_sbuf) - (char *) x25iop);
  713.  
  714.         _x25b_print_facil(&x25iop->x_facil);
  715.         return n;
  716.     }
  717.     return -1;
  718. }
  719.  
  720. _x25b_log_buff(fd, buff, len, type)
  721. char *buff;
  722. {    extern errno;
  723.     static last_was_hdr=0;
  724.  
  725.     if (x25b_debug & 0x10)
  726.     {    int i=0;
  727.         int b1=x25hdrsize;
  728.         int b2=b1+2;
  729.  
  730.         if (last_was_hdr)
  731.         {    b1 = 0;
  732.             b2 = b1 + 2;
  733.         }
  734.  
  735.         x25b_logit(X25B_L_STAMP | X25B_L_DEBUG,
  736.             "Fd %d %s, Type %02x, Data %d:",
  737.             (fd < 0) ? ~fd : fd,
  738.             (fd < 0) ? "recv" : "send",
  739.             type, len);
  740.         for (; i<b1 && i<len; i++)
  741.         x25b_logit(X25B_L_DEBUG,  "%s%02x",
  742.             (i % 26 == 13) ? "\r\n++ ":" ", 
  743.             ((unsigned char *)buff)[i]);
  744.         if (b1 && i<len) x25b_logit(X25B_L_DEBUG,  " -");
  745.         for (; i<b2 && i<len; i++)
  746.         x25b_logit(X25B_L_DEBUG,  "%s%02x",
  747.             (i % 26 == 13) ? "\r\n++ " : " ", 
  748.             ((unsigned char *)buff)[i]);
  749.         if (b2 && i<len) x25b_logit(X25B_L_DEBUG,  ":");
  750.         for (; i<len; i++)
  751.         x25b_logit(X25B_L_DEBUG,  "%s%02x",
  752.             (i % 26 == 12) ? "\r\n++ ":" ", 
  753.             ((unsigned char *)buff)[i]);
  754.         if (len == b1)    last_was_hdr=1;
  755.         else        last_was_hdr=0;
  756.         x25b_logit(X25B_L_DEBUG,  " (%d)\r\n", errno);
  757.     }
  758. }
  759.  
  760. _x25b_chartohex(to, from)
  761. char *from;
  762. char *to;
  763. {    int offset = 0;
  764.  
  765.     for (offset=0; *from; from++, offset++)
  766.     {    int    val;
  767.         switch(*from)
  768.         {    case '0': case '1': case '2': case '3': case '4':
  769.             case '5': case '6': case '7': case '8': case '9':
  770.             val = (*from) - '0';                break;
  771.             case 'a': case 'b': case 'c':
  772.             case 'd': case 'e': case 'f':
  773.             val = (*from) - 'a' + 10;            break;
  774.             case 'A': case 'B': case 'C':
  775.             case 'D': case 'E': case 'F':
  776.             val = (*from) - 'A' + 10;            break;
  777.             default:
  778.             return;
  779.         }
  780.  
  781.         if (offset & 1)
  782.             to[offset/2] |= val;
  783.         else    to[offset/2]  = val << 4;
  784.     }
  785. }
  786.