Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

/* Copyright © 2003 Russ Cox, MIT; see /sys/src/libsunrpc/COPYING */
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <sunrpc.h>

int chatty;
SunClient *client;

void
usage(void)
{
        fprint(2, "usage: portmap address [cmd]\n"
                "cmd is one of:\n"
                "\tnull\n"
                "\tset prog vers proto port\n"
                "\tunset prog vers proto port\n"
                "\tgetport prog vers proto\n"
                "\tdump (default)\n");
        threadexitsall("usage");
}

void
portCall(SunCall *c, PortCallType type)
{
        c->rpc.prog = PortProgram;
        c->rpc.vers = PortVersion;
        c->rpc.proc = type>>1;
        c->rpc.iscall = !(type&1);
        c->type = type;
}

void
tnull(char **argv)
{
        PortTNull tx;
        PortRNull rx;

        USED(argv);

        memset(&tx, 0, sizeof tx);
        portCall(&tx.call, PortCallTNull);

        memset(&rx, 0, sizeof rx);
        portCall(&rx.call, PortCallRNull);

        if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
                sysfatal("rpc: %r");
}

void
tset(char **argv)
{
        PortTSet tx;
        PortRSet rx;

        memset(&tx, 0, sizeof tx);
        portCall(&tx.call, PortCallTSet);
        tx.map.prog = strtol(argv[0], 0, 0);
        tx.map.vers = strtol(argv[1], 0, 0);
        tx.map.prot = strtol(argv[2], 0, 0);
        tx.map.port = strtol(argv[3], 0, 0);

        memset(&rx, 0, sizeof rx);
        portCall(&rx.call, PortCallRSet);

        if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
                sysfatal("rpc: %r");

        if(rx.b == 0)
                print("rejected\n");
}

void
tunset(char **argv)
{
        PortTUnset tx;
        PortRUnset rx;

        memset(&tx, 0, sizeof tx);
        portCall(&tx.call, PortCallTUnset);
        tx.map.prog = strtol(argv[0], 0, 0);
        tx.map.vers = strtol(argv[1], 0, 0);
        tx.map.prot = strtol(argv[2], 0, 0);
        tx.map.port = strtol(argv[3], 0, 0);

        memset(&rx, 0, sizeof rx);
        portCall(&rx.call, PortCallRUnset);

        if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
                sysfatal("rpc: %r");

        if(rx.b == 0)
                print("rejected\n");
}

void
tgetport(char **argv)
{
        PortTGetport tx;
        PortRGetport rx;

        memset(&tx, 0, sizeof tx);
        portCall(&tx.call, PortCallTGetport);
        tx.map.prog = strtol(argv[0], 0, 0);
        tx.map.vers = strtol(argv[1], 0, 0);
        tx.map.prot = strtol(argv[2], 0, 0);

        memset(&rx, 0, sizeof rx);
        portCall(&rx.call, PortCallRGetport);

        if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
                sysfatal("rpc: %r");

        print("%d\n", rx.port);
}

void
tdump(char **argv)
{
        int i;
        uchar *p;
        PortTDump tx;
        PortRDump rx;
        PortMap *m;

        USED(argv);

        memset(&tx, 0, sizeof tx);
        portCall(&tx.call, PortCallTDump);

        memset(&rx, 0, sizeof rx);
        portCall(&rx.call, PortCallRDump);

        if(sunClientRpc(client, 0, &tx.call, &rx.call, &p) < 0)
                sysfatal("rpc: %r");

        for(i=0, m=rx.map; i<rx.nmap; i++, m++)
                print("%ud %ud %ud %ud\n", (uint)m->prog, (uint)m->vers, (uint)m->prot, (uint)m->port);

        free(p);
}

static struct {
        char *cmd;
        int narg;
        void (*fn)(char**);
} tab[] = {
        "null", 0,      tnull,
        "set",  4,      tset,
        "unset",        4,      tunset,
        "getport",      3,      tgetport,
        "dump", 0,      tdump,
};

void
threadmain(int argc, char **argv)
{
        char *dflt[] = { "dump", };
        char *addr, *cmd;
        int i;

        ARGBEGIN{
        case 'R':
                chatty++;
                break;
        }ARGEND

        if(argc < 1)
                usage();

        fmtinstall('B', sunRpcFmt);
        fmtinstall('C', sunCallFmt);
        fmtinstall('H', encodefmt);
        sunFmtInstall(&portProg);

        addr = netmkaddr(argv[0], "udp", "portmap");
        if((client = sunDial(addr)) == nil)
                sysfatal("dial %s: %r", addr);

        client->chatty = chatty;
        sunClientProg(client, &portProg);

        argv++;
        argc--;

        if(argc == 0){
                argc = 1;
                argv = dflt;
        }
        cmd = argv[0];
        argv++;
        argc--;

        for(i=0; i<nelem(tab); i++){
                if(strcmp(tab[i].cmd, cmd) == 0){
                        if(tab[i].narg != argc)
                                usage();
                        (*tab[i].fn)(argv);
                        threadexitsall(nil);
                }
        }
        usage();
}