]> Zhao Yanbai Git Server - minix.git/commitdiff
Socket library
authorPhilip Homburg <philip@cs.vu.nl>
Wed, 27 Jul 2005 11:57:59 +0000 (11:57 +0000)
committerPhilip Homburg <philip@cs.vu.nl>
Wed, 27 Jul 2005 11:57:59 +0000 (11:57 +0000)
14 files changed:
lib/ip/Makefile
lib/ip/accept.c [new file with mode: 0644]
lib/ip/bind.c [new file with mode: 0644]
lib/ip/connect.c [new file with mode: 0644]
lib/ip/getpeername.c [new file with mode: 0644]
lib/ip/hton.c
lib/ip/listen.c [new file with mode: 0644]
lib/ip/recv.c [new file with mode: 0644]
lib/ip/recvfrom.c [new file with mode: 0644]
lib/ip/send.c [new file with mode: 0644]
lib/ip/sendto.c [new file with mode: 0644]
lib/ip/sethostent.c [new file with mode: 0644]
lib/ip/setsockopt.c [new file with mode: 0644]
lib/ip/socket.c [new file with mode: 0644]

index 4d309d305cb73e66058cc3fed19d85f255d80c18..fed1b163a1ecb6cc9df41b1d93a8c63705db3d47 100755 (executable)
@@ -10,6 +10,9 @@ LIBRARY       = ../libc.a
 all:   $(LIBRARY)
 
 OBJECTS        = \
+       $(LIBRARY)(accept.o) \
+       $(LIBRARY)(bind.o) \
+       $(LIBRARY)(connect.o) \
        $(LIBRARY)(dhcp_gettag.o) \
        $(LIBRARY)(dhcp_settag.o) \
        $(LIBRARY)(ether_line.o) \
@@ -24,6 +27,7 @@ OBJECTS       = \
        $(LIBRARY)(getnetent.o) \
        $(LIBRARY)(getnetbyname.o) \
        $(LIBRARY)(getnetbyaddr.o) \
+       $(LIBRARY)(getpeername.o) \
        $(LIBRARY)(getproto.o) \
        $(LIBRARY)(getprotoent.o) \
        $(LIBRARY)(getservent.o) \
@@ -33,21 +37,38 @@ OBJECTS     = \
        $(LIBRARY)(inet_addr.o) \
        $(LIBRARY)(inet_network.o) \
        $(LIBRARY)(inet_ntoa.o) \
+       $(LIBRARY)(listen.o) \
        $(LIBRARY)(memcspn.o) \
        $(LIBRARY)(rcmd.o) \
+       $(LIBRARY)(recv.o) \
+       $(LIBRARY)(recvfrom.o) \
        $(LIBRARY)(res_comp.o) \
        $(LIBRARY)(res_init.o) \
        $(LIBRARY)(res_mkquery.o) \
        $(LIBRARY)(res_query.o) \
        $(LIBRARY)(res_send.o) \
        $(LIBRARY)(ruserok.o) \
+       $(LIBRARY)(send.o) \
+       $(LIBRARY)(sendto.o) \
+       $(LIBRARY)(sethostent.o) \
+       $(LIBRARY)(setsockopt.o) \
        $(LIBRARY)(servxcheck.o) \
+       $(LIBRARY)(socket.o) \
        $(LIBRARY)(strcasecmp.o) \
 
 $(LIBRARY):    $(OBJECTS)
        aal cr $@ *.o
        rm *.o
 
+$(LIBRARY)(accept.o):  accept.c
+       $(CC1) accept.c
+
+$(LIBRARY)(bind.o):    bind.c
+       $(CC1) bind.c
+
+$(LIBRARY)(connect.o): connect.c
+       $(CC1) connect.c
+
 $(LIBRARY)(dhcp_gettag.o):     dhcp_gettag.c
        $(CC1) dhcp_gettag.c
 
@@ -90,6 +111,9 @@ $(LIBRARY)(getnetbyname.o):  getnetbyname.c
 $(LIBRARY)(getnetbyaddr.o):    getnetbyaddr.c
        $(CC1) getnetbyaddr.c
 
+$(LIBRARY)(getpeername.o):     getpeername.c
+       $(CC1) getpeername.c
+
 $(LIBRARY)(getproto.o):        getproto.c
        $(CC1) getproto.c
 
@@ -117,6 +141,9 @@ $(LIBRARY)(inet_network.o): inet_network.c
 $(LIBRARY)(inet_ntoa.o):       inet_ntoa.c
        $(CC1) inet_ntoa.c
 
+$(LIBRARY)(listen.o):  listen.c
+       $(CC1) listen.c
+
 $(LIBRARY)(memcspn.o): memcspn.c
        $(CC1) memcspn.c
 
@@ -126,6 +153,12 @@ $(LIBRARY)(oneC_sum.o):    oneC_sum.c
 $(LIBRARY)(rcmd.o):    rcmd.c
        $(CC1) rcmd.c
 
+$(LIBRARY)(recv.o):    recv.c
+       $(CC1) recv.c
+
+$(LIBRARY)(recvfrom.o):        recvfrom.c
+       $(CC1) recvfrom.c
+
 $(LIBRARY)(res_comp.o):        res_comp.c
        $(CC1) res_comp.c
 
@@ -144,8 +177,23 @@ $(LIBRARY)(res_send.o):    res_send.c
 $(LIBRARY)(ruserok.o): ruserok.c
        $(CC1) ruserok.c
 
+$(LIBRARY)(send.o):    send.c
+       $(CC1) send.c
+
+$(LIBRARY)(sendto.o):  sendto.c
+       $(CC1) sendto.c
+
+$(LIBRARY)(sethostent.o):      sethostent.c
+       $(CC1) sethostent.c
+
+$(LIBRARY)(setsockopt.o):      setsockopt.c
+       $(CC1) setsockopt.c
+
 $(LIBRARY)(servxcheck.o):      servxcheck.c
        $(CC1) servxcheck.c
 
+$(LIBRARY)(socket.o):  socket.c
+       $(CC1) socket.c
+
 $(LIBRARY)(strcasecmp.o):      strcasecmp.c
        $(CC1) strcasecmp.c
diff --git a/lib/ip/accept.c b/lib/ip/accept.c
new file mode 100644 (file)
index 0000000..28a543b
--- /dev/null
@@ -0,0 +1,65 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/netlib.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static int _tcp_accept(int socket, struct sockaddr *_RESTRICT address,
+       socklen_t *_RESTRICT address_len);
+
+int accept(int socket, struct sockaddr *_RESTRICT address,
+       socklen_t *_RESTRICT address_len)
+{
+       int r;
+
+       r= _tcp_accept(socket, address, address_len);
+       return r;
+
+#if DEBUG
+       fprintf(stderr, "accept: not implemented for fd %d\n", socket);
+#endif
+       errno= ENOSYS;
+       return -1;
+}
+
+static int _tcp_accept(int socket, struct sockaddr *_RESTRICT address,
+       socklen_t *_RESTRICT address_len)
+{
+       int r, s1, t_errno;
+       tcp_cookie_t cookie;
+
+       s1= open(TCP_DEVICE, O_RDWR);
+       if (s1 == -1)
+               return s1;
+       r= ioctl(s1, NWIOGTCPCOOKIE, &cookie);
+       if (r == -1)
+       {
+               t_errno= errno;
+               close(s1);
+               errno= t_errno;
+               return -1;
+       }
+       r= ioctl(socket, NWIOTCPACCEPTTO, &cookie);
+       if (r == -1)
+       {
+               t_errno= errno;
+               close(s1);
+               errno= t_errno;
+               return -1;
+       }
+       if (address != NULL)
+               getpeername(s1, address, address_len);
+       return s1;
+}
diff --git a/lib/ip/bind.c b/lib/ip/bind.c
new file mode 100644 (file)
index 0000000..f84e2be
--- /dev/null
@@ -0,0 +1,153 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static int _tcp_bind(int socket, const struct sockaddr *address,
+       socklen_t address_len, nwio_tcpconf_t *tcpconfp);
+static int _udp_bind(int socket, const struct sockaddr *address,
+       socklen_t address_len, nwio_udpopt_t *udpoptp);
+
+int bind(int socket, const struct sockaddr *address, socklen_t address_len)
+{
+       int r;
+       nwio_tcpconf_t tcpconf;
+       nwio_udpopt_t udpopt;
+
+       r= ioctl(socket, NWIOGTCPCONF, &tcpconf);
+       if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
+       {
+               if (r == -1)
+                       return r;
+               r= _tcp_bind(socket, address, address_len, &tcpconf);
+#if DEBUG
+               if (r == -1)
+               {
+                       int t_errno= errno;
+                       fprintf(stderr, "bind(tcp) failed: %s\n",
+                               strerror(errno));
+                       errno= t_errno;
+               }
+#endif
+               return r;
+       }
+
+       r= ioctl(socket, NWIOGUDPOPT, &udpopt);
+       if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
+       {
+               if (r == -1)
+                       return r;
+               return _udp_bind(socket, address, address_len, &udpopt);
+       }
+
+#if DEBUG
+       fprintf(stderr, "bind: not implemented for fd %d\n", socket);
+#endif
+       errno= ENOSYS;
+       return -1;
+}
+
+static int _tcp_bind(int socket, const struct sockaddr *address,
+       socklen_t address_len, nwio_tcpconf_t *tcpconfp)
+{
+       int r;
+       nwio_tcpconf_t tcpconf;
+       struct sockaddr_in *sinp;
+
+       sinp= (struct sockaddr_in *)address;
+       if (sinp->sin_family != AF_INET || address_len != sizeof(*sinp))
+       {
+#if DEBUG
+               fprintf(stderr, "bind(tcp): sin_family = %d, len = %d\n",
+                       sinp->sin_family, address_len);
+#endif
+               errno= EAFNOSUPPORT;
+               return -1;
+       }
+
+       if (sinp->sin_addr.s_addr != INADDR_ANY &&
+               sinp->sin_addr.s_addr != tcpconfp->nwtc_locaddr)
+       {
+               errno= EADDRNOTAVAIL;
+               return -1;
+       }
+
+       tcpconf.nwtc_flags= 0;
+
+       if (sinp->sin_port == 0)
+               tcpconf.nwtc_flags |= NWTC_LP_SEL;
+       else
+       {
+               tcpconf.nwtc_flags |= NWTC_LP_SET;
+               tcpconf.nwtc_locport= sinp->sin_port;
+       }
+
+       r= ioctl(socket, NWIOSTCPCONF, &tcpconf);
+       return r;
+}
+
+static int _udp_bind(int socket, const struct sockaddr *address,
+       socklen_t address_len, nwio_udpopt_t *udpoptp)
+{
+       int r;
+       unsigned long curr_flags;
+       nwio_udpopt_t udpopt;
+       struct sockaddr_in *sinp;
+
+       sinp= (struct sockaddr_in *)address;
+       if (sinp->sin_family != AF_INET || address_len != sizeof(*sinp))
+       {
+#if DEBUG
+               fprintf(stderr, "bind(udp): sin_family = %d, len = %d\n",
+                       sinp->sin_family, address_len);
+#endif
+               errno= EAFNOSUPPORT;
+               return -1;
+       }
+
+       if (sinp->sin_addr.s_addr != INADDR_ANY &&
+               sinp->sin_addr.s_addr != udpoptp->nwuo_locaddr)
+       {
+               errno= EADDRNOTAVAIL;
+               return -1;
+       }
+
+       udpopt.nwuo_flags= 0;
+
+       if (sinp->sin_port == 0)
+               udpopt.nwuo_flags |= NWUO_LP_SEL;
+       else
+       {
+               udpopt.nwuo_flags |= NWUO_LP_SET;
+               udpopt.nwuo_locport= sinp->sin_port;
+       }
+
+       curr_flags= udpoptp->nwuo_flags;
+       if (!(curr_flags & NWUO_ACC_MASK))
+               udpopt.nwuo_flags |= NWUO_EXCL;
+       if (!(curr_flags & (NWUO_EN_LOC|NWUO_DI_LOC)))
+               udpopt.nwuo_flags |= NWUO_EN_LOC;
+       if (!(curr_flags & (NWUO_EN_BROAD|NWUO_DI_BROAD)))
+               udpopt.nwuo_flags |= NWUO_EN_BROAD;
+       if (!(curr_flags & (NWUO_RP_SET|NWUO_RP_ANY)))
+               udpopt.nwuo_flags |= NWUO_RP_ANY;
+       if (!(curr_flags & (NWUO_RA_SET|NWUO_RA_ANY)))
+               udpopt.nwuo_flags |= NWUO_RA_ANY;
+       if (!(curr_flags & (NWUO_RWDATONLY|NWUO_RWDATALL)))
+               udpopt.nwuo_flags |= NWUO_RWDATALL;
+       if (!(curr_flags & (NWUO_EN_IPOPT|NWUO_DI_IPOPT)))
+               udpopt.nwuo_flags |= NWUO_DI_IPOPT;
+
+       r= ioctl(socket, NWIOSUDPOPT, &udpopt);
+       return r;
+}
diff --git a/lib/ip/connect.c b/lib/ip/connect.c
new file mode 100644 (file)
index 0000000..295bb8c
--- /dev/null
@@ -0,0 +1,90 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static int _tcp_connect(int socket, const struct sockaddr *address,
+       socklen_t address_len, nwio_tcpconf_t *tcpconfp);
+
+int connect(int socket, const struct sockaddr *address,
+       socklen_t address_len)
+{
+       int r;
+       nwio_tcpconf_t tcpconf;
+
+       r= ioctl(socket, NWIOGTCPCONF, &tcpconf);
+       if (r != -1 || errno != ENOTTY)
+       {
+               if (r == -1)
+               {
+                       /* Bad file descriptor */
+                       return -1;
+               }
+               return _tcp_connect(socket, address, address_len, &tcpconf);
+       }
+#if DEBUG
+       fprintf(stderr, "connect: not implemented for fd %d\n", socket);
+#endif
+       errno= ENOSYS;
+       return -1;
+}
+
+static int _tcp_connect(int socket, const struct sockaddr *address,
+       socklen_t address_len, nwio_tcpconf_t *tcpconfp)
+{
+       int r;
+       struct sockaddr_in *sinp;
+       nwio_tcpconf_t tcpconf;
+       nwio_tcpcl_t tcpcl;
+
+       if (address_len != sizeof(*sinp))
+       {
+               errno= EINVAL;
+               return -1;
+       }
+       sinp= (struct sockaddr_in *)address;
+       if (sinp->sin_family != AF_INET)
+       {
+               errno= EINVAL;
+               return -1;
+       }
+       tcpconf.nwtc_flags= NWTC_SET_RA | NWTC_SET_RP;
+       if ((tcpconfp->nwtc_flags & NWTC_LOCPORT_MASK) == NWTC_LP_UNSET)
+               tcpconf.nwtc_flags |= NWTC_LP_SEL;
+       tcpconf.nwtc_remaddr= sinp->sin_addr.s_addr;
+       tcpconf.nwtc_remport= sinp->sin_port;
+
+       if (ioctl(socket, NWIOSTCPCONF, &tcpconf) == -1)
+       {
+               int  t_errno= errno;
+
+               fprintf(stderr, "setconf failed: %s\n", strerror(errno));
+
+               errno= t_errno;
+
+               return -1;
+       }
+
+       tcpcl.nwtcl_flags= 0;
+
+       r= ioctl(socket, NWIOTCPCONN, &tcpcl);
+       if (r == -1)
+       {
+               int  t_errno= errno;
+
+               fprintf(stderr, "connect failed: %s\n", strerror(errno));
+
+               errno= t_errno;
+       }
+       return r;
+}
diff --git a/lib/ip/getpeername.c b/lib/ip/getpeername.c
new file mode 100644 (file)
index 0000000..3d5d826
--- /dev/null
@@ -0,0 +1,70 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static int _tcp_getpeername(int socket, struct sockaddr *_RESTRICT address,
+       socklen_t *_RESTRICT address_len, nwio_tcpconf_t *tcpconfp);
+
+int getpeername(int socket, struct sockaddr *_RESTRICT address,
+       socklen_t *_RESTRICT address_len)
+{
+       int r;
+       nwio_tcpconf_t tcpconf;
+
+       r= ioctl(socket, NWIOGTCPCONF, &tcpconf);
+       if (r != -1 || errno != ENOTTY)
+       {
+               if (r == -1)
+               {
+                       /* Bad file descriptor */
+                       return -1;
+               }
+               return _tcp_getpeername(socket, address, address_len,
+                       &tcpconf);
+       }
+
+#if DEBUG
+       fprintf(stderr, "getpeername: not implemented for fd %d\n", socket);
+#endif
+       errno= ENOSYS;
+       return -1;
+}
+
+static int _tcp_getpeername(int socket, struct sockaddr *_RESTRICT address,
+       socklen_t *_RESTRICT address_len, nwio_tcpconf_t *tcpconfp)
+{
+       socklen_t len;
+       struct sockaddr_in sin;
+
+       if (((tcpconfp->nwtc_flags & NWTC_REMADDR_MASK) != NWTC_SET_RA) ||
+               ((tcpconfp->nwtc_flags & NWTC_REMPORT_MASK) != NWTC_SET_RP))
+       {
+               errno= ENOTCONN;
+               return -1;
+       }
+
+       memset(&sin, '\0', sizeof(sin));
+       sin.sin_family= AF_INET;
+       sin.sin_addr.s_addr= tcpconfp->nwtc_remaddr;
+       sin.sin_port= tcpconfp->nwtc_remport;
+
+       len= *address_len;
+       if (len > sizeof(sin))
+               len= sizeof(sin);
+       memcpy(address, &sin, len);
+       *address_len= len;
+
+       return 0;
+}
+
index 69e3dbd572d8f3c7747002dcddc3d6c88a2b36a4..4f93f591ac42c56955d9ed3f86dcf3ee4ccfe4a7 100755 (executable)
@@ -8,3 +8,11 @@ hton.c
 
 u16_t _tmp;
 u32_t _tmp_l;
+
+#if _WORD_SIZE > 2
+u16_t (htons)(u16_t x) { return HTONS(x); }
+u16_t (ntohs)(u16_t x) { return NTOHS(x); }
+u32_t (htonl)(u32_t x) { return HTONL(x); }
+u32_t (ntohl)(u32_t x) { return NTOHL(x); }
+#endif
+
diff --git a/lib/ip/listen.c b/lib/ip/listen.c
new file mode 100644 (file)
index 0000000..d2283e5
--- /dev/null
@@ -0,0 +1,30 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+int listen(int socket, int backlog)
+{
+       int r;
+
+       r= ioctl(socket, NWIOTCPLISTENQ, &backlog);
+       if (r != -1 || errno != EBADIOCTL)
+               return r;
+
+#if DEBUG
+       fprintf(stderr, "listen: not implemented for fd %d\n", socket);
+#endif
+       errno= ENOSYS;
+       return -1;
+}
+
diff --git a/lib/ip/recv.c b/lib/ip/recv.c
new file mode 100644 (file)
index 0000000..6806ef2
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdlib.h>
+#include <sys/socket.h>
+
+ssize_t recv(int socket, void *buffer, size_t length, int flags)
+{
+       return recvfrom(socket, buffer, length, flags, NULL, NULL);
+}
+
diff --git a/lib/ip/recvfrom.c b/lib/ip/recvfrom.c
new file mode 100644 (file)
index 0000000..ee09f83
--- /dev/null
@@ -0,0 +1,120 @@
+#undef NDEBUG
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static ssize_t _udp_recvfrom(int socket, void *_RESTRICT buffer, size_t length,
+       int flags, struct sockaddr *_RESTRICT address,
+       socklen_t *_RESTRICT address_len, nwio_udpopt_t *udpoptp);
+
+ssize_t recvfrom(int socket, void *_RESTRICT buffer, size_t length,
+       int flags, struct sockaddr *_RESTRICT address,
+       socklen_t *_RESTRICT address_len)
+{
+       int r;
+       nwio_udpopt_t udpopt;
+
+       fprintf(stderr, "recvfrom: for fd %d\n", socket);
+
+       r= ioctl(socket, NWIOGUDPOPT, &udpopt);
+       if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
+       {
+               if (r == -1)
+                       return r;
+               return _udp_recvfrom(socket, buffer, length, flags,
+                       address, address_len, &udpopt);
+       }
+
+#if DEBUG
+       fprintf(stderr, "recvfrom: not implemented for fd %d\n", socket);
+#endif
+       errno= ENOSYS;
+       assert(0);
+       return -1;
+}
+
+static ssize_t _udp_recvfrom(int socket, void *_RESTRICT buffer, size_t length,
+       int flags, struct sockaddr *_RESTRICT address,
+       socklen_t *_RESTRICT address_len, nwio_udpopt_t *udpoptp)
+{
+       int r, t_errno;
+       size_t buflen, len;
+       void *buf;
+       struct sockaddr_in *sinp;
+       udp_io_hdr_t *io_hdrp;
+       struct sockaddr_in sin;
+
+       if (flags)
+       {
+#if DEBUG
+               fprintf(stderr, "recvfrom(udp): flags not implemented\n");
+#endif
+               errno= ENOSYS;
+               return -1;
+       }
+
+       if (udpoptp->nwuo_flags & NWUO_RWDATONLY)
+       {
+#if DEBUG
+               fprintf(stderr,
+                       "recvfrom(udp): NWUO_RWDATONLY not implemented\n");
+#endif
+               errno= ENOSYS;
+               return -1;
+       }
+
+       buflen= sizeof(*io_hdrp) + length;
+       if (buflen < length)
+       {       
+               /* Overflow */
+               errno= EMSGSIZE;
+               return -1;
+       }
+       buf= malloc(buflen);
+       if (buf == NULL)
+               return -1;
+
+       r= read(socket, buf, buflen);
+       if (r == -1)
+       {
+               t_errno= errno;
+               free(buf);
+               errno= t_errno;
+               return -1;
+       }
+
+       assert(r >= sizeof(*io_hdrp));
+       length= r-sizeof(*io_hdrp);
+
+       io_hdrp= buf;
+       memcpy(buffer, &io_hdrp[1], length);
+
+       if (address != NULL)
+       {
+               sin.sin_family= AF_INET;
+               sin.sin_addr.s_addr= io_hdrp->uih_src_addr;
+               sin.sin_port= io_hdrp->uih_src_port;
+               len= *address_len;
+               if (len > sizeof(sin))
+                       len= sizeof(sin);
+               memcpy(address, &sin, len);
+               *address_len= sizeof(sin);
+       }       
+       free(buf);
+       return length;
+}
+
diff --git a/lib/ip/send.c b/lib/ip/send.c
new file mode 100644 (file)
index 0000000..27ea0d0
--- /dev/null
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+#include <sys/socket.h>
+
+ssize_t send(int socket, const void *buffer, size_t length, int flags)
+{
+       struct sockaddr sa;
+
+       sa.sa_family= AF_UNSPEC;
+       return sendto(socket, buffer, length, flags, &sa, sizeof(sa));
+}
+
diff --git a/lib/ip/sendto.c b/lib/ip/sendto.c
new file mode 100644 (file)
index 0000000..1646cf4
--- /dev/null
@@ -0,0 +1,123 @@
+#undef NDEBUG
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static ssize_t _udp_sendto(int socket, const void *message, size_t length,
+       int flags, const struct sockaddr *dest_addr, socklen_t dest_len,
+       nwio_udpopt_t *udpoptp);
+
+ssize_t sendto(int socket, const void *message, size_t length, int flags,
+       const struct sockaddr *dest_addr, socklen_t dest_len)
+{
+       int r;
+       nwio_udpopt_t udpopt;
+
+       r= ioctl(socket, NWIOGUDPOPT, &udpopt);
+       if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
+       {
+               if (r == -1)
+                       return r;
+               return _udp_sendto(socket, message, length, flags,
+                       dest_addr, dest_len, &udpopt);
+       }
+
+#if DEBUG
+       fprintf(stderr, "sendto: not implemented for fd %d\n", socket);
+#endif
+       errno= ENOSYS;
+       return -1;
+}
+
+static ssize_t _udp_sendto(int socket, const void *message, size_t length,
+       int flags, const struct sockaddr *dest_addr, socklen_t dest_len,
+       nwio_udpopt_t *udpoptp)
+{
+       int r, t_errno;
+       size_t buflen;
+       void *buf;
+       struct sockaddr_in *sinp;
+       udp_io_hdr_t *io_hdrp;
+
+       if (flags)
+       {
+#if DEBUG
+               fprintf(stderr, "sendto(udp): flags not implemented\n");
+#endif
+               errno= ENOSYS;
+               return -1;
+       }
+
+       if (udpoptp->nwuo_flags & NWUO_RWDATONLY)
+               return write(socket, message, length);
+
+       if ((udpoptp->nwuo_flags & NWUO_RP_ANY) ||
+               (udpoptp->nwuo_flags & NWUO_RA_ANY))
+       {
+               /* Check destination address */
+               if (dest_len < sizeof(*sinp))
+               {
+                       errno= EINVAL;
+                       return -1;
+               }
+               sinp= (struct sockaddr_in *)dest_addr;
+               if (sinp->sin_family != AF_INET)
+               {
+                       errno= EAFNOSUPPORT;
+                       return -1;
+               }
+       }
+
+       buflen= sizeof(*io_hdrp) + length;
+       if (buflen < length)
+       {       
+               /* Overflow */
+               errno= EMSGSIZE;
+               return -1;
+       }
+       buf= malloc(buflen);
+       if (buf == NULL)
+               return -1;
+
+       io_hdrp= buf;
+       io_hdrp->uih_src_addr= 0;       /* Unused */
+       io_hdrp->uih_src_port= 0;       /* Will cause error if NWUO_LP_ANY */
+       if (udpoptp->nwuo_flags & NWUO_RA_ANY)
+               io_hdrp->uih_dst_addr= sinp->sin_addr.s_addr;
+       else
+               io_hdrp->uih_dst_addr= 0;
+       if (udpoptp->nwuo_flags & NWUO_RP_ANY)
+               io_hdrp->uih_dst_port= sinp->sin_port;
+       else
+               io_hdrp->uih_dst_port= 0;
+       io_hdrp->uih_ip_opt_len= 0;
+       io_hdrp->uih_data_len= 0;
+
+       memcpy(&io_hdrp[1], message, length);
+       r= write(socket, buf, buflen);
+       if (r == -1)
+       {
+               t_errno= errno;
+               free(buf);
+               errno= t_errno;
+               return -1;
+       }
+       assert(r == buflen);
+       free(buf);
+       return length;
+}
+
diff --git a/lib/ip/sethostent.c b/lib/ip/sethostent.c
new file mode 100644 (file)
index 0000000..d0b6416
--- /dev/null
@@ -0,0 +1,79 @@
+/*     $OpenBSD: sethostent.c,v 1.1 1997/03/12 10:42:11 downsj Exp $   */
+
+/*
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)sethostent.c       8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: sethostent.c,v 8.5 1996/09/28 06:51:07 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: sethostent.c,v 1.1 1997/03/12 10:42:11 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef notyet
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+#else
+#include <sys/types.h>
+#include <net/gen/in.h>
+#include <net/gen/nameser.h>
+#include <net/gen/netdb.h>
+#include <net/gen/resolv.h>
+#endif
+
+void
+sethostent(stayopen)
+       int stayopen;
+{
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+               return;
+       if (stayopen)
+               _res.options |= RES_STAYOPEN | RES_USEVC;
+}
+
+void
+endhostent()
+{
+       _res.options &= ~(RES_STAYOPEN | RES_USEVC);
+       _res_close();
+}
+
+/*
+ * $PchId: sethostent.c,v 1.2 2000/04/01 18:27:16 philip Exp $
+ */
diff --git a/lib/ip/setsockopt.c b/lib/ip/setsockopt.c
new file mode 100644 (file)
index 0000000..f6ddff0
--- /dev/null
@@ -0,0 +1,70 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+
+#define DEBUG 0
+
+static int _tcp_setsockopt(int socket, int level, int option_name,
+       const void *option_value, socklen_t option_len);
+
+int setsockopt(int socket, int level, int option_name,
+        const void *option_value, socklen_t option_len)
+{
+       int r;
+       nwio_tcpopt_t tcpopt;
+
+       r= ioctl(socket, NWIOGTCPOPT, &tcpopt);
+       if (r != -1 || errno != ENOTTY)
+       {
+               if (r == -1)
+               {
+                       /* Bad file descriptor */
+                       return -1;
+               }
+               return _tcp_setsockopt(socket, level, option_name,
+                       option_value, option_len);
+       }
+
+#if DEBUG
+       fprintf(stderr, "setsockopt: not implemented for fd %d\n", socket);
+#endif
+       errno= ENOSYS;
+       return -1;
+}
+
+static int _tcp_setsockopt(int socket, int level, int option_name,
+       const void *option_value, socklen_t option_len)
+{
+       int i;
+
+       if (level == SOL_SOCKET && option_name == SO_KEEPALIVE)
+       {
+               if (option_len != sizeof(i))
+               {
+                       errno= EINVAL;
+                       return -1;
+               }
+               i= *(int *)option_value;
+               if (!i)
+               {
+                       /* At the moment there is no way to turn off 
+                        * keepalives.
+                        */
+                       errno= ENOSYS;
+                       return -1;
+               }
+               return 0;
+       }
+       fprintf(stderr, "_tcp_setsocketopt: level %d, name %d\n",
+               level, option_name);
+
+       assert(0);
+}
+
diff --git a/lib/ip/socket.c b/lib/ip/socket.c
new file mode 100644 (file)
index 0000000..95a7fd0
--- /dev/null
@@ -0,0 +1,66 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/socket.h>
+
+#include <net/netlib.h>
+
+#define DEBUG 0
+
+static int _tcp_socket(int protocol);
+static int _udp_socket(int protocol);
+
+int socket(int domain, int type, int protocol)
+{
+       if (domain != AF_INET)
+       {
+#if DEBUG
+               fprintf(stderr, "socket: bad domain %d\n", domain);
+#endif
+               errno= EAFNOSUPPORT;
+               return -1;
+       }
+       if (type == SOCK_STREAM)
+               return _tcp_socket(protocol);
+
+       if (type == SOCK_DGRAM)
+               return _udp_socket(protocol);
+
+#if DEBUG
+       fprintf(stderr, "socket: nothing for domain %d, type %d, protocol %d\n",
+               domain, type, protocol);
+#endif
+       errno= EPROTOTYPE;
+       return -1;
+}
+
+static int _tcp_socket(int protocol)
+{
+       int fd;
+       if (protocol != 0)
+       {
+#if DEBUG
+               fprintf(stderr, "socket(tcp): bad protocol %d\n", protocol);
+#endif
+               errno= EPROTONOSUPPORT;
+               return -1;
+       }
+       fd= open(TCP_DEVICE, O_RDWR);
+       return fd;
+}
+
+static int _udp_socket(int protocol)
+{
+       int fd;
+       if (protocol != 0)
+       {
+#if DEBUG
+               fprintf(stderr, "socket(udp): bad protocol %d\n", protocol);
+#endif
+               errno= EPROTONOSUPPORT;
+               return -1;
+       }
+       fd= open(UDP_DEVICE, O_RDWR);
+       return fd;
+}
+