From: brian Date: Thu, 1 Jul 2004 01:12:20 +0000 (-0700) Subject: more socket stuff X-Git-Url: http://git.megacz.com/?p=nestedvm.git;a=commitdiff_plain;h=d63db5ad45b5fd3121c4cf267d08a67d60751fc2 more socket stuff darcs-hash:20040701011220-24bed-e27abfaaeda5e7638568cbfaf77d73b0d7ae60fd.gz --- diff --git a/src/org/ibex/nestedvm/support_aux.c b/src/org/ibex/nestedvm/support_aux.c index fcb7b31..603f6ee 100644 --- a/src/org/ibex/nestedvm/support_aux.c +++ b/src/org/ibex/nestedvm/support_aux.c @@ -286,6 +286,33 @@ void herror(const char *string) { fprintf(stderr,"%s: %s\n",string,hstrerror(h_errno)); } +extern int _resolve_ip(int addr, char *buf, size_t size); + +struct hostent *gethostbyaddr(const char *addr, int len, int type) { + static struct hostent hostent; + static char name[128]; + static char *aliases[1]; + static char *addr_list[1]; + static char addr_list_buf[4]; + int err,i; + + if(type != AF_INET || len != 4) return NULL; + memcpy(&i,addr,4); + memcpy(addr_list_buf,addr,4); + err = _resolve_ip(i,name,sizeof(name)); + if(err != 0) { h_errno = err; return NULL; } + + hostent.h_name = name; + hostent.h_aliases = aliases; + aliases[0] = NULL; + hostent.h_addrtype = AF_INET; + hostent.h_length = sizeof(struct in_addr); + hostent.h_addr_list = addr_list; + addr_list[0] = addr_list_buf; + + return &hostent; +} + extern int _resolve_hostname(const char *, char *buf, size_t *size); struct hostent *gethostbyname(const char *hostname) { @@ -515,6 +542,23 @@ struct utsname *name; return (rval); } +/* FreeBSD's gethostname */ +int +gethostname(name, namelen) +char *name; +int namelen; +{ + int mib[2]; + size_t size; + + mib[0] = CTL_KERN; + mib[1] = KERN_HOSTNAME; + size = namelen; + if (sysctl(mib, 2, name, &size, NULL, 0) == -1) + return (-1); + return (0); +} + /* FreeBSD's daemon() - modified for nestedvm */ int daemon(nochdir, noclose) @@ -546,3 +590,184 @@ int nochdir, noclose; } return (0); } + +/* FreeBSD's inet_addr/inet_aton */ + +/* +* Check whether "cp" is a valid ASCII representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inet_aton(cp, addr) +register const char *cp; +struct in_addr *addr; +{ + u_long parts[4]; + in_addr_t val; + char *c; + char *endptr; + int gotend, n; + + c = (char *)cp; + n = 0; + /* + * Run through the string, grabbing numbers until + * the end of the string, or some error + */ + gotend = 0; + while (!gotend) { + errno = 0; + val = strtoul(c, &endptr, 0); + + if (errno == ERANGE) /* Fail completely if it overflowed. */ + return (0); + + /* + * If the whole string is invalid, endptr will equal + * c.. this way we can make sure someone hasn't + * gone '.12' or something which would get past + * the next check. + */ + if (endptr == c) + return (0); + parts[n] = val; + c = endptr; + + /* Check the next character past the previous number's end */ + switch (*c) { + case '.' : + /* Make sure we only do 3 dots .. */ + if (n == 3) /* Whoops. Quit. */ + return (0); + n++; + c++; + break; + + case '\0': + gotend = 1; + break; + + default: + if (isspace((unsigned char)*c)) { + gotend = 1; + break; + } else + return (0); /* Invalid character, so fail */ + } + + } + + /* + * Concoct the address according to + * the number of parts specified. + */ + + switch (n) { + case 0: /* a -- 32 bits */ + /* + * Nothing is necessary here. Overflow checking was + * already done in strtoul(). + */ + break; + case 1: /* a.b -- 8.24 bits */ + if (val > 0xffffff || parts[0] > 0xff) + return (0); + val |= parts[0] << 24; + break; + + case 2: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 3: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff || + parts[2] > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + + if (addr != NULL) + addr->s_addr = htonl(val); + return (1); +} + +/* + * ASCII internet address interpretation routine. + * The value returned is in network order. + */ +in_addr_t /* XXX should be struct in_addr :( */ +inet_addr(cp) +register const char *cp; +{ + struct in_addr val; + + if (inet_aton(cp, &val)) + return (val.s_addr); + return (INADDR_NONE); +} + +int +getgrouplist(uname, agroup, groups, grpcnt) +const char *uname; +gid_t agroup; +register gid_t *groups; +int *grpcnt; +{ + register struct group *grp; + register int i, ngroups; + int ret, maxgroups; + + ret = 0; + ngroups = 0; + maxgroups = *grpcnt; + /* + * When installing primary group, duplicate it; + * the first element of groups is the effective gid + * and will be overwritten when a setgid file is executed. + */ + groups[ngroups++] = agroup; + if (maxgroups > 1) + groups[ngroups++] = agroup; + /* + * Scan the group file to find additional groups. + */ + setgrent(); + while ((grp = getgrent())) { + for (i = 0; i < ngroups; i++) { + if (grp->gr_gid == groups[i]) + goto skip; + } + for (i = 0; grp->gr_mem[i]; i++) { + if (!strcmp(grp->gr_mem[i], uname)) { + if (ngroups >= maxgroups) { + ret = -1; + break; + } + groups[ngroups++] = grp->gr_gid; + break; + } + } +skip: ; + } + endgrent(); + *grpcnt = ngroups; + return (ret); +} + +int +initgroups(uname, agroup) +const char *uname; +gid_t agroup; +{ + gid_t groups[32], ngroups; + + ngroups = 32; + getgrouplist(uname, agroup, groups, &ngroups); + return (setgroups(ngroups, groups)); +} diff --git a/upstream/misc/extraheaders.sh b/upstream/misc/extraheaders.sh index 7550e07..61fe163 100755 --- a/upstream/misc/extraheaders.sh +++ b/upstream/misc/extraheaders.sh @@ -1,9 +1,9 @@ #!/bin/sh -e -mkdir -p arpa netinet sys nestedvm +mkdir -p arpa netinet sys nestedvm net -for f in arpa/inet.h netdb.h netinet/in.h sys/socket.h; do +for f in arpa/inet.h netdb.h netinet/in.h sys/socket.h net/if.h; do test -f $f || echo "#include " > $f done @@ -377,6 +377,10 @@ static unsigned long htonl(int x) { return x; } static unsigned short ntohs(int x) { return x; } static unsigned long ntohl(int x) { return x; } +/* Note AF_UNIX isn't supported */ +#define AF_UNIX 1 +#define PF_UNIX AF_UNIX + #define AF_INET 2 #define PF_INET AF_INET @@ -392,12 +396,17 @@ static unsigned long ntohl(int x) { return x; } #define SO_REUSEADDR 0x0004 #define SO_KEEPALIVE 0x0008 +#define SO_BROADCAST 0x0020 +#define SO_TYPE 0x1008 #define SHUT_RD 0 #define SHUT_WR 1 #define SHUT_RDWR 2 #define INADDR_ANY 0 +#define INADDR_NONE -1 +#define INADDR_LOOPBACK 0x7f000001 +#define INADDR_BROADCAST 0xffffffff typedef unsigned long in_addr_t; typedef int socklen_t; @@ -419,6 +428,14 @@ struct sockaddr_in { struct in_addr sin_addr; }; +struct sockaddr_un { + u_char sun_len; + u_char sun_family; + char sun_path[256]; +}; + +#define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) + struct servent { char *s_name; /* official name of service */ char **s_aliases; /* alias list */ @@ -445,7 +462,11 @@ int listen(int s, int backlog); int accept(int s, struct sockaddr *addr, socklen_t *addrlen); int shutdown(int s, int how); int connect(int s, const struct sockaddr *name, socklen_t namelen); + char *inet_ntoa(struct in_addr in); +in_addr_t inet_addr(const char *cp); +int inet_aton(const char *cp, struct in_addr *addr); + int recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); int sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);