Mercurial > illumos > onarm
annotate usr/src/cmd/ipf/tools/ip_fil.c @ 4:1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Mon, 31 Aug 2009 14:38:03 +0900 |
parents | c9caec207d52 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 * Copyright (C) 1993-2001, 2003 by Darren Reed. | |
3 * | |
4 * See the IPFILTER.LICENCE file for details on licencing. | |
5 * | |
6 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. | |
7 * Use is subject to license terms. | |
8 */ | |
9 | |
4
1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
Koji Uno <koji.uno@sun.com>
parents:
0
diff
changeset
|
10 #pragma ident "%Z%%M% %I% %E% SMI" |
0 | 11 |
12 #if !defined(lint) | |
13 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; | |
14 static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.133.2.9 2005/01/08 14:22:18 darrenr Exp $"; | |
15 #endif | |
16 | |
17 #ifndef SOLARIS | |
18 #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) | |
19 #endif | |
20 | |
21 #include <sys/param.h> | |
22 #if defined(__FreeBSD__) && !defined(__FreeBSD_version) | |
23 # if defined(IPFILTER_LKM) | |
24 # ifndef __FreeBSD_cc_version | |
25 # include <osreldate.h> | |
26 # else | |
27 # if __FreeBSD_cc_version < 430000 | |
28 # include <osreldate.h> | |
29 # endif | |
30 # endif | |
31 # endif | |
32 #endif | |
33 #include <sys/errno.h> | |
34 #if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL) | |
35 # include <sys/kern_svcs.h> | |
36 #endif | |
37 #include <sys/types.h> | |
38 #define _KERNEL | |
39 #define KERNEL | |
40 #ifdef __OpenBSD__ | |
41 struct file; | |
42 #endif | |
43 #include <sys/uio.h> | |
44 #undef _KERNEL | |
45 #undef KERNEL | |
46 #include <sys/file.h> | |
47 #include <sys/ioctl.h> | |
48 #ifdef __sgi | |
49 # include <sys/ptimers.h> | |
50 #endif | |
51 #include <sys/time.h> | |
52 #if !SOLARIS | |
53 # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) | |
54 # include <sys/dirent.h> | |
55 # else | |
56 # include <sys/dir.h> | |
57 # endif | |
58 #else | |
59 # include <sys/filio.h> | |
60 #endif | |
61 #ifndef linux | |
62 # include <sys/protosw.h> | |
63 #endif | |
64 #include <sys/socket.h> | |
65 | |
66 #include <stdio.h> | |
67 #include <string.h> | |
68 #include <stdlib.h> | |
69 #include <ctype.h> | |
70 #include <fcntl.h> | |
71 #include <sys/zone.h> | |
72 #include <arpa/inet.h> | |
73 | |
74 #ifdef __hpux | |
75 # define _NET_ROUTE_INCLUDED | |
76 #endif | |
77 #include <net/if.h> | |
78 #ifdef sun | |
79 # include <net/af.h> | |
80 #endif | |
81 #if __FreeBSD_version >= 300000 | |
82 # include <net/if_var.h> | |
83 #endif | |
84 #ifdef __sgi | |
85 #include <sys/debug.h> | |
86 # ifdef IFF_DRVRLOCK /* IRIX6 */ | |
87 #include <sys/hashing.h> | |
88 # endif | |
89 #endif | |
90 #if defined(__FreeBSD__) | |
91 # include "radix_ipf.h" | |
92 #endif | |
93 #include <net/route.h> | |
94 #include <netinet/in.h> | |
95 #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \ | |
96 !defined(__hpux) && !defined(linux) | |
97 # include <netinet/in_var.h> | |
98 #endif | |
99 #include <netinet/in_systm.h> | |
100 #include <netinet/ip.h> | |
101 #if !defined(linux) | |
102 # include <netinet/ip_var.h> | |
103 #endif | |
104 #include <netinet/tcp.h> | |
105 #if defined(__osf__) | |
106 # include <netinet/tcp_timer.h> | |
107 #endif | |
108 #if defined(__osf__) || defined(__hpux) || defined(__sgi) | |
109 # include "radix_ipf_local.h" | |
110 # define _RADIX_H_ | |
111 #endif | |
112 #include <netinet/udp.h> | |
113 #include <netinet/tcpip.h> | |
114 #include <netinet/ip_icmp.h> | |
115 #include <unistd.h> | |
116 #include <syslog.h> | |
117 #ifdef __hpux | |
118 # undef _NET_ROUTE_INCLUDED | |
119 #endif | |
120 #include "netinet/ip_compat.h" | |
121 #include "netinet/ip_fil.h" | |
122 #include "netinet/ip_nat.h" | |
123 #include "netinet/ip_frag.h" | |
124 #include "netinet/ip_state.h" | |
125 #include "netinet/ip_proxy.h" | |
126 #include "netinet/ip_auth.h" | |
127 #ifdef IPFILTER_SYNC | |
128 #include "netinet/ip_sync.h" | |
129 #endif | |
130 #ifdef IPFILTER_SCAN | |
131 #include "netinet/ip_scan.h" | |
132 #endif | |
133 #include "netinet/ip_pool.h" | |
134 #ifdef IPFILTER_COMPILED | |
135 # include "netinet/ip_rules.h" | |
136 #endif | |
137 #include "netinet/ipf_stack.h" | |
138 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) | |
139 # include <sys/malloc.h> | |
140 #endif | |
141 #ifdef __hpux | |
142 struct rtentry; | |
143 #endif | |
144 #include "md5.h" | |
145 | |
146 | |
147 #if !defined(__osf__) | |
148 extern struct protosw inetsw[]; | |
149 #endif | |
150 | |
151 #include "ipt.h" | |
152 static struct ifnet **ifneta = NULL; | |
153 static int nifs = 0; | |
154 | |
155 static int frzerostats __P((caddr_t, ipf_stack_t *ifs)); | |
156 static void fr_setifpaddr __P((struct ifnet *, char *)); | |
157 void init_ifp __P((void)); | |
158 #if defined(__sgi) && (IRIX < 60500) | |
159 static int no_output __P((struct ifnet *, struct mbuf *, | |
160 struct sockaddr *)); | |
161 static int write_output __P((struct ifnet *, struct mbuf *, | |
162 struct sockaddr *)); | |
163 #else | |
164 # if TRU64 >= 1885 | |
165 static int no_output __P((struct ifnet *, struct mbuf *, | |
166 struct sockaddr *, struct rtentry *, char *)); | |
167 static int write_output __P((struct ifnet *, struct mbuf *, | |
168 struct sockaddr *, struct rtentry *, char *)); | |
169 # else | |
170 static int no_output __P((struct ifnet *, struct mbuf *, | |
171 struct sockaddr *, struct rtentry *)); | |
172 static int write_output __P((struct ifnet *, struct mbuf *, | |
173 struct sockaddr *, struct rtentry *)); | |
174 # endif | |
175 #endif | |
176 | |
177 | |
178 int iplattach(ifs, ns) | |
179 ipf_stack_t *ifs; | |
180 netstack_t *ns; | |
181 { | |
182 ifs->ifs_fr_running = 1; | |
183 return 0; | |
184 } | |
185 | |
186 | |
187 int ipldetach(ifs) | |
188 ipf_stack_t *ifs; | |
189 { | |
190 ifs->ifs_fr_running = -1; | |
191 return 0; | |
192 } | |
193 | |
194 | |
195 static int frzerostats(data, ifs) | |
196 caddr_t data; | |
197 ipf_stack_t *ifs; | |
198 { | |
199 friostat_t fio; | |
200 int error; | |
201 | |
202 fr_getstat(&fio, ifs); | |
203 error = copyoutptr(&fio, data, sizeof(fio)); | |
204 if (error) | |
205 return EFAULT; | |
206 | |
207 bzero((char *)ifs->ifs_frstats, sizeof(*ifs->ifs_frstats) * 2); | |
208 | |
209 return 0; | |
210 } | |
211 | |
212 | |
213 /* | |
214 * Filter ioctl interface. | |
215 */ | |
216 int iplioctl(dev, cmd, data, mode) | |
217 int dev; | |
218 ioctlcmd_t cmd; | |
219 caddr_t data; | |
220 int mode; | |
221 { | |
222 int error = 0, unit = 0, tmp, uid; | |
223 friostat_t fio; | |
224 ipf_stack_t *ifs; | |
225 extern ipf_stack_t *get_ifs(); | |
226 | |
227 unit = dev; | |
228 uid = getuid(); | |
229 | |
230 ifs = get_ifs(); | |
231 | |
232 SPL_NET(s); | |
233 | |
234 if (unit == IPL_LOGNAT) { | |
235 if (ifs->ifs_fr_running > 0) | |
236 error = fr_nat_ioctl(data, cmd, mode, uid, NULL, ifs); | |
237 else | |
238 error = EIO; | |
239 SPL_X(s); | |
240 return error; | |
241 } | |
242 if (unit == IPL_LOGSTATE) { | |
243 if (ifs->ifs_fr_running > 0) | |
244 error = fr_state_ioctl(data, cmd, mode, uid, NULL, ifs); | |
245 else | |
246 error = EIO; | |
247 SPL_X(s); | |
248 return error; | |
249 } | |
250 if (unit == IPL_LOGAUTH) { | |
251 if (ifs->ifs_fr_running > 0) { | |
252 if ((cmd == (ioctlcmd_t)SIOCADAFR) || | |
253 (cmd == (ioctlcmd_t)SIOCRMAFR)) { | |
254 if (!(mode & FWRITE)) { | |
255 error = EPERM; | |
256 } else { | |
257 error = frrequest(unit, cmd, data, | |
258 ifs->ifs_fr_active, 1, ifs); | |
259 } | |
260 } else { | |
261 error = fr_auth_ioctl(data, mode, cmd, uid, NULL, ifs); | |
262 } | |
263 } else | |
264 error = EIO; | |
265 SPL_X(s); | |
266 return error; | |
267 } | |
268 if (unit == IPL_LOGSYNC) { | |
269 #ifdef IPFILTER_SYNC | |
270 if (ifs->ifs_fr_running > 0) | |
271 error = fr_sync_ioctl(data, cmd, mode); | |
272 else | |
273 #endif | |
274 error = EIO; | |
275 SPL_X(s); | |
276 return error; | |
277 } | |
278 if (unit == IPL_LOGSCAN) { | |
279 #ifdef IPFILTER_SCAN | |
280 if (ifs->ifs_fr_running > 0) | |
281 error = fr_scan_ioctl(data, cmd, mode); | |
282 else | |
283 #endif | |
284 error = EIO; | |
285 SPL_X(s); | |
286 return error; | |
287 } | |
288 if (unit == IPL_LOGLOOKUP) { | |
289 if (ifs->ifs_fr_running > 0) | |
290 error = ip_lookup_ioctl(data, cmd, mode, uid, | |
291 NULL, ifs); | |
292 else | |
293 error = EIO; | |
294 SPL_X(s); | |
295 return error; | |
296 } | |
297 | |
298 switch (cmd) | |
299 { | |
300 case FIONREAD : | |
301 #ifdef IPFILTER_LOG | |
302 error = COPYOUT(&ifs->ifs_iplused[IPL_LOGIPF], (caddr_t)data, | |
303 sizeof(ifs->ifs_iplused[IPL_LOGIPF])); | |
304 #endif | |
305 break; | |
306 case SIOCFRENB : | |
307 if (!(mode & FWRITE)) | |
308 error = EPERM; | |
309 else { | |
310 error = COPYIN(data, &tmp, sizeof(tmp)); | |
311 if (error) | |
312 break; | |
313 if (tmp) | |
314 error = iplattach(ifs, NULL); | |
315 else | |
316 error = ipldetach(ifs); | |
317 } | |
318 break; | |
319 case SIOCIPFSET : | |
320 if (!(mode & FWRITE)) { | |
321 error = EPERM; | |
322 break; | |
323 } | |
324 case SIOCIPFGETNEXT : | |
325 case SIOCIPFGET : | |
326 error = fr_ipftune(cmd, (void *)data, ifs); | |
327 break; | |
328 case SIOCSETFF : | |
329 if (!(mode & FWRITE)) | |
330 error = EPERM; | |
331 else | |
332 error = COPYIN(data, &ifs->ifs_fr_flags, | |
333 sizeof(ifs->ifs_fr_flags)); | |
334 break; | |
335 case SIOCGETFF : | |
336 error = COPYOUT(&ifs->ifs_fr_flags, data, | |
337 sizeof(ifs->ifs_fr_flags)); | |
338 break; | |
339 case SIOCFUNCL : | |
340 error = fr_resolvefunc(data); | |
341 break; | |
342 case SIOCINAFR : | |
343 case SIOCRMAFR : | |
344 case SIOCADAFR : | |
345 case SIOCZRLST : | |
346 if (!(mode & FWRITE)) | |
347 error = EPERM; | |
348 else | |
349 error = frrequest(unit, cmd, data, | |
350 ifs->ifs_fr_active, 1, ifs); | |
351 break; | |
352 case SIOCINIFR : | |
353 case SIOCRMIFR : | |
354 case SIOCADIFR : | |
355 if (!(mode & FWRITE)) | |
356 error = EPERM; | |
357 else | |
358 error = frrequest(unit, cmd, data, | |
359 1 - ifs->ifs_fr_active, 1, ifs); | |
360 break; | |
361 case SIOCSWAPA : | |
362 if (!(mode & FWRITE)) | |
363 error = EPERM; | |
364 else { | |
365 bzero((char *)ifs->ifs_frcache, | |
366 sizeof(ifs->ifs_frcache[0]) * 2); | |
367 *(u_int *)data = ifs->ifs_fr_active; | |
368 ifs->ifs_fr_active = 1 - ifs->ifs_fr_active; | |
369 } | |
370 break; | |
371 case SIOCGETFS : | |
372 fr_getstat(&fio, ifs); | |
373 error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT); | |
374 break; | |
375 case SIOCFRZST : | |
376 if (!(mode & FWRITE)) | |
377 error = EPERM; | |
378 else | |
379 error = frzerostats(data, ifs); | |
380 break; | |
381 case SIOCIPFFL : | |
382 if (!(mode & FWRITE)) | |
383 error = EPERM; | |
384 else { | |
385 error = COPYIN(data, &tmp, sizeof(tmp)); | |
386 if (!error) { | |
387 tmp = frflush(unit, 4, tmp, ifs); | |
388 error = COPYOUT(&tmp, data, sizeof(tmp)); | |
389 } | |
390 } | |
391 break; | |
392 #ifdef USE_INET6 | |
393 case SIOCIPFL6 : | |
394 if (!(mode & FWRITE)) | |
395 error = EPERM; | |
396 else { | |
397 error = COPYIN(data, &tmp, sizeof(tmp)); | |
398 if (!error) { | |
399 tmp = frflush(unit, 6, tmp, ifs); | |
400 error = COPYOUT(&tmp, data, sizeof(tmp)); | |
401 } | |
402 } | |
403 break; | |
404 #endif | |
405 case SIOCSTLCK : | |
406 error = COPYIN(data, &tmp, sizeof(tmp)); | |
407 if (error == 0) { | |
408 ifs->ifs_fr_state_lock = tmp; | |
409 ifs->ifs_fr_nat_lock = tmp; | |
410 ifs->ifs_fr_frag_lock = tmp; | |
411 ifs->ifs_fr_auth_lock = tmp; | |
412 } else | |
413 error = EFAULT; | |
414 break; | |
415 #ifdef IPFILTER_LOG | |
416 case SIOCIPFFB : | |
417 if (!(mode & FWRITE)) | |
418 error = EPERM; | |
419 else | |
420 *(int *)data = ipflog_clear(unit, ifs); | |
421 break; | |
422 #endif /* IPFILTER_LOG */ | |
423 case SIOCGFRST : | |
424 error = fr_outobj(data, fr_fragstats(ifs), IPFOBJ_FRAGSTAT); | |
425 break; | |
426 case SIOCFRSYN : | |
427 if (!(mode & FWRITE)) | |
428 error = EPERM; | |
429 else { | |
430 frsync(IPFSYNC_RESYNC, IPFSYNC_RESYNC, NULL, NULL, ifs); | |
431 } | |
432 break; | |
433 default : | |
434 error = EINVAL; | |
435 break; | |
436 } | |
437 SPL_X(s); | |
438 return error; | |
439 } | |
440 | |
441 | |
442 void fr_forgetifp(ifp, ifs) | |
443 void *ifp; | |
444 ipf_stack_t *ifs; | |
445 { | |
446 register frentry_t *f; | |
447 | |
448 WRITE_ENTER(&ifs->ifs_ipf_mutex); | |
449 for (f = ifs->ifs_ipacct[0][ifs->ifs_fr_active]; (f != NULL); | |
450 f = f->fr_next) | |
451 if (f->fr_ifa == ifp) | |
452 f->fr_ifa = (void *)-1; | |
453 for (f = ifs->ifs_ipacct[1][ifs->ifs_fr_active]; (f != NULL); | |
454 f = f->fr_next) | |
455 if (f->fr_ifa == ifp) | |
456 f->fr_ifa = (void *)-1; | |
457 for (f = ifs->ifs_ipfilter[0][ifs->ifs_fr_active]; (f != NULL); | |
458 f = f->fr_next) | |
459 if (f->fr_ifa == ifp) | |
460 f->fr_ifa = (void *)-1; | |
461 for (f = ifs->ifs_ipfilter[1][ifs->ifs_fr_active]; (f != NULL); | |
462 f = f->fr_next) | |
463 if (f->fr_ifa == ifp) | |
464 f->fr_ifa = (void *)-1; | |
465 #ifdef USE_INET6 | |
466 for (f = ifs->ifs_ipacct6[0][ifs->ifs_fr_active]; (f != NULL); | |
467 f = f->fr_next) | |
468 if (f->fr_ifa == ifp) | |
469 f->fr_ifa = (void *)-1; | |
470 for (f = ifs->ifs_ipacct6[1][ifs->ifs_fr_active]; (f != NULL); | |
471 f = f->fr_next) | |
472 if (f->fr_ifa == ifp) | |
473 f->fr_ifa = (void *)-1; | |
474 for (f = ifs->ifs_ipfilter6[0][ifs->ifs_fr_active]; (f != NULL); | |
475 f = f->fr_next) | |
476 if (f->fr_ifa == ifp) | |
477 f->fr_ifa = (void *)-1; | |
478 for (f = ifs->ifs_ipfilter6[1][ifs->ifs_fr_active]; (f != NULL); | |
479 f = f->fr_next) | |
480 if (f->fr_ifa == ifp) | |
481 f->fr_ifa = (void *)-1; | |
482 #endif | |
483 RWLOCK_EXIT(&ifs->ifs_ipf_mutex); | |
484 fr_natifpsync(IPFSYNC_OLDIFP, ifp, NULL, ifs); | |
485 } | |
486 | |
487 | |
488 void fr_resolvedest(fdp, v, ifs) | |
489 frdest_t *fdp; | |
490 int v; | |
491 ipf_stack_t *ifs; | |
492 { | |
493 fdp->fd_ifp = NULL; | |
494 | |
495 if (*fdp->fd_ifname) { | |
496 fdp->fd_ifp = GETIFP(fdp->fd_ifname, v, ifs); | |
497 if (!fdp->fd_ifp) | |
498 fdp->fd_ifp = (struct ifnet *)-1; | |
499 } | |
500 } | |
501 | |
502 | |
503 #if defined(__sgi) && (IRIX < 60500) | |
504 static int no_output(ifp, m, s) | |
505 #else | |
506 # if TRU64 >= 1885 | |
507 static int no_output (ifp, m, s, rt, cp) | |
508 char *cp; | |
509 # else | |
510 static int no_output(ifp, m, s, rt) | |
511 # endif | |
512 struct rtentry *rt; | |
513 #endif | |
514 struct ifnet *ifp; | |
515 struct mbuf *m; | |
516 struct sockaddr *s; | |
517 { | |
518 return 0; | |
519 } | |
520 | |
521 | |
522 #if defined(__sgi) && (IRIX < 60500) | |
523 static int write_output(ifp, m, s) | |
524 #else | |
525 # if TRU64 >= 1885 | |
526 static int write_output (ifp, m, s, rt, cp) | |
527 char *cp; | |
528 # else | |
529 static int write_output(ifp, m, s, rt) | |
530 # endif | |
531 struct rtentry *rt; | |
532 #endif | |
533 struct ifnet *ifp; | |
534 struct mbuf *m; | |
535 struct sockaddr *s; | |
536 { | |
537 char fname[32]; | |
538 mb_t *mb; | |
539 ip_t *ip; | |
540 int fd; | |
541 | |
542 mb = (mb_t *)m; | |
543 ip = MTOD(mb, ip_t *); | |
544 | |
545 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ | |
546 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ | |
547 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) | |
548 sprintf(fname, "/tmp/%s", ifp->if_xname); | |
549 #else | |
550 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); | |
551 #endif | |
552 fd = open(fname, O_WRONLY|O_APPEND); | |
553 if (fd == -1) { | |
554 perror("open"); | |
555 return -1; | |
556 } | |
557 write(fd, (char *)ip, ntohs(ip->ip_len)); | |
558 close(fd); | |
559 return 0; | |
560 } | |
561 | |
562 | |
563 static void fr_setifpaddr(ifp, addr) | |
564 struct ifnet *ifp; | |
565 char *addr; | |
566 { | |
567 #ifdef __sgi | |
568 struct in_ifaddr *ifa; | |
569 #else | |
570 struct ifaddr *ifa; | |
571 #endif | |
572 | |
573 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) | |
574 if (ifp->if_addrlist.tqh_first != NULL) | |
575 #else | |
576 # ifdef __sgi | |
577 if (ifp->in_ifaddr != NULL) | |
578 # else | |
579 if (ifp->if_addrlist != NULL) | |
580 # endif | |
581 #endif | |
582 return; | |
583 | |
584 ifa = (struct ifaddr *)malloc(sizeof(*ifa)); | |
585 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) | |
586 ifp->if_addrlist.tqh_first = ifa; | |
587 #else | |
588 # ifdef __sgi | |
589 ifp->in_ifaddr = ifa; | |
590 # else | |
591 ifp->if_addrlist = ifa; | |
592 # endif | |
593 #endif | |
594 | |
595 if (ifa != NULL) { | |
596 struct sockaddr_in *sin; | |
597 | |
598 #ifdef __sgi | |
599 sin = (struct sockaddr_in *)&ifa->ia_addr; | |
600 #else | |
601 sin = (struct sockaddr_in *)&ifa->ifa_addr; | |
602 #endif | |
603 sin->sin_addr.s_addr = inet_addr(addr); | |
604 if (sin->sin_addr.s_addr == 0) | |
605 abort(); | |
606 } | |
607 } | |
608 | |
609 /*ARGSUSED*/ | |
610 struct ifnet *get_unit(name, v, ifs) | |
611 char *name; | |
612 int v; | |
613 ipf_stack_t *ifs; | |
614 { | |
615 struct ifnet *ifp, **ifpp, **old_ifneta; | |
616 char *addr; | |
617 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ | |
618 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ | |
619 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) | |
620 | |
621 if (name == NULL) | |
622 name = "anon0"; | |
623 | |
624 addr = strchr(name, '='); | |
625 if (addr != NULL) | |
626 *addr++ = '\0'; | |
627 | |
628 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { | |
629 if (!strcmp(name, ifp->if_xname)) { | |
630 if (addr != NULL) | |
631 fr_setifpaddr(ifp, addr); | |
632 return ifp; | |
633 } | |
634 } | |
635 #else | |
636 char *s, ifname[LIFNAMSIZ+1]; | |
637 | |
638 if (name == NULL) | |
639 name = "anon0"; | |
640 | |
641 addr = strchr(name, '='); | |
642 if (addr != NULL) | |
643 *addr++ = '\0'; | |
644 | |
645 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { | |
646 COPYIFNAME(ifp, ifname, 0); | |
647 if (!strcmp(name, ifname)) { | |
648 if (addr != NULL) | |
649 fr_setifpaddr(ifp, addr); | |
650 return ifp; | |
651 } | |
652 } | |
653 #endif | |
654 | |
655 if (!ifneta) { | |
656 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2); | |
657 if (!ifneta) | |
658 return NULL; | |
659 ifneta[1] = NULL; | |
660 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp)); | |
661 if (!ifneta[0]) { | |
662 free(ifneta); | |
663 return NULL; | |
664 } | |
665 nifs = 1; | |
666 } else { | |
667 old_ifneta = ifneta; | |
668 nifs++; | |
669 ifneta = (struct ifnet **)realloc(ifneta, | |
670 (nifs + 1) * sizeof(ifp)); | |
671 if (!ifneta) { | |
672 free(old_ifneta); | |
673 nifs = 0; | |
674 return NULL; | |
675 } | |
676 ifneta[nifs] = NULL; | |
677 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp)); | |
678 if (!ifneta[nifs - 1]) { | |
679 nifs--; | |
680 return NULL; | |
681 } | |
682 } | |
683 ifp = ifneta[nifs - 1]; | |
684 | |
685 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ | |
686 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ | |
687 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) | |
688 (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); | |
689 #else | |
690 for (s = name; *s && !ISDIGIT(*s); s++) | |
691 ; | |
692 if (*s && ISDIGIT(*s)) { | |
693 ifp->if_unit = atoi(s); | |
694 ifp->if_name = (char *)malloc(s - name + 1); | |
695 if (ifp->if_name == NULL) { | |
696 /* | |
697 * XXX do it more elegantly: free up mem, | |
698 * return NULL | |
699 */ | |
700 perror("malloc"); | |
701 exit(1); | |
702 } | |
703 (void) strncpy(ifp->if_name, name, s - name); | |
704 ifp->if_name[s - name] = '\0'; | |
705 } else { | |
706 ifp->if_name = strdup(name); | |
707 ifp->if_unit = -1; | |
708 } | |
709 #endif | |
710 ifp->if_output = no_output; | |
711 | |
712 if (addr != NULL) { | |
713 fr_setifpaddr(ifp, addr); | |
714 } | |
715 | |
716 return ifp; | |
717 } | |
718 | |
719 | |
720 char *get_ifname(ifp) | |
721 struct ifnet *ifp; | |
722 { | |
723 static char ifname[LIFNAMSIZ]; | |
724 | |
725 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \ | |
726 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) | |
727 sprintf(ifname, "%s", ifp->if_xname); | |
728 #else | |
729 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); | |
730 #endif | |
731 return ifname; | |
732 } | |
733 | |
734 | |
735 | |
736 void init_ifp() | |
737 { | |
738 struct ifnet *ifp, **ifpp; | |
739 char fname[32]; | |
740 int fd; | |
741 | |
742 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ | |
743 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ | |
744 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) | |
745 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { | |
746 ifp->if_output = write_output; | |
747 sprintf(fname, "/tmp/%s", ifp->if_xname); | |
748 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); | |
749 if (fd == -1) | |
750 perror("open"); | |
751 else | |
752 close(fd); | |
753 } | |
754 #else | |
755 | |
756 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { | |
757 ifp->if_output = write_output; | |
758 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); | |
759 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); | |
760 if (fd == -1) | |
761 perror("open"); | |
762 else | |
763 close(fd); | |
764 } | |
765 #endif | |
766 } | |
767 | |
768 | |
769 int fr_fastroute(m, mpp, fin, fdp) | |
770 mb_t *m, **mpp; | |
771 fr_info_t *fin; | |
772 frdest_t *fdp; | |
773 { | |
774 struct ifnet *ifp = fdp->fd_ifp; | |
775 ip_t *ip = fin->fin_ip; | |
776 | |
777 if (!ifp) | |
778 return 0; /* no routing table out here */ | |
779 | |
780 ip->ip_len = htons((u_short)ip->ip_len); | |
781 ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); | |
782 ip->ip_sum = 0; | |
783 #if defined(__sgi) && (IRIX < 60500) | |
784 (*ifp->if_output)(ifp, (void *)ip, NULL); | |
785 # if TRU64 >= 1885 | |
786 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0); | |
787 # else | |
788 (*ifp->if_output)(ifp, (void *)m, NULL, 0); | |
789 # endif | |
790 #endif | |
791 return 0; | |
792 } | |
793 | |
794 | |
795 int fr_send_reset(fin) | |
796 fr_info_t *fin; | |
797 { | |
798 verbose("- TCP RST sent\n"); | |
799 return 0; | |
800 } | |
801 | |
802 | |
803 int fr_send_icmp_err(type, fin, dst) | |
804 int type; | |
805 fr_info_t *fin; | |
806 int dst; | |
807 { | |
808 verbose("- ICMP unreachable sent\n"); | |
809 return 0; | |
810 } | |
811 | |
812 | |
813 void frsync(command, version, nic, data, ifs) | |
814 int command, version; | |
815 void *nic; | |
816 char *data; | |
817 ipf_stack_t *ifs; | |
818 { | |
819 return; | |
820 } | |
821 | |
822 | |
823 void m_freem(m) | |
824 mb_t *m; | |
825 { | |
826 return; | |
827 } | |
828 | |
829 | |
830 void m_copydata(m, off, len, cp) | |
831 mb_t *m; | |
832 int off, len; | |
833 caddr_t cp; | |
834 { | |
835 bcopy((char *)m + off, cp, len); | |
836 } | |
837 | |
838 | |
839 int ipfuiomove(buf, len, rwflag, uio) | |
840 caddr_t buf; | |
841 int len, rwflag; | |
842 struct uio *uio; | |
843 { | |
844 int left, ioc, num, offset; | |
845 struct iovec *io; | |
846 char *start; | |
847 | |
848 if (rwflag == UIO_READ) { | |
849 left = len; | |
850 ioc = 0; | |
851 | |
852 offset = uio->uio_offset; | |
853 | |
854 while ((left > 0) && (ioc < uio->uio_iovcnt)) { | |
855 io = uio->uio_iov + ioc; | |
856 num = io->iov_len; | |
857 if (num > left) | |
858 num = left; | |
859 start = (char *)io->iov_base + offset; | |
860 if (start > (char *)io->iov_base + io->iov_len) { | |
861 offset -= io->iov_len; | |
862 ioc++; | |
863 continue; | |
864 } | |
865 bcopy(buf, start, num); | |
866 uio->uio_resid -= num; | |
867 uio->uio_offset += num; | |
868 left -= num; | |
869 if (left > 0) | |
870 ioc++; | |
871 } | |
872 if (left > 0) | |
873 return EFAULT; | |
874 } | |
875 return 0; | |
876 } | |
877 | |
878 | |
879 u_32_t fr_newisn(fin) | |
880 fr_info_t *fin; | |
881 { | |
882 static int iss_seq_off = 0; | |
883 u_char hash[16]; | |
884 u_32_t newiss; | |
885 MD5_CTX ctx; | |
886 | |
887 /* | |
888 * Compute the base value of the ISS. It is a hash | |
889 * of (saddr, sport, daddr, dport, secret). | |
890 */ | |
891 MD5Init(&ctx); | |
892 | |
893 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, | |
894 sizeof(fin->fin_fi.fi_src)); | |
895 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, | |
896 sizeof(fin->fin_fi.fi_dst)); | |
897 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); | |
898 | |
899 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */ | |
900 | |
901 MD5Final(hash, &ctx); | |
902 | |
903 memcpy(&newiss, hash, sizeof(newiss)); | |
904 | |
905 /* | |
906 * Now increment our "timer", and add it in to | |
907 * the computed value. | |
908 * | |
909 * XXX Use `addin'? | |
910 * XXX TCP_ISSINCR too large to use? | |
911 */ | |
912 iss_seq_off += 0x00010000; | |
913 newiss += iss_seq_off; | |
914 return newiss; | |
915 } | |
916 | |
917 | |
918 /* ------------------------------------------------------------------------ */ | |
919 /* Function: fr_nextipid */ | |
920 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */ | |
921 /* Parameters: fin(I) - pointer to packet information */ | |
922 /* */ | |
923 /* Returns the next IPv4 ID to use for this packet. */ | |
924 /* ------------------------------------------------------------------------ */ | |
925 INLINE u_short fr_nextipid(fin) | |
926 fr_info_t *fin; | |
927 { | |
928 static u_short ipid = 0; | |
929 u_short id; | |
930 ipf_stack_t *ifs = fin->fin_ifs; | |
931 | |
932 MUTEX_ENTER(&ifs->ifs_ipf_rw); | |
933 id = ipid++; | |
934 MUTEX_EXIT(&ifs->ifs_ipf_rw); | |
935 | |
936 return id; | |
937 } | |
938 | |
939 | |
940 INLINE void fr_checkv4sum(fin) | |
941 fr_info_t *fin; | |
942 { | |
943 if (fr_checkl4sum(fin) == -1) | |
944 fin->fin_flx |= FI_BAD; | |
945 } | |
946 | |
947 | |
948 #ifdef USE_INET6 | |
949 INLINE void fr_checkv6sum(fin) | |
950 fr_info_t *fin; | |
951 { | |
952 if (fr_checkl4sum(fin) == -1) | |
953 fin->fin_flx |= FI_BAD; | |
954 } | |
955 #endif | |
956 | |
957 | |
958 /* | |
959 * See above for description, except that all addressing is in user space. | |
960 */ | |
961 int copyoutptr(src, dst, size) | |
962 void *src, *dst; | |
963 size_t size; | |
964 { | |
965 caddr_t ca; | |
966 | |
967 bcopy(dst, (char *)&ca, sizeof(ca)); | |
968 bcopy(src, ca, size); | |
969 return 0; | |
970 } | |
971 | |
972 | |
973 /* | |
974 * See above for description, except that all addressing is in user space. | |
975 */ | |
976 int copyinptr(src, dst, size) | |
977 void *src, *dst; | |
978 size_t size; | |
979 { | |
980 caddr_t ca; | |
981 | |
982 bcopy(src, (char *)&ca, sizeof(ca)); | |
983 bcopy(ca, dst, size); | |
984 return 0; | |
985 } | |
986 | |
987 | |
988 /* | |
989 * return the first IP Address associated with an interface | |
990 */ | |
991 int fr_ifpaddr(v, atype, ifptr, inp, inpmask, ifs) | |
992 int v, atype; | |
993 void *ifptr; | |
994 struct in_addr *inp, *inpmask; | |
995 ipf_stack_t *ifs; | |
996 { | |
997 struct ifnet *ifp = ifptr; | |
998 #ifdef __sgi | |
999 struct in_ifaddr *ifa; | |
1000 #else | |
1001 struct ifaddr *ifa; | |
1002 #endif | |
1003 | |
1004 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) | |
1005 ifa = ifp->if_addrlist.tqh_first; | |
1006 #else | |
1007 # ifdef __sgi | |
1008 ifa = (struct in_ifaddr *)ifp->in_ifaddr; | |
1009 # else | |
1010 ifa = ifp->if_addrlist; | |
1011 # endif | |
1012 #endif | |
1013 if (ifa != NULL) { | |
1014 struct sockaddr_in *sin, mask; | |
1015 | |
1016 mask.sin_addr.s_addr = 0xffffffff; | |
1017 | |
1018 #ifdef __sgi | |
1019 sin = (struct sockaddr_in *)&ifa->ia_addr; | |
1020 #else | |
1021 sin = (struct sockaddr_in *)&ifa->ifa_addr; | |
1022 #endif | |
1023 | |
1024 return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask); | |
1025 } | |
1026 return 0; | |
1027 } |