SOCKET Socket_ConnectVMCI(unsigned int cid, // IN unsigned int port, // IN gboolean isPriv, // IN SockConnError *outError) // OUT { struct sockaddr_vm addr; SOCKET fd; SockConnError error = SOCKERR_GENERIC; int sysErr; socklen_t addrLen = sizeof addr; int vsockDev = -1; int family = VMCISock_GetAFValueFd(&vsockDev); if (outError) { *outError = SOCKERR_SUCCESS; } if (!SocketStartup()) { goto error; } if (family == -1) { Warning(LGPFX "Couldn't get VMCI socket family info."); goto error; } memset((char *)&addr, 0, sizeof addr); addr.svm_family = family; addr.svm_cid = cid; addr.svm_port = port; Debug(LGPFX "creating new socket, connecting to %u:%u\n", cid, port); fd = socket(addr.svm_family, SOCK_STREAM, 0); if (fd == INVALID_SOCKET) { sysErr = SocketGetLastError(); Warning(LGPFX "failed to create socket, error %d: %s\n", sysErr, Err_Errno2String(sysErr)); goto error; } if (isPriv) { struct sockaddr_vm localAddr; gboolean bindOk = FALSE; int localPort; memset(&localAddr, 0, sizeof localAddr); localAddr.svm_family = addr.svm_family; localAddr.svm_cid = VMCISock_GetLocalCID(); /* Try to bind to port 1~1023 for a privileged user. */ for (localPort = PRIVILEGED_PORT_MAX; localPort >= PRIVILEGED_PORT_MIN; localPort--) { localAddr.svm_port = localPort; if (bind(fd, (struct sockaddr *)&localAddr, sizeof localAddr) != 0) { sysErr = SocketGetLastError(); if (sysErr == SYSERR_EACCESS) { Warning(LGPFX "Couldn't bind to privileged port for " "socket %d\n", fd); error = SOCKERR_EACCESS; Socket_Close(fd); goto error; } if (sysErr == SYSERR_EADDRINUSE) { continue; } Warning(LGPFX "could not bind socket, error %d: %s\n", sysErr, Err_Errno2String(sysErr)); Socket_Close(fd); error = SOCKERR_BIND; goto error; } else { bindOk = TRUE; break; } } if (!bindOk) { Warning(LGPFX "Failed to bind to privileged port for socket %d, " "no port available\n", fd); error = SOCKERR_BIND; Socket_Close(fd); goto error; } else { Debug(LGPFX "Successfully bound to port %d for socket %d\n", localAddr.svm_port, fd); } } if (connect(fd, (struct sockaddr *)&addr, addrLen) != 0) { sysErr = SocketGetLastError(); Warning(LGPFX "socket connect failed, error %d: %s\n", sysErr, Err_Errno2String(sysErr)); Socket_Close(fd); error = SOCKERR_CONNECT; goto error; } VMCISock_ReleaseAFValueFd(vsockDev); Debug(LGPFX "socket %d connected\n", fd); return fd; error: if (outError) { *outError = error; } VMCISock_ReleaseAFValueFd(vsockDev); return INVALID_SOCKET; }
int main() { int listen_fd, client_fd, nfds; uint64_t buf_size, t; socklen_t size; struct sockaddr_vm my_addr = {0}, their_addr; int vmci_address_family; fd_set read_fds; unsigned int cid; uint8_t buf[BUFSIZE]; socket_startup(); if ((vmci_address_family = VMCISock_GetAFValue()) < 0) { fprintf(stderr, "VMCISock_GetAFValue failed: %d. You probably need root privileges\n", vmci_address_family); goto cleanup; } if ((listen_fd = socket(vmci_address_family, SOCK_STREAM, 0)) == -1) { perror("socket"); goto cleanup; } /* * SO_VMCI_BUFFER_SIZE – Default size of communicating buffers; 65536 bytes if not set. * SO_VMCI_BUFFER_MIN_SIZE – Minimum size of communicating buffers; defaults to 128 bytes. * SO_VMCI_BUFFER_MAX_SIZE – Maximum size of communicating buffers; defaults to 262144 bytes. */ buf_size = 32768; /* reduce buffer to above size and check */ if (setsockopt(listen_fd, vmci_address_family, SO_VMCI_BUFFER_SIZE, (void *)&buf_size, sizeof(buf_size)) == -1) { perror("setsockopt"); goto close; } size = sizeof(t); if (getsockopt(listen_fd, vmci_address_family, SO_VMCI_BUFFER_SIZE, (void *)&t, &size) == -1) { perror("getsockopt"); goto close; } if (t != buf_size) { fprintf(stderr, "SO_VMCI_BUFFER_SIZE not set to size requested.\n"); goto close; } my_addr.svm_family = vmci_address_family; my_addr.svm_cid = VMADDR_CID_ANY; my_addr.svm_port = VMADDR_PORT_ANY; if (bind(listen_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) == -1) { perror("bind"); goto close; } if ((cid = VMCISock_GetLocalCID()) == (unsigned int)-1) { fprintf(stderr, "VMCISock_GetLocalCID failed\n"); } else { fprintf(stderr, "server cid: %u\n", cid); } size = sizeof(my_addr); if (getsockname(listen_fd, (struct sockaddr *)&my_addr, &size) == -1) { perror("getsockname"); goto close; } fprintf(stderr, "server (cid, port): %u:%u\n", my_addr.svm_cid, my_addr.svm_port); for (;;) { if (listen(listen_fd, CONNECTION_BACKLOG) == -1) { perror("listen"); goto close; } size = sizeof(their_addr); if ((client_fd = accept(listen_fd, (struct sockaddr *) &their_addr, &size)) == -1) { perror("accept"); goto close; } fprintf(stderr, "client connected\n"); FD_ZERO(&read_fds); FD_SET(client_fd, &read_fds); nfds = client_fd + 1; if (select(nfds, &read_fds, NULL, NULL, NULL) == -1) { perror("select"); goto close; } if (FD_ISSET(client_fd, &read_fds)) { ssize_t s; if ((s = recv(client_fd, (void*)buf, sizeof(buf), 0)) < 0) { fprintf(stderr, "recv failed: %s\n", strerror(errno)); } else { int i; fprintf(stderr, "recved %lld bytes\n", (long long int)s); for (i=0; i<s; i++) { putc(buf[i], stderr); } putc('\n', stderr); } } close(client_fd); } close: socket_close(listen_fd); cleanup: socket_cleanup(); return 0; }