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