Home | History | Annotate | Line # | Download | only in common
      1 /*	$NetBSD: pf-linux2.c,v 1.2 2020/10/27 17:07:14 abs Exp $	*/
      2 
      3 /*
      4  * General Purpose AppleTalk Packet Filter Interface
      5  *
      6  * Copyright (c) 1992-1995, The University of Melbourne.
      7  * All Rights Reserved.  Permission to redistribute or
      8  * use any part of this software for any purpose must
      9  * be obtained in writing from the copyright owner.
     10  *
     11  * This software is supplied "as is" without express
     12  * or implied warranty.
     13  *
     14  * djh (at) munnari.OZ.AU
     15  *
     16  * Supports:
     17  *	Linux SOCK_PACKET
     18  *
     19  *
     20  * Modified for use with the linux-mopd port by Karl Maftoum
     21  * u963870 (at) student.canberra.edu.au
     22  *
     23  */
     24 
     25 #include "port.h"
     26 __RCSID("$NetBSD: pf-linux2.c,v 1.2 2020/10/27 17:07:14 abs Exp $");
     27 
     28 /*
     29  * include header files
     30  *
     31  */
     32 
     33 #include <stdio.h>
     34 #include <fcntl.h>
     35 #include <unistd.h>
     36 #include <sys/types.h>
     37 #include <sys/time.h>
     38 #include <sys/ioctl.h>
     39 #include <sys/file.h>
     40 #include <sys/socket.h>
     41 #include <net/if.h>
     42 #include <sys/errno.h>
     43 #include <linux/if_ether.h>
     44 #include <netdb.h>
     45 #include <ctype.h>
     46 #include <string.h>
     47 
     48 #define MOPDEF_SUPRESS_EXTERN
     49 #include "mopdef.h"
     50 
     51 /*
     52  * definitions
     53  *
     54  */
     55 
     56 #define	READBUFSIZ	4096
     57 #define	NUMRDS		32
     58 
     59 struct RDS {
     60   u_short dataLen;
     61   u_char *dataPtr;
     62 };
     63 
     64 /*
     65  * variables
     66  *
     67  */
     68 
     69 struct socklist {
     70   int iflen;
     71   struct sockaddr sa;
     72 } socklist[32];
     73 
     74 struct ifreq ifr;
     75 extern int errno;
     76 extern int promisc;
     77 
     78 struct RDS RDS[NUMRDS];
     79 static int setup_pf(int, int, u_short);
     80 
     81 /*
     82  * Open and initialize packet filter
     83  * for a particular protocol type.
     84  *
     85  */
     86 
     87 
     88 int
     89 pfInit(char *interface, int mode, u_short protocol, int typ)
     90 {
     91   int s;
     92   int ioarg;
     93   char device[64];
     94   unsigned long if_flags;
     95 
     96 
     97   { u_short prot;
     98 
     99     prot = ((typ == TRANS_8023) ? htons(ETH_P_802_2) : htons(protocol));
    100     if ((s = socket(AF_INET, SOCK_PACKET, prot)) < 0) {
    101       perror(interface);
    102       return(-1);
    103     }
    104     if (s >= 32) {
    105       close(s);
    106       return(-1);
    107     }
    108   }
    109 
    110   /*
    111    * set filter for protocol and type (IPTalk, Phase 1/2)
    112    *
    113    */
    114 
    115   if (setup_pf(s, protocol, typ) < 0)
    116     return(-1);
    117 
    118   /*
    119    * set options, bind to underlying interface
    120    *
    121    */
    122 
    123   strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
    124 
    125   /* record socket interface name and length */
    126   strncpy(socklist[s].sa.sa_data, interface, sizeof(socklist[s].sa.sa_data));
    127   socklist[s].iflen = strlen(interface);
    128 
    129   return(s);
    130 }
    131 
    132 /*
    133  * establish protocol filter
    134  *
    135  */
    136 
    137 static int
    138 setup_pf(int s, int typ, u_short prot)
    139 {
    140   int ioarg;
    141   u_short offset;
    142   return(0);
    143 }
    144 
    145 /*
    146  * get the interface ethernet address
    147  *
    148  */
    149 
    150 int
    151 pfEthAddr(int s, char *interface, u_char *addr)
    152 {
    153   strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name) -1);
    154   ifr.ifr_name[sizeof(ifr.ifr_name)] = 0;
    155   ifr.ifr_addr.sa_family = AF_INET;
    156   if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) {
    157     perror("SIOCGIFHWADDR");
    158     return(-1);
    159   }
    160   memcpy((char *)addr, ifr.ifr_hwaddr.sa_data, 6);
    161   return(0);
    162 }
    163 
    164 /*
    165  * add a multicast address to the interface
    166  *
    167  */
    168 
    169 int
    170 pfAddMulti(int s, char *interface, u_char *addr)
    171 {
    172   int sock;
    173 
    174   strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name) - 1);
    175   ifr.ifr_name[sizeof(ifr.ifr_name)] = 0;
    176 
    177   ifr.ifr_addr.sa_family = AF_UNSPEC;
    178   bcopy((char *)addr, ifr.ifr_addr.sa_data, 6);
    179 
    180   /*
    181    * open a socket, temporarily, to use for SIOC* ioctls
    182    *
    183    */
    184   if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    185     perror("socket()");
    186     return(-1);
    187   }
    188   if (ioctl(sock, SIOCADDMULTI, (caddr_t)&ifr) < 0) {
    189     perror("SIOCADDMULTI");
    190     close(sock);
    191     return(-1);
    192   }
    193   close(sock);
    194 
    195   return(0);
    196 }
    197 
    198 /*
    199  * delete a multicast address from the interface
    200  *
    201  */
    202 
    203 int
    204 pfDelMulti(int s, char *interface, u_char *addr)
    205 {
    206   int sock;
    207 
    208   strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name) - 1);
    209   ifr.ifr_name[sizeof(ifr.ifr_name)] = 0;
    210 
    211   ifr.ifr_addr.sa_family = AF_UNSPEC;
    212   bcopy((char *)addr, ifr.ifr_addr.sa_data, 6);
    213 
    214   /*
    215    * open a socket, temporarily, to use for SIOC* ioctls
    216    *
    217    */
    218   if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    219     perror("socket()");
    220     return(-1);
    221   }
    222   if (ioctl(sock, SIOCDELMULTI, (caddr_t)&ifr) < 0) {
    223     perror("SIOCDELMULTI");
    224     close(sock);
    225     return(-1);
    226   }
    227   close(sock);
    228 
    229   return(0);
    230 }
    231 
    232 /*
    233  * return 1 if ethernet interface capable of multiple opens
    234  *
    235  */
    236 
    237 int
    238 eth_mopen(int phase)
    239 {
    240   if (phase == 2)
    241     return(0);
    242   return(1);
    243 }
    244 
    245 /*
    246  * read a packet
    247  * Read Data Structure describes packet(s) received
    248  *
    249  */
    250 
    251 
    252 
    253 
    254 int
    255 pfRead(int fd, u_char *buf, int len)
    256 {
    257   int i, cc;
    258 
    259   int fromlen;
    260   struct sockaddr sa;
    261 
    262   RDS[0].dataLen = 0;
    263   fromlen = sizeof(struct sockaddr);
    264 
    265   if ((cc = recvfrom(fd, (char *)buf, len, 0, &sa, &fromlen)) <= 0)
    266     return(cc);
    267 
    268   /* check if from right interface */
    269   for (i = socklist[fd].iflen-1; i >= 0; i--)
    270     if (sa.sa_data[i] != socklist[fd].sa.sa_data[i])
    271       return(0);
    272 
    273   RDS[0].dataLen = cc;
    274   RDS[0].dataPtr = buf;
    275   RDS[1].dataLen = 0;
    276 
    277   return(cc);
    278 }
    279 
    280 /*
    281  * write a packet
    282  *
    283  */
    284 
    285 int
    286 pfWrite(int fd, u_char *buf, int len)
    287 {
    288 
    289   if (sendto(fd, buf, len, 0, &socklist[fd].sa, sizeof(struct sockaddr)) == len)
    290     return(len);
    291 
    292   return(-1);
    293 }
    294 
    295 /*
    296  * Return information to device.c how to open device.
    297  * In this case the driver can handle both Ethernet type II and
    298  * IEEE 802.3 frames (SNAP) in a single pfOpen.
    299  */
    300 
    301 int
    302 pfTrans(char *interface)
    303 {
    304 	return TRANS_ETHER+TRANS_8023;
    305 }
    306