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