Make Dt match installed file name.
[netbsd-mini2440.git] / dist / ipf / ip_fil.c
blobdb4f1b771b5faf883ab3b7b3164d114c75937a15
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 1993-2001 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
7 */
8 #if !defined(lint)
9 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
10 static const char rcsid[] = "@(#)Id: ip_fil.c,v 2.133.2.20 2008/07/27 08:27:04 darrenr Exp";
11 #endif
13 #ifndef SOLARIS
14 #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
15 #endif
17 #include <sys/param.h>
18 #if defined(__FreeBSD__) && !defined(__FreeBSD_version)
19 # if defined(IPFILTER_LKM)
20 # ifndef __FreeBSD_cc_version
21 # include <osreldate.h>
22 # else
23 # if __FreeBSD_cc_version < 430000
24 # include <osreldate.h>
25 # endif
26 # endif
27 # endif
28 #endif
29 #include <sys/errno.h>
30 #if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL)
31 # include <sys/kern_svcs.h>
32 #endif
33 #include <sys/types.h>
34 #define _KERNEL
35 #define KERNEL
36 #ifdef __OpenBSD__
37 struct file;
38 #endif
39 #include <sys/uio.h>
40 #undef _KERNEL
41 #undef KERNEL
42 #include <sys/file.h>
43 #include <sys/ioctl.h>
44 #ifdef __sgi
45 # include <sys/ptimers.h>
46 #endif
47 #include <sys/time.h>
48 #if !SOLARIS
49 # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
50 # include <sys/dirent.h>
51 # else
52 # include <sys/dir.h>
53 # endif
54 #else
55 # include <sys/filio.h>
56 #endif
57 #ifndef linux
58 # include <sys/protosw.h>
59 #endif
60 #include <sys/socket.h>
62 #include <stdio.h>
63 #include <string.h>
64 #include <stdlib.h>
65 #include <ctype.h>
66 #include <fcntl.h>
68 #ifdef __hpux
69 # define _NET_ROUTE_INCLUDED
70 #endif
71 #include <net/if.h>
72 #ifdef sun
73 # include <net/af.h>
74 #endif
75 #if __FreeBSD_version >= 300000
76 # include <net/if_var.h>
77 #endif
78 #ifdef __sgi
79 #include <sys/debug.h>
80 # ifdef IFF_DRVRLOCK /* IRIX6 */
81 #include <sys/hashing.h>
82 # endif
83 #endif
84 #if defined(__FreeBSD__) || defined(SOLARIS2)
85 # include "radix_ipf.h"
86 #endif
87 #ifndef __osf__
88 # include <net/route.h>
89 #endif
90 #include <netinet/in.h>
91 #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \
92 !defined(__hpux) && !defined(linux)
93 # include <netinet/in_var.h>
94 #endif
95 #include <netinet/in_systm.h>
96 #include <netinet/ip.h>
97 #if !defined(linux)
98 # include <netinet/ip_var.h>
99 #endif
100 #include <netinet/tcp.h>
101 #if defined(__osf__)
102 # include <netinet/tcp_timer.h>
103 #endif
104 #if defined(__osf__) || defined(__hpux) || defined(__sgi)
105 # include "radix_ipf_local.h"
106 # define _RADIX_H_
107 #endif
108 #include <netinet/udp.h>
109 #include <netinet/tcpip.h>
110 #include <netinet/ip_icmp.h>
111 #include <unistd.h>
112 #include <syslog.h>
113 #include <arpa/inet.h>
114 #ifdef __hpux
115 # undef _NET_ROUTE_INCLUDED
116 #endif
117 #include "netinet/ip_compat.h"
118 #include "netinet/ip_fil.h"
119 #include "netinet/ip_nat.h"
120 #include "netinet/ip_frag.h"
121 #include "netinet/ip_state.h"
122 #include "netinet/ip_proxy.h"
123 #include "netinet/ip_auth.h"
124 #ifdef IPFILTER_SYNC
125 #include "netinet/ip_sync.h"
126 #endif
127 #ifdef IPFILTER_SCAN
128 #include "netinet/ip_scan.h"
129 #endif
130 #include "netinet/ip_pool.h"
131 #ifdef IPFILTER_COMPILED
132 # include "netinet/ip_rules.h"
133 #endif
134 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
135 # include <sys/malloc.h>
136 #endif
137 #ifdef __hpux
138 struct rtentry;
139 #endif
140 #include "md5.h"
143 #if !defined(__osf__) && !defined(__linux__)
144 extern struct protosw inetsw[];
145 #endif
147 #include "ipt.h"
148 static struct ifnet **ifneta = NULL;
149 static int nifs = 0;
151 static void fr_setifpaddr __P((struct ifnet *, char *));
152 void init_ifp __P((void));
153 #if defined(__sgi) && (IRIX < 60500)
154 static int no_output __P((struct ifnet *, struct mbuf *,
155 struct sockaddr *));
156 static int write_output __P((struct ifnet *, struct mbuf *,
157 struct sockaddr *));
158 #else
159 # if TRU64 >= 1885
160 static int no_output __P((struct ifnet *, struct mbuf *,
161 struct sockaddr *, struct rtentry *, char *));
162 static int write_output __P((struct ifnet *, struct mbuf *,
163 struct sockaddr *, struct rtentry *, char *));
164 # else
165 #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 499001100)
166 static int no_output(struct ifnet *, struct mbuf *,
167 const struct sockaddr *, struct rtentry *);
168 static int write_output(struct ifnet *, struct mbuf *,
169 const struct sockaddr *, struct rtentry *);
170 #else
171 static int no_output __P((struct ifnet *, struct mbuf *,
172 struct sockaddr *, struct rtentry *));
173 static int write_output __P((struct ifnet *, struct mbuf *,
174 struct sockaddr *, struct rtentry *));
175 #endif
176 # endif
177 #endif
180 int ipfattach()
182 fr_running = 1;
183 return 0;
187 int ipfdetach()
189 fr_running = -1;
190 return 0;
195 * Filter ioctl interface.
197 int iplioctl(dev, cmd, data, mode)
198 int dev;
199 ioctlcmd_t cmd;
200 void *data;
201 int mode;
203 int error = 0, unit = 0, uid;
204 SPL_INT(s);
206 uid = getuid();
207 unit = dev;
209 SPL_NET(s);
211 error = fr_ioctlswitch(unit, data, cmd, mode, uid, NULL);
212 if (error != -1) {
213 SPL_X(s);
214 return error;
217 SPL_X(s);
218 return error;
222 void fr_forgetifp(ifp)
223 void *ifp;
225 register frentry_t *f;
227 WRITE_ENTER(&ipf_mutex);
228 for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
229 if (f->fr_ifa == ifp)
230 f->fr_ifa = (void *)-1;
231 for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
232 if (f->fr_ifa == ifp)
233 f->fr_ifa = (void *)-1;
234 for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
235 if (f->fr_ifa == ifp)
236 f->fr_ifa = (void *)-1;
237 for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
238 if (f->fr_ifa == ifp)
239 f->fr_ifa = (void *)-1;
240 #ifdef USE_INET6
241 for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next)
242 if (f->fr_ifa == ifp)
243 f->fr_ifa = (void *)-1;
244 for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next)
245 if (f->fr_ifa == ifp)
246 f->fr_ifa = (void *)-1;
247 for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next)
248 if (f->fr_ifa == ifp)
249 f->fr_ifa = (void *)-1;
250 for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next)
251 if (f->fr_ifa == ifp)
252 f->fr_ifa = (void *)-1;
253 #endif
254 RWLOCK_EXIT(&ipf_mutex);
255 fr_natsync(ifp);
259 #if defined(__sgi) && (IRIX < 60500)
260 static int no_output(ifp, m, s)
261 #else
262 # if TRU64 >= 1885
263 static int no_output (ifp, m, s, rt, cp)
264 char *cp;
265 # else
266 static int no_output(ifp, m, s, rt)
267 # endif
268 struct rtentry *rt;
269 #endif
270 struct ifnet *ifp;
271 struct mbuf *m;
272 #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 499001100)
273 const struct sockaddr *s;
274 #else
275 struct sockaddr *s;
276 #endif
278 return 0;
282 #if defined(__sgi) && (IRIX < 60500)
283 static int write_output(ifp, m, s)
284 #else
285 # if TRU64 >= 1885
286 static int write_output (ifp, m, s, rt, cp)
287 char *cp;
288 # else
289 static int write_output(ifp, m, s, rt)
290 # endif
291 struct rtentry *rt;
292 #endif
293 struct ifnet *ifp;
294 struct mbuf *m;
295 #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 499001100)
296 const struct sockaddr *s;
297 #else
298 struct sockaddr *s;
299 #endif
301 char fname[32];
302 mb_t *mb;
303 ip_t *ip;
304 int fd;
306 mb = (mb_t *)m;
307 ip = MTOD(mb, ip_t *);
309 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
310 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
311 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
312 sprintf(fname, "/tmp/%s", ifp->if_xname);
313 #else
314 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
315 #endif
316 fd = open(fname, O_WRONLY|O_APPEND);
317 if (fd == -1) {
318 perror("open");
319 return -1;
321 write(fd, (char *)ip, ntohs(ip->ip_len));
322 close(fd);
323 return 0;
327 static void fr_setifpaddr(ifp, addr)
328 struct ifnet *ifp;
329 char *addr;
331 #ifdef __sgi
332 struct in_ifaddr *ifa;
333 #else
334 struct ifaddr *ifa;
335 #endif
337 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
338 if (ifp->if_addrlist.tqh_first != NULL)
339 #else
340 # ifdef __sgi
341 if (ifp->in_ifaddr != NULL)
342 # else
343 if (ifp->if_addrlist != NULL)
344 # endif
345 #endif
346 return;
348 ifa = (struct ifaddr *)malloc(sizeof(*ifa));
349 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
350 ifp->if_addrlist.tqh_first = ifa;
351 #else
352 # ifdef __sgi
353 ifp->in_ifaddr = ifa;
354 # else
355 ifp->if_addrlist = ifa;
356 # endif
357 #endif
359 if (ifa != NULL) {
360 struct sockaddr_in *sin;
362 #ifdef __sgi
363 sin = (struct sockaddr_in *)&ifa->ia_addr;
364 #else
365 sin = (struct sockaddr_in *)&ifa->ifa_addr;
366 #endif
367 sin->sin_addr.s_addr = inet_addr(addr);
368 if (sin->sin_addr.s_addr == 0)
369 abort();
373 struct ifnet *get_unit(name, v)
374 char *name;
375 int v;
377 struct ifnet *ifp, **ifpp, **old_ifneta;
378 char *addr;
379 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
380 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
381 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
383 if (name == NULL)
384 name = "anon0";
386 addr = strchr(name, '=');
387 if (addr != NULL)
388 *addr++ = '\0';
390 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
391 if (!strcmp(name, ifp->if_xname)) {
392 if (addr != NULL)
393 fr_setifpaddr(ifp, addr);
394 return ifp;
397 #else
398 char *s, ifname[LIFNAMSIZ+1];
400 if (name == NULL)
401 name = "anon0";
403 addr = strchr(name, '=');
404 if (addr != NULL)
405 *addr++ = '\0';
407 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
408 COPYIFNAME(v, ifp, ifname);
409 if (!strcmp(name, ifname)) {
410 if (addr != NULL)
411 fr_setifpaddr(ifp, addr);
412 return ifp;
415 #endif
417 if (!ifneta) {
418 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
419 if (!ifneta)
420 return NULL;
421 ifneta[1] = NULL;
422 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
423 if (!ifneta[0]) {
424 free(ifneta);
425 return NULL;
427 nifs = 1;
428 } else {
429 old_ifneta = ifneta;
430 nifs++;
431 ifneta = (struct ifnet **)realloc(ifneta,
432 (nifs + 1) * sizeof(ifp));
433 if (!ifneta) {
434 free(old_ifneta);
435 nifs = 0;
436 return NULL;
438 ifneta[nifs] = NULL;
439 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
440 if (!ifneta[nifs - 1]) {
441 nifs--;
442 return NULL;
445 ifp = ifneta[nifs - 1];
447 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
448 TAILQ_INIT(&ifp->if_addrlist);
449 #endif
450 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
451 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
452 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
453 (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
454 #else
455 for (s = name; *s && !ISDIGIT(*s); s++)
457 if (*s && ISDIGIT(*s)) {
458 ifp->if_unit = atoi(s);
459 ifp->if_name = (char *)malloc(s - name + 1);
460 (void) strncpy(ifp->if_name, name, s - name);
461 ifp->if_name[s - name] = '\0';
462 } else {
463 ifp->if_name = strdup(name);
464 ifp->if_unit = -1;
466 #endif
467 ifp->if_output = (void *)no_output;
469 if (addr != NULL) {
470 fr_setifpaddr(ifp, addr);
473 return ifp;
477 char *get_ifname(ifp)
478 struct ifnet *ifp;
480 static char ifname[LIFNAMSIZ];
482 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \
483 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
484 sprintf(ifname, "%s", ifp->if_xname);
485 #else
486 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
487 #endif
488 return ifname;
493 void init_ifp()
495 struct ifnet *ifp, **ifpp;
496 char fname[32];
497 int fd;
499 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
500 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
501 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
502 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
503 ifp->if_output = (void *)write_output;
504 sprintf(fname, "/tmp/%s", ifp->if_xname);
505 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
506 if (fd == -1)
507 perror("open");
508 else
509 close(fd);
511 #else
513 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
514 ifp->if_output = write_output;
515 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
516 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
517 if (fd == -1)
518 perror("open");
519 else
520 close(fd);
522 #endif
526 int fr_fastroute(m, mpp, fin, fdp)
527 mb_t *m, **mpp;
528 fr_info_t *fin;
529 frdest_t *fdp;
531 struct ifnet *ifp = fdp->fd_ifp;
532 ip_t *ip = fin->fin_ip;
533 int error = 0;
534 frentry_t *fr;
535 void *sifp;
537 if (!ifp)
538 return 0; /* no routing table out here */
540 fr = fin->fin_fr;
541 ip->ip_sum = 0;
543 if (fin->fin_out == 0) {
544 sifp = fin->fin_ifp;
545 fin->fin_ifp = ifp;
546 fin->fin_out = 1;
547 (void) fr_acctpkt(fin, NULL);
548 fin->fin_fr = NULL;
549 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
550 u_32_t pass;
552 (void) fr_checkstate(fin, &pass);
555 switch (fr_checknatout(fin, NULL))
557 case 0 :
558 break;
559 case 1 :
560 ip->ip_sum = 0;
561 break;
562 case -1 :
563 error = -1;
564 goto done;
565 break;
568 fin->fin_ifp = sifp;
569 fin->fin_out = 0;
572 #if defined(__sgi) && (IRIX < 60500)
573 (*ifp->if_output)(ifp, (void *)ip, NULL);
574 # if TRU64 >= 1885
575 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
576 # else
577 (*ifp->if_output)(ifp, (void *)m, NULL, 0);
578 # endif
579 #endif
580 done:
581 return error;
585 int fr_send_reset(fin)
586 fr_info_t *fin;
588 verbose("- TCP RST sent\n");
589 return 0;
593 int fr_send_icmp_err(type, fin, dst)
594 int type;
595 fr_info_t *fin;
596 int dst;
598 verbose("- ICMP unreachable sent\n");
599 return 0;
603 void frsync(ifp)
604 void *ifp;
606 return;
610 void m_freem(m)
611 mb_t *m;
613 return;
617 void m_copydata(m, off, len, cp)
618 mb_t *m;
619 int off, len;
620 void *cp;
622 bcopy((char *)m + off, cp, len);
626 int ipfuiomove(buf, len, rwflag, uio)
627 void *buf;
628 int len, rwflag;
629 struct uio *uio;
631 int left, ioc, num, offset;
632 struct iovec *io;
633 char *start;
635 if (rwflag == UIO_READ) {
636 left = len;
637 ioc = 0;
639 offset = uio->uio_offset;
641 while ((left > 0) && (ioc < uio->uio_iovcnt)) {
642 io = uio->uio_iov + ioc;
643 num = io->iov_len;
644 if (num > left)
645 num = left;
646 start = (char *)io->iov_base + offset;
647 if (start > (char *)io->iov_base + io->iov_len) {
648 offset -= io->iov_len;
649 ioc++;
650 continue;
652 bcopy(buf, start, num);
653 uio->uio_resid -= num;
654 uio->uio_offset += num;
655 left -= num;
656 if (left > 0)
657 ioc++;
659 if (left > 0)
660 return EFAULT;
662 return 0;
666 u_32_t fr_newisn(fin)
667 fr_info_t *fin;
669 static int iss_seq_off = 0;
670 u_char hash[16];
671 u_32_t newiss;
672 MD5_CTX ctx;
675 * Compute the base value of the ISS. It is a hash
676 * of (saddr, sport, daddr, dport, secret).
678 MD5Init(&ctx);
680 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
681 sizeof(fin->fin_fi.fi_src));
682 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
683 sizeof(fin->fin_fi.fi_dst));
684 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
686 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
688 MD5Final(hash, &ctx);
690 memcpy(&newiss, hash, sizeof(newiss));
693 * Now increment our "timer", and add it in to
694 * the computed value.
696 * XXX Use `addin'?
697 * XXX TCP_ISSINCR too large to use?
699 iss_seq_off += 0x00010000;
700 newiss += iss_seq_off;
701 return newiss;
705 /* ------------------------------------------------------------------------ */
706 /* Function: fr_nextipid */
707 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
708 /* Parameters: fin(I) - pointer to packet information */
709 /* */
710 /* Returns the next IPv4 ID to use for this packet. */
711 /* ------------------------------------------------------------------------ */
712 INLINE u_short fr_nextipid(fin)
713 fr_info_t *fin;
715 static u_short ipid = 0;
716 u_short id;
718 MUTEX_ENTER(&ipf_rw);
719 id = ipid++;
720 MUTEX_EXIT(&ipf_rw);
722 return id;
726 INLINE void fr_checkv4sum(fin)
727 fr_info_t *fin;
729 if (fr_checkl4sum(fin) == -1)
730 fin->fin_flx |= FI_BAD;
734 #ifdef USE_INET6
735 INLINE void fr_checkv6sum(fin)
736 fr_info_t *fin;
738 if (fr_checkl4sum(fin) == -1)
739 fin->fin_flx |= FI_BAD;
741 #endif
745 * See above for description, except that all addressing is in user space.
747 int copyoutptr(src, dst, size)
748 void *src, *dst;
749 size_t size;
751 caddr_t ca;
753 bcopy(dst, (char *)&ca, sizeof(ca));
754 bcopy(src, ca, size);
755 return 0;
760 * See above for description, except that all addressing is in user space.
762 int copyinptr(src, dst, size)
763 void *src, *dst;
764 size_t size;
766 caddr_t ca;
768 bcopy(src, (char *)&ca, sizeof(ca));
769 bcopy(ca, dst, size);
770 return 0;
775 * return the first IP Address associated with an interface
777 int fr_ifpaddr(v, atype, ifptr, inp, inpmask)
778 int v, atype;
779 void *ifptr;
780 struct in_addr *inp, *inpmask;
782 struct ifnet *ifp = ifptr;
783 #ifdef __sgi
784 struct in_ifaddr *ifa;
785 #else
786 struct ifaddr *ifa;
787 #endif
789 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
790 ifa = ifp->if_addrlist.tqh_first;
791 #else
792 # ifdef __sgi
793 ifa = (struct in_ifaddr *)ifp->in_ifaddr;
794 # else
795 ifa = ifp->if_addrlist;
796 # endif
797 #endif
798 if (ifa != NULL) {
799 struct sockaddr_in *sin, mask;
801 mask.sin_addr.s_addr = 0xffffffff;
803 #ifdef __sgi
804 sin = (struct sockaddr_in *)&ifa->ia_addr;
805 #else
806 sin = (struct sockaddr_in *)&ifa->ifa_addr;
807 #endif
809 return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask);
811 return 0;
815 int ipfsync()
817 return 0;
822 * This function is not meant to be random, rather just produce a
823 * sequence of numbers that isn't linear to show "randomness".
825 u_32_t
826 ipf_random()
828 static int last = 0xa5a5a5a5;
829 static int calls = 0;
830 int number;
832 calls++;
835 * These are deliberately chosen to ensure that there is some
836 * attempt to test whether the output covers the range in test n18.
838 switch (calls)
840 case 1 :
841 number = 0;
842 break;
843 case 2 :
844 number = 4;
845 break;
846 case 3 :
847 number = 3999;
848 break;
849 case 4 :
850 number = 4000;
851 break;
852 case 5 :
853 number = 48999;
854 break;
855 case 6 :
856 number = 49000;
857 break;
858 default :
860 * So why not use srand/rand/srandom/random? Because the
861 * actual values returned vary from platform to platform
862 * and what is needed is seomthing that is the same everywhere
863 * so that regression tests can work. Well, they could be
864 * built on each platform to suit but that's a whole lot of
865 * work for little gain given that we don't actually need
866 * random numbers here, just a spread to test the NAT code
867 * with.
869 number = last;
870 last *= calls;
871 last++;
872 number ^= last;
873 break;
875 return number;