blob: adf54917f99b3ced7e1a8485c96d3314e931d9a3 [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)
sewardjfdf91b42005-09-28 00:53:09 +000040#include "pub_core_clientstate.h" // VG_(fd_hard_limit)
njn9abd6082005-06-17 21:31:45 +000041#include "pub_core_syscall.h"
njneb8896b2005-06-04 20:03:55 +000042
43/* ---------------------------------------------------------------------
44 File stuff
45 ------------------------------------------------------------------ */
46
47static inline Bool fd_exists(Int fd)
48{
49 struct vki_stat st;
50
51 return VG_(fstat)(fd, &st) == 0;
52}
53
54/* Move an fd into the Valgrind-safe range */
55Int VG_(safe_fd)(Int oldfd)
56{
57 Int newfd;
58
59 vg_assert(VG_(fd_hard_limit) != -1);
60
61 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
62 if (newfd != -1)
63 VG_(close)(oldfd);
64
sewardj9a66bb92006-10-17 01:38:13 +000065 /* Set the close-on-exec flag for this fd. */
njneb8896b2005-06-04 20:03:55 +000066 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
67
68 vg_assert(newfd >= VG_(fd_hard_limit));
69 return newfd;
70}
71
njnae7359b2005-06-19 21:10:42 +000072/* Given a file descriptor, attempt to deduce its filename. To do
73 this, we use /proc/self/fd/<FD>. If this doesn't point to a file,
njnf845f8f2005-06-23 02:26:47 +000074 or if it doesn't exist, we return False. */
75Bool VG_(resolve_filename) ( Int fd, HChar* buf, Int n_buf )
njnae7359b2005-06-19 21:10:42 +000076{
77 HChar tmp[64];
78
79 VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
njnf845f8f2005-06-23 02:26:47 +000080 VG_(memset)(buf, 0, n_buf);
njnae7359b2005-06-19 21:10:42 +000081
sewardj45f4e7c2005-09-27 19:20:21 +000082 if (VG_(readlink)(tmp, buf, n_buf) > 0 && buf[0] == '/')
njnf845f8f2005-06-23 02:26:47 +000083 return True;
84 else
85 return False;
njnae7359b2005-06-19 21:10:42 +000086}
87
sewardj92645592005-07-23 09:18:34 +000088SysRes VG_(open) ( const Char* pathname, Int flags, Int mode )
njneb8896b2005-06-04 20:03:55 +000089{
sewardja8d8e232005-06-07 20:04:56 +000090 SysRes res = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode);
sewardj92645592005-07-23 09:18:34 +000091 return res;
njneb8896b2005-06-04 20:03:55 +000092}
93
94void VG_(close) ( Int fd )
95{
sewardja8d8e232005-06-07 20:04:56 +000096 (void)VG_(do_syscall1)(__NR_close, fd);
njneb8896b2005-06-04 20:03:55 +000097}
98
99Int VG_(read) ( Int fd, void* buf, Int count)
100{
sewardj9a66bb92006-10-17 01:38:13 +0000101 Int ret;
sewardja8d8e232005-06-07 20:04:56 +0000102 SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
sewardj9a66bb92006-10-17 01:38:13 +0000103 if (res.isError) {
104 ret = - (Int)(Word)res.err;
105 vg_assert(ret < 0);
106 } else {
107 ret = (Int)(Word)res.res;
108 vg_assert(ret >= 0);
109 }
110 return ret;
njneb8896b2005-06-04 20:03:55 +0000111}
112
113Int VG_(write) ( Int fd, const void* buf, Int count)
114{
sewardj9a66bb92006-10-17 01:38:13 +0000115 Int ret;
sewardja8d8e232005-06-07 20:04:56 +0000116 SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
sewardj9a66bb92006-10-17 01:38:13 +0000117 if (res.isError) {
118 ret = - (Int)(Word)res.err;
119 vg_assert(ret < 0);
120 } else {
121 ret = (Int)(Word)res.res;
122 vg_assert(ret >= 0);
123 }
124 return ret;
njneb8896b2005-06-04 20:03:55 +0000125}
126
127Int VG_(pipe) ( Int fd[2] )
128{
sewardja8d8e232005-06-07 20:04:56 +0000129 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
130 return res.isError ? -1 : 0;
njneb8896b2005-06-04 20:03:55 +0000131}
132
sewardj45f4e7c2005-09-27 19:20:21 +0000133OffT VG_(lseek) ( Int fd, OffT offset, Int whence )
njneb8896b2005-06-04 20:03:55 +0000134{
sewardja8d8e232005-06-07 20:04:56 +0000135 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
sewardj9a66bb92006-10-17 01:38:13 +0000136 return res.isError ? (-1) : res.res;
sewardj45f4e7c2005-09-27 19:20:21 +0000137 /* if you change the error-reporting conventions of this, also
138 change VG_(pread) and all other usage points. */
njneb8896b2005-06-04 20:03:55 +0000139}
140
tom6c93c4f2005-08-05 07:46:32 +0000141SysRes VG_(stat) ( Char* file_name, struct vki_stat* buf )
njneb8896b2005-06-04 20:03:55 +0000142{
sewardj9a66bb92006-10-17 01:38:13 +0000143# if defined(VGO_linux)
sewardja8d8e232005-06-07 20:04:56 +0000144 SysRes res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)buf);
tom6c93c4f2005-08-05 07:46:32 +0000145 return res;
sewardj9a66bb92006-10-17 01:38:13 +0000146# elif defined(VGO_aix5)
147 SysRes res = VG_(do_syscall4)(__NR_AIX5_statx,
148 (UWord)file_name,
149 (UWord)buf,
150 sizeof(struct vki_stat),
151 VKI_STX_NORMAL);
152 return res;
153# else
154# error Unknown OS
155# endif
njneb8896b2005-06-04 20:03:55 +0000156}
157
158Int VG_(fstat) ( Int fd, struct vki_stat* buf )
159{
sewardj9a66bb92006-10-17 01:38:13 +0000160# if defined(VGO_linux)
sewardja8d8e232005-06-07 20:04:56 +0000161 SysRes res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf);
162 return res.isError ? (-1) : 0;
sewardj9a66bb92006-10-17 01:38:13 +0000163# elif defined(VGO_aix5)
164 I_die_here;
165# else
166# error Unknown OS
167# endif
njneb8896b2005-06-04 20:03:55 +0000168}
169
sewardj45f4e7c2005-09-27 19:20:21 +0000170Int VG_(fsize) ( Int fd )
njneb8896b2005-06-04 20:03:55 +0000171{
sewardj9a66bb92006-10-17 01:38:13 +0000172# if defined(VGO_linux) && defined(__NR_fstat64)
tom574b8932006-07-05 17:47:46 +0000173 struct vki_stat64 buf;
174 SysRes res = VG_(do_syscall2)(__NR_fstat64, fd, (UWord)&buf);
sewardj9a66bb92006-10-17 01:38:13 +0000175 return res.isError ? (-1) : buf.st_size;
176# elif defined(VGO_linux) && !defined(__NR_fstat64)
sewardj45f4e7c2005-09-27 19:20:21 +0000177 struct vki_stat buf;
178 SysRes res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)&buf);
179 return res.isError ? (-1) : buf.st_size;
sewardj9a66bb92006-10-17 01:38:13 +0000180# elif defined(VGO_aix5)
181 I_die_here;
182# else
183# error Unknown OS
184# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000185}
186
njn73750612005-10-14 03:11:30 +0000187Bool VG_(is_dir) ( HChar* f )
188{
189 struct vki_stat buf;
sewardj9a66bb92006-10-17 01:38:13 +0000190 SysRes res = VG_(stat)(f, &buf);
njn73750612005-10-14 03:11:30 +0000191 return res.isError ? False
192 : VKI_S_ISDIR(buf.st_mode) ? True : False;
193}
194
sewardj45f4e7c2005-09-27 19:20:21 +0000195SysRes VG_(dup) ( Int oldfd )
196{
197 return VG_(do_syscall1)(__NR_dup, oldfd);
njneb8896b2005-06-04 20:03:55 +0000198}
199
njn327fe8a2005-06-12 02:49:35 +0000200/* Returns -1 on error. */
201Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
202{
203 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
sewardj9a66bb92006-10-17 01:38:13 +0000204 return res.isError ? -1 : res.res;
njn327fe8a2005-06-12 02:49:35 +0000205}
206
njneb8896b2005-06-04 20:03:55 +0000207Int VG_(rename) ( Char* old_name, Char* new_name )
208{
sewardja8d8e232005-06-07 20:04:56 +0000209 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
210 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000211}
212
213Int VG_(unlink) ( Char* file_name )
214{
sewardja8d8e232005-06-07 20:04:56 +0000215 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
216 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000217}
218
njn57ca7ab2005-06-21 23:44:58 +0000219Bool VG_(getcwd) ( Char* buf, SizeT size )
njneb8896b2005-06-04 20:03:55 +0000220{
sewardj9a66bb92006-10-17 01:38:13 +0000221# if defined(VGO_linux)
sewardja8d8e232005-06-07 20:04:56 +0000222 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000223 vg_assert(buf != NULL);
224 res = VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size);
njn57ca7ab2005-06-21 23:44:58 +0000225 return res.isError ? False : True;
sewardj9a66bb92006-10-17 01:38:13 +0000226# elif defined(VGO_aix5)
227 static Int complaints = 3;
228 if (complaints-- > 0)
229 VG_(debugLog)(0, "libcfile",
230 "Warning: AIX5: m_libcfile.c: kludged 'getcwd'\n");
231 if (size < 2) return False;
232 buf[0] = '.';
233 buf[1] = 0;
234 return True;
235# else
236# error Unknown OS
237# endif
njneb8896b2005-06-04 20:03:55 +0000238}
239
240Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
241{
sewardja8d8e232005-06-07 20:04:56 +0000242 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000243 /* res = readlink( path, buf, bufsiz ); */
244 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
sewardj9a66bb92006-10-17 01:38:13 +0000245 return res.isError ? -1 : res.res;
njneb8896b2005-06-04 20:03:55 +0000246}
247
248Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
249{
sewardja8d8e232005-06-07 20:04:56 +0000250 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000251 /* res = getdents( fd, dirp, count ); */
252 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
sewardj9a66bb92006-10-17 01:38:13 +0000253 return res.isError ? -1 : res.res;
njneb8896b2005-06-04 20:03:55 +0000254}
255
sewardj45f4e7c2005-09-27 19:20:21 +0000256/* Check accessibility of a file. Returns zero for access granted,
257 nonzero otherwise. */
258Int VG_(access) ( HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
259{
sewardj9a66bb92006-10-17 01:38:13 +0000260# if defined(VGO_linux)
sewardj45f4e7c2005-09-27 19:20:21 +0000261 /* Very annoyingly, I cannot find any definition for R_OK et al in
262 the kernel interfaces. Therefore I reluctantly resort to
263 hardwiring in these magic numbers that I determined by
264 experimentation. */
265 UWord w = (irusr ? 4/*R_OK*/ : 0)
266 | (iwusr ? 2/*W_OK*/ : 0)
267 | (ixusr ? 1/*X_OK*/ : 0);
268 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
sewardj9a66bb92006-10-17 01:38:13 +0000269 return res.isError ? 1 : 0;
270# elif defined(VGO_aix5)
271 UWord w = (irusr ? VKI_R_OK : 0)
272 | (iwusr ? VKI_W_OK : 0)
273 | (ixusr ? VKI_X_OK : 0);
274 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
275 return res.isError ? 1 : 0;
276# else
277# error "Don't know how to do VG_(access) on this OS"
278# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000279}
280
njn73750612005-10-14 03:11:30 +0000281/*
282 Emulate the normal Unix permissions checking algorithm.
283
284 If owner matches, then use the owner permissions, else
285 if group matches, then use the group permissions, else
286 use other permissions.
287
288 Note that we can't deal with SUID/SGID, so we refuse to run them
289 (otherwise the executable may misbehave if it doesn't have the
290 permissions it thinks it does).
291*/
292/* returns: 0 = success, non-0 is failure */
293Int VG_(check_executable)(HChar* f)
294{
sewardj26b87282006-10-17 12:49:31 +0000295 /* This is something of a kludge. Really we should fix VG_(stat) to
296 do this itself, but not clear how to do it as it depends on
297 having a 'struct vki_stat64' which is different from 'struct
298 vki_stat'. */
299# if defined(VGO_linux) && defined(__NR_stat64)
toma346c262006-09-29 08:12:08 +0000300 struct vki_stat64 st;
301 SysRes res = VG_(do_syscall2)(__NR_stat64, (UWord)f, (UWord)&st);
sewardj26b87282006-10-17 12:49:31 +0000302# else
njn73750612005-10-14 03:11:30 +0000303 struct vki_stat st;
sewardj26b87282006-10-17 12:49:31 +0000304 SysRes res = VG_(stat)(f, &st);
305# endif
njn73750612005-10-14 03:11:30 +0000306
njn73750612005-10-14 03:11:30 +0000307 if (res.isError) {
sewardj9a66bb92006-10-17 01:38:13 +0000308 return res.err;
njn73750612005-10-14 03:11:30 +0000309 }
310
311 if (st.st_mode & (VKI_S_ISUID | VKI_S_ISGID)) {
sewardj9a66bb92006-10-17 01:38:13 +0000312 /* VG_(printf)("Can't execute suid/sgid executable %s\n", exe); */
njn73750612005-10-14 03:11:30 +0000313 return VKI_EACCES;
314 }
315
316 if (VG_(geteuid)() == st.st_uid) {
317 if (!(st.st_mode & VKI_S_IXUSR))
318 return VKI_EACCES;
319 } else {
sewardj45406ef2006-10-18 00:33:46 +0000320 Int grpmatch = 0;
njn73750612005-10-14 03:11:30 +0000321
322 if (VG_(getegid)() == st.st_gid)
323 grpmatch = 1;
324 else {
325 UInt groups[32];
326 Int ngrp = VG_(getgroups)(32, groups);
327 Int i;
328 /* ngrp will be -1 if VG_(getgroups) failed. */
329 for (i = 0; i < ngrp; i++) {
330 if (groups[i] == st.st_gid) {
331 grpmatch = 1;
332 break;
333 }
334 }
335 }
336
337 if (grpmatch) {
338 if (!(st.st_mode & VKI_S_IXGRP)) {
339 return VKI_EACCES;
340 }
341 } else if (!(st.st_mode & VKI_S_IXOTH)) {
342 return VKI_EACCES;
343 }
344 }
345
346 return 0;
347}
348
sewardj45f4e7c2005-09-27 19:20:21 +0000349SysRes VG_(pread) ( Int fd, void* buf, Int count, Int offset )
350{
351 OffT off = VG_(lseek)( fd, (OffT)offset, VKI_SEEK_SET);
tomf4c23102005-10-31 17:05:21 +0000352 if (off < 0)
sewardj45f4e7c2005-09-27 19:20:21 +0000353 return VG_(mk_SysRes_Error)( VKI_EINVAL );
tom60a4b0b2005-10-12 10:45:27 +0000354 return VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count );
sewardj45f4e7c2005-09-27 19:20:21 +0000355}
356
357/* Create and open (-rw------) a tmp file name incorporating said arg.
358 Returns -1 on failure, else the fd of the file. If fullname is
359 non-NULL, the file's name is written into it. The number of bytes
360 written is guaranteed not to exceed 64+strlen(part_of_name). */
361
362Int VG_(mkstemp) ( HChar* part_of_name, /*OUT*/HChar* fullname )
363{
364 HChar buf[200];
365 Int n, tries, fd;
366 UInt seed;
367 SysRes sres;
368
369 vg_assert(part_of_name);
370 n = VG_(strlen)(part_of_name);
371 vg_assert(n > 0 && n < 100);
372
373 seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
374
375 tries = 0;
376 while (True) {
377 if (tries > 10)
378 return -1;
379 VG_(sprintf)( buf, "/tmp/valgrind_%s_%08x",
380 part_of_name, VG_(random)( &seed ));
381 if (0)
382 VG_(printf)("VG_(mkstemp): trying: %s\n", buf);
383
384 sres = VG_(open)(buf,
385 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
386 VKI_S_IRUSR|VKI_S_IWUSR);
387 if (sres.isError)
388 continue;
389 /* VG_(safe_fd) doesn't return if it fails. */
sewardj9a66bb92006-10-17 01:38:13 +0000390 fd = VG_(safe_fd)( sres.res );
sewardj45f4e7c2005-09-27 19:20:21 +0000391 if (fullname)
392 VG_(strcpy)( fullname, buf );
393 return fd;
394 }
395 /* NOTREACHED */
396}
397
398
njneb8896b2005-06-04 20:03:55 +0000399/* ---------------------------------------------------------------------
400 Socket-related stuff. This is very Linux-kernel specific.
401 ------------------------------------------------------------------ */
402
403static
404Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
405
406static
407Int my_socket ( Int domain, Int type, Int protocol );
408
409static
sewardj9a66bb92006-10-17 01:38:13 +0000410Int my_connect ( Int sockfd,
411# if defined(VGO_linux)
412 struct vki_sockaddr_in* serv_addr,
413# else
414 void* serv_addr,
415# endif
njneb8896b2005-06-04 20:03:55 +0000416 Int addrlen );
417
toma4a4f412005-11-17 12:01:56 +0000418UInt VG_(htonl) ( UInt x )
njneb8896b2005-06-04 20:03:55 +0000419{
sewardja1c4bfb2005-10-18 02:15:39 +0000420# if defined(VG_BIGENDIAN)
421 return x;
422# else
njneb8896b2005-06-04 20:03:55 +0000423 return
424 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
425 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
sewardja1c4bfb2005-10-18 02:15:39 +0000426# endif
njneb8896b2005-06-04 20:03:55 +0000427}
428
toma4a4f412005-11-17 12:01:56 +0000429UInt VG_(ntohl) ( UInt x )
430{
431# if defined(VG_BIGENDIAN)
432 return x;
433# else
434 return
435 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
436 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
437# endif
438}
439
440UShort VG_(htons) ( UShort x )
441{
442# if defined(VG_BIGENDIAN)
443 return x;
444# else
445 return
446 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
447# endif
448}
449
450UShort VG_(ntohs) ( UShort x )
njneb8896b2005-06-04 20:03:55 +0000451{
sewardja1c4bfb2005-10-18 02:15:39 +0000452# if defined(VG_BIGENDIAN)
453 return x;
454# else
njneb8896b2005-06-04 20:03:55 +0000455 return
456 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
sewardja1c4bfb2005-10-18 02:15:39 +0000457# endif
njneb8896b2005-06-04 20:03:55 +0000458}
459
460
461/* The main function.
462
463 Supplied string contains either an ip address "192.168.0.1" or
464 an ip address and port pair, "192.168.0.1:1500". Parse these,
465 and return:
466 -1 if there is a parse error
467 -2 if no parse error, but specified host:port cannot be opened
468 the relevant file (socket) descriptor, otherwise.
469 is used.
470*/
471Int VG_(connect_via_socket)( UChar* str )
472{
sewardj9a66bb92006-10-17 01:38:13 +0000473#if defined(VGO_aix5)
474 I_die_here;
475#else /* Yay, Linux */
njneb8896b2005-06-04 20:03:55 +0000476 Int sd, res;
477 struct vki_sockaddr_in servAddr;
478 UInt ip = 0;
479 UShort port = VG_CLO_DEFAULT_LOGPORT;
480 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
481 if (!ok)
482 return -1;
483
484 //if (0)
485 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
486 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
487 // (ip >> 8) & 0xFF, ip & 0xFF,
488 // (UInt)port );
489
490 servAddr.sin_family = VKI_AF_INET;
toma4a4f412005-11-17 12:01:56 +0000491 servAddr.sin_addr.s_addr = VG_(htonl)(ip);
492 servAddr.sin_port = VG_(htons)(port);
njneb8896b2005-06-04 20:03:55 +0000493
494 /* create socket */
495 sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
496 if (sd < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000497 /* this shouldn't happen ... nevertheless */
498 return -2;
njneb8896b2005-06-04 20:03:55 +0000499 }
sewardja1c4bfb2005-10-18 02:15:39 +0000500
njneb8896b2005-06-04 20:03:55 +0000501 /* connect to server */
502 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
503 sizeof(servAddr));
504 if (res < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000505 /* connection failed */
506 return -2;
njneb8896b2005-06-04 20:03:55 +0000507 }
508
509 return sd;
sewardj9a66bb92006-10-17 01:38:13 +0000510#endif
njneb8896b2005-06-04 20:03:55 +0000511}
512
513
514/* Let d = one or more digits. Accept either:
515 d.d.d.d or d.d.d.d:d
516*/
sewardj9a66bb92006-10-17 01:38:13 +0000517static Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
njneb8896b2005-06-04 20:03:55 +0000518{
519# define GET_CH ((*str) ? (*str++) : 0)
520 UInt ipa, i, j, c, any;
521 ipa = 0;
522 for (i = 0; i < 4; i++) {
523 j = 0;
524 any = 0;
525 while (1) {
526 c = GET_CH;
527 if (c < '0' || c > '9') break;
528 j = 10 * j + (int)(c - '0');
529 any = 1;
530 }
531 if (any == 0 || j > 255) goto syntaxerr;
532 ipa = (ipa << 8) + j;
533 if (i <= 2 && c != '.') goto syntaxerr;
534 }
535 if (c == 0 || c == ':')
536 *ip_addr = ipa;
537 if (c == 0) goto ok;
538 if (c != ':') goto syntaxerr;
539 j = 0;
540 any = 0;
541 while (1) {
542 c = GET_CH;
543 if (c < '0' || c > '9') break;
544 j = j * 10 + (int)(c - '0');
545 any = 1;
546 if (j > 65535) goto syntaxerr;
547 }
548 if (any == 0 || c != 0) goto syntaxerr;
549 if (j < 1024) goto syntaxerr;
550 *port = (UShort)j;
551 ok:
552 return 1;
553 syntaxerr:
554 return 0;
555# undef GET_CH
556}
557
njneb8896b2005-06-04 20:03:55 +0000558static
559Int my_socket ( Int domain, Int type, Int protocol )
560{
sewardj2c48c7b2005-11-29 13:05:56 +0000561#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000562 SysRes res;
563 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000564 args[0] = domain;
565 args[1] = type;
566 args[2] = protocol;
567 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
sewardj9a66bb92006-10-17 01:38:13 +0000568 return res.isError ? -1 : res.res;
cerion85665ca2005-06-20 15:51:07 +0000569
570#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000571 SysRes res;
572 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
sewardj9a66bb92006-10-17 01:38:13 +0000573 return res.isError ? -1 : res.res;
574
575#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
576 I_die_here;
cerion85665ca2005-06-20 15:51:07 +0000577
cerion85665ca2005-06-20 15:51:07 +0000578#else
579# error Unknown arch
580#endif
njneb8896b2005-06-04 20:03:55 +0000581}
582
583static
sewardj9a66bb92006-10-17 01:38:13 +0000584Int my_connect ( Int sockfd,
585# if defined(VGO_linux)
586 struct vki_sockaddr_in* serv_addr,
587# else
588 void* serv_addr,
589# endif
njneb8896b2005-06-04 20:03:55 +0000590 Int addrlen )
591{
sewardj2c48c7b2005-11-29 13:05:56 +0000592#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000593 SysRes res;
594 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000595 args[0] = sockfd;
596 args[1] = (UWord)serv_addr;
597 args[2] = addrlen;
598 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
sewardj9a66bb92006-10-17 01:38:13 +0000599 return res.isError ? -1 : res.res;
cerion85665ca2005-06-20 15:51:07 +0000600
601#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000602 SysRes res;
603 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
sewardj9a66bb92006-10-17 01:38:13 +0000604 return res.isError ? -1 : res.res;
605
606#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
607 I_die_here;
cerion85665ca2005-06-20 15:51:07 +0000608
cerion85665ca2005-06-20 15:51:07 +0000609#else
610# error Unknown arch
611#endif
njneb8896b2005-06-04 20:03:55 +0000612}
613
614Int VG_(write_socket)( Int sd, void *msg, Int count )
615{
njneb8896b2005-06-04 20:03:55 +0000616 /* This is actually send(). */
sewardj9a66bb92006-10-17 01:38:13 +0000617 /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
618 errors on stream oriented sockets when the other end breaks the
619 connection. The EPIPE error is still returned. */
njneb8896b2005-06-04 20:03:55 +0000620
sewardj2c48c7b2005-11-29 13:05:56 +0000621#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000622 SysRes res;
623 UWord args[4];
njneb8896b2005-06-04 20:03:55 +0000624 args[0] = sd;
625 args[1] = (UWord)msg;
626 args[2] = count;
sewardj9a66bb92006-10-17 01:38:13 +0000627 args[3] = VKI_MSG_NOSIGNAL;
njneb8896b2005-06-04 20:03:55 +0000628 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
sewardj9a66bb92006-10-17 01:38:13 +0000629 return res.isError ? -1 : res.res;
cerion85665ca2005-06-20 15:51:07 +0000630
631#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000632 SysRes res;
sewardj9a66bb92006-10-17 01:38:13 +0000633 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
634 count, VKI_MSG_NOSIGNAL, 0,0);
635 return res.isError ? -1 : res.res;
636
637#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
638 I_die_here;
cerion85665ca2005-06-20 15:51:07 +0000639
cerion85665ca2005-06-20 15:51:07 +0000640#else
641# error Unknown arch
642#endif
njneb8896b2005-06-04 20:03:55 +0000643}
644
645Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
646{
sewardj2c48c7b2005-11-29 13:05:56 +0000647#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000648 SysRes res;
sewardja8d8e232005-06-07 20:04:56 +0000649 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000650 args[0] = sd;
651 args[1] = (UWord)name;
652 args[2] = (UWord)namelen;
653 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
sewardj9a66bb92006-10-17 01:38:13 +0000654 return res.isError ? -1 : res.res;
sewardja5c9e4a2005-06-09 13:21:58 +0000655
cerion85665ca2005-06-20 15:51:07 +0000656#elif defined(VGP_amd64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000657 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000658 res = VG_(do_syscall3)( __NR_getsockname,
659 (UWord)sd, (UWord)name, (UWord)namelen );
sewardj9a66bb92006-10-17 01:38:13 +0000660 return res.isError ? -1 : res.res;
661
662#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
663 I_die_here;
sewardja5c9e4a2005-06-09 13:21:58 +0000664
cerion85665ca2005-06-20 15:51:07 +0000665#else
666# error Unknown arch
667#endif
njneb8896b2005-06-04 20:03:55 +0000668}
669
670Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
671{
sewardj2c48c7b2005-11-29 13:05:56 +0000672#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000673 SysRes res;
sewardja8d8e232005-06-07 20:04:56 +0000674 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000675 args[0] = sd;
676 args[1] = (UWord)name;
677 args[2] = (UWord)namelen;
678 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
sewardj9a66bb92006-10-17 01:38:13 +0000679 return res.isError ? -1 : res.res;
sewardja5c9e4a2005-06-09 13:21:58 +0000680
cerion85665ca2005-06-20 15:51:07 +0000681#elif defined(VGP_amd64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000682 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000683 res = VG_(do_syscall3)( __NR_getpeername,
684 (UWord)sd, (UWord)name, (UWord)namelen );
sewardj9a66bb92006-10-17 01:38:13 +0000685 return res.isError ? -1 : res.res;
686
687#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
688 I_die_here;
sewardja5c9e4a2005-06-09 13:21:58 +0000689
cerion85665ca2005-06-20 15:51:07 +0000690#else
sewardj9a66bb92006-10-17 01:38:13 +0000691# error Unknown arch
cerion85665ca2005-06-20 15:51:07 +0000692#endif
njneb8896b2005-06-04 20:03:55 +0000693}
694
695Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
696 Int *optlen)
697{
sewardj2c48c7b2005-11-29 13:05:56 +0000698#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000699 SysRes res;
sewardja8d8e232005-06-07 20:04:56 +0000700 UWord args[5];
njneb8896b2005-06-04 20:03:55 +0000701 args[0] = sd;
702 args[1] = level;
703 args[2] = optname;
704 args[3] = (UWord)optval;
705 args[4] = (UWord)optlen;
706 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
sewardj9a66bb92006-10-17 01:38:13 +0000707 return res.isError ? -1 : res.res;
sewardja5c9e4a2005-06-09 13:21:58 +0000708
cerion85665ca2005-06-20 15:51:07 +0000709#elif defined(VGP_amd64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000710 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000711 res = VG_(do_syscall5)( __NR_getsockopt,
712 (UWord)sd, (UWord)level, (UWord)optname,
713 (UWord)optval, (UWord)optlen );
sewardj9a66bb92006-10-17 01:38:13 +0000714 return res.isError ? -1 : res.res;
715
716#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
717 I_die_here;
sewardja5c9e4a2005-06-09 13:21:58 +0000718
cerion85665ca2005-06-20 15:51:07 +0000719#else
720# error Unknown arch
721#endif
njneb8896b2005-06-04 20:03:55 +0000722}
723
724
725
726/*--------------------------------------------------------------------*/
727/*--- end ---*/
728/*--------------------------------------------------------------------*/
729