tgetnetconn.c - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tgetnetconn.c (3240B)
       ---
            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 <arpa/inet.h>
            9 #include <sys/un.h>
           10 #include <errno.h>
           11 
           12 #undef sun
           13 #define sun sockun
           14 
           15 extern int _p9netfd(char*);
           16 
           17 static char *unknown = "unknown";
           18 
           19 static int
           20 convert(int s, struct sockaddr *sa, char **lsys, char **lserv, char **laddr)
           21 {
           22         struct sockaddr_un *sun;
           23         struct sockaddr_in *sin;
           24         struct sockaddr_in6 *sin6;
           25         uchar *ip;
           26         u32int ipl;
           27         socklen_t sn;
           28         int n;
           29         char *net;
           30 
           31         switch(sa->sa_family){
           32         case AF_INET:
           33                 sin = (void*)sa;
           34                 ip = (uchar*)&sin->sin_addr;
           35                 ipl = *(u32int*)ip;
           36                 if(ipl == 0)
           37                         *lsys = strdup("*");
           38                 else
           39                         *lsys = smprint("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
           40                 *lserv = smprint("%d", ntohs(sin->sin_port));
           41                 sn = sizeof n;
           42                 if(getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) < 0)
           43                         return -1;
           44                 if(n == SOCK_STREAM)
           45                         net = "tcp";
           46                 else if(n == SOCK_DGRAM)
           47                         net = "udp";
           48                 else{
           49                         werrstr("unknown network type");
           50                         return -1;
           51                 }
           52                 *laddr = smprint("%s!%s!%s", net, *lsys, *lserv);
           53                 if(*lsys == nil || *lserv == nil || *laddr == nil)
           54                         return -1;
           55                 return 0;
           56         case AF_INET6:
           57                 sin6 = (void*)sa;
           58                 if (memcmp(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0)
           59                         *lsys = strdup("*");
           60                 else{
           61                         *lsys = malloc(INET6_ADDRSTRLEN);
           62                         inet_ntop(AF_INET6, &sin6->sin6_addr, *lsys, INET6_ADDRSTRLEN);
           63                 }
           64                 *lserv = smprint("%d", ntohs(sin6->sin6_port));
           65                 sn = sizeof n;
           66                 if(getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) < 0)
           67                         return -1;
           68                 if(n == SOCK_STREAM)
           69                         net = "tcp";
           70                 else if(n == SOCK_DGRAM)
           71                         net = "udp";
           72                 else{
           73                         werrstr("unknown network type");
           74                         return -1;
           75                 }
           76                 *laddr = smprint("%s!%s!%s", net, *lsys, *lserv);
           77                 if(*lsys == nil || *lserv == nil || *laddr == nil)
           78                         return -1;
           79                 return 0;
           80         case AF_UNIX:
           81                 sun = (void*)sa;
           82                 *lsys = unknown;
           83                 *lserv = unknown;
           84                 *laddr = smprint("unix!%s", sun->sun_path);
           85                 if(*laddr == nil)
           86                         return -1;
           87                 return 0;
           88         default:
           89                 werrstr("unknown socket family");
           90                 return -1;
           91         }
           92 }
           93 
           94 NetConnInfo*
           95 getnetconninfo(char *dir, int fd)
           96 {
           97         socklen_t sn;
           98         union {
           99                 struct sockaddr sa;
          100                 struct sockaddr_in sin;
          101                 struct sockaddr_in6 sin6;
          102                 struct sockaddr_un sun;
          103         } u;
          104         NetConnInfo *nci;
          105 
          106         if(dir){
          107                 if((fd = _p9netfd(dir)) < 0){
          108                         werrstr("no such network connection %s", dir);
          109                         return nil;
          110                 }
          111         }
          112 
          113         nci = mallocz(sizeof *nci, 1);
          114         if(nci == nil)
          115                 goto err;
          116         nci->dir = smprint("/dev/fd/%d", fd);
          117         nci->root = strdup("/net");
          118         nci->spec = unknown;
          119         if(nci->dir == nil || nci->root == nil)
          120                 goto err;
          121         sn = sizeof u;
          122         if(getsockname(fd, &u.sa, &sn) < 0)
          123                 goto err;
          124         if(convert(fd, &u.sa, &nci->lsys, &nci->lserv, &nci->laddr) < 0)
          125                 goto err;
          126         sn = sizeof u;
          127         if(getpeername(fd, &u.sa, &sn) < 0)
          128                 goto err;
          129         if(convert(fd, &u.sa, &nci->rsys, &nci->rserv, &nci->raddr) < 0)
          130                 goto err;
          131         return nci;
          132 
          133 err:
          134         freenetconninfo(nci);
          135         return nil;
          136 }
          137 
          138 static void
          139 xfree(void *v)
          140 {
          141         if(v != nil && v != unknown)
          142                 free(v);
          143 }
          144 
          145 void
          146 freenetconninfo(NetConnInfo *nci)
          147 {
          148         if(nci == nil)
          149                 return;
          150         xfree(nci->dir);
          151         xfree(nci->root);
          152         xfree(nci->spec);
          153         xfree(nci->lsys);
          154         xfree(nci->lserv);
          155         xfree(nci->rsys);
          156         xfree(nci->rserv);
          157         xfree(nci->laddr);
          158         xfree(nci->raddr);
          159         free(nci);
          160 }