📄 ip_masq_app.c
字号:
/* * IP_MASQ_APP application masquerading module * * * $Id: ip_masq_app.c,v 1.16 1998/08/29 23:51:14 davem Exp $ * * Author: Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar> * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Fixes: * JJC : Implemented also input pkt hook * Miquel van Smoorenburg : Copy more stuff when resizing skb * * * FIXME: * - ip_masq_skb_replace(): use same skb if space available. * */#include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/skbuff.h>#include <linux/in.h>#include <linux/ip.h>#include <linux/init.h>#include <net/protocol.h>#include <net/tcp.h>#include <net/udp.h>#include <asm/system.h>#include <linux/stat.h>#include <linux/proc_fs.h>#include <net/ip_masq.h>#define IP_MASQ_APP_TAB_SIZE 16 /* must be power of 2 */#define IP_MASQ_APP_HASH(proto, port) ((port^proto) & (IP_MASQ_APP_TAB_SIZE-1))#define IP_MASQ_APP_TYPE(proto, port) ( proto<<16 | port )#define IP_MASQ_APP_PORT(type) ( type & 0xffff )#define IP_MASQ_APP_PROTO(type) ( (type>>16) & 0x00ff )EXPORT_SYMBOL(register_ip_masq_app);EXPORT_SYMBOL(unregister_ip_masq_app);EXPORT_SYMBOL(ip_masq_skb_replace);/* * will hold masq app. hashed list heads */struct ip_masq_app *ip_masq_app_base[IP_MASQ_APP_TAB_SIZE];/* * ip_masq_app registration routine * port: host byte order. */int register_ip_masq_app(struct ip_masq_app *mapp, unsigned short proto, __u16 port){ unsigned long flags; unsigned hash; if (!mapp) { IP_MASQ_ERR("register_ip_masq_app(): NULL arg\n"); return -EINVAL; } mapp->type = IP_MASQ_APP_TYPE(proto, port); mapp->n_attach = 0; hash = IP_MASQ_APP_HASH(proto, port); save_flags(flags); cli(); mapp->next = ip_masq_app_base[hash]; ip_masq_app_base[hash] = mapp; restore_flags(flags); return 0;}/* * ip_masq_app unreg. routine. */int unregister_ip_masq_app(struct ip_masq_app *mapp){ struct ip_masq_app **mapp_p; unsigned hash; unsigned long flags; if (!mapp) { IP_MASQ_ERR("unregister_ip_masq_app(): NULL arg\n"); return -EINVAL; } /* * only allow unregistration if it has no attachments */ if (mapp->n_attach) { IP_MASQ_ERR("unregister_ip_masq_app(): has %d attachments. failed\n", mapp->n_attach); return -EINVAL; } hash = IP_MASQ_APP_HASH(IP_MASQ_APP_PROTO(mapp->type), IP_MASQ_APP_PORT(mapp->type)); save_flags(flags); cli(); for (mapp_p = &ip_masq_app_base[hash]; *mapp_p ; mapp_p = &(*mapp_p)->next) if (mapp == (*mapp_p)) { *mapp_p = mapp->next; restore_flags(flags); return 0; } restore_flags(flags); IP_MASQ_ERR("unregister_ip_masq_app(proto=%s,port=%u): not hashed!\n", masq_proto_name(IP_MASQ_APP_PROTO(mapp->type)), IP_MASQ_APP_PORT(mapp->type)); return -EINVAL;}/* * get ip_masq_app object by its proto and port (net byte order). */struct ip_masq_app * ip_masq_app_get(unsigned short proto, __u16 port){ struct ip_masq_app *mapp; unsigned hash; unsigned type; port = ntohs(port); type = IP_MASQ_APP_TYPE(proto,port); hash = IP_MASQ_APP_HASH(proto,port); for(mapp = ip_masq_app_base[hash]; mapp ; mapp = mapp->next) { if (type == mapp->type) return mapp; } return NULL;}/* * ip_masq_app object binding related funcs. *//* * change ip_masq_app object's number of bindings */static __inline__ int ip_masq_app_bind_chg(struct ip_masq_app *mapp, int delta){ unsigned long flags; int n_at; if (!mapp) return -1; save_flags(flags); cli(); n_at = mapp->n_attach + delta; if (n_at < 0) { restore_flags(flags); IP_MASQ_ERR("ip_masq_app: tried to set n_attach < 0 for (proto=%s,port==%d) ip_masq_app object.\n", masq_proto_name(IP_MASQ_APP_PROTO(mapp->type)), IP_MASQ_APP_PORT(mapp->type)); return -1; } mapp->n_attach = n_at; restore_flags(flags); return 0;}/* * Bind ip_masq to its ip_masq_app based on proto and dport ALREADY * set in ip_masq struct. Also calls constructor. */struct ip_masq_app * ip_masq_bind_app(struct ip_masq *ms){ struct ip_masq_app * mapp; if (ms->protocol != IPPROTO_TCP && ms->protocol != IPPROTO_UDP) return NULL; mapp = ip_masq_app_get(ms->protocol, ms->dport);#if 0000/* #ifdef CONFIG_IP_MASQUERADE_IPAUTOFW */ if (mapp == NULL) mapp = ip_masq_app_get(ms->protocol, ms->sport);/* #endif */#endif if (mapp != NULL) { /* * don't allow binding if already bound */ if (ms->app != NULL) { IP_MASQ_ERR("ip_masq_bind_app() called for already bound object.\n"); return ms->app; } ms->app = mapp; if (mapp->masq_init_1) mapp->masq_init_1(mapp, ms); ip_masq_app_bind_chg(mapp, +1); } return mapp;}/* * Unbind ms from type object and call ms destructor (does not kfree()). */int ip_masq_unbind_app(struct ip_masq *ms){ struct ip_masq_app * mapp; mapp = ms->app; if (ms->protocol != IPPROTO_TCP && ms->protocol != IPPROTO_UDP) return 0; if (mapp != NULL) { if (mapp->masq_done_1) mapp->masq_done_1(mapp, ms); ms->app = NULL; ip_masq_app_bind_chg(mapp, -1); } return (mapp != NULL);}/* * Fixes th->seq based on ip_masq_seq info. */static __inline__ void masq_fix_seq(const struct ip_masq_seq *ms_seq, struct tcphdr *th){ __u32 seq; seq = ntohl(th->seq); /* * Adjust seq with delta-offset for all packets after * the most recent resized pkt seq and with previous_delta offset * for all packets before most recent resized pkt seq. */ if (ms_seq->delta || ms_seq->previous_delta) { if(after(seq,ms_seq->init_seq) ) { th->seq = htonl(seq + ms_seq->delta); IP_MASQ_DEBUG(1, "masq_fix_seq() : added delta (%d) to seq\n",ms_seq->delta); } else { th->seq = htonl(seq + ms_seq->previous_delta); IP_MASQ_DEBUG(1, "masq_fix_seq() : added previous_delta (%d) to seq\n",ms_seq->previous_delta); } }}/* * Fixes th->ack_seq based on ip_masq_seq info. */static __inline__ void masq_fix_ack_seq(const struct ip_masq_seq *ms_seq, struct tcphdr *th){ __u32 ack_seq; ack_seq=ntohl(th->ack_seq); /* * Adjust ack_seq with delta-offset for * the packets AFTER most recent resized pkt has caused a shift * for packets before most recent resized pkt, use previous_delta */ if (ms_seq->delta || ms_seq->previous_delta) { if(after(ack_seq,ms_seq->init_seq)) { th->ack_seq = htonl(ack_seq-ms_seq->delta); IP_MASQ_DEBUG(1, "masq_fix_ack_seq() : subtracted delta (%d) from ack_seq\n",ms_seq->delta); } else { th->ack_seq = htonl(ack_seq-ms_seq->previous_delta); IP_MASQ_DEBUG(1, "masq_fix_ack_seq() : subtracted previous_delta (%d) from ack_seq\n",ms_seq->previous_delta); } }}/* * Updates ip_masq_seq if pkt has been resized * Assumes already checked proto==IPPROTO_TCP and diff!=0. */static __inline__ void masq_seq_update(struct ip_masq *ms, struct ip_masq_seq *ms_seq, unsigned mflag, __u32 seq, int diff){ /* if (diff == 0) return; */ if ( !(ms->flags & mflag) || after(seq, ms_seq->init_seq)) { ms_seq->previous_delta=ms_seq->delta; ms_seq->delta+=diff; ms_seq->init_seq=seq; ms->flags |= mflag; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -