blob: 2038ee46c1fb66d4e489d3de73a2cc3ae192cd23 [file] [log] [blame]
njneb8896b2005-06-04 20:03:55 +00001
2/*--------------------------------------------------------------------*/
3/*--- File- and socket-related libc stuff. m_libcfile.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj9ebd6e02007-01-08 06:01:59 +000010 Copyright (C) 2000-2007 Julian Seward
njneb8896b2005-06-04 20:03:55 +000011 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000032#include "pub_core_vki.h"
sewardj9a66bb92006-10-17 01:38:13 +000033#include "pub_core_vkiscnums.h"
sewardj26b87282006-10-17 12:49:31 +000034#include "pub_core_debuglog.h"
njneb8896b2005-06-04 20:03:55 +000035#include "pub_core_libcbase.h"
36#include "pub_core_libcassert.h"
37#include "pub_core_libcfile.h"
sewardjfdf91b42005-09-28 00:53:09 +000038#include "pub_core_libcprint.h" // VG_(sprintf)
sewardj45f4e7c2005-09-27 19:20:21 +000039#include "pub_core_libcproc.h" // VG_(getpid), VG_(getppid)
sewardj14c7cc52007-02-25 15:08:24 +000040#include "pub_core_xarray.h"
sewardjfdf91b42005-09-28 00:53:09 +000041#include "pub_core_clientstate.h" // VG_(fd_hard_limit)
njn9abd6082005-06-17 21:31:45 +000042#include "pub_core_syscall.h"
njneb8896b2005-06-04 20:03:55 +000043
44/* ---------------------------------------------------------------------
45 File stuff
46 ------------------------------------------------------------------ */
47
48static inline Bool fd_exists(Int fd)
49{
50 struct vki_stat st;
51
52 return VG_(fstat)(fd, &st) == 0;
53}
54
55/* Move an fd into the Valgrind-safe range */
56Int VG_(safe_fd)(Int oldfd)
57{
58 Int newfd;
59
60 vg_assert(VG_(fd_hard_limit) != -1);
61
62 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
63 if (newfd != -1)
64 VG_(close)(oldfd);
65
sewardj9a66bb92006-10-17 01:38:13 +000066 /* Set the close-on-exec flag for this fd. */
njneb8896b2005-06-04 20:03:55 +000067 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
68
69 vg_assert(newfd >= VG_(fd_hard_limit));
70 return newfd;
71}
72
njnae7359b2005-06-19 21:10:42 +000073/* Given a file descriptor, attempt to deduce its filename. To do
74 this, we use /proc/self/fd/<FD>. If this doesn't point to a file,
njnf845f8f2005-06-23 02:26:47 +000075 or if it doesn't exist, we return False. */
76Bool VG_(resolve_filename) ( Int fd, HChar* buf, Int n_buf )
njnae7359b2005-06-19 21:10:42 +000077{
78 HChar tmp[64];
79
80 VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
njnf845f8f2005-06-23 02:26:47 +000081 VG_(memset)(buf, 0, n_buf);
njnae7359b2005-06-19 21:10:42 +000082
sewardj45f4e7c2005-09-27 19:20:21 +000083 if (VG_(readlink)(tmp, buf, n_buf) > 0 && buf[0] == '/')
njnf845f8f2005-06-23 02:26:47 +000084 return True;
85 else
86 return False;
njnae7359b2005-06-19 21:10:42 +000087}
88
sewardj92645592005-07-23 09:18:34 +000089SysRes VG_(open) ( const Char* pathname, Int flags, Int mode )
njneb8896b2005-06-04 20:03:55 +000090{
sewardja8d8e232005-06-07 20:04:56 +000091 SysRes res = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode);
sewardj92645592005-07-23 09:18:34 +000092 return res;
njneb8896b2005-06-04 20:03:55 +000093}
94
95void VG_(close) ( Int fd )
96{
sewardja8d8e232005-06-07 20:04:56 +000097 (void)VG_(do_syscall1)(__NR_close, fd);
njneb8896b2005-06-04 20:03:55 +000098}
99
100Int VG_(read) ( Int fd, void* buf, Int count)
101{
sewardj9a66bb92006-10-17 01:38:13 +0000102 Int ret;
sewardja8d8e232005-06-07 20:04:56 +0000103 SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
sewardj9a66bb92006-10-17 01:38:13 +0000104 if (res.isError) {
105 ret = - (Int)(Word)res.err;
106 vg_assert(ret < 0);
107 } else {
108 ret = (Int)(Word)res.res;
109 vg_assert(ret >= 0);
110 }
111 return ret;
njneb8896b2005-06-04 20:03:55 +0000112}
113
114Int VG_(write) ( Int fd, const void* buf, Int count)
115{
sewardj9a66bb92006-10-17 01:38:13 +0000116 Int ret;
sewardja8d8e232005-06-07 20:04:56 +0000117 SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
sewardj9a66bb92006-10-17 01:38:13 +0000118 if (res.isError) {
119 ret = - (Int)(Word)res.err;
120 vg_assert(ret < 0);
121 } else {
122 ret = (Int)(Word)res.res;
123 vg_assert(ret >= 0);
124 }
125 return ret;
njneb8896b2005-06-04 20:03:55 +0000126}
127
128Int VG_(pipe) ( Int fd[2] )
129{
sewardja8d8e232005-06-07 20:04:56 +0000130 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
131 return res.isError ? -1 : 0;
njneb8896b2005-06-04 20:03:55 +0000132}
133
sewardj45f4e7c2005-09-27 19:20:21 +0000134OffT VG_(lseek) ( Int fd, OffT offset, Int whence )
njneb8896b2005-06-04 20:03:55 +0000135{
sewardja8d8e232005-06-07 20:04:56 +0000136 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
sewardj9a66bb92006-10-17 01:38:13 +0000137 return res.isError ? (-1) : res.res;
sewardj45f4e7c2005-09-27 19:20:21 +0000138 /* if you change the error-reporting conventions of this, also
139 change VG_(pread) and all other usage points. */
njneb8896b2005-06-04 20:03:55 +0000140}
141
tom6c93c4f2005-08-05 07:46:32 +0000142SysRes VG_(stat) ( Char* file_name, struct vki_stat* buf )
njneb8896b2005-06-04 20:03:55 +0000143{
sewardj9a66bb92006-10-17 01:38:13 +0000144# if defined(VGO_linux)
sewardja8d8e232005-06-07 20:04:56 +0000145 SysRes res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)buf);
tom6c93c4f2005-08-05 07:46:32 +0000146 return res;
sewardj9a66bb92006-10-17 01:38:13 +0000147# elif defined(VGO_aix5)
148 SysRes res = VG_(do_syscall4)(__NR_AIX5_statx,
149 (UWord)file_name,
150 (UWord)buf,
151 sizeof(struct vki_stat),
152 VKI_STX_NORMAL);
153 return res;
154# else
155# error Unknown OS
156# endif
njneb8896b2005-06-04 20:03:55 +0000157}
158
159Int VG_(fstat) ( Int fd, struct vki_stat* buf )
160{
sewardj9a66bb92006-10-17 01:38:13 +0000161# if defined(VGO_linux)
sewardja8d8e232005-06-07 20:04:56 +0000162 SysRes res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf);
163 return res.isError ? (-1) : 0;
sewardj9a66bb92006-10-17 01:38:13 +0000164# elif defined(VGO_aix5)
165 I_die_here;
166# else
167# error Unknown OS
168# endif
njneb8896b2005-06-04 20:03:55 +0000169}
170
sewardj45f4e7c2005-09-27 19:20:21 +0000171Int VG_(fsize) ( Int fd )
njneb8896b2005-06-04 20:03:55 +0000172{
sewardj9a66bb92006-10-17 01:38:13 +0000173# if defined(VGO_linux) && defined(__NR_fstat64)
tom574b8932006-07-05 17:47:46 +0000174 struct vki_stat64 buf;
175 SysRes res = VG_(do_syscall2)(__NR_fstat64, fd, (UWord)&buf);
sewardj9a66bb92006-10-17 01:38:13 +0000176 return res.isError ? (-1) : buf.st_size;
177# elif defined(VGO_linux) && !defined(__NR_fstat64)
sewardj45f4e7c2005-09-27 19:20:21 +0000178 struct vki_stat buf;
179 SysRes res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)&buf);
180 return res.isError ? (-1) : buf.st_size;
sewardj9a66bb92006-10-17 01:38:13 +0000181# elif defined(VGO_aix5)
182 I_die_here;
183# else
184# error Unknown OS
185# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000186}
187
njn73750612005-10-14 03:11:30 +0000188Bool VG_(is_dir) ( HChar* f )
189{
190 struct vki_stat buf;
sewardj9a66bb92006-10-17 01:38:13 +0000191 SysRes res = VG_(stat)(f, &buf);
njn73750612005-10-14 03:11:30 +0000192 return res.isError ? False
193 : VKI_S_ISDIR(buf.st_mode) ? True : False;
194}
195
sewardj45f4e7c2005-09-27 19:20:21 +0000196SysRes VG_(dup) ( Int oldfd )
197{
198 return VG_(do_syscall1)(__NR_dup, oldfd);
njneb8896b2005-06-04 20:03:55 +0000199}
200
njn327fe8a2005-06-12 02:49:35 +0000201/* Returns -1 on error. */
202Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
203{
204 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
sewardj9a66bb92006-10-17 01:38:13 +0000205 return res.isError ? -1 : res.res;
njn327fe8a2005-06-12 02:49:35 +0000206}
207
njneb8896b2005-06-04 20:03:55 +0000208Int VG_(rename) ( Char* old_name, Char* new_name )
209{
sewardja8d8e232005-06-07 20:04:56 +0000210 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
211 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000212}
213
214Int VG_(unlink) ( Char* file_name )
215{
sewardja8d8e232005-06-07 20:04:56 +0000216 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
217 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000218}
219
njn57ca7ab2005-06-21 23:44:58 +0000220Bool VG_(getcwd) ( Char* buf, SizeT size )
njneb8896b2005-06-04 20:03:55 +0000221{
sewardj9a66bb92006-10-17 01:38:13 +0000222# if defined(VGO_linux)
sewardja8d8e232005-06-07 20:04:56 +0000223 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000224 vg_assert(buf != NULL);
225 res = VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size);
njn57ca7ab2005-06-21 23:44:58 +0000226 return res.isError ? False : True;
sewardj9a66bb92006-10-17 01:38:13 +0000227# elif defined(VGO_aix5)
228 static Int complaints = 3;
229 if (complaints-- > 0)
230 VG_(debugLog)(0, "libcfile",
231 "Warning: AIX5: m_libcfile.c: kludged 'getcwd'\n");
232 if (size < 2) return False;
233 buf[0] = '.';
234 buf[1] = 0;
235 return True;
236# else
237# error Unknown OS
238# endif
njneb8896b2005-06-04 20:03:55 +0000239}
240
241Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
242{
sewardja8d8e232005-06-07 20:04:56 +0000243 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000244 /* res = readlink( path, buf, bufsiz ); */
245 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
sewardj9a66bb92006-10-17 01:38:13 +0000246 return res.isError ? -1 : res.res;
njneb8896b2005-06-04 20:03:55 +0000247}
248
249Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
250{
sewardja8d8e232005-06-07 20:04:56 +0000251 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000252 /* res = getdents( fd, dirp, count ); */
253 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
sewardj9a66bb92006-10-17 01:38:13 +0000254 return res.isError ? -1 : res.res;
njneb8896b2005-06-04 20:03:55 +0000255}
256
sewardj45f4e7c2005-09-27 19:20:21 +0000257/* Check accessibility of a file. Returns zero for access granted,
258 nonzero otherwise. */
259Int VG_(access) ( HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
260{
sewardj9a66bb92006-10-17 01:38:13 +0000261# if defined(VGO_linux)
sewardj45f4e7c2005-09-27 19:20:21 +0000262 /* Very annoyingly, I cannot find any definition for R_OK et al in
263 the kernel interfaces. Therefore I reluctantly resort to
264 hardwiring in these magic numbers that I determined by
265 experimentation. */
266 UWord w = (irusr ? 4/*R_OK*/ : 0)
267 | (iwusr ? 2/*W_OK*/ : 0)
268 | (ixusr ? 1/*X_OK*/ : 0);
269 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
sewardj9a66bb92006-10-17 01:38:13 +0000270 return res.isError ? 1 : 0;
271# elif defined(VGO_aix5)
272 UWord w = (irusr ? VKI_R_OK : 0)
273 | (iwusr ? VKI_W_OK : 0)
274 | (ixusr ? VKI_X_OK : 0);
275 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
276 return res.isError ? 1 : 0;
277# else
278# error "Don't know how to do VG_(access) on this OS"
279# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000280}
281
njn73750612005-10-14 03:11:30 +0000282/*
283 Emulate the normal Unix permissions checking algorithm.
284
285 If owner matches, then use the owner permissions, else
286 if group matches, then use the group permissions, else
287 use other permissions.
288
289 Note that we can't deal with SUID/SGID, so we refuse to run them
290 (otherwise the executable may misbehave if it doesn't have the
291 permissions it thinks it does).
292*/
293/* returns: 0 = success, non-0 is failure */
294Int VG_(check_executable)(HChar* f)
295{
sewardj26b87282006-10-17 12:49:31 +0000296 /* This is something of a kludge. Really we should fix VG_(stat) to
297 do this itself, but not clear how to do it as it depends on
298 having a 'struct vki_stat64' which is different from 'struct
299 vki_stat'. */
300# if defined(VGO_linux) && defined(__NR_stat64)
toma346c262006-09-29 08:12:08 +0000301 struct vki_stat64 st;
302 SysRes res = VG_(do_syscall2)(__NR_stat64, (UWord)f, (UWord)&st);
sewardj26b87282006-10-17 12:49:31 +0000303# else
njn73750612005-10-14 03:11:30 +0000304 struct vki_stat st;
sewardj26b87282006-10-17 12:49:31 +0000305 SysRes res = VG_(stat)(f, &st);
306# endif
njn73750612005-10-14 03:11:30 +0000307
njn73750612005-10-14 03:11:30 +0000308 if (res.isError) {
sewardj9a66bb92006-10-17 01:38:13 +0000309 return res.err;
njn73750612005-10-14 03:11:30 +0000310 }
311
312 if (st.st_mode & (VKI_S_ISUID | VKI_S_ISGID)) {
sewardj9a66bb92006-10-17 01:38:13 +0000313 /* VG_(printf)("Can't execute suid/sgid executable %s\n", exe); */
njn73750612005-10-14 03:11:30 +0000314 return VKI_EACCES;
315 }
316
317 if (VG_(geteuid)() == st.st_uid) {
318 if (!(st.st_mode & VKI_S_IXUSR))
319 return VKI_EACCES;
320 } else {
sewardj45406ef2006-10-18 00:33:46 +0000321 Int grpmatch = 0;
njn73750612005-10-14 03:11:30 +0000322
323 if (VG_(getegid)() == st.st_gid)
324 grpmatch = 1;
325 else {
326 UInt groups[32];
327 Int ngrp = VG_(getgroups)(32, groups);
328 Int i;
329 /* ngrp will be -1 if VG_(getgroups) failed. */
330 for (i = 0; i < ngrp; i++) {
331 if (groups[i] == st.st_gid) {
332 grpmatch = 1;
333 break;
334 }
335 }
336 }
337
338 if (grpmatch) {
339 if (!(st.st_mode & VKI_S_IXGRP)) {
340 return VKI_EACCES;
341 }
342 } else if (!(st.st_mode & VKI_S_IXOTH)) {
343 return VKI_EACCES;
344 }
345 }
346
347 return 0;
348}
349
sewardj45f4e7c2005-09-27 19:20:21 +0000350SysRes VG_(pread) ( Int fd, void* buf, Int count, Int offset )
351{
352 OffT off = VG_(lseek)( fd, (OffT)offset, VKI_SEEK_SET);
tomf4c23102005-10-31 17:05:21 +0000353 if (off < 0)
sewardj45f4e7c2005-09-27 19:20:21 +0000354 return VG_(mk_SysRes_Error)( VKI_EINVAL );
tom60a4b0b2005-10-12 10:45:27 +0000355 return VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count );
sewardj45f4e7c2005-09-27 19:20:21 +0000356}
357
358/* Create and open (-rw------) a tmp file name incorporating said arg.
359 Returns -1 on failure, else the fd of the file. If fullname is
360 non-NULL, the file's name is written into it. The number of bytes
361 written is guaranteed not to exceed 64+strlen(part_of_name). */
362
363Int VG_(mkstemp) ( HChar* part_of_name, /*OUT*/HChar* fullname )
364{
365 HChar buf[200];
366 Int n, tries, fd;
367 UInt seed;
368 SysRes sres;
369
370 vg_assert(part_of_name);
371 n = VG_(strlen)(part_of_name);
372 vg_assert(n > 0 && n < 100);
373
374 seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
375
376 tries = 0;
377 while (True) {
378 if (tries > 10)
379 return -1;
380 VG_(sprintf)( buf, "/tmp/valgrind_%s_%08x",
381 part_of_name, VG_(random)( &seed ));
382 if (0)
383 VG_(printf)("VG_(mkstemp): trying: %s\n", buf);
384
385 sres = VG_(open)(buf,
386 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
387 VKI_S_IRUSR|VKI_S_IWUSR);
388 if (sres.isError)
389 continue;
390 /* VG_(safe_fd) doesn't return if it fails. */
sewardj9a66bb92006-10-17 01:38:13 +0000391 fd = VG_(safe_fd)( sres.res );
sewardj45f4e7c2005-09-27 19:20:21 +0000392 if (fullname)
393 VG_(strcpy)( fullname, buf );
394 return fd;
395 }
396 /* NOTREACHED */
397}
398
399
njneb8896b2005-06-04 20:03:55 +0000400/* ---------------------------------------------------------------------
401 Socket-related stuff. This is very Linux-kernel specific.
402 ------------------------------------------------------------------ */
403
404static
405Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
406
407static
408Int my_socket ( Int domain, Int type, Int protocol );
409
410static
sewardj9a66bb92006-10-17 01:38:13 +0000411Int my_connect ( Int sockfd,
412# if defined(VGO_linux)
413 struct vki_sockaddr_in* serv_addr,
414# else
415 void* serv_addr,
416# endif
njneb8896b2005-06-04 20:03:55 +0000417 Int addrlen );
418
toma4a4f412005-11-17 12:01:56 +0000419UInt VG_(htonl) ( UInt x )
njneb8896b2005-06-04 20:03:55 +0000420{
sewardja1c4bfb2005-10-18 02:15:39 +0000421# if defined(VG_BIGENDIAN)
422 return x;
423# else
njneb8896b2005-06-04 20:03:55 +0000424 return
425 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
426 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
sewardja1c4bfb2005-10-18 02:15:39 +0000427# endif
njneb8896b2005-06-04 20:03:55 +0000428}
429
toma4a4f412005-11-17 12:01:56 +0000430UInt VG_(ntohl) ( UInt x )
431{
432# if defined(VG_BIGENDIAN)
433 return x;
434# else
435 return
436 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
437 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
438# endif
439}
440
441UShort VG_(htons) ( UShort x )
442{
443# if defined(VG_BIGENDIAN)
444 return x;
445# else
446 return
447 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
448# endif
449}
450
451UShort VG_(ntohs) ( UShort x )
njneb8896b2005-06-04 20:03:55 +0000452{
sewardja1c4bfb2005-10-18 02:15:39 +0000453# if defined(VG_BIGENDIAN)
454 return x;
455# else
njneb8896b2005-06-04 20:03:55 +0000456 return
457 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
sewardja1c4bfb2005-10-18 02:15:39 +0000458# endif
njneb8896b2005-06-04 20:03:55 +0000459}
460
461
462/* The main function.
463
464 Supplied string contains either an ip address "192.168.0.1" or
465 an ip address and port pair, "192.168.0.1:1500". Parse these,
466 and return:
467 -1 if there is a parse error
468 -2 if no parse error, but specified host:port cannot be opened
469 the relevant file (socket) descriptor, otherwise.
470 is used.
471*/
472Int VG_(connect_via_socket)( UChar* str )
473{
sewardj9a66bb92006-10-17 01:38:13 +0000474#if defined(VGO_aix5)
475 I_die_here;
476#else /* Yay, Linux */
njneb8896b2005-06-04 20:03:55 +0000477 Int sd, res;
478 struct vki_sockaddr_in servAddr;
479 UInt ip = 0;
480 UShort port = VG_CLO_DEFAULT_LOGPORT;
481 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
482 if (!ok)
483 return -1;
484
485 //if (0)
486 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
487 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
488 // (ip >> 8) & 0xFF, ip & 0xFF,
489 // (UInt)port );
490
491 servAddr.sin_family = VKI_AF_INET;
toma4a4f412005-11-17 12:01:56 +0000492 servAddr.sin_addr.s_addr = VG_(htonl)(ip);
493 servAddr.sin_port = VG_(htons)(port);
njneb8896b2005-06-04 20:03:55 +0000494
495 /* create socket */
496 sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
497 if (sd < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000498 /* this shouldn't happen ... nevertheless */
499 return -2;
njneb8896b2005-06-04 20:03:55 +0000500 }
sewardja1c4bfb2005-10-18 02:15:39 +0000501
njneb8896b2005-06-04 20:03:55 +0000502 /* connect to server */
503 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
504 sizeof(servAddr));
505 if (res < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000506 /* connection failed */
507 return -2;
njneb8896b2005-06-04 20:03:55 +0000508 }
509
510 return sd;
sewardj9a66bb92006-10-17 01:38:13 +0000511#endif
njneb8896b2005-06-04 20:03:55 +0000512}
513
514
515/* Let d = one or more digits. Accept either:
516 d.d.d.d or d.d.d.d:d
517*/
sewardj9a66bb92006-10-17 01:38:13 +0000518static Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
njneb8896b2005-06-04 20:03:55 +0000519{
520# define GET_CH ((*str) ? (*str++) : 0)
521 UInt ipa, i, j, c, any;
522 ipa = 0;
523 for (i = 0; i < 4; i++) {
524 j = 0;
525 any = 0;
526 while (1) {
527 c = GET_CH;
528 if (c < '0' || c > '9') break;
529 j = 10 * j + (int)(c - '0');
530 any = 1;
531 }
532 if (any == 0 || j > 255) goto syntaxerr;
533 ipa = (ipa << 8) + j;
534 if (i <= 2 && c != '.') goto syntaxerr;
535 }
536 if (c == 0 || c == ':')
537 *ip_addr = ipa;
538 if (c == 0) goto ok;
539 if (c != ':') goto syntaxerr;
540 j = 0;
541 any = 0;
542 while (1) {
543 c = GET_CH;
544 if (c < '0' || c > '9') break;
545 j = j * 10 + (int)(c - '0');
546 any = 1;
547 if (j > 65535) goto syntaxerr;
548 }
549 if (any == 0 || c != 0) goto syntaxerr;
550 if (j < 1024) goto syntaxerr;
551 *port = (UShort)j;
552 ok:
553 return 1;
554 syntaxerr:
555 return 0;
556# undef GET_CH
557}
558
njneb8896b2005-06-04 20:03:55 +0000559static
560Int my_socket ( Int domain, Int type, Int protocol )
561{
sewardj2c48c7b2005-11-29 13:05:56 +0000562#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000563 SysRes res;
564 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000565 args[0] = domain;
566 args[1] = type;
567 args[2] = protocol;
568 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
sewardj9a66bb92006-10-17 01:38:13 +0000569 return res.isError ? -1 : res.res;
cerion85665ca2005-06-20 15:51:07 +0000570
571#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000572 SysRes res;
573 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
sewardj9a66bb92006-10-17 01:38:13 +0000574 return res.isError ? -1 : res.res;
575
576#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
577 I_die_here;
cerion85665ca2005-06-20 15:51:07 +0000578
cerion85665ca2005-06-20 15:51:07 +0000579#else
580# error Unknown arch
581#endif
njneb8896b2005-06-04 20:03:55 +0000582}
583
584static
sewardj9a66bb92006-10-17 01:38:13 +0000585Int my_connect ( Int sockfd,
586# if defined(VGO_linux)
587 struct vki_sockaddr_in* serv_addr,
588# else
589 void* serv_addr,
590# endif
njneb8896b2005-06-04 20:03:55 +0000591 Int addrlen )
592{
sewardj2c48c7b2005-11-29 13:05:56 +0000593#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000594 SysRes res;
595 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000596 args[0] = sockfd;
597 args[1] = (UWord)serv_addr;
598 args[2] = addrlen;
599 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
sewardj9a66bb92006-10-17 01:38:13 +0000600 return res.isError ? -1 : res.res;
cerion85665ca2005-06-20 15:51:07 +0000601
602#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000603 SysRes res;
604 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
sewardj9a66bb92006-10-17 01:38:13 +0000605 return res.isError ? -1 : res.res;
606
607#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
608 I_die_here;
cerion85665ca2005-06-20 15:51:07 +0000609
cerion85665ca2005-06-20 15:51:07 +0000610#else
611# error Unknown arch
612#endif
njneb8896b2005-06-04 20:03:55 +0000613}
614
615Int VG_(write_socket)( Int sd, void *msg, Int count )
616{
njneb8896b2005-06-04 20:03:55 +0000617 /* This is actually send(). */
sewardj9a66bb92006-10-17 01:38:13 +0000618 /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
619 errors on stream oriented sockets when the other end breaks the
620 connection. The EPIPE error is still returned. */
njneb8896b2005-06-04 20:03:55 +0000621
sewardj2c48c7b2005-11-29 13:05:56 +0000622#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000623 SysRes res;
624 UWord args[4];
njneb8896b2005-06-04 20:03:55 +0000625 args[0] = sd;
626 args[1] = (UWord)msg;
627 args[2] = count;
sewardj9a66bb92006-10-17 01:38:13 +0000628 args[3] = VKI_MSG_NOSIGNAL;
njneb8896b2005-06-04 20:03:55 +0000629 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
sewardj9a66bb92006-10-17 01:38:13 +0000630 return res.isError ? -1 : res.res;
cerion85665ca2005-06-20 15:51:07 +0000631
632#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000633 SysRes res;
sewardj9a66bb92006-10-17 01:38:13 +0000634 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
635 count, VKI_MSG_NOSIGNAL, 0,0);
636 return res.isError ? -1 : res.res;
637
638#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
639 I_die_here;
cerion85665ca2005-06-20 15:51:07 +0000640
cerion85665ca2005-06-20 15:51:07 +0000641#else
642# error Unknown arch
643#endif
njneb8896b2005-06-04 20:03:55 +0000644}
645
646Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
647{
sewardj2c48c7b2005-11-29 13:05:56 +0000648#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000649 SysRes res;
sewardja8d8e232005-06-07 20:04:56 +0000650 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000651 args[0] = sd;
652 args[1] = (UWord)name;
653 args[2] = (UWord)namelen;
654 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
sewardj9a66bb92006-10-17 01:38:13 +0000655 return res.isError ? -1 : res.res;
sewardja5c9e4a2005-06-09 13:21:58 +0000656
cerion85665ca2005-06-20 15:51:07 +0000657#elif defined(VGP_amd64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000658 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000659 res = VG_(do_syscall3)( __NR_getsockname,
660 (UWord)sd, (UWord)name, (UWord)namelen );
sewardj9a66bb92006-10-17 01:38:13 +0000661 return res.isError ? -1 : res.res;
662
663#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
664 I_die_here;
sewardja5c9e4a2005-06-09 13:21:58 +0000665
cerion85665ca2005-06-20 15:51:07 +0000666#else
667# error Unknown arch
668#endif
njneb8896b2005-06-04 20:03:55 +0000669}
670
671Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
672{
sewardj2c48c7b2005-11-29 13:05:56 +0000673#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000674 SysRes res;
sewardja8d8e232005-06-07 20:04:56 +0000675 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000676 args[0] = sd;
677 args[1] = (UWord)name;
678 args[2] = (UWord)namelen;
679 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
sewardj9a66bb92006-10-17 01:38:13 +0000680 return res.isError ? -1 : res.res;
sewardja5c9e4a2005-06-09 13:21:58 +0000681
cerion85665ca2005-06-20 15:51:07 +0000682#elif defined(VGP_amd64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000683 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000684 res = VG_(do_syscall3)( __NR_getpeername,
685 (UWord)sd, (UWord)name, (UWord)namelen );
sewardj9a66bb92006-10-17 01:38:13 +0000686 return res.isError ? -1 : res.res;
687
688#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
689 I_die_here;
sewardja5c9e4a2005-06-09 13:21:58 +0000690
cerion85665ca2005-06-20 15:51:07 +0000691#else
sewardj9a66bb92006-10-17 01:38:13 +0000692# error Unknown arch
cerion85665ca2005-06-20 15:51:07 +0000693#endif
njneb8896b2005-06-04 20:03:55 +0000694}
695
696Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
697 Int *optlen)
698{
sewardj2c48c7b2005-11-29 13:05:56 +0000699#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000700 SysRes res;
sewardja8d8e232005-06-07 20:04:56 +0000701 UWord args[5];
njneb8896b2005-06-04 20:03:55 +0000702 args[0] = sd;
703 args[1] = level;
704 args[2] = optname;
705 args[3] = (UWord)optval;
706 args[4] = (UWord)optlen;
707 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
sewardj9a66bb92006-10-17 01:38:13 +0000708 return res.isError ? -1 : res.res;
sewardja5c9e4a2005-06-09 13:21:58 +0000709
cerion85665ca2005-06-20 15:51:07 +0000710#elif defined(VGP_amd64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000711 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000712 res = VG_(do_syscall5)( __NR_getsockopt,
713 (UWord)sd, (UWord)level, (UWord)optname,
714 (UWord)optval, (UWord)optlen );
sewardj9a66bb92006-10-17 01:38:13 +0000715 return res.isError ? -1 : res.res;
716
717#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
718 I_die_here;
sewardja5c9e4a2005-06-09 13:21:58 +0000719
cerion85665ca2005-06-20 15:51:07 +0000720#else
721# error Unknown arch
722#endif
njneb8896b2005-06-04 20:03:55 +0000723}
724
725
726
727/*--------------------------------------------------------------------*/
728/*--- end ---*/
729/*--------------------------------------------------------------------*/
730