~ubuntu-branches/ubuntu/trusty/libssh/trusty

« back to all changes in this revision

Viewing changes to libssh/connect.c

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Bigonville
  • Date: 2009-12-12 14:29:12 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20091212142912-ha5g2iibt6nfnjq8
Tags: 0.4.0-1
* New upstream release.
  - Bump soname
  - Adjust .symbols file
* Readd static library in -dev package
* Let dh_lintian install override file
* debian/README.Debian: Update file
* debian/rules: Add list-missing rule

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 *
4
4
 * This file is part of the SSH Library
5
5
 *
6
 
 * Copyright (c) 2003-2008 by Aris Adamantiadis
 
6
 * Copyright (c) 2003-2009 by Aris Adamantiadis
7
7
 *
8
8
 * The SSH Library is free software; you can redistribute it and/or modify
9
9
 * it under the terms of the GNU Lesser General Public License as published by
26
26
#include <stdio.h>
27
27
#include <stdlib.h>
28
28
#include <string.h>
29
 
#include <unistd.h>
30
29
 
31
30
#ifdef _WIN32
32
 
/* getaddrinfo, freeaddrinfo, getnameinfo */
33
 
#define _WIN32_WINNT 0x0501
 
31
/*
 
32
 * Only use Windows API functions available on Windows 2000 SP4 or later.
 
33
 * The available constants are in <sdkddkver.h>.
 
34
 *  http://msdn.microsoft.com/en-us/library/aa383745.aspx
 
35
 *  http://blogs.msdn.com/oldnewthing/archive/2007/04/11/2079137.aspx
 
36
 */
 
37
#undef _WIN32_WINNT
 
38
#ifdef HAVE_WSPIAPI_H
 
39
#define _WIN32_WINNT 0x0500 /* _WIN32_WINNT_WIN2K */
 
40
#undef NTDDI_VERSION
 
41
#define NTDDI_VERSION 0x05000400 /* NTDDI_WIN2KSP4 */
 
42
#else
 
43
#define _WIN32_WINNT 0x0501 /* _WIN32_WINNT_WINXP */
 
44
#undef NTDDI_VERSION
 
45
#define NTDDI_VERSION 0x05010000 /* NTDDI_WINXP */
 
46
#endif
34
47
 
35
48
#include <winsock2.h>
36
49
#include <ws2tcpip.h>
37
50
 
38
 
#include "wspiapi.h" /* Workaround for w2k systems */
 
51
/* <wspiapi.h> is necessary for getaddrinfo before Windows XP, but it isn't
 
52
 * available on some platforms like MinGW. */
 
53
#ifdef HAVE_WSPIAPI_H
 
54
#include <wspiapi.h>
 
55
#endif
39
56
 
40
57
#else /* _WIN32 */
41
58
 
47
64
#endif /* _WIN32 */
48
65
 
49
66
#include "libssh/priv.h"
 
67
#include "libssh/socket.h"
 
68
#include "libssh/channels.h"
 
69
#include "libssh/session.h"
50
70
 
51
71
#ifndef HAVE_SELECT
52
72
#error "Your system must have select()"
56
76
#error "Your system must have getaddrinfo()"
57
77
#endif
58
78
 
 
79
#ifdef HAVE_REGCOMP
 
80
/* don't declare gnu extended regexp's */
 
81
#ifndef _POSIX_C_SOURCE
 
82
#define _POSIX_C_SOURCE
 
83
#endif
 
84
#include <regex.h>
 
85
#endif /* HAVE_REGCOMP */
 
86
 
59
87
#ifdef _WIN32
60
88
static void sock_set_nonblocking(socket_t sock) {
61
89
  u_long nonblocking = 1;
85
113
static void sock_set_blocking(socket_t sock) {
86
114
  fcntl(sock, F_SETFL, 0);
87
115
}
 
116
 
88
117
#endif /* _WIN32 */
89
118
 
90
 
static int getai(const char *host, int port, struct addrinfo **ai) {
 
119
#ifdef HAVE_REGCOMP
 
120
static regex_t *ip_regex = NULL;
 
121
 
 
122
/** @internal
 
123
 * @brief initializes and compile the regexp to be used for IP matching
 
124
 * @returns -1 on error (and error message is set)
 
125
 * @returns 0 on success
 
126
 */
 
127
int ssh_regex_init(){
 
128
  if(ip_regex==NULL){
 
129
    int err;
 
130
    regex_t *regex=malloc(sizeof (regex_t));
 
131
    ZERO_STRUCTP(regex);
 
132
    err=regcomp(regex,"^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$",REG_EXTENDED | REG_NOSUB);
 
133
    if(err != 0){
 
134
      char buffer[128];
 
135
      regerror(err,regex,buffer,sizeof(buffer));
 
136
      fprintf(stderr,"Error while compiling regular expression : %s\n",buffer);
 
137
      SAFE_FREE(regex);
 
138
      return -1;
 
139
    }
 
140
    ip_regex=regex;
 
141
  }
 
142
  return 0;
 
143
}
 
144
 
 
145
/** @internal
 
146
 * @brief clean up the IP regexp
 
147
 */
 
148
void ssh_regex_finalize(){
 
149
  if(ip_regex){
 
150
    regfree(ip_regex);
 
151
    SAFE_FREE(ip_regex);
 
152
  }
 
153
}
 
154
 
 
155
#else /* HAVE_REGCOMP */
 
156
int ssh_regex_init(){
 
157
  return 0;
 
158
}
 
159
void ssh_regex_finalize(){
 
160
}
 
161
#endif
 
162
 
 
163
 
 
164
static int ssh_connect_socket_close(socket_t s){
 
165
#ifdef _WIN32
 
166
  return closesocket(s);
 
167
#else
 
168
  return close(s);
 
169
#endif
 
170
}
 
171
 
 
172
 
 
173
static int getai(ssh_session session, const char *host, int port, struct addrinfo **ai) {
91
174
  const char *service = NULL;
92
175
  struct addrinfo hints;
93
176
  char s_port[10];
103
186
  } else {
104
187
    snprintf(s_port, sizeof(s_port), "%hu", port);
105
188
    service = s_port;
106
 
  }
107
 
 
 
189
#ifdef AI_NUMERICSERV
 
190
    hints.ai_flags=AI_NUMERICSERV;
 
191
#endif
 
192
  }
 
193
#ifdef HAVE_REGCOMP
 
194
  if(regexec(ip_regex,host,0,NULL,0) == 0){
 
195
    /* this is an IP address */
 
196
    ssh_log(session,SSH_LOG_PACKET,"host %s matches an IP address",host);
 
197
    hints.ai_flags |= AI_NUMERICHOST;
 
198
  }
 
199
#endif
108
200
  return getaddrinfo(host, service, &hints, ai);
109
201
}
110
202
 
111
 
static int ssh_connect_ai_timeout(SSH_SESSION *session, const char *host,
 
203
static int ssh_connect_ai_timeout(ssh_session session, const char *host,
112
204
    int port, struct addrinfo *ai, long timeout, long usec, socket_t s) {
113
205
  struct timeval to;
114
206
  fd_set set;
122
214
 
123
215
  sock_set_nonblocking(s);
124
216
 
 
217
  ssh_log(session, SSH_LOG_RARE, "Trying to connect to host: %s:%d with "
 
218
      "timeout %ld.%ld", host, port, timeout, usec);
 
219
 
125
220
  /* The return value is checked later */
126
221
  connect(s, ai->ai_addr, ai->ai_addrlen);
127
222
  freeaddrinfo(ai);
134
229
    /* timeout */
135
230
    ssh_set_error(session, SSH_FATAL,
136
231
        "Timeout while connecting to %s:%d", host, port);
137
 
    close(s);
 
232
    ssh_connect_socket_close(s);
138
233
    leave_function();
139
234
    return -1;
140
235
  }
142
237
  if (rc < 0) {
143
238
    ssh_set_error(session, SSH_FATAL,
144
239
        "Select error: %s", strerror(errno));
145
 
    close(s);
 
240
    ssh_connect_socket_close(s);
146
241
    leave_function();
147
242
    return -1;
148
243
  }
153
248
  if (rc != 0) {
154
249
    ssh_set_error(session, SSH_FATAL,
155
250
        "Connect to %s:%d failed: %s", host, port, strerror(rc));
156
 
    close(s);
 
251
    ssh_connect_socket_close(s);
157
252
    leave_function();
158
253
    return -1;
159
254
  }
174
269
 *
175
270
 * @returns A file descriptor, < 0 on error.
176
271
 */
177
 
socket_t ssh_connect_host(SSH_SESSION *session, const char *host,
 
272
socket_t ssh_connect_host(ssh_session session, const char *host,
178
273
    const char *bind_addr, int port, long timeout, long usec) {
179
274
  socket_t s = -1;
180
275
  int rc;
183
278
 
184
279
  enter_function();
185
280
 
186
 
  rc = getai(host, port, &ai);
 
281
  rc = getai(session,host, port, &ai);
187
282
  if (rc != 0) {
188
283
    ssh_set_error(session, SSH_FATAL,
189
284
        "Failed to resolve hostname %s (%s)", host, gai_strerror(rc));
206
301
 
207
302
      ssh_log(session, SSH_LOG_PACKET, "Resolving %s\n", bind_addr);
208
303
 
209
 
      rc = getai(host, 0, &bind_ai);
 
304
      rc = getai(session,bind_addr, 0, &bind_ai);
210
305
      if (rc != 0) {
211
306
        ssh_set_error(session, SSH_FATAL,
212
307
            "Failed to resolve bind address %s (%s)",
229
324
 
230
325
      /* Cannot bind to any local addresses */
231
326
      if (bind_itr == NULL) {
232
 
        close(s);
 
327
        ssh_connect_socket_close(s);
233
328
        s = -1;
234
329
        continue;
235
330
      }
244
339
 
245
340
    if (connect(s, itr->ai_addr, itr->ai_addrlen) < 0) {
246
341
      ssh_set_error(session, SSH_FATAL, "Connect failed: %s", strerror(errno));
247
 
      close(s);
 
342
      ssh_connect_socket_close(s);
248
343
      s = -1;
249
344
      leave_function();
250
345
      continue;
292
387
 *
293
388
 * @see select(2)
294
389
 */
295
 
int ssh_select(CHANNEL **channels, CHANNEL **outchannels, socket_t maxfd,
 
390
int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
296
391
    fd_set *readfds, struct timeval *timeout) {
297
392
  struct timeval zerotime;
298
393
  fd_set localset, localset2;