1 // SPDX-License-Identifier: GPL-2.0-only
2 /* SIP extension for NAT alteration.
3 *
4 * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
5 * based on RR's ip_nat_ftp.c and other modules.
6 * (C) 2007 United Security Providers
7 * (C) 2007, 2008, 2011, 2012 Patrick McHardy <kaber@trash.net>
8 */
9
10 #include <linux/module.h>
11 #include <linux/skbuff.h>
12 #include <linux/inet.h>
13 #include <linux/udp.h>
14 #include <linux/tcp.h>
15
16 #include <net/netfilter/nf_nat.h>
17 #include <net/netfilter/nf_nat_helper.h>
18 #include <net/netfilter/nf_conntrack_core.h>
19 #include <net/netfilter/nf_conntrack_helper.h>
20 #include <net/netfilter/nf_conntrack_expect.h>
21 #include <net/netfilter/nf_conntrack_seqadj.h>
22 #include <linux/netfilter/nf_conntrack_sip.h>
23
24 #define NAT_HELPER_NAME "sip"
25
26 MODULE_LICENSE("GPL");
27 MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
28 MODULE_DESCRIPTION("SIP NAT helper");
29 MODULE_ALIAS_NF_NAT_HELPER(NAT_HELPER_NAME);
30
31 static struct nf_conntrack_nat_helper nat_helper_sip =
32 NF_CT_NAT_HELPER_INIT(NAT_HELPER_NAME);
33
mangle_packet(struct sk_buff * skb,unsigned int protoff,unsigned int dataoff,const char ** dptr,unsigned int * datalen,unsigned int matchoff,unsigned int matchlen,const char * buffer,unsigned int buflen)34 static unsigned int mangle_packet(struct sk_buff *skb, unsigned int protoff,
35 unsigned int dataoff,
36 const char **dptr, unsigned int *datalen,
37 unsigned int matchoff, unsigned int matchlen,
38 const char *buffer, unsigned int buflen)
39 {
40 enum ip_conntrack_info ctinfo;
41 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
42 struct tcphdr *th;
43 unsigned int baseoff;
44
45 if (nf_ct_protonum(ct) == IPPROTO_TCP) {
46 th = (struct tcphdr *)(skb->data + protoff);
47 baseoff = protoff + th->doff * 4;
48 matchoff += dataoff - baseoff;
49
50 if (!__nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
51 protoff, matchoff, matchlen,
52 buffer, buflen, false))
53 return 0;
54 } else {
55 baseoff = protoff + sizeof(struct udphdr);
56 matchoff += dataoff - baseoff;
57
58 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
59 protoff, matchoff, matchlen,
60 buffer, buflen))
61 return 0;
62 }
63
64 /* Reload data pointer and adjust datalen value */
65 *dptr = skb->data + dataoff;
66 *datalen += buflen - matchlen;
67 return 1;
68 }
69
sip_sprintf_addr(const struct nf_conn * ct,char * buffer,size_t size,const union nf_inet_addr * addr,bool delim)70 static int sip_sprintf_addr(const struct nf_conn *ct, char *buffer,
71 size_t size,
72 const union nf_inet_addr *addr, bool delim)
73 {
74 if (nf_ct_l3num(ct) == NFPROTO_IPV4)
75 return scnprintf(buffer, size, "%pI4", &addr->ip);
76 else {
77 if (delim)
78 return scnprintf(buffer, size, "[%pI6c]", &addr->ip6);
79 else
80 return scnprintf(buffer, size, "%pI6c", &addr->ip6);
81 }
82 }
83
sip_sprintf_addr_port(const struct nf_conn * ct,char * buffer,size_t size,const union nf_inet_addr * addr,u16 port)84 static int sip_sprintf_addr_port(const struct nf_conn *ct, char *buffer,
85 size_t size,
86 const union nf_inet_addr *addr, u16 port)
87 {
88 if (nf_ct_l3num(ct) == NFPROTO_IPV4)
89 return scnprintf(buffer, size, "%pI4:%u", &addr->ip, port);
90 else
91 return scnprintf(buffer, size, "[%pI6c]:%u", &addr->ip6, port);
92 }
93
map_addr(struct sk_buff * skb,unsigned int protoff,unsigned int dataoff,const char ** dptr,unsigned int * datalen,unsigned int matchoff,unsigned int matchlen,union nf_inet_addr * addr,__be16 port)94 static int map_addr(struct sk_buff *skb, unsigned int protoff,
95 unsigned int dataoff,
96 const char **dptr, unsigned int *datalen,
97 unsigned int matchoff, unsigned int matchlen,
98 union nf_inet_addr *addr, __be16 port)
99 {
100 enum ip_conntrack_info ctinfo;
101 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
102 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
103 struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
104 char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
105 unsigned int buflen;
106 union nf_inet_addr newaddr;
107 __be16 newport;
108
109 if (!ct_sip_info)
110 return 0;
111
112 if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, addr) &&
113 ct->tuplehash[dir].tuple.src.u.udp.port == port) {
114 newaddr = ct->tuplehash[!dir].tuple.dst.u3;
115 newport = ct->tuplehash[!dir].tuple.dst.u.udp.port;
116 } else if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, addr) &&
117 ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
118 newaddr = ct->tuplehash[!dir].tuple.src.u3;
119 newport = ct_sip_info->forced_dport ? :
120 ct->tuplehash[!dir].tuple.src.u.udp.port;
121 } else
122 return 1;
123
124 if (nf_inet_addr_cmp(&newaddr, addr) && newport == port)
125 return 1;
126
127 buflen = sip_sprintf_addr_port(ct, buffer, sizeof(buffer), &newaddr, ntohs(newport));
128 return mangle_packet(skb, protoff, dataoff, dptr, datalen,
129 matchoff, matchlen, buffer, buflen);
130 }
131
map_sip_addr(struct sk_buff * skb,unsigned int protoff,unsigned int dataoff,const char ** dptr,unsigned int * datalen,enum sip_header_types type)132 static int map_sip_addr(struct sk_buff *skb, unsigned int protoff,
133 unsigned int dataoff,
134 const char **dptr, unsigned int *datalen,
135 enum sip_header_types type)
136 {
137 enum ip_conntrack_info ctinfo;
138 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
139 unsigned int matchlen, matchoff;
140 union nf_inet_addr addr;
141 __be16 port;
142
143 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL,
144 &matchoff, &matchlen, &addr, &port) <= 0)
145 return 1;
146 return map_addr(skb, protoff, dataoff, dptr, datalen,
147 matchoff, matchlen, &addr, port);
148 }
149
nf_nat_sip(struct sk_buff * skb,unsigned int protoff,unsigned int dataoff,const char ** dptr,unsigned int * datalen)150 static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
151 unsigned int dataoff,
152 const char **dptr, unsigned int *datalen)
153 {
154 enum ip_conntrack_info ctinfo;
155 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
156 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
157 struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
158 unsigned int coff, matchoff, matchlen;
159 enum sip_header_types hdr;
160 union nf_inet_addr addr;
161 __be16 port;
162 int request, in_header;
163
164 if (!ct_sip_info)
165 return NF_DROP;
166
167 /* Basic rules: requests and responses. */
168 if (strncasecmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
169 if (ct_sip_parse_request(ct, *dptr, *datalen,
170 &matchoff, &matchlen,
171 &addr, &port) > 0 &&
172 !map_addr(skb, protoff, dataoff, dptr, datalen,
173 matchoff, matchlen, &addr, port)) {
174 nf_ct_helper_log(skb, ct, "cannot mangle SIP message");
175 return NF_DROP;
176 }
177 request = 1;
178 } else
179 request = 0;
180
181 if (nf_ct_protonum(ct) == IPPROTO_TCP)
182 hdr = SIP_HDR_VIA_TCP;
183 else
184 hdr = SIP_HDR_VIA_UDP;
185
186 /* Translate topmost Via header and parameters */
187 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
188 hdr, NULL, &matchoff, &matchlen,
189 &addr, &port) > 0) {
190 unsigned int olen, matchend, poff, plen, buflen, n;
191 char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
192
193 /* We're only interested in headers related to this
194 * connection */
195 if (request) {
196 if (!nf_inet_addr_cmp(&addr,
197 &ct->tuplehash[dir].tuple.src.u3) ||
198 port != ct->tuplehash[dir].tuple.src.u.udp.port)
199 goto next;
200 } else {
201 if (!nf_inet_addr_cmp(&addr,
202 &ct->tuplehash[dir].tuple.dst.u3) ||
203 port != ct->tuplehash[dir].tuple.dst.u.udp.port)
204 goto next;
205 }
206
207 olen = *datalen;
208 if (!map_addr(skb, protoff, dataoff, dptr, datalen,
209 matchoff, matchlen, &addr, port)) {
210 nf_ct_helper_log(skb, ct, "cannot mangle Via header");
211 return NF_DROP;
212 }
213
214 matchend = matchoff + matchlen + *datalen - olen;
215
216 /* The maddr= parameter (RFC 2361) specifies where to send
217 * the reply. */
218 if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
219 "maddr=", &poff, &plen,
220 &addr, true) > 0 &&
221 nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.src.u3) &&
222 !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3)) {
223 buflen = sip_sprintf_addr(ct, buffer, sizeof(buffer),
224 &ct->tuplehash[!dir].tuple.dst.u3,
225 true);
226 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
227 poff, plen, buffer, buflen)) {
228 nf_ct_helper_log(skb, ct, "cannot mangle maddr");
229 return NF_DROP;
230 }
231 }
232
233 /* The received= parameter (RFC 2361) contains the address
234 * from which the server received the request. */
235 if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
236 "received=", &poff, &plen,
237 &addr, false) > 0 &&
238 nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.dst.u3) &&
239 !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.src.u3)) {
240 buflen = sip_sprintf_addr(ct, buffer, sizeof(buffer),
241 &ct->tuplehash[!dir].tuple.src.u3,
242 false);
243 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
244 poff, plen, buffer, buflen)) {
245 nf_ct_helper_log(skb, ct, "cannot mangle received");
246 return NF_DROP;
247 }
248 }
249
250 /* The rport= parameter (RFC 3581) contains the port number
251 * from which the server received the request. */
252 if (ct_sip_parse_numerical_param(ct, *dptr, matchend, *datalen,
253 "rport=", &poff, &plen,
254 &n) > 0 &&
255 n >= 1024 && n <= 65535 &&
256 htons(n) == ct->tuplehash[dir].tuple.dst.u.udp.port &&
257 htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) {
258 __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port;
259 buflen = scnprintf(buffer, sizeof(buffer), "%u", ntohs(p));
260 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
261 poff, plen, buffer, buflen)) {
262 nf_ct_helper_log(skb, ct, "cannot mangle rport");
263 return NF_DROP;
264 }
265 }
266 }
267
268 next:
269 /* Translate Contact headers */
270 coff = 0;
271 in_header = 0;
272 while (ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen,
273 SIP_HDR_CONTACT, &in_header,
274 &matchoff, &matchlen,
275 &addr, &port) > 0) {
276 int old_len = skb->len, delta;
277
278 if (!map_addr(skb, protoff, dataoff, dptr, datalen,
279 matchoff, matchlen,
280 &addr, port)) {
281 nf_ct_helper_log(skb, ct, "cannot mangle contact");
282 return NF_DROP;
283 }
284
285 delta = (int)skb->len - old_len;
286 coff += delta;
287 }
288
289 if (!map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_FROM) ||
290 !map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_TO)) {
291 nf_ct_helper_log(skb, ct, "cannot mangle SIP from/to");
292 return NF_DROP;
293 }
294
295 /* Mangle destination port for Cisco phones, then fix up checksums */
296 if (dir == IP_CT_DIR_REPLY && ct_sip_info->forced_dport) {
297 int doff = *dptr - (const char *)skb->data;
298 struct udphdr *uh;
299
300 if (doff <= 0) {
301 DEBUG_NET_WARN_ON_ONCE(1);
302 return NF_DROP;
303 }
304
305 /* ct_sip_info->forced_dport only expected with UDP */
306 if (nf_ct_protonum(ct) != IPPROTO_UDP)
307 return NF_DROP;
308
309 if (skb_ensure_writable(skb, skb->len)) {
310 nf_ct_helper_log(skb, ct, "cannot mangle packet");
311 return NF_DROP;
312 }
313
314 *dptr = skb->data + doff;
315 uh = (void *)skb->data + protoff;
316 uh->dest = ct_sip_info->forced_dport;
317
318 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, protoff,
319 0, 0, NULL, 0)) {
320 nf_ct_helper_log(skb, ct, "cannot mangle packet");
321 return NF_DROP;
322 }
323 }
324
325 return NF_ACCEPT;
326 }
327
nf_nat_sip_seq_adjust(struct sk_buff * skb,unsigned int protoff,s32 off)328 static void nf_nat_sip_seq_adjust(struct sk_buff *skb, unsigned int protoff,
329 s32 off)
330 {
331 enum ip_conntrack_info ctinfo;
332 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
333 const struct tcphdr *th;
334
335 if (nf_ct_protonum(ct) != IPPROTO_TCP || off == 0)
336 return;
337
338 th = (struct tcphdr *)(skb->data + protoff);
339 nf_ct_seqadj_set(ct, ctinfo, th->seq, off);
340 }
341
342 /* Handles expected signalling connections and media streams */
nf_nat_sip_expected(struct nf_conn * ct,struct nf_conntrack_expect * exp)343 static void nf_nat_sip_expected(struct nf_conn *ct,
344 struct nf_conntrack_expect *exp)
345 {
346 struct nf_conn_help *help = nfct_help(ct->master);
347 struct nf_conntrack_expect *pair_exp;
348 int range_set_for_snat = 0;
349 struct nf_nat_range2 range;
350
351 if (!help)
352 return;
353
354 /* This must be a fresh one. */
355 BUG_ON(ct->status & IPS_NAT_DONE_MASK);
356
357 /* For DST manip, map port here to where it's expected. */
358 range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
359 range.min_proto = range.max_proto = exp->saved_proto;
360 range.min_addr = range.max_addr = exp->saved_addr;
361 nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
362
363 /* Do media streams SRC manip according with the parameters
364 * found in the paired expectation.
365 */
366 if (exp->class != SIP_EXPECT_SIGNALLING) {
367 spin_lock_bh(&nf_conntrack_expect_lock);
368 hlist_for_each_entry(pair_exp, &help->expectations, lnode) {
369 if (pair_exp->tuple.src.l3num == nf_ct_l3num(ct) &&
370 pair_exp->tuple.dst.protonum == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum &&
371 nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, &pair_exp->saved_addr) &&
372 ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all == pair_exp->saved_proto.all) {
373 range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
374 range.min_proto.all = range.max_proto.all = pair_exp->tuple.dst.u.all;
375 range.min_addr = range.max_addr = pair_exp->tuple.dst.u3;
376 range_set_for_snat = 1;
377 break;
378 }
379 }
380 spin_unlock_bh(&nf_conntrack_expect_lock);
381 }
382
383 /* When no paired expectation has been found, change src to
384 * where master sends to, but only if the connection actually came
385 * from the same source.
386 */
387 if (!range_set_for_snat &&
388 nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
389 &ct->master->tuplehash[exp->dir].tuple.src.u3)) {
390 range.flags = NF_NAT_RANGE_MAP_IPS;
391 range.min_addr = range.max_addr
392 = ct->master->tuplehash[!exp->dir].tuple.dst.u3;
393 range_set_for_snat = 1;
394 }
395
396 /* Perform SRC manip. */
397 if (range_set_for_snat)
398 nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
399 }
400
nf_nat_sip_expect(struct sk_buff * skb,unsigned int protoff,unsigned int dataoff,const char ** dptr,unsigned int * datalen,struct nf_conntrack_expect * exp,unsigned int matchoff,unsigned int matchlen)401 static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff,
402 unsigned int dataoff,
403 const char **dptr, unsigned int *datalen,
404 struct nf_conntrack_expect *exp,
405 unsigned int matchoff,
406 unsigned int matchlen)
407 {
408 enum ip_conntrack_info ctinfo;
409 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
410 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
411 struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
412 union nf_inet_addr newaddr;
413 u_int16_t port;
414 __be16 srcport;
415 char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
416 unsigned int buflen;
417
418 if (!ct_sip_info)
419 return NF_DROP;
420
421 /* Connection will come from reply */
422 if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
423 &ct->tuplehash[!dir].tuple.dst.u3))
424 newaddr = exp->tuple.dst.u3;
425 else
426 newaddr = ct->tuplehash[!dir].tuple.dst.u3;
427
428 /* If the signalling port matches the connection's source port in the
429 * original direction, try to use the destination port in the opposite
430 * direction. */
431 srcport = ct_sip_info->forced_dport ? :
432 ct->tuplehash[dir].tuple.src.u.udp.port;
433 if (exp->tuple.dst.u.udp.port == srcport)
434 port = ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port);
435 else
436 port = ntohs(exp->tuple.dst.u.udp.port);
437
438 exp->saved_addr = exp->tuple.dst.u3;
439 exp->tuple.dst.u3 = newaddr;
440 exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
441 exp->dir = !dir;
442 exp->expectfn = nf_nat_sip_expected;
443
444 port = nf_nat_exp_find_port(exp, port);
445 if (port == 0) {
446 nf_ct_helper_log(skb, ct, "all ports in use for SIP");
447 return NF_DROP;
448 }
449
450 if (!nf_inet_addr_cmp(&exp->tuple.dst.u3, &exp->saved_addr) ||
451 exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) {
452 buflen = sip_sprintf_addr_port(ct, buffer, sizeof(buffer),
453 &newaddr, port);
454 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
455 matchoff, matchlen, buffer, buflen)) {
456 nf_ct_helper_log(skb, ct, "cannot mangle packet");
457 goto err;
458 }
459 }
460 return NF_ACCEPT;
461
462 err:
463 nf_ct_unexpect_related(exp);
464 return NF_DROP;
465 }
466
mangle_content_len(struct sk_buff * skb,unsigned int protoff,unsigned int dataoff,const char ** dptr,unsigned int * datalen)467 static int mangle_content_len(struct sk_buff *skb, unsigned int protoff,
468 unsigned int dataoff,
469 const char **dptr, unsigned int *datalen)
470 {
471 enum ip_conntrack_info ctinfo;
472 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
473 char buffer[sizeof("4294967295")];
474 unsigned int matchoff, matchlen;
475 int buflen, c_len;
476
477 /* Get actual SDP length */
478 if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
479 SDP_HDR_VERSION, SDP_HDR_UNSPEC,
480 &matchoff, &matchlen) <= 0)
481 return 0;
482 c_len = *datalen - matchoff + strlen("v=");
483
484 /* Now, update SDP length */
485 if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CONTENT_LENGTH,
486 &matchoff, &matchlen) <= 0)
487 return 0;
488
489 buflen = scnprintf(buffer, sizeof(buffer), "%u", c_len);
490 return mangle_packet(skb, protoff, dataoff, dptr, datalen,
491 matchoff, matchlen, buffer, buflen);
492 }
493
mangle_sdp_packet(struct sk_buff * skb,unsigned int protoff,unsigned int dataoff,const char ** dptr,unsigned int * datalen,unsigned int sdpoff,enum sdp_header_types type,enum sdp_header_types term,char * buffer,int buflen)494 static int mangle_sdp_packet(struct sk_buff *skb, unsigned int protoff,
495 unsigned int dataoff,
496 const char **dptr, unsigned int *datalen,
497 unsigned int sdpoff,
498 enum sdp_header_types type,
499 enum sdp_header_types term,
500 char *buffer, int buflen)
501 {
502 enum ip_conntrack_info ctinfo;
503 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
504 unsigned int matchlen, matchoff;
505
506 if (ct_sip_get_sdp_header(ct, *dptr, sdpoff, *datalen, type, term,
507 &matchoff, &matchlen) <= 0)
508 return -ENOENT;
509 return mangle_packet(skb, protoff, dataoff, dptr, datalen,
510 matchoff, matchlen, buffer, buflen) ? 0 : -EINVAL;
511 }
512
nf_nat_sdp_addr(struct sk_buff * skb,unsigned int protoff,unsigned int dataoff,const char ** dptr,unsigned int * datalen,unsigned int sdpoff,enum sdp_header_types type,enum sdp_header_types term,const union nf_inet_addr * addr)513 static unsigned int nf_nat_sdp_addr(struct sk_buff *skb, unsigned int protoff,
514 unsigned int dataoff,
515 const char **dptr, unsigned int *datalen,
516 unsigned int sdpoff,
517 enum sdp_header_types type,
518 enum sdp_header_types term,
519 const union nf_inet_addr *addr)
520 {
521 enum ip_conntrack_info ctinfo;
522 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
523 char buffer[INET6_ADDRSTRLEN];
524 unsigned int buflen;
525
526 buflen = sip_sprintf_addr(ct, buffer, sizeof(buffer), addr, false);
527 if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen,
528 sdpoff, type, term, buffer, buflen))
529 return 0;
530
531 return mangle_content_len(skb, protoff, dataoff, dptr, datalen);
532 }
533
nf_nat_sdp_port(struct sk_buff * skb,unsigned int protoff,unsigned int dataoff,const char ** dptr,unsigned int * datalen,unsigned int matchoff,unsigned int matchlen,u_int16_t port)534 static unsigned int nf_nat_sdp_port(struct sk_buff *skb, unsigned int protoff,
535 unsigned int dataoff,
536 const char **dptr, unsigned int *datalen,
537 unsigned int matchoff,
538 unsigned int matchlen,
539 u_int16_t port)
540 {
541 char buffer[sizeof("nnnnn")];
542 unsigned int buflen;
543
544 buflen = scnprintf(buffer, sizeof(buffer), "%u", port);
545 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
546 matchoff, matchlen, buffer, buflen))
547 return 0;
548
549 return mangle_content_len(skb, protoff, dataoff, dptr, datalen);
550 }
551
nf_nat_sdp_session(struct sk_buff * skb,unsigned int protoff,unsigned int dataoff,const char ** dptr,unsigned int * datalen,unsigned int sdpoff,const union nf_inet_addr * addr)552 static unsigned int nf_nat_sdp_session(struct sk_buff *skb, unsigned int protoff,
553 unsigned int dataoff,
554 const char **dptr, unsigned int *datalen,
555 unsigned int sdpoff,
556 const union nf_inet_addr *addr)
557 {
558 enum ip_conntrack_info ctinfo;
559 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
560 char buffer[INET6_ADDRSTRLEN];
561 unsigned int buflen;
562
563 /* Mangle session description owner and contact addresses */
564 buflen = sip_sprintf_addr(ct, buffer, sizeof(buffer), addr, false);
565 if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, sdpoff,
566 SDP_HDR_OWNER, SDP_HDR_MEDIA, buffer, buflen))
567 return 0;
568
569 switch (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, sdpoff,
570 SDP_HDR_CONNECTION, SDP_HDR_MEDIA,
571 buffer, buflen)) {
572 case 0:
573 /*
574 * RFC 2327:
575 *
576 * Session description
577 *
578 * c=* (connection information - not required if included in all media)
579 */
580 case -ENOENT:
581 break;
582 default:
583 return 0;
584 }
585
586 return mangle_content_len(skb, protoff, dataoff, dptr, datalen);
587 }
588
589 /* So, this packet has hit the connection tracking matching code.
590 Mangle it, and change the expectation to match the new version. */
nf_nat_sdp_media(struct sk_buff * skb,unsigned int protoff,unsigned int dataoff,const char ** dptr,unsigned int * datalen,struct nf_conntrack_expect * rtp_exp,struct nf_conntrack_expect * rtcp_exp,unsigned int mediaoff,unsigned int medialen,union nf_inet_addr * rtp_addr)591 static unsigned int nf_nat_sdp_media(struct sk_buff *skb, unsigned int protoff,
592 unsigned int dataoff,
593 const char **dptr, unsigned int *datalen,
594 struct nf_conntrack_expect *rtp_exp,
595 struct nf_conntrack_expect *rtcp_exp,
596 unsigned int mediaoff,
597 unsigned int medialen,
598 union nf_inet_addr *rtp_addr)
599 {
600 struct nf_conntrack_expect *rtp_pair[2] = { rtp_exp, rtcp_exp };
601 enum ip_conntrack_info ctinfo;
602 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
603 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
604 u_int16_t port;
605
606 /* Connection will come from reply */
607 if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
608 &ct->tuplehash[!dir].tuple.dst.u3))
609 *rtp_addr = rtp_exp->tuple.dst.u3;
610 else
611 *rtp_addr = ct->tuplehash[!dir].tuple.dst.u3;
612
613 rtp_exp->saved_addr = rtp_exp->tuple.dst.u3;
614 rtp_exp->tuple.dst.u3 = *rtp_addr;
615 rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
616 rtp_exp->dir = !dir;
617 rtp_exp->expectfn = nf_nat_sip_expected;
618
619 rtcp_exp->saved_addr = rtcp_exp->tuple.dst.u3;
620 rtcp_exp->tuple.dst.u3 = *rtp_addr;
621 rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
622 rtcp_exp->dir = !dir;
623 rtcp_exp->expectfn = nf_nat_sip_expected;
624
625 /* Try to get same pair of ports: if not, try to change them. */
626 for (port = ntohs(rtp_exp->tuple.dst.u.udp.port);
627 port != 0; port += 2) {
628 int ret;
629
630 rtp_exp->tuple.dst.u.udp.port = htons(port);
631 rtcp_exp->tuple.dst.u.udp.port = htons(port + 1);
632
633 ret = nf_ct_expect_related_pair(rtp_pair,
634 NF_CT_EXP_F_SKIP_MASTER);
635 if (ret == 0)
636 break;
637 else if (ret == -EBUSY)
638 continue;
639 else if (ret < 0) {
640 port = 0;
641 break;
642 }
643 }
644
645 if (port == 0) {
646 nf_ct_helper_log(skb, ct, "all ports in use for SDP media");
647 goto err1;
648 }
649
650 /* Update media port. */
651 if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port &&
652 !nf_nat_sdp_port(skb, protoff, dataoff, dptr, datalen,
653 mediaoff, medialen, port)) {
654 nf_ct_helper_log(skb, ct, "cannot mangle SDP message");
655 goto err2;
656 }
657
658 return NF_ACCEPT;
659
660 err2:
661 nf_ct_unexpect_related(rtp_exp);
662 nf_ct_unexpect_related(rtcp_exp);
663 err1:
664 return NF_DROP;
665 }
666
667 static struct nf_ct_helper_expectfn sip_nat = {
668 .name = "sip",
669 .expectfn = nf_nat_sip_expected,
670 };
671
nf_nat_sip_fini(void)672 static void __exit nf_nat_sip_fini(void)
673 {
674 nf_nat_helper_unregister(&nat_helper_sip);
675 RCU_INIT_POINTER(nf_nat_sip_hooks, NULL);
676 nf_ct_helper_expectfn_unregister(&sip_nat);
677 synchronize_rcu();
678 nf_ct_helper_expectfn_destroy(&sip_nat);
679 }
680
681 static const struct nf_nat_sip_hooks sip_hooks = {
682 .msg = nf_nat_sip,
683 .seq_adjust = nf_nat_sip_seq_adjust,
684 .expect = nf_nat_sip_expect,
685 .sdp_addr = nf_nat_sdp_addr,
686 .sdp_port = nf_nat_sdp_port,
687 .sdp_session = nf_nat_sdp_session,
688 .sdp_media = nf_nat_sdp_media,
689 };
690
nf_nat_sip_init(void)691 static int __init nf_nat_sip_init(void)
692 {
693 BUG_ON(nf_nat_sip_hooks != NULL);
694 nf_nat_helper_register(&nat_helper_sip);
695 RCU_INIT_POINTER(nf_nat_sip_hooks, &sip_hooks);
696 nf_ct_helper_expectfn_register(&sip_nat);
697 return 0;
698 }
699
700 module_init(nf_nat_sip_init);
701 module_exit(nf_nat_sip_fini);
702