📄 ipchains_core.c
字号:
} else { ret = ip_fw_check(ip, new->fwt_packet.fwp_vianame, NULL, chain, NULL, SLOT_NUMBER(), 1); switch (ret) { case FW_ACCEPT: ret = 0; break; case FW_REDIRECT: ret = ECONNABORTED; break; case FW_MASQUERADE: ret = ECONNRESET; break; case FW_REJECT: ret = ECONNREFUSED; break; /* Hack to help diag; these only get returned when testing. */ case FW_SKIP+1: ret = ELOOP; break; case FW_SKIP: ret = ENFILE; break; default: /* FW_BLOCK */ ret = ETIMEDOUT; break; } } } FWC_READ_UNLOCK(&ip_fw_lock); return ret; } case IP_FW_MASQ_TIMEOUTS: { ret = ip_fw_masq_timeouts(m, len); } break; case IP_FW_REPLACE: { struct ip_fwkernel *ip_fwkern; struct ip_fwnew *new = m; if (len != sizeof(struct ip_fwnew) || !check_label(new->fwn_label)) ret = EINVAL; else if ((chain = find_label(new->fwn_label)) == NULL) ret = ENOENT; else if ((ip_fwkern = convert_ipfw(&new->fwn_rule, &ret)) != NULL) ret = replace_in_chain(chain, ip_fwkern, new->fwn_rulenum); } break; case IP_FW_APPEND: { struct ip_fwchange *new = m; struct ip_fwkernel *ip_fwkern; if (len != sizeof(struct ip_fwchange) || !check_label(new->fwc_label)) ret = EINVAL; else if ((chain = find_label(new->fwc_label)) == NULL) ret = ENOENT; else if ((ip_fwkern = convert_ipfw(&new->fwc_rule, &ret)) != NULL) ret = append_to_chain(chain, ip_fwkern); } break; case IP_FW_INSERT: { struct ip_fwkernel *ip_fwkern; struct ip_fwnew *new = m; if (len != sizeof(struct ip_fwnew) || !check_label(new->fwn_label)) ret = EINVAL; else if ((chain = find_label(new->fwn_label)) == NULL) ret = ENOENT; else if ((ip_fwkern = convert_ipfw(&new->fwn_rule, &ret)) != NULL) ret = insert_in_chain(chain, ip_fwkern, new->fwn_rulenum); } break; case IP_FW_DELETE: { struct ip_fwchange *new = m; struct ip_fwkernel *ip_fwkern; if (len != sizeof(struct ip_fwchange) || !check_label(new->fwc_label)) ret = EINVAL; else if ((chain = find_label(new->fwc_label)) == NULL) ret = ENOENT; else if ((ip_fwkern = convert_ipfw(&new->fwc_rule, &ret)) != NULL) { ret = del_rule_from_chain(chain, ip_fwkern); kfree(ip_fwkern); } } break; case IP_FW_DELETE_NUM: { struct ip_fwdelnum *new = m; if (len != sizeof(struct ip_fwdelnum) || !check_label(new->fwd_label)) ret = EINVAL; else if ((chain = find_label(new->fwd_label)) == NULL) ret = ENOENT; else ret = del_num_from_chain(chain, new->fwd_rulenum); } break; case IP_FW_CREATECHAIN: { if (len != sizeof(ip_chainlabel)) { duprintf("create_chain: bad size %i\n", len); ret = EINVAL; } else ret = create_chain(m); } break; case IP_FW_DELETECHAIN: { if (len != sizeof(ip_chainlabel)) { duprintf("delete_chain: bad size %i\n", len); ret = EINVAL; } else ret = del_chain(m); } break; case IP_FW_POLICY: { struct ip_fwpolicy *new = m; if (len != sizeof(struct ip_fwpolicy) || !check_label(new->fwp_label)) ret = EINVAL; else if ((chain = find_label(new->fwp_label)) == NULL) ret = ENOENT; else if (chain != IP_FW_INPUT_CHAIN && chain != IP_FW_FORWARD_CHAIN && chain != IP_FW_OUTPUT_CHAIN) { duprintf("change_policy: can't change policy on user" " defined chain.\n"); ret = EINVAL; } else { int pol = FW_SKIP; find_special(new->fwp_policy, &pol); switch(pol) { case FW_MASQUERADE: if (chain != IP_FW_FORWARD_CHAIN) { ret = EINVAL; break; } /* Fall thru... */ case FW_BLOCK: case FW_ACCEPT: case FW_REJECT: ret = change_policy(chain, pol); break; default: duprintf("change_policy: bad policy `%s'\n", new->fwp_policy); ret = EINVAL; } } break; } default: duprintf("ip_fw_ctl: unknown request %d\n",cmd); ret = ENOPROTOOPT; } FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags); return ret;}/* Returns bytes used - doesn't NUL terminate */static int dump_rule(char *buffer, const char *chainlabel, const struct ip_fwkernel *rule){ int len; unsigned int i; __u64 packets = 0, bytes = 0; FWC_HAVE_LOCK(fwc_wlocks); for (i = 0; i < NUM_SLOTS; i++) { packets += rule->counters[i].pcnt; bytes += rule->counters[i].bcnt; } len=sprintf(buffer, "%9s " /* Chain name */ "%08X/%08X->%08X/%08X " /* Source & Destination IPs */ "%.16s " /* Interface */ "%X %X " /* fw_flg and fw_invflg fields */ "%u " /* Protocol */ "%-9u %-9u %-9u %-9u " /* Packet & byte counters */ "%u-%u %u-%u " /* Source & Dest port ranges */ "A%02X X%02X " /* TOS and and xor masks */ "%08X " /* Redirection port */ "%u " /* fw_mark field */ "%u " /* output size */ "%9s\n", /* Target */ chainlabel, ntohl(rule->ipfw.fw_src.s_addr), ntohl(rule->ipfw.fw_smsk.s_addr), ntohl(rule->ipfw.fw_dst.s_addr), ntohl(rule->ipfw.fw_dmsk.s_addr), (rule->ipfw.fw_vianame)[0] ? rule->ipfw.fw_vianame : "-", rule->ipfw.fw_flg, rule->ipfw.fw_invflg, rule->ipfw.fw_proto, (__u32)(packets >> 32), (__u32)packets, (__u32)(bytes >> 32), (__u32)bytes, rule->ipfw.fw_spts[0], rule->ipfw.fw_spts[1], rule->ipfw.fw_dpts[0], rule->ipfw.fw_dpts[1], rule->ipfw.fw_tosand, rule->ipfw.fw_tosxor, rule->ipfw.fw_redirpt, rule->ipfw.fw_mark, rule->ipfw.fw_outputsize, branchname(rule->branch,rule->simplebranch)); duprintf("dump_rule: %i bytes done.\n", len); return len;}/* File offset is actually in records, not bytes. */static int ip_chain_procinfo(char *buffer, char **start, off_t offset, int length#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29) , int reset#endif ){#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29) /* FIXME: No more `atomic' read and reset. Wonderful 8-( --RR */ int reset = 0;#endif struct ip_chain *i; struct ip_fwkernel *j = ip_fw_chains->chain; unsigned long flags; int len = 0; int last_len = 0; off_t upto = 0; duprintf("Offset starts at %lu\n", offset); duprintf("ip_fw_chains is 0x%0lX\n", (unsigned long int)ip_fw_chains); /* Need a write lock to lock out ``readers'' which update counters. */ FWC_WRITE_LOCK_IRQ(&ip_fw_lock, flags); for (i = ip_fw_chains; i; i = i->next) { for (j = i->chain; j; j = j->next) { if (upto == offset) break; duprintf("Skipping rule in chain `%s'\n", i->label); upto++; } if (upto == offset) break; } /* Don't init j first time, or once i = NULL */ for (; i; (void)((i = i->next) && (j = i->chain))) { duprintf("Dumping chain `%s'\n", i->label); for (; j; j = j->next, upto++, last_len = len) { len += dump_rule(buffer+len, i->label, j); if (len > length) { duprintf("Dumped to %i (past %i). " "Moving back to %i.\n", len, length, last_len); len = last_len; goto outside; } else if (reset) memset(j->counters, 0, sizeof(struct ip_counters)*NUM_SLOTS); } }outside: FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags); buffer[len] = '\0'; duprintf("ip_chain_procinfo: Length = %i (of %i). Offset = %li.\n", len, length, upto); /* `start' hack - see fs/proc/generic.c line ~165 */ *start=(char *)((unsigned int)upto-offset); return len;}static int ip_chain_name_procinfo(char *buffer, char **start, off_t offset, int length){ struct ip_chain *i; int len = 0,last_len = 0; off_t pos = 0,begin = 0; unsigned long flags; /* Need a write lock to lock out ``readers'' which update counters. */ FWC_WRITE_LOCK_IRQ(&ip_fw_lock, flags); for (i = ip_fw_chains; i; i = i->next) { unsigned int j; __u32 packetsHi = 0, packetsLo = 0, bytesHi = 0, bytesLo = 0; for (j = 0; j < NUM_SLOTS; j++) { packetsLo += i->reent[j].counters.pcnt & 0xFFFFFFFF; packetsHi += ((i->reent[j].counters.pcnt >> 32) & 0xFFFFFFFF); bytesLo += i->reent[j].counters.bcnt & 0xFFFFFFFF; bytesHi += ((i->reent[j].counters.bcnt >> 32) & 0xFFFFFFFF); } /* print the label and the policy */ len+=sprintf(buffer+len,"%s %s %i %u %u %u %u\n", i->label,branchname(NULL, i->policy),i->refcount, packetsHi, packetsLo, bytesHi, bytesLo); pos=begin+len; if(pos<offset) { len=0; begin=pos; } else if(pos>offset+length) { len = last_len; break; } last_len = len; } FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags); *start = buffer+(offset-begin); len-=(offset-begin); if(len>length) len=length; return len;}/* * Interface to the generic firewall chains. */int ipfw_input_check(struct firewall_ops *this, int pf, struct net_device *dev, void *phdr, void *arg, struct sk_buff **pskb){ return ip_fw_check(phdr, dev->name, arg, IP_FW_INPUT_CHAIN, *pskb, SLOT_NUMBER(), 0);}int ipfw_output_check(struct firewall_ops *this, int pf, struct net_device *dev, void *phdr, void *arg, struct sk_buff **pskb){ /* Locally generated bogus packets by root. <SIGH>. */ if (((struct iphdr *)phdr)->ihl * 4 < sizeof(struct iphdr) || (*pskb)->len < sizeof(struct iphdr)) return FW_ACCEPT; return ip_fw_check(phdr, dev->name, arg, IP_FW_OUTPUT_CHAIN, *pskb, SLOT_NUMBER(), 0);}int ipfw_forward_check(struct firewall_ops *this, int pf, struct net_device *dev, void *phdr, void *arg, struct sk_buff **pskb){ return ip_fw_check(phdr, dev->name, arg, IP_FW_FORWARD_CHAIN, *pskb, SLOT_NUMBER(), 0);}struct firewall_ops ipfw_ops={ NULL, ipfw_forward_check, ipfw_input_check, ipfw_output_check, NULL, NULL};int ipfw_init_or_cleanup(int init){ struct proc_dir_entry *proc; int ret = 0; unsigned long flags; if (!init) goto cleanup;#ifdef DEBUG_IP_FIREWALL_LOCKING fwc_wlocks = fwc_rlocks = 0;#endif#if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE) ipfwsk = netlink_kernel_create(NETLINK_FIREWALL, NULL); if (ipfwsk == NULL) goto cleanup_nothing;#endif ret = register_firewall(PF_INET, &ipfw_ops); if (ret < 0) goto cleanup_netlink; proc = proc_net_create(IP_FW_PROC_CHAINS, S_IFREG | S_IRUSR | S_IWUSR, ip_chain_procinfo); if (proc) proc->owner = THIS_MODULE; proc = proc_net_create(IP_FW_PROC_CHAIN_NAMES, S_IFREG | S_IRUSR | S_IWUSR, ip_chain_name_procinfo); if (proc) proc->owner = THIS_MODULE; IP_FW_INPUT_CHAIN = ip_init_chain(IP_FW_LABEL_INPUT, 1, FW_ACCEPT); IP_FW_FORWARD_CHAIN = ip_init_chain(IP_FW_LABEL_FORWARD, 1, FW_ACCEPT); IP_FW_OUTPUT_CHAIN = ip_init_chain(IP_FW_LABEL_OUTPUT, 1, FW_ACCEPT); return ret; cleanup: unregister_firewall(PF_INET, &ipfw_ops); FWC_WRITE_LOCK_IRQ(&ip_fw_lock, flags); while (ip_fw_chains) { struct ip_chain *next = ip_fw_chains->next; clear_fw_chain(ip_fw_chains); kfree(ip_fw_chains); ip_fw_chains = next; } FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags); proc_net_remove(IP_FW_PROC_CHAINS); proc_net_remove(IP_FW_PROC_CHAIN_NAMES); cleanup_netlink:#if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE) sock_release(ipfwsk->socket); cleanup_nothing:#endif return ret;}MODULE_LICENSE("BSD without advertisement clause");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -