gno/kern/gno/net.c

431 lines
9.3 KiB
C

/* $Id: net.c,v 1.1 1998/02/02 08:18:36 taubert Exp $ */
/*
* GNO/ME Network Support
*
* Copyright 1994-1998, Procyon Enterprises Inc.
*
* Written by Derek Taubert and Jawaid Bazyar
*
* KERNInstallNetDriver(inf *netcore,int *ERRNO)
* KERNsocket(int domain, int type, int protocol, int *ERRNO)
* KERNbind(int fd, struct sockaddr *my_addr, int addrlen, int *ERRNO)
* KERNconnect(int fd, struct sockaddr *serv_addr, int addrlen, int *ERRNO)
* KERNlisten(int fd, int backlog, int *ERRNO)
* KERNaccept(int fd, struct sockaddr *rem_addr, int *addrlen, int *ERRNO)
* KERNrecvfrom(int fd, void *buf, size_t len, unsigned int flags, struct sockaddr *rem_addr, int *addrlen, int *ERRNO)
* KERNsendto(int fd, void *buf, size_t len, unsigned int flags, struct sockaddr *rem_addr, int addrlen, int *ERRNO)
* KERNrecv(int fd, void *buf, size_t len, unsigned int flags, int *ERRNO)
* KERNsend(int fd, void *buf, size_t len, unsigned int flags, int *ERRNO)
*
* KERNgetpeername(int s, struct sockaddr *peer_addr, int *addrlen, int *ERRNO)
* KERNgetsockname(int s, struct sockaddr *sock_addr, int *addrlen, int *ERRNO)
* KERNgetsockopt(int s, int level, int optname, void *optval, int *optlen, int *ERRNO)
* KERNsetsockopt(int s, int level, int optname, void *optval, int optlen, int *ERRNO)
*/
#include "gno.h"
#include "proc.h"
#include "sys.h"
#include "kernel.h"
#include "net.h"
#include "/lang/orca/libraries/orcacdefs/string.h"
#include "/lang/orca/libraries/orcacdefs/stdlib.h"
#include <locator.h>
#include <orca.h>
#include <memory.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
/*#define DEBUG
#include <debug.h>*/
#pragma optimize 79
segment "KERN3 ";
extern void selwakeup(int col_flag, int pid);
int (*pr_usrreq)(int socknum, int req, void *m, size_t *m_len,
struct sockaddr *addr, int *addrlen, void *rights) = NULL;
#pragma databank 1
int SOCKioctl(void *dataptr, longword tioc, int sock)
{
if (!pr_usrreq) return EPFNOSUPPORT;
return (*pr_usrreq)(sock,PRU_CONTROL,(void *)&tioc,NULL,(struct sockaddr *)dataptr,NULL,NULL);
}
/* socket number to select on, and flags */
int SOCKselect(int pid, int fl, int sock)
{
if (!pr_usrreq) return EPFNOSUPPORT;
sock++; /* downfall of optimization in calling routine */
(*pr_usrreq)(sock,PRU_SELECT,NULL,(size_t *)&pid,(struct sockaddr *)&fl,NULL,NULL);
return (fl != 0) ? 1 : 0;
}
int SOCKclose(int sock)
/* Called from inside GS/OS, has to return special error codes */
{
int err = 0;
if (!pr_usrreq) return EPFNOSUPPORT|0x4300;
(*pr_usrreq)(
sock,
PRU_DISCONNECT,
NULL,
NULL,
NULL,
NULL,
NULL);
err = (*pr_usrreq)(
sock,
PRU_DETACH,
NULL,
NULL,
NULL,
NULL,
NULL);
return (!err) ? 0 : 0x4300 | err;
}
/* returns the refNum field of a file descriptor if that fd is a socket,
and is valid. Otherwise, returns -ERRNO */
int getsocknum(int fd)
{
fdentryPtr fdp;
extern fdentryPtr getFDptr(int);
if (!pr_usrreq) return -EPFNOSUPPORT;
fdp = getFDptr(fd);
if (fdp == NULL) return -EBADF;
if (fdp->refType != rtSOCKET) return -ENOTSOCK; /* Not a socket */
return fdp->refNum;
}
struct rwPBlock {
word ref;
void *buffer;
size_t reqCount;
size_t xferCount;
word cachePriority;
};
int SOCKrdwr(struct rwPBlock *pb, word cmd, int sock)
/* Called from inside GS/OS, has to return special error codes */
{
size_t len;
int err;
if (!pr_usrreq) return 0x4300|EPFNOSUPPORT;
len = pb->reqCount;
err = (*pr_usrreq) (
sock,
(((cmd & 0xFF) == 0x12) ? PRU_RCVD : PRU_SEND),
pb->buffer,
&len,
NULL,
NULL,
NULL);
pb->xferCount = len;
return (err == 0) ? 0 : err | 0x4300;
}
#pragma toolparms 1
pascal int KERNInstallNetDriver(void *netcore,int domain,int *ERRNO)
{
pr_usrreq = netcore;
/* don't need domain yet, we only support one type of network */
return 0;
}
pascal int KERNsocket(int domain, int type, int protocol, int *ERRNO)
{
int fd,sock;
fdentryPtr fdp;
fdtablePtr fdt;
if ((domain != PF_INET) || (!pr_usrreq)) {
*ERRNO = EPFNOSUPPORT;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
type,
PRU_ATTACH,
&sock,
(size_t *)selwakeup,
(struct sockaddr *) &protocol,
NULL,
NULL)) return -1;
disableps();
fdt = PROC->openFiles;
fdt->fdCount++;
fdp = allocFD(&fd);
fdp->refNum = sock;
fdp->refType = rtSOCKET;
fdp->refFlags = 0;
fdp->refLevel = fdt->fdLevel | fdt->fdLevelMode;
fdp->NLenableMask = 0;
fdp->NLnumChars = 0;
fdp->NLtable = NULL;
AddRefnum(rtSOCKET,sock);
enableps();
return fd;
}
pascal int KERNbind(int fd, struct sockaddr *my_addr, int addrlen, int *ERRNO)
{
int err,sock;
if ((sock = getsocknum(fd)) < 0) {
*ERRNO = -sock;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
sock,
PRU_BIND,
NULL,
NULL,
my_addr,
&addrlen,
NULL)) return -1;
return 0;
}
pascal int KERNconnect(int fd, struct sockaddr *serv_addr, int addrlen, int *ERRNO)
{
int sock;
if ((sock = getsocknum(fd)) < 0) {
*ERRNO = -sock;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
sock,
PRU_CONNECT,
NULL,
NULL,
serv_addr,
&addrlen,
NULL)) return -1;
return 0;
}
pascal int KERNlisten(int fd, int backlog, int *ERRNO)
{
int sock;
if ((sock = getsocknum(fd)) < 0) {
*ERRNO = -sock;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
sock,
PRU_LISTEN,
&backlog,
NULL,
NULL,
NULL,
NULL)) return -1;
return 0;
}
pascal int KERNaccept(int fd, struct sockaddr *rem_addr, int *addrlen, int *ERRNO)
{
int newfd,sock;
fdentryPtr fdp;
fdtablePtr fdt;
if ((sock = getsocknum(fd)) < 0) {
*ERRNO = -sock;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
sock,
PRU_ACCEPT,
&newfd,
(size_t *)selwakeup,
rem_addr,
addrlen,
NULL)) return -1;
disableps();
fdt = PROC->openFiles;
fdt->fdCount++;
fdp = allocFD(&fd);
fdp->refNum = newfd;
fdp->refType = rtSOCKET;
fdp->refFlags = 0;
fdp->refLevel = fdt->fdLevel | fdt->fdLevelMode;
fdp->NLenableMask = 0;
fdp->NLnumChars = 0;
fdp->NLtable = NULL;
AddRefnum(rtSOCKET,newfd);
enableps();
return fd;
}
pascal int KERNrecvfrom(int fd, void *buf, size_t len, unsigned int flags, struct sockaddr *rem_addr, int *addrlen, int *ERRNO)
{
int sock;
if ((sock = getsocknum(fd)) < 0) {
*ERRNO = -sock;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
sock,
(flags & MSG_OOB) ? PRU_RCVOOB : PRU_RCVD,
buf,
&len,
rem_addr,
addrlen,
NULL)) return -1;
return len;
}
pascal int KERNsendto(int fd, void *buf, size_t len, unsigned int flags, struct sockaddr *rem_addr, int addrlen, int *ERRNO)
{
int sock;
if ((sock = getsocknum(fd)) < 0) {
*ERRNO = -sock;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
sock,
(flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
buf,
&len,
rem_addr,
&addrlen,
NULL)) return -1;
return len;
}
pascal int KERNrecv(int fd, void *buf, size_t len, unsigned int flags, int *ERRNO)
{
int sock;
if ((sock = getsocknum(fd)) < 0) {
*ERRNO = -sock;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
sock,
(flags & MSG_OOB) ? PRU_RCVOOB : PRU_RCVD,
buf,
&len,
NULL,
NULL,
NULL)) return -1;
return len;
}
pascal int KERNsend(int fd, void *buf, size_t len, unsigned int flags, int *ERRNO)
{
int sock;
if ((sock = getsocknum(fd)) < 0) {
*ERRNO = -sock;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
sock,
(flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
buf,
&len,
NULL,
NULL,
NULL)) return -1;
return len;
}
pascal int KERNgetpeername(int s, struct sockaddr *peer_addr, int *addrlen, int *ERRNO) {
int sock;
if ((sock = getsocknum(s)) < 0) {
*ERRNO = -sock;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
sock,
PRU_PEERADDR,
NULL,
NULL,
peer_addr,
addrlen,
NULL)) return -1;
return 0;
}
pascal int KERNgetsockname(int s, struct sockaddr *sock_addr, int *addrlen, int *ERRNO) {
int sock;
if ((sock = getsocknum(s)) < 0) {
*ERRNO = -sock;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
sock,
PRU_SOCKADDR,
NULL,
NULL,
sock_addr,
addrlen,
NULL)) return -1;
return 0;
}
pascal int KERNgetsockopt(int s, int level, int optname, void *optval, int *optlen, int *ERRNO) {
int sock;
if ((sock = getsocknum(s)) < 0) {
*ERRNO = -sock;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
sock,
PRU_CO_GETOPT,
&level,
(size_t *)&optname,
(struct sockaddr *)optval,
optlen,
NULL)) return -1;
return 0;
}
pascal int KERNsetsockopt(int s, int level, int optname, void *optval, int optlen, int *ERRNO) {
int sock;
if ((sock = getsocknum(s)) < 0) {
*ERRNO = -sock;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
sock,
PRU_CO_SETOPT,
&level,
(size_t *)&optname,
(struct sockaddr *)optval,
&optlen,
NULL)) return -1;
return 0;
}
pascal int KERNshutdown(int s, int how, int *ERRNO)
{
int sock;
if ((sock = getsocknum(s)) < 0) {
*ERRNO = -sock;
return -1;
}
if (*ERRNO = (*pr_usrreq)(
sock,
PRU_SHUTDOWN,
&how,
NULL,
NULL,
NULL,
NULL)) return -1;
return 0;
}
#pragma toolparms 0
#pragma databank 0