raw.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*
  2. * "Raw" backend.
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <limits.h>
  7. #include "putty.h"
  8. #define RAW_MAX_BACKLOG 4096
  9. typedef struct Raw Raw;
  10. struct Raw {
  11. Socket *s;
  12. bool closed_on_socket_error;
  13. size_t bufsize;
  14. Seat *seat;
  15. LogContext *logctx;
  16. Ldisc *ldisc;
  17. bool sent_console_eof, sent_socket_eof, socket_connected;
  18. char *description;
  19. Conf *conf;
  20. Plug plug;
  21. Backend backend;
  22. Interactor interactor;
  23. };
  24. static void raw_size(Backend *be, int width, int height);
  25. static void c_write(Raw *raw, const void *buf, size_t len)
  26. {
  27. size_t backlog = seat_stdout(raw->seat, buf, len);
  28. sk_set_frozen(raw->s, backlog > RAW_MAX_BACKLOG);
  29. }
  30. static void raw_log(Plug *plug, Socket *s, PlugLogType type, SockAddr *addr,
  31. int port, const char *error_msg, int error_code)
  32. {
  33. Raw *raw = container_of(plug, Raw, plug);
  34. backend_socket_log(raw->seat, raw->logctx, s, type, addr, port,
  35. error_msg, error_code, raw->conf,
  36. raw->socket_connected);
  37. if (type == PLUGLOG_CONNECT_SUCCESS) {
  38. raw->socket_connected = true;
  39. if (raw->ldisc)
  40. ldisc_check_sendok(raw->ldisc);
  41. }
  42. }
  43. static void raw_check_close(Raw *raw)
  44. {
  45. /*
  46. * Called after we send EOF on either the socket or the console.
  47. * Its job is to wind up the session once we have sent EOF on both.
  48. */
  49. if (raw->sent_console_eof && raw->sent_socket_eof) {
  50. if (raw->s) {
  51. sk_close(raw->s);
  52. raw->s = NULL;
  53. seat_notify_remote_exit(raw->seat);
  54. seat_notify_remote_disconnect(raw->seat);
  55. }
  56. }
  57. }
  58. static void raw_closing(Plug *plug, PlugCloseType type, const char *error_msg)
  59. {
  60. Raw *raw = container_of(plug, Raw, plug);
  61. if (type != PLUGCLOSE_NORMAL) {
  62. /* A socket error has occurred. */
  63. if (raw->s) {
  64. sk_close(raw->s);
  65. raw->s = NULL;
  66. raw->closed_on_socket_error = true;
  67. seat_notify_remote_exit(raw->seat);
  68. seat_notify_remote_disconnect(raw->seat);
  69. }
  70. logevent(raw->logctx, error_msg);
  71. if (type != PLUGCLOSE_USER_ABORT)
  72. seat_connection_fatal(raw->seat, "%s", error_msg);
  73. } else {
  74. /* Otherwise, the remote side closed the connection normally. */
  75. if (!raw->sent_console_eof && seat_eof(raw->seat)) {
  76. /*
  77. * The front end wants us to close the outgoing side of the
  78. * connection as soon as we see EOF from the far end.
  79. */
  80. if (!raw->sent_socket_eof) {
  81. if (raw->s)
  82. sk_write_eof(raw->s);
  83. raw->sent_socket_eof = true;
  84. }
  85. }
  86. raw->sent_console_eof = true;
  87. raw_check_close(raw);
  88. }
  89. }
  90. static void raw_receive(Plug *plug, int urgent, const char *data, size_t len)
  91. {
  92. Raw *raw = container_of(plug, Raw, plug);
  93. c_write(raw, data, len);
  94. }
  95. static void raw_sent(Plug *plug, size_t bufsize)
  96. {
  97. Raw *raw = container_of(plug, Raw, plug);
  98. raw->bufsize = bufsize;
  99. seat_sent(raw->seat, raw->bufsize);
  100. }
  101. static const PlugVtable Raw_plugvt = {
  102. .log = raw_log,
  103. .closing = raw_closing,
  104. .receive = raw_receive,
  105. .sent = raw_sent,
  106. };
  107. static char *raw_description(Interactor *itr)
  108. {
  109. Raw *raw = container_of(itr, Raw, interactor);
  110. return dupstr(raw->description);
  111. }
  112. static LogPolicy *raw_logpolicy(Interactor *itr)
  113. {
  114. Raw *raw = container_of(itr, Raw, interactor);
  115. return log_get_policy(raw->logctx);
  116. }
  117. static Seat *raw_get_seat(Interactor *itr)
  118. {
  119. Raw *raw = container_of(itr, Raw, interactor);
  120. return raw->seat;
  121. }
  122. static void raw_set_seat(Interactor *itr, Seat *seat)
  123. {
  124. Raw *raw = container_of(itr, Raw, interactor);
  125. raw->seat = seat;
  126. }
  127. static const InteractorVtable Raw_interactorvt = {
  128. .description = raw_description,
  129. .logpolicy = raw_logpolicy,
  130. .get_seat = raw_get_seat,
  131. .set_seat = raw_set_seat,
  132. };
  133. /*
  134. * Called to set up the raw connection.
  135. *
  136. * Returns an error message, or NULL on success.
  137. *
  138. * Also places the canonical host name into `realhost'. It must be
  139. * freed by the caller.
  140. */
  141. static char *raw_init(const BackendVtable *vt, Seat *seat,
  142. Backend **backend_handle, LogContext *logctx,
  143. Conf *conf, const char *host, int port,
  144. char **realhost, bool nodelay, bool keepalive)
  145. {
  146. SockAddr *addr;
  147. const char *err;
  148. Raw *raw;
  149. int addressfamily;
  150. char *loghost;
  151. raw = snew(Raw);
  152. memset(raw, 0, sizeof(Raw));
  153. raw->plug.vt = &Raw_plugvt;
  154. raw->backend.vt = vt;
  155. raw->interactor.vt = &Raw_interactorvt;
  156. raw->backend.interactor = &raw->interactor;
  157. raw->s = NULL;
  158. raw->closed_on_socket_error = false;
  159. *backend_handle = &raw->backend;
  160. raw->sent_console_eof = raw->sent_socket_eof = false;
  161. raw->bufsize = 0;
  162. raw->socket_connected = false;
  163. raw->conf = conf_copy(conf);
  164. raw->description = default_description(vt, host, port);
  165. raw->seat = seat;
  166. raw->logctx = logctx;
  167. addressfamily = conf_get_int(conf, CONF_addressfamily);
  168. /*
  169. * Try to find host.
  170. */
  171. addr = name_lookup(host, port, realhost, conf, addressfamily,
  172. raw->logctx, "main connection");
  173. if ((err = sk_addr_error(addr)) != NULL) {
  174. sk_addr_free(addr);
  175. return dupstr(err);
  176. }
  177. if (port < 0)
  178. port = 23; /* default telnet port */
  179. /*
  180. * Open socket.
  181. */
  182. raw->s = new_connection(addr, *realhost, port, false, true, nodelay,
  183. keepalive, &raw->plug, conf, &raw->interactor);
  184. if ((err = sk_socket_error(raw->s)) != NULL)
  185. return dupstr(err);
  186. /* No local authentication phase in this protocol */
  187. seat_set_trust_status(raw->seat, false);
  188. loghost = conf_get_str(conf, CONF_loghost);
  189. if (*loghost) {
  190. char *colon;
  191. sfree(*realhost);
  192. *realhost = dupstr(loghost);
  193. colon = host_strrchr(*realhost, ':');
  194. if (colon)
  195. *colon++ = '\0';
  196. }
  197. return NULL;
  198. }
  199. static void raw_free(Backend *be)
  200. {
  201. Raw *raw = container_of(be, Raw, backend);
  202. if (is_tempseat(raw->seat))
  203. tempseat_free(raw->seat);
  204. if (raw->s)
  205. sk_close(raw->s);
  206. conf_free(raw->conf);
  207. sfree(raw->description);
  208. sfree(raw);
  209. }
  210. /*
  211. * Stub routine (we don't have any need to reconfigure this backend).
  212. */
  213. static void raw_reconfig(Backend *be, Conf *conf)
  214. {
  215. }
  216. /*
  217. * Called to send data down the raw connection.
  218. */
  219. static void raw_send(Backend *be, const char *buf, size_t len)
  220. {
  221. Raw *raw = container_of(be, Raw, backend);
  222. if (raw->s == NULL)
  223. return;
  224. raw->bufsize = sk_write(raw->s, buf, len);
  225. }
  226. /*
  227. * Called to query the current socket sendability status.
  228. */
  229. static size_t raw_sendbuffer(Backend *be)
  230. {
  231. Raw *raw = container_of(be, Raw, backend);
  232. return raw->bufsize;
  233. }
  234. /*
  235. * Called to set the size of the window
  236. */
  237. static void raw_size(Backend *be, int width, int height)
  238. {
  239. /* Do nothing! */
  240. return;
  241. }
  242. /*
  243. * Send raw special codes. We only handle outgoing EOF here.
  244. */
  245. static void raw_special(Backend *be, SessionSpecialCode code, int arg)
  246. {
  247. Raw *raw = container_of(be, Raw, backend);
  248. if (code == SS_EOF && raw->s) {
  249. if (!raw->sent_socket_eof)
  250. sk_write_eof(raw->s);
  251. raw->sent_socket_eof = true;
  252. raw_check_close(raw);
  253. }
  254. return;
  255. }
  256. /*
  257. * Return a list of the special codes that make sense in this
  258. * protocol.
  259. */
  260. static const SessionSpecial *raw_get_specials(Backend *be)
  261. {
  262. return NULL;
  263. }
  264. static bool raw_connected(Backend *be)
  265. {
  266. Raw *raw = container_of(be, Raw, backend);
  267. return raw->s != NULL;
  268. }
  269. static bool raw_sendok(Backend *be)
  270. {
  271. Raw *raw = container_of(be, Raw, backend);
  272. return raw->socket_connected;
  273. }
  274. static void raw_unthrottle(Backend *be, size_t backlog)
  275. {
  276. Raw *raw = container_of(be, Raw, backend);
  277. sk_set_frozen(raw->s, backlog > RAW_MAX_BACKLOG);
  278. }
  279. static bool raw_ldisc(Backend *be, int option)
  280. {
  281. if (option == LD_EDIT || option == LD_ECHO)
  282. return true;
  283. return false;
  284. }
  285. static void raw_provide_ldisc(Backend *be, Ldisc *ldisc)
  286. {
  287. Raw *raw = container_of(be, Raw, backend);
  288. raw->ldisc = ldisc;
  289. }
  290. static int raw_exitcode(Backend *be)
  291. {
  292. Raw *raw = container_of(be, Raw, backend);
  293. if (raw->s != NULL)
  294. return -1; /* still connected */
  295. else if (raw->closed_on_socket_error)
  296. return INT_MAX; /* a socket error counts as an unclean exit */
  297. else
  298. /* Exit codes are a meaningless concept in the Raw protocol */
  299. return 0;
  300. }
  301. /*
  302. * cfg_info for Raw does nothing at all.
  303. */
  304. static int raw_cfg_info(Backend *be)
  305. {
  306. return 0;
  307. }
  308. const BackendVtable raw_backend = {
  309. .init = raw_init,
  310. .free = raw_free,
  311. .reconfig = raw_reconfig,
  312. .send = raw_send,
  313. .sendbuffer = raw_sendbuffer,
  314. .size = raw_size,
  315. .special = raw_special,
  316. .get_specials = raw_get_specials,
  317. .connected = raw_connected,
  318. .exitcode = raw_exitcode,
  319. .sendok = raw_sendok,
  320. .ldisc_option_state = raw_ldisc,
  321. .provide_ldisc = raw_provide_ldisc,
  322. .unthrottle = raw_unthrottle,
  323. .cfg_info = raw_cfg_info,
  324. .id = "raw",
  325. .displayname_tc = "Raw",
  326. .displayname_lc = "raw",
  327. .protocol = PROT_RAW,
  328. .default_port = 0,
  329. };