1

I've got process that listen to unix socket. However, before i read, i'd like to check some meta data about this incoming message such as it's source process (say i'd like to drop messages from non trusted senders). is there any syscall that retrieve this information.

    if(listen(sock_fd, 10) != 0) {
        assert("listen failed");
    }

    while((conn_fd = accept(sock_fd,
                       (struct sockaddr *) &address,
                       &address_length)) != -1) {
        int nbytes = 0;
        static char buffer[PAYLOAD_SZ];
        nbytes = (int)read(conn_fd, buffer, PAYLOAD_SZ);
alk
  • 69,737
  • 10
  • 105
  • 255
Zohar81
  • 4,554
  • 5
  • 29
  • 82
  • _Trusted_ based on what? – LPs Jul 04 '16 at 12:54
  • BTW it smells like a [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). So what is you real aim? What do you want to achieve? Could be a first handshake, after connection accept, a solution for you? I mean the client ask for a connection and, base on something, the server accept or close the connection. – LPs Jul 04 '16 at 13:04
  • @LPs, thanks for you comment. perhaps my phrasing wasn't clear enough. I'd like to allow reading messages from specific processes (pids) based on a predefined list. therefore, when I pop a new message from socket queue, I'd like to verify its origin. – Zohar81 Jul 04 '16 at 14:12
  • Well, how could you have a _predefined list_ of pids? Have those processes fixed PIDs? If not, as I commented, couldn't be a solution accept the connection, ask for PID number and a password/hash/whatever to validate the connection and than add the specific connection to the white list? – LPs Jul 04 '16 at 14:28
  • @LPs, the predefined list is fixed and it's given as an input to the listener process. – Zohar81 Jul 04 '16 at 14:51
  • So AFAIK you must perform an "handshake" to get infos you need. Tale a look at [this SO post](http://stackoverflow.com/questions/16470715/is-there-a-way-to-find-pid-of-a-process-of-socket-peer) Maybe it helps. – LPs Jul 04 '16 at 15:00
  • I am not aware of any possibility to pull the connecting side's PID from whatever kind of socket. – alk Jul 04 '16 at 16:04
  • "*some meta data*" if it's more then the PID you need, please tell us. – alk Jul 04 '16 at 16:05
  • Adding up to my 1st comment: "*to pull*" without accepting the connection. – alk Jul 04 '16 at 16:12
  • @alk, No, at this stage i only need the PID of the sender process. – Zohar81 Jul 04 '16 at 16:29

3 Answers3

6

After doing some research, I've found the answer that is most suitable for my needs.

using getsockopt i was able to get the peer pid.

getsockopt(fd,SOCK_STREAM, LOCAL_PEERPID, &pid, &pid_len); 

using this function i'm also capable to collect peer credentials, and more. just need to verify that the peer doesn't close the socket when this query is sent.

Zohar81
  • 4,554
  • 5
  • 29
  • 82
0

For linux kernel 3.3 and its later versions, you have the command line ss -xp.

This question on Unix & Linux has a good discussion and answers that might help you understand.

Community
  • 1
  • 1
ViKiG
  • 764
  • 9
  • 21
  • I forgot to mention that I work under OSX platform, that support unix socket, but doesn't have /proc folder. I believe that each item on the listener queue (there are up to 'backlog' pending items) has meta data that describe the pid of the origin process that wrote this message. I wonder if there's a C api to retrieve this information... – Zohar81 Jul 04 '16 at 14:57
  • And, does `ss` provide the PID of any connecting process sitting the backlog? – alk Jul 04 '16 at 17:19
  • I believe not. If the connection queue is exhausted, the connection request might simply get refused. Then there might be no case of getting the PID of the process. – ViKiG Jul 04 '16 at 18:34
-1

getpeername() may be what you are looking for. Example code :

// assume s is a connected socket

socklen_t len;
struct sockaddr_storage addr;
char ipstr[INET6_ADDRSTRLEN];
int port;

len = sizeof addr;
getpeername(s, (struct sockaddr*)&addr, &len);

// deal with both IPv4 and IPv6:
if (addr.ss_family == AF_INET) {
    struct sockaddr_in *s = (struct sockaddr_in *)&addr;
    port = ntohs(s->sin_port);
    inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
} else { // AF_INET6
    struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
    port = ntohs(s->sin6_port);
    inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
}

printf("Peer IP address: %s\n", ipstr);
printf("Peer port      : %d\n", port);
evaitl
  • 1,365
  • 8
  • 16
  • Well, and if `LOCALHOST` (`127.0.0.1`) is used? – LPs Jul 04 '16 at 13:04
  • getpeername() still works if the peer is on the same host, unless I am missing what you are saying. – evaitl Jul 04 '16 at 16:12
  • I meant that you cannot recognize different processes on the same machine. – LPs Jul 04 '16 at 16:29
  • getpeername() will get the port # of the peer. If you do an strace of `lsof -i :###` it looks like it opens and reads all of the /proc//fdinfo files to find a matching port number and print the pid. Probably not useful to OP. Perhaps push OP to use an SSL connection to verify clients? Seems like a big step for someone who is getting a handle on sockets. – evaitl Jul 04 '16 at 16:58
  • OP is working specifically with [Unix domain sockets](https://en.wikipedia.org/wiki/Unix_domain_socket " "), not with IP. – Kotauskas Jul 04 '20 at 11:25