aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2008-03-25 23:19:30 -0400
committerDavid S. Miller <davem@davemloft.net>2008-03-25 23:19:30 -0400
commit624f8b7bba98c27a1464f5f858c4a861d5d3e8d7 (patch)
tree4abd5e353784665ba9f7c17ae340ad630672c48e /net
parent05e3ced297fe755093140e7487e292fb7603316e (diff)
[NETFILTER]: nf_nat_sip: get rid of text based header translation
Use the URI parsing helper to get the numerical addresses and get rid of the text based header translation. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c100
-rw-r--r--net/netfilter/nf_conntrack_sip.c27
2 files changed, 60 insertions, 67 deletions
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index c13e43862361..5b4a5cd23f39 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -26,39 +26,6 @@ MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
26MODULE_DESCRIPTION("SIP NAT helper"); 26MODULE_DESCRIPTION("SIP NAT helper");
27MODULE_ALIAS("ip_nat_sip"); 27MODULE_ALIAS("ip_nat_sip");
28 28
29struct addr_map {
30 struct {
31 char src[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
32 char dst[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
33 unsigned int srclen, srciplen;
34 unsigned int dstlen, dstiplen;
35 } addr[IP_CT_DIR_MAX];
36};
37
38static void addr_map_init(const struct nf_conn *ct, struct addr_map *map)
39{
40 const struct nf_conntrack_tuple *t;
41 enum ip_conntrack_dir dir;
42 unsigned int n;
43
44 for (dir = 0; dir < IP_CT_DIR_MAX; dir++) {
45 t = &ct->tuplehash[dir].tuple;
46
47 n = sprintf(map->addr[dir].src, "%u.%u.%u.%u",
48 NIPQUAD(t->src.u3.ip));
49 map->addr[dir].srciplen = n;
50 n += sprintf(map->addr[dir].src + n, ":%u",
51 ntohs(t->src.u.udp.port));
52 map->addr[dir].srclen = n;
53
54 n = sprintf(map->addr[dir].dst, "%u.%u.%u.%u",
55 NIPQUAD(t->dst.u3.ip));
56 map->addr[dir].dstiplen = n;
57 n += sprintf(map->addr[dir].dst + n, ":%u",
58 ntohs(t->dst.u.udp.port));
59 map->addr[dir].dstlen = n;
60 }
61}
62 29
63static unsigned int mangle_packet(struct sk_buff *skb, 30static unsigned int mangle_packet(struct sk_buff *skb,
64 const char **dptr, unsigned int *datalen, 31 const char **dptr, unsigned int *datalen,
@@ -81,43 +48,51 @@ static unsigned int mangle_packet(struct sk_buff *skb,
81static int map_addr(struct sk_buff *skb, 48static int map_addr(struct sk_buff *skb,
82 const char **dptr, unsigned int *datalen, 49 const char **dptr, unsigned int *datalen,
83 unsigned int matchoff, unsigned int matchlen, 50 unsigned int matchoff, unsigned int matchlen,
84 struct addr_map *map) 51 union nf_inet_addr *addr, __be16 port)
85{ 52{
86 enum ip_conntrack_info ctinfo; 53 enum ip_conntrack_info ctinfo;
87 struct nf_conn *ct __maybe_unused = nf_ct_get(skb, &ctinfo); 54 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
88 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 55 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
89 unsigned int addrlen; 56 char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
90 char *addr; 57 unsigned int buflen;
91 58 __be32 newaddr;
92 if ((matchlen == map->addr[dir].srciplen || 59 __be16 newport;
93 matchlen == map->addr[dir].srclen) && 60
94 strncmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) { 61 if (ct->tuplehash[dir].tuple.src.u3.ip == addr->ip &&
95 addr = map->addr[!dir].dst; 62 ct->tuplehash[dir].tuple.src.u.udp.port == port) {
96 addrlen = map->addr[!dir].dstlen; 63 newaddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
97 } else if ((matchlen == map->addr[dir].dstiplen || 64 newport = ct->tuplehash[!dir].tuple.dst.u.udp.port;
98 matchlen == map->addr[dir].dstlen) && 65 } else if (ct->tuplehash[dir].tuple.dst.u3.ip == addr->ip &&
99 strncmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) { 66 ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
100 addr = map->addr[!dir].src; 67 newaddr = ct->tuplehash[!dir].tuple.src.u3.ip;
101 addrlen = map->addr[!dir].srclen; 68 newport = ct->tuplehash[!dir].tuple.src.u.udp.port;
102 } else 69 } else
103 return 1; 70 return 1;
104 71
72 if (newaddr == addr->ip && newport == port)
73 return 1;
74
75 buflen = sprintf(buffer, "%u.%u.%u.%u:%u",
76 NIPQUAD(newaddr), ntohs(newport));
77
105 return mangle_packet(skb, dptr, datalen, matchoff, matchlen, 78 return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
106 addr, addrlen); 79 buffer, buflen);
107} 80}
108 81
109static int map_sip_addr(struct sk_buff *skb, 82static int map_sip_addr(struct sk_buff *skb,
110 const char **dptr, unsigned int *datalen, 83 const char **dptr, unsigned int *datalen,
111 enum sip_header_types type, struct addr_map *map) 84 enum sip_header_types type)
112{ 85{
113 enum ip_conntrack_info ctinfo; 86 enum ip_conntrack_info ctinfo;
114 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 87 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
115 unsigned int matchlen, matchoff; 88 unsigned int matchlen, matchoff;
89 union nf_inet_addr addr;
90 __be16 port;
116 91
117 if (ct_sip_get_header(ct, *dptr, 0, *datalen, type, 92 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL,
118 &matchoff, &matchlen) <= 0) 93 &matchoff, &matchlen, &addr, &port) <= 0)
119 return 1; 94 return 1;
120 return map_addr(skb, dptr, datalen, matchoff, matchlen, map); 95 return map_addr(skb, dptr, datalen, matchoff, matchlen, &addr, port);
121} 96}
122 97
123static unsigned int ip_nat_sip(struct sk_buff *skb, 98static unsigned int ip_nat_sip(struct sk_buff *skb,
@@ -125,26 +100,27 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
125{ 100{
126 enum ip_conntrack_info ctinfo; 101 enum ip_conntrack_info ctinfo;
127 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 102 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
128 struct addr_map map;
129 unsigned int matchoff, matchlen; 103 unsigned int matchoff, matchlen;
104 union nf_inet_addr addr;
105 __be16 port;
130 106
131 if (*datalen < strlen("SIP/2.0")) 107 if (*datalen < strlen("SIP/2.0"))
132 return NF_ACCEPT; 108 return NF_ACCEPT;
133 109
134 addr_map_init(ct, &map);
135
136 /* Basic rules: requests and responses. */ 110 /* Basic rules: requests and responses. */
137 if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) { 111 if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
138 if (ct_sip_parse_request(ct, *dptr, *datalen, 112 if (ct_sip_parse_request(ct, *dptr, *datalen,
139 &matchoff, &matchlen) > 0 && 113 &matchoff, &matchlen,
140 !map_addr(skb, dptr, datalen, matchoff, matchlen, &map)) 114 &addr, &port) > 0 &&
115 !map_addr(skb, dptr, datalen, matchoff, matchlen,
116 &addr, port))
141 return NF_DROP; 117 return NF_DROP;
142 } 118 }
143 119
144 if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM, &map) || 120 if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM) ||
145 !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO, &map) || 121 !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO) ||
146 !map_sip_addr(skb, dptr, datalen, SIP_HDR_VIA, &map) || 122 !map_sip_addr(skb, dptr, datalen, SIP_HDR_VIA) ||
147 !map_sip_addr(skb, dptr, datalen, SIP_HDR_CONTACT, &map)) 123 !map_sip_addr(skb, dptr, datalen, SIP_HDR_CONTACT))
148 return NF_DROP; 124 return NF_DROP;
149 return NF_ACCEPT; 125 return NF_ACCEPT;
150} 126}
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index a74d76a97312..f20fa2d94c0a 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -151,10 +151,12 @@ static int skp_epaddr_len(const struct nf_conn *ct, const char *dptr,
151 */ 151 */
152int ct_sip_parse_request(const struct nf_conn *ct, 152int ct_sip_parse_request(const struct nf_conn *ct,
153 const char *dptr, unsigned int datalen, 153 const char *dptr, unsigned int datalen,
154 unsigned int *matchoff, unsigned int *matchlen) 154 unsigned int *matchoff, unsigned int *matchlen,
155 union nf_inet_addr *addr, __be16 *port)
155{ 156{
156 const char *start = dptr, *limit = dptr + datalen; 157 const char *start = dptr, *limit = dptr + datalen, *end;
157 unsigned int mlen; 158 unsigned int mlen;
159 unsigned int p;
158 int shift = 0; 160 int shift = 0;
159 161
160 /* Skip method and following whitespace */ 162 /* Skip method and following whitespace */
@@ -173,10 +175,25 @@ int ct_sip_parse_request(const struct nf_conn *ct,
173 if (strnicmp(dptr, "sip:", strlen("sip:")) == 0) 175 if (strnicmp(dptr, "sip:", strlen("sip:")) == 0)
174 break; 176 break;
175 } 177 }
176 *matchlen = skp_epaddr_len(ct, dptr, limit, &shift); 178 if (!skp_epaddr_len(ct, dptr, limit, &shift))
177 if (!*matchlen)
178 return 0; 179 return 0;
179 *matchoff = dptr - start + shift; 180 dptr += shift;
181
182 if (!parse_addr(ct, dptr, &end, addr, limit))
183 return -1;
184 if (end < limit && *end == ':') {
185 end++;
186 p = simple_strtoul(end, (char **)&end, 10);
187 if (p < 1024 || p > 65535)
188 return -1;
189 *port = htons(p);
190 } else
191 *port = htons(SIP_PORT);
192
193 if (end == dptr)
194 return 0;
195 *matchoff = dptr - start;
196 *matchlen = end - dptr;
180 return 1; 197 return 1;
181} 198}
182EXPORT_SYMBOL_GPL(ct_sip_parse_request); 199EXPORT_SYMBOL_GPL(ct_sip_parse_request);