root/src/dps8/libtelnet.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: CC-PDDC
   4  * SPDX-FileCopyrightText: Public domain
   5  * scspell-id: 8a194784-f62f-11ec-85b5-80ee73e9b8e7
   6  *
   7  * ---------------------------------------------------------------------------
   8  *
   9  * libTELNET - TELNET protocol handling library
  10  *
  11  * SUMMARY:
  12  *
  13  * libTELNET is a library for handling the TELNET protocol.  It includes
  14  * routines for parsing incoming data from a remote peer as well as
  15  * formatting data to send to the remote peer.
  16  *
  17  * libTELNET uses a callback-oriented API, allowing application-specific
  18  * handling of various events.  The callback system is also used for
  19  * buffering outgoing protocol data, allowing the application to maintain
  20  * control over the actual socket connection.
  21  *
  22  * Features supported include the full TELNET protocol, Q-method option
  23  * negotiation, and NEW-ENVIRON.
  24  *
  25  * ---------------------------------------------------------------------------
  26  *
  27  * CONFORMS TO:
  28  *
  29  * RFC-854   -  https://www.faqs.org/rfcs/rfc854.html
  30  * RFC-855   -  https://www.faqs.org/rfcs/rfc855.html
  31  * RFC-1091  -  https://www.faqs.org/rfcs/rfc1091.html
  32  * RFC-1143  -  https://www.faqs.org/rfcs/rfc1143.html
  33  * RFC-1408  -  https://www.faqs.org/rfcs/rfc1408.html
  34  * RFC-1572  -  https://www.faqs.org/rfcs/rfc1572.html
  35  *
  36  * ---------------------------------------------------------------------------
  37  *
  38  * LICENSE:
  39  *
  40  * The author or authors of this code dedicate any and all copyright
  41  * interest in this code to the public domain. We make this dedication
  42  * for the benefit of the public at large and to the detriment of our
  43  * heirs and successors. We intend this dedication to be an overt act
  44  * of relinquishment in perpetuity of all present and future rights to
  45  * this code under copyright law.
  46  *
  47  * ---------------------------------------------------------------------------
  48  *
  49  * Sean Middleditch <sean@sourcemud.org>
  50  *
  51  * ---------------------------------------------------------------------------
  52  */
  53 
  54 /*
  55  * The person or persons who have associated work with this document
  56  * (the "Dedicator" or "Certifier") hereby either (a) certifies that,
  57  * to the best of his knowledge, the work of authorship identified
  58  * is in the public domain of the country from which the work is
  59  * published, or (b) hereby dedicates whatever copyright the dedicators
  60  * holds in the work of authorship identified below (the "Work") to the
  61  * public domain. A certifier, moreover, dedicates any copyright
  62  * interest he may have in the associated work, and for these purposes,
  63  * is described as a "dedicator" below.
  64  *
  65  * A certifier has taken reasonable steps to verify the copyright
  66  * status of this work. Certifier recognizes that his good faith
  67  * efforts may not shield him from liability if in fact the work
  68  * certified is not in the public domain.
  69  *
  70  * Dedicator makes this dedication for the benefit of the public at
  71  * large and to the detriment of the Dedicator's heirs and successors.
  72  * Dedicator intends this dedication to be an overt act of
  73  * relinquishment in perpetuity of all present and future rights under
  74  * copyright law, whether vested or contingent, in the Work. Dedicator
  75  * understands that such relinquishment of all rights includes the
  76  * relinquishment of all rights to enforce (by lawsuit or otherwise)
  77  * those copyrights in the Work.
  78  *
  79  * Dedicator recognizes that, once placed in the public domain, the
  80  * Work may be freely reproduced, distributed, transmitted, used,
  81  * modified, built upon, or otherwise exploited by anyone for any
  82  * purpose, commercial or non-commercial, and in any way, including by
  83  * methods that have not yet been invented or conceived.
  84  */
  85 
  86 #if !defined(LIBTELNET_INCLUDE)
  87 # define LIBTELNET_INCLUDE 1
  88 
  89 /* local definitions */
  90 # include "dps8.h"
  91 
  92 /* standard C headers necessary for the libTELNET API */
  93 # include <stdarg.h>
  94 # include <stddef.h>
  95 
  96 /* printf type checking feature in GCC and some other compilers */
  97 # if defined(__GNUC__) && !defined(USING_DPSPRINTF)
  98 #  define TELNET_GNU_PRINTF(f,a) __attribute__((format(printf, f, a))) /* internal helper */
  99 #  define TELNET_GNU_SENTINEL __attribute__((sentinel)) /* internal helper */
 100 # else
 101 #  define TELNET_GNU_PRINTF(f,a) /* internal helper */
 102 #  define TELNET_GNU_SENTINEL /* internal helper */
 103 # endif
 104 
 105 /* Disable environ macro for Visual C++ 2015. */
 106 # undef environ
 107 
 108 /* Telnet state tracker object type. */
 109 typedef struct telnet_t telnet_t;
 110 
 111 /* Telnet event object type. */
 112 typedef union telnet_event_t telnet_event_t;
 113 
 114 /* Telnet option table element type. */
 115 typedef struct telnet_telopt_t telnet_telopt_t;
 116 
 117 /* Telnet commands and special values. */
 118 # define TELNET_IAC   255
 119 # define TELNET_DONT  254
 120 # define TELNET_DO    253
 121 # define TELNET_WONT  252
 122 # define TELNET_WILL  251
 123 # define TELNET_SB    250
 124 # define TELNET_GA    249
 125 # define TELNET_EL    248
 126 # define TELNET_EC    247
 127 # define TELNET_AYT   246
 128 # define TELNET_AO    245
 129 # define TELNET_IP    244
 130 # define TELNET_BREAK 243
 131 # define TELNET_DM    242
 132 # define TELNET_NOP   241
 133 # define TELNET_SE    240
 134 # define TELNET_EOR   239
 135 # define TELNET_ABORT 238
 136 # define TELNET_SUSP  237
 137 # define TELNET_EOF   236
 138 
 139 /* Telnet option values. */
 140 # define TELNET_TELOPT_BINARY          0
 141 # define TELNET_TELOPT_ECHO            1
 142 # define TELNET_TELOPT_RCP             2
 143 # define TELNET_TELOPT_SGA             3
 144 # define TELNET_TELOPT_NAMS            4
 145 # define TELNET_TELOPT_STATUS          5
 146 # define TELNET_TELOPT_TM              6
 147 # define TELNET_TELOPT_RCTE            7
 148 # define TELNET_TELOPT_NAOL            8
 149 # define TELNET_TELOPT_NAOP            9
 150 # define TELNET_TELOPT_NAOCRD         10
 151 # define TELNET_TELOPT_NAOHTS         11
 152 # define TELNET_TELOPT_NAOHTD         12
 153 # define TELNET_TELOPT_NAOFFD         13
 154 # define TELNET_TELOPT_NAOVTS         14
 155 # define TELNET_TELOPT_NAOVTD         15
 156 # define TELNET_TELOPT_NAOLFD         16
 157 # define TELNET_TELOPT_XASCII         17
 158 # define TELNET_TELOPT_LOGOUT         18
 159 # define TELNET_TELOPT_BM             19
 160 # define TELNET_TELOPT_DET            20
 161 # define TELNET_TELOPT_SUPDUP         21
 162 # define TELNET_TELOPT_SUPDUPOUTPUT   22
 163 # define TELNET_TELOPT_SNDLOC         23
 164 # define TELNET_TELOPT_TTYPE          24
 165 # define TELNET_TELOPT_EOR            25
 166 # define TELNET_TELOPT_TUID           26
 167 # define TELNET_TELOPT_OUTMRK         27
 168 # define TELNET_TELOPT_TTYLOC         28
 169 # define TELNET_TELOPT_3270REGIME     29
 170 # define TELNET_TELOPT_X3PAD          30
 171 # define TELNET_TELOPT_NAWS           31
 172 # define TELNET_TELOPT_TSPEED         32
 173 # define TELNET_TELOPT_LFLOW          33
 174 # define TELNET_TELOPT_LINEMODE       34
 175 # define TELNET_TELOPT_XDISPLOC       35
 176 # define TELNET_TELOPT_ENVIRON        36
 177 # define TELNET_TELOPT_AUTHENTICATION 37
 178 # define TELNET_TELOPT_ENCRYPT        38
 179 # define TELNET_TELOPT_NEW_ENVIRON    39
 180 # define TELNET_TELOPT_EXOPL         255
 181 
 182 /* Protocol codes for TERMINAL-TYPE commands. */
 183 # define TELNET_TTYPE_IS   0
 184 # define TELNET_TTYPE_SEND 1
 185 
 186 /* Protocol codes for NEW-ENVIRON/ENVIRON commands. */
 187 # define TELNET_ENVIRON_IS      0
 188 # define TELNET_ENVIRON_SEND    1
 189 # define TELNET_ENVIRON_INFO    2
 190 # define TELNET_ENVIRON_VAR     0
 191 # define TELNET_ENVIRON_VALUE   1
 192 # define TELNET_ENVIRON_ESC     2
 193 # define TELNET_ENVIRON_USERVAR 3
 194 
 195 /* Telnet state tracker flags. */
 196 
 197 /* Control behavior of telnet state tracker. */
 198 # define TELNET_FLAG_PROXY   (1<<0)
 199 # define TELNET_FLAG_NVT_EOL (1<<1)
 200 
 201 /* Internal-only bits in option flags */
 202 # define TELNET_FLAG_TRANSMIT_BINARY (1<<5)
 203 # define TELNET_FLAG_RECEIVE_BINARY  (1<<6)
 204 # define TELNET_PFLAG_DEFLATE        (1<<7)
 205 
 206 /*
 207  * error codes
 208  */
 209 enum telnet_error_t {
 210         TELNET_EOK = 0,   /* no error                          */
 211         TELNET_EBADVAL,   /* invalid parameter, or API misuse  */
 212         TELNET_ENOMEM,    /* memory allocation failure         */
 213         TELNET_EOVERFLOW, /* data exceeds buffer size          */
 214         TELNET_EPROTOCOL, /* invalid sequence of special bytes */
 215 };
 216 typedef enum telnet_error_t telnet_error_t; /* Error code type. */
 217 
 218 /*
 219  * event codes
 220  */
 221 enum telnet_event_type_t {
 222         TELNET_EV_DATA = 0,        /* raw text data has been received    */
 223         TELNET_EV_SEND,            /* data needs to be sent to the peer  */
 224         TELNET_EV_IAC,             /* generic IAC code received          */
 225         TELNET_EV_WILL,            /* WILL option negotiation received   */
 226         TELNET_EV_WONT,            /* WONT option negotiation received   */
 227         TELNET_EV_DO,              /* DO option negotiation received     */
 228         TELNET_EV_DONT,            /* DONT option negotiation received   */
 229         TELNET_EV_SUBNEGOTIATION,  /* sub-negotiation data received      */
 230         TELNET_EV_TTYPE,           /* TTYPE command has been received    */
 231         TELNET_EV_ENVIRON,         /* ENVIRON command has been received  */
 232         TELNET_EV_WARNING,         /* recoverable error has occurred     */
 233         TELNET_EV_ERROR            /* non-recoverable error has occurred */
 234 };
 235 typedef enum telnet_event_type_t telnet_event_type_t; /* Telnet event type */
 236 
 237 /*
 238  * environ command information
 239  */
 240 struct telnet_environ_t {
 241         unsigned char type; /* either TELNET_ENVIRON_VAR or TELNET_ENVIRON_USERVAR   */
 242         char *var;          /* name of the variable being set                        */
 243         char *value;        /* value of variable being set; empty string if no value */
 244 };
 245 
 246 /*
 247  * event information
 248  */
 249 union telnet_event_t {
 250         /*
 251          * Event type
 252          *
 253          * The type field determines which event structure fields have been filled in.
 254          */
 255         enum telnet_event_type_t type;
 256 
 257         /*
 258          * Data event: for DATA and SEND events
 259          */
 260         struct data_t {
 261                 enum telnet_event_type_t _type; /* alias for type            */
 262                 const char *buffer;             /* byte buffer               */
 263                 size_t size;                    /* number of bytes in buffer */
 264         } data;
 265 
 266         /*
 267          * WARNING and ERROR events
 268          */
 269         struct error_t {
 270                 enum telnet_event_type_t _type; /* alias for type                */
 271                 const char *file;               /* file the error occurred in     */
 272                 const char *func;               /* function the error occurred in */
 273                 const char *msg;                /* error message string          */
 274                 int line;                       /* line of file error occurred on */
 275                 telnet_error_t errcode;         /* error code                    */
 276         } error;
 277 
 278         /*
 279          * command event: for IAC
 280          */
 281         struct iac_t {
 282                 enum telnet_event_type_t _type; /* alias for type          */
 283                 unsigned char cmd;              /* telnet command received */
 284         } iac;
 285 
 286         /*
 287          * negotiation event: WILL, WONT, DO, DONT
 288          */
 289         struct negotiate_t {
 290                 enum telnet_event_type_t _type; /* alias for type          */
 291                 unsigned char telopt;           /* option being negotiated */
 292         } neg;
 293 
 294         /*
 295          * subnegotiation event
 296          */
 297         struct subnegotiate_t {
 298                 enum telnet_event_type_t _type; /* alias for type              */
 299                 const char *buffer;             /* data of sub-negotiation     */
 300                 size_t size;                    /* number of bytes in buffer   */
 301                 unsigned char telopt;           /* option code for negotiation */
 302         } sub;
 303 
 304         /*
 305          * TTYPE event
 306          */
 307         struct ttype_t {
 308                 enum telnet_event_type_t _type; /* alias for type                       */
 309                 unsigned char cmd;              /* TELNET_TTYPE_IS or TELNET_TTYPE_SEND */
 310                 const char* name;               /* terminal type name (IS only)         */
 311         } ttype;
 312 
 313         /*
 314          * ENVIRON/NEW-ENVIRON event
 315          */
 316         struct environ_t {
 317                 enum telnet_event_type_t _type;        /* alias for type               */
 318                 const struct telnet_environ_t *values; /* array of variable values     */
 319                 size_t size;                           /* number of elements in values */
 320                 unsigned char cmd;                     /* SEND, IS, or INFO            */
 321         } environ;
 322 };
 323 
 324 /*
 325  * event handler
 326  *
 327  * This is the type of function that must be passed to
 328  * telnet_init() when creating a new telnet object.  The
 329  * function will be invoked once for every event generated
 330  * by the libTELNET protocol parser.
 331  *
 332  * param telnet    The telnet object that generated the event
 333  * param event     Event structure with details about the event
 334  * param user_data User-supplied pointer
 335  */
 336 typedef void (*telnet_event_handler_t)(telnet_t *telnet,
 337                 telnet_event_t *event, void *user_data);
 338 
 339 /*
 340  * telopt support table element; use telopt of -1 for end marker
 341  */
 342 struct telnet_telopt_t {
 343         short telopt;      /* one of the TELOPT codes or -1 */
 344         unsigned char us;  /* TELNET_WILL or TELNET_WONT    */
 345         unsigned char him; /* TELNET_DO or TELNET_DONT      */
 346 };
 347 
 348 /*
 349  * state tracker -- private data structure
 350  */
 351 struct telnet_t;
 352 
 353 /*
 354  * Initialize a telnet state tracker.
 355  *
 356  * This function initializes a new state tracker, which is used for all
 357  * other libTELNET functions.  Each connection must have its own
 358  * telnet state tracker object.
 359  *
 360  * param telopts   Table of TELNET options the application supports.
 361  * param eh        Event handler function called for every event.
 362  * param flags     0 or TELNET_FLAG_PROXY.
 363  * param user_data Optional data pointer that will be passed to eh.
 364  * return Telnet state tracker object.
 365  */
 366 extern telnet_t* telnet_init(const telnet_telopt_t *telopts,
 367                 telnet_event_handler_t eh, unsigned char flags, void *user_data);
 368 
 369 /*
 370  * Free up any memory allocated by a state tracker.
 371  *
 372  * This function must be called when a telnet state tracker is no
 373  * longer needed (such as after the connection has been closed) to
 374  * release any memory resources used by the state tracker.
 375  *
 376  * param telnet Telnet state tracker object.
 377  */
 378 extern void telnet_free(telnet_t *telnet);
 379 
 380 /*
 381  * Push a byte buffer into the state tracker.
 382  *
 383  * Passes one or more bytes to the telnet state tracker for
 384  * protocol parsing.  The byte buffer is most often going to be
 385  * the buffer that recv() was called for while handling the
 386  * connection.
 387  *
 388  * param telnet Telnet state tracker object.
 389  * param buffer Pointer to byte buffer.
 390  * param size   Number of bytes pointed to by buffer.
 391  */
 392 extern void telnet_recv(telnet_t *telnet, const char *buffer,
 393                 size_t size);
 394 
 395 /*
 396  * Send a telnet command.
 397  *
 398  * param telnet Telnet state tracker object.
 399  * param cmd    Command to send.
 400  */
 401 extern void telnet_iac(telnet_t *telnet, unsigned char cmd);
 402 
 403 /*
 404  * Send negotiation command.
 405  *
 406  * Internally, libTELNET uses RFC1143 option negotiation rules.
 407  * The negotiation commands sent with this function may be ignored
 408  * if they are determined to be redundant.
 409  *
 410  * param telnet Telnet state tracker object.
 411  * param cmd    TELNET_WILL, TELNET_WONT, TELNET_DO, or TELNET_DONT.
 412  * param opt    One of the TELNET_TELOPT_* values.
 413  */
 414 extern void telnet_negotiate(telnet_t *telnet, unsigned char cmd,
 415                 unsigned char opt);
 416 
 417 /*
 418  * Send non-command data (escapes IAC bytes).
 419  *
 420  * param telnet Telnet state tracker object.
 421  * param buffer Buffer of bytes to send.
 422  * param size   Number of bytes to send.
 423  */
 424 extern void telnet_send(telnet_t *telnet,
 425                 const char *buffer, size_t size);
 426 
 427 /*
 428  * Send non-command text (escapes IAC bytes and translates
 429  * \\r -> CR-NUL and \\n -> CR-LF unless in BINARY mode.
 430  *
 431  * param telnet Telnet state tracker object.
 432  * param buffer Buffer of bytes to send.
 433  * param size   Number of bytes to send.
 434  */
 435 extern void telnet_send_text(telnet_t *telnet,
 436                 const char *buffer, size_t size);
 437 
 438 /*
 439  * Begin a sub-negotiation command.
 440  *
 441  * Sends IAC SB followed by the telopt code.  All following data sent
 442  * will be part of the sub-negotiation, until telnet_finish_sb() is
 443  * called.
 444  *
 445  * param telnet Telnet state tracker object.
 446  * param telopt One of the TELNET_TELOPT_* values.
 447  */
 448 extern void telnet_begin_sb(telnet_t *telnet,
 449                 unsigned char telopt);
 450 
 451 /*
 452  * Finish a sub-negotiation command.
 453  *
 454  * This must be called after a call to telnet_begin_sb() to finish a
 455  * sub-negotiation command.
 456  *
 457  * param telnet Telnet state tracker object.
 458  */
 459 # define telnet_finish_sb(telnet) telnet_iac((telnet), TELNET_SE)
 460 
 461 /*
 462  * Send formatted data.
 463  *
 464  * This function is a wrapper around telnet_send().  It allows using
 465  * printf-style formatting.
 466  *
 467  * Additionally, this function will translate \\r to the CR NUL construct and
 468  * \\n with CR LF, as well as automatically escaping IAC bytes like
 469  * telnet_send().
 470  *
 471  * param telnet Telnet state tracker object.
 472  * param fmt    Format string.
 473  * return Number of bytes sent.
 474  */
 475 extern int telnet_printf(telnet_t *telnet, const char *fmt, ...)
 476                 TELNET_GNU_PRINTF(2, 3);
 477 
 478 /*
 479  * Send formatted data.
 480  *
 481  * See telnet_printf().
 482  */
 483 extern int telnet_vprintf(telnet_t *telnet, const char *fmt, va_list va);
 484 
 485 /*
 486  * Send formatted data (no newline escaping).
 487  *
 488  * This behaves identically to telnet_printf(), except that the \\r and \\n
 489  * characters are not translated.  The IAC byte is still escaped as normal
 490  * with telnet_send().
 491  *
 492  * param telnet Telnet state tracker object.
 493  * param fmt    Format string.
 494  * return Number of bytes sent.
 495  */
 496 extern int telnet_raw_printf(telnet_t *telnet, const char *fmt, ...)
 497                 TELNET_GNU_PRINTF(2, 3);
 498 
 499 /*
 500  * Send formatted data (no newline escaping).
 501  *
 502  * See telnet_raw_printf().
 503  */
 504 extern int telnet_raw_vprintf(telnet_t *telnet, const char *fmt, va_list va);
 505 
 506 #endif /* !defined(LIBTELNET_INCLUDE) */

/* [previous][next][first][last][top][bottom][index][help] */