mirror of
https://github.com/mabam/CAP.git
synced 2024-11-01 01:05:24 +00:00
316 lines
6.7 KiB
C
316 lines
6.7 KiB
C
static char rcsid[] = "$Author: djh $ $Date: 91/02/15 23:06:01 $";
|
|
static char rcsident[] = "$Header: dlip.c,v 2.1 91/02/15 23:06:01 djh Rel $";
|
|
static char revision[] = "$Revision: 2.1 $";
|
|
|
|
/*
|
|
* dlip.c - Simple "protocol" level interface to DLI
|
|
*
|
|
* Provides ability to read/write packets at ethernet level
|
|
*
|
|
* Copyright (c) 1988 by The Trustees of Columbia University
|
|
* in the City of New York.
|
|
*
|
|
* Permission is granted to any individual or institution to use,
|
|
* copy, or redistribute this software so long as it is not sold for
|
|
* profit, provided that this notice and the original copyright
|
|
* notices are retained. Columbia University nor the author make no
|
|
* representations about the suitability of this software for any
|
|
* purpose. It is provided "as is" without express or implied
|
|
* warranty.
|
|
*
|
|
*
|
|
* Edit History:
|
|
*
|
|
* April 3, 1988 CCKim Created
|
|
*
|
|
*/
|
|
|
|
static char columbia_copyright[] = "Copyright (c) 1988 by The Trustees of \
|
|
Columbia University in the City of New York";
|
|
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/uio.h>
|
|
|
|
#include <net/if.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/if_ether.h>
|
|
#include <netdnet/dli_var.h>
|
|
|
|
#include <netat/appletalk.h>
|
|
#include "../uab/proto_intf.h"
|
|
|
|
typedef struct ephandle { /* ethernet protocol driver handle */
|
|
int inuse; /* true if inuse */
|
|
int fd; /* file descriptor of socket */
|
|
int protocol; /* ethernet protocol */
|
|
int socket; /* ddp socket */
|
|
struct sockaddr_dl sdli; /* dli interface: to send with */
|
|
struct sockaddr_dl rdli; /* dli interface: to receive with */
|
|
} EPHANDLE;
|
|
|
|
private inited = FALSE;
|
|
|
|
private EPHANDLE ephlist[MAXOPENPROT];
|
|
|
|
extern char interface[50];
|
|
|
|
/*
|
|
* setup for particular device devno
|
|
* all pi_open's will go this device
|
|
*
|
|
*/
|
|
export
|
|
pi_setup()
|
|
{
|
|
int i;
|
|
|
|
if (!inited) {
|
|
for (i = 0 ; i < MAXOPENPROT; i++)
|
|
ephlist[i].inuse = FALSE;
|
|
(void)init_fdlistening();
|
|
inited = TRUE; /* don't forget now */
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Open up a protocol handle:
|
|
* user level data:
|
|
* file descriptor
|
|
* protocol
|
|
*
|
|
* returns -1 and ephandle == NULL if memory allocation problems
|
|
* returns -1 for other errors
|
|
* return 0 for okay
|
|
*/
|
|
export int
|
|
pi_open(protocol, sock, dev, devno)
|
|
int protocol;
|
|
int sock;
|
|
char *dev;
|
|
int devno;
|
|
{
|
|
struct ephandle *eph;
|
|
struct sockaddr_dl *dl;
|
|
int s, i;
|
|
|
|
for (i = 0; i < MAXOPENPROT; i++) {
|
|
if (!ephlist[i].inuse)
|
|
break;
|
|
}
|
|
if (i == MAXOPENPROT)
|
|
return(0); /* nothing */
|
|
eph = &ephlist[i]; /* find handle */
|
|
|
|
dl = &eph->sdli; /* point */
|
|
dl->dli_family = AF_DLI;
|
|
strcpy(dl->dli_device.dli_devname, dev);
|
|
dl->dli_device.dli_devnumber = devno;
|
|
dl->dli_substructype = DLI_ETHERNET;
|
|
/* update these */
|
|
dl->choose_addr.dli_eaddr.dli_ioctlflg = DLI_EXCLUSIVE;
|
|
dl->choose_addr.dli_eaddr.dli_protype = protocol;
|
|
|
|
if ((s = socket(AF_DLI, SOCK_DGRAM, DLPROTO_DLI)) < 0)
|
|
return(-1);
|
|
if (bind(s, dl, sizeof(struct sockaddr_dl)) < 0) {
|
|
close(s);
|
|
return(-1);
|
|
}
|
|
bcopy(dl, &eph->rdli, sizeof(struct sockaddr_dl));
|
|
|
|
eph->inuse = TRUE;
|
|
eph->fd = s;
|
|
eph->protocol = protocol;
|
|
eph->socket = sock;
|
|
return(i+1); /* skip zero */
|
|
}
|
|
|
|
/* returns TRUE if machine will see own broadcasts */
|
|
export int
|
|
pi_delivers_self_broadcasts()
|
|
{
|
|
return(TRUE);
|
|
}
|
|
|
|
export int
|
|
pi_close(edx)
|
|
int edx;
|
|
{
|
|
if (edx < 1 || edx > MAXOPENPROT || !ephlist[edx-1].inuse)
|
|
return(-1);
|
|
fdunlisten(ephlist[edx-1].fd); /* toss listener */
|
|
close(ephlist[edx-1].fd);
|
|
ephlist[edx-1].inuse = 0;
|
|
return(0);
|
|
}
|
|
|
|
export int
|
|
pi_get_ethernet_address(edx,ea)
|
|
int edx;
|
|
u_char *ea;
|
|
{
|
|
struct ifdevea buf;
|
|
struct ephandle *eph;
|
|
|
|
if (edx < 1 || edx > MAXOPENPROT || !ephlist[edx-1].inuse)
|
|
return(-1);
|
|
|
|
eph = &ephlist[edx-1]; /* find handle */
|
|
sprintf(buf.ifr_name, "%s%d",eph->sdli.dli_device.dli_devname,
|
|
eph->sdli.dli_device.dli_devnumber);
|
|
if (ioctl(eph->fd,SIOCRPHYSADDR, &buf) < 0) {
|
|
perror("iotcl");
|
|
return(-1);
|
|
}
|
|
bcopy(buf.current_pa, ea, DLI_EADDRSIZE);
|
|
return(0);
|
|
}
|
|
|
|
export
|
|
pi_listener(edx, listener, arg)
|
|
int edx;
|
|
int (*listener)();
|
|
caddr_t arg;
|
|
{
|
|
if (edx < 1 || edx > MAXOPENPROT || !ephlist[edx-1].inuse)
|
|
return(-1);
|
|
|
|
fdlistener(ephlist[edx-1].fd, listener, arg, edx);
|
|
return(0);
|
|
}
|
|
|
|
export
|
|
pi_listener_2(edx, listener, arg1, arg2)
|
|
int edx;
|
|
int (*listener)();
|
|
caddr_t arg1;
|
|
int arg2;
|
|
{
|
|
if (edx < 1 || edx > MAXOPENPROT || !ephlist[edx-1].inuse)
|
|
return(-1);
|
|
|
|
fdlistener(ephlist[edx-1].fd, listener, arg1, arg2);
|
|
}
|
|
|
|
|
|
export int
|
|
pi_readv(edx, iov, iovlen)
|
|
int edx;
|
|
struct iovec *iov;
|
|
int iovlen;
|
|
{
|
|
struct msghdr msg;
|
|
int cc;
|
|
struct ephandle *eph ;
|
|
struct ethernet_addresses *ea;
|
|
|
|
if (edx < 1 || edx > MAXOPENPROT)
|
|
return(-1);
|
|
eph = &ephlist[edx-1];
|
|
if (!eph->inuse)
|
|
return(-1);
|
|
|
|
msg.msg_iov = iov+1;
|
|
msg.msg_iovlen = iovlen-1;
|
|
msg.msg_name = (caddr_t)&eph->rdli;
|
|
msg.msg_namelen = sizeof(eph->rdli);
|
|
msg.msg_accrights = 0;
|
|
msg.msg_accrightslen = 0;
|
|
if ((cc = recvmsg(eph->fd, &msg, 0)) < 0) {
|
|
perror("recvmsg");
|
|
return(cc);
|
|
}
|
|
ea = (struct ethernet_addresses *)iov[0].iov_base;
|
|
ea->etype = eph->protocol;
|
|
/* check length -- naw */
|
|
bcopy(eph->rdli.choose_addr.dli_eaddr.dli_target, ea->saddr, EHRD);
|
|
bcopy(eph->rdli.choose_addr.dli_eaddr.dli_dest, ea->daddr, EHRD);
|
|
return(cc+iov[0].iov_len);
|
|
}
|
|
|
|
export int
|
|
pi_read(edx, buf, bufsiz)
|
|
int edx;
|
|
caddr_t buf;
|
|
int bufsiz;
|
|
{
|
|
struct iovec iov[2];
|
|
struct ethernet_addresses ea;
|
|
int cc;
|
|
|
|
iov[0].iov_base = (caddr_t)&ea;
|
|
iov[0].iov_len = sizeof(ea);
|
|
iov[1].iov_base = (caddr_t)buf;
|
|
iov[1].iov_len = bufsiz;
|
|
cc = pi_readv(edx, iov, 2);
|
|
return(cc - sizeof(ea));
|
|
}
|
|
|
|
export int
|
|
pi_reada(fd, buf, bufsiz, eaddr)
|
|
int fd;
|
|
caddr_t buf;
|
|
int bufsiz;
|
|
char *eaddr;
|
|
{
|
|
struct iovec iov[2];
|
|
int cc;
|
|
|
|
iov[0].iov_base = (caddr_t)eaddr;
|
|
iov[0].iov_len = 14;
|
|
iov[1].iov_base = (caddr_t)buf;
|
|
iov[1].iov_len = bufsiz;
|
|
|
|
if ((cc = readv(fd, iov, 2)) < 0) {
|
|
perror("abread");
|
|
return(cc);
|
|
}
|
|
return(cc - 14);
|
|
}
|
|
|
|
export int
|
|
pi_write(edx, buf, buflen, eaddr)
|
|
int edx;
|
|
caddr_t buf;
|
|
int buflen;
|
|
char *eaddr;
|
|
{
|
|
struct iovec iov[1];
|
|
|
|
iov[0].iov_base = buf;
|
|
iov[0].iov_len = buflen;
|
|
return(pi_writev(edx, iov, 1, eaddr));
|
|
}
|
|
|
|
export int
|
|
pi_writev(edx, iov, iovlen, eaddr)
|
|
int edx;
|
|
struct iovec *iov;
|
|
int iovlen;
|
|
char *eaddr;
|
|
{
|
|
struct ephandle *eph;
|
|
struct msghdr msg;
|
|
int cc;
|
|
|
|
if (edx < 1 || edx > MAXOPENPROT || eaddr == NULL)
|
|
return(-1);
|
|
eph = &ephlist[edx-1];
|
|
if (!eph->inuse)
|
|
return(-1);
|
|
|
|
bcopy(eaddr, eph->sdli.choose_addr.dli_eaddr.dli_target, DLI_EADDRSIZE);
|
|
msg.msg_name = (caddr_t)&eph->sdli;
|
|
msg.msg_namelen = sizeof(eph->sdli);
|
|
msg.msg_accrights = 0;
|
|
msg.msg_accrightslen = 0;
|
|
msg.msg_iov = iov;
|
|
msg.msg_iovlen = iovlen;
|
|
cc = sendmsg(eph->fd, &msg, 0);
|
|
return(cc);
|
|
}
|