Assigning source address (IP:port) from grpc c++ client

689 views
Skip to first unread message

Sachin Bharadwaj S

unread,
Sep 27, 2022, 6:03:42 PM9/27/22
to grpc.io
Hi All,

Is there a way to designate a source IP and PORT from grpc c++ client?

Generally, on the client side, we specify the IP and PORT of the server's listening port to connect to and we don't care about the client's IP and port. When a client tries to create a channel, it assigns a random unused port for the outgoing connection and uses the IP which has reachability towards the server.

But, generally, in systems that have multiple interfaces and multiple IP addresses, can the application decide which outgoing interface/IP/port to be used for the connection?

I have used SetSocketMutator() and during the creation of fd, grpc stack gives a callback to the application and the application can mutate the fd to perform any add-on setsockopt() on the fd to change its behavior.
In the same callback, if I try to perform bind() to a source address and port, it gives an "Invalid argument" error.

Code snippet for reference:

bool mutate_fd_callback(const grpc_mutate_socket_info* info,

                    grpc_socket_mutator* mutator) {


    int ret = 0;

    struct   sockaddr_in addr;

    memset(&addr, '\0', sizeof(addr));


    addr.sin_addr.s_addr = inet_addr("20.0.0.1");

    addr.sin_port = htons(51234);

    addr.sin_family = AF_INET;


    ret = ::bind(info->fd, (struct sockaddr *)&addr, sizeof(struct sockaddr));


Does the grpc stack itself does a bind() internally and the application has no control over choosing its own IP/port? Or is there any other way of specifying src IP/PORT instead of bind()?

Please correct me if I'm wrong in any of the above understanding.

Regards,
Sachin

Sachin Bharadwaj S

unread,
Sep 30, 2022, 6:22:17 PM9/30/22
to grpc.io
Hi,

Just wanted to check on this again. Is this something possible or not supported in grpc c++?
Any inputs regarding this is highly appreciated.

Regards,
Sachin

Manish Khandelwal

unread,
Feb 2, 2023, 11:20:43 PM2/2/23
to grpc.io
Hi Sachin, 

I am having the same use case scenario.
Did your issue got resolved or in case if you followed any other approach to achieve this.

Requesting to please share the details. 

Thanks & Regards
Manish Khandelwal

Sachin Bharadwaj S

unread,
Feb 6, 2023, 3:07:39 PM2/6/23
to Manish Khandelwal, grpc.io
Hi Manish,

Yes it worked by binding to IPv6 (Prepend "::ffff:" to your IPv4 address)

The code looks something like this:

bool mutate_fd_callback(const grpc_mutate_socket_info* info,

                    grpc_socket_mutator* mutator) {


   int ret = 0;

    struct sockaddr_in6 addr;
    memset(&addr, '\0', sizeof(addr));
    addr.sin6_family = AF_INET6;
    addr.sin6_port = htons(51234);
    std::string src = "::ffff:20.0.0.1";
    inet_pton(AF_INET6, src.c_str(), &addr.sin6_addr);

    ret = bind(info->fd, (struct sockaddr *)&addr, sizeof(addr));

Regards,
Sachin

--
You received this message because you are subscribed to the Google Groups "grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email to grpc-io+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/grpc-io/3c8c001a-e278-4c59-aeac-d07f8f51b286n%40googlegroups.com.
Message has been deleted

Yasoob Khalid

unread,
Jun 30, 2023, 1:30:38 PM6/30/23
to grpc.io
Hi future readers, 

This is just a note for others who might be in a similar situation. The reason Sachin had to use IPv6 was because grpc.core uses dual-stack sockets (at least on windows and that is what I cared for). There is no IPv4 socket to mutate. The socket file descriptor returned by `info->fd` is for a dual-stack socket. Grpc.core will use the same socket to connect to IPv4 and IPv6 remote addresses. Just translate your IPv4 address to IPv6 format and use that as the source. This should do the trick. Read more about dual-stack sockets to understand what I am talking about.

I hope this helps others who are new to this stuff.

~ Yasoob

Kuldip Patel

unread,
Apr 3, 2024, 2:00:48 PMApr 3
to grpc.io
Hello Sachin,
My need is to attach vrf to grpc socket while creation so that it can communcate via interface/vrf. I have come up with below assumed code but i m not sure i can do it.
Any working example would be helpful

class MySocketMutator : public grpc::ChannelArguments::SocketMutator {
public:
    // Override the Mutate function
    void Mutate(grpc_impl::unique_fd* fd) override {
        auto loggr = Logger::getInstance();
        // Here you can perform any custom modifications to the socket, such as setting socket options
        // For example, you can use setsockopt to set specific source interfaces or VRFs
       grpc_impl::ChannelArguments::SocketMutator::Mutate(fd);
        // Example: Set the SO_BINDTODEVICE option to bind the socket to a specific network interface
        const char* interfaceName = "mgmt"; // Replace with your desired interface name
        if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, interfaceName, strlen(interfaceName) + 1) < 0) {
            perror("setsockopt SO_BINDTODEVICE");
            loggr->error("kuldip mutator setting failed.",LOG_INF);
            // Handle error
        }
    loggr->error("kuldip mutator setting called and done.",LOG_INF);
    }
};

 loggr->error("kuldip channel creation starting.",LOG_INF);
    std::shared_ptr<MySocketMutator> socketMutator = std::make_shared<MySocketMutator>();
    // Set up channel arguments
    grpc::ChannelArguments channelArgs;
    // Set the socket mutator
    loggr->error("kuldip mutator setting.",LOG_INF);
    //channelArgs.SetSocketMutator(socketMutator.get());
    MySocketMutator* rawPtr = socketMutator.get();
    channelArgs.SetSocketMutator(rawPtr);

    // Create a channel with the specified options
    std::shared_ptr<grpc::Channel> channel = grpc::CreateCustomChannel(
           collectoraddress, grpc::InsecureChannelCredentials(), channelArgs);

    // Create the RegistrationClient using the custom channel
   RegistrationClient registration(channel);
   bool rpcreply = registration.RegistrationInfo(RegDetails, RegistrationStatus);
Can u help here if you how can i do it?
Reply all
Reply to author
Forward
0 new messages