📄 ip_fw.c
字号:
f_prt = f->fw_flg & IP_FW_F_KIND; /* If wildcard, match */ if (f_prt == IP_FW_F_ALL) goto got_match; /* If different, dont match */ if (prt != f_prt) continue; /* ICMP, done */ if (prt == IP_FW_F_ICMP) { if (!icmptype_match(icmp, f)) continue; goto got_match; } /* Check TCP flags and TCP/UDP ports only if packet is not fragment */ if (!(ip->ip_off & IP_OFFMASK)) { /* TCP, a little more checking */ if (prt == IP_FW_F_TCP && (f->fw_tcpf != f->fw_tcpnf) && (!tcpflg_match(tcp, f))) continue; if (!port_match(&f->fw_pts[0], f->fw_nsp, src_port, f->fw_flg & IP_FW_F_SRNG)) continue; if (!port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port, f->fw_flg & IP_FW_F_DRNG)) continue; }got_match: f->fw_pcnt++; f->fw_bcnt+=ip->ip_len; f->timestamp = time.tv_sec; if (f->fw_flg & IP_FW_F_PRN) { if (f->fw_flg & IP_FW_F_ACCEPT) ipfw_report("Allow", f->fw_number, ip, f->fw_pcnt); else if (f->fw_flg & IP_FW_F_COUNT) ipfw_report("Count", f->fw_number, ip, f->fw_pcnt); else ipfw_report("Deny", f->fw_number, ip, f->fw_pcnt); } if (f->fw_flg & IP_FW_F_ACCEPT) return 1; if (f->fw_flg & IP_FW_F_COUNT) continue; break; } /* * Don't icmp outgoing packets at all */ if (f != NULL && !dir) { /* * Do not ICMP reply to icmp packets....:) or to packets * rejected by entry without the special ICMP reply flag. */ if ((f_prt != IP_FW_F_ICMP) && (f->fw_flg & IP_FW_F_ICMPRPL)) { if (f_prt == IP_FW_F_ALL) icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0L, 0); else icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0L, 0); return 0; } } m_freem(m); return 0;}static intadd_entry(chainptr, frwl) struct ip_fw_head *chainptr; struct ip_fw *frwl;{ struct ip_fw *ftmp = 0; struct ip_fw_chain *fwc = 0, *fcp, *fcpl = 0; u_short nbr = 0; int s; fwc = malloc(sizeof *fwc, M_IPFW, M_DONTWAIT); ftmp = malloc(sizeof *ftmp, M_IPFW, M_DONTWAIT); if (!fwc || !ftmp) { dprintf(("ip_fw_ctl: malloc said no\n")); if (fwc) free(fwc, M_IPFW); if (ftmp) free(ftmp, M_IPFW); return (ENOSPC); } bcopy(frwl, ftmp, sizeof(struct ip_fw)); ftmp->fw_pcnt = 0L; ftmp->fw_bcnt = 0L; fwc->rule = ftmp; s = splnet(); if (!chainptr->lh_first) { LIST_INSERT_HEAD(chainptr, fwc, chain); splx(s); return(0); } else if (ftmp->fw_number == (u_short)-1) { if (fwc) free(fwc, M_IPFW); if (ftmp) free(ftmp, M_IPFW); splx(s); return (EINVAL); } /* If entry number is 0, find highest numbered rule and add 100 */ if (ftmp->fw_number == 0) { for (fcp = chainptr->lh_first; fcp; fcp = fcp->chain.le_next) { if (fcp->rule->fw_number != (u_short)-1) nbr = fcp->rule->fw_number; else break; } if (nbr < (u_short)-1 - 100) nbr += 100; ftmp->fw_number = nbr; } /* Got a valid number; now insert it, keeping the list ordered */ for (fcp = chainptr->lh_first; fcp; fcp = fcp->chain.le_next) { if (fcp->rule->fw_number > ftmp->fw_number) { if (fcpl) { LIST_INSERT_AFTER(fcpl, fwc, chain); } else { LIST_INSERT_HEAD(chainptr, fwc, chain); } break; } else { fcpl = fcp; } } splx(s); return (0);}static intdel_entry(chainptr, frwl) struct ip_fw_head *chainptr; struct ip_fw *frwl;{ struct ip_fw_chain *fcp; int s; s = splnet(); fcp = chainptr->lh_first; if (frwl->fw_number != (u_short)-1) { for (; fcp; fcp = fcp->chain.le_next) { if (fcp->rule->fw_number == frwl->fw_number) { LIST_REMOVE(fcp, chain); splx(s); free(fcp->rule, M_IPFW); free(fcp, M_IPFW); return 0; } } } splx(s); return (EINVAL);}static intzero_entry(struct mbuf *m){ struct ip_fw *frwl; struct ip_fw_chain *fcp; int s; if (m) { frwl = check_ipfw_struct(m); if (!frwl) return(EINVAL); } else frwl = NULL; /* * It's possible to insert multiple chain entries with the * same number, so we don't stop after finding the first * match if zeroing a specific entry. */ s = splnet(); for (fcp = ip_fw_chain.lh_first; fcp; fcp = fcp->chain.le_next) if (!frwl || frwl->fw_number == fcp->rule->fw_number) { fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0; fcp->rule->timestamp = 0; } splx(s); return(0);}static struct ip_fw *check_ipfw_struct(m) struct mbuf *m;{ struct ip_fw *frwl; if (m->m_len != sizeof(struct ip_fw)) { dprintf(("ip_fw_ctl: len=%d, want %d\n", m->m_len, sizeof(struct ip_fw))); return (NULL); } frwl = mtod(m, struct ip_fw *); if ((frwl->fw_flg & ~IP_FW_F_MASK) != 0) { dprintf(("ip_fw_ctl: undefined flag bits set (flags=%x)\n", frwl->fw_flg)); return (NULL); } /* If neither In nor Out, then both */ if (!(frwl->fw_flg & (IP_FW_F_IN | IP_FW_F_OUT))) frwl->fw_flg |= IP_FW_F_IN | IP_FW_F_OUT; if ((frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2) { dprintf(("ip_fw_ctl: src range set but n_src_p=%d\n", frwl->fw_nsp)); return (NULL); } if ((frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2) { dprintf(("ip_fw_ctl: dst range set but n_dst_p=%d\n", frwl->fw_ndp)); return (NULL); } if (frwl->fw_nsp + frwl->fw_ndp > IP_FW_MAX_PORTS) { dprintf(("ip_fw_ctl: too many ports (%d+%d)\n", frwl->fw_nsp, frwl->fw_ndp)); return (NULL); } return frwl;}intip_fw_ctl(stage, mm) int stage; struct mbuf **mm;{ int error; struct mbuf *m; if (stage == IP_FW_GET) { struct ip_fw_chain *fcp = ip_fw_chain.lh_first; *mm = m = m_get(M_WAIT, MT_SOOPTS); for (; fcp; fcp = fcp->chain.le_next) { memcpy(m->m_data, fcp->rule, sizeof *(fcp->rule)); m->m_len = sizeof *(fcp->rule); m->m_next = m_get(M_WAIT, MT_SOOPTS); m = m->m_next; m->m_len = 0; } return (0); } m = *mm; /* only allow get calls if secure mode > 2 */ if (securelevel > 2) { if (m) (void)m_free(m); return(EPERM); } if (stage == IP_FW_FLUSH) { while (ip_fw_chain.lh_first != NULL && ip_fw_chain.lh_first->rule->fw_number != (u_short)-1) { struct ip_fw_chain *fcp = ip_fw_chain.lh_first; int s = splnet(); LIST_REMOVE(ip_fw_chain.lh_first, chain); splx(s); free(fcp->rule, M_IPFW); free(fcp, M_IPFW); } if (m) (void)m_free(m); return (0); } if (stage == IP_FW_ZERO) { error = zero_entry(m); if (m) (void)m_free(m); return (error); } if (m == NULL) { printf("ip_fw_ctl: NULL mbuf ptr\n"); return (EINVAL); } if (stage == IP_FW_ADD || stage == IP_FW_DEL) { struct ip_fw *frwl = check_ipfw_struct(m); if (!frwl) { if (m) (void)m_free(m); return (EINVAL); } if (stage == IP_FW_ADD) error = add_entry(&ip_fw_chain, frwl); else error = del_entry(&ip_fw_chain, frwl); if (m) (void)m_free(m); return error; } dprintf(("ip_fw_ctl: unknown request %d\n", stage)); if (m) (void)m_free(m); return (EINVAL);}voidip_fw_init(void){ struct ip_fw deny; ip_fw_chk_ptr = ip_fw_chk; ip_fw_ctl_ptr = ip_fw_ctl; LIST_INIT(&ip_fw_chain); bzero(&deny, sizeof deny); deny.fw_flg = IP_FW_F_ALL; deny.fw_number = (u_short)-1; add_entry(&ip_fw_chain, &deny); printf("IP firewall initialized, ");#ifndef IPFIREWALL_VERBOSE printf("logging disabled\n");#else if (fw_verbose_limit == 0) printf("unlimited logging\n"); else printf("logging limited to %d packets/entry\n", fw_verbose_limit);#endif}#ifdef ACTUALLY_LKM_NOT_KERNEL#include <sys/conf.h>#include <sys/exec.h>#include <sys/sysent.h>#include <sys/lkm.h>static int (*old_chk_ptr)(struct mbuf *, struct ip *, struct ifnet *, int dir);static int (*old_ctl_ptr)(int, struct mbuf **);static intipfw_load(struct lkm_table *lkmtp, int cmd){ int s=splnet(); old_chk_ptr = ip_fw_chk_ptr; old_ctl_ptr = ip_fw_ctl_ptr; ip_fw_init(); splx(s); return 0;}static intipfw_unload(struct lkm_table *lkmtp, int cmd){ int s=splnet(); ip_fw_chk_ptr = old_chk_ptr; ip_fw_ctl_ptr = old_ctl_ptr; while (ip_fw_chain.lh_first != NULL) { struct ip_fw_chain *fcp = ip_fw_chain.lh_first; LIST_REMOVE(ip_fw_chain.lh_first, chain); free(fcp->rule, M_IPFW); free(fcp, M_IPFW); } splx(s); printf("IP firewall unloaded\n"); return 0;}MOD_MISC("ipfw_mod")intipfw_mod(struct lkm_table *lkmtp, int cmd, int ver){ DISPATCH(lkmtp, cmd, ver, ipfw_load, ipfw_unload, nosys);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -