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