/* Copyright © 2003 Russ Cox, MIT; see /sys/src/libsunrpc/COPYING */ #include #include #include #include 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; iprog, (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