/* radare - LGPL - Copyright 2006-2010 pancake */ #define USE_SOCKETS #include #include #include #include #include #include #include #include #include #include #include #if __UNIX__ #include #include #include #include #include #include #include #endif #define BUFFER_SIZE 4096 R_API int r_socket_write(int fd, void *buf, int len) { int ret, delta = 0; for (;;) { ret = send(fd, buf+delta, len, 0); if (ret == 0) return -1; if (ret == len) return len; if (ret<0) break; delta+=ret; len-=ret; } if (ret == -1) return -1; return delta; } R_API int r_socket_puts(int fd, char *buf) { int len = strlen (buf); return r_socket_write (fd, buf, len); } // XXX: rewrite it to use select // /* waits secs until new data is received. */ /* returns -1 on error, 0 is false, 1 is true */ R_API int r_socket_ready(int fd, int secs, int usecs) { #if __UNIX__ int ret; struct pollfd fds[1]; fds[0].fd = fd; fds[0].events = POLLIN|POLLPRI; fds[0].revents = POLLNVAL|POLLHUP|POLLERR; ret = poll((struct pollfd *)&fds, 1, usecs); return ret; #elif __WINDOWS__ fd_set rfds; struct timeval tv; int retval; if (fd==-1) return -1; FD_ZERO(&rfds); FD_SET(fd, &rfds); tv.tv_sec = secs; tv.tv_usec = usecs; retval = select (1, &rfds, NULL, NULL, &tv); if (retval==-1) return -1; return FD_ISSET(0, &rfds); #else return 1; /* always ready if unknown */ #endif } R_API void r_socket_block(int fd, int block) { #if __UNIX__ fcntl (fd, F_SETFL, O_NONBLOCK, !block); #elif __WINDOWS__ ioctlsocket (fd, FIONBIO, (u_long FAR*)&block); #endif } R_API void r_socket_printf(int fd, const char *fmt, ...) { char buf[BUFFER_SIZE]; va_list ap; if (fd < 0) return; va_start(ap, fmt); vsnprintf(buf, BUFFER_SIZE, fmt, ap); r_socket_write(fd, buf, strlen(buf)); va_end(ap); } #if __UNIX__ R_API int r_socket_unix_connect(const char *file) { struct sockaddr_un addr; int sock; sock = socket (PF_UNIX, SOCK_STREAM, 0); if (sock <0) return -1; // TODO: set socket options addr.sun_family = AF_UNIX; strncpy (addr.sun_path, file, sizeof(addr.sun_path)); if (connect(sock, (struct sockaddr *)&addr, sizeof(addr))==-1) { close(sock); return -1; } return sock; } R_API int r_socket_unix_listen(const char *file) { struct sockaddr_un unix_name; int sock; sock = socket(PF_UNIX, SOCK_STREAM, 0); if (sock <0) return -1; // TODO: set socket options unix_name.sun_family = AF_UNIX; strncpy (unix_name.sun_path, file, sizeof(unix_name.sun_path)); /* just to make sure there is no other socket file */ unlink (unix_name.sun_path); if (bind (sock, (struct sockaddr *) &unix_name, sizeof (unix_name)) < 0) return -1; signal(SIGPIPE, SIG_IGN); /* change permissions */ if (chmod (unix_name.sun_path, 0777) != 0) return -1; if (listen(sock, 1)) return -1; return sock; } #endif R_API int r_socket_connect(char *host, int port) { struct sockaddr_in sa; struct hostent *he; int s; #if __WINDOWS__ WSADATA wsadata; if (WSAStartup(MAKEWORD(1,1), &wsadata) == SOCKET_ERROR) { eprintf("Error creating socket."); return -1; } #endif #if __UNIX__ signal(SIGPIPE, SIG_IGN); #endif s = socket(AF_INET, SOCK_STREAM, 0); if (s == -1) return -1; memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; he = (struct hostent *)gethostbyname( host ); if (he == (struct hostent*)0) { close (s); return -1; } sa.sin_addr = *((struct in_addr *)he->h_addr); sa.sin_port = htons( port ); if (connect(s, (const struct sockaddr*)&sa, sizeof(struct sockaddr))) { close (s); return -1; } return s; } R_API int r_socket_listen(int port) { int ret, s; struct sockaddr_in sa; struct linger linger = { 0 }; linger.l_onoff = 1; linger.l_linger = 1; s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s <0) return -1; setsockopt(s, SOL_SOCKET, SO_LINGER, (const char *) &linger, sizeof(linger)); memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_ANY); sa.sin_port = htons( port ); ret = bind(s, (struct sockaddr *)&sa, sizeof(sa)); if (ret < 0) return -1; ret = listen(s, 1); if (ret < 0) return -1; return s; } R_API int r_socket_close(int fd) { #if __UNIX__ shutdown(fd, SHUT_RDWR); return close(fd); #else WSACleanup(); return closesocket(fd); #endif } R_API int r_socket_read_block(int fd, unsigned char *buf, int len) { int r, ret = 0; for (ret=0;retsin_addr); if ((str = malloc(32))) sprintf (str, "%d.%d.%d.%d:%d", a[0],a[1],a[2],a[3], ntohs (sain->sin_port)); } else eprintf ("getperrname: failed\n"); //r_sys_perror ("getpeername"); #endif return str; #endif } R_API int r_socket_udp_connect(const char *host, int port) { struct sockaddr_in sa; struct hostent *he; int s; #if __WINDOWS__ WSADATA wsadata; if (WSAStartup (MAKEWORD (1,1), &wsadata) == SOCKET_ERROR) { eprintf ("Error creating socket."); return -1; } #endif #if __UNIX__ signal (SIGPIPE, SIG_IGN); #endif s = socket (AF_INET, SOCK_DGRAM, 0); if (s == -1) return -1; memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; he = (struct hostent *)gethostbyname (host); if (he == (struct hostent*)0) { close (s); return -1; } sa.sin_addr = *((struct in_addr *)he->h_addr); sa.sin_port = htons( port ); if (connect (s, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) { close (s); return -1; } return s; }