#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ucred.h>
#include <netinet/in.h>
#include <arpa/inet.h>
static void probe(int fd, const char *label){
  struct xucred cr; memset(&cr,0,sizeof cr); socklen_t len=sizeof cr;
  int r=getsockopt(fd,SOL_LOCAL,LOCAL_PEERCRED,&cr,&len);
  printf("%-8s getsockopt=%d errno=%d len=%u cr_version=%u (XUCRED_VERSION=%u) cr_uid=%u\n",
    label,r,r?errno:0,(unsigned)len,cr.cr_version,XUCRED_VERSION,cr.cr_uid);
}
int main(void){
  printf("SOL_LOCAL=%d IPPROTO_IP=%d LOCAL_PEERCRED=%d IP_OPTIONS=%d my uid=%u\n",SOL_LOCAL,IPPROTO_IP,LOCAL_PEERCRED,IP_OPTIONS,getuid());
  int ls=socket(AF_INET,SOCK_STREAM,0); struct sockaddr_in a={0}; a.sin_family=AF_INET; a.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
  bind(ls,(void*)&a,sizeof a); listen(ls,1); socklen_t al=sizeof a; getsockname(ls,(void*)&a,&al);
  int c=socket(AF_INET,SOCK_STREAM,0); connect(c,(void*)&a,sizeof a); int s=accept(ls,0,0); probe(s,"AF_INET");
  char path[]="/tmp/p42-growth-peercred.sock"; unlink(path);
  int lu=socket(AF_UNIX,SOCK_STREAM,0); struct sockaddr_un u={0}; u.sun_family=AF_UNIX; strcpy(u.sun_path,path);
  bind(lu,(void*)&u,sizeof u); listen(lu,1); int cu=socket(AF_UNIX,SOCK_STREAM,0); connect(cu,(void*)&u,sizeof u);
  int su=accept(lu,0,0); probe(su,"AF_UNIX"); unlink(path); return 0;
}
