📄 ip_masq.c
字号:
case CHECKSUM_HW: if (csum_tcpudp_magic(iph->saddr, iph->daddr, size, iph->protocol, skb->csum)) { IP_MASQ_DEBUG(0, "Incoming failed %s checksum from %d.%d.%d.%d (size=%d)!\n", masq_proto_name(iph->protocol), NIPQUAD(iph->saddr), size); return -1; } default: /* CHECKSUM_UNNECESSARY */ } break; default: return 0; } IP_MASQ_DEBUG(2, "Incoming %s %08lX:%04X -> %08lX:%04X\n", masq_proto_name(iph->protocol), ntohl(iph->saddr), ntohs(h.portp[0]), ntohl(iph->daddr), ntohs(h.portp[1])); /* * reroute to original host:port if found... */ ms = ip_masq_in_get_iph(iph); /* * Give additional modules a chance to create an entry */#ifdef CONFIG_IP_MASQUERADE_MOD if (!ms) ms = ip_masq_mod_in_create(skb, iph, maddr); /* * Call module's input update hook */ ip_masq_mod_in_update(skb, iph, ms);#endif if (ms != NULL) { /* * got reply, so clear flag */ ms->flags &= ~IP_MASQ_F_NO_REPLY; /* * Set daddr,dport if not defined yet * and tunnel is not setup as "dest loose" */ if (ms->flags & IP_MASQ_F_DLOOSE) { /* * update dest loose values */ ms->dport = h.portp[0]; ms->daddr = iph->saddr; } else { if ( ms->flags & IP_MASQ_F_NO_DPORT ) { /* && ms->protocol == IPPROTO_TCP ) { */ write_lock(&__ip_masq_lock); ip_masq_unhash(ms); ms->flags &= ~IP_MASQ_F_NO_DPORT; ms->dport = h.portp[0]; ip_masq_hash(ms); /* hash on new dport */ write_unlock(&__ip_masq_lock); IP_MASQ_DEBUG(1, "ip_fw_demasquerade(): filled dport=%d\n", ntohs(ms->dport)); } if (ms->flags & IP_MASQ_F_NO_DADDR ) { /* && ms->protocol == IPPROTO_TCP) { */ write_lock(&__ip_masq_lock); ip_masq_unhash(ms); ms->flags &= ~IP_MASQ_F_NO_DADDR; ms->daddr = iph->saddr; ip_masq_hash(ms); /* hash on new daddr */ write_unlock(&__ip_masq_lock); IP_MASQ_DEBUG(1, "ip_fw_demasquerade(): filled daddr=%lX\n", ntohl(ms->daddr)); } } if ((skb=masq_skb_cow(skb_p, &iph, &h.raw)) == NULL) { ip_masq_put(ms); return -1; } iph->daddr = ms->saddr; h.portp[1] = ms->sport; /* * Invalidate csum saving if tunnel has masq helper */ if (ms->app) csum_ok = 0; /* * Attempt ip_masq_app call. * will fix ip_masq and iph ack_seq stuff */ if (ip_masq_app_pkt_in(ms, skb_p, maddr) != 0) { /* * skb has changed, update pointers. */ skb = *skb_p; iph = skb->nh.iph; h.raw = (char*) iph + iph->ihl*4; size = ntohs(iph->tot_len) - (iph->ihl * 4); } /* * Yug! adjust UDP/TCP checksums */ /* * Transport's payload partial csum */ if (!csum_ok) { csum = csum_partial(h.raw + doff, size - doff, 0); } skb->csum = csum; /* * Protocol csum */ switch (iph->protocol) { case IPPROTO_TCP: h.th->check = 0; h.th->check=csum_tcpudp_magic(iph->saddr, iph->daddr, size, iph->protocol, csum_partial(h.raw , doff, csum)); break; case IPPROTO_UDP: h.uh->check = 0; h.uh->check=csum_tcpudp_magic(iph->saddr, iph->daddr, size, iph->protocol, csum_partial(h.raw , doff, csum)); if (h.uh->check == 0) h.uh->check = 0xFFFF; break; } ip_send_check(iph); IP_MASQ_DEBUG(2, "I-routed to %08lX:%04X\n",ntohl(iph->daddr),ntohs(h.portp[1])); masq_set_state (ms, 0, iph, h.portp); ip_masq_put(ms); return 1; } /* sorry, all this trouble for a no-hit :) */ return 0;}void ip_masq_control_add(struct ip_masq *ms, struct ip_masq* ctl_ms){ if (ms->control) { IP_MASQ_ERR( "request control ADD for already controlled: %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n", NIPQUAD(ms->saddr),ntohs(ms->sport), NIPQUAD(ms->daddr),ntohs(ms->dport)); ip_masq_control_del(ms); } IP_MASQ_DEBUG(1, "ADDing control for: ms.dst=%d.%d.%d.%d:%d ctl_ms.dst=%d.%d.%d.%d:%d\n", NIPQUAD(ms->daddr),ntohs(ms->dport), NIPQUAD(ctl_ms->daddr),ntohs(ctl_ms->dport)); ms->control = ctl_ms; atomic_inc(&ctl_ms->n_control);}void ip_masq_control_del(struct ip_masq *ms){ struct ip_masq *ctl_ms = ms->control; if (!ctl_ms) { IP_MASQ_ERR( "request control DEL for uncontrolled: %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n", NIPQUAD(ms->saddr),ntohs(ms->sport), NIPQUAD(ms->daddr),ntohs(ms->dport)); return; } IP_MASQ_DEBUG(1, "DELeting control for: ms.dst=%d.%d.%d.%d:%d ctl_ms.dst=%d.%d.%d.%d:%d\n", NIPQUAD(ms->daddr),ntohs(ms->dport), NIPQUAD(ctl_ms->daddr),ntohs(ctl_ms->dport)); ms->control = NULL; if (atomic_read(&ctl_ms->n_control) == 0) { IP_MASQ_ERR( "BUG control DEL with n=0 : %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n", NIPQUAD(ms->saddr),ntohs(ms->sport), NIPQUAD(ms->daddr),ntohs(ms->dport)); return; } atomic_dec(&ctl_ms->n_control);}struct ip_masq * ip_masq_control_get(struct ip_masq *ms){ return ms->control;}#ifdef CONFIG_PROC_FS/* * /proc/net entries * From userspace */static int ip_msqhst_procinfo(char *buffer, char **start, off_t offset, int length, int unused){ off_t pos=0, begin; struct ip_masq *ms; char temp[129]; int idx = 0; int len=0; struct list_head *l,*e; if (offset < 128) { sprintf(temp, "Prc FromIP FPrt ToIP TPrt Masq Init-seq Delta PDelta Expires (free=%d,%d,%d)", atomic_read(ip_masq_free_ports), atomic_read(ip_masq_free_ports+1), atomic_read(ip_masq_free_ports+2)); len = sprintf(buffer, "%-127s\n", temp); } pos = 128; for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++) { /* * Lock is actually only need in next loop * we are called from uspace: must stop bh. */ read_lock_bh(&__ip_masq_lock); l = &ip_masq_m_table[idx]; for (e=l->next; e!=l; e=e->next) { ms = list_entry(e, struct ip_masq, m_list); pos += 128; if (pos <= offset) { len = 0; continue; } /* * We have locked the tables, no need to del/add timers * nor cli() 8) */ sprintf(temp,"%s %08X:%04X %08X:%04X %04X %08X %6d %6d %7lu", masq_proto_name(ms->protocol), ntohl(ms->saddr), ntohs(ms->sport), ntohl(ms->daddr), ntohs(ms->dport), ntohs(ms->mport), ms->out_seq.init_seq, ms->out_seq.delta, ms->out_seq.previous_delta, ms->timer.expires-jiffies); len += sprintf(buffer+len, "%-127s\n", temp); if(len >= length) { read_unlock_bh(&__ip_masq_lock); goto done; } } read_unlock_bh(&__ip_masq_lock); }done: begin = len - (pos - offset); *start = buffer + begin; len -= begin; if(len>length) len = length; return len;}#endif/* * Timeouts handling by ipfwadm/ipchains * From ip_fw.c */int ip_fw_masq_timeouts(void *m, int len) { struct ip_fw_masq *masq; int ret = EINVAL; if (len != sizeof(struct ip_fw_masq)) { IP_MASQ_DEBUG(1, "ip_fw_masq_timeouts: length %d, expected %d\n", len, sizeof(struct ip_fw_masq)); } else { masq = (struct ip_fw_masq *)m; if (masq->tcp_timeout) masq_timeout_table.timeout[IP_MASQ_S_ESTABLISHED] = masq->tcp_timeout; if (masq->tcp_fin_timeout) masq_timeout_table.timeout[IP_MASQ_S_FIN_WAIT] = masq->tcp_fin_timeout; if (masq->udp_timeout) masq_timeout_table.timeout[IP_MASQ_S_UDP] = masq->udp_timeout; ret = 0; } return ret;}/* * Module autoloading stuff */static int ip_masq_user_check_hook(void) {#ifdef CONFIG_KMOD if (ip_masq_user_hook == NULL) { IP_MASQ_DEBUG(1, "About to request \"ip_masq_user\" module\n"); request_module("ip_masq_user"); }#endif /* CONFIG_KMOD */ return (ip_masq_user_hook != NULL);}/* * user module hook- info */static int ip_masq_user_info(char *buffer, char **start, off_t offset, int len, int *eof, void *data){ int ret = -ENOPKG; if (ip_masq_user_check_hook()) { ret = ip_masq_user_hook->info(buffer, start, offset, len, (int) data); } return ret;}/* * user module hook- entry mgmt */static int ip_masq_user_ctl(int optname, void *arg, int arglen){ int ret = -ENOPKG; if (ip_masq_user_check_hook()) { ret = ip_masq_user_hook->ctl(optname, arg, arglen); } return ret;}/* * Control from ip_sockglue * MAIN ENTRY point from userspace (apart from /proc *info entries) * Returns errno */int ip_masq_uctl(int optname, char * optval , int optlen){ struct ip_masq_ctl masq_ctl; int ret = -EINVAL; if(optlen>sizeof(masq_ctl)) return -EINVAL; if(copy_from_user(&masq_ctl,optval,optlen)) return -EFAULT; IP_MASQ_DEBUG(1,"ip_masq_ctl(optname=%d, optlen=%d, target=%d, cmd=%d)\n", optname, optlen, masq_ctl.m_target, masq_ctl.m_cmd); switch (masq_ctl.m_target) { case IP_MASQ_TARGET_USER: ret = ip_masq_user_ctl(optname, &masq_ctl, optlen); break;#ifdef CONFIG_IP_MASQUERADE_MOD case IP_MASQ_TARGET_MOD: ret = ip_masq_mod_ctl(optname, &masq_ctl, optlen); break;#endif } /* * If ret>0, copy to user space */ if (ret > 0 && ret <= sizeof (masq_ctl)) { if (copy_to_user(optval, &masq_ctl, ret) ) return -EFAULT; ret = 0; } return ret;}#ifdef CONFIG_PROC_FSstatic struct proc_dir_entry *proc_net_ip_masq = NULL;#ifdef MODULEstatic void ip_masq_proc_count(struct inode *inode, int fill){ if (fill) MOD_INC_USE_COUNT; else MOD_DEC_USE_COUNT;}#endifint ip_masq_proc_register(struct proc_dir_entry *ent){ if (!proc_net_ip_masq) return -1; IP_MASQ_DEBUG(1, "registering \"/proc/net/ip_masq/%s\" entry\n", ent->name); return proc_register(proc_net_ip_masq, ent);}void ip_masq_proc_unregister(struct proc_dir_entry *ent){ if (!proc_net_ip_masq) return; IP_MASQ_DEBUG(1, "unregistering \"/proc/net/ip_masq/%s\" entry\n", ent->name); proc_unregister(proc_net_ip_masq, ent->low_ino);}__initfunc(static void masq_proc_init(void)){ IP_MASQ_DEBUG(1,"registering /proc/net/ip_masq\n"); if (!proc_net_ip_masq) { struct proc_dir_entry *ent; ent = create_proc_entry("net/ip_masq", S_IFDIR, 0); if (ent) {#ifdef MODULE ent->fill_inode = ip_masq_proc_count;#endif proc_net_ip_masq = ent; } else { IP_MASQ_ERR("Could not create \"/proc/net/ip_masq\" entry\n"); } }}#endif /* CONFIG_PROC_FS *//* * Wrapper over inet_select_addr() */u32 ip_masq_select_addr(struct device *dev, u32 dst, int scope){ return inet_select_addr(dev, dst, scope);}/* * Initialize ip masquerading */__initfunc(int ip_masq_init(void)){ int idx; for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++) { INIT_LIST_HEAD(&ip_masq_s_table[idx]); INIT_LIST_HEAD(&ip_masq_m_table[idx]); INIT_LIST_HEAD(&ip_masq_d_table[idx]); }#ifdef CONFIG_PROC_FS proc_net_register(&(struct proc_dir_entry) { PROC_NET_IPMSQHST, 13, "ip_masquerade", S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_net_inode_operations, ip_msqhst_procinfo }); masq_proc_init(); ip_masq_proc_register(&(struct proc_dir_entry) { 0, 3, "tcp", S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_net_inode_operations, NULL, /* get_info */ NULL, /* fill_inode */ NULL, NULL, NULL, (char *) IPPROTO_TCP, ip_masq_user_info }); ip_masq_proc_register(&(struct proc_dir_entry) { 0, 3, "udp", S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_net_inode_operations, NULL, /* get_info */ NULL, /* fill_inode */ NULL, NULL, NULL, (char *) IPPROTO_UDP, ip_masq_user_info }); ip_masq_proc_registe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -