libtelnet.h (21426B)
1/*! 2 * \brief libtelnet - TELNET protocol handling library 3 * 4 * SUMMARY: 5 * 6 * libtelnet is a library for handling the TELNET protocol. It includes 7 * routines for parsing incoming data from a remote peer as well as formatting 8 * data to send to the remote peer. 9 * 10 * libtelnet uses a callback-oriented API, allowing application-specific 11 * handling of various events. The callback system is also used for buffering 12 * outgoing protocol data, allowing the application to maintain control over 13 * the actual socket connection. 14 * 15 * Features supported include the full TELNET protocol, Q-method option 16 * negotiation, ZMP, MCCP2, MSSP, and NEW-ENVIRON. 17 * 18 * CONFORMS TO: 19 * 20 * RFC854 - http://www.faqs.org/rfcs/rfc854.html 21 * RFC855 - http://www.faqs.org/rfcs/rfc855.html 22 * RFC1091 - http://www.faqs.org/rfcs/rfc1091.html 23 * RFC1143 - http://www.faqs.org/rfcs/rfc1143.html 24 * RFC1408 - http://www.faqs.org/rfcs/rfc1408.html 25 * RFC1572 - http://www.faqs.org/rfcs/rfc1572.html 26 * 27 * LICENSE: 28 * 29 * The author or authors of this code dedicate any and all copyright interest 30 * in this code to the public domain. We make this dedication for the benefit 31 * of the public at large and to the detriment of our heirs and successors. We 32 * intend this dedication to be an overt act of relinquishment in perpetuity of 33 * all present and future rights to this code under copyright law. 34 * 35 * \file libtelnet.h 36 * 37 * \version 0.23 38 * 39 * \author Sean Middleditch <sean@sourcemud.org> 40 */ 41 42#if !defined(LIBTELNET_INCLUDE) 43#define LIBTELNET_INCLUDE 1 44 45/* standard C headers necessary for the libtelnet API */ 46#include <stdarg.h> 47#include <stddef.h> 48 49/* C++ support */ 50#if defined(__cplusplus) 51extern "C" { 52#endif 53 54/* printf type checking feature in GCC and some other compilers */ 55#if __GNUC__ 56# define TELNET_GNU_PRINTF(f,a) __attribute__((format(printf, f, a))) /*!< internal helper */ 57# define TELNET_GNU_SENTINEL __attribute__((sentinel)) /*!< internal helper */ 58#else 59# define TELNET_GNU_PRINTF(f,a) /*!< internal helper */ 60# define TELNET_GNU_SENTINEL /*!< internal helper */ 61#endif 62 63/* Disable environ macro for Visual C++ 2015. */ 64#undef environ 65 66/*! Telnet state tracker object type. */ 67typedef struct telnet_t telnet_t; 68 69/*! Telnet event object type. */ 70typedef union telnet_event_t telnet_event_t; 71 72/*! Telnet option table element type. */ 73typedef struct telnet_telopt_t telnet_telopt_t; 74 75/*! \name Telnet commands */ 76/*@{*/ 77/*! Telnet commands and special values. */ 78#define TELNET_IAC 255 79#define TELNET_DONT 254 80#define TELNET_DO 253 81#define TELNET_WONT 252 82#define TELNET_WILL 251 83#define TELNET_SB 250 84#define TELNET_GA 249 85#define TELNET_EL 248 86#define TELNET_EC 247 87#define TELNET_AYT 246 88#define TELNET_AO 245 89#define TELNET_IP 244 90#define TELNET_BREAK 243 91#define TELNET_DM 242 92#define TELNET_NOP 241 93#define TELNET_SE 240 94#define TELNET_EOR 239 95#define TELNET_ABORT 238 96#define TELNET_SUSP 237 97#define TELNET_EOF 236 98/*@}*/ 99 100/*! \name Telnet option values. */ 101/*@{*/ 102/*! Telnet options. */ 103#define TELNET_TELOPT_BINARY 0 104#define TELNET_TELOPT_ECHO 1 105#define TELNET_TELOPT_RCP 2 106#define TELNET_TELOPT_SGA 3 107#define TELNET_TELOPT_NAMS 4 108#define TELNET_TELOPT_STATUS 5 109#define TELNET_TELOPT_TM 6 110#define TELNET_TELOPT_RCTE 7 111#define TELNET_TELOPT_NAOL 8 112#define TELNET_TELOPT_NAOP 9 113#define TELNET_TELOPT_NAOCRD 10 114#define TELNET_TELOPT_NAOHTS 11 115#define TELNET_TELOPT_NAOHTD 12 116#define TELNET_TELOPT_NAOFFD 13 117#define TELNET_TELOPT_NAOVTS 14 118#define TELNET_TELOPT_NAOVTD 15 119#define TELNET_TELOPT_NAOLFD 16 120#define TELNET_TELOPT_XASCII 17 121#define TELNET_TELOPT_LOGOUT 18 122#define TELNET_TELOPT_BM 19 123#define TELNET_TELOPT_DET 20 124#define TELNET_TELOPT_SUPDUP 21 125#define TELNET_TELOPT_SUPDUPOUTPUT 22 126#define TELNET_TELOPT_SNDLOC 23 127#define TELNET_TELOPT_TTYPE 24 128#define TELNET_TELOPT_EOR 25 129#define TELNET_TELOPT_TUID 26 130#define TELNET_TELOPT_OUTMRK 27 131#define TELNET_TELOPT_TTYLOC 28 132#define TELNET_TELOPT_3270REGIME 29 133#define TELNET_TELOPT_X3PAD 30 134#define TELNET_TELOPT_NAWS 31 135#define TELNET_TELOPT_TSPEED 32 136#define TELNET_TELOPT_LFLOW 33 137#define TELNET_TELOPT_LINEMODE 34 138#define TELNET_TELOPT_XDISPLOC 35 139#define TELNET_TELOPT_ENVIRON 36 140#define TELNET_TELOPT_AUTHENTICATION 37 141#define TELNET_TELOPT_ENCRYPT 38 142#define TELNET_TELOPT_NEW_ENVIRON 39 143#define TELNET_TELOPT_MSSP 70 144#define TELNET_TELOPT_COMPRESS 85 145#define TELNET_TELOPT_COMPRESS2 86 146#define TELNET_TELOPT_ZMP 93 147#define TELNET_TELOPT_EXOPL 255 148 149#define TELNET_TELOPT_MCCP2 86 150/*@}*/ 151 152/*! \name Protocol codes for TERMINAL-TYPE commands. */ 153/*@{*/ 154/*! TERMINAL-TYPE codes. */ 155#define TELNET_TTYPE_IS 0 156#define TELNET_TTYPE_SEND 1 157/*@}*/ 158 159/*! \name Protocol codes for NEW-ENVIRON/ENVIRON commands. */ 160/*@{*/ 161/*! NEW-ENVIRON/ENVIRON codes. */ 162#define TELNET_ENVIRON_IS 0 163#define TELNET_ENVIRON_SEND 1 164#define TELNET_ENVIRON_INFO 2 165#define TELNET_ENVIRON_VAR 0 166#define TELNET_ENVIRON_VALUE 1 167#define TELNET_ENVIRON_ESC 2 168#define TELNET_ENVIRON_USERVAR 3 169/*@}*/ 170 171/*! \name Protocol codes for MSSP commands. */ 172/*@{*/ 173/*! MSSP codes. */ 174#define TELNET_MSSP_VAR 1 175#define TELNET_MSSP_VAL 2 176/*@}*/ 177 178/*! \name Telnet state tracker flags. */ 179/*@{*/ 180/*! Control behavior of telnet state tracker. */ 181#define TELNET_FLAG_PROXY (1<<0) 182#define TELNET_FLAG_NVT_EOL (1<<1) 183 184/* Internal-only bits in option flags */ 185#define TELNET_FLAG_TRANSMIT_BINARY (1<<5) 186#define TELNET_FLAG_RECEIVE_BINARY (1<<6) 187#define TELNET_PFLAG_DEFLATE (1<<7) 188/*@}*/ 189 190/*! 191 * error codes 192 */ 193enum telnet_error_t { 194 TELNET_EOK = 0, /*!< no error */ 195 TELNET_EBADVAL, /*!< invalid parameter, or API misuse */ 196 TELNET_ENOMEM, /*!< memory allocation failure */ 197 TELNET_EOVERFLOW, /*!< data exceeds buffer size */ 198 TELNET_EPROTOCOL, /*!< invalid sequence of special bytes */ 199 TELNET_ECOMPRESS /*!< error handling compressed streams */ 200}; 201typedef enum telnet_error_t telnet_error_t; /*!< Error code type. */ 202 203/*! 204 * event codes 205 */ 206enum telnet_event_type_t { 207 TELNET_EV_DATA = 0, /*!< raw text data has been received */ 208 TELNET_EV_SEND, /*!< data needs to be sent to the peer */ 209 TELNET_EV_IAC, /*!< generic IAC code received */ 210 TELNET_EV_WILL, /*!< WILL option negotiation received */ 211 TELNET_EV_WONT, /*!< WONT option neogitation received */ 212 TELNET_EV_DO, /*!< DO option negotiation received */ 213 TELNET_EV_DONT, /*!< DONT option negotiation received */ 214 TELNET_EV_SUBNEGOTIATION, /*!< sub-negotiation data received */ 215 TELNET_EV_COMPRESS, /*!< compression has been enabled */ 216 TELNET_EV_ZMP, /*!< ZMP command has been received */ 217 TELNET_EV_TTYPE, /*!< TTYPE command has been received */ 218 TELNET_EV_ENVIRON, /*!< ENVIRON command has been received */ 219 TELNET_EV_MSSP, /*!< MSSP command has been received */ 220 TELNET_EV_WARNING, /*!< recoverable error has occured */ 221 TELNET_EV_ERROR /*!< non-recoverable error has occured */ 222}; 223typedef enum telnet_event_type_t telnet_event_type_t; /*!< Telnet event type. */ 224 225/*! 226 * environ/MSSP command information 227 */ 228struct telnet_environ_t { 229 unsigned char type; /*!< either TELNET_ENVIRON_VAR or TELNET_ENVIRON_USERVAR */ 230 char *var; /*!< name of the variable being set */ 231 char *value; /*!< value of variable being set; empty string if no value */ 232}; 233 234/*! 235 * event information 236 */ 237union telnet_event_t { 238 /*! 239 * \brief Event type 240 * 241 * The type field will determine which of the other event structure fields 242 * have been filled in. For instance, if the event type is TELNET_EV_ZMP, 243 * then the zmp event field (and ONLY the zmp event field) will be filled 244 * in. 245 */ 246 enum telnet_event_type_t type; 247 248 /*! 249 * data event: for DATA and SEND events 250 */ 251 struct data_t { 252 enum telnet_event_type_t _type; /*!< alias for type */ 253 const char *buffer; /*!< byte buffer */ 254 size_t size; /*!< number of bytes in buffer */ 255 } data; 256 257 /*! 258 * WARNING and ERROR events 259 */ 260 struct error_t { 261 enum telnet_event_type_t _type; /*!< alias for type */ 262 const char *file; /*!< file the error occured in */ 263 const char *func; /*!< function the error occured in */ 264 const char *msg; /*!< error message string */ 265 int line; /*!< line of file error occured on */ 266 telnet_error_t errcode; /*!< error code */ 267 } error; 268 269 /*! 270 * command event: for IAC 271 */ 272 struct iac_t { 273 enum telnet_event_type_t _type; /*!< alias for type */ 274 unsigned char cmd; /*!< telnet command received */ 275 } iac; 276 277 /*! 278 * negotiation event: WILL, WONT, DO, DONT 279 */ 280 struct negotiate_t { 281 enum telnet_event_type_t _type; /*!< alias for type */ 282 unsigned char telopt; /*!< option being negotiated */ 283 } neg; 284 285 /*! 286 * subnegotiation event 287 */ 288 struct subnegotiate_t { 289 enum telnet_event_type_t _type; /*!< alias for type */ 290 const char *buffer; /*!< data of sub-negotiation */ 291 size_t size; /*!< number of bytes in buffer */ 292 unsigned char telopt; /*!< option code for negotiation */ 293 } sub; 294 295 /*! 296 * ZMP event 297 */ 298 struct zmp_t { 299 enum telnet_event_type_t _type; /*!< alias for type */ 300 const char **argv; /*!< array of argument string */ 301 size_t argc; /*!< number of elements in argv */ 302 } zmp; 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 * COMPRESS event 315 */ 316 struct compress_t { 317 enum telnet_event_type_t _type; /*!< alias for type */ 318 unsigned char state; /*!< 1 if compression is enabled, 319 0 if disabled */ 320 } compress; 321 322 /*! 323 * ENVIRON/NEW-ENVIRON event 324 */ 325 struct environ_t { 326 enum telnet_event_type_t _type; /*!< alias for type */ 327 const struct telnet_environ_t *values; /*!< array of variable values */ 328 size_t size; /*!< number of elements in values */ 329 unsigned char cmd; /*!< SEND, IS, or INFO */ 330 } environ; 331 332 /*! 333 * MSSP event 334 */ 335 struct mssp_t { 336 enum telnet_event_type_t _type; /*!< alias for type */ 337 const struct telnet_environ_t *values; /*!< array of variable values */ 338 size_t size; /*!< number of elements in values */ 339 } mssp; 340}; 341 342/*! 343 * \brief event handler 344 * 345 * This is the type of function that must be passed to 346 * telnet_init() when creating a new telnet object. The 347 * function will be invoked once for every event generated 348 * by the libtelnet protocol parser. 349 * 350 * \param telnet The telnet object that generated the event 351 * \param event Event structure with details about the event 352 * \param user_data User-supplied pointer 353 */ 354typedef void (*telnet_event_handler_t)(telnet_t *telnet, 355 telnet_event_t *event, void *user_data); 356 357/*! 358 * telopt support table element; use telopt of -1 for end marker 359 */ 360struct telnet_telopt_t { 361 short telopt; /*!< one of the TELOPT codes or -1 */ 362 unsigned char us; /*!< TELNET_WILL or TELNET_WONT */ 363 unsigned char him; /*!< TELNET_DO or TELNET_DONT */ 364}; 365 366/*! 367 * state tracker -- private data structure 368 */ 369struct telnet_t; 370 371/*! 372 * \brief Initialize a telnet state tracker. 373 * 374 * This function initializes a new state tracker, which is used for all 375 * other libtelnet functions. Each connection must have its own 376 * telnet state tracker object. 377 * 378 * \param telopts Table of TELNET options the application supports. 379 * \param eh Event handler function called for every event. 380 * \param flags 0 or TELNET_FLAG_PROXY. 381 * \param user_data Optional data pointer that will be passsed to eh. 382 * \return Telnet state tracker object. 383 */ 384extern telnet_t* telnet_init(const telnet_telopt_t *telopts, 385 telnet_event_handler_t eh, unsigned char flags, void *user_data); 386 387/*! 388 * \brief Free up any memory allocated by a state tracker. 389 * 390 * This function must be called when a telnet state tracker is no 391 * longer needed (such as after the connection has been closed) to 392 * release any memory resources used by the state tracker. 393 * 394 * \param telnet Telnet state tracker object. 395 */ 396extern void telnet_free(telnet_t *telnet); 397 398/*! 399 * \brief Push a byte buffer into the state tracker. 400 * 401 * Passes one or more bytes to the telnet state tracker for 402 * protocol parsing. The byte buffer is most often going to be 403 * the buffer that recv() was called for while handling the 404 * connection. 405 * 406 * \param telnet Telnet state tracker object. 407 * \param buffer Pointer to byte buffer. 408 * \param size Number of bytes pointed to by buffer. 409 */ 410extern void telnet_recv(telnet_t *telnet, const char *buffer, 411 size_t size); 412 413/*! 414 * \brief Send a telnet command. 415 * 416 * \param telnet Telnet state tracker object. 417 * \param cmd Command to send. 418 */ 419extern void telnet_iac(telnet_t *telnet, unsigned char cmd); 420 421/*! 422 * \brief Send negotiation command. 423 * 424 * Internally, libtelnet uses RFC1143 option negotiation rules. 425 * The negotiation commands sent with this function may be ignored 426 * if they are determined to be redundant. 427 * 428 * \param telnet Telnet state tracker object. 429 * \param cmd TELNET_WILL, TELNET_WONT, TELNET_DO, or TELNET_DONT. 430 * \param opt One of the TELNET_TELOPT_* values. 431 */ 432extern void telnet_negotiate(telnet_t *telnet, unsigned char cmd, 433 unsigned char opt); 434 435/*! 436 * Send non-command data (escapes IAC bytes). 437 * 438 * \param telnet Telnet state tracker object. 439 * \param buffer Buffer of bytes to send. 440 * \param size Number of bytes to send. 441 */ 442extern void telnet_send(telnet_t *telnet, 443 const char *buffer, size_t size); 444 445/*! 446 * Send non-command text (escapes IAC bytes and translates 447 * \\r -> CR-NUL and \\n -> CR-LF unless in BINARY mode. 448 * 449 * \param telnet Telnet state tracker object. 450 * \param buffer Buffer of bytes to send. 451 * \param size Number of bytes to send. 452 */ 453extern void telnet_send_text(telnet_t *telnet, 454 const char *buffer, size_t size); 455 456/*! 457 * \brief Begin a sub-negotiation command. 458 * 459 * Sends IAC SB followed by the telopt code. All following data sent 460 * will be part of the sub-negotiation, until telnet_finish_sb() is 461 * called. 462 * 463 * \param telnet Telnet state tracker object. 464 * \param telopt One of the TELNET_TELOPT_* values. 465 */ 466extern void telnet_begin_sb(telnet_t *telnet, 467 unsigned char telopt); 468 469/*! 470 * \brief Finish a sub-negotiation command. 471 * 472 * This must be called after a call to telnet_begin_sb() to finish a 473 * sub-negotiation command. 474 * 475 * \param telnet Telnet state tracker object. 476 */ 477#define telnet_finish_sb(telnet) telnet_iac((telnet), TELNET_SE) 478 479/*! 480 * \brief Shortcut for sending a complete subnegotiation buffer. 481 * 482 * Equivalent to: 483 * telnet_begin_sb(telnet, telopt); 484 * telnet_send(telnet, buffer, size); 485 * telnet_finish_sb(telnet); 486 * 487 * \param telnet Telnet state tracker format. 488 * \param telopt One of the TELNET_TELOPT_* values. 489 * \param buffer Byte buffer for sub-negotiation data. 490 * \param size Number of bytes to use for sub-negotiation data. 491 */ 492extern void telnet_subnegotiation(telnet_t *telnet, unsigned char telopt, 493 const char *buffer, size_t size); 494 495/*! 496 * \brief Begin sending compressed data. 497 * 498 * This function will begein sending data using the COMPRESS2 option, 499 * which enables the use of zlib to compress data sent to the client. 500 * The client must offer support for COMPRESS2 with option negotiation, 501 * and zlib support must be compiled into libtelnet. 502 * 503 * Only the server may call this command. 504 * 505 * \param telnet Telnet state tracker object. 506 */ 507extern void telnet_begin_compress2(telnet_t *telnet); 508 509/*! 510 * \brief Send formatted data. 511 * 512 * This function is a wrapper around telnet_send(). It allows using 513 * printf-style formatting. 514 * 515 * Additionally, this function will translate \\r to the CR NUL construct and 516 * \\n with CR LF, as well as automatically escaping IAC bytes like 517 * telnet_send(). 518 * 519 * \param telnet Telnet state tracker object. 520 * \param fmt Format string. 521 * \return Number of bytes sent. 522 */ 523extern int telnet_printf(telnet_t *telnet, const char *fmt, ...) 524 TELNET_GNU_PRINTF(2, 3); 525 526/*! 527 * \brief Send formatted data. 528 * 529 * See telnet_printf(). 530 */ 531extern int telnet_vprintf(telnet_t *telnet, const char *fmt, va_list va); 532 533/*! 534 * \brief Send formatted data (no newline escaping). 535 * 536 * This behaves identically to telnet_printf(), except that the \\r and \\n 537 * characters are not translated. The IAC byte is still escaped as normal 538 * with telnet_send(). 539 * 540 * \param telnet Telnet state tracker object. 541 * \param fmt Format string. 542 * \return Number of bytes sent. 543 */ 544extern int telnet_raw_printf(telnet_t *telnet, const char *fmt, ...) 545 TELNET_GNU_PRINTF(2, 3); 546 547/*! 548 * \brief Send formatted data (no newline escaping). 549 * 550 * See telnet_raw_printf(). 551 */ 552extern int telnet_raw_vprintf(telnet_t *telnet, const char *fmt, va_list va); 553 554/*! 555 * \brief Begin a new set of NEW-ENVIRON values to request or send. 556 * 557 * This function will begin the sub-negotiation block for sending or 558 * requesting NEW-ENVIRON values. 559 * 560 * The telnet_finish_newenviron() macro must be called after this 561 * function to terminate the NEW-ENVIRON command. 562 * 563 * \param telnet Telnet state tracker object. 564 * \param type One of TELNET_ENVIRON_SEND, TELNET_ENVIRON_IS, or 565 * TELNET_ENVIRON_INFO. 566 */ 567extern void telnet_begin_newenviron(telnet_t *telnet, unsigned char type); 568 569/*! 570 * \brief Send a NEW-ENVIRON variable name or value. 571 * 572 * This can only be called between calls to telnet_begin_newenviron() and 573 * telnet_finish_newenviron(). 574 * 575 * \param telnet Telnet state tracker object. 576 * \param type One of TELNET_ENVIRON_VAR, TELNET_ENVIRON_USERVAR, or 577 * TELNET_ENVIRON_VALUE. 578 * \param string Variable name or value. 579 */ 580extern void telnet_newenviron_value(telnet_t* telnet, unsigned char type, 581 const char *string); 582 583/*! 584 * \brief Finish a NEW-ENVIRON command. 585 * 586 * This must be called after a call to telnet_begin_newenviron() to finish a 587 * NEW-ENVIRON variable list. 588 * 589 * \param telnet Telnet state tracker object. 590 */ 591#define telnet_finish_newenviron(telnet) telnet_finish_sb((telnet)) 592 593/*! 594 * \brief Send the TERMINAL-TYPE SEND command. 595 * 596 * Sends the sequence IAC TERMINAL-TYPE SEND. 597 * 598 * \param telnet Telnet state tracker object. 599 */ 600extern void telnet_ttype_send(telnet_t *telnet); 601 602/*! 603 * \brief Send the TERMINAL-TYPE IS command. 604 * 605 * Sends the sequence IAC TERMINAL-TYPE IS "string". 606 * 607 * According to the RFC, the recipient of a TERMINAL-TYPE SEND shall 608 * send the next possible terminal-type the client supports. Upon sending 609 * the type, the client should switch modes to begin acting as the terminal 610 * type is just sent. 611 * 612 * The server may continue sending TERMINAL-TYPE IS until it receives a 613 * terminal type is understands. To indicate to the server that it has 614 * reached the end of the available optoins, the client must send the last 615 * terminal type a second time. When the server receives the same terminal 616 * type twice in a row, it knows it has seen all available terminal types. 617 * 618 * After the last terminal type is sent, if the client receives another 619 * TERMINAL-TYPE SEND command, it must begin enumerating the available 620 * terminal types from the very beginning. This allows the server to 621 * scan the available types for a preferred terminal type and, if none 622 * is found, to then ask the client to switch to an acceptable 623 * alternative. 624 * 625 * Note that if the client only supports a single terminal type, then 626 * simply sending that one type in response to every SEND will satisfy 627 * the behavior requirements. 628 * 629 * \param telnet Telnet state tracker object. 630 * \param ttype Name of the terminal-type being sent. 631 */ 632extern void telnet_ttype_is(telnet_t *telnet, const char* ttype); 633 634/*! 635 * \brief Send a ZMP command. 636 * 637 * \param telnet Telnet state tracker object. 638 * \param argc Number of ZMP commands being sent. 639 * \param argv Array of argument strings. 640 */ 641extern void telnet_send_zmp(telnet_t *telnet, size_t argc, const char **argv); 642 643/*! 644 * \brief Send a ZMP command. 645 * 646 * Arguments are listed out in var-args style. After the last argument, a 647 * NULL pointer must be passed in as a sentinel value. 648 * 649 * \param telnet Telnet state tracker object. 650 */ 651extern void telnet_send_zmpv(telnet_t *telnet, ...) TELNET_GNU_SENTINEL; 652 653/*! 654 * \brief Send a ZMP command. 655 * 656 * See telnet_send_zmpv(). 657 */ 658extern void telnet_send_vzmpv(telnet_t *telnet, va_list va); 659 660/*! 661 * \brief Begin sending a ZMP command 662 * 663 * \param telnet Telnet state tracker object. 664 * \param cmd The first argument (command name) for the ZMP command. 665 */ 666extern void telnet_begin_zmp(telnet_t *telnet, const char *cmd); 667 668/*! 669 * \brief Send a ZMP command argument. 670 * 671 * \param telnet Telnet state tracker object. 672 * \param arg Telnet argument string. 673 */ 674extern void telnet_zmp_arg(telnet_t *telnet, const char *arg); 675 676/*! 677 * \brief Finish a ZMP command. 678 * 679 * This must be called after a call to telnet_begin_zmp() to finish a 680 * ZMP argument list. 681 * 682 * \param telnet Telnet state tracker object. 683 */ 684#define telnet_finish_zmp(telnet) telnet_finish_sb((telnet)) 685 686/* C++ support */ 687#if defined(__cplusplus) 688} /* extern "C" */ 689#endif 690 691#endif /* !defined(LIBTELNET_INCLUDE) */