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