1 | /* $NetBSD: ip_fil.c,v 1.5 2018/02/04 08:19:42 mrg Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (C) 2012 by Darren Reed. |
5 | * |
6 | * See the IPFILTER.LICENCE file for details on licencing. |
7 | * |
8 | * Id: ip_fil.c,v 1.1.1.2 2012/07/22 13:44:12 darrenr Exp |
9 | */ |
10 | #if !defined(lint) |
11 | static __attribute__((__used__)) const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed" ; |
12 | static __attribute__((__used__)) const char rcsid[] = "@(#)Id: ip_fil.c,v 1.1.1.2 2012/07/22 13:44:12 darrenr Exp" ; |
13 | #endif |
14 | |
15 | #include "ipf.h" |
16 | #include "md5.h" |
17 | #include "ipt.h" |
18 | |
19 | ipf_main_softc_t ipfmain; |
20 | |
21 | static struct ifnet **ifneta = NULL; |
22 | static int nifs = 0; |
23 | |
24 | struct rtentry; |
25 | |
26 | static void ipf_setifpaddr __P((struct ifnet *, char *)); |
27 | void init_ifp __P((void)); |
28 | #if defined(__sgi) && (IRIX < 60500) |
29 | static int no_output __P((struct ifnet *, struct mbuf *, |
30 | struct sockaddr *)); |
31 | static int write_output __P((struct ifnet *, struct mbuf *, |
32 | struct sockaddr *)); |
33 | #else |
34 | # if TRU64 >= 1885 |
35 | static int no_output __P((struct ifnet *, struct mbuf *, |
36 | struct sockaddr *, struct rtentry *, char *)); |
37 | static int write_output __P((struct ifnet *, struct mbuf *, |
38 | struct sockaddr *, struct rtentry *, char *)); |
39 | # else |
40 | #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 499001100) |
41 | static int no_output(struct ifnet *, struct mbuf *, |
42 | const struct sockaddr *, struct rtentry *); |
43 | static int write_output(struct ifnet *, struct mbuf *, |
44 | const struct sockaddr *, struct rtentry *); |
45 | #else |
46 | static int no_output __P((struct ifnet *, struct mbuf *, |
47 | struct sockaddr *, struct rtentry *)); |
48 | static int write_output __P((struct ifnet *, struct mbuf *, |
49 | struct sockaddr *, struct rtentry *)); |
50 | #endif |
51 | # endif |
52 | #endif |
53 | |
54 | |
55 | int |
56 | ipfattach(softc) |
57 | ipf_main_softc_t *softc; |
58 | { |
59 | return 0; |
60 | } |
61 | |
62 | |
63 | int |
64 | ipfdetach(softc) |
65 | ipf_main_softc_t *softc; |
66 | { |
67 | return 0; |
68 | } |
69 | |
70 | |
71 | /* |
72 | * Filter ioctl interface. |
73 | */ |
74 | int |
75 | ipfioctl(softc, dev, cmd, data, mode) |
76 | ipf_main_softc_t *softc; |
77 | int dev; |
78 | ioctlcmd_t cmd; |
79 | void *data; |
80 | int mode; |
81 | { |
82 | int error = 0, unit = 0, uid; |
83 | |
84 | uid = getuid(); |
85 | unit = dev; |
86 | |
87 | SPL_NET(s); |
88 | |
89 | error = ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, NULL); |
90 | if (error != -1) { |
91 | SPL_X(s); |
92 | return error; |
93 | } |
94 | SPL_X(s); |
95 | return error; |
96 | } |
97 | |
98 | |
99 | void |
100 | ipf_forgetifp(softc, ifp) |
101 | ipf_main_softc_t *softc; |
102 | void *ifp; |
103 | { |
104 | register frentry_t *f; |
105 | |
106 | WRITE_ENTER(&softc->ipf_mutex); |
107 | for (f = softc->ipf_acct[0][softc->ipf_active]; (f != NULL); |
108 | f = f->fr_next) |
109 | if (f->fr_ifa == ifp) |
110 | f->fr_ifa = (void *)-1; |
111 | for (f = softc->ipf_acct[1][softc->ipf_active]; (f != NULL); |
112 | f = f->fr_next) |
113 | if (f->fr_ifa == ifp) |
114 | f->fr_ifa = (void *)-1; |
115 | for (f = softc->ipf_rules[0][softc->ipf_active]; (f != NULL); |
116 | f = f->fr_next) |
117 | if (f->fr_ifa == ifp) |
118 | f->fr_ifa = (void *)-1; |
119 | for (f = softc->ipf_rules[1][softc->ipf_active]; (f != NULL); |
120 | f = f->fr_next) |
121 | if (f->fr_ifa == ifp) |
122 | f->fr_ifa = (void *)-1; |
123 | RWLOCK_EXIT(&softc->ipf_mutex); |
124 | ipf_nat_sync(softc, ifp); |
125 | ipf_lookup_sync(softc, ifp); |
126 | } |
127 | |
128 | |
129 | static int |
130 | #if defined(__sgi) && (IRIX < 60500) |
131 | no_output(ifp, m, s) |
132 | #else |
133 | # if TRU64 >= 1885 |
134 | no_output (ifp, m, s, rt, cp) |
135 | char *cp; |
136 | # else |
137 | no_output(ifp, m, s, rt) |
138 | # endif |
139 | struct rtentry *rt; |
140 | #endif |
141 | struct ifnet *ifp; |
142 | struct mbuf *m; |
143 | const struct sockaddr *s; |
144 | { |
145 | return 0; |
146 | } |
147 | |
148 | |
149 | static int |
150 | #if defined(__sgi) && (IRIX < 60500) |
151 | write_output(ifp, m, s) |
152 | #else |
153 | # if TRU64 >= 1885 |
154 | write_output (ifp, m, s, rt, cp) |
155 | char *cp; |
156 | # else |
157 | write_output(ifp, m, s, rt) |
158 | # endif |
159 | struct rtentry *rt; |
160 | #endif |
161 | struct ifnet *ifp; |
162 | struct mbuf *m; |
163 | const struct sockaddr *s; |
164 | { |
165 | char fname[32]; |
166 | mb_t *mb; |
167 | ip_t *ip; |
168 | int fd; |
169 | |
170 | mb = (mb_t *)m; |
171 | ip = MTOD(mb, ip_t *); |
172 | |
173 | #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ |
174 | (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ |
175 | (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) |
176 | sprintf(fname, "/tmp/%s" , ifp->if_xname); |
177 | #else |
178 | sprintf(fname, "/tmp/%s%d" , ifp->if_name, ifp->if_unit); |
179 | #endif |
180 | fd = open(fname, O_WRONLY|O_APPEND); |
181 | if (fd == -1) { |
182 | perror("open" ); |
183 | return -1; |
184 | } |
185 | write(fd, (char *)ip, ntohs(ip->ip_len)); |
186 | close(fd); |
187 | return 0; |
188 | } |
189 | |
190 | |
191 | static void |
192 | ipf_setifpaddr(ifp, addr) |
193 | struct ifnet *ifp; |
194 | char *addr; |
195 | { |
196 | #ifdef __sgi |
197 | struct in_ifaddr *ifa; |
198 | #else |
199 | struct ifaddr *ifa; |
200 | #endif |
201 | |
202 | #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) |
203 | if (ifp->if_addrlist.tqh_first != NULL) |
204 | #else |
205 | # ifdef __sgi |
206 | if (ifp->in_ifaddr != NULL) |
207 | # else |
208 | if (ifp->if_addrlist != NULL) |
209 | # endif |
210 | #endif |
211 | return; |
212 | |
213 | ifa = (struct ifaddr *)calloc(1, sizeof(*ifa)); |
214 | #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) |
215 | ifp->if_addrlist.tqh_first = ifa; |
216 | #else |
217 | # ifdef __sgi |
218 | ifp->in_ifaddr = ifa; |
219 | # else |
220 | ifp->if_addrlist = ifa; |
221 | # endif |
222 | #endif |
223 | |
224 | if (ifa != NULL) { |
225 | struct sockaddr_in *sin; |
226 | |
227 | #ifdef __sgi |
228 | sin = (struct sockaddr_in *)&ifa->ia_addr; |
229 | #else |
230 | sin = (struct sockaddr_in *)&ifa->ifa_addr; |
231 | #endif |
232 | #ifdef USE_INET6 |
233 | if (index(addr, ':') != NULL) { |
234 | struct sockaddr_in6 *sin6; |
235 | |
236 | sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr; |
237 | sin6->sin6_family = AF_INET6; |
238 | inet_pton(AF_INET6, addr, &sin6->sin6_addr); |
239 | } else |
240 | #endif |
241 | { |
242 | sin->sin_family = AF_INET; |
243 | sin->sin_addr.s_addr = inet_addr(addr); |
244 | if (sin->sin_addr.s_addr == 0) |
245 | abort(); |
246 | } |
247 | } |
248 | } |
249 | |
250 | struct ifnet * |
251 | get_unit(name, family) |
252 | char *name; |
253 | int family; |
254 | { |
255 | struct ifnet *ifp, **ifpp, **old_ifneta; |
256 | char *addr; |
257 | #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ |
258 | (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ |
259 | (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) |
260 | |
261 | if (!*name) |
262 | return NULL; |
263 | |
264 | if (name == NULL) |
265 | name = "anon0" ; |
266 | |
267 | addr = strchr(name, '='); |
268 | if (addr != NULL) |
269 | *addr++ = '\0'; |
270 | |
271 | for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { |
272 | if (!strcmp(name, ifp->if_xname)) { |
273 | if (addr != NULL) |
274 | ipf_setifpaddr(ifp, addr); |
275 | return ifp; |
276 | } |
277 | } |
278 | #else |
279 | char *s, ifname[LIFNAMSIZ+1]; |
280 | |
281 | if (name == NULL) |
282 | name = "anon0" ; |
283 | |
284 | addr = strchr(name, '='); |
285 | if (addr != NULL) |
286 | *addr++ = '\0'; |
287 | |
288 | for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { |
289 | COPYIFNAME(family, ifp, ifname); |
290 | if (!strcmp(name, ifname)) { |
291 | if (addr != NULL) |
292 | ipf_setifpaddr(ifp, addr); |
293 | return ifp; |
294 | } |
295 | } |
296 | #endif |
297 | |
298 | if (!ifneta) { |
299 | ifneta = (struct ifnet **)calloc(1, sizeof(ifp) * 2); |
300 | if (!ifneta) |
301 | return NULL; |
302 | ifneta[1] = NULL; |
303 | ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp)); |
304 | if (!ifneta[0]) { |
305 | free(ifneta); |
306 | return NULL; |
307 | } |
308 | nifs = 1; |
309 | } else { |
310 | old_ifneta = ifneta; |
311 | nifs++; |
312 | ifneta = (struct ifnet **)realloc(ifneta, |
313 | (nifs + 1) * sizeof(ifp)); |
314 | if (!ifneta) { |
315 | free(old_ifneta); |
316 | nifs = 0; |
317 | return NULL; |
318 | } |
319 | ifneta[nifs] = NULL; |
320 | ifneta[nifs - 1] = (struct ifnet *)calloc(1, sizeof(*ifp)); |
321 | if (!ifneta[nifs - 1]) { |
322 | nifs--; |
323 | return NULL; |
324 | } |
325 | } |
326 | ifp = ifneta[nifs - 1]; |
327 | |
328 | #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) |
329 | TAILQ_INIT(&ifp->if_addrlist); |
330 | #endif |
331 | #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ |
332 | (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ |
333 | (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) |
334 | (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); |
335 | #else |
336 | s = name + strlen(name) - 1; |
337 | for (; s > name; s--) { |
338 | if (!ISDIGIT(*s)) { |
339 | s++; |
340 | break; |
341 | } |
342 | } |
343 | |
344 | if ((s > name) && (*s != 0) && ISDIGIT(*s)) { |
345 | ifp->if_unit = atoi(s); |
346 | ifp->if_name = (char *)malloc(s - name + 1); |
347 | (void) strncpy(ifp->if_name, name, s - name); |
348 | ifp->if_name[s - name] = '\0'; |
349 | } else { |
350 | ifp->if_name = strdup(name); |
351 | ifp->if_unit = -1; |
352 | } |
353 | #endif |
354 | ifp->if_output = (void *)no_output; |
355 | |
356 | if (addr != NULL) { |
357 | ipf_setifpaddr(ifp, addr); |
358 | } |
359 | |
360 | return ifp; |
361 | } |
362 | |
363 | |
364 | char * |
365 | get_ifname(ifp) |
366 | struct ifnet *ifp; |
367 | { |
368 | static char ifname[LIFNAMSIZ]; |
369 | |
370 | #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \ |
371 | (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) |
372 | sprintf(ifname, "%s" , ifp->if_xname); |
373 | #else |
374 | if (ifp->if_unit != -1) |
375 | sprintf(ifname, "%s%d" , ifp->if_name, ifp->if_unit); |
376 | else |
377 | strcpy(ifname, ifp->if_name); |
378 | #endif |
379 | return ifname; |
380 | } |
381 | |
382 | |
383 | |
384 | void |
385 | init_ifp() |
386 | { |
387 | struct ifnet *ifp, **ifpp; |
388 | char fname[32]; |
389 | int fd; |
390 | |
391 | #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ |
392 | (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ |
393 | (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) |
394 | for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { |
395 | ifp->if_output = (void *)write_output; |
396 | sprintf(fname, "/tmp/%s" , ifp->if_xname); |
397 | fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); |
398 | if (fd == -1) |
399 | perror("open" ); |
400 | else |
401 | close(fd); |
402 | } |
403 | #else |
404 | |
405 | for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { |
406 | ifp->if_output = (void *)write_output; |
407 | sprintf(fname, "/tmp/%s%d" , ifp->if_name, ifp->if_unit); |
408 | fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); |
409 | if (fd == -1) |
410 | perror("open" ); |
411 | else |
412 | close(fd); |
413 | } |
414 | #endif |
415 | } |
416 | |
417 | |
418 | int |
419 | ipf_fastroute(m, mpp, fin, fdp) |
420 | mb_t *m, **mpp; |
421 | fr_info_t *fin; |
422 | frdest_t *fdp; |
423 | { |
424 | struct ifnet *ifp; |
425 | ip_t *ip = fin->fin_ip; |
426 | frdest_t node; |
427 | int error = 0; |
428 | frentry_t *fr; |
429 | void *sifp; |
430 | int sout; |
431 | |
432 | sifp = fin->fin_ifp; |
433 | sout = fin->fin_out; |
434 | fr = fin->fin_fr; |
435 | ip->ip_sum = 0; |
436 | |
437 | if (!(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && |
438 | (fdp->fd_type == FRD_DSTLIST)) { |
439 | bzero(&node, sizeof(node)); |
440 | ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node); |
441 | fdp = &node; |
442 | } |
443 | ifp = fdp->fd_ptr; |
444 | |
445 | if (ifp == NULL) |
446 | return 0; /* no routing table out here */ |
447 | |
448 | if (fin->fin_out == 0) { |
449 | fin->fin_ifp = ifp; |
450 | fin->fin_out = 1; |
451 | (void) ipf_acctpkt(fin, NULL); |
452 | fin->fin_fr = NULL; |
453 | if (!fr || !(fr->fr_flags & FR_RETMASK)) { |
454 | u_32_t pass; |
455 | |
456 | (void) ipf_state_check(fin, &pass); |
457 | } |
458 | |
459 | switch (ipf_nat_checkout(fin, NULL)) |
460 | { |
461 | case 0 : |
462 | break; |
463 | case 1 : |
464 | ip->ip_sum = 0; |
465 | break; |
466 | case -1 : |
467 | error = -1; |
468 | goto done; |
469 | break; |
470 | } |
471 | |
472 | } |
473 | |
474 | m->mb_ifp = ifp; |
475 | printpacket(fin->fin_out, m); |
476 | |
477 | #if defined(__sgi) && (IRIX < 60500) |
478 | (*ifp->if_output)(ifp, (void *)ip, NULL); |
479 | # if TRU64 >= 1885 |
480 | (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0); |
481 | # else |
482 | (*ifp->if_output)(ifp, (void *)m, NULL, 0); |
483 | # endif |
484 | #endif |
485 | done: |
486 | fin->fin_ifp = sifp; |
487 | fin->fin_out = sout; |
488 | return error; |
489 | } |
490 | |
491 | |
492 | int |
493 | ipf_send_reset(fin) |
494 | fr_info_t *fin; |
495 | { |
496 | ipfkverbose("- TCP RST sent\n" ); |
497 | return 0; |
498 | } |
499 | |
500 | |
501 | int |
502 | ipf_send_icmp_err(type, fin, dst) |
503 | int type; |
504 | fr_info_t *fin; |
505 | int dst; |
506 | { |
507 | ipfkverbose("- ICMP unreachable sent\n" ); |
508 | return 0; |
509 | } |
510 | |
511 | |
512 | void |
513 | m_freem(m) |
514 | mb_t *m; |
515 | { |
516 | return; |
517 | } |
518 | |
519 | |
520 | void |
521 | m_copydata(m, off, len, cp) |
522 | mb_t *m; |
523 | int off, len; |
524 | void * cp; |
525 | { |
526 | bcopy((char *)m + off, cp, len); |
527 | } |
528 | |
529 | |
530 | int |
531 | ipfuiomove(buf, len, rwflag, uio) |
532 | void *buf; |
533 | int len, rwflag; |
534 | struct uio *uio; |
535 | { |
536 | int left, ioc, num, offset; |
537 | struct iovec *io; |
538 | char *start; |
539 | |
540 | if (rwflag == UIO_READ) { |
541 | left = len; |
542 | ioc = 0; |
543 | |
544 | offset = uio->uio_offset; |
545 | |
546 | while ((left > 0) && (ioc < uio->uio_iovcnt)) { |
547 | io = uio->uio_iov + ioc; |
548 | num = io->iov_len; |
549 | if (num > left) |
550 | num = left; |
551 | start = (char *)io->iov_base + offset; |
552 | if (start > (char *)io->iov_base + io->iov_len) { |
553 | offset -= io->iov_len; |
554 | ioc++; |
555 | continue; |
556 | } |
557 | bcopy(buf, start, num); |
558 | uio->uio_resid -= num; |
559 | uio->uio_offset += num; |
560 | left -= num; |
561 | if (left > 0) |
562 | ioc++; |
563 | } |
564 | if (left > 0) |
565 | return EFAULT; |
566 | } |
567 | return 0; |
568 | } |
569 | |
570 | |
571 | u_32_t |
572 | ipf_newisn(fin) |
573 | fr_info_t *fin; |
574 | { |
575 | static int iss_seq_off = 0; |
576 | u_char hash[16]; |
577 | u_32_t newiss; |
578 | MD5_CTX ctx; |
579 | |
580 | /* |
581 | * Compute the base value of the ISS. It is a hash |
582 | * of (saddr, sport, daddr, dport, secret). |
583 | */ |
584 | MD5Init(&ctx); |
585 | |
586 | MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, |
587 | sizeof(fin->fin_fi.fi_src)); |
588 | MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, |
589 | sizeof(fin->fin_fi.fi_dst)); |
590 | MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); |
591 | |
592 | /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */ |
593 | |
594 | MD5Final(hash, &ctx); |
595 | |
596 | memcpy(&newiss, hash, sizeof(newiss)); |
597 | |
598 | /* |
599 | * Now increment our "timer", and add it in to |
600 | * the computed value. |
601 | * |
602 | * XXX Use `addin'? |
603 | * XXX TCP_ISSINCR too large to use? |
604 | */ |
605 | iss_seq_off += 0x00010000; |
606 | newiss += iss_seq_off; |
607 | return newiss; |
608 | } |
609 | |
610 | |
611 | /* ------------------------------------------------------------------------ */ |
612 | /* Function: ipf_nextipid */ |
613 | /* Returns: int - 0 == success, -1 == error (packet should be droppped) */ |
614 | /* Parameters: fin(I) - pointer to packet information */ |
615 | /* */ |
616 | /* Returns the next IPv4 ID to use for this packet. */ |
617 | /* ------------------------------------------------------------------------ */ |
618 | EXTERN_INLINE u_short |
619 | ipf_nextipid(fin) |
620 | fr_info_t *fin; |
621 | { |
622 | static u_short ipid = 0; |
623 | ipf_main_softc_t *softc = fin->fin_main_soft; |
624 | u_short id; |
625 | |
626 | MUTEX_ENTER(&softc->ipf_rw); |
627 | if (fin->fin_pktnum != 0) { |
628 | /* |
629 | * The -1 is for aligned test results. |
630 | */ |
631 | id = (fin->fin_pktnum - 1) & 0xffff; |
632 | } else { |
633 | } |
634 | id = ipid++; |
635 | MUTEX_EXIT(&softc->ipf_rw); |
636 | |
637 | return id; |
638 | } |
639 | |
640 | |
641 | EXTERN_INLINE int |
642 | ipf_checkv4sum(fin) |
643 | fr_info_t *fin; |
644 | { |
645 | |
646 | if (fin->fin_flx & FI_SHORT) |
647 | return 1; |
648 | |
649 | if (ipf_checkl4sum(fin) == -1) { |
650 | fin->fin_flx |= FI_BAD; |
651 | return -1; |
652 | } |
653 | return 0; |
654 | } |
655 | |
656 | |
657 | #ifdef USE_INET6 |
658 | EXTERN_INLINE int |
659 | ipf_checkv6sum(fin) |
660 | fr_info_t *fin; |
661 | { |
662 | if (fin->fin_flx & FI_SHORT) |
663 | return 1; |
664 | |
665 | if (ipf_checkl4sum(fin) == -1) { |
666 | fin->fin_flx |= FI_BAD; |
667 | return -1; |
668 | } |
669 | return 0; |
670 | } |
671 | #endif |
672 | |
673 | |
674 | #if 0 |
675 | /* |
676 | * See above for description, except that all addressing is in user space. |
677 | */ |
678 | int |
679 | copyoutptr(softc, src, dst, size) |
680 | void *src, *dst; |
681 | size_t size; |
682 | { |
683 | caddr_t ca; |
684 | |
685 | bcopy(dst, (char *)&ca, sizeof(ca)); |
686 | bcopy(src, ca, size); |
687 | return 0; |
688 | } |
689 | |
690 | |
691 | /* |
692 | * See above for description, except that all addressing is in user space. |
693 | */ |
694 | int |
695 | copyinptr(src, dst, size) |
696 | void *src, *dst; |
697 | size_t size; |
698 | { |
699 | caddr_t ca; |
700 | |
701 | bcopy(src, (char *)&ca, sizeof(ca)); |
702 | bcopy(ca, dst, size); |
703 | return 0; |
704 | } |
705 | #endif |
706 | |
707 | |
708 | /* |
709 | * return the first IP Address associated with an interface |
710 | */ |
711 | int |
712 | ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) |
713 | ipf_main_softc_t *softc; |
714 | int v, atype; |
715 | void *ifptr; |
716 | i6addr_t *inp, *inpmask; |
717 | { |
718 | struct ifnet *ifp = ifptr; |
719 | #ifdef __sgi |
720 | struct in_ifaddr *ifa; |
721 | #else |
722 | struct ifaddr *ifa; |
723 | #endif |
724 | |
725 | #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) |
726 | ifa = ifp->if_addrlist.tqh_first; |
727 | #else |
728 | # ifdef __sgi |
729 | ifa = (struct in_ifaddr *)ifp->in_ifaddr; |
730 | # else |
731 | ifa = ifp->if_addrlist; |
732 | # endif |
733 | #endif |
734 | if (ifa != NULL) { |
735 | if (v == 4) { |
736 | struct sockaddr_in *sin, mask; |
737 | |
738 | mask.sin_addr.s_addr = 0xffffffff; |
739 | |
740 | #ifdef __sgi |
741 | sin = (struct sockaddr_in *)&ifa->ia_addr; |
742 | #else |
743 | sin = (struct sockaddr_in *)&ifa->ifa_addr; |
744 | #endif |
745 | |
746 | return ipf_ifpfillv4addr(atype, sin, &mask, |
747 | &inp->in4, &inpmask->in4); |
748 | } |
749 | #ifdef USE_INET6 |
750 | if (v == 6) { |
751 | struct sockaddr_in6 *sin6, mask; |
752 | |
753 | sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr; |
754 | ((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff; |
755 | ((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff; |
756 | ((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff; |
757 | ((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff; |
758 | return ipf_ifpfillv6addr(atype, sin6, &mask, |
759 | inp, inpmask); |
760 | } |
761 | #endif |
762 | } |
763 | return 0; |
764 | } |
765 | |
766 | |
767 | /* |
768 | * This function is not meant to be random, rather just produce a |
769 | * sequence of numbers that isn't linear to show "randomness". |
770 | */ |
771 | u_32_t |
772 | ipf_random() |
773 | { |
774 | static unsigned int last = 0xa5a5a5a5; |
775 | static int calls = 0; |
776 | int number; |
777 | |
778 | calls++; |
779 | |
780 | /* |
781 | * These are deliberately chosen to ensure that there is some |
782 | * attempt to test whether the output covers the range in test n18. |
783 | */ |
784 | switch (calls) |
785 | { |
786 | case 1 : |
787 | number = 0; |
788 | break; |
789 | case 2 : |
790 | number = 4; |
791 | break; |
792 | case 3 : |
793 | number = 3999; |
794 | break; |
795 | case 4 : |
796 | number = 4000; |
797 | break; |
798 | case 5 : |
799 | number = 48999; |
800 | break; |
801 | case 6 : |
802 | number = 49000; |
803 | break; |
804 | default : |
805 | number = last; |
806 | last *= calls; |
807 | last++; |
808 | number ^= last; |
809 | break; |
810 | } |
811 | return number; |
812 | } |
813 | |
814 | |
815 | int |
816 | ipf_verifysrc(fin) |
817 | fr_info_t *fin; |
818 | { |
819 | return 1; |
820 | } |
821 | |
822 | |
823 | int |
824 | ipf_inject(fin, m) |
825 | fr_info_t *fin; |
826 | mb_t *m; |
827 | { |
828 | FREE_MB_T(m); |
829 | |
830 | return 0; |
831 | } |
832 | |
833 | |
834 | u_int |
835 | ipf_pcksum(fin, hlen, sum) |
836 | fr_info_t *fin; |
837 | int hlen; |
838 | u_int sum; |
839 | { |
840 | u_short *sp; |
841 | u_int sum2; |
842 | int slen; |
843 | |
844 | slen = fin->fin_plen - hlen; |
845 | sp = (u_short *)((u_char *)fin->fin_ip + hlen); |
846 | |
847 | for (; slen > 1; slen -= 2) |
848 | sum += *sp++; |
849 | if (slen) |
850 | sum += ntohs(*(u_char *)sp << 8); |
851 | while (sum > 0xffff) |
852 | sum = (sum & 0xffff) + (sum >> 16); |
853 | sum2 = (u_short)(~sum & 0xffff); |
854 | |
855 | return sum2; |
856 | } |
857 | |
858 | |
859 | void * |
860 | ipf_pullup(m, fin, plen) |
861 | mb_t *m; |
862 | fr_info_t *fin; |
863 | int plen; |
864 | { |
865 | if (M_LEN(m) >= plen) |
866 | return fin->fin_ip; |
867 | |
868 | /* |
869 | * Fake ipf_pullup failing |
870 | */ |
871 | fin->fin_reason = FRB_PULLUP; |
872 | *fin->fin_mp = NULL; |
873 | fin->fin_m = NULL; |
874 | fin->fin_ip = NULL; |
875 | return NULL; |
876 | } |
877 | |