getnetconn.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       getnetconn.c (2498B)
       ---
            1 #include <u.h>
            2 #define NOPLAN9DEFINES
            3 #include <libc.h>
            4 
            5 #include <sys/socket.h>
            6 #include <netinet/in.h>
            7 #include <netinet/tcp.h>
            8 #include <sys/un.h>
            9 #include <errno.h>
           10 
           11 #undef sun
           12 #define sun sockun
           13 
           14 extern int _p9netfd(char*);
           15 
           16 static char *unknown = "unknown";
           17 
           18 static int
           19 convert(int s, struct sockaddr *sa, char **lsys, char **lserv, char **laddr)
           20 {
           21         struct sockaddr_un *sun;
           22         struct sockaddr_in *sin;
           23         uchar *ip;
           24         u32int ipl;
           25         socklen_t sn;
           26         int n;
           27         char *net;
           28         
           29         switch(sa->sa_family){
           30         case AF_INET:
           31                 sin = (void*)sa;
           32                 ip = (uchar*)&sin->sin_addr;
           33                 ipl = *(u32int*)ip;
           34                 if(ipl == 0)
           35                         *lsys = strdup("*");
           36                 else
           37                         *lsys = smprint("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
           38                 *lserv = smprint("%d", ntohs(sin->sin_port));
           39                 sn = sizeof n;
           40                 if(getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) < 0)
           41                         return -1;
           42                 if(n == SOCK_STREAM)
           43                         net = "tcp";
           44                 else if(n == SOCK_DGRAM)
           45                         net = "udp";
           46                 else{
           47                         werrstr("unknown network type");
           48                         return -1;
           49                 }
           50                 *laddr = smprint("%s!%s!%s", net, *lsys, *lserv);
           51                 if(*lsys == nil || *lserv == nil || *laddr == nil)
           52                         return -1;
           53                 return 0;
           54         case AF_UNIX:
           55                 sun = (void*)sa;
           56                 *lsys = unknown;
           57                 *lserv = unknown;
           58                 *laddr = smprint("unix!%s", sun->sun_path);
           59                 if(*laddr == nil)
           60                         return -1;
           61                 return 0;
           62         default:
           63                 werrstr("unknown socket family");
           64                 return -1;
           65         }
           66 }
           67 
           68 NetConnInfo*
           69 getnetconninfo(char *dir, int fd)
           70 {
           71         socklen_t sn;
           72         union {
           73                 struct sockaddr sa;
           74                 struct sockaddr_in sin;
           75                 struct sockaddr_un sun;
           76         } u;
           77         NetConnInfo *nci;
           78 
           79         if(dir){
           80                 if((fd = _p9netfd(dir)) < 0){
           81                         werrstr("no such network connection %s", dir);
           82                         return nil;
           83                 }
           84         }
           85 
           86         nci = mallocz(sizeof *nci, 1);
           87         if(nci == nil)
           88                 goto err;
           89         nci->dir = smprint("/dev/fd/%d", fd);
           90         nci->root = strdup("/net");
           91         nci->spec = unknown;
           92         if(nci->dir == nil || nci->root == nil)
           93                 goto err;
           94         sn = sizeof u;
           95         if(getsockname(fd, &u.sa, &sn) < 0)
           96                 goto err;
           97         if(convert(fd, &u.sa, &nci->lsys, &nci->lserv, &nci->laddr) < 0)
           98                 goto err;
           99         sn = sizeof u;
          100         if(getpeername(fd, &u.sa, &sn) < 0)
          101                 goto err;
          102         if(convert(fd, &u.sa, &nci->rsys, &nci->rserv, &nci->raddr) < 0)
          103                 goto err;
          104         return nci;
          105 
          106 err:
          107         freenetconninfo(nci);
          108         return nil;
          109 }
          110 
          111 static void
          112 xfree(void *v)
          113 {
          114         if(v != nil && v != unknown)
          115                 free(v);
          116 }
          117 
          118 void
          119 freenetconninfo(NetConnInfo *nci)
          120 {
          121         if(nci == nil)
          122                 return;
          123         xfree(nci->dir);
          124         xfree(nci->root);
          125         xfree(nci->spec);
          126         xfree(nci->lsys);
          127         xfree(nci->lserv);
          128         xfree(nci->rsys);
          129         xfree(nci->rserv);
          130         xfree(nci->laddr);
          131         xfree(nci->raddr);
          132         free(nci);
          133 }
          134