From 37a9506df9dab17552c6c34b62dc4295504b6c8c Mon Sep 17 00:00:00 2001 From: brian Date: Thu, 20 May 2004 05:36:15 -0700 Subject: [PATCH] uname/sysctl support darcs-hash:20040520123615-24bed-e8cbfb1444e79e3677d18b8293aa6466a9128575.gz --- src/org/ibex/nestedvm/Runtime.java | 9 + src/org/ibex/nestedvm/UnixRuntime.java | 281 +++++++++++++++++++++++++++++++- src/org/ibex/nestedvm/support_aux.c | 95 +++++++++++ 3 files changed, 384 insertions(+), 1 deletion(-) diff --git a/src/org/ibex/nestedvm/Runtime.java b/src/org/ibex/nestedvm/Runtime.java index 2a4567f..4d965e7 100644 --- a/src/org/ibex/nestedvm/Runtime.java +++ b/src/org/ibex/nestedvm/Runtime.java @@ -9,6 +9,8 @@ import java.io.*; import java.util.Arrays; public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { + public static final String VERSION = "1.0"; + /** True to write useful diagnostic information to stderr when things go wrong */ final static boolean STDERR_DIAG = true; @@ -1422,6 +1424,13 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { } } + static byte[] getNullTerminatedBytes(String s) { + byte[] buf1 = getBytes(s); + byte[] buf2 = new byte[buf1.length+1]; + System.arraycopy(buf1,0,buf2,0,buf1.length); + return buf2; + } + final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); } final static int min(int a, int b) { return a < b ? a : b; } final static int max(int a, int b) { return a > b ? a : b; } diff --git a/src/org/ibex/nestedvm/UnixRuntime.java b/src/org/ibex/nestedvm/UnixRuntime.java index 1c33a08..4c9ed5a 100644 --- a/src/org/ibex/nestedvm/UnixRuntime.java +++ b/src/org/ibex/nestedvm/UnixRuntime.java @@ -628,7 +628,286 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { public FStat _fstat() { return new FStat(); } } - public int sys_opensocket(int cstring, int port) throws FaultException, ErrnoException { + private int sys_socket(int domain, int type, int proto) { + if(domain != AF_INET || (type != SOCK_STREAM && type != SOCK_DGRAM)) return -EPROTONOSUPPORT; + return addFD(new SocketFD(type == SOCK_STREAM ? SocketFD.TYPE_STREAM : SocketFD.TYPE_DGRAM)); + } + + private SocketFD getSocketFD(int fdn) throws ErrnoException { + if(fdn < 0 || fdn >= OPEN_MAX) throw new ErrnoException(EBADFD); + if(fds[fdn] == null) throw new ErrnoException(EBADFD); + if(!(fds[fdn] instanceof SocketFD)) throw new ErrnoException(ENOTSOCK); + + return (SocketFD) fds[fdn]; + } + + private int sys_connect(int fdn, int addr, int namelen) throws ErrnoException, FaultException { + SocketFD fd = getSocketFD(fdn); + + if(fd.type() == SocketFD.TYPE_STREAM && fd.o != null) return -EISCONN; + int word1 = memRead(addr); + if( ((word1 >>> 16)&0xff) != AF_INET) return -EAFNOSUPPORT; + int port = word1 & 0xffff; + byte[] ip = new byte[4]; + copyin(addr+4,ip,4); + + InetAddress inetAddr; + try { + inetAddr = InetAddress.getByAddress(ip); + } catch(UnknownHostException e) { + return -EADDRNOTAVAIL; + } + + try { + switch(fd.type()) { + case SocketFD.TYPE_STREAM: { + Socket s = new Socket(inetAddr,port); + fd.o = s; + fd.setOptions(); + fd.is = s.getInputStream(); + fd.os = s.getOutputStream(); + break; + } + case SocketFD.TYPE_DGRAM: { + DatagramSocket s = (DatagramSocket) fd.o; + if(s == null) s = new DatagramSocket(); + s.connect(inetAddr,port); + break; + } + default: + throw new Error("should never happen"); + } + } catch(IOException e) { + return -ECONNREFUSED; + } + + return 0; + } + + private int sys_resolve_hostname(int chostname, int addr, int sizeAddr) throws FaultException { + String hostname = cstring(chostname); + int size = memRead(sizeAddr); + InetAddress[] inetAddrs; + try { + inetAddrs = InetAddress.getAllByName(hostname); + } catch(UnknownHostException e) { + return HOST_NOT_FOUND; + } + int count = min(size/4,inetAddrs.length); + for(int i=0;i>> 16)&0xff) != AF_INET) return -EAFNOSUPPORT; + int port = word1 & 0xffff; + InetAddress inetAddr = null; + if(memRead(addr+4) != 0) { + byte[] ip = new byte[4]; + copyin(addr+4,ip,4); + + try { + inetAddr = InetAddress.getByAddress(ip); + } catch(UnknownHostException e) { + return -EADDRNOTAVAIL; + } + } + + switch(fd.type()) { + case SocketFD.TYPE_STREAM: { + fd.bindAddr = inetAddr; + fd.bindPort = port; + return 0; + } + case SocketFD.TYPE_DGRAM: { + DatagramSocket s = (DatagramSocket) fd.o; + if(s != null) s.close(); + try { + fd.o = inetAddr != null ? new DatagramSocket(port,inetAddr) : new DatagramSocket(port); + } catch(IOException e) { + return -EADDRINUSE; + } + return 0; + } + default: + throw new Error("should never happen"); + } + } + + private int sys_listen(int fdn, int backlog) throws ErrnoException { + SocketFD fd = getSocketFD(fdn); + if(fd.type() != SocketFD.TYPE_STREAM) return -EOPNOTSUPP; + if(fd.o != null) return -EISCONN; + if(fd.bindPort < 0) return -EOPNOTSUPP; + + try { + fd.o = new ServerSocket(fd.bindPort,backlog,fd.bindAddr); + fd.flags |= SocketFD.LISTEN; + return 0; + } catch(IOException e) { + return -EADDRINUSE; + } + + } + + private int sys_accept(int fdn, int addr, int lenaddr) throws ErrnoException, FaultException { + SocketFD fd = getSocketFD(fdn); + if(fd.type() != SocketFD.TYPE_STREAM) return -EOPNOTSUPP; + if(!fd.listen()) return -EOPNOTSUPP; + + int size = memRead(lenaddr); + + ServerSocket s = (ServerSocket) fd.o; + Socket client; + try { + client = s.accept(); + } catch(IOException e) { + return -EIO; + } + + if(size >= 8) { + memWrite(addr,(6 << 24) | (AF_INET << 16) | client.getPort()); + byte[] b = client.getInetAddress().getAddress(); + copyout(b,addr+4,4); + memWrite(lenaddr,8); + } + + SocketFD clientFD = new SocketFD(SocketFD.TYPE_STREAM); + clientFD.o = client; + try { + clientFD.is = client.getInputStream(); + clientFD.os = client.getOutputStream(); + } catch(IOException e) { + return -EIO; + } + int n = addFD(clientFD); + if(n == -1) { clientFD.close(); return -ENFILE; } + return n; + } + + private int sys_shutdown(int fdn, int how) throws ErrnoException { + SocketFD fd = getSocketFD(fdn); + if(fd.type() != SocketFD.TYPE_STREAM || fd.listen()) return -EOPNOTSUPP; + if(fd.o == null) return -ENOTCONN; + + Socket s = (Socket) fd.o; + + try { + if(how == SHUT_RD || how == SHUT_RDWR) s.shutdownInput(); + if(how == SHUT_WR || how == SHUT_RDWR) s.shutdownOutput(); + } catch(IOException e) { + return -EIO; + } + + return 0; + } + + private static String hostName() { + try { + return InetAddress.getLocalHost().getHostName(); + } catch(UnknownHostException e) { + return "darkstar"; + } + } + + private int sys_sysctl(int nameaddr, int namelen, int oldp, int oldlenaddr, int newp, int newlen) throws FaultException { + if(newp != 0) return -EPERM; + if(namelen == 0) return -ENOENT; + if(oldp == 0) return 0; + + Object o = null; + switch(memRead(nameaddr)) { + case CTL_KERN: + if(namelen != 2) break; + switch(memRead(nameaddr+4)) { + case KERN_OSTYPE: o = "NestedVM"; break; + case KERN_HOSTNAME: o = hostName(); break; + case KERN_OSRELEASE: o = VERSION; break; + case KERN_VERSION: o = "NestedVM Kernel Version " + VERSION; break; + } + break; + case CTL_HW: + if(namelen != 2) break; + switch(memRead(nameaddr+4)) { + case HW_MACHINE: o = "NestedVM Virtual Machine"; break; + } + break; + } + if(o == null) return -ENOENT; + int len = memRead(oldlenaddr); + if(o instanceof String) { + byte[] b = getNullTerminatedBytes((String)o); + if(len < b.length) return -ENOMEM; + len = b.length; + copyout(b,oldp,len); + memWrite(oldlenaddr,len); + } else if(o instanceof Integer) { + if(len < 4) return -ENOMEM; + memWrite(oldp,((Integer)o).intValue()); + } else { + throw new Error("should never happen"); + } + return 0; + } + + + /*public int sys_opensocket(int cstring, int port) throws FaultException, ErrnoException { String hostname = cstring(cstring); try { FD fd = new SocketFD(new Socket(hostname,port)); diff --git a/src/org/ibex/nestedvm/support_aux.c b/src/org/ibex/nestedvm/support_aux.c index c309899..78cc495 100644 --- a/src/org/ibex/nestedvm/support_aux.c +++ b/src/org/ibex/nestedvm/support_aux.c @@ -155,6 +155,19 @@ long _pathconf_r(struct _reent *ptr,const char *path, int name) { } } +int _sysctl_r(struct _reent *ptr, int *name, int namelen, void *oldp, size_t *oldlen, void *newp, size_t newlen) { + if(name[0] != CTL_USER) return _sysctl(name,namelen,oldp,oldlen,newp,newlen); + if(newp != NULL) { ptr->_errno = EPERM; return -1; } + if(namelen != 2) { ptr->_errno = EINVAL; return -1; } + + switch(name[1]) { + default: + fprintf(stderr,"WARNING: sysctl: Unknown name: %d\n",name[1]); + ptr->_errno = EINVAL; + return -1; + } +} + void sync() { /* do nothing*/ } @@ -425,6 +438,88 @@ const char *path; return(bname); } +/* FreeBSD's uname */ +int +uname(name) +struct utsname *name; +{ + int mib[2], rval; + size_t len; + char *p; + int oerrno; + + rval = 0; + + mib[0] = CTL_KERN; + mib[1] = KERN_OSTYPE; + len = sizeof(name->sysname); + oerrno = errno; + if (sysctl(mib, 2, &name->sysname, &len, NULL, 0) == -1) { + if(errno == ENOMEM) + errno = oerrno; + else + rval = -1; + } + name->sysname[sizeof(name->sysname) - 1] = '\0'; + + mib[0] = CTL_KERN; + mib[1] = KERN_HOSTNAME; + len = sizeof(name->nodename); + oerrno = errno; + if (sysctl(mib, 2, &name->nodename, &len, NULL, 0) == -1) { + if(errno == ENOMEM) + errno = oerrno; + else + rval = -1; + } + name->nodename[sizeof(name->nodename) - 1] = '\0'; + + mib[0] = CTL_KERN; + mib[1] = KERN_OSRELEASE; + len = sizeof(name->release); + oerrno = errno; + if (sysctl(mib, 2, &name->release, &len, NULL, 0) == -1) { + if(errno == ENOMEM) + errno = oerrno; + else + rval = -1; + } + name->release[sizeof(name->release) - 1] = '\0'; + + /* The version may have newlines in it, turn them into spaces. */ + mib[0] = CTL_KERN; + mib[1] = KERN_VERSION; + len = sizeof(name->version); + oerrno = errno; + if (sysctl(mib, 2, &name->version, &len, NULL, 0) == -1) { + if (errno == ENOMEM) + errno = oerrno; + else + rval = -1; + } + name->version[sizeof(name->version) - 1] = '\0'; + for (p = name->version; len--; ++p) { + if (*p == '\n' || *p == '\t') { + if (len > 1) + *p = ' '; + else + *p = '\0'; + } + } + + mib[0] = CTL_HW; + mib[1] = HW_MACHINE; + len = sizeof(name->machine); + oerrno = errno; + if (sysctl(mib, 2, &name->machine, &len, NULL, 0) == -1) { + if (errno == ENOMEM) + errno = oerrno; + else + rval = -1; + } + name->machine[sizeof(name->machine) - 1] = '\0'; + return (rval); +} /* FreeBSD's daemon() - modified for nestedvm */ int -- 1.7.10.4