INTERPOSE (accept, int, int sockfd, struct sockaddr * addr, socklen_t * addrlen) { v4v_addr_t peer; int ret; CHECK_INTERPOSE (accept); if (!is_our_fd (sockfd)) return orig_accept (sockfd, addr, addrlen); ret = v4v_accept (sockfd, &peer); register_fd (ret); if (is_our_af (sockfd)) { v4v_map_v4va_to_sxenv4v (addr, addrlen, &peer); } else { v4v_map_v4va_to_sin (addr, addrlen, &peer); } return ret; }
INTERPOSE (connect, int, int sockfd, const struct sockaddr * addr, socklen_t addrlen) { v4v_addr_t peer, me; char *val, *end; int addend, ret; CHECK_INTERPOSE (connect); if (!is_our_fd (sockfd)) return orig_connect (sockfd, addr, addrlen); if (v4v_map_sa_to_v4va (&peer, addr, addrlen)) return -EINVAL; /* Bind the socket to a specific port if requested */ val = getenv ("V4V_CLIENT_PORT_ADDEND"); if (val != NULL) { addend = strtol(val, &end, 10); /* Sanitize the addend */ if (end == NULL || *end != '\0' || addend < 0) return -EINVAL; me.domain = V4V_DOMID_ANY; me.port = peer.port + addend; DEBUG_PRINTF ("BINDING CLIENT TO port %d\n", (int) me.port); DEBUG_PRINTF (" AND SET %d AS THE PARTNER\n", (int) peer.domain); ret = v4v_bind(sockfd, &me, peer.domain); if (ret) return ret; } DEBUG_PRINTF ("CONNECTING TO %d:%d\n", (int) peer.domain, (int) peer.port); return v4v_connect (sockfd, &peer); }
INTERPOSE (shutdown, int, int sockfd, int how) { CHECK_INTERPOSE (shutdown); if (!is_our_fd (sockfd)) return orig_shutdown (sockfd, how); return 0; }
INTERPOSE (recv, ssize_t, int sockfd, void *buf, size_t len, int flags) { CHECK_INTERPOSE (recv); if (!is_our_fd (sockfd)) return orig_recv (sockfd, buf, len, flags); return v4v_recv (sockfd, buf, len, flags); }
INTERPOSE (send, ssize_t, int sockfd, const void *buf, size_t len, int flags) { CHECK_INTERPOSE (send); if (!is_our_fd (sockfd)) return orig_send (sockfd, buf, len, flags); return v4v_send (sockfd, buf, len, flags); }
INTERPOSE (getsockopt, int, int sockfd, int level, int optname, void *optval, socklen_t * optlen) { int ret; CHECK_INTERPOSE (getsockopt); if (!is_our_fd (sockfd)) return orig_getsockopt (sockfd, level, optname, optval, optlen); return v4v_getsockopt (sockfd, level, optname, optval, optlen); }
INTERPOSE (listen, int, int sockfd, int backlog) { int ret; CHECK_INTERPOSE (listen); if (!is_our_fd (sockfd)) return orig_listen (sockfd, backlog); return v4v_listen (sockfd, backlog); }
INTERPOSE (setsockopt, int, int sockfd, int level, int optname, const void *optval, socklen_t optlen) { CHECK_INTERPOSE (setsockopt); if (!is_our_fd (sockfd)) return orig_setsockopt (sockfd, level, optname, optval, optlen); if ((level == SOL_SOCKET) && (optname == SO_KEEPALIVE)) { /* Can be safely ignored */ return 0; } if ((level == SOL_SOCKET) && (optname == SO_REUSEADDR)) { //FIXME return 0; } if ((level == SOL_SOCKET) && (optname == SO_LINGER)) { //FIXME return 0; } if ((level == IPPROTO_IP) && (optname == IP_PKTINFO)) { //FIXME return 0; } if ((level == IPPROTO_IP) && (optname == IP_TOS)) { /* Can be safely ignored */ return 0; } if ((level == IPPROTO_IP) && (optname == IP_TTL)) { /* Can be safely ignored */ return 0; } if ((level == IPPROTO_TCP) && (optname == TCP_NODELAY)) { //FIXME return 0; } DEBUG_PRINTF ("unknown setsockopt %d %d %d %p %d\n", sockfd, level, optname, optval, optlen); errno = ENOPROTOOPT; return -1; }
INTERPOSE (sendto, ssize_t, int sockfd, const void *buf, size_t len, int flags, const struct sockaddr * dest_addr, socklen_t addrlen) { v4v_addr_t peer; CHECK_INTERPOSE (sendto); if (!is_our_fd (sockfd)) return orig_sendto (sockfd, buf, len, flags, dest_addr, addrlen); if (dest_addr && v4v_map_sa_to_v4va (&peer, dest_addr, addrlen)) return -EINVAL; return v4v_sendto (sockfd, buf, len, flags, dest_addr ? &peer : NULL); }
INTERPOSE (connect, int, int sockfd, const struct sockaddr * addr, socklen_t addrlen) { v4v_addr_t peer; CHECK_INTERPOSE (connect); if (!is_our_fd (sockfd)) return orig_connect (sockfd, addr, addrlen); if (v4v_map_sa_to_v4va (&peer, addr, addrlen)) return -EINVAL; DEBUG_PRINTF ("CONNECTING TO %d:%d\n", (int) peer.domain, (int) peer.port); return v4v_connect (sockfd, &peer); }
INTERPOSE (bind, int, int sockfd, const struct sockaddr * addr, socklen_t addrlen) { v4v_addr_t v4va; CHECK_INTERPOSE (bind); if (!is_our_fd (sockfd)) return orig_bind (sockfd, addr, addrlen); if (addr->sa_family == AF_XENV4V) register_af (sockfd); else unregister_af (sockfd); if (v4v_map_sa_to_v4va (&v4va, addr, addrlen)) return -EINVAL; return v4v_bind (sockfd, &v4va, getenv ("V4V_ACCEPT_DOM0_ONLY") ? 0 : V4V_DOMID_NONE); }
INTERPOSE (sendmsg, ssize_t, int sockfd, const struct msghdr * msg, int flags) { struct msghdr v4vmsg; v4v_addr_t v4va; CHECK_INTERPOSE (sendmsg); if (!is_our_fd (sockfd)) return orig_sendmsg (sockfd, msg, flags); if (!msg) return -EINVAL; v4vmsg = *msg; if (v4vmsg.msg_name) { if (v4v_map_sa_to_v4va(&v4va, v4vmsg.msg_name, v4vmsg.msg_namelen)) return -EINVAL; v4vmsg.msg_name = &v4va; v4vmsg.msg_namelen = sizeof(v4va); } return v4v_sendmsg (sockfd, &v4vmsg, flags); }
INTERPOSE (getpeername, int, int sockfd, struct sockaddr * addr, socklen_t * addrlen) { ssize_t ret; v4v_addr_t ring_addr = { 0 }; CHECK_INTERPOSE (getpeername); if (!is_our_fd (sockfd)) return orig_getpeername (sockfd, addr, addrlen); ret = v4v_getpeername (sockfd, &ring_addr); if (is_our_af (sockfd)) { v4v_map_v4va_to_sxenv4v (addr, addrlen, &ring_addr); } else { v4v_map_v4va_to_sin (addr, addrlen, &ring_addr); } return ret; }
INTERPOSE (recvfrom, ssize_t, int sockfd, void *buf, size_t len, int flags, struct sockaddr * src_addr, socklen_t * addrlen) { ssize_t ret; v4v_addr_t peer = { 0 }; CHECK_INTERPOSE (recvfrom); if (!is_our_fd (sockfd)) return orig_recvfrom (sockfd, buf, len, flags, src_addr, addrlen); ret = v4v_recvfrom (sockfd, buf, len, flags, &peer); if (is_our_af (sockfd)) { v4v_map_v4va_to_sxenv4v (src_addr, addrlen, &peer); } else { v4v_map_v4va_to_sin (src_addr, addrlen, &peer); } return ret; }
INTERPOSE (recvmsg, ssize_t, int sockfd, struct msghdr * msg, int flags) { struct v4v_addr peer; struct msghdr my_msg = *msg; ssize_t ret; CHECK_INTERPOSE (recvmsg); if (!is_our_fd (sockfd)) return orig_recvmsg (sockfd, msg, flags); if (msg->msg_name) { my_msg.msg_name = &peer; } ret = v4v_recvmsg (sockfd, &my_msg, flags); if (msg->msg_name) { if (is_our_af (sockfd)) { v4v_map_v4va_to_sxenv4v (msg->msg_name, &msg->msg_namelen, &peer); } else { v4v_map_v4va_to_sin (msg->msg_name, &msg->msg_namelen, &peer); } } msg->msg_controllen = my_msg.msg_controllen; return ret; }