Bug Summary

File:obj-scan-build/libftpconn/../../libftpconn/xfer.c
Location:line 42, column 37
Description:Result of 'malloc' is converted to a pointer of type 'struct sockaddr', which is incompatible with sizeof operand type 'struct sockaddr_in'

Annotated Source Code

1/* Start/stop data channel transfer
2
3 Copyright (C) 1997,2002 Free Software Foundation, Inc.
4 Written by Miles Bader <miles@gnu.org>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2, or (at
9 your option) any later version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include <unistd.h>
21#include <errno(*__errno_location ()).h>
22#include <string.h>
23#include <netinet/in.h>
24
25#include <ftpconn.h>
26#include "priv.h"
27
28/* Open an active data connection, returning the file descriptor in DATA. */
29static error_t
30ftp_conn_start_open_actv_data (struct ftp_conn *conn, int *data)
31{
32 error_t err = 0;
33 /* DCQ is a socket on which to listen for data connections from the server. */
34 int dcq;
35 struct sockaddr *addr = conn->actv_data_addr;
36 socklen_t addr_len = sizeof *addr;
37
38 if (! addr)
39 /* Generate an address for the data connection (which we must know,
40 so we can tell the server). */
41 {
42 addr = conn->actv_data_addr = malloc (sizeof (struct sockaddr_in));
Result of 'malloc' is converted to a pointer of type 'struct sockaddr', which is incompatible with sizeof operand type 'struct sockaddr_in'
43 if (! addr)
44 return ENOMEM((0x10 << 26) | ((12) & 0x3fff));
45
46 /* Get the local address chosen by the system. */
47 if (conn->control < 0)
48 err = EBADF((0x10 << 26) | ((9) & 0x3fff));
49 else if (getsockname (conn->control, addr, &addr_len) < 0)
50 err = errno(*__errno_location ());
51
52 if (err == EBADF((0x10 << 26) | ((9) & 0x3fff)) || err == EPIPE((0x10 << 26) | ((32) & 0x3fff)))
53 /* Control connection has closed; reopen it and try again. */
54 {
55 err = ftp_conn_open (conn);
56 if (!err && getsockname (conn->control, addr, &addr_len) < 0)
57 err = errno(*__errno_location ());
58 }
59
60 if (err)
61 {
62 free (addr);
63 conn->actv_data_addr = 0;
64 return err;
65 }
66 }
67
68 dcq = socket (AF_INET2, SOCK_STREAMSOCK_STREAM, 0);
69 if (dcq < 0)
70 return errno(*__errno_location ());
71
72 /* Let the system choose a port for us. */
73 ((struct sockaddr_in *)addr)->sin_port = 0;
74
75 /* Use ADDR as the data socket's local address. */
76 if (!err && bind (dcq, addr, addr_len) < 0)
77 err = errno(*__errno_location ());
78
79 /* See what port was chosen by the system. */
80 if (!err && getsockname (dcq, addr, &addr_len) < 0)
81 err = errno(*__errno_location ());
82
83 /* Set the incoming connection queue length. */
84 if (!err && listen (dcq, 1) < 0)
85 err = errno(*__errno_location ());
86
87 if (err)
88 close (dcq);
89 else
90 err = ftp_conn_send_actv_addr (conn, conn->actv_data_addr);
91
92 if (! err)
93 *data = dcq;
94
95 return err;
96}
97
98/* Finish opening the active data connection *DATA opened with
99 ftp_conn_start_open_actv_data, following the sending of the command that
100 uses the connection to the server. This function closes the file
101 descriptor in *DATA, and returns a new file descriptor for the actual data
102 connection. */
103static error_t
104ftp_conn_finish_open_actv_data (struct ftp_conn *conn, int *data)
105{
106 struct sockaddr_in rmt_addr;
107 socklen_t rmt_addr_len = sizeof rmt_addr;
108 int real = accept (*data, &rmt_addr, &rmt_addr_len);
109
110 close (*data);
111
112 if (real < 0)
113 return errno(*__errno_location ());
114
115 *data = real;
116
117 return 0;
118}
119
120/* Abort an active data connection open sequence; this function should be
121 called if ftp_conn_start_open_actv_data succeeds, but an error happens
122 before ftp_conn_finish_open_actv_data can be called. */
123static void
124ftp_conn_abort_open_actv_data (struct ftp_conn *conn, int data)
125{
126 close (data);
127}
128
129/* Return a data connection, which may not be in a completely open state;
130 this call should be followed by the command that uses the connection, and
131 a call to ftp_conn_finish_open_data, if that succeeds. */
132static error_t
133ftp_conn_start_open_data (struct ftp_conn *conn, int *data)
134{
135 error_t err;
136
137 if (conn->use_passive)
138 /* First try a passive connection. */
139 {
140 struct sockaddr *addr;
141
142 /* Tell the server we wan't to use passive mode, for which it should
143 give us an address to connect to. */
144 err = ftp_conn_get_pasv_addr (conn, &addr);
145
146 if (! err)
147 {
148 int dsock = socket (PF_INET2, SOCK_STREAMSOCK_STREAM, 0);
149
150 if (dsock < 0)
151 err = errno(*__errno_location ());
152 else if (connect (dsock, addr, addr->sa_len) < 0)
153 {
154 err = errno(*__errno_location ());
155 close (dsock);
156 }
157 else
158 *data = dsock;
159
160 free (addr);
161 }
162 }
163 else
164 err = EAGAIN((0x10 << 26) | ((35) & 0x3fff));
165
166 if (err)
167 /* Using a passive connection didn't work, try an active one. */
168 {
169 conn->use_passive = 0; /* Don't try again. */
170 err = ftp_conn_start_open_actv_data (conn, data);
171 }
172
173 return err;
174}
175
176/* Finish opening the data connection *DATA opened with
177 ftp_conn_start_open_data, following the sending of the command that uses
178 the connection to the server. This function may change *DATA, in which
179 case the old file descriptor is closed. */
180static error_t
181ftp_conn_finish_open_data (struct ftp_conn *conn, int *data)
182{
183 if (conn->use_passive)
184 /* Passive connections should already have been completely opened. */
185 return 0;
186 else
187 return ftp_conn_finish_open_actv_data (conn, data);
188}
189
190/* Abort a data connection open sequence; this function should be called if
191 ftp_conn_start_open_data succeeds, but an error happens before
192 ftp_conn_finish_open_data can be called. */
193static void
194ftp_conn_abort_open_data (struct ftp_conn *conn, int data)
195{
196 if (conn->use_passive)
197 close (data);
198 else
199 return ftp_conn_abort_open_actv_data (conn, data);
200}
201
202/* Start a transfer command CMD/ARG, returning a file descriptor in DATA.
203 POSS_ERRS is a list of errnos to try matching against any resulting error
204 text. */
205error_t
206ftp_conn_start_transfer (struct ftp_conn *conn,
207 const char *cmd, const char *arg,
208 const error_t *poss_errs,
209 int *data)
210{
211 error_t err = ftp_conn_start_open_data (conn, data);
212
213 if (! err)
214 {
215 int reply;
216 const char *txt;
217
218 err = ftp_conn_cmd (conn, cmd, arg, &reply, &txt);
219 if (!err && !REPLY_IS_PRELIM (reply)((reply) >= 100 && (reply) < 200))
220 err = unexpected_reply (conn, reply, txt, poss_errs);
221
222 if (err)
223 ftp_conn_abort_open_data (conn, *data);
224 else
225 err = ftp_conn_finish_open_data (conn, data);
226 }
227
228 return err;
229}
230
231/* Wait for the reply signalling the end of a data transfer. */
232error_t
233ftp_conn_finish_transfer (struct ftp_conn *conn)
234{
235 int reply;
236 error_t err = ftp_conn_get_reply (conn, &reply, 0);
237 if (!err && reply != REPLY_TRANS_OK226 && reply != REPLY_FCMD_OK250)
238 err = unexpected_reply (conn, reply, 0, 0);
239 return err;
240}
241
242/* Start retreiving file NAME over CONN, returning a file descriptor in DATA
243 over which the data can be read. */
244error_t
245ftp_conn_start_retrieve (struct ftp_conn *conn, const char *name, int *data)
246{
247 if (! name)
248 return EINVAL((0x10 << 26) | ((22) & 0x3fff));
249 return
250 ftp_conn_start_transfer (conn, "retr", name, ftp_conn_poss_file_errs, data);
251}
252
253/* Start retreiving a list of files in NAME over CONN, returning a file
254 descriptor in DATA over which the data can be read. */
255error_t
256ftp_conn_start_list (struct ftp_conn *conn, const char *name, int *data)
257{
258 return
259 ftp_conn_start_transfer (conn, "nlst", name, ftp_conn_poss_file_errs, data);
260}
261
262/* Start retreiving a directory listing of NAME over CONN, returning a file
263 descriptor in DATA over which the data can be read. */
264error_t
265ftp_conn_start_dir (struct ftp_conn *conn, const char *name, int *data)
266{
267 return
268 ftp_conn_start_transfer (conn, "list", name, ftp_conn_poss_file_errs, data);
269}
270
271/* Start storing into file NAME over CONN, returning a file descriptor in DATA
272 into which the data can be written. */
273error_t
274ftp_conn_start_store (struct ftp_conn *conn, const char *name, int *data)
275{
276 if (! name)
277 return EINVAL((0x10 << 26) | ((22) & 0x3fff));
278 return
279 ftp_conn_start_transfer (conn, "stor", name, ftp_conn_poss_file_errs, data);
280}