Commit c9f18815 authored by Tigran Mkrtchyan's avatar Tigran Mkrtchyan
Browse files

portmap: added a basic portmap support

parent 7e4179dd
......@@ -133,6 +133,11 @@ public class OncRpcClient {
connector_handler = (TCPConnectorHandler) controller.acquireConnectorHandler(Controller.Protocol.TCP);
connector_handler.connect(new InetSocketAddress(_address, _port), (CallbackHandler<Context>) null);
if( !connector_handler.isConnected() ) {
throw new IOException("Failed to connect");
}
return new ClientTransport(connector_handler, _replyQueue);
}
......
......@@ -18,6 +18,7 @@ package org.dcache.xdr;
import com.sun.grizzly.BaseSelectionKeyHandler;
import com.sun.grizzly.Controller;
import com.sun.grizzly.ControllerStateListenerAdapter;
import com.sun.grizzly.DefaultProtocolChain;
import com.sun.grizzly.DefaultProtocolChainInstanceHandler;
import com.sun.grizzly.ProtocolChain;
......@@ -28,6 +29,7 @@ import com.sun.grizzly.util.DefaultThreadPool;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.logging.Level;
import java.util.logging.Logger;
......@@ -37,6 +39,7 @@ public class OncRpcSvc {
private final static Logger _log = Logger.getLogger(OncRpcSvc.class.getName());
private final Controller _controller = new Controller();
private final CountDownLatch _serverReady = new CountDownLatch(1);
/**
* mapping of registered programs.
......@@ -60,6 +63,14 @@ public class OncRpcSvc {
tcp_handler.setSelectionKeyHandler(new BaseSelectionKeyHandler());
_controller.addSelectorHandler(tcp_handler);
_controller.addStateListener(
new ControllerStateListenerAdapter() {
@Override
public void onReady() {
_serverReady.countDown();
}
});
DefaultThreadPool defp;
ExecutorService executorService = _controller.getThreadPool();
......@@ -100,8 +111,14 @@ public class OncRpcSvc {
/**
* Start service.
*/
public void start() {
public void start() throws IOException {
new Thread(_controller).start();
try {
_serverReady.await();
} catch (InterruptedException ex) {
_log.log(Level.SEVERE, "failed to start Controller", ex);
throw new IOException(ex.getMessage());
}
}
/**
......
......@@ -25,7 +25,7 @@ import com.sun.grizzly.Context;
import com.sun.grizzly.ProtocolFilter;
import com.sun.grizzly.ProtocolParser;
class RpcProtocolFilter implements ProtocolFilter {
public class RpcProtocolFilter implements ProtocolFilter {
public static final String RPC_CALL = "RPC_CALL";
......
......@@ -21,7 +21,7 @@ import java.io.IOException;
import java.net.InetAddress;
import org.acplt.oncrpc.OncRpcPortmapClient;
import org.acplt.oncrpc.apps.jportmap.OncRpcEmbeddedPortmap;
import org.dcache.xdr.portmap.OncRpcEmbeddedPortmap;
public class SimpleRpcServer {
......@@ -40,7 +40,7 @@ public class SimpleRpcServer {
port = Integer.parseInt(args[0]);
}
new OncRpcEmbeddedPortmap(2000);
new OncRpcEmbeddedPortmap();
OncRpcPortmapClient portmap = new OncRpcPortmapClient(InetAddress
.getByName("127.0.0.1"));
......
/*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program (see the file COPYING.LIB for more
* details); if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.dcache.xdr.portmap;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.logging.Logger;
import org.dcache.xdr.OncRpcClient;
import org.dcache.xdr.OncRpcException;
import org.dcache.xdr.RpcAuthTypeNone;
import org.dcache.xdr.RpcCall;
import org.dcache.xdr.XdrTransport;
public class GenericPortmapClient implements OncPortmapClient {
private final static Logger _log = Logger.getLogger(GenericPortmapClient.class.getName());
private final RpcAuthTypeNone _auth = new RpcAuthTypeNone();
private final OncPortmapClient _portmapClient;
public GenericPortmapClient(XdrTransport transport) {
OncPortmapClient portmapClient = new RpcbindV4Client(new RpcCall(100000, 4, _auth, _auth, transport));
if( !portmapClient.ping() ) {
portmapClient = new PortmapV2Client( new RpcCall(100000, 2, _auth, _auth, transport) );
if(!portmapClient.ping()) {
// FIXME: return correct exception
throw new IllegalStateException("portmap service not available");
}
}
_portmapClient = portmapClient;
}
public void dump() throws OncRpcException, IOException {
_portmapClient.dump();
}
public boolean ping() {
return _portmapClient.ping();
}
public boolean setPort(int program, int version, String netid, String addr, String owner) throws OncRpcException, IOException {
return _portmapClient.setPort(program, version, netid, addr, owner);
}
public static void main(String[] args) throws UnknownHostException, InterruptedException, IOException, OncRpcException {
OncRpcClient rpcClient = new OncRpcClient(InetAddress.getByName("127.0.0.1"), 0, 111);
XdrTransport transport = rpcClient.connect();
OncPortmapClient portmapClient = new GenericPortmapClient(transport);
try {
/*
* check for V4
*/
portmapClient.ping();
portmapClient.dump();
portmapClient.setPort(100003, 4, "tcp", "127.0.0.2.8.4", "3750");
} finally {
rpcClient.close();
}
}
}
/*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program (see the file COPYING.LIB for more
* details); if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.dcache.xdr.portmap;
import java.io.IOException;
import org.dcache.xdr.OncRpcException;
public interface OncPortmapClient {
void dump() throws OncRpcException, IOException;
boolean ping();
boolean setPort(int program, int version, String netid, String addr, String owner) throws OncRpcException, IOException;
}
/*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program (see the file COPYING.LIB for more
* details); if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.dcache.xdr.portmap;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.dcache.xdr.OncRpcClient;
import org.dcache.xdr.OncRpcException;
import org.dcache.xdr.OncRpcSvc;
import org.dcache.xdr.RpcAuth;
import org.dcache.xdr.RpcAuthTypeNone;
import org.dcache.xdr.RpcCall;
import org.dcache.xdr.XdrTransport;
import org.dcache.xdr.XdrVoid;
public class OncRpcEmbeddedPortmap {
private static final RpcAuth _auth = new RpcAuthTypeNone();
public OncRpcEmbeddedPortmap() throws UnknownHostException, IOException {
this(2000);
}
public OncRpcEmbeddedPortmap(int timeout) throws UnknownHostException, IOException {
// we start embeded portmap only if there no other one is running
OncRpcClient rpcClient = null;
boolean localPortmapperRunning = false;
try {
rpcClient = new OncRpcClient(InetAddress.getLocalHost(), 0, OncRpcPortmap.PORTMAP_PORT);
XdrTransport transport = rpcClient.connect();
/* check for version 2, 3 and 4 */
for (int i = 2; i < 5; i++) {
RpcCall call = new RpcCall(OncRpcPortmap.PORTMAP_PROGRAMM,
i, _auth, _auth, transport);
try {
call.call(0, XdrVoid.XDR_VOID, XdrVoid.XDR_VOID, 2000);
} catch (OncRpcException ex) {}
localPortmapperRunning = true;
}
} catch (IOException e) {
} finally {
if(rpcClient != null) rpcClient.close();
}
if(!localPortmapperRunning) {
OncRpcSvc rpcbindServer = new OncRpcSvc(OncRpcPortmap.PORTMAP_PORT);
rpcbindServer.register(OncRpcPortmap.PORTMAP_PROGRAMM, new OncRpcbindServer());
rpcbindServer.start();
}
}
}
/*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program (see the file COPYING.LIB for more
* details); if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.dcache.xdr.portmap;
public class OncRpcPortmap {
/**
* portmap/rpcbing program number as defined in rfc1833.
*/
public static final int PORTMAP_PROGRAMM = 100000;
/**
* portmap/rpcbing TCP/UDP port number as defined in rfc1833.
*/
public static final int PORTMAP_PORT = 111;
/*
* V2
*/
public static final int PMAPPROC_NULL = 0;
public static final int PMAPPROC_SET = 1;
public static final int PMAPPROC_UNSET = 2;
public static final int PMAPPROC_GETPORT = 3;
public static final int PMAPPROC_DUMP = 4;
public static final int PMAPPROC_CALLIT = 5;
/*
* V4
*/
public static final int RPCBPROC_SET = 1;
public static final int RPCBPROC_UNSET = 2;
public static final int RPCBPROC_GETADDR = 3;
public static final int RPCBPROC_DUMP = 4;
public static final int RPCBPROC_GETTIME = 6;
public static final int RPCBPROC_UADDR2TADDR = 7;
public static final int RPCBPROC_TADDR2UADDR = 8;
public static final int RPCBPROC_GETVERSADDR = 9;
public static final int RPCBPROC_INDIRECT = 10;
public static final int RPCBPROC_GETADDRLIST = 11;
public static final int RPCBPROC_GETSTAT = 12;
}
/*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program (see the file COPYING.LIB for more
* details); if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.dcache.xdr.portmap;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
import org.dcache.xdr.OncRpcException;
import org.dcache.xdr.RpcCall;
import org.dcache.xdr.RpcDispatchable;
import org.dcache.xdr.OncRpcSvc;
import org.dcache.xdr.XdrBoolean;
import org.dcache.xdr.XdrVoid;
public class OncRpcbindServer implements RpcDispatchable {
private final static Logger _log = Logger.getLogger(OncRpcbindServer.class.getName());
/**
* Set of registered services.
*/
private final Set<rpcb> _services = new HashSet<rpcb>();
public OncRpcbindServer() {
_services.add(new rpcb(100000, 2, "tcp", "0.0.0.0.0.111", "superuser"));
//_services.add(new rpcb(100000, 4, "tcp", "0.0.0.0.0.111", "superuser"));
}
public void dispatchOncRpcCall(RpcCall call) throws OncRpcException, IOException {
int version = call.getProgramVersion();
switch(version) {
case 2:
processV2Call(call);
break;
case 3:
case 4:
// break;
default:
call.failProgramMismatch(2, 4);
}
}
private void processV2Call(RpcCall call) throws OncRpcException, IOException {
switch(call.getProcedure()) {
case OncRpcPortmap.PMAPPROC_NULL:
call.reply(XdrVoid.XDR_VOID);
break;
case OncRpcPortmap.PMAPPROC_SET:
mapping newMapping = new mapping();
call.retrieveCall(newMapping);
// we sore every thing in v4 format
rpcb rpcbMapping = new rpcb(newMapping);
synchronized(_services) {
_services.add(rpcbMapping);
}
call.reply(XdrBoolean.True);
break;
case OncRpcPortmap.PMAPPROC_DUMP:
pmaplist list = new pmaplist();
pmaplist next = list;
synchronized(_services) {
for(rpcb mapping: _services) {
next.setEntry(mapping.toMapping());
pmaplist n = new pmaplist();
next.setNext(n);
next = n;
}
}
call.reply(list);
break;
case OncRpcPortmap.PMAPPROC_GETPORT:
mapping query = new mapping();
call.retrieveCall(query);
rpcb result = search(new rpcb(query));
Port port;
if(result == null) {
port = new Port(0);
}else{
port = new Port( result.toMapping().getPort());
}
call.reply(port);
break;
default:
call.failProcedureUnavailable();
}
}
private rpcb search(rpcb query) {
synchronized(_services) {
for( rpcb e: _services) {
if( e.match(query)) return e;
}
}
return null;
}
public static void main(String[] args) throws Exception {
if (args.length > 1) {
System.err.println("Usage: SimpleRpcServer <port>");
System.exit(1);
}
int port = OncRpcPortmap.PORTMAP_PORT;
if (args.length == 1) {
port = Integer.parseInt(args[0]);
}
RpcDispatchable rpcbind = new OncRpcbindServer();
OncRpcSvc server = new OncRpcSvc(port);
server.register(OncRpcPortmap.PORTMAP_PROGRAMM, rpcbind);
server.start();
}
}
/*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program (see the file COPYING.LIB for more
* details); if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.dcache.xdr.portmap;
import java.io.IOException;
import org.dcache.xdr.OncRpcException;
import org.dcache.xdr.XdrAble;
import org.dcache.xdr.XdrDecodingStream;
import org.dcache.xdr.XdrEncodingStream;
/**
* reply to PORTMAP_GETPORT command
*/
public class Port implements XdrAble {
private int _port;
public Port(int port) {
_port = port;
}
public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
_port = xdr.xdrDecodeInt();
}
public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
xdr.xdrEncodeInt(_port);
}
}
/*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program (see the file COPYING.LIB for more
* details); if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.dcache.xdr.portmap;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.dcache.xdr.IpProtocolType;
import org.dcache.xdr.OncRpcException;
import org.dcache.xdr.RpcCall;
import org.dcache.xdr.XdrBoolean;
import org.dcache.xdr.XdrVoid;
public class PortmapV2Client implements OncPortmapClient {
private final static Logger _log = Logger.getLogger(PortmapV2Client.class.getName());
private final RpcCall _call;
public PortmapV2Client(RpcCall call) {
_call = call;
}
public void dump() throws OncRpcException, IOException {
_log.log(Level.FINEST, "portmap dump");
pmaplist list_reply = new pmaplist();
_call.call(OncRpcPortmap.PMAPPROC_DUMP, XdrVoid.XDR_VOID, list_reply);
System.out.println(list_reply);
}
public boolean ping() {
_log.log(Level.FINEST, "portmap ping");
boolean pong = false;
try {
_call.call(OncRpcPortmap.PMAPPROC_NULL, XdrVoid.XDR_VOID, XdrVoid.XDR_VOID, 2000);
pong = true;
}catch(OncRpcException e) {
}catch(IOException e) {
}
return pong;
}
public boolean setPort(int program, int version, String netid, String addr, String owner) throws OncRpcException, IOException {
_log.log(Level.FINEST, "portmap set port: prog: {0} vers: {1}, netid: {2} addr: {3}, owner: {4}",
new Object[]{program, version, netid, addr, owner});
InetSocketAddress address = org.dcache.xdr.netid.toInetSocketAddress(addr);
// FIXME : nettype detection
mapping m1 = new mapping(program, version, IpProtocolType.TCP, address.getPort());
XdrBoolean isSet = new XdrBoolean();
_call.call(OncRpcPortmap.PMAPPROC_SET, m1, isSet);
return isSet.booleanValue();
}
}
\ No newline at end of file
/*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,