4 * Copyright (C) 2012 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
11 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
12 static const char rcsid[] = "@(#)$Id$";
19 ipf_main_softc_t ipfmain;
21 static struct ifnet **ifneta = NULL;
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 *,
31 static int write_output __P((struct ifnet *, struct mbuf *,
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 *));
40 static int no_output __P((struct ifnet *, struct mbuf *,
41 struct sockaddr *, struct rtentry *));
42 static int write_output __P((struct ifnet *, struct mbuf *,
43 struct sockaddr *, struct rtentry *));
48 struct sockaddr_storage ifa_addr;
53 ipf_main_softc_t *softc;
61 ipf_main_softc_t *softc;
68 * Filter ioctl interface.
71 ipfioctl(softc, dev, cmd, data, mode)
72 ipf_main_softc_t *softc;
78 int error = 0, unit = 0, uid;
85 error = ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, NULL);
96 ipf_forgetifp(softc, ifp)
97 ipf_main_softc_t *softc;
100 register frentry_t *f;
102 WRITE_ENTER(&softc->ipf_mutex);
103 for (f = softc->ipf_acct[0][softc->ipf_active]; (f != NULL);
105 if (f->fr_ifa == ifp)
106 f->fr_ifa = (void *)-1;
107 for (f = softc->ipf_acct[1][softc->ipf_active]; (f != NULL);
109 if (f->fr_ifa == ifp)
110 f->fr_ifa = (void *)-1;
111 for (f = softc->ipf_rules[0][softc->ipf_active]; (f != NULL);
113 if (f->fr_ifa == ifp)
114 f->fr_ifa = (void *)-1;
115 for (f = softc->ipf_rules[1][softc->ipf_active]; (f != NULL);
117 if (f->fr_ifa == ifp)
118 f->fr_ifa = (void *)-1;
119 RWLOCK_EXIT(&softc->ipf_mutex);
120 ipf_nat_sync(softc, ifp);
121 ipf_lookup_sync(softc, ifp);
126 #if defined(__sgi) && (IRIX < 60500)
130 no_output (ifp, m, s, rt, cp)
133 no_output(ifp, m, s, rt)
146 #if defined(__sgi) && (IRIX < 60500)
147 write_output(ifp, m, s)
150 write_output (ifp, m, s, rt, cp)
153 write_output(ifp, m, s, rt)
167 ip = MTOD(mb, ip_t *);
169 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
170 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
171 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
172 sprintf(fname, "/tmp/%s", ifp->if_xname);
174 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
176 fd = open(fname, O_WRONLY|O_APPEND);
181 write(fd, (char *)ip, ntohs(ip->ip_len));
188 ipf_setifpaddr(ifp, addr)
193 struct in_ifaddr *ifa;
198 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
199 if (ifp->if_addrlist.tqh_first != NULL)
202 if (ifp->in_ifaddr != NULL)
204 if (ifp->if_addrlist != NULL)
209 ifa = (struct ifaddr *)malloc(sizeof(*ifa));
210 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
211 ifp->if_addrlist.tqh_first = ifa;
214 ifp->in_ifaddr = ifa;
216 ifp->if_addrlist = ifa;
221 struct sockaddr_in *sin;
224 sin = (struct sockaddr_in *)&ifa->ia_addr;
226 sin = (struct sockaddr_in *)&ifa->ifa_addr;
229 if (index(addr, ':') != NULL) {
230 struct sockaddr_in6 *sin6;
232 sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
233 sin6->sin6_family = AF_INET6;
234 /* Abort if bad address. */
235 switch (inet_pton(AF_INET6, addr, &sin6->sin6_addr))
250 sin->sin_family = AF_INET;
251 sin->sin_addr.s_addr = inet_addr(addr);
252 if (sin->sin_addr.s_addr == 0)
259 get_unit(name, family)
263 struct ifnet *ifp, **ifpp, **old_ifneta;
265 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
266 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
267 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
275 addr = strchr(name, '=');
279 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
280 if (!strcmp(name, ifp->if_xname)) {
282 ipf_setifpaddr(ifp, addr);
287 char *s, ifname[LIFNAMSIZ+1];
292 addr = strchr(name, '=');
296 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
297 COPYIFNAME(family, ifp, ifname);
298 if (!strcmp(name, ifname)) {
300 ipf_setifpaddr(ifp, addr);
307 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
311 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
320 ifneta = (struct ifnet **)realloc(ifneta,
321 (nifs + 1) * sizeof(ifp));
328 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
329 if (!ifneta[nifs - 1]) {
334 ifp = ifneta[nifs - 1];
336 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
337 TAILQ_INIT(&ifp->if_addrlist);
339 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
340 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
341 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
342 (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
344 s = name + strlen(name) - 1;
345 for (; s > name; s--) {
352 if ((s > name) && (*s != 0) && ISDIGIT(*s)) {
353 ifp->if_unit = atoi(s);
354 ifp->if_name = (char *)malloc(s - name + 1);
355 (void) strncpy(ifp->if_name, name, s - name);
356 ifp->if_name[s - name] = '\0';
358 ifp->if_name = strdup(name);
362 ifp->if_output = (void *)no_output;
365 ipf_setifpaddr(ifp, addr);
376 static char ifname[LIFNAMSIZ];
378 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \
379 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
380 sprintf(ifname, "%s", ifp->if_xname);
382 if (ifp->if_unit != -1)
383 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
385 strcpy(ifname, ifp->if_name);
395 struct ifnet *ifp, **ifpp;
399 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
400 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
401 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
402 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
403 ifp->if_output = (void *)write_output;
404 sprintf(fname, "/tmp/%s", ifp->if_xname);
405 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
413 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
414 ifp->if_output = (void *)write_output;
415 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
416 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
427 ipf_fastroute(m, mpp, fin, fdp)
433 ip_t *ip = fin->fin_ip;
445 if (!(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) &&
446 (fdp->fd_type == FRD_DSTLIST)) {
447 bzero(&node, sizeof(node));
448 ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node);
454 return 0; /* no routing table out here */
456 if (fin->fin_out == 0) {
459 (void) ipf_acctpkt(fin, NULL);
461 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
464 (void) ipf_state_check(fin, &pass);
467 switch (ipf_nat_checkout(fin, NULL))
483 printpacket(fin->fin_out, m);
485 #if defined(__sgi) && (IRIX < 60500)
486 (*ifp->if_output)(ifp, (void *)ip, NULL);
488 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
490 (*ifp->if_output)(ifp, (void *)m, NULL, 0);
504 ipfkverbose("- TCP RST sent\n");
510 ipf_send_icmp_err(type, fin, dst)
515 ipfkverbose("- ICMP unreachable sent\n");
529 m_copydata(m, off, len, cp)
534 bcopy((char *)m + off, cp, len);
539 ipfuiomove(buf, len, rwflag, uio)
544 int left, ioc, num, offset;
548 if (rwflag == UIO_READ) {
552 offset = uio->uio_offset;
554 while ((left > 0) && (ioc < uio->uio_iovcnt)) {
555 io = uio->uio_iov + ioc;
559 start = (char *)io->iov_base + offset;
560 if (start > (char *)io->iov_base + io->iov_len) {
561 offset -= io->iov_len;
565 bcopy(buf, start, num);
566 uio->uio_resid -= num;
567 uio->uio_offset += num;
583 static int iss_seq_off = 0;
589 * Compute the base value of the ISS. It is a hash
590 * of (saddr, sport, daddr, dport, secret).
594 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
595 sizeof(fin->fin_fi.fi_src));
596 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
597 sizeof(fin->fin_fi.fi_dst));
598 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
600 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
602 MD5Final(hash, &ctx);
604 memcpy(&newiss, hash, sizeof(newiss));
607 * Now increment our "timer", and add it in to
608 * the computed value.
611 * XXX TCP_ISSINCR too large to use?
613 iss_seq_off += 0x00010000;
614 newiss += iss_seq_off;
619 /* ------------------------------------------------------------------------ */
620 /* Function: ipf_nextipid */
621 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
622 /* Parameters: fin(I) - pointer to packet information */
624 /* Returns the next IPv4 ID to use for this packet. */
625 /* ------------------------------------------------------------------------ */
630 static u_short ipid = 0;
631 ipf_main_softc_t *softc = fin->fin_main_soft;
634 MUTEX_ENTER(&softc->ipf_rw);
635 if (fin->fin_pktnum != 0) {
637 * The -1 is for aligned test results.
639 id = (fin->fin_pktnum - 1) & 0xffff;
643 MUTEX_EXIT(&softc->ipf_rw);
654 if (fin->fin_flx & FI_SHORT)
657 if (ipf_checkl4sum(fin) == -1) {
658 fin->fin_flx |= FI_BAD;
670 if (fin->fin_flx & FI_SHORT)
673 if (ipf_checkl4sum(fin) == -1) {
674 fin->fin_flx |= FI_BAD;
684 * See above for description, except that all addressing is in user space.
687 copyoutptr(softc, src, dst, size)
693 bcopy(dst, (char *)&ca, sizeof(ca));
694 bcopy(src, ca, size);
700 * See above for description, except that all addressing is in user space.
703 copyinptr(src, dst, size)
709 bcopy(src, (char *)&ca, sizeof(ca));
710 bcopy(ca, dst, size);
717 * return the first IP Address associated with an interface
720 ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask)
721 ipf_main_softc_t *softc;
724 i6addr_t *inp, *inpmask;
726 struct ifnet *ifp = ifptr;
728 struct in_ifaddr *ifa;
733 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
734 ifa = ifp->if_addrlist.tqh_first;
737 ifa = (struct in_ifaddr *)ifp->in_ifaddr;
739 ifa = ifp->if_addrlist;
744 struct sockaddr_in *sin, mask;
746 mask.sin_addr.s_addr = 0xffffffff;
749 sin = (struct sockaddr_in *)&ifa->ia_addr;
751 sin = (struct sockaddr_in *)&ifa->ifa_addr;
754 return ipf_ifpfillv4addr(atype, sin, &mask,
755 &inp->in4, &inpmask->in4);
759 struct sockaddr_in6 *sin6, mask;
761 sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
762 ((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff;
763 ((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff;
764 ((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff;
765 ((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff;
766 return ipf_ifpfillv6addr(atype, sin6, &mask,
776 * This function is not meant to be random, rather just produce a
777 * sequence of numbers that isn't linear to show "randomness".
782 static unsigned int last = 0xa5a5a5a5;
783 static int calls = 0;
789 * These are deliberately chosen to ensure that there is some
790 * attempt to test whether the output covers the range in test n18.
843 ipf_pcksum(fin, hlen, sum)
852 slen = fin->fin_plen - hlen;
853 sp = (u_short *)((u_char *)fin->fin_ip + hlen);
855 for (; slen > 1; slen -= 2)
858 sum += ntohs(*(u_char *)sp << 8);
860 sum = (sum & 0xffff) + (sum >> 16);
861 sum2 = (u_short)(~sum & 0xffff);
868 ipf_pullup(m, fin, plen)
873 if (M_LEN(m) >= plen)
877 * Fake ipf_pullup failing
879 fin->fin_reason = FRB_PULLUP;