1 /* Copyright (C) 2007-2008 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 ** GNU General Public License for more details.
11 */
12 #include "sockets.h"
13 #include "qemu-common.h"
14 #include <fcntl.h>
15 #include <stddef.h>
16 #include "qemu_debug.h"
17 #include "qemu-char.h"
18 #include <stdlib.h>
19 #include <string.h>
20 #include "android/utils/path.h"
21 #include "android/utils/debug.h"
22 #include "android/utils/misc.h"
23
24 #define D(...) VERBOSE_PRINT(socket,__VA_ARGS__)
25
26 #ifdef _WIN32
27 # define xxWIN32_LEAN_AND_MEAN
28 # include <windows.h>
29 # include <winsock2.h>
30 # include <ws2tcpip.h>
31 #else /* !_WIN32 */
32 # include <sys/ioctl.h>
33 # include <sys/socket.h>
34 # include <netinet/in.h>
35 # include <netinet/tcp.h>
36 # ifdef __linux__ /* Recent versions of glibc only define EAI_NODATA, which is an
37 extension to the POSIX standard, if __USE_GNU is defined. */
38 # define __USE_GNU
39 # include <netdb.h>
40 # undef __USE_GNU
41 # else /* !__linux__ */
42 # include <netdb.h>
43 # endif /* !__linux__ */
44 # if HAVE_UNIX_SOCKETS
45 # include <sys/un.h>
46 # ifndef UNIX_PATH_MAX
47 # define UNIX_PATH_MAX (sizeof(((struct sockaddr_un*)0)->sun_path)-1)
48 # endif
49 # endif
50 #endif /* !_WIN32 */
51
52
53
54 /* QSOCKET_CALL is used to deal with the fact that EINTR happens pretty
55 * easily in QEMU since we use SIGALRM to implement periodic timers
56 */
57 #ifdef _WIN32
58 # define QSOCKET_CALL(_ret,_cmd) \
59 do { _ret = (_cmd); } while ( _ret < 0 && WSAGetLastError() == WSAEINTR )
60 #else
61 # define QSOCKET_CALL(_ret,_cmd) \
62 do { \
63 errno = 0; \
64 do { _ret = (_cmd); } while ( _ret < 0 && errno == EINTR ); \
65 } while (0);
66 #endif
67
68 #ifdef _WIN32
69
70 #include <errno.h>
71
72 static int winsock_error;
73
74 #define WINSOCK_ERRORS_LIST \
75 EE(WSA_INVALID_HANDLE,EINVAL,"invalid handle") \
76 EE(WSA_NOT_ENOUGH_MEMORY,ENOMEM,"not enough memory") \
77 EE(WSA_INVALID_PARAMETER,EINVAL,"invalid parameter") \
78 EE(WSAEINTR,EINTR,"interrupted function call") \
79 EE(WSAEALREADY,EALREADY,"operation already in progress") \
80 EE(WSAEBADF,EBADF,"bad file descriptor") \
81 EE(WSAEACCES,EACCES,"permission denied") \
82 EE(WSAEFAULT,EFAULT,"bad address") \
83 EE(WSAEINVAL,EINVAL,"invalid argument") \
84 EE(WSAEMFILE,EMFILE,"too many opened files") \
85 EE(WSAEWOULDBLOCK,EWOULDBLOCK,"resource temporarily unavailable") \
86 EE(WSAEINPROGRESS,EINPROGRESS,"operation now in progress") \
87 EE(WSAEALREADY,EAGAIN,"operation already in progress") \
88 EE(WSAENOTSOCK,EBADF,"socket operation not on socket") \
89 EE(WSAEDESTADDRREQ,EDESTADDRREQ,"destination address required") \
90 EE(WSAEMSGSIZE,EMSGSIZE,"message too long") \
91 EE(WSAEPROTOTYPE,EPROTOTYPE,"wrong protocol type for socket") \
92 EE(WSAENOPROTOOPT,ENOPROTOOPT,"bad protocol option") \
93 EE(WSAEADDRINUSE,EADDRINUSE,"address already in use") \
94 EE(WSAEADDRNOTAVAIL,EADDRNOTAVAIL,"cannot assign requested address") \
95 EE(WSAENETDOWN,ENETDOWN,"network is down") \
96 EE(WSAENETUNREACH,ENETUNREACH,"network unreachable") \
97 EE(WSAENETRESET,ENETRESET,"network dropped connection on reset") \
98 EE(WSAECONNABORTED,ECONNABORTED,"software caused connection abort") \
99 EE(WSAECONNRESET,ECONNRESET,"connection reset by peer") \
100 EE(WSAENOBUFS,ENOBUFS,"no buffer space available") \
101 EE(WSAEISCONN,EISCONN,"socket is already connected") \
102 EE(WSAENOTCONN,ENOTCONN,"socket is not connected") \
103 EE(WSAESHUTDOWN,ESHUTDOWN,"cannot send after socket shutdown") \
104 EE(WSAETOOMANYREFS,ETOOMANYREFS,"too many references") \
105 EE(WSAETIMEDOUT,ETIMEDOUT,"connection timed out") \
106 EE(WSAECONNREFUSED,ECONNREFUSED,"connection refused") \
107 EE(WSAELOOP,ELOOP,"cannot translate name") \
108 EE(WSAENAMETOOLONG,ENAMETOOLONG,"name too long") \
109 EE(WSAEHOSTDOWN,EHOSTDOWN,"host is down") \
110 EE(WSAEHOSTUNREACH,EHOSTUNREACH,"no route to host") \
111
112 typedef struct {
113 int winsock;
114 int unix;
115 const char* string;
116 } WinsockError;
117
118 static const WinsockError _winsock_errors[] = {
119 #define EE(w,u,s) { w, u, s },
120 WINSOCK_ERRORS_LIST
121 #undef EE
122 { -1, -1, NULL }
123 };
124
125 /* this function reads the latest winsock error code and updates
126 * errno to a matching value. It also returns the new value of
127 * errno.
128 */
129 static int
_fix_errno(void)130 _fix_errno( void )
131 {
132 const WinsockError* werr = _winsock_errors;
133 int unix = EINVAL; /* generic error code */
134
135 winsock_error = WSAGetLastError();
136
137 for ( ; werr->string != NULL; werr++ ) {
138 if (werr->winsock == winsock_error) {
139 unix = werr->unix;
140 break;
141 }
142 }
143 errno = unix;
144 return -1;
145 }
146
147 static int
_set_errno(int code)148 _set_errno( int code )
149 {
150 winsock_error = -1;
151 errno = code;
152 return -1;
153 }
154
155 /* this function returns a string describing the latest Winsock error */
156 const char*
_errno_str(void)157 _errno_str(void)
158 {
159 const WinsockError* werr = _winsock_errors;
160 const char* result = NULL;
161
162 for ( ; werr->string; werr++ ) {
163 if (werr->winsock == winsock_error) {
164 result = werr->string;
165 break;
166 }
167 }
168
169 if (result == NULL) {
170 result = tempstr_format(
171 "Unkown socket error (Winsock=0x%08x) errno=%d: %s",
172 winsock_error, errno, strerror(errno));
173 }
174 return result;
175 }
176 #else
177 static int
_fix_errno(void)178 _fix_errno( void )
179 {
180 return -1;
181 }
182
183 static int
_set_errno(int code)184 _set_errno( int code )
185 {
186 errno = code;
187 return -1;
188 }
189 #endif
190
191 /* socket types */
192
193 static int
socket_family_to_bsd(SocketFamily family)194 socket_family_to_bsd( SocketFamily family )
195 {
196 switch (family) {
197 case SOCKET_INET: return AF_INET;
198 case SOCKET_IN6: return AF_INET6;
199 #if HAVE_UNIX_SOCKETS
200 case SOCKET_UNIX: return AF_LOCAL;
201 #endif
202 default: return -1;
203 }
204 }
205
206 static int
socket_type_to_bsd(SocketType type)207 socket_type_to_bsd( SocketType type )
208 {
209 switch (type) {
210 case SOCKET_DGRAM: return SOCK_DGRAM;
211 case SOCKET_STREAM: return SOCK_STREAM;
212 default: return 0;
213 }
214 }
215
216 static SocketType
socket_type_from_bsd(int type)217 socket_type_from_bsd( int type )
218 {
219 switch (type) {
220 case SOCK_DGRAM: return SOCKET_DGRAM;
221 case SOCK_STREAM: return SOCKET_STREAM;
222 default: return (SocketType) SOCKET_UNSPEC;
223 }
224 }
225
226 #if 0
227 static int
228 socket_type_check( SocketType type )
229 {
230 return (type == SOCKET_DGRAM || type == SOCKET_STREAM);
231 }
232 #endif
233
234 /* socket addresses */
235
236 void
sock_address_init_inet(SockAddress * a,uint32_t ip,uint16_t port)237 sock_address_init_inet( SockAddress* a, uint32_t ip, uint16_t port )
238 {
239 a->family = SOCKET_INET;
240 a->u.inet.port = port;
241 a->u.inet.address = ip;
242 }
243
244 void
sock_address_init_in6(SockAddress * a,const uint8_t * ip6[16],uint16_t port)245 sock_address_init_in6 ( SockAddress* a, const uint8_t* ip6[16], uint16_t port )
246 {
247 a->family = SOCKET_IN6;
248 a->u.in6.port = port;
249 memcpy( a->u.in6.address, ip6, sizeof(a->u.in6.address) );
250 }
251
252 void
sock_address_init_unix(SockAddress * a,const char * path)253 sock_address_init_unix( SockAddress* a, const char* path )
254 {
255 a->family = SOCKET_UNIX;
256 a->u._unix.path = strdup(path ? path : "");
257 a->u._unix.owner = 1;
258 }
259
sock_address_done(SockAddress * a)260 void sock_address_done( SockAddress* a )
261 {
262 if (a->family == SOCKET_UNIX && a->u._unix.owner) {
263 a->u._unix.owner = 0;
264 free((char*)a->u._unix.path);
265 }
266 }
267
268 static char*
format_char(char * buf,char * end,int c)269 format_char( char* buf, char* end, int c )
270 {
271 if (buf < end) {
272 if (buf+1 == end) {
273 *buf++ = 0;
274 } else {
275 *buf++ = (char) c;
276 *buf = 0;
277 }
278 }
279 return buf;
280 }
281
282 static char*
format_str(char * buf,char * end,const char * str)283 format_str( char* buf, char* end, const char* str )
284 {
285 int len = strlen(str);
286 int avail = end - buf;
287
288 if (len > avail)
289 len = avail;
290
291 memcpy( buf, str, len );
292 buf += len;
293
294 if (buf == end)
295 buf[-1] = 0;
296 else
297 buf[0] = 0;
298
299 return buf;
300 }
301
302 static char*
format_unsigned(char * buf,char * end,unsigned val)303 format_unsigned( char* buf, char* end, unsigned val )
304 {
305 char temp[16];
306 int nn;
307
308 for ( nn = 0; val != 0; nn++ ) {
309 int rem = val % 10;
310 temp[nn] = '0'+rem;
311 val /= 10;
312 }
313
314 if (nn == 0)
315 temp[nn++] = '0';
316
317 while (nn > 0)
318 buf = format_char(buf, end, temp[--nn]);
319
320 return buf;
321 }
322
323 static char*
format_hex(char * buf,char * end,unsigned val,int ndigits)324 format_hex( char* buf, char* end, unsigned val, int ndigits )
325 {
326 int shift = 4*ndigits;
327 static const char hex[16] = "0123456789abcdef";
328
329 while (shift >= 0) {
330 buf = format_char(buf, end, hex[(val >> shift) & 15]);
331 shift -= 4;
332 }
333 return buf;
334 }
335
336 static char*
format_ip4(char * buf,char * end,uint32_t ip)337 format_ip4( char* buf, char* end, uint32_t ip )
338 {
339 buf = format_unsigned( buf, end, (unsigned)(ip >> 24) );
340 buf = format_char( buf, end, '.');
341 buf = format_unsigned( buf, end, (unsigned)((ip >> 16) & 255));
342 buf = format_char( buf, end, '.');
343 buf = format_unsigned( buf, end, (unsigned)((ip >> 8) & 255));
344 buf = format_char( buf, end, '.');
345 buf = format_unsigned( buf, end, (unsigned)(ip & 255));
346 return buf;
347 }
348
349 static char*
format_ip6(char * buf,char * end,const uint8_t * ip6)350 format_ip6( char* buf, char* end, const uint8_t* ip6 )
351 {
352 int nn;
353 for (nn = 0; nn < 8; nn++) {
354 int val = (ip6[0] << 16) | ip6[1];
355 ip6 += 2;
356 if (nn > 0)
357 buf = format_char(buf, end, ':');
358 if (val == 0)
359 continue;
360 buf = format_hex(buf, end, val, 4);
361 }
362 return buf;
363 }
364
365 const char*
sock_address_to_string(const SockAddress * a)366 sock_address_to_string( const SockAddress* a )
367 {
368 static char buf0[MAX_PATH];
369 char *buf = buf0, *end = buf + sizeof(buf0);
370
371 switch (a->family) {
372 case SOCKET_INET:
373 buf = format_ip4( buf, end, a->u.inet.address );
374 buf = format_char( buf, end, ':' );
375 buf = format_unsigned( buf, end, (unsigned) a->u.inet.port );
376 break;
377
378 case SOCKET_IN6:
379 buf = format_ip6( buf, end, a->u.in6.address );
380 buf = format_char( buf, end, ':' );
381 buf = format_unsigned( buf, end, (unsigned) a->u.in6.port );
382 break;
383
384 case SOCKET_UNIX:
385 buf = format_str( buf, end, a->u._unix.path );
386 break;
387
388 default:
389 return NULL;
390 }
391
392 return buf0;
393 }
394
395 int
sock_address_equal(const SockAddress * a,const SockAddress * b)396 sock_address_equal( const SockAddress* a, const SockAddress* b )
397 {
398 if (a->family != b->family)
399 return 0;
400
401 switch (a->family) {
402 case SOCKET_INET:
403 return (a->u.inet.address == b->u.inet.address &&
404 a->u.inet.port == b->u.inet.port);
405
406 case SOCKET_IN6:
407 return (!memcmp(a->u.in6.address, b->u.in6.address, 16) &&
408 a->u.in6.port == b->u.in6.port);
409
410 case SOCKET_UNIX:
411 return (!strcmp(a->u._unix.path, b->u._unix.path));
412
413 default:
414 return 0;
415 }
416 }
417
418 int
sock_address_get_port(const SockAddress * a)419 sock_address_get_port( const SockAddress* a )
420 {
421 switch (a->family) {
422 case SOCKET_INET:
423 return a->u.inet.port;
424 case SOCKET_IN6:
425 return a->u.in6.port;
426 default:
427 return -1;
428 }
429 }
430
431 void
sock_address_set_port(SockAddress * a,uint16_t port)432 sock_address_set_port( SockAddress* a, uint16_t port )
433 {
434 switch (a->family) {
435 case SOCKET_INET:
436 a->u.inet.port = port;
437 break;
438 case SOCKET_IN6:
439 a->u.in6.port = port;
440 break;
441 default:
442 ;
443 }
444 }
445
446 const char*
sock_address_get_path(const SockAddress * a)447 sock_address_get_path( const SockAddress* a )
448 {
449 if (a->family == SOCKET_UNIX)
450 return a->u._unix.path;
451 else
452 return NULL;
453 }
454
455 int
sock_address_get_ip(const SockAddress * a)456 sock_address_get_ip( const SockAddress* a )
457 {
458 if (a->family == SOCKET_INET)
459 return a->u.inet.address;
460
461 return -1;
462 }
463
464 #if 0
465 char*
466 bufprint_sock_address( char* p, char* end, const SockAddress* a )
467 {
468 switch (a->family) {
469 case SOCKET_INET:
470 {
471 uint32_t ip = a->u.inet.address;
472
473 return bufprint( p, end, "%d.%d.%d.%d:%d",
474 (ip >> 24) & 255, (ip >> 16) & 255,
475 (ip >> 8) & 255, ip & 255,
476 a->u.inet.port );
477 }
478 case SOCKET_IN6:
479 {
480 int nn = 0;
481 const char* column = "";
482 const uint8_t* tab = a->u.in6.address;
483 for (nn = 0; nn < 16; nn += 2) {
484 p = bufprint(p, end, "%s%04x", column, (tab[n] << 8) | tab[n+1]);
485 column = ":";
486 }
487 return bufprint(p, end, ":%d", a->u.in6.port);
488 }
489 case SOCKET_UNIX:
490 {
491 return bufprint(p, end, "%s", a->u._unix.path);
492 }
493 default:
494 return p;
495 }
496 }
497 #endif
498
499 int
sock_address_to_bsd(const SockAddress * a,void * paddress,size_t * psize)500 sock_address_to_bsd( const SockAddress* a, void* paddress, size_t *psize )
501 {
502 switch (a->family) {
503 case SOCKET_INET:
504 {
505 struct sockaddr_in* dst = (struct sockaddr_in*) paddress;
506
507 *psize = sizeof(*dst);
508
509 memset( paddress, 0, *psize );
510
511 dst->sin_family = AF_INET;
512 dst->sin_port = htons(a->u.inet.port);
513 dst->sin_addr.s_addr = htonl(a->u.inet.address);
514 }
515 break;
516
517 #if HAVE_IN6_SOCKETS
518 case SOCKET_IN6:
519 {
520 struct sockaddr_in6* dst = (struct sockaddr_in6*) paddress;
521
522 *psize = sizeof(*dst);
523
524 memset( paddress, 0, *psize );
525
526 dst->sin6_family = AF_INET6;
527 dst->sin6_port = htons(a->u.in6.port);
528 memcpy( dst->sin6_addr.s6_addr, a->u.in6.address, 16 );
529 }
530 break;
531 #endif /* HAVE_IN6_SOCKETS */
532
533 #if HAVE_UNIX_SOCKETS
534 case SOCKET_UNIX:
535 {
536 int slen = strlen(a->u._unix.path);
537 struct sockaddr_un* dst = (struct sockaddr_un*) paddress;
538
539 if (slen >= UNIX_PATH_MAX)
540 return -1;
541
542 memset( paddress, 0, sizeof(*dst) );
543
544 dst->sun_family = AF_LOCAL;
545 memcpy( dst->sun_path, a->u._unix.path, slen );
546 dst->sun_path[slen] = 0;
547
548 *psize = (char*)&dst->sun_path[slen+1] - (char*)dst;
549 }
550 break;
551 #endif /* HAVE_UNIX_SOCKETS */
552
553 default:
554 return _set_errno(EINVAL);
555 }
556
557 return 0;
558 }
559
560 int
sock_address_to_inet(SockAddress * a,int * paddr_ip,int * paddr_port)561 sock_address_to_inet( SockAddress* a, int *paddr_ip, int *paddr_port )
562 {
563 struct sockaddr addr;
564 socklen_t addrlen;
565
566 if (a->family != SOCKET_INET) {
567 return _set_errno(EINVAL);
568 }
569
570 if (sock_address_to_bsd(a, &addr, &addrlen) < 0)
571 return -1;
572
573 *paddr_ip = ntohl(((struct sockaddr_in*)&addr)->sin_addr.s_addr);
574 *paddr_port = ntohs(((struct sockaddr_in*)&addr)->sin_port);
575
576 return 0;
577 }
578
579 int
sock_address_from_bsd(SockAddress * a,const void * from,size_t fromlen)580 sock_address_from_bsd( SockAddress* a, const void* from, size_t fromlen )
581 {
582 switch (((struct sockaddr*)from)->sa_family) {
583 case AF_INET:
584 {
585 struct sockaddr_in* src = (struct sockaddr_in*) from;
586
587 if (fromlen < sizeof(*src))
588 return _set_errno(EINVAL);
589
590 a->family = SOCKET_INET;
591 a->u.inet.port = ntohs(src->sin_port);
592 a->u.inet.address = ntohl(src->sin_addr.s_addr);
593 }
594 break;
595
596 #ifdef HAVE_IN6_SOCKETS
597 case AF_INET6:
598 {
599 struct sockaddr_in6* src = (struct sockaddr_in6*) from;
600
601 if (fromlen < sizeof(*src))
602 return _set_errno(EINVAL);
603
604 a->family = SOCKET_IN6;
605 a->u.in6.port = ntohs(src->sin6_port);
606 memcpy(a->u.in6.address, src->sin6_addr.s6_addr, 16);
607 }
608 break;
609 #endif
610
611 #ifdef HAVE_UNIX_SOCKETS
612 case AF_LOCAL:
613 {
614 struct sockaddr_un* src = (struct sockaddr_un*) from;
615 char* end;
616
617 if (fromlen < sizeof(*src))
618 return _set_errno(EINVAL);
619
620 /* check that the path is zero-terminated */
621 end = memchr(src->sun_path, 0, UNIX_PATH_MAX);
622 if (end == NULL)
623 return _set_errno(EINVAL);
624
625 a->family = SOCKET_UNIX;
626 a->u._unix.owner = 1;
627 a->u._unix.path = strdup(src->sun_path);
628 }
629 break;
630 #endif
631
632 default:
633 return _set_errno(EINVAL);
634 }
635 return 0;
636 }
637
638
639 int
sock_address_init_resolve(SockAddress * a,const char * hostname,uint16_t port,int preferIn6)640 sock_address_init_resolve( SockAddress* a, const char* hostname, uint16_t port, int preferIn6 )
641 {
642 struct addrinfo hints[1];
643 struct addrinfo* res;
644 int ret;
645
646 memset(hints, 0, sizeof(hints));
647 hints->ai_family = preferIn6 ? AF_INET6 : AF_UNSPEC;
648
649 ret = getaddrinfo(hostname, NULL, hints, &res);
650 if (ret != 0) {
651 int err;
652
653 switch (ret) {
654 case EAI_AGAIN: /* server is down */
655 case EAI_FAIL: /* server is sick */
656 err = EHOSTDOWN;
657 break;
658
659 #ifdef EAI_NODATA
660 case EAI_NODATA:
661 #endif
662 case EAI_NONAME:
663 err = ENOENT;
664 break;
665
666 case EAI_MEMORY:
667 err = ENOMEM;
668 break;
669
670 default:
671 err = EINVAL;
672 }
673 return _set_errno(err);
674 }
675
676 /* Parse the returned list of addresses. */
677 {
678 struct addrinfo* res_ipv4 = NULL;
679 struct addrinfo* res_ipv6 = NULL;
680 struct addrinfo* r;
681
682 /* If preferIn6 is false, we stop on the first IPv4 address,
683 * otherwise, we stop on the first IPv6 one
684 */
685 for (r = res; r != NULL; r = r->ai_next) {
686 if (r->ai_family == AF_INET && res_ipv4 == NULL) {
687 res_ipv4 = r;
688 if (!preferIn6)
689 break;
690 }
691 else if (r->ai_family == AF_INET6 && res_ipv6 == NULL) {
692 res_ipv6 = r;
693 if (preferIn6)
694 break;
695 }
696 }
697
698 /* Select the best address in 'r', which will be NULL
699 * if there is no corresponding address.
700 */
701 if (preferIn6) {
702 r = res_ipv6;
703 if (r == NULL)
704 r = res_ipv4;
705 } else {
706 r = res_ipv4;
707 if (r == NULL)
708 r = res_ipv6;
709 }
710
711 if (r == NULL) {
712 ret = _set_errno(ENOENT);
713 goto Exit;
714 }
715
716 /* Convert to a SockAddress */
717 ret = sock_address_from_bsd( a, r->ai_addr, r->ai_addrlen );
718 if (ret < 0)
719 goto Exit;
720 }
721
722 /* need to set the port */
723 switch (a->family) {
724 case SOCKET_INET: a->u.inet.port = port; break;
725 case SOCKET_IN6: a->u.in6.port = port; break;
726 default: ;
727 }
728
729 Exit:
730 freeaddrinfo(res);
731 return ret;
732 }
733
734 /* The Winsock headers for mingw lack some definitions */
735 #ifndef AI_ADDRCONFIG
736 # define AI_ADDRCONFIG 0
737 #endif
738
739 SockAddress**
sock_address_list_create(const char * hostname,const char * port,unsigned flags)740 sock_address_list_create( const char* hostname,
741 const char* port,
742 unsigned flags )
743 {
744 SockAddress** list = NULL;
745 SockAddress* addr;
746 int nn, count, ret;
747 struct addrinfo ai, *res, *e;
748
749 memset(&ai, 0, sizeof(ai));
750 ai.ai_flags |= AI_ADDRCONFIG;
751 ai.ai_family = PF_UNSPEC;
752
753 if (flags & SOCKET_LIST_FORCE_INET)
754 ai.ai_family = PF_INET;
755 else if (flags & SOCKET_LIST_FORCE_IN6)
756 ai.ai_family = PF_INET6;
757
758 if (flags & SOCKET_LIST_PASSIVE)
759 ai.ai_flags |= AI_PASSIVE;
760 else
761 ai.ai_flags |= AI_CANONNAME;
762
763 while (1) {
764 struct addrinfo hints = ai;
765
766 ret = getaddrinfo(hostname, port, &hints, &res);
767 if (ret == 0)
768 break;
769
770 switch (ret) {
771 #ifdef EAI_ADDRFAMILY
772 case EAI_ADDRFAMILY:
773 #endif
774 case EAI_NODATA:
775 _set_errno(ENOENT);
776 break;
777 case EAI_FAMILY:
778 _set_errno(EAFNOSUPPORT);
779 break;
780 case EAI_AGAIN:
781 _set_errno(EAGAIN);
782 break;
783 #ifdef EAI_SYSTEM
784 case EAI_SYSTEM:
785 if (errno == EINTR)
786 continue;
787 break;
788 #endif
789 default:
790 _set_errno(EINVAL);
791 }
792 return NULL;
793 }
794
795 /* allocate result list */
796 for (count = 0, e = res; e != NULL; e = e->ai_next)
797 count += 1;
798
799 list = (SockAddress**) qemu_malloc((count+1)*sizeof(SockAddress*));
800 addr = (SockAddress*) qemu_malloc(count*sizeof(SockAddress));
801
802 for (nn = 0, e = res; e != NULL; e = e->ai_next) {
803
804 ret = sock_address_from_bsd(addr, e->ai_addr, e->ai_addrlen);
805 if (ret < 0)
806 continue;
807
808 list[nn++] = addr++;
809 }
810 list[nn] = NULL;
811 freeaddrinfo(res);
812 return list;
813 }
814
815 void
sock_address_list_free(SockAddress ** list)816 sock_address_list_free( SockAddress** list )
817 {
818 int nn;
819 SockAddress* addr;
820
821 if (list == NULL)
822 return;
823
824 addr = list[0];
825 for (nn = 0; list[nn] != NULL; nn++) {
826 sock_address_done(list[nn]);
827 list[nn] = NULL;
828 }
829 qemu_free(addr);
830 qemu_free(list);
831 }
832
833 int
sock_address_get_numeric_info(SockAddress * a,char * host,size_t hostlen,char * serv,size_t servlen)834 sock_address_get_numeric_info( SockAddress* a,
835 char* host,
836 size_t hostlen,
837 char* serv,
838 size_t servlen )
839 {
840 struct sockaddr* saddr;
841 socklen_t slen;
842 int ret;
843
844 switch (a->family) {
845 case SOCKET_INET:
846 saddr = (struct sockaddr*) &a->u.inet.address;
847 slen = sizeof(a->u.inet.address);
848 break;
849
850 #if HAVE_IN6_SOCKET
851 case SOCKET_IN6:
852 saddr = (struct sockaddr*) &a->u.in6.address;
853 slen = sizeof(a->u.in6.address);
854 break;
855 #endif
856 default:
857 return _set_errno(EINVAL);
858 }
859
860 ret = getnameinfo( saddr, slen, host, hostlen, serv, servlen,
861 NI_NUMERICHOST | NI_NUMERICSERV );
862
863 switch (ret) {
864 case 0:
865 break;
866 case EAI_AGAIN:
867 ret = EAGAIN;
868 break;
869 default:
870 ret = EINVAL;
871 }
872 return ret;
873 }
874
875 int
socket_create(SocketFamily family,SocketType type)876 socket_create( SocketFamily family, SocketType type )
877 {
878 int ret;
879 int sfamily = socket_family_to_bsd(family);
880 int stype = socket_type_to_bsd(type);
881
882 if (sfamily < 0 || stype < 0) {
883 return _set_errno(EINVAL);
884 }
885
886 QSOCKET_CALL(ret, socket(sfamily, stype, 0));
887 if (ret < 0)
888 return _fix_errno();
889
890 return ret;
891 }
892
893
894 int
socket_create_inet(SocketType type)895 socket_create_inet( SocketType type )
896 {
897 return socket_create( SOCKET_INET, type );
898 }
899
900 #if HAVE_IN6_SOCKETS
901 int
socket_create_in6(SocketType type)902 socket_create_in6 ( SocketType type )
903 {
904 return socket_create( SOCKET_IN6, type );
905 }
906 #endif
907
908 #if HAVE_UNIX_SOCKETS
909 int
socket_create_unix(SocketType type)910 socket_create_unix( SocketType type )
911 {
912 return socket_create( SOCKET_UNIX, type );
913 }
914 #endif
915
socket_can_read(int fd)916 int socket_can_read(int fd)
917 {
918 #ifdef _WIN32
919 unsigned long opt;
920
921 if (ioctlsocket(fd, FIONREAD, &opt) < 0)
922 return 0;
923
924 return opt;
925 #else
926 int opt;
927
928 if (ioctl(fd, FIONREAD, &opt) < 0)
929 return 0;
930
931 return opt;
932 #endif
933 }
934
935 #define SOCKET_CALL(cmd) \
936 int ret; \
937 QSOCKET_CALL(ret, (cmd)); \
938 if (ret < 0) \
939 return _fix_errno(); \
940 return ret; \
941
942 int
socket_send(int fd,const void * buf,int buflen)943 socket_send(int fd, const void* buf, int buflen)
944 {
945 SOCKET_CALL(send(fd, buf, buflen, 0))
946 }
947
948 int
socket_send_oob(int fd,const void * buf,int buflen)949 socket_send_oob( int fd, const void* buf, int buflen )
950 {
951 SOCKET_CALL(send(fd, buf, buflen, MSG_OOB));
952 }
953
954 int
socket_sendto(int fd,const void * buf,int buflen,const SockAddress * to)955 socket_sendto(int fd, const void* buf, int buflen, const SockAddress* to)
956 {
957 struct sockaddr sa;
958 socklen_t salen;
959
960 if (sock_address_to_bsd(to, &sa, &salen) < 0)
961 return -1;
962
963 SOCKET_CALL(sendto(fd, buf, buflen, 0, &sa, salen));
964 }
965
966 int
socket_recv(int fd,void * buf,int len)967 socket_recv(int fd, void* buf, int len)
968 {
969 SOCKET_CALL(recv(fd, buf, len, 0));
970 }
971
972 int
socket_recvfrom(int fd,void * buf,int len,SockAddress * from)973 socket_recvfrom(int fd, void* buf, int len, SockAddress* from)
974 {
975 struct sockaddr sa;
976 socklen_t salen = sizeof(sa);
977 int ret;
978
979 QSOCKET_CALL(ret,recvfrom(fd,buf,len,0,&sa,&salen));
980 if (ret < 0)
981 return _fix_errno();
982
983 if (sock_address_from_bsd(from, &sa, salen) < 0)
984 return -1;
985
986 return ret;
987 }
988
989 int
socket_connect(int fd,const SockAddress * address)990 socket_connect( int fd, const SockAddress* address )
991 {
992 struct sockaddr addr;
993 socklen_t addrlen;
994
995 if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
996 return -1;
997
998 SOCKET_CALL(connect(fd,&addr,addrlen));
999 }
1000
1001 int
socket_bind(int fd,const SockAddress * address)1002 socket_bind( int fd, const SockAddress* address )
1003 {
1004 struct sockaddr addr;
1005 socklen_t addrlen;
1006
1007 if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
1008 return -1;
1009
1010 SOCKET_CALL(bind(fd, &addr, addrlen));
1011 }
1012
1013 int
socket_get_address(int fd,SockAddress * address)1014 socket_get_address( int fd, SockAddress* address )
1015 {
1016 struct sockaddr addr;
1017 socklen_t addrlen = sizeof(addr);
1018 int ret;
1019
1020 QSOCKET_CALL(ret, getsockname(fd, &addr, &addrlen));
1021 if (ret < 0)
1022 return _fix_errno();
1023
1024 return sock_address_from_bsd(address, &addr, addrlen);
1025 }
1026
1027 int
socket_get_peer_address(int fd,SockAddress * address)1028 socket_get_peer_address( int fd, SockAddress* address )
1029 {
1030 struct sockaddr addr;
1031 socklen_t addrlen = sizeof(addr);
1032 int ret;
1033
1034 QSOCKET_CALL(ret, getpeername(fd, &addr, &addrlen));
1035 if (ret < 0)
1036 return _fix_errno();
1037
1038 return sock_address_from_bsd(address, &addr, addrlen);
1039 }
1040
1041 int
socket_listen(int fd,int backlog)1042 socket_listen( int fd, int backlog )
1043 {
1044 SOCKET_CALL(listen(fd, backlog));
1045 }
1046
1047 int
socket_accept(int fd,SockAddress * address)1048 socket_accept( int fd, SockAddress* address )
1049 {
1050 struct sockaddr addr;
1051 socklen_t addrlen = sizeof(addr);
1052 int ret;
1053
1054 QSOCKET_CALL(ret, accept(fd, &addr, &addrlen));
1055 if (ret < 0)
1056 return _fix_errno();
1057
1058 if (address) {
1059 if (sock_address_from_bsd(address, &addr, addrlen) < 0) {
1060 socket_close(ret);
1061 return -1;
1062 }
1063 }
1064 return ret;
1065 }
1066
1067 static int
socket_getoption(int fd,int domain,int option,int defaut)1068 socket_getoption(int fd, int domain, int option, int defaut)
1069 {
1070 int ret;
1071 while (1) {
1072 #ifdef _WIN32
1073 DWORD opt = (DWORD)-1;
1074 #else
1075 int opt = -1;
1076 #endif
1077 size_t optlen = sizeof(opt);
1078 ret = getsockopt(fd, domain, option, (char*)&opt, &optlen);
1079 if (ret == 0)
1080 return (int)opt;
1081 if (errno != EINTR)
1082 return defaut;
1083 }
1084 #undef OPT_CAST
1085 }
1086
1087
socket_get_type(int fd)1088 SocketType socket_get_type(int fd)
1089 {
1090 int so_type = socket_getoption(fd, SOL_SOCKET, SO_TYPE, -1);
1091 return socket_type_from_bsd(so_type);
1092 }
1093
socket_set_nonblock(int fd)1094 int socket_set_nonblock(int fd)
1095 {
1096 #ifdef _WIN32
1097 unsigned long opt = 1;
1098 return ioctlsocket(fd, FIONBIO, &opt);
1099 #else
1100 int flags = fcntl(fd, F_GETFL);
1101 return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
1102 #endif
1103 }
1104
socket_set_blocking(int fd)1105 int socket_set_blocking(int fd)
1106 {
1107 #ifdef _WIN32
1108 unsigned long opt = 0;
1109 return ioctlsocket(fd, FIONBIO, &opt);
1110 #else
1111 int flags = fcntl(fd, F_GETFL);
1112 return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
1113 #endif
1114 }
1115
1116 static int
socket_setoption(int fd,int domain,int option,int _flag)1117 socket_setoption(int fd, int domain, int option, int _flag)
1118 {
1119 #ifdef _WIN32
1120 DWORD flag = (DWORD) _flag;
1121 #else
1122 int flag = _flag;
1123 #endif
1124 return setsockopt( fd, domain, option, (const char*)&flag, sizeof(flag) );
1125 }
1126
socket_set_xreuseaddr(int fd)1127 int socket_set_xreuseaddr(int fd)
1128 {
1129 #ifdef _WIN32
1130 /* on Windows, SO_REUSEADDR is used to indicate that several programs can
1131 * bind to the same port. this is completely different from the Unix
1132 * semantics. instead of SO_EXCLUSIVEADDR to ensure that explicitely prevent
1133 * this.
1134 */
1135 return socket_setoption(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 1);
1136 #else
1137 return socket_setoption(fd, SOL_SOCKET, SO_REUSEADDR, 1);
1138 #endif
1139 }
1140
1141
socket_set_oobinline(int fd)1142 int socket_set_oobinline(int fd)
1143 {
1144 return socket_setoption(fd, SOL_SOCKET, SO_OOBINLINE, 1);
1145 }
1146
1147
socket_set_nodelay(int fd)1148 int socket_set_nodelay(int fd)
1149 {
1150 return socket_setoption(fd, IPPROTO_TCP, TCP_NODELAY, 1);
1151 }
1152
socket_set_ipv6only(int fd)1153 int socket_set_ipv6only(int fd)
1154 {
1155 /* IPV6_ONLY is only supported since Vista on Windows,
1156 * and the Mingw headers lack its definition anyway.
1157 */
1158 #if defined(_WIN32) && !defined(IPV6_V6ONLY)
1159 return 0;
1160 #else
1161 return socket_setoption(fd, IPPROTO_IPV6, IPV6_V6ONLY, 1);
1162 #endif
1163 }
1164
1165
socket_get_error(int fd)1166 int socket_get_error(int fd)
1167 {
1168 return socket_getoption(fd, SOL_SOCKET, SO_ERROR, -1);
1169 }
1170
1171 #ifdef _WIN32
1172 #include <stdlib.h>
1173
socket_cleanup(void)1174 static void socket_cleanup(void)
1175 {
1176 WSACleanup();
1177 }
1178
socket_init(void)1179 int socket_init(void)
1180 {
1181 WSADATA Data;
1182 int ret, err;
1183
1184 ret = WSAStartup(MAKEWORD(2,2), &Data);
1185 if (ret != 0) {
1186 err = WSAGetLastError();
1187 return -1;
1188 }
1189 atexit(socket_cleanup);
1190 return 0;
1191 }
1192
1193 #else /* !_WIN32 */
1194
socket_init(void)1195 int socket_init(void)
1196 {
1197 return 0; /* nothing to do on Unix */
1198 }
1199
1200 #endif /* !_WIN32 */
1201
1202 #ifdef _WIN32
1203
1204 static void
socket_close_handler(void * _fd)1205 socket_close_handler( void* _fd )
1206 {
1207 int fd = (int)_fd;
1208 int ret;
1209 char buff[64];
1210
1211 /* we want to drain the read side of the socket before closing it */
1212 do {
1213 ret = recv( fd, buff, sizeof(buff), 0 );
1214 } while (ret < 0 && WSAGetLastError() == WSAEINTR);
1215
1216 if (ret < 0 && WSAGetLastError() == EWOULDBLOCK)
1217 return;
1218
1219 qemu_set_fd_handler( fd, NULL, NULL, NULL );
1220 closesocket( fd );
1221 }
1222
1223 void
socket_close(int fd)1224 socket_close( int fd )
1225 {
1226 int old_errno = errno;
1227
1228 shutdown( fd, SD_BOTH );
1229 /* we want to drain the socket before closing it */
1230 qemu_set_fd_handler( fd, socket_close_handler, NULL, (void*)fd );
1231
1232 errno = old_errno;
1233 }
1234
1235 #else /* !_WIN32 */
1236
1237 #include <unistd.h>
1238
1239 void
socket_close(int fd)1240 socket_close( int fd )
1241 {
1242 int old_errno = errno;
1243
1244 shutdown( fd, SHUT_RDWR );
1245 close( fd );
1246
1247 errno = old_errno;
1248 }
1249
1250 #endif /* !_WIN32 */
1251
1252
1253 static int
socket_bind_server(int s,const SockAddress * to,SocketType type)1254 socket_bind_server( int s, const SockAddress* to, SocketType type )
1255 {
1256 socket_set_xreuseaddr(s);
1257
1258 if (socket_bind(s, to) < 0) {
1259 D("could not bind server socket address %s: %s",
1260 sock_address_to_string(to), errno_str);
1261 goto FAIL;
1262 }
1263
1264 if (type == SOCKET_STREAM) {
1265 if (socket_listen(s, 4) < 0) {
1266 D("could not listen server socket %s: %s",
1267 sock_address_to_string(to), errno_str);
1268 goto FAIL;
1269 }
1270 }
1271 return s;
1272
1273 FAIL:
1274 socket_close(s);
1275 return -1;
1276 }
1277
1278
1279 static int
socket_connect_client(int s,const SockAddress * to)1280 socket_connect_client( int s, const SockAddress* to )
1281 {
1282 if (socket_connect(s, to) < 0) {
1283 D( "could not connect client socket to %s: %s\n",
1284 sock_address_to_string(to), errno_str );
1285 socket_close(s);
1286 return -1;
1287 }
1288
1289 socket_set_nonblock( s );
1290 return s;
1291 }
1292
1293
1294 static int
socket_in_server(int address,int port,SocketType type)1295 socket_in_server( int address, int port, SocketType type )
1296 {
1297 SockAddress addr;
1298 int s;
1299
1300 sock_address_init_inet( &addr, address, port );
1301 s = socket_create_inet( type );
1302 if (s < 0)
1303 return -1;
1304
1305 return socket_bind_server( s, &addr, type );
1306 }
1307
1308
1309 static int
socket_in_client(SockAddress * to,SocketType type)1310 socket_in_client( SockAddress* to, SocketType type )
1311 {
1312 int s;
1313
1314 s = socket_create_inet( type );
1315 if (s < 0) return -1;
1316
1317 return socket_connect_client( s, to );
1318 }
1319
1320
1321 int
socket_loopback_server(int port,SocketType type)1322 socket_loopback_server( int port, SocketType type )
1323 {
1324 return socket_in_server( SOCK_ADDRESS_INET_LOOPBACK, port, type );
1325 }
1326
1327 int
socket_loopback_client(int port,SocketType type)1328 socket_loopback_client( int port, SocketType type )
1329 {
1330 SockAddress addr;
1331
1332 sock_address_init_inet( &addr, SOCK_ADDRESS_INET_LOOPBACK, port );
1333 return socket_in_client( &addr, type );
1334 }
1335
1336
1337 int
socket_network_client(const char * host,int port,SocketType type)1338 socket_network_client( const char* host, int port, SocketType type )
1339 {
1340 SockAddress addr;
1341
1342 if (sock_address_init_resolve( &addr, host, port, 0) < 0)
1343 return -1;
1344
1345 return socket_in_client( &addr, type );
1346 }
1347
1348
1349 int
socket_anyaddr_server(int port,SocketType type)1350 socket_anyaddr_server( int port, SocketType type )
1351 {
1352 return socket_in_server( SOCK_ADDRESS_INET_ANY, port, type );
1353 }
1354
1355 int
socket_accept_any(int server_fd)1356 socket_accept_any( int server_fd )
1357 {
1358 int fd;
1359
1360 QSOCKET_CALL(fd, accept( server_fd, NULL, 0 ));
1361 if (fd < 0) {
1362 D( "could not accept client connection from fd %d: %s",
1363 server_fd, errno_str );
1364 return -1;
1365 }
1366
1367 /* set to non-blocking */
1368 socket_set_nonblock( fd );
1369 return fd;
1370 }
1371
1372
1373 #if HAVE_UNIX_SOCKETS
1374
1375 int
socket_unix_server(const char * name,SocketType type)1376 socket_unix_server( const char* name, SocketType type )
1377 {
1378 SockAddress addr;
1379 int s, ret;
1380
1381 s = socket_create_unix( type );
1382 if (s < 0)
1383 return -1;
1384
1385 sock_address_init_unix( &addr, name );
1386
1387 do {
1388 ret = unlink( name );
1389 } while (ret < 0 && errno == EINTR);
1390
1391 ret = socket_bind_server( s, &addr, type );
1392
1393 sock_address_done( &addr );
1394 return ret;
1395 }
1396
1397 int
socket_unix_client(const char * name,SocketType type)1398 socket_unix_client( const char* name, SocketType type )
1399 {
1400 SockAddress addr;
1401 int s, ret;
1402
1403 s = socket_create_unix(type);
1404 if (s < 0)
1405 return -1;
1406
1407 sock_address_init_unix( &addr, name );
1408
1409 ret = socket_connect_client( s, &addr );
1410
1411 sock_address_done( &addr );
1412 return ret;
1413 }
1414
1415 #endif /* HAVE_UNIX_SOCKETS */
1416
1417
1418
1419 int
socket_pair(int * fd1,int * fd2)1420 socket_pair(int *fd1, int *fd2)
1421 {
1422 #ifndef _WIN32
1423 int fds[2];
1424 int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
1425
1426 if (!ret) {
1427 socket_set_nonblock(fds[0]);
1428 socket_set_nonblock(fds[1]);
1429 *fd1 = fds[0];
1430 *fd2 = fds[1];
1431 }
1432 return ret;
1433 #else /* _WIN32 */
1434 /* on Windows, select() only works with network sockets, which
1435 * means we absolutely cannot use Win32 PIPEs to implement
1436 * socket pairs with the current event loop implementation.
1437 * We're going to do like Cygwin: create a random pair
1438 * of localhost TCP sockets and connect them together
1439 */
1440 int s0, s1, s2, port;
1441 struct sockaddr_in sockin;
1442 socklen_t len;
1443
1444 /* first, create the 'server' socket.
1445 * a port number of 0 means 'any port between 1024 and 5000.
1446 * see Winsock bind() documentation for details */
1447 s0 = socket_loopback_server( 0, SOCK_STREAM );
1448 if (s0 < 0)
1449 return -1;
1450
1451 /* now connect a client socket to it, we first need to
1452 * extract the server socket's port number */
1453 len = sizeof sockin;
1454 if (getsockname(s0, (struct sockaddr*) &sockin, &len) < 0) {
1455 closesocket (s0);
1456 return -1;
1457 }
1458
1459 port = ntohs(sockin.sin_port);
1460 s2 = socket_loopback_client( port, SOCK_STREAM );
1461 if (s2 < 0) {
1462 closesocket(s0);
1463 return -1;
1464 }
1465
1466 /* we need to accept the connection on the server socket
1467 * this will create the second socket for the pair
1468 */
1469 len = sizeof sockin;
1470 s1 = accept(s0, (struct sockaddr*) &sockin, &len);
1471 if (s1 == INVALID_SOCKET) {
1472 closesocket (s0);
1473 closesocket (s2);
1474 return -1;
1475 }
1476 socket_set_nonblock(s1);
1477
1478 /* close server socket */
1479 closesocket(s0);
1480 *fd1 = s1;
1481 *fd2 = s2;
1482 return 0;
1483 #endif /* _WIN32 */
1484 }
1485
1486
1487
1488 int
socket_mcast_inet_add_membership(int s,uint32_t ip)1489 socket_mcast_inet_add_membership( int s, uint32_t ip )
1490 {
1491 struct ip_mreq imr;
1492
1493 imr.imr_multiaddr.s_addr = htonl(ip);
1494 imr.imr_interface.s_addr = htonl(INADDR_ANY);
1495
1496 if ( setsockopt( s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
1497 (const char *)&imr,
1498 sizeof(struct ip_mreq)) < 0 )
1499 {
1500 return _fix_errno();
1501 }
1502 return 0;
1503 }
1504
1505 int
socket_mcast_inet_drop_membership(int s,uint32_t ip)1506 socket_mcast_inet_drop_membership( int s, uint32_t ip )
1507 {
1508 struct ip_mreq imr;
1509
1510 imr.imr_multiaddr.s_addr = htonl(ip);
1511 imr.imr_interface.s_addr = htonl(INADDR_ANY);
1512
1513 if ( setsockopt( s, IPPROTO_IP, IP_DROP_MEMBERSHIP,
1514 (const char *)&imr,
1515 sizeof(struct ip_mreq)) < 0 )
1516 {
1517 return _fix_errno();
1518 }
1519 return 0;
1520 }
1521
1522 int
socket_mcast_inet_set_loop(int s,int enabled)1523 socket_mcast_inet_set_loop( int s, int enabled )
1524 {
1525 return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_LOOP, !!enabled );
1526 }
1527
1528 int
socket_mcast_inet_set_ttl(int s,int ttl)1529 socket_mcast_inet_set_ttl( int s, int ttl )
1530 {
1531 return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_TTL, ttl );
1532 }
1533
1534
1535 char*
host_name(void)1536 host_name( void )
1537 {
1538 static char buf[256]; /* 255 is the max host name length supported by DNS */
1539 int ret;
1540
1541 QSOCKET_CALL(ret, gethostname(buf, sizeof(buf)));
1542
1543 if (ret < 0)
1544 return "localhost";
1545 else
1546 return buf;
1547 }
1548