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