📄 ip_masq_mfw.c
字号:
h = list_entry(e, struct ip_masq_mfw_host, list); pos += 64; if (pos <= offset) { len = 0; continue; } sprintf(temp,"0x%x > %08lX %5u %5d %5d", h->fwmark, ntohl(h->addr), ntohs(h->port), atomic_read(&h->pref_cnt), h->pref); len += sprintf(buffer+len, "%-63s\n", temp); if(len >= length) { read_unlock_bh(&mfw->lock); read_unlock(&mfw_lock); goto done; } } read_unlock_bh(&mfw->lock); } read_unlock(&mfw_lock); }done: if (len) { begin = len - (pos - offset); *start = buffer + begin; len -= begin; } if(len>length) len = length; MOD_DEC_USE_COUNT; return len;}static struct proc_dir_entry mfw_proc_entry = {/* 0, 0, NULL", */ 0, 3, "mfw", S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_net_inode_operations, mfw_procinfo};#define proc_ent &mfw_proc_entry#else /* !CONFIG_PROC_FS */#define proc_ent NULL#endifstatic void mfw_flush(void){ struct ip_masq_mfw *mfw, *local_table[IP_MASQ_MFW_HSIZE]; struct ip_masq_mfw_host *h; struct ip_masq_mfw *mfw_next; int idx; struct list_head *l,*e; write_lock_bh(&mfw_lock); memcpy(local_table, ip_masq_mfw_table, sizeof ip_masq_mfw_table); memset(ip_masq_mfw_table, 0, sizeof ip_masq_mfw_table); write_unlock_bh(&mfw_lock); /* * For every hash table row ... */ for(idx=0;idx<IP_MASQ_MFW_HSIZE;idx++) { /* * For every m-entry in row ... */ for(mfw=local_table[idx];mfw;mfw=mfw_next) { /* * For every m.host in m-entry ... */ l=&mfw->hosts; while((e=l->next) != l) { h = list_entry(e, struct ip_masq_mfw_host, list); atomic_dec(&mfw->nhosts); list_del(&h->list); kfree_s(h, sizeof(*h)); MOD_DEC_USE_COUNT; } if (atomic_read(&mfw->nhosts)) { IP_MASQ_ERR("mfw_flush(): after flushing row nhosts=%d\n", atomic_read(&mfw->nhosts)); } mfw_next = mfw->next; kfree_s(mfw, sizeof(*mfw)); MOD_DEC_USE_COUNT; ip_masq_mod_dec_nent(mmod_self); } }}/* * User space control entry point */static int mfw_ctl(int optname, struct ip_masq_ctl *mctl, int optlen){ struct ip_mfw_user *mu = &mctl->u.mfw_user; struct ip_masq_mfw *mfw; int ret = EINVAL; int arglen = optlen - IP_MASQ_CTL_BSIZE; int cmd; IP_MASQ_DEBUG(1-debug, "ip_masq_user_ctl(len=%d/%d|%d/%d)\n", arglen, sizeof (*mu), optlen, sizeof (*mctl)); /* * checks ... */ if (arglen != sizeof(*mu) && optlen != sizeof(*mctl)) return -EINVAL; /* * Don't trust the lusers - plenty of error checking! */ cmd = mctl->m_cmd; IP_MASQ_DEBUG(1-debug, "ip_masq_mfw_ctl(cmd=%d, fwmark=%d)\n", cmd, mu->fwmark); switch(cmd) { case IP_MASQ_CMD_NONE: return 0; case IP_MASQ_CMD_FLUSH: break; case IP_MASQ_CMD_ADD: case IP_MASQ_CMD_INSERT: case IP_MASQ_CMD_SET: if (mu->fwmark == 0) { IP_MASQ_DEBUG(1-debug, "invalid fwmark==0\n"); return -EINVAL; } if (mu->pref < 0) { IP_MASQ_DEBUG(1-debug, "invalid pref==%d\n", mu->pref); return -EINVAL; } break; } ret = -EINVAL; switch(cmd) { case IP_MASQ_CMD_ADD: case IP_MASQ_CMD_INSERT: if (!mu->raddr) { IP_MASQ_DEBUG(0-debug, "ip_masq_mfw_ctl(ADD): invalid redirect 0x%x:%d\n", mu->raddr, mu->rport); goto out; } /* * Cannot just use mfw_lock because below * are allocations that can sleep; so * to assure "new entry" atomic creation * I use a semaphore. * */ down(&mfw_sema); read_lock(&mfw_lock); mfw = __mfw_get(mu->fwmark); read_unlock(&mfw_lock); /* * If first host, create m-entry */ if (mfw == NULL) { mfw = mfw_new(mu->fwmark); if (mfw == NULL) ret = -ENOMEM; } if (mfw) { /* * Put m.host in m-entry. */ ret = mfw_addhost(mfw, mu, cmd == IP_MASQ_CMD_ADD); /* * If first host, link m-entry to hash table. * Already protected by global lock. */ if (ret == 0 && atomic_read(&mfw->nhosts) == 1) { write_lock_bh(&mfw_lock); __mfw_add(mfw); write_unlock_bh(&mfw_lock); } if (atomic_read(&mfw->nhosts) == 0) { mfw_destroy(mfw); } } up(&mfw_sema); break; case IP_MASQ_CMD_DEL: down(&mfw_sema); read_lock(&mfw_lock); mfw = __mfw_get(mu->fwmark); read_unlock(&mfw_lock); if (mfw) { ret = mfw_delhost(mfw, mu); /* * Last lease will free * XXX check logic XXX */ if (atomic_read(&mfw->nhosts) == 0) { write_lock_bh(&mfw_lock); __mfw_del(mfw); write_unlock_bh(&mfw_lock); mfw_destroy(mfw); } } else ret = -ESRCH; up(&mfw_sema); break; case IP_MASQ_CMD_FLUSH: down(&mfw_sema); mfw_flush(); up(&mfw_sema); ret = 0; break; case IP_MASQ_CMD_SET: /* * No need to semaphorize here, main list is not * modified. */ read_lock(&mfw_lock); mfw = __mfw_get(mu->fwmark); if (mfw) { write_lock_bh(&mfw->lock); if (mu->flags & IP_MASQ_MFW_SCHED) { struct ip_masq_mfw_host *h; if ((h=__mfw_sched(mfw, 1))) { mfw_host_to_user(h, mu); ret = 0; } } else { ret = __mfw_edithost(mfw, mu); } write_unlock_bh(&mfw->lock); } read_unlock(&mfw_lock); break; }out: return ret;}/* * Module stubs called from ip_masq core module */ /* * Input rule stub, called very early for each incoming packet, * to see if this module has "interest" in packet. */static int mfw_in_rule(const struct sk_buff *skb, const struct iphdr *iph){ int val; read_lock(&mfw_lock); val = ( __mfw_get(skb->fwmark) != 0); read_unlock(&mfw_lock); return val;}/* * Input-create stub, called to allow "custom" masq creation */static struct ip_masq * mfw_in_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr){ union ip_masq_tphdr tph; struct ip_masq *ms = NULL; struct ip_masq_mfw_host *h = NULL; tph.raw = (char*) iph + iph->ihl * 4; switch (iph->protocol) { case IPPROTO_TCP: /* * Only open TCP tunnel if SYN+!ACK packet */ if (!tph.th->syn || tph.th->ack) return NULL; case IPPROTO_UDP: break; default: return NULL; } /* * If no entry exists in the masquerading table * and the port is involved * in port forwarding, create a new masq entry */ if ((h=mfw_lookup(skb->fwmark))) { ms = ip_masq_new(iph->protocol, iph->daddr, tph.portp[1], /* if no redir-port, use packet dest port */ h->addr, h->port? h->port : tph.portp[1], iph->saddr, tph.portp[0], 0); if (ms != NULL) ip_masq_listen(ms); } return ms;}#define mfw_in_update NULL#define mfw_out_rule NULL#define mfw_out_create NULL#define mfw_out_update NULLstatic struct ip_masq_mod mfw_mod = { NULL, /* next */ NULL, /* next_reg */ "mfw", /* name */ ATOMIC_INIT(0), /* nent */ ATOMIC_INIT(0), /* refcnt */ proc_ent, mfw_ctl, NULL, /* masq_mod_init */ NULL, /* masq_mod_done */ mfw_in_rule, mfw_in_update, mfw_in_create, mfw_out_rule, mfw_out_update, mfw_out_create,};__initfunc(int ip_mfw_init(void)){ return register_ip_masq_mod ((mmod_self=&mfw_mod));}int ip_mfw_done(void){ return unregister_ip_masq_mod(&mfw_mod);}#ifdef MODULEEXPORT_NO_SYMBOLS;int init_module(void){ if (ip_mfw_init() != 0) return -EIO; return 0;}void cleanup_module(void){ if (ip_mfw_done() != 0) printk(KERN_INFO "can't remove module");}#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -