Files
dreamlayers.netbsd-mopd/common/pf-linux.c
Maciej W. Rozycki 2a42d24d4f Application of mopd-2.5.3-vax-linux.patch:
* Fri Oct 26 2001 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
- added a few more updates from the VAX/Linux version of
  mopd-linux; mostly security fixes (vax-linux)

Downloaded from:
ftp://ftp.linux-mips.org/pub/linux/mips/people/macro/mopd/mopd-2.5.3-vax-linux.patch.gz
.patch SHA256 = a76757c7dcd4befbcdbe9e3a386c2f2ede26c0394d4a56de1e1750e76e23f524
Patch history copied from:
ftp://ftp.linux-mips.org/pub/linux/mips/people/macro/mopd/mopd-2.5.3-15.spec
2020-10-31 23:51:52 -04:00

376 lines
6.0 KiB
C

/*
* General Purpose AppleTalk Packet Filter Interface
*
* Copyright (c) 1992-1995, The University of Melbourne.
* All Rights Reserved. Permission to redistribute or
* use any part of this software for any purpose must
* be obtained in writing from the copyright owner.
*
* This software is supplied "as is" without express
* or implied warranty.
*
* djh@munnari.OZ.AU
*
* Supports:
* Linux SOCK_PACKET
*
* $Author: djh $
* $Revision: 1.21 $
*
*
* Modified for use with the linux-mopd port by Karl Maftoum
* u963870@student.canberra.edu.au
*
*/
#ifdef __linux__
/*
* include header files
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <net/if.h>
#include <sys/errno.h>
#include <linux/if_ether.h>
#include <netdb.h>
#include <ctype.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include "mopdef.h"
/*
* map compatible functions
*
*/
#ifdef MAPFUNCS
#define bcopy(a,b,l) memcpy((char *)(b),(char *)(a),(l))
#define bcmp(a,b,l) memcmp((char *)(a),(char *)(b),(l))
#define bzero(a,l) memset((char *)(a),0,(l))
#define rindex(s,c) strrchr((char *)(s),(c))
#define index(s,c) strchr((char *)(s),(c))
#endif MAPFUNCS
/*
* select common modules
*
*/
#define USE_SADDMULTI
/*
* definitions
*
*/
#define READBUFSIZ 4096
#define NUMRDS 32
struct RDS {
u_short dataLen;
u_char *dataPtr;
};
/*
* variables
*
*/
struct socklist {
int iflen;
struct sockaddr sa;
} socklist[32];
struct ifreq ifr;
extern int errno;
extern int promisc;
struct RDS RDS[NUMRDS];
/*
* establish protocol filter
*
*/
int
setup_pf(s, prot, typ)
int s, typ;
u_short prot;
{
int ioarg;
u_short offset;
return(0);
}
/*
* Open and initialize packet filter
* for a particular protocol type.
*
*/
int
pfInit(interface, mode, protocol, typ)
char *interface;
u_short protocol;
int typ, mode;
{
int s;
int ioarg;
char device[64];
unsigned long if_flags;
{ u_short prot;
prot = ((typ == TRANS_8023) ? htons(ETH_P_802_2) : htons(protocol));
if ((s = socket(AF_INET, SOCK_PACKET, prot)) < 0) {
perror(interface);
return(-1);
}
if (s >= 32) {
close(s);
return(-1);
}
}
/*
* set filter for protocol and type (IPTalk, Phase 1/2)
*
*/
if (setup_pf(s, protocol, typ) < 0)
return(-1);
/*
* set options, bind to underlying interface
*
*/
strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
/* record socket interface name and length */
strncpy(socklist[s].sa.sa_data, interface, sizeof(socklist[s].sa.sa_data));
socklist[s].iflen = strlen(interface);
return(s);
}
/*
* get the interface ethernet address
*
*/
int
pfEthAddr(s, interface, addr)
int s;
char *interface;
u_char *addr;
{
strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name) - 1);
ifr.ifr_name[sizeof(ifr.ifr_name)] = 0;
ifr.ifr_addr.sa_family = AF_INET;
if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) {
perror("SIOCGIFHWADDR");
return(-1);
}
memcpy((char *)addr, ifr.ifr_hwaddr.sa_data, 6);
return(0);
}
/*
* add a multicast address to the interface
*
*/
int
pfAddMulti(s, interface, addr)
int s;
char *interface;
u_char *addr;
{
int sock;
#ifdef USE_SADDMULTI
strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name) - 1);
ifr.ifr_name[sizeof(ifr.ifr_name)] = 0;
#ifdef UPFILT
/* get the real interface name */
if (ioctl(s, EIOCIFNAME, &ifr) < 0) {
perror("EIOCIFNAME");
return(-1);
}
#endif UPFILT
ifr.ifr_addr.sa_family = AF_UNSPEC;
bcopy((char *)addr, ifr.ifr_addr.sa_data, 6);
/*
* open a socket, temporarily, to use for SIOC* ioctls
*
*/
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket()");
return(-1);
}
if (ioctl(sock, SIOCADDMULTI, (caddr_t)&ifr) < 0) {
perror("SIOCADDMULTI");
close(sock);
return(-1);
}
close(sock);
#endif USE_SADDMULTI
return(0);
}
/*
* delete a multicast address from the interface
*
*/
int
pfDelMulti(s, interface, addr)
int s;
char *interface;
u_char *addr;
{
int sock;
#ifdef USE_SADDMULTI
strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name) - 1);
ifr.ifr_name[sizeof(ifr.ifr_name)] = 0;
ifr.ifr_addr.sa_family = AF_UNSPEC;
bcopy((char *)addr, ifr.ifr_addr.sa_data, 6);
/*
* open a socket, temporarily, to use for SIOC* ioctls
*
*/
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket()");
return(-1);
}
if (ioctl(sock, SIOCDELMULTI, (caddr_t)&ifr) < 0) {
perror("SIOCDELMULTI");
close(sock);
return(-1);
}
close(sock);
#endif USE_SADDMULTI
return(0);
}
/*
* return 1 if ethernet interface capable of multiple opens
*
*/
int
eth_mopen(phase)
int phase;
{
if (phase == 2)
return(0);
return(1);
}
/*
* read a packet
* Read Data Structure describes packet(s) received
*
*/
int
pfRead(fd, buf, len)
int fd, len;
u_char *buf;
{
int i, cc;
int fromlen;
struct sockaddr sa;
RDS[0].dataLen = 0;
fromlen = sizeof(struct sockaddr);
if ((cc = recvfrom(fd, (char *)buf, len, 0, &sa, &fromlen)) <= 0)
return(cc);
/* check if from right interface */
for (i = socklist[fd].iflen-1; i >= 0; i--)
if (sa.sa_data[i] != socklist[fd].sa.sa_data[i])
return(0);
RDS[0].dataLen = cc;
RDS[0].dataPtr = buf;
RDS[1].dataLen = 0;
return(cc);
}
/*
* write a packet
*
*/
int
pfWrite(fd, buf, len)
int fd, len;
u_char *buf;
{
#ifdef USE_WRITEV
struct iovec iov[2];
iov[0].iov_base = (caddr_t)buf;
iov[0].iov_len = 14;
iov[1].iov_base = (caddr_t)buf+14;
iov[1].iov_len = len-14;
if (writev(fd, iov, 2) == len)
return(len);
#endif USE_WRITEV
if (sendto(fd, buf, len, 0, &socklist[fd].sa, sizeof(struct sockaddr)) == len)
return(len);
return(-1);
}
/*
* Return information to device.c how to open device.
* In this case the driver can handle both Ethernet type II and
* IEEE 802.3 frames (SNAP) in a single pfOpen.
*/
int
pfTrans(interface)
char *interface;
{
return TRANS_ETHER+TRANS_8023;
}
#endif /* __linux__ */