-1

Here UNix Domain server and client code that I am using. Server and Client messages each other by receiving message from each other.

Server code sents message to Client by from recvfrom by populating client_address. Moreover as u can see this unix domain socket code use abstract naming system. Server named as UnixServer, and client named as UnixClient. If server can send message to client by populating its client_address, I would like to see what is that address. Is that a meaningful address can I print it as #UdsClient etc?

server Code:

#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h> 
#include <string.h>

#include <unistd.h>`

#define SERVER_SOCKET "#UdsServer" // The # is replaced by 0 for abstract namespace

int main(void)
{
int socket_fd;
struct sockaddr_un server_address, client_address; 
int bytes_received, bytes_sent, integer_buffer;


socklen_t address_length = sizeof(server_address.sun_family)+strlen(SERVER_SOCKET );

if ((socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
{
    perror("server: socket");
    return -1;
}

memset(&server_address, 0, sizeof(server_address));
server_address.sun_family = AF_UNIX;
memcpy(server_address.sun_path, SERVER_SOCKET,sizeof(SERVER_SOCKET)-1);// the path is not a C string, and is not NULL turminated
server_address.sun_path[0] = 0; 

if (bind(socket_fd,
         (const struct sockaddr *) &server_address,
         address_length) < 0)
{
    perror("server: bind");
    close(socket_fd);        
    return -1;
}

for (;;)
{
    bytes_received = recvfrom(socket_fd,
                              &integer_buffer,
                              sizeof(integer_buffer),
                              0, 
                              (struct sockaddr *) &client_address,
                              &address_length);

    

    struct sockaddr_storage ss;
    socklen_t sslen = sizeof(struct sockaddr_storage);
    if (getsockname(socket_fd, (struct sockaddr *)&ss, &sslen) == 0) {
           struct sockaddr_un *un = (struct sockaddr_un *)&ss;
           printf("socket name is: %s\n", un->sun_path);
    }

    if(bytes_received != sizeof(integer_buffer))
    {
        printf("Error: recvfrom - %d.\n", bytes_received);

    } else {
        printf("received: %d.\n", integer_buffer);



        integer_buffer += 10;

        bytes_sent = sendto(socket_fd,
                            &integer_buffer,
                            sizeof(integer_buffer),
                            0,
                            (struct sockaddr *) &client_address, 
                            address_length);

    //printf("clientaddress: %s", client_address.sa_data);
    }
}

close(socket_fd);

return 0;
}

Client Code:

#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define SERVER_SOCKET "#UdsServer" 
#define CLIENT_SOCKET "#UdsClient"
int main(void)
{
int socket_fd;
struct sockaddr_un server_address, client_address; 
int bytes_received, bytes_sent, integer_buffer;
socklen_t address_length = sizeof(server_address.sun_family) + strlen(CLIENT_SOCKET);

if((socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
{
    perror("client: socket");
    return -1;
}

memset(&client_address, 0, sizeof(client_address));
client_address.sun_family = AF_UNIX;
memcpy(client_address.sun_path, CLIENT_SOCKET,sizeof(CLIENT_SOCKET )-1 );
client_address.sun_path[0] = 0;

if(bind(socket_fd,
        (const struct sockaddr *) &client_address, 
        address_length) < 0)
{
    perror("client: bind");
    return -1;
}

memset(&server_address, 0, sizeof(server_address));
server_address.sun_family = AF_UNIX;
memcpy(server_address.sun_path, SERVER_SOCKET,sizeof(SERVER_SOCKET)-1);
server_address.sun_path[0] = 0;

integer_buffer = 1;

for (;;)
{
   bytes_sent = sendto(socket_fd, 
                       &integer_buffer,
                       sizeof(integer_buffer),
                       0,
                       (struct sockaddr *) &server_address, 
                       address_length);
      printf("clientaddress: %s", server_address.sun_path);

   bytes_received = recvfrom(socket_fd,
                             &integer_buffer,
                             sizeof(integer_buffer),
                             0, 
                             (struct sockaddr *) &server_address,
                             &address_length);
     printf("clientaddress: %s", server_address.sun_path);

   if (bytes_received != sizeof(integer_buffer))
   {
       printf("Error: recvfrom - %d.\n", bytes_received);
       return -1;
   }

   printf("received: %d\n", integer_buffer);

   integer_buffer += 1;

   sleep(10);
}

close(socket_fd);

return 0;
}

Moreover I tried to print it by using these line of codes but it prints nothing:

   struct sockaddr_storage ss;
    socklen_t sslen = sizeof(struct sockaddr_storage);
    if (getsockname(socket_fd, (struct sockaddr *)&ss, &sslen) == 0) {
           struct sockaddr_un *un = (struct sockaddr_un *)&ss;
           printf("socket name is: %s\n", un->sun_path);
    } 

What am I doing wrong how to print #UdsClient, or any other meaning full thing?

EDIT, MY SOLUTION

This is relatively easy problem I believe. Instead of the last piece of code I could be able to read it as below:

printf("socket name is: #%s\n", client_address.sun_path + 1);

So the path gets populated however it cannot be directly printed out since the first letter is null.

Also u can use this method for nonAbstract file path systems.

Meric Ozcan
  • 678
  • 5
  • 25

1 Answers1

1

When you use %s as a format specifier for printf it will treat the associated parameter as a null terminated char array. However, you're making use of an abstract socket by setting...

server_address.sun_path[0] = 0;

Hence printf will treat server_address.sun_path as a zero length string -- it knows nothing about the data immediately after that leading null character.

G.M.
  • 12,232
  • 2
  • 15
  • 18
  • so what to do? Is there a way to read it? I would like to read this info because in my real system there would be multiple clients and I need their abstract naming – Meric Ozcan Aug 29 '20 at 08:57
  • If you're *absolutely* sure `un->sun_path` refers to an abstract socket name then you could try `printf("socket name is: #%s\n", un->sun_path + 1)` depending on how you want to represent the leading null character. – G.M. Aug 29 '20 at 09:09
  • Thanks but it prints UdsServer as address. But I found a solution – Meric Ozcan Aug 29 '20 at 09:20
  • can u upvote my question? and I can select u as answer. – Meric Ozcan Aug 29 '20 at 09:27