/* $NetBSD: pf-linux2.c,v 1.1 2016/06/08 01:11:49 christos Exp $ */ /* * 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 * * * Modified for use with the linux-mopd port by Karl Maftoum * u963870@student.canberra.edu.au * */ #include "port.h" __RCSID("$NetBSD: pf-linux2.c,v 1.1 2016/06/08 01:11:49 christos Exp $"); /* * include header files * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MOPDEF_SUPRESS_EXTERN #include "mopdef.h" /* * 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]; static int setup_pf(int, int, u_short); /* * Open and initialize packet filter * for a particular protocol type. * */ int pfInit(char *interface, u_short protocol, int typ, int 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); } /* * establish protocol filter * */ static int setup_pf(int s, int typ, u_short prot) { int ioarg; u_short offset; return(0); } /* * get the interface ethernet address * */ int pfEthAddr(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(int s, char *interface, u_char *addr) { int sock; 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, SIOCADDMULTI, (caddr_t)&ifr) < 0) { perror("SIOCADDMULTI"); close(sock); return(-1); } close(sock); return(0); } /* * delete a multicast address from the interface * */ int pfDelMulti(int s, char *interface, u_char *addr) { int sock; 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); return(0); } /* * return 1 if ethernet interface capable of multiple opens * */ int eth_mopen(int phase) { if (phase == 2) return(0); return(1); } /* * read a packet * Read Data Structure describes packet(s) received * */ int pfRead(int fd, u_char *buf, int len) { 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(int fd, u_char *buf, int len) { 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(char *interface) { return TRANS_ETHER+TRANS_8023; }