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