]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - portfwd.c
Miscellaneous fixes to finish up `remove-statics'. rlogin.c had a
[PuTTY.git] / portfwd.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include "putty.h"
5 #include "ssh.h"
6
7 #ifndef FALSE
8 #define FALSE 0
9 #endif
10 #ifndef TRUE
11 #define TRUE 1
12 #endif
13
14 #define GET_32BIT_LSB_FIRST(cp) \
15   (((unsigned long)(unsigned char)(cp)[0]) | \
16   ((unsigned long)(unsigned char)(cp)[1] << 8) | \
17   ((unsigned long)(unsigned char)(cp)[2] << 16) | \
18   ((unsigned long)(unsigned char)(cp)[3] << 24))
19
20 #define PUT_32BIT_LSB_FIRST(cp, value) ( \
21   (cp)[0] = (value), \
22   (cp)[1] = (value) >> 8, \
23   (cp)[2] = (value) >> 16, \
24   (cp)[3] = (value) >> 24 )
25
26 #define GET_16BIT_LSB_FIRST(cp) \
27   (((unsigned long)(unsigned char)(cp)[0]) | \
28   ((unsigned long)(unsigned char)(cp)[1] << 8))
29
30 #define PUT_16BIT_LSB_FIRST(cp, value) ( \
31   (cp)[0] = (value), \
32   (cp)[1] = (value) >> 8 )
33
34 #define GET_32BIT_MSB_FIRST(cp) \
35   (((unsigned long)(unsigned char)(cp)[0] << 24) | \
36   ((unsigned long)(unsigned char)(cp)[1] << 16) | \
37   ((unsigned long)(unsigned char)(cp)[2] << 8) | \
38   ((unsigned long)(unsigned char)(cp)[3]))
39
40 #define PUT_32BIT_MSB_FIRST(cp, value) ( \
41   (cp)[0] = (value) >> 24, \
42   (cp)[1] = (value) >> 16, \
43   (cp)[2] = (value) >> 8, \
44   (cp)[3] = (value) )
45
46 #define GET_16BIT_MSB_FIRST(cp) \
47   (((unsigned long)(unsigned char)(cp)[0] << 8) | \
48   ((unsigned long)(unsigned char)(cp)[1]))
49
50 #define PUT_16BIT_MSB_FIRST(cp, value) ( \
51   (cp)[0] = (value) >> 8, \
52   (cp)[1] = (value) )
53
54 struct pfwd_queue {
55     struct pfwd_queue *next;
56     char *buf;
57 };
58
59 struct PFwdPrivate {
60     const struct plug_function_table *fn;
61     /* the above variable absolutely *must* be the first in this structure */
62     void *c;                           /* (channel) data used by ssh.c */
63     void *backhandle;                  /* instance of SSH backend itself */
64     /* Note that backhandle need not be filled in if c is non-NULL */
65     Socket s;
66     char hostname[128];
67     int throttled, throttle_override;
68     int port;
69     int ready;
70     struct pfwd_queue *waiting;
71 };
72
73
74 static int pfd_closing(Plug plug, char *error_msg, int error_code,
75                        int calling_back)
76 {
77     struct PFwdPrivate *pr = (struct PFwdPrivate *) plug;
78
79     /*
80      * We have no way to communicate down the forwarded connection,
81      * so if an error occurred on the socket, we just ignore it
82      * and treat it like a proper close.
83      */
84     sshfwd_close(pr->c);
85     pfd_close(pr->s);
86     return 1;
87 }
88
89 static int pfd_receive(Plug plug, int urgent, char *data, int len)
90 {
91     struct PFwdPrivate *pr = (struct PFwdPrivate *) plug;
92     if (pr->ready) {
93         if (sshfwd_write(pr->c, data, len) > 0) {
94             pr->throttled = 1;
95             sk_set_frozen(pr->s, 1);
96         }
97     }
98     return 1;
99 }
100
101 static void pfd_sent(Plug plug, int bufsize)
102 {
103     struct PFwdPrivate *pr = (struct PFwdPrivate *) plug;
104
105     sshfwd_unthrottle(pr->c, bufsize);
106 }
107
108 /*
109  * Called when receiving a PORT OPEN from the server
110  */
111 char *pfd_newconnect(Socket *s, char *hostname, int port, void *c,
112                      const Config *cfg)
113 {
114     static const struct plug_function_table fn_table = {
115         pfd_closing,
116         pfd_receive,
117         pfd_sent,
118         NULL
119     };
120
121     SockAddr addr;
122     char *err, *dummy_realhost;
123     struct PFwdPrivate *pr;
124
125     /*
126      * Try to find host.
127      */
128     addr = name_lookup(hostname, port, &dummy_realhost, cfg);
129     if ((err = sk_addr_error(addr)) != NULL)
130         return err;
131
132     /*
133      * Open socket.
134      */
135     pr = (struct PFwdPrivate *) smalloc(sizeof(struct PFwdPrivate));
136     pr->fn = &fn_table;
137     pr->throttled = pr->throttle_override = 0;
138     pr->ready = 1;
139     pr->c = c;
140     pr->backhandle = NULL;             /* we shouldn't need this */
141
142     pr->s = *s = new_connection(addr, dummy_realhost, port,
143                                 0, 1, 0, (Plug) pr, cfg);
144     if ((err = sk_socket_error(*s)) != NULL) {
145         sfree(pr);
146         return err;
147     }
148
149     sk_set_private_ptr(*s, pr);
150     sk_addr_free(addr);
151     return NULL;
152 }
153
154 /*
155  called when someone connects to the local port
156  */
157
158 static int pfd_accepting(Plug p, void *sock)
159 {
160     static const struct plug_function_table fn_table = {
161         pfd_closing,
162         pfd_receive,
163         pfd_sent,
164         NULL
165     };
166     struct PFwdPrivate *pr, *org;
167     Socket s;
168     char *err;
169
170     org = (struct PFwdPrivate *)p;
171     pr = (struct PFwdPrivate *) smalloc(sizeof(struct PFwdPrivate));
172     pr->fn = &fn_table;
173
174     pr->c = NULL;
175     pr->backhandle = org->backhandle;
176
177     pr->s = s = sk_register(sock, (Plug) pr);
178     if ((err = sk_socket_error(s)) != NULL) {
179         sfree(pr);
180         return err != NULL;
181     }
182
183     pr->c = new_sock_channel(org->backhandle, s);
184
185     strcpy(pr->hostname, org->hostname);
186     pr->port = org->port;
187     pr->throttled = pr->throttle_override = 0;
188     pr->ready = 0;
189     pr->waiting = NULL;
190
191     sk_set_private_ptr(s, pr);
192
193     if (pr->c == NULL) {
194         sfree(pr);
195         return 1;
196     } else {
197         /* asks to forward to the specified host/port for this */
198         ssh_send_port_open(pr->c, pr->hostname, pr->port, "forwarding");
199     }
200
201     return 0;
202 }
203
204
205 /* Add a new forwarding from port -> desthost:destport
206  sets up a listener on the local machine on (srcaddr:)port
207  */
208 char *pfd_addforward(char *desthost, int destport, char *srcaddr, int port,
209                      void *backhandle, const Config *cfg)
210 {
211     static const struct plug_function_table fn_table = {
212         pfd_closing,
213         pfd_receive,                   /* should not happen... */
214         pfd_sent,                      /* also should not happen */
215         pfd_accepting
216     };
217
218     char *err;
219     struct PFwdPrivate *pr;
220     Socket s;
221
222     /*
223      * Open socket.
224      */
225     pr = (struct PFwdPrivate *) smalloc(sizeof(struct PFwdPrivate));
226     pr->fn = &fn_table;
227     pr->c = NULL;
228     strcpy(pr->hostname, desthost);
229     pr->port = destport;
230     pr->throttled = pr->throttle_override = 0;
231     pr->ready = 0;
232     pr->waiting = NULL;
233     pr->backhandle = backhandle;
234
235     pr->s = s = new_listener(srcaddr, port, (Plug) pr,
236                              !cfg->lport_acceptall, cfg);
237     if ((err = sk_socket_error(s)) != NULL) {
238         sfree(pr);
239         return err;
240     }
241
242     sk_set_private_ptr(s, pr);
243
244     return NULL;
245 }
246
247 void pfd_close(Socket s)
248 {
249     struct PFwdPrivate *pr;
250
251     if (!s)
252         return;
253
254     pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
255
256     sfree(pr);
257
258     sk_close(s);
259 }
260
261 void pfd_unthrottle(Socket s)
262 {
263     struct PFwdPrivate *pr;
264     if (!s)
265         return;
266     pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
267
268     pr->throttled = 0;
269     sk_set_frozen(s, pr->throttled || pr->throttle_override);
270 }
271
272 void pfd_override_throttle(Socket s, int enable)
273 {
274     struct PFwdPrivate *pr;
275     if (!s)
276         return;
277     pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
278
279     pr->throttle_override = enable;
280     sk_set_frozen(s, pr->throttled || pr->throttle_override);
281 }
282
283 /*
284  * Called to send data down the raw connection.
285  */
286 int pfd_send(Socket s, char *data, int len)
287 {
288     if (s == NULL)
289         return 0;
290     return sk_write(s, data, len);
291 }
292
293
294 void pfd_confirm(Socket s)
295 {
296     struct PFwdPrivate *pr;
297
298     if (s == NULL)
299         return;
300
301     pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
302     pr->ready = 1;
303     sk_set_frozen(s, 0);
304     sk_write(s, NULL, 0);
305 }