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 *));
50 ipf_main_softc_t *softc;
58 ipf_main_softc_t *softc;
65 * Filter ioctl interface.
68 ipfioctl(softc, dev, cmd, data, mode)
69 ipf_main_softc_t *softc;
75 int error = 0, unit = 0, uid;
82 error = ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, NULL);
93 ipf_forgetifp(softc, ifp)
94 ipf_main_softc_t *softc;
97 register frentry_t *f;
99 WRITE_ENTER(&softc->ipf_mutex);
100 for (f = softc->ipf_acct[0][softc->ipf_active]; (f != NULL);
102 if (f->fr_ifa == ifp)
103 f->fr_ifa = (void *)-1;
104 for (f = softc->ipf_acct[1][softc->ipf_active]; (f != NULL);
106 if (f->fr_ifa == ifp)
107 f->fr_ifa = (void *)-1;
108 for (f = softc->ipf_rules[0][softc->ipf_active]; (f != NULL);
110 if (f->fr_ifa == ifp)
111 f->fr_ifa = (void *)-1;
112 for (f = softc->ipf_rules[1][softc->ipf_active]; (f != NULL);
114 if (f->fr_ifa == ifp)
115 f->fr_ifa = (void *)-1;
116 RWLOCK_EXIT(&softc->ipf_mutex);
117 ipf_nat_sync(softc, ifp);
118 ipf_lookup_sync(softc, ifp);
123 #if defined(__sgi) && (IRIX < 60500)
127 no_output (ifp, m, s, rt, cp)
130 no_output(ifp, m, s, rt)
143 #if defined(__sgi) && (IRIX < 60500)
144 write_output(ifp, m, s)
147 write_output (ifp, m, s, rt, cp)
150 write_output(ifp, m, s, rt)
164 ip = MTOD(mb, ip_t *);
166 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
167 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
168 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
169 sprintf(fname, "/tmp/%s", ifp->if_xname);
171 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
173 fd = open(fname, O_WRONLY|O_APPEND);
178 write(fd, (char *)ip, ntohs(ip->ip_len));
185 ipf_setifpaddr(ifp, addr)
190 struct in_ifaddr *ifa;
195 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
196 if (ifp->if_addrlist.tqh_first != NULL)
199 if (ifp->in_ifaddr != NULL)
201 if (ifp->if_addrlist != NULL)
206 ifa = (struct ifaddr *)malloc(sizeof(*ifa));
207 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
208 ifp->if_addrlist.tqh_first = ifa;
211 ifp->in_ifaddr = ifa;
213 ifp->if_addrlist = ifa;
218 struct sockaddr_in *sin;
221 sin = (struct sockaddr_in *)&ifa->ia_addr;
223 sin = (struct sockaddr_in *)&ifa->ifa_addr;
226 if (index(addr, ':') != NULL) {
227 struct sockaddr_in6 *sin6;
229 sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
230 sin6->sin6_family = AF_INET6;
231 /* Abort if bad address. */
232 switch (inet_pton(AF_INET6, addr, &sin6->sin6_addr))
247 sin->sin_family = AF_INET;
248 sin->sin_addr.s_addr = inet_addr(addr);
249 if (sin->sin_addr.s_addr == 0)
256 get_unit(name, family)
260 struct ifnet *ifp, **ifpp, **old_ifneta;
262 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
263 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
264 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
272 addr = strchr(name, '=');
276 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
277 if (!strcmp(name, ifp->if_xname)) {
279 ipf_setifpaddr(ifp, addr);
284 char *s, ifname[LIFNAMSIZ+1];
289 addr = strchr(name, '=');
293 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
294 COPYIFNAME(family, ifp, ifname);
295 if (!strcmp(name, ifname)) {
297 ipf_setifpaddr(ifp, addr);
304 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
308 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
317 ifneta = (struct ifnet **)realloc(ifneta,
318 (nifs + 1) * sizeof(ifp));
325 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
326 if (!ifneta[nifs - 1]) {
331 ifp = ifneta[nifs - 1];
333 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
334 TAILQ_INIT(&ifp->if_addrlist);
336 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
337 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
338 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
339 (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
341 s = name + strlen(name) - 1;
342 for (; s > name; s--) {
349 if ((s > name) && (*s != 0) && ISDIGIT(*s)) {
350 ifp->if_unit = atoi(s);
351 ifp->if_name = (char *)malloc(s - name + 1);
352 (void) strncpy(ifp->if_name, name, s - name);
353 ifp->if_name[s - name] = '\0';
355 ifp->if_name = strdup(name);
359 ifp->if_output = (void *)no_output;
362 ipf_setifpaddr(ifp, addr);
373 static char ifname[LIFNAMSIZ];
375 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \
376 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
377 sprintf(ifname, "%s", ifp->if_xname);
379 if (ifp->if_unit != -1)
380 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
382 strcpy(ifname, ifp->if_name);
392 struct ifnet *ifp, **ifpp;
396 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
397 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
398 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
399 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
400 ifp->if_output = (void *)write_output;
401 sprintf(fname, "/tmp/%s", ifp->if_xname);
402 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
410 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
411 ifp->if_output = (void *)write_output;
412 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
413 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
424 ipf_fastroute(m, mpp, fin, fdp)
430 ip_t *ip = fin->fin_ip;
442 if (!(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) &&
443 (fdp->fd_type == FRD_DSTLIST)) {
444 bzero(&node, sizeof(node));
445 ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node);
451 return 0; /* no routing table out here */
453 if (fin->fin_out == 0) {
456 (void) ipf_acctpkt(fin, NULL);
458 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
461 (void) ipf_state_check(fin, &pass);
464 switch (ipf_nat_checkout(fin, NULL))
480 printpacket(fin->fin_out, m);
482 (*ifp->if_output)(ifp, (void *)m, NULL, 0);
494 ipfkverbose("- TCP RST sent\n");
500 ipf_send_icmp_err(type, fin, dst)
505 ipfkverbose("- ICMP unreachable sent\n");
519 m_copydata(m, off, len, cp)
524 bcopy((char *)m + off, cp, len);
529 ipfuiomove(buf, len, rwflag, uio)
534 int left, ioc, num, offset;
538 if (rwflag == UIO_READ) {
542 offset = uio->uio_offset;
544 while ((left > 0) && (ioc < uio->uio_iovcnt)) {
545 io = uio->uio_iov + ioc;
549 start = (char *)io->iov_base + offset;
550 if (start > (char *)io->iov_base + io->iov_len) {
551 offset -= io->iov_len;
555 bcopy(buf, start, num);
556 uio->uio_resid -= num;
557 uio->uio_offset += num;
573 static int iss_seq_off = 0;
579 * Compute the base value of the ISS. It is a hash
580 * of (saddr, sport, daddr, dport, secret).
584 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
585 sizeof(fin->fin_fi.fi_src));
586 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
587 sizeof(fin->fin_fi.fi_dst));
588 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
590 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
592 MD5Final(hash, &ctx);
594 memcpy(&newiss, hash, sizeof(newiss));
597 * Now increment our "timer", and add it in to
598 * the computed value.
601 * XXX TCP_ISSINCR too large to use?
603 iss_seq_off += 0x00010000;
604 newiss += iss_seq_off;
609 /* ------------------------------------------------------------------------ */
610 /* Function: ipf_nextipid */
611 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
612 /* Parameters: fin(I) - pointer to packet information */
614 /* Returns the next IPv4 ID to use for this packet. */
615 /* ------------------------------------------------------------------------ */
620 static u_short ipid = 0;
621 ipf_main_softc_t *softc = fin->fin_main_soft;
624 MUTEX_ENTER(&softc->ipf_rw);
625 if (fin->fin_pktnum != 0) {
627 * The -1 is for aligned test results.
629 id = (fin->fin_pktnum - 1) & 0xffff;
633 MUTEX_EXIT(&softc->ipf_rw);
644 if (fin->fin_flx & FI_SHORT)
647 if (ipf_checkl4sum(fin) == -1) {
648 fin->fin_flx |= FI_BAD;
660 if (fin->fin_flx & FI_SHORT)
663 if (ipf_checkl4sum(fin) == -1) {
664 fin->fin_flx |= FI_BAD;
674 * See above for description, except that all addressing is in user space.
677 copyoutptr(softc, src, dst, size)
683 bcopy(dst, (char *)&ca, sizeof(ca));
684 bcopy(src, ca, size);
690 * See above for description, except that all addressing is in user space.
693 copyinptr(src, dst, size)
699 bcopy(src, (char *)&ca, sizeof(ca));
700 bcopy(ca, dst, size);
707 * return the first IP Address associated with an interface
710 ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask)
711 ipf_main_softc_t *softc;
714 i6addr_t *inp, *inpmask;
716 struct ifnet *ifp = ifptr;
718 struct in_ifaddr *ifa;
723 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
724 ifa = ifp->if_addrlist.tqh_first;
727 ifa = (struct in_ifaddr *)ifp->in_ifaddr;
729 ifa = ifp->if_addrlist;
734 struct sockaddr_in *sin, mask;
736 mask.sin_addr.s_addr = 0xffffffff;
739 sin = (struct sockaddr_in *)&ifa->ia_addr;
741 sin = (struct sockaddr_in *)&ifa->ifa_addr;
744 return ipf_ifpfillv4addr(atype, sin, &mask,
745 &inp->in4, &inpmask->in4);
749 struct sockaddr_in6 *sin6, mask;
751 sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
752 ((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff;
753 ((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff;
754 ((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff;
755 ((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff;
756 return ipf_ifpfillv6addr(atype, sin6, &mask,
766 * This function is not meant to be random, rather just produce a
767 * sequence of numbers that isn't linear to show "randomness".
772 static unsigned int last = 0xa5a5a5a5;
773 static int calls = 0;
779 * These are deliberately chosen to ensure that there is some
780 * attempt to test whether the output covers the range in test n18.
833 ipf_pcksum(fin, hlen, sum)
842 slen = fin->fin_plen - hlen;
843 sp = (u_short *)((u_char *)fin->fin_ip + hlen);
845 for (; slen > 1; slen -= 2)
848 sum += ntohs(*(u_char *)sp << 8);
850 sum = (sum & 0xffff) + (sum >> 16);
851 sum2 = (u_short)(~sum & 0xffff);
858 ipf_pullup(m, fin, plen)
863 if (M_LEN(m) >= plen)
867 * Fake ipf_pullup failing
869 fin->fin_reason = FRB_PULLUP;