xref: /netbsd-src/usr.sbin/mopd/common/pf-linux2.c (revision c185136d00c42fa6e8d717ebe8ce10e0c08a293c)
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@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@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
pfInit(char * interface,int mode,u_short protocol,int typ)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
setup_pf(int s,int typ,u_short prot)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
pfEthAddr(int s,char * interface,u_char * addr)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
pfAddMulti(int s,char * interface,u_char * addr)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
pfDelMulti(int s,char * interface,u_char * addr)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
eth_mopen(int phase)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
pfRead(int fd,u_char * buf,int len)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
pfWrite(int fd,u_char * buf,int len)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
pfTrans(char * interface)302 pfTrans(char *interface)
303 {
304 	return TRANS_ETHER+TRANS_8023;
305 }
306