home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Black Box 4
/
BlackBox.cdr
/
lan
/
soss.arj
/
SRC
/
SOCK.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-22
|
7KB
|
298 lines
/*
* sock.c --
* Socket interface for PC NFS file server. This module provides
* one level of abstraction above the socket libraries and socket driver
* functions perculiar to different PC Ethernet cards.
* Note: this version for pcip only.
*
* Author:
* Tony G. Thomas 4/2/90
*/
#include "sock.h"
#include "debug.h"
#define bool_t int
#define enum_t int
#define u_int unsigned int
#define u_short unsigned short
#define u_long unsigned long
#define u_char unsigned char
#define __dontcare__ -1
#define caddr_t char *
#include "in.h"
extern NET nets[];
extern long cticks;
extern bcopy_fn();
extern bcopy_nf();
extern bcopy_ff();
void far *_fmalloc();
/* templates for local types
static struct sockproto UDP_PROTO = { PF_INET, IPPROTO_UDP };
static struct sockproto TCP_PROTO = { PF_INET, IPPROTO_TCP }; */
struct sockaddr_in *laddr[8], *raddr[8];
char far *p_pkts[8];
int ready_packs[8], used_socks[8];
UDPCONN con[8];
int handler();
/*
* int sock_create(int type, int protocol, struct sockaddr_in *addr) --
* Creates a socket of type using protocol, bound to address *addr on the
* local PC. Returns the socket descriptor or -1 if an error
* occurred.
*/
int sock_create(type, protocol, addr)
int type, protocol;
struct sockaddr_in *addr;
{
if (type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return sock_udpcreate(addr);
/* if (type == SOCK_STREAM && protocol == IPPROTO_TCP)
return sock_tcpcreate(addr); */
(void) fprintf(stderr, "Protocol not supported\n");
return -1;
}
/*
* int sock_udpcreate(struct sockaddr_in addr) --
* Creates a UDP socket on the local host using address specified.
* If port == 0 then an arbitrary port is assigned.
*/
int sock_udpcreate(addr)
struct sockaddr_in *addr;
{
int sock;
unsigned port;
DBGPRT0 (nfsdebug, "creating socket");
for (sock = 0; sock < 8; sock++ ) {
if (used_socks[sock] == 0) break;
if (sock == 7) {
(void) fprintf(stderr, "sock_udpcreate: too many sockets;");
return -1;
}
}
port = (unsigned) ( addr->sin_port ? addr->sin_port : udp_socket() );
ready_packs[sock] = 0;
con[sock] = udp_open(0L, 0, port, handler, (unsigned) sock);
if (con[sock] == NULL) {
(void) fprintf(stderr, "sock_udpcreate: error opening socket;");
return -1;
}
laddr[sock] = (struct sockaddr_in *) calloc(1, sizeof(struct sockaddr_in));
raddr[sock] = (struct sockaddr_in *) calloc(1, sizeof(struct sockaddr_in));
laddr[sock]->sin_family = addr->sin_family;
raddr[sock]->sin_family = addr->sin_family;
laddr[sock]->sin_port = (unsigned) (port);
(laddr[sock]->sin_addr).s_addr = (addr->sin_addr).s_addr;
used_socks[sock] = 1;
return sock;
}
/*
* Udp Packet Handler
*/
handler(p, len, host, sock)
PACKET p;
unsigned len;
in_name host;
unsigned sock;
{
if (ready_packs[sock] == 1) {
(void) fprintf(stderr, "UDP: discarding packet\n");
udp_free(p);
return;
}
p_pkts[sock] = (char far *) _fmalloc(len);
bcopy_nf(udp_data(udp_head(in_head(p))), p_pkts[sock], len);
ready_packs[sock] = 1;
raddr[sock]->sin_port = (unsigned) ((udp_head(in_head(p)))->ud_srcp);
(raddr[sock]->sin_addr).s_addr = host;
udp_free(p);
return;
}
/*
* void sock_close(int sock) --
* Closes the socket descriptor sock.
*/
void sock_close(sock)
int sock;
{
used_socks[sock] = 0;
free(laddr[sock]);
free(raddr[sock]);
udp_close(con[sock]);
return;
}
/*
* int sock_select(int *rfds, int *wfds) --
* Returns the number of descriptors readable corresponding to
* the bit masks in *rfds, or writable in *wfds.
* *rfds and *wfds are changed to reflect the readable sockets.
*/
int sock_select(rfds, wfds)
long *rfds, *wfds;
{
/* should use soselect, but the function seems to be buggy */
int sock, nd; /* socket and # of descriptors */
long mask, count;
tk_yield();
for(mask = 0, sock = 0, nd = 0; rfds != NULL && *rfds != 0;
sock++, *rfds >>= 1) {
if (*rfds & 1 != 0) {
/* soioctl(sock, FIONREAD, &count);
if (count != 0) */
if( ready_packs[sock] == 1)
mask |= 1 << sock, nd++;
}
}
*rfds = mask;
for(mask = 0, sock = 0; wfds != NULL && *wfds != 0;
sock++, *wfds >>= 1) {
if (*wfds & 1 != 0) {
/* soioctl(sock, FIONREAD, &count);
if (count != 0) */
if (used_socks[sock] = 1)
mask |= 1 << sock, nd++;
}
}
*wfds = mask;
return nd;
}
/*
* int sock_recv(int sock, char far *buf, int bufsiz, struct sockaddr_in *from) --
* Recevies message from socket and puts it into buffer. The from address
* is placed in *from. Returns the size of the message.
*/
int sock_recv(sock, buf, bufsiz, from)
int sock;
char far *buf;
int bufsiz;
struct sockaddr_in *from;
{
int recvlen;
/* struct sockaddr_in f; */
if (ready_packs[sock] == 0) return (0);
recvlen= (int) _fmsize(p_pkts[sock]);
if (recvlen < 0 ) (void) fprintf(stderr, "--> recv err\n");
*from = *raddr[sock];
bcopy_ff(p_pkts[sock], buf, (unsigned) bufsiz);
_ffree(p_pkts[sock]);
ready_packs[sock] = 0;
return recvlen;
}
/*
* int sock_send(int sock, struct sockaddr_in *addr, char far *msg, int len) --
* Transmits a message msg using sock to host at *addr of length len.
* Assumed to be a UDP socket. Returns the number of bytes sent, or -1
* if an error occurred.
*/
int sock_send(sock, addr, msg, len)
int sock;
struct sockaddr_in *addr;
char far *msg;
int len;
{
unsigned paclen = 1000;
PACKET p;
if (len < 1000) paclen = (unsigned) len;
/* printf("room %u: paclen %u: stack %u\n", _memavl(), paclen, stackavail()); */
if ((p = udp_alloc(paclen, 0))== NULL) return -1;
bcopy_fn(msg, udp_data(udp_head(in_head(p))), paclen);
if ( udp_send_to(addr->sin_addr.s_addr, addr->sin_port,
(unsigned) (laddr[sock]->sin_port), p, paclen) < 0) {
udp_free(p);
return -1;
}
udp_free(p);
return (int) paclen;
}
/*
* int sock_getsockaddr(int sock, struct sockaddr_in *addr) --]
* Returns socket address in *addr. Returns -1 if an error
* occurred.
*/
int sock_getsockaddr(sock, addr)
int sock;
struct sockaddr_in *addr;
{
*addr = *laddr[sock];
return;
}
/*
* long sock_gethostbyname(char *name) --
* Returns host IP address given host name. Returns -1 for error.
*/
long sock_gethostbyname(modename)
char *modename;
{
in_name fhost;
fhost = resolve_name(modename);
if(fhost == 0) {
printf("Couldn't resolve hostname %s.\n", modename);
return -1; }
if(fhost == NAMETMO) {
printf("name servers not responding.\n");
return -1;
}
return fhost;
}
/*
* char *sock_gethostbyaddr(struct sockaddr_in addr) --
* Returns a character pointer to the hostname
* Needs entry in hosts file
*/
char *sock_gethostbyaddr(addr)
struct sockaddr_in addr;
{
char *s;
FILE *fp;
s = (char *) malloc(40);
if ((fp = fopen("hosts", "r")) == NULL) return NULL;
while ( fgets(s, 40, fp) != NULL) {
if ( addr.sin_addr.s_addr == resolve_name(s)) {
fclose(fp);
return s;
}
}
fclose(fp);
s = "no_hosts_entry";
return s;
}