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 static int no_output __P((struct ifnet *, struct mbuf *,
29 struct sockaddr *, struct rtentry *));
30 static int write_output __P((struct ifnet *, struct mbuf *,
31 struct sockaddr *, struct rtentry *));
34 struct sockaddr_storage ifa_addr;
39 ipf_main_softc_t *softc;
47 ipf_main_softc_t *softc;
54 * Filter ioctl interface.
57 ipfioctl(softc, dev, cmd, data, mode)
58 ipf_main_softc_t *softc;
64 int error = 0, unit = 0, uid;
71 error = ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, NULL);
82 ipf_forgetifp(softc, ifp)
83 ipf_main_softc_t *softc;
86 register frentry_t *f;
88 WRITE_ENTER(&softc->ipf_mutex);
89 for (f = softc->ipf_acct[0][softc->ipf_active]; (f != NULL);
92 f->fr_ifa = (void *)-1;
93 for (f = softc->ipf_acct[1][softc->ipf_active]; (f != NULL);
96 f->fr_ifa = (void *)-1;
97 for (f = softc->ipf_rules[0][softc->ipf_active]; (f != NULL);
100 f->fr_ifa = (void *)-1;
101 for (f = softc->ipf_rules[1][softc->ipf_active]; (f != NULL);
103 if (f->fr_ifa == ifp)
104 f->fr_ifa = (void *)-1;
105 RWLOCK_EXIT(&softc->ipf_mutex);
106 ipf_nat_sync(softc, ifp);
107 ipf_lookup_sync(softc, ifp);
112 no_output(ifp, m, s, rt)
123 write_output(ifp, m, s, rt)
135 ip = MTOD(mb, ip_t *);
137 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
139 sprintf(fname, "/tmp/%s", ifp->if_xname);
141 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
143 fd = open(fname, O_WRONLY|O_APPEND);
148 write(fd, (char *)ip, ntohs(ip->ip_len));
155 ipf_setifpaddr(ifp, addr)
161 #if defined(__NetBSD__) || defined(__FreeBSD__)
162 if (ifp->if_addrlist.tqh_first != NULL)
164 if (ifp->if_addrlist != NULL)
168 ifa = (struct ifaddr *)malloc(sizeof(*ifa));
169 #if defined(__NetBSD__) || defined(__FreeBSD__)
170 ifp->if_addrlist.tqh_first = ifa;
172 ifp->if_addrlist = ifa;
176 struct sockaddr_in *sin;
178 sin = (struct sockaddr_in *)&ifa->ifa_addr;
180 if (index(addr, ':') != NULL) {
181 struct sockaddr_in6 *sin6;
183 sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
184 sin6->sin6_family = AF_INET6;
185 /* Abort if bad address. */
186 switch (inet_pton(AF_INET6, addr, &sin6->sin6_addr))
201 sin->sin_family = AF_INET;
202 sin->sin_addr.s_addr = inet_addr(addr);
203 if (sin->sin_addr.s_addr == 0)
210 get_unit(name, family)
214 struct ifnet *ifp, **ifpp, **old_ifneta;
216 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
225 addr = strchr(name, '=');
229 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
230 if (!strcmp(name, ifp->if_xname)) {
232 ipf_setifpaddr(ifp, addr);
237 char *s, ifname[LIFNAMSIZ+1];
242 addr = strchr(name, '=');
246 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
247 COPYIFNAME(family, ifp, ifname);
248 if (!strcmp(name, ifname)) {
250 ipf_setifpaddr(ifp, addr);
257 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
261 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
270 ifneta = (struct ifnet **)reallocarray(ifneta, nifs + 1,
278 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
279 if (!ifneta[nifs - 1]) {
284 ifp = ifneta[nifs - 1];
286 #if defined(__NetBSD__) || defined(__FreeBSD__)
287 TAILQ_INIT(&ifp->if_addrlist);
289 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
291 (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
293 s = name + strlen(name) - 1;
294 for (; s > name; s--) {
301 if ((s > name) && (*s != 0) && ISDIGIT(*s)) {
302 ifp->if_unit = atoi(s);
303 ifp->if_name = (char *)malloc(s - name + 1);
304 (void) strncpy(ifp->if_name, name, s - name);
305 ifp->if_name[s - name] = '\0';
307 ifp->if_name = strdup(name);
311 ifp->if_output = (void *)no_output;
314 ipf_setifpaddr(ifp, addr);
325 static char ifname[LIFNAMSIZ];
327 #if defined(__NetBSD__) || defined(__FreeBSD__)
328 sprintf(ifname, "%s", ifp->if_xname);
330 if (ifp->if_unit != -1)
331 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
333 strcpy(ifname, ifp->if_name);
343 struct ifnet *ifp, **ifpp;
347 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
349 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
350 ifp->if_output = (void *)write_output;
351 sprintf(fname, "/tmp/%s", ifp->if_xname);
352 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
360 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
361 ifp->if_output = (void *)write_output;
362 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
363 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
374 ipf_fastroute(m, mpp, fin, fdp)
380 ip_t *ip = fin->fin_ip;
392 if (!(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) &&
393 (fdp->fd_type == FRD_DSTLIST)) {
394 bzero(&node, sizeof(node));
395 ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node);
401 return 0; /* no routing table out here */
403 if (fin->fin_out == 0) {
406 (void) ipf_acctpkt(fin, NULL);
408 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
411 (void) ipf_state_check(fin, &pass);
414 switch (ipf_nat_checkout(fin, NULL))
430 printpacket(fin->fin_out, m);
432 (*ifp->if_output)(ifp, (void *)m, NULL, 0);
444 ipfkverbose("- TCP RST sent\n");
450 ipf_send_icmp_err(type, fin, dst)
455 ipfkverbose("- ICMP unreachable sent\n");
469 m_copydata(m, off, len, cp)
474 bcopy((char *)m + off, cp, len);
479 ipfuiomove(buf, len, rwflag, uio)
484 int left, ioc, num, offset;
488 if (rwflag == UIO_READ) {
492 offset = uio->uio_offset;
494 while ((left > 0) && (ioc < uio->uio_iovcnt)) {
495 io = uio->uio_iov + ioc;
499 start = (char *)io->iov_base + offset;
500 if (start > (char *)io->iov_base + io->iov_len) {
501 offset -= io->iov_len;
505 bcopy(buf, start, num);
506 uio->uio_resid -= num;
507 uio->uio_offset += num;
523 static int iss_seq_off = 0;
529 * Compute the base value of the ISS. It is a hash
530 * of (saddr, sport, daddr, dport, secret).
534 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
535 sizeof(fin->fin_fi.fi_src));
536 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
537 sizeof(fin->fin_fi.fi_dst));
538 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
540 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
542 MD5Final(hash, &ctx);
544 memcpy(&newiss, hash, sizeof(newiss));
547 * Now increment our "timer", and add it in to
548 * the computed value.
551 * XXX TCP_ISSINCR too large to use?
553 iss_seq_off += 0x00010000;
554 newiss += iss_seq_off;
559 /* ------------------------------------------------------------------------ */
560 /* Function: ipf_nextipid */
561 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
562 /* Parameters: fin(I) - pointer to packet information */
564 /* Returns the next IPv4 ID to use for this packet. */
565 /* ------------------------------------------------------------------------ */
570 static u_short ipid = 0;
571 ipf_main_softc_t *softc = fin->fin_main_soft;
574 MUTEX_ENTER(&softc->ipf_rw);
575 if (fin->fin_pktnum != 0) {
577 * The -1 is for aligned test results.
579 id = (fin->fin_pktnum - 1) & 0xffff;
583 MUTEX_EXIT(&softc->ipf_rw);
594 if (fin->fin_flx & FI_SHORT)
597 if (ipf_checkl4sum(fin) == -1) {
598 fin->fin_flx |= FI_BAD;
610 if (fin->fin_flx & FI_SHORT)
613 if (ipf_checkl4sum(fin) == -1) {
614 fin->fin_flx |= FI_BAD;
624 * See above for description, except that all addressing is in user space.
627 copyoutptr(softc, src, dst, size)
633 bcopy(dst, (char *)&ca, sizeof(ca));
634 bcopy(src, ca, size);
640 * See above for description, except that all addressing is in user space.
643 copyinptr(src, dst, size)
649 bcopy(src, (char *)&ca, sizeof(ca));
650 bcopy(ca, dst, size);
657 * return the first IP Address associated with an interface
660 ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask)
661 ipf_main_softc_t *softc;
664 i6addr_t *inp, *inpmask;
666 struct ifnet *ifp = ifptr;
669 #if defined(__NetBSD__) || defined(__FreeBSD__)
670 ifa = ifp->if_addrlist.tqh_first;
672 ifa = ifp->if_addrlist;
676 struct sockaddr_in *sin, mask;
678 mask.sin_addr.s_addr = 0xffffffff;
680 sin = (struct sockaddr_in *)&ifa->ifa_addr;
682 return ipf_ifpfillv4addr(atype, sin, &mask,
683 &inp->in4, &inpmask->in4);
687 struct sockaddr_in6 *sin6, mask;
689 sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
690 ((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff;
691 ((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff;
692 ((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff;
693 ((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff;
694 return ipf_ifpfillv6addr(atype, sin6, &mask,
704 * This function is not meant to be random, rather just produce a
705 * sequence of numbers that isn't linear to show "randomness".
710 static unsigned int last = 0xa5a5a5a5;
711 static int calls = 0;
717 * These are deliberately chosen to ensure that there is some
718 * attempt to test whether the output covers the range in test n18.
771 ipf_pcksum(fin, hlen, sum)
780 slen = fin->fin_plen - hlen;
781 sp = (u_short *)((u_char *)fin->fin_ip + hlen);
783 for (; slen > 1; slen -= 2)
786 sum += ntohs(*(u_char *)sp << 8);
788 sum = (sum & 0xffff) + (sum >> 16);
789 sum2 = (u_short)(~sum & 0xffff);
796 ipf_pullup(m, fin, plen)
801 if (M_LEN(m) >= plen)
805 * Fake ipf_pullup failing
807 fin->fin_reason = FRB_PULLUP;