This source file includes following definitions.
- _send
- _check_telopt
- _get_rfc1143
- _set_rfc1143
- _send_negotiate
- _negotiate
- _environ_telnet
- _ttype_telnet
- _subnegotiate
- telnet_init
- telnet_free
- _buffer_byte
- _process
- telnet_recv
- telnet_iac
- telnet_negotiate
- telnet_send
- telnet_send_text
- telnet_begin_sb
- telnet_vprintf
- telnet_printf
- telnet_raw_vprintf
- telnet_raw_printf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 #include <stdlib.h>
56 #include <string.h>
57 #include <stdio.h>
58 #include <errno.h>
59 #include <string.h>
60 #include <stdarg.h>
61
62 #if defined(__GNUC__)
63 # define NO_RETURN __attribute__ ((noreturn))
64 # define UNUSED __attribute__ ((unused))
65 #else
66 # define NO_RETURN
67 # define UNUSED
68 #endif
69
70
71 #if defined(_WIN32)
72 # define __func__ __FUNCTION__
73 # if defined(_MSC_VER)
74 # if _MSC_VER <= 1700
75 # define va_copy(dest, src) (dest = src)
76 # endif
77 # endif
78 #endif
79
80 #include "libtelnet.h"
81
82 #if defined(FREE)
83 # undef FREE
84 #endif
85 #define FREE(p) do \
86 { \
87 free((p)); \
88 (p) = NULL; \
89 } while(0)
90
91
92 #define Q_US(q) ((q).state & 0x0F)
93 #define Q_HIM(q) (((q).state & 0xF0) >> 4)
94 #define Q_MAKE(us,him) ((us) | ((him) << 4))
95
96
97 #define NEGOTIATE_EVENT(telnet,cmd,opt) \
98 ev.type = (cmd); \
99 ev.neg.telopt = (opt); \
100 (telnet)->eh((telnet), &ev, (telnet)->ud);
101
102
103 enum telnet_state_t {
104 TELNET_STATE_DATA = 0,
105 TELNET_STATE_EOL,
106 TELNET_STATE_IAC,
107 TELNET_STATE_WILL,
108 TELNET_STATE_WONT,
109 TELNET_STATE_DO,
110 TELNET_STATE_DONT,
111 TELNET_STATE_SB,
112 TELNET_STATE_SB_DATA,
113 TELNET_STATE_SB_DATA_IAC
114 };
115 typedef enum telnet_state_t telnet_state_t;
116
117
118 struct telnet_t {
119
120 void *ud;
121
122 const telnet_telopt_t *telopts;
123
124 telnet_event_handler_t eh;
125
126 struct telnet_rfc1143_t *q;
127
128 char *buffer;
129
130 size_t buffer_size;
131
132 size_t buffer_pos;
133
134 enum telnet_state_t state;
135
136 unsigned char flags;
137
138 unsigned char sb_telopt;
139
140 unsigned int q_size;
141
142 unsigned int q_cnt;
143 };
144
145
146 typedef struct telnet_rfc1143_t {
147 unsigned char telopt;
148 unsigned char state;
149 } telnet_rfc1143_t;
150
151
152 #define Q_NO 0
153 #define Q_YES 1
154 #define Q_WANTNO 2
155 #define Q_WANTYES 3
156 #define Q_WANTNO_OP 4
157 #define Q_WANTYES_OP 5
158
159
160 static const char CRLF[] = { '\r', '\n' };
161 static const char CRNUL[] = { '\r', '\0' };
162
163
164 static const size_t _buffer_sizes[] = { 0, 512, 2048, 8192, 16384, };
165 static const size_t _buffer_sizes_count = sizeof(_buffer_sizes) /
166 sizeof(_buffer_sizes[0]);
167
168
169 static telnet_error_t _error(telnet_t *telnet, unsigned line,
170 const char* func, telnet_error_t err,
171 int fatal, const char *fmt, ...) {
172 telnet_event_t ev;
173 char buffer[512];
174 va_list va;
175
176
177 va_start(va, fmt);
178 (void)vsnprintf(buffer, sizeof(buffer), fmt, va);
179 va_end(va);
180
181
182 ev.type = fatal ? TELNET_EV_ERROR : TELNET_EV_WARNING;
183 ev.error.file = __FILE__;
184 ev.error.func = func;
185 ev.error.line = (int) line;
186 ev.error.msg = buffer;
187 telnet->eh(telnet, &ev, telnet->ud);
188
189 return err;
190 }
191
192
193 static void _send(telnet_t *telnet, const char *buffer,
194 size_t size) {
195 telnet_event_t ev;
196
197 ev.type = TELNET_EV_SEND;
198 ev.data.buffer = buffer;
199 ev.data.size = size;
200 telnet->eh(telnet, &ev, telnet->ud);
201 }
202
203
204 #define _sendu(t, d, s) _send((t), (const char*)(d), (s))
205
206
207
208
209
210
211
212 static __inline__ int _check_telopt(telnet_t *telnet, unsigned char telopt,
213 int us) {
214 int i;
215
216
217 if (telnet->telopts == 0)
218 return 0;
219
220
221 for (i = 0; telnet->telopts[i].telopt != -1; ++i) {
222 if (telnet->telopts[i].telopt == telopt) {
223 if (us && telnet->telopts[i].us == TELNET_WILL)
224 return 1;
225 else if (!us && telnet->telopts[i].him == TELNET_DO)
226 return 1;
227 else
228 return 0;
229 }
230 }
231
232
233 return 0;
234 }
235
236
237 static __inline__ telnet_rfc1143_t _get_rfc1143(telnet_t *telnet,
238 unsigned char telopt) {
239 telnet_rfc1143_t empty;
240 unsigned int i;
241
242
243 for (i = 0; i != telnet->q_cnt; ++i) {
244 if (telnet->q[i].telopt == telopt) {
245 return telnet->q[i];
246 }
247 }
248
249
250 empty.telopt = telopt;
251 empty.state = 0;
252 return empty;
253 }
254
255
256 static __inline__ void _set_rfc1143(telnet_t *telnet, unsigned char telopt,
257 unsigned char us, unsigned char him) {
258 telnet_rfc1143_t *qtmp;
259 unsigned int i;
260
261
262 for (i = 0; i != telnet->q_cnt; ++i) {
263 if (telnet->q[i].telopt == telopt) {
264 telnet->q[i].state = (unsigned char) Q_MAKE(us,him);
265 if (telopt != TELNET_TELOPT_BINARY)
266 return;
267 telnet->flags &=
268 (unsigned char)~(TELNET_FLAG_TRANSMIT_BINARY |
269 TELNET_FLAG_RECEIVE_BINARY);
270 if (us == Q_YES)
271 telnet->flags |= TELNET_FLAG_TRANSMIT_BINARY;
272 if (him == Q_YES)
273 telnet->flags |= TELNET_FLAG_RECEIVE_BINARY;
274 return;
275 }
276 }
277
278
279
280
281
282
283
284
285
286 #define QUANTUM 4
287
288 if (i >= telnet->q_size) {
289
290 if ((qtmp = (telnet_rfc1143_t *)realloc(telnet->q,
291 sizeof(telnet_rfc1143_t) * (telnet->q_size + QUANTUM))) == 0) {
292 _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
293 "realloc() failed: %s", xstrerror_l(errno));
294 return;
295 }
296 (void)memset(&qtmp[telnet->q_size], 0, sizeof(telnet_rfc1143_t) * QUANTUM);
297 telnet->q = qtmp;
298 telnet->q_size += QUANTUM;
299 }
300
301 telnet->q[telnet->q_cnt].telopt = telopt;
302 telnet->q[telnet->q_cnt].state = (unsigned char) Q_MAKE(us, him);
303 telnet->q_cnt ++;
304 }
305
306
307 static __inline__ void _send_negotiate(telnet_t *telnet, unsigned char cmd,
308 unsigned char telopt) {
309 unsigned char bytes[3];
310 bytes[0] = TELNET_IAC;
311 bytes[1] = cmd;
312 bytes[2] = telopt;
313 _sendu(telnet, bytes, 3);
314 }
315
316
317 static void _negotiate(telnet_t *telnet, unsigned char telopt) {
318 telnet_event_t ev;
319 telnet_rfc1143_t q;
320
321
322 if (telnet->flags & TELNET_FLAG_PROXY) {
323 switch ((int)telnet->state) {
324 case TELNET_STATE_WILL:
325 NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
326 break;
327 case TELNET_STATE_WONT:
328 NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
329 break;
330 case TELNET_STATE_DO:
331 NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
332 break;
333 case TELNET_STATE_DONT:
334 NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt);
335 break;
336 }
337 return;
338 }
339
340
341 q = _get_rfc1143(telnet, telopt);
342
343
344 switch ((int)telnet->state) {
345
346 case TELNET_STATE_WILL:
347 switch (Q_HIM(q)) {
348 case Q_NO:
349 if (_check_telopt(telnet, telopt, 0)) {
350 _set_rfc1143(telnet, telopt, Q_US(q), Q_YES);
351 _send_negotiate(telnet, TELNET_DO, telopt);
352 NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
353 } else
354 _send_negotiate(telnet, TELNET_DONT, telopt);
355 break;
356 case Q_WANTNO:
357 _set_rfc1143(telnet, telopt, Q_US(q), Q_NO);
358 NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
359 _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
360 "DONT answered by WILL");
361 break;
362 case Q_WANTNO_OP:
363 _set_rfc1143(telnet, telopt, Q_US(q), Q_YES);
364 _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
365 "DONT answered by WILL");
366 break;
367 case Q_WANTYES:
368 _set_rfc1143(telnet, telopt, Q_US(q), Q_YES);
369 NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
370 break;
371 case Q_WANTYES_OP:
372 _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTNO);
373 _send_negotiate(telnet, TELNET_DONT, telopt);
374 NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
375 break;
376 }
377 break;
378
379
380 case TELNET_STATE_WONT:
381 switch (Q_HIM(q)) {
382 case Q_YES:
383 _set_rfc1143(telnet, telopt, Q_US(q), Q_NO);
384 _send_negotiate(telnet, TELNET_DONT, telopt);
385 NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
386 break;
387 case Q_WANTNO:
388 _set_rfc1143(telnet, telopt, Q_US(q), Q_NO);
389 NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
390 break;
391 case Q_WANTNO_OP:
392 _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTYES);
393 _send_negotiate(telnet, TELNET_DO, telopt);
394 NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
395 break;
396 case Q_WANTYES:
397 case Q_WANTYES_OP:
398 _set_rfc1143(telnet, telopt, Q_US(q), Q_NO);
399 break;
400 }
401 break;
402
403
404 case TELNET_STATE_DO:
405 switch (Q_US(q)) {
406 case Q_NO:
407 if (_check_telopt(telnet, telopt, 1)) {
408 _set_rfc1143(telnet, telopt, Q_YES, Q_HIM(q));
409 _send_negotiate(telnet, TELNET_WILL, telopt);
410 NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
411 } else
412 _send_negotiate(telnet, TELNET_WONT, telopt);
413 break;
414 case Q_WANTNO:
415 _set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q));
416 NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt);
417 _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
418 "WONT answered by DO");
419 break;
420 case Q_WANTNO_OP:
421 _set_rfc1143(telnet, telopt, Q_YES, Q_HIM(q));
422 _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
423 "WONT answered by DO");
424 break;
425 case Q_WANTYES:
426 _set_rfc1143(telnet, telopt, Q_YES, Q_HIM(q));
427 NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
428 break;
429 case Q_WANTYES_OP:
430 _set_rfc1143(telnet, telopt, Q_WANTNO, Q_HIM(q));
431 _send_negotiate(telnet, TELNET_WONT, telopt);
432 NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
433 break;
434 }
435 break;
436
437
438 case TELNET_STATE_DONT:
439 switch (Q_US(q)) {
440 case Q_YES:
441 _set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q));
442 _send_negotiate(telnet, TELNET_WONT, telopt);
443 NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt);
444 break;
445 case Q_WANTNO:
446 _set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q));
447 NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt);
448 break;
449 case Q_WANTNO_OP:
450 _set_rfc1143(telnet, telopt, Q_WANTYES, Q_HIM(q));
451 _send_negotiate(telnet, TELNET_WILL, telopt);
452 NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt);
453 break;
454 case Q_WANTYES:
455 case Q_WANTYES_OP:
456 _set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q));
457 break;
458 }
459 break;
460 }
461 }
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477 static int _environ_telnet(telnet_t *telnet, unsigned char type,
478 char* buffer, size_t size) {
479 telnet_event_t ev;
480 struct telnet_environ_t *values = 0;
481 char *c, *last, *out;
482 size_t eindex, count;
483
484
485 if (size == 0) {
486 return 0;
487 }
488
489
490 if ((unsigned)buffer[0] != TELNET_ENVIRON_SEND &&
491 (unsigned)buffer[0] != TELNET_ENVIRON_IS &&
492 (unsigned)buffer[0] != TELNET_ENVIRON_INFO) {
493 _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
494 "telopt %ld subneg has invalid command", (long) type);
495 return 0;
496 }
497
498
499 ev.environ.cmd = (unsigned char) buffer[0];
500
501
502 if (size == 1) {
503
504 ev.environ.values = 0;
505 ev.environ.size = 0;
506
507
508 ev.type = TELNET_EV_ENVIRON;
509 telnet->eh(telnet, &ev, telnet->ud);
510
511 return 0;
512 }
513
514
515 if ((unsigned)buffer[1] != TELNET_ENVIRON_VAR &&
516 (unsigned)buffer[1] != TELNET_ENVIRON_USERVAR) {
517 _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
518 "telopt %d subneg missing variable type", type);
519 return 0;
520 }
521
522
523 if ((unsigned)buffer[size - 1] == TELNET_ENVIRON_ESC) {
524 _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
525 "telopt %d subneg ends with ESC", type);
526 return 0;
527 }
528
529
530 count = 0;
531 for (c = buffer + 1; c < buffer + size; ++c) {
532 if (*c == TELNET_ENVIRON_VAR || *c == TELNET_ENVIRON_USERVAR) {
533 ++count;
534 } else if (*c == TELNET_ENVIRON_ESC) {
535
536 ++c;
537 }
538 }
539
540
541 if ((values = (struct telnet_environ_t *)calloc(count,
542 sizeof(struct telnet_environ_t))) == 0) {
543 _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
544 "calloc() failed: %s", xstrerror_l(errno));
545 return 0;
546 }
547
548
549 out = buffer;
550 c = buffer + 1;
551 for (eindex = 0; eindex != count; ++eindex) {
552
553 values[eindex].type = (unsigned char) (*c++);
554
555
556
557 last = out;
558 while (c < buffer + size) {
559
560 if ((unsigned)*c == TELNET_ENVIRON_VAR ||
561 (unsigned)*c == TELNET_ENVIRON_VALUE ||
562 (unsigned)*c == TELNET_ENVIRON_USERVAR) {
563 break;
564 }
565
566
567 if (*c == TELNET_ENVIRON_ESC) {
568 ++c;
569 }
570
571 *out++ = *c++;
572 }
573 *out++ = '\0';
574
575
576 values[eindex].var = last;
577 values[eindex].value = "";
578
579
580
581 if (c < buffer + size && *c == TELNET_ENVIRON_VALUE) {
582 ++c;
583 last = out;
584 while (c < buffer + size) {
585
586 if ((unsigned)*c == TELNET_ENVIRON_VAR ||
587 (unsigned)*c == TELNET_ENVIRON_USERVAR) {
588 break;
589 }
590
591
592 if (*c == TELNET_ENVIRON_ESC) {
593 ++c;
594 }
595
596 *out++ = *c++;
597 }
598 *out++ = '\0';
599
600
601 values[eindex].value = last;
602 }
603 }
604
605
606 ev.environ.values = values;
607 ev.environ.size = count;
608
609
610 ev.type = TELNET_EV_ENVIRON;
611 telnet->eh(telnet, &ev, telnet->ud);
612
613
614 FREE(values);
615 return 0;
616 }
617
618
619 static int _ttype_telnet(telnet_t *telnet, const char* buffer, size_t size) {
620 telnet_event_t ev;
621
622
623 if (size == 0) {
624 _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
625 "incomplete TERMINAL-TYPE request");
626 return 0;
627 }
628
629
630 if (buffer[0] != TELNET_TTYPE_IS &&
631 buffer[0] != TELNET_TTYPE_SEND) {
632 _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
633 "TERMINAL-TYPE request has invalid type");
634 return 0;
635 }
636
637
638 if (buffer[0] == TELNET_TTYPE_IS) {
639 char *name;
640
641
642 if ((name = (char *)malloc(size)) == 0) {
643 _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
644 "malloc() failed: %s", xstrerror_l(errno));
645 return 0;
646 }
647 memcpy(name, buffer + 1, size - 1);
648 name[size - 1] = '\0';
649
650 ev.type = TELNET_EV_TTYPE;
651 ev.ttype.cmd = TELNET_TTYPE_IS;
652 ev.ttype.name = name;
653 telnet->eh(telnet, &ev, telnet->ud);
654
655
656 FREE(name);
657 } else {
658 ev.type = TELNET_EV_TTYPE;
659 ev.ttype.cmd = TELNET_TTYPE_SEND;
660 ev.ttype.name = 0;
661 telnet->eh(telnet, &ev, telnet->ud);
662 }
663
664 return 0;
665 }
666
667
668
669
670
671
672 static int _subnegotiate(telnet_t *telnet) {
673 telnet_event_t ev;
674
675
676 ev.type = TELNET_EV_SUBNEGOTIATION;
677 ev.sub.telopt = telnet->sb_telopt;
678 ev.sub.buffer = telnet->buffer;
679 ev.sub.size = telnet->buffer_pos;
680 telnet->eh(telnet, &ev, telnet->ud);
681
682 switch (telnet->sb_telopt) {
683
684 case TELNET_TELOPT_TTYPE:
685 return _ttype_telnet(telnet, telnet->buffer, telnet->buffer_pos);
686 case TELNET_TELOPT_ENVIRON:
687 case TELNET_TELOPT_NEW_ENVIRON:
688 return _environ_telnet(telnet, telnet->sb_telopt, telnet->buffer,
689 telnet->buffer_pos);
690 default:
691 return 0;
692 }
693 }
694
695
696 telnet_t *telnet_init(const telnet_telopt_t *telopts,
697 telnet_event_handler_t eh, unsigned char flags, void *user_data) {
698
699 struct telnet_t *telnet = (telnet_t*)calloc(1, sizeof(telnet_t));
700 if (telnet == 0)
701 return 0;
702
703
704 telnet->ud = user_data;
705 telnet->telopts = telopts;
706 telnet->eh = eh;
707 telnet->flags = flags;
708
709 return telnet;
710 }
711
712
713 void telnet_free(telnet_t *telnet) {
714
715 if (telnet->buffer != 0) {
716 FREE(telnet->buffer);
717 telnet->buffer = 0;
718 telnet->buffer_size = 0;
719 telnet->buffer_pos = 0;
720 }
721
722
723 if (telnet->q) {
724 FREE(telnet->q);
725 telnet->q = NULL;
726 telnet->q_size = 0;
727 telnet->q_cnt = 0;
728 }
729
730
731 free(telnet);
732 }
733
734
735 static telnet_error_t _buffer_byte(telnet_t *telnet,
736 unsigned char byte) {
737 char *new_buffer;
738
739
740 if (telnet->buffer_pos == telnet->buffer_size) {
741 size_t i;
742
743 for (i = 0; i != _buffer_sizes_count; ++i) {
744 if (_buffer_sizes[i] == telnet->buffer_size) {
745 break;
746 }
747 }
748
749
750 if (i >= _buffer_sizes_count - 1) {
751 _error(telnet, __LINE__, __func__, TELNET_EOVERFLOW, 0,
752 "subnegotiation buffer size limit reached");
753 return TELNET_EOVERFLOW;
754 }
755
756
757 new_buffer = (char *)realloc(telnet->buffer, _buffer_sizes[i + 1]);
758 if (new_buffer == 0) {
759 _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
760 "realloc() failed");
761 return TELNET_ENOMEM;
762 }
763
764 telnet->buffer = new_buffer;
765 telnet->buffer_size = _buffer_sizes[i + 1];
766 }
767
768
769 telnet->buffer[telnet->buffer_pos++] = (char) byte;
770 return TELNET_EOK;
771 }
772
773 static void _process(telnet_t *telnet, const char *buffer, size_t size) {
774 telnet_event_t ev;
775 unsigned char byte;
776 size_t i, start;
777 for (i = start = 0; i != size; ++i) {
778 byte = (unsigned char) buffer[i];
779 switch (telnet->state) {
780
781 case TELNET_STATE_DATA:
782
783
784 if (byte == TELNET_IAC) {
785 if (i != start) {
786 ev.type = TELNET_EV_DATA;
787 ev.data.buffer = buffer + start;
788 ev.data.size = i - start;
789 telnet->eh(telnet, &ev, telnet->ud);
790 }
791 telnet->state = TELNET_STATE_IAC;
792 } else if (byte == '\r' &&
793 (telnet->flags & TELNET_FLAG_NVT_EOL) &&
794 !(telnet->flags & TELNET_FLAG_RECEIVE_BINARY)) {
795 if (i != start) {
796 ev.type = TELNET_EV_DATA;
797 ev.data.buffer = buffer + start;
798 ev.data.size = i - start;
799 telnet->eh(telnet, &ev, telnet->ud);
800 }
801 telnet->state = TELNET_STATE_EOL;
802 }
803 break;
804
805
806 case TELNET_STATE_EOL:
807 if (byte != '\n') {
808 byte = '\r';
809 ev.type = TELNET_EV_DATA;
810 ev.data.buffer = (char*)&byte;
811 ev.data.size = 1;
812 telnet->eh(telnet, &ev, telnet->ud);
813 byte = (unsigned char) buffer[i];
814 }
815
816
817 start = i;
818 if (byte == '\0')
819 ++start;
820
821 telnet->state = TELNET_STATE_DATA;
822 break;
823
824
825 case TELNET_STATE_IAC:
826 switch (byte) {
827
828 case TELNET_SB:
829 telnet->state = TELNET_STATE_SB;
830 break;
831
832 case TELNET_WILL:
833 telnet->state = TELNET_STATE_WILL;
834 break;
835 case TELNET_WONT:
836 telnet->state = TELNET_STATE_WONT;
837 break;
838 case TELNET_DO:
839 telnet->state = TELNET_STATE_DO;
840 break;
841 case TELNET_DONT:
842 telnet->state = TELNET_STATE_DONT;
843 break;
844
845 case TELNET_IAC:
846
847 ev.type = TELNET_EV_DATA;
848 ev.data.buffer = (char*)&byte;
849 ev.data.size = 1;
850 telnet->eh(telnet, &ev, telnet->ud);
851
852
853 start = i + 1;
854 telnet->state = TELNET_STATE_DATA;
855 break;
856
857 default:
858
859 ev.type = TELNET_EV_IAC;
860 ev.iac.cmd = byte;
861 telnet->eh(telnet, &ev, telnet->ud);
862
863
864 start = i + 1;
865 telnet->state = TELNET_STATE_DATA;
866 }
867 break;
868
869
870 case TELNET_STATE_WILL:
871 case TELNET_STATE_WONT:
872 case TELNET_STATE_DO:
873 case TELNET_STATE_DONT:
874 _negotiate(telnet, byte);
875 start = i + 1;
876 telnet->state = TELNET_STATE_DATA;
877 break;
878
879
880 case TELNET_STATE_SB:
881 telnet->sb_telopt = byte;
882 telnet->buffer_pos = 0;
883 telnet->state = TELNET_STATE_SB_DATA;
884 break;
885
886
887 case TELNET_STATE_SB_DATA:
888
889 if (byte == TELNET_IAC) {
890 telnet->state = TELNET_STATE_SB_DATA_IAC;
891 } else if (_buffer_byte(telnet, byte) != TELNET_EOK) {
892 start = i + 1;
893 telnet->state = TELNET_STATE_DATA;
894 }
895 break;
896
897
898 case TELNET_STATE_SB_DATA_IAC:
899 switch (byte) {
900
901 case TELNET_SE:
902
903 start = i + 1;
904 telnet->state = TELNET_STATE_DATA;
905
906
907 if (_subnegotiate(telnet) != 0) {
908 telnet_recv(telnet, &buffer[start], size - start);
909 return;
910 }
911 break;
912
913 case TELNET_IAC:
914
915 if (_buffer_byte(telnet, TELNET_IAC) !=
916 TELNET_EOK) {
917 start = i + 1;
918 telnet->state = TELNET_STATE_DATA;
919 } else {
920 telnet->state = TELNET_STATE_SB_DATA;
921 }
922 break;
923
924
925
926
927
928
929 default:
930 _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
931 "unexpected byte after IAC inside SB: %d",
932 byte);
933
934
935 start = i + 1;
936 telnet->state = TELNET_STATE_IAC;
937
938
939
940
941
942
943 if (_subnegotiate(telnet) != 0) {
944 telnet_recv(telnet, &buffer[start], size - start);
945 return;
946 } else {
947
948
949
950
951
952
953 _process(telnet, (char *)&byte, 1);
954 }
955 break;
956 }
957 break;
958 }
959 }
960
961
962 if (telnet->state == TELNET_STATE_DATA && i != start) {
963 ev.type = TELNET_EV_DATA;
964 ev.data.buffer = buffer + start;
965 ev.data.size = i - start;
966 telnet->eh(telnet, &ev, telnet->ud);
967 }
968 }
969
970
971 void telnet_recv(telnet_t *telnet, const char *buffer,
972 size_t size) {
973 _process(telnet, buffer, size);
974 }
975
976
977 void telnet_iac(telnet_t *telnet, unsigned char cmd) {
978 unsigned char bytes[2];
979 bytes[0] = TELNET_IAC;
980 bytes[1] = cmd;
981 _sendu(telnet, bytes, 2);
982 }
983
984
985 void telnet_negotiate(telnet_t *telnet, unsigned char cmd,
986 unsigned char telopt) {
987 telnet_rfc1143_t q;
988
989
990 if (telnet->flags & TELNET_FLAG_PROXY) {
991 unsigned char bytes[3];
992 bytes[0] = TELNET_IAC;
993 bytes[1] = cmd;
994 bytes[2] = telopt;
995 _sendu(telnet, bytes, 3);
996 return;
997 }
998
999
1000 q = _get_rfc1143(telnet, telopt);
1001
1002 switch (cmd) {
1003
1004 case TELNET_WILL:
1005 switch (Q_US(q)) {
1006 case Q_NO:
1007 _set_rfc1143(telnet, telopt, Q_WANTYES, Q_HIM(q));
1008 _send_negotiate(telnet, TELNET_WILL, telopt);
1009 break;
1010 case Q_WANTNO:
1011 _set_rfc1143(telnet, telopt, Q_WANTNO_OP, Q_HIM(q));
1012 break;
1013 case Q_WANTYES_OP:
1014 _set_rfc1143(telnet, telopt, Q_WANTYES, Q_HIM(q));
1015 break;
1016 }
1017 break;
1018
1019
1020 case TELNET_WONT:
1021 switch (Q_US(q)) {
1022 case Q_YES:
1023 _set_rfc1143(telnet, telopt, Q_WANTNO, Q_HIM(q));
1024 _send_negotiate(telnet, TELNET_WONT, telopt);
1025 break;
1026 case Q_WANTYES:
1027 _set_rfc1143(telnet, telopt, Q_WANTYES_OP, Q_HIM(q));
1028 break;
1029 case Q_WANTNO_OP:
1030 _set_rfc1143(telnet, telopt, Q_WANTNO, Q_HIM(q));
1031 break;
1032 }
1033 break;
1034
1035
1036 case TELNET_DO:
1037 switch (Q_HIM(q)) {
1038 case Q_NO:
1039 _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTYES);
1040 _send_negotiate(telnet, TELNET_DO, telopt);
1041 break;
1042 case Q_WANTNO:
1043 _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTNO_OP);
1044 break;
1045 case Q_WANTYES_OP:
1046 _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTYES);
1047 break;
1048 }
1049 break;
1050
1051
1052 case TELNET_DONT:
1053 switch (Q_HIM(q)) {
1054 case Q_YES:
1055 _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTNO);
1056 _send_negotiate(telnet, TELNET_DONT, telopt);
1057 break;
1058 case Q_WANTYES:
1059 _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTYES_OP);
1060 break;
1061 case Q_WANTNO_OP:
1062 _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTNO);
1063 break;
1064 }
1065 break;
1066 }
1067 }
1068
1069
1070 void telnet_send(telnet_t *telnet, const char *buffer,
1071 size_t size) {
1072 size_t i, l;
1073
1074 for (l = i = 0; i != size; ++i) {
1075
1076 if (buffer[i] == (char)TELNET_IAC) {
1077
1078 if (i != l) {
1079 _send(telnet, buffer + l, i - l);
1080 }
1081 l = i + 1;
1082
1083
1084 telnet_iac(telnet, TELNET_IAC);
1085 }
1086 }
1087
1088
1089 if (i != l) {
1090 _send(telnet, buffer + l, i - l);
1091 }
1092 }
1093
1094
1095 void telnet_send_text(telnet_t *telnet, const char *buffer,
1096 size_t size) {
1097 size_t i, l;
1098
1099 for (l = i = 0; i != size; ++i) {
1100
1101 if (buffer[i] == (char)TELNET_IAC) {
1102
1103 if (i != l) {
1104 _send(telnet, buffer + l, i - l);
1105 }
1106 l = i + 1;
1107
1108
1109 telnet_iac(telnet, TELNET_IAC);
1110 }
1111
1112 else if (!(telnet->flags & TELNET_FLAG_TRANSMIT_BINARY) &&
1113 (buffer[i] == '\r' || buffer[i] == '\n')) {
1114
1115 if (i != l) {
1116 _send(telnet, buffer + l, i - l);
1117 }
1118 l = i + 1;
1119
1120
1121 if (buffer[i] == '\r') {
1122 _send(telnet, CRNUL, 2);
1123 }
1124
1125 else {
1126 _send(telnet, CRLF, 2);
1127 }
1128 }
1129 }
1130
1131
1132 if (i != l) {
1133 _send(telnet, buffer + l, i - l);
1134 }
1135 }
1136
1137
1138 void telnet_begin_sb(telnet_t *telnet, unsigned char telopt) {
1139 unsigned char sb[3];
1140 sb[0] = TELNET_IAC;
1141 sb[1] = TELNET_SB;
1142 sb[2] = telopt;
1143 _sendu(telnet, sb, 3);
1144 }
1145
1146
1147 int telnet_vprintf(telnet_t *telnet, const char *fmt, va_list va) {
1148 char buffer[1024];
1149 char *output = buffer;
1150 int rs, i, l;
1151
1152
1153 va_list va2;
1154 va_copy(va2, va);
1155 rs = vsnprintf(buffer, sizeof(buffer), fmt, va);
1156 if ((unsigned long) rs >= sizeof(buffer)) {
1157 output = (char*)malloc((unsigned long) ((unsigned long)rs + 1L));
1158 if (output == 0) {
1159 _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
1160 "malloc() failed: %s", xstrerror_l(errno));
1161 va_end(va2);
1162 return -1;
1163 }
1164 rs = vsnprintf(output, rs + 1, fmt, va2);
1165 }
1166 va_end(va2);
1167 va_end(va);
1168
1169
1170 for (l = i = 0; i != rs; ++i) {
1171
1172 if (output[i] == (char)TELNET_IAC || output[i] == '\r' ||
1173 output[i] == '\n') {
1174
1175 if (i != l)
1176 _send(telnet, output + l, (size_t) (i - l));
1177 l = i + 1;
1178
1179
1180 if (output[i] == (char)TELNET_IAC)
1181 telnet_iac(telnet, TELNET_IAC);
1182
1183 else if (output[i] == '\r')
1184 _send(telnet, CRNUL, 2);
1185
1186 else if (output[i] == '\n')
1187 _send(telnet, CRLF, 2);
1188 }
1189 }
1190
1191
1192 if (i != l) {
1193 _send(telnet, output + l, (size_t) (i - l));
1194 }
1195
1196
1197 if (output != buffer) {
1198 FREE(output);
1199 }
1200
1201 return rs;
1202 }
1203
1204
1205 int telnet_printf(telnet_t *telnet, const char *fmt, ...) {
1206 va_list va;
1207 int rs;
1208
1209 va_start(va, fmt);
1210 rs = telnet_vprintf(telnet, fmt, va);
1211 va_end(va);
1212
1213 return rs;
1214 }
1215
1216
1217 int telnet_raw_vprintf(telnet_t *telnet, const char *fmt, va_list va) {
1218 char buffer[1024];
1219 char *output = buffer;
1220 int rs;
1221
1222
1223 va_list va2;
1224 va_copy(va2, va);
1225 rs = vsnprintf(buffer, sizeof(buffer), fmt, va);
1226 if ((unsigned long) rs >= sizeof(buffer)) {
1227 output = (char*)malloc((unsigned long) rs + 1);
1228 if (output == 0) {
1229 _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
1230 "malloc() failed: %s", xstrerror_l(errno));
1231 va_end(va2);
1232 return -1;
1233 }
1234 rs = vsnprintf(output, (int)((unsigned int) rs + 1), fmt, va2);
1235 }
1236 va_end(va2);
1237 va_end(va);
1238
1239
1240 telnet_send(telnet, output, (size_t) rs);
1241
1242
1243 if (output != buffer) {
1244 FREE(output);
1245 }
1246
1247 return rs;
1248 }
1249
1250
1251 int telnet_raw_printf(telnet_t *telnet, const char *fmt, ...) {
1252 va_list va;
1253 int rs;
1254
1255 va_start(va, fmt);
1256 rs = telnet_raw_vprintf(telnet, fmt, va);
1257 va_end(va);
1258
1259 return rs;
1260 }