URI: 
       tadd getnetconninfo - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 06f4d9201a6552b3c832fccc72ff0627986977e5
   DIR parent 18b1814390e9d3bff470de940b448dfddf87187d
  HTML Author: rsc <devnull@localhost>
       Date:   Sun, 13 Feb 2005 19:25:44 +0000
       
       add getnetconninfo
       
       Diffstat:
         A src/lib9/getnetconn.c               |     134 +++++++++++++++++++++++++++++++
         M src/lib9/mkfile                     |       1 +
       
       2 files changed, 135 insertions(+), 0 deletions(-)
       ---
   DIR diff --git a/src/lib9/getnetconn.c b/src/lib9/getnetconn.c
       t@@ -0,0 +1,134 @@
       +#include <u.h>
       +#define NOPLAN9DEFINES
       +#include <libc.h>
       +
       +#include <sys/socket.h>
       +#include <netinet/in.h>
       +#include <netinet/tcp.h>
       +#include <sys/un.h>
       +#include <errno.h>
       +
       +#undef sun
       +#define sun sockun
       +
       +extern int _p9netfd(char*);
       +
       +static char *unknown = "unknown";
       +
       +static int
       +convert(int s, struct sockaddr *sa, char **lsys, char **lserv, char **laddr)
       +{
       +        struct sockaddr_un *sun;
       +        struct sockaddr_in *sin;
       +        uchar *ip;
       +        u32int ipl;
       +        socklen_t sn;
       +        int n;
       +        char *net;
       +        
       +        switch(sa->sa_family){
       +        case AF_INET:
       +                sin = (void*)sa;
       +                ip = (uchar*)&sin->sin_addr;
       +                ipl = *(u32int*)ip;
       +                if(ipl == 0)
       +                        *lsys = strdup("*");
       +                else
       +                        *lsys = smprint("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
       +                *lserv = smprint("%d", ntohs(sin->sin_port));
       +                sn = sizeof n;
       +                if(getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) < 0)
       +                        return -1;
       +                if(n == SOCK_STREAM)
       +                        net = "tcp";
       +                else if(n == SOCK_DGRAM)
       +                        net = "udp";
       +                else{
       +                        werrstr("unknown network type");
       +                        return -1;
       +                }
       +                *laddr = smprint("%s!%s!%s", net, *lsys, *lserv);
       +                if(*lsys == nil || *lserv == nil || *laddr == nil)
       +                        return -1;
       +                return 0;
       +        case AF_UNIX:
       +                sun = (void*)sa;
       +                *lsys = unknown;
       +                *lserv = unknown;
       +                *laddr = smprint("unix!%s", sun->sun_path);
       +                if(*laddr == nil)
       +                        return -1;
       +                return 0;
       +        default:
       +                werrstr("unknown socket family");
       +                return -1;
       +        }
       +}
       +
       +NetConnInfo*
       +getnetconninfo(char *dir, int fd)
       +{
       +        socklen_t sn;
       +        union {
       +                struct sockaddr sa;
       +                struct sockaddr_in sin;
       +                struct sockaddr_un sun;
       +        } u;
       +        NetConnInfo *nci;
       +
       +        if(dir){
       +                if((fd = _p9netfd(dir)) < 0){
       +                        werrstr("no such network connection %s", dir);
       +                        return nil;
       +                }
       +        }
       +
       +        nci = mallocz(sizeof *nci, 1);
       +        if(nci == nil)
       +                goto err;
       +        nci->dir = smprint("/dev/fd/%d", fd);
       +        nci->root = strdup("/net");
       +        nci->spec = unknown;
       +        if(nci->dir == nil || nci->root == nil)
       +                goto err;
       +        sn = sizeof sn;
       +        if(getsockname(fd, &u.sa, &sn) < 0)
       +                goto err;
       +        if(convert(fd, &u.sa, &nci->lsys, &nci->lserv, &nci->laddr) < 0)
       +                goto err;
       +        sn = sizeof sn;
       +        if(getpeername(fd, &u.sa, &sn) < 0)
       +                goto err;
       +        if(convert(fd, &u.sa, &nci->rsys, &nci->rserv, &nci->raddr) < 0)
       +                goto err;
       +        return nci;
       +
       +err:
       +        freenetconninfo(nci);
       +        return nil;
       +}
       +
       +static void
       +xfree(void *v)
       +{
       +        if(v != nil && v != unknown)
       +                free(v);
       +}
       +
       +void
       +freenetconninfo(NetConnInfo *nci)
       +{
       +        if(nci == nil)
       +                return;
       +        xfree(nci->dir);
       +        xfree(nci->root);
       +        xfree(nci->spec);
       +        xfree(nci->lsys);
       +        xfree(nci->lserv);
       +        xfree(nci->rsys);
       +        xfree(nci->rserv);
       +        xfree(nci->laddr);
       +        xfree(nci->raddr);
       +        free(nci);
       +}
       +
   DIR diff --git a/src/lib9/mkfile b/src/lib9/mkfile
       t@@ -104,6 +104,7 @@ LIB9OFILES=\
                getcallerpc-$OBJTYPE.$O\
                getenv.$O\
                getfields.$O\
       +        getnetconn.$O\
                getns.$O\
                getuser.$O\
                getwd.$O\