?? ipchains_core.c
字號:
if ((chain = find_label(new->fwt_label)) == NULL) ret = ENOENT; else { struct sk_buff *tmp_skb; int hdrlen; hdrlen = sizeof(struct ip_fwpkt) - sizeof(struct in_addr) - IFNAMSIZ; ip = &(new->fwt_packet.fwp_iph); /* Fix this one up by hand, who knows how many * tools will break if we start to barf on this. */ if (ntohs(ip->tot_len) > hdrlen) ip->tot_len = htons(hdrlen); if (ip->ihl != sizeof(struct iphdr) / sizeof(u32)) { duprintf("ip_fw_ctl: ip->ihl=%d, want %d\n", ip->ihl, sizeof(struct iphdr) / sizeof(u32)); ret = EINVAL; } else if ((tmp_skb = alloc_skb(hdrlen, GFP_ATOMIC)) == NULL) { duprintf("ip_fw_ctl: tmp_skb alloc failure\n"); ret = EFAULT; } else { skb_reserve(tmp_skb, hdrlen); skb_push(tmp_skb, hdrlen); memcpy(tmp_skb->data, ip, hdrlen); tmp_skb->nh.raw = (unsigned char *) tmp_skb->data; ret = ip_fw_check(new->fwt_packet.fwp_vianame, NULL, chain, &tmp_skb, SLOT_NUMBER(), 1); kfree_skb(tmp_skb); 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){ 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; } } }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 *arg, struct sk_buff **pskb){ return ip_fw_check(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 *arg, struct sk_buff **pskb){ /* Locally generated bogus packets by root. <SIGH>. */ if ((*pskb)->len < sizeof(struct iphdr) || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) return FW_ACCEPT; return ip_fw_check(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 *arg, struct sk_buff **pskb){ return ip_fw_check(dev->name, arg, IP_FW_FORWARD_CHAIN, pskb, SLOT_NUMBER(), 0);}struct firewall_ops ipfw_ops = { .fw_forward = ipfw_forward_check, .fw_input = ipfw_input_check, .fw_output = ipfw_output_check,};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->sk_socket); cleanup_nothing:#endif return ret;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -