Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nf_conntrack_sip: pass data offset to NAT functions

When using TCP multiple SIP messages might be present in a single packet.
A following patch will parse them by setting the dptr to the beginning of
each message. The NAT helper needs to reload the dptr value after mangling
the packet however, so it needs to know the offset of the message to the
beginning of the packet.

Signed-off-by: Patrick McHardy <kaber@trash.net>

+105 -92
+10 -4
include/linux/netfilter/nf_conntrack_sip.h
··· 34 34 struct sip_handler { 35 35 const char *method; 36 36 unsigned int len; 37 - int (*request)(struct sk_buff *skb, 37 + int (*request)(struct sk_buff *skb, unsigned int dataoff, 38 38 const char **dptr, unsigned int *datalen, 39 39 unsigned int cseq); 40 - int (*response)(struct sk_buff *skb, 40 + int (*response)(struct sk_buff *skb, unsigned int dataoff, 41 41 const char **dptr, unsigned int *datalen, 42 42 unsigned int cseq, unsigned int code); 43 43 }; ··· 100 100 }; 101 101 102 102 extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, 103 + unsigned int dataoff, 103 104 const char **dptr, 104 105 unsigned int *datalen); 105 106 extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, 107 + unsigned int dataoff, 106 108 const char **dptr, 107 109 unsigned int *datalen, 108 110 struct nf_conntrack_expect *exp, 109 111 unsigned int matchoff, 110 112 unsigned int matchlen); 111 113 extern unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, 112 - const char **dptr, 113 114 unsigned int dataoff, 115 + const char **dptr, 114 116 unsigned int *datalen, 117 + unsigned int sdpoff, 115 118 enum sdp_header_types type, 116 119 enum sdp_header_types term, 117 120 const union nf_inet_addr *addr); 118 121 extern unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, 122 + unsigned int dataoff, 119 123 const char **dptr, 120 124 unsigned int *datalen, 121 125 unsigned int matchoff, 122 126 unsigned int matchlen, 123 127 u_int16_t port); 124 128 extern unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb, 125 - const char **dptr, 126 129 unsigned int dataoff, 130 + const char **dptr, 127 131 unsigned int *datalen, 132 + unsigned int sdpoff, 128 133 const union nf_inet_addr *addr); 129 134 extern unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, 135 + unsigned int dataoff, 130 136 const char **dptr, 131 137 unsigned int *datalen, 132 138 struct nf_conntrack_expect *rtp_exp,
+51 -50
net/ipv4/netfilter/nf_nat_sip.c
··· 29 29 MODULE_ALIAS("ip_nat_sip"); 30 30 31 31 32 - static unsigned int mangle_packet(struct sk_buff *skb, 32 + static unsigned int mangle_packet(struct sk_buff *skb, unsigned int dataoff, 33 33 const char **dptr, unsigned int *datalen, 34 34 unsigned int matchoff, unsigned int matchlen, 35 35 const char *buffer, unsigned int buflen) ··· 42 42 return 0; 43 43 44 44 /* Reload data pointer and adjust datalen value */ 45 - *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr); 45 + *dptr = skb->data + dataoff; 46 46 *datalen += buflen - matchlen; 47 47 return 1; 48 48 } 49 49 50 - static int map_addr(struct sk_buff *skb, 50 + static int map_addr(struct sk_buff *skb, unsigned int dataoff, 51 51 const char **dptr, unsigned int *datalen, 52 52 unsigned int matchoff, unsigned int matchlen, 53 53 union nf_inet_addr *addr, __be16 port) ··· 76 76 77 77 buflen = sprintf(buffer, "%pI4:%u", &newaddr, ntohs(newport)); 78 78 79 - return mangle_packet(skb, dptr, datalen, matchoff, matchlen, 79 + return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen, 80 80 buffer, buflen); 81 81 } 82 82 83 - static int map_sip_addr(struct sk_buff *skb, 83 + static int map_sip_addr(struct sk_buff *skb, unsigned int dataoff, 84 84 const char **dptr, unsigned int *datalen, 85 85 enum sip_header_types type) 86 86 { ··· 93 93 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL, 94 94 &matchoff, &matchlen, &addr, &port) <= 0) 95 95 return 1; 96 - return map_addr(skb, dptr, datalen, matchoff, matchlen, &addr, port); 96 + return map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, 97 + &addr, port); 97 98 } 98 99 99 - static unsigned int ip_nat_sip(struct sk_buff *skb, 100 + static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, 100 101 const char **dptr, unsigned int *datalen) 101 102 { 102 103 enum ip_conntrack_info ctinfo; 103 104 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 104 105 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 105 - unsigned int dataoff, matchoff, matchlen; 106 + unsigned int coff, matchoff, matchlen; 106 107 union nf_inet_addr addr; 107 108 __be16 port; 108 109 int request, in_header; ··· 113 112 if (ct_sip_parse_request(ct, *dptr, *datalen, 114 113 &matchoff, &matchlen, 115 114 &addr, &port) > 0 && 116 - !map_addr(skb, dptr, datalen, matchoff, matchlen, 115 + !map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, 117 116 &addr, port)) 118 117 return NF_DROP; 119 118 request = 1; ··· 139 138 goto next; 140 139 } 141 140 142 - if (!map_addr(skb, dptr, datalen, matchoff, matchlen, 141 + if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, 143 142 &addr, port)) 144 143 return NF_DROP; 145 144 ··· 154 153 addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) { 155 154 buflen = sprintf(buffer, "%pI4", 156 155 &ct->tuplehash[!dir].tuple.dst.u3.ip); 157 - if (!mangle_packet(skb, dptr, datalen, poff, plen, 158 - buffer, buflen)) 156 + if (!mangle_packet(skb, dataoff, dptr, datalen, 157 + poff, plen, buffer, buflen)) 159 158 return NF_DROP; 160 159 } 161 160 ··· 168 167 addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { 169 168 buflen = sprintf(buffer, "%pI4", 170 169 &ct->tuplehash[!dir].tuple.src.u3.ip); 171 - if (!mangle_packet(skb, dptr, datalen, poff, plen, 172 - buffer, buflen)) 170 + if (!mangle_packet(skb, dataoff, dptr, datalen, 171 + poff, plen, buffer, buflen)) 173 172 return NF_DROP; 174 173 } 175 174 ··· 182 181 htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) { 183 182 __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port; 184 183 buflen = sprintf(buffer, "%u", ntohs(p)); 185 - if (!mangle_packet(skb, dptr, datalen, poff, plen, 186 - buffer, buflen)) 184 + if (!mangle_packet(skb, dataoff, dptr, datalen, 185 + poff, plen, buffer, buflen)) 187 186 return NF_DROP; 188 187 } 189 188 } 190 189 191 190 next: 192 191 /* Translate Contact headers */ 193 - dataoff = 0; 192 + coff = 0; 194 193 in_header = 0; 195 - while (ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen, 194 + while (ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen, 196 195 SIP_HDR_CONTACT, &in_header, 197 196 &matchoff, &matchlen, 198 197 &addr, &port) > 0) { 199 - if (!map_addr(skb, dptr, datalen, matchoff, matchlen, 198 + if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, 200 199 &addr, port)) 201 200 return NF_DROP; 202 201 } 203 202 204 - if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM) || 205 - !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO)) 203 + if (!map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_FROM) || 204 + !map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_TO)) 206 205 return NF_DROP; 207 206 return NF_ACCEPT; 208 207 } ··· 233 232 } 234 233 } 235 234 236 - static unsigned int ip_nat_sip_expect(struct sk_buff *skb, 235 + static unsigned int ip_nat_sip_expect(struct sk_buff *skb, unsigned int dataoff, 237 236 const char **dptr, unsigned int *datalen, 238 237 struct nf_conntrack_expect *exp, 239 238 unsigned int matchoff, ··· 280 279 if (exp->tuple.dst.u3.ip != exp->saved_ip || 281 280 exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) { 282 281 buflen = sprintf(buffer, "%pI4:%u", &newip, port); 283 - if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen, 284 - buffer, buflen)) 282 + if (!mangle_packet(skb, dataoff, dptr, datalen, 283 + matchoff, matchlen, buffer, buflen)) 285 284 goto err; 286 285 } 287 286 return NF_ACCEPT; ··· 291 290 return NF_DROP; 292 291 } 293 292 294 - static int mangle_content_len(struct sk_buff *skb, 293 + static int mangle_content_len(struct sk_buff *skb, unsigned int dataoff, 295 294 const char **dptr, unsigned int *datalen) 296 295 { 297 296 enum ip_conntrack_info ctinfo; ··· 313 312 return 0; 314 313 315 314 buflen = sprintf(buffer, "%u", c_len); 316 - return mangle_packet(skb, dptr, datalen, matchoff, matchlen, 315 + return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen, 317 316 buffer, buflen); 318 317 } 319 318 320 - static int mangle_sdp_packet(struct sk_buff *skb, const char **dptr, 321 - unsigned int dataoff, unsigned int *datalen, 319 + static int mangle_sdp_packet(struct sk_buff *skb, unsigned int dataoff, 320 + const char **dptr, unsigned int *datalen, 321 + unsigned int sdpoff, 322 322 enum sdp_header_types type, 323 323 enum sdp_header_types term, 324 324 char *buffer, int buflen) ··· 328 326 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 329 327 unsigned int matchlen, matchoff; 330 328 331 - if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term, 329 + if (ct_sip_get_sdp_header(ct, *dptr, sdpoff, *datalen, type, term, 332 330 &matchoff, &matchlen) <= 0) 333 331 return -ENOENT; 334 - return mangle_packet(skb, dptr, datalen, matchoff, matchlen, 332 + return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen, 335 333 buffer, buflen) ? 0 : -EINVAL; 336 334 } 337 335 338 - static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr, 339 - unsigned int dataoff, 340 - unsigned int *datalen, 336 + static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, unsigned int dataoff, 337 + const char **dptr, unsigned int *datalen, 338 + unsigned int sdpoff, 341 339 enum sdp_header_types type, 342 340 enum sdp_header_types term, 343 341 const union nf_inet_addr *addr) ··· 346 344 unsigned int buflen; 347 345 348 346 buflen = sprintf(buffer, "%pI4", &addr->ip); 349 - if (mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term, 347 + if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff, type, term, 350 348 buffer, buflen)) 351 349 return 0; 352 350 353 - return mangle_content_len(skb, dptr, datalen); 351 + return mangle_content_len(skb, dataoff, dptr, datalen); 354 352 } 355 353 356 - static unsigned int ip_nat_sdp_port(struct sk_buff *skb, 357 - const char **dptr, 358 - unsigned int *datalen, 354 + static unsigned int ip_nat_sdp_port(struct sk_buff *skb, unsigned int dataoff, 355 + const char **dptr, unsigned int *datalen, 359 356 unsigned int matchoff, 360 357 unsigned int matchlen, 361 358 u_int16_t port) ··· 363 362 unsigned int buflen; 364 363 365 364 buflen = sprintf(buffer, "%u", port); 366 - if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen, 365 + if (!mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen, 367 366 buffer, buflen)) 368 367 return 0; 369 368 370 - return mangle_content_len(skb, dptr, datalen); 369 + return mangle_content_len(skb, dataoff, dptr, datalen); 371 370 } 372 371 373 - static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr, 374 - unsigned int dataoff, 375 - unsigned int *datalen, 372 + static unsigned int ip_nat_sdp_session(struct sk_buff *skb, unsigned int dataoff, 373 + const char **dptr, unsigned int *datalen, 374 + unsigned int sdpoff, 376 375 const union nf_inet_addr *addr) 377 376 { 378 377 char buffer[sizeof("nnn.nnn.nnn.nnn")]; ··· 380 379 381 380 /* Mangle session description owner and contact addresses */ 382 381 buflen = sprintf(buffer, "%pI4", &addr->ip); 383 - if (mangle_sdp_packet(skb, dptr, dataoff, datalen, 382 + if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff, 384 383 SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA, 385 384 buffer, buflen)) 386 385 return 0; 387 386 388 - switch (mangle_sdp_packet(skb, dptr, dataoff, datalen, 387 + switch (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff, 389 388 SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA, 390 389 buffer, buflen)) { 391 390 case 0: ··· 402 401 return 0; 403 402 } 404 403 405 - return mangle_content_len(skb, dptr, datalen); 404 + return mangle_content_len(skb, dataoff, dptr, datalen); 406 405 } 407 406 408 407 /* So, this packet has hit the connection tracking matching code. 409 408 Mangle it, and change the expectation to match the new version. */ 410 - static unsigned int ip_nat_sdp_media(struct sk_buff *skb, 411 - const char **dptr, 412 - unsigned int *datalen, 409 + static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff, 410 + const char **dptr, unsigned int *datalen, 413 411 struct nf_conntrack_expect *rtp_exp, 414 412 struct nf_conntrack_expect *rtcp_exp, 415 413 unsigned int mediaoff, ··· 456 456 457 457 /* Update media port. */ 458 458 if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port && 459 - !ip_nat_sdp_port(skb, dptr, datalen, mediaoff, medialen, port)) 459 + !ip_nat_sdp_port(skb, dataoff, dptr, datalen, 460 + mediaoff, medialen, port)) 460 461 goto err2; 461 462 462 463 return NF_ACCEPT;
+44 -38
net/netfilter/nf_conntrack_sip.c
··· 50 50 MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling " 51 51 "endpoints only (default 1)"); 52 52 53 - unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, 53 + unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, unsigned int dataoff, 54 54 const char **dptr, 55 55 unsigned int *datalen) __read_mostly; 56 56 EXPORT_SYMBOL_GPL(nf_nat_sip_hook); 57 57 58 58 unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, 59 + unsigned int dataoff, 59 60 const char **dptr, 60 61 unsigned int *datalen, 61 62 struct nf_conntrack_expect *exp, ··· 64 63 unsigned int matchlen) __read_mostly; 65 64 EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook); 66 65 67 - unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, 66 + unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, unsigned int dataoff, 68 67 const char **dptr, 69 - unsigned int dataoff, 70 68 unsigned int *datalen, 69 + unsigned int sdpoff, 71 70 enum sdp_header_types type, 72 71 enum sdp_header_types term, 73 72 const union nf_inet_addr *addr) 74 73 __read_mostly; 75 74 EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook); 76 75 77 - unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, 76 + unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, unsigned int dataoff, 78 77 const char **dptr, 79 78 unsigned int *datalen, 80 79 unsigned int matchoff, ··· 83 82 EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook); 84 83 85 84 unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb, 86 - const char **dptr, 87 85 unsigned int dataoff, 86 + const char **dptr, 88 87 unsigned int *datalen, 88 + unsigned int sdpoff, 89 89 const union nf_inet_addr *addr) 90 90 __read_mostly; 91 91 EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook); 92 92 93 - unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, 93 + unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, unsigned int dataoff, 94 94 const char **dptr, 95 95 unsigned int *datalen, 96 96 struct nf_conntrack_expect *rtp_exp, ··· 731 729 spin_unlock_bh(&nf_conntrack_lock); 732 730 } 733 731 734 - static int set_expected_rtp_rtcp(struct sk_buff *skb, 732 + static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff, 735 733 const char **dptr, unsigned int *datalen, 736 734 union nf_inet_addr *daddr, __be16 port, 737 735 enum sip_expectation_classes class, ··· 808 806 if (direct_rtp) { 809 807 nf_nat_sdp_port = rcu_dereference(nf_nat_sdp_port_hook); 810 808 if (nf_nat_sdp_port && 811 - !nf_nat_sdp_port(skb, dptr, datalen, 809 + !nf_nat_sdp_port(skb, dataoff, dptr, datalen, 812 810 mediaoff, medialen, ntohs(rtp_port))) 813 811 goto err1; 814 812 } ··· 830 828 831 829 nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook); 832 830 if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp) 833 - ret = nf_nat_sdp_media(skb, dptr, datalen, rtp_exp, rtcp_exp, 831 + ret = nf_nat_sdp_media(skb, dataoff, dptr, datalen, 832 + rtp_exp, rtcp_exp, 834 833 mediaoff, medialen, daddr); 835 834 else { 836 835 if (nf_ct_expect_related(rtp_exp) == 0) { ··· 870 867 return NULL; 871 868 } 872 869 873 - static int process_sdp(struct sk_buff *skb, 870 + static int process_sdp(struct sk_buff *skb, unsigned int dataoff, 874 871 const char **dptr, unsigned int *datalen, 875 872 unsigned int cseq) 876 873 { ··· 945 942 else 946 943 return NF_DROP; 947 944 948 - ret = set_expected_rtp_rtcp(skb, dptr, datalen, 945 + ret = set_expected_rtp_rtcp(skb, dataoff, dptr, datalen, 949 946 &rtp_addr, htons(port), t->class, 950 947 mediaoff, medialen); 951 948 if (ret != NF_ACCEPT) ··· 953 950 954 951 /* Update media connection address if present */ 955 952 if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) { 956 - ret = nf_nat_sdp_addr(skb, dptr, mediaoff, datalen, 957 - c_hdr, SDP_HDR_MEDIA, &rtp_addr); 953 + ret = nf_nat_sdp_addr(skb, dataoff, dptr, datalen, 954 + mediaoff, c_hdr, SDP_HDR_MEDIA, 955 + &rtp_addr); 958 956 if (ret != NF_ACCEPT) 959 957 return ret; 960 958 } ··· 965 961 /* Update session connection and owner addresses */ 966 962 nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook); 967 963 if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK) 968 - ret = nf_nat_sdp_session(skb, dptr, sdpoff, datalen, &rtp_addr); 964 + ret = nf_nat_sdp_session(skb, dataoff, dptr, datalen, sdpoff, 965 + &rtp_addr); 969 966 970 967 if (ret == NF_ACCEPT && i > 0) 971 968 help->help.ct_sip_info.invite_cseq = cseq; 972 969 973 970 return ret; 974 971 } 975 - static int process_invite_response(struct sk_buff *skb, 972 + static int process_invite_response(struct sk_buff *skb, unsigned int dataoff, 976 973 const char **dptr, unsigned int *datalen, 977 974 unsigned int cseq, unsigned int code) 978 975 { ··· 983 978 984 979 if ((code >= 100 && code <= 199) || 985 980 (code >= 200 && code <= 299)) 986 - return process_sdp(skb, dptr, datalen, cseq); 981 + return process_sdp(skb, dataoff, dptr, datalen, cseq); 987 982 else if (help->help.ct_sip_info.invite_cseq == cseq) 988 983 flush_expectations(ct, true); 989 984 return NF_ACCEPT; 990 985 } 991 986 992 - static int process_update_response(struct sk_buff *skb, 987 + static int process_update_response(struct sk_buff *skb, unsigned int dataoff, 993 988 const char **dptr, unsigned int *datalen, 994 989 unsigned int cseq, unsigned int code) 995 990 { ··· 999 994 1000 995 if ((code >= 100 && code <= 199) || 1001 996 (code >= 200 && code <= 299)) 1002 - return process_sdp(skb, dptr, datalen, cseq); 997 + return process_sdp(skb, dataoff, dptr, datalen, cseq); 1003 998 else if (help->help.ct_sip_info.invite_cseq == cseq) 1004 999 flush_expectations(ct, true); 1005 1000 return NF_ACCEPT; 1006 1001 } 1007 1002 1008 - static int process_prack_response(struct sk_buff *skb, 1003 + static int process_prack_response(struct sk_buff *skb, unsigned int dataoff, 1009 1004 const char **dptr, unsigned int *datalen, 1010 1005 unsigned int cseq, unsigned int code) 1011 1006 { ··· 1015 1010 1016 1011 if ((code >= 100 && code <= 199) || 1017 1012 (code >= 200 && code <= 299)) 1018 - return process_sdp(skb, dptr, datalen, cseq); 1013 + return process_sdp(skb, dataoff, dptr, datalen, cseq); 1019 1014 else if (help->help.ct_sip_info.invite_cseq == cseq) 1020 1015 flush_expectations(ct, true); 1021 1016 return NF_ACCEPT; 1022 1017 } 1023 1018 1024 - static int process_bye_request(struct sk_buff *skb, 1019 + static int process_bye_request(struct sk_buff *skb, unsigned int dataoff, 1025 1020 const char **dptr, unsigned int *datalen, 1026 1021 unsigned int cseq) 1027 1022 { ··· 1036 1031 * signalling connections. The expectation is marked inactive and is activated 1037 1032 * when receiving a response indicating success from the registrar. 1038 1033 */ 1039 - static int process_register_request(struct sk_buff *skb, 1034 + static int process_register_request(struct sk_buff *skb, unsigned int dataoff, 1040 1035 const char **dptr, unsigned int *datalen, 1041 1036 unsigned int cseq) 1042 1037 { ··· 1106 1101 1107 1102 nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook); 1108 1103 if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK) 1109 - ret = nf_nat_sip_expect(skb, dptr, datalen, exp, 1104 + ret = nf_nat_sip_expect(skb, dataoff, dptr, datalen, exp, 1110 1105 matchoff, matchlen); 1111 1106 else { 1112 1107 if (nf_ct_expect_related(exp) != 0) ··· 1122 1117 return ret; 1123 1118 } 1124 1119 1125 - static int process_register_response(struct sk_buff *skb, 1120 + static int process_register_response(struct sk_buff *skb, unsigned int dataoff, 1126 1121 const char **dptr, unsigned int *datalen, 1127 1122 unsigned int cseq, unsigned int code) 1128 1123 { ··· 1132 1127 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 1133 1128 union nf_inet_addr addr; 1134 1129 __be16 port; 1135 - unsigned int matchoff, matchlen, dataoff = 0; 1130 + unsigned int matchoff, matchlen, coff = 0; 1136 1131 unsigned int expires = 0; 1137 1132 int in_contact = 0, ret; 1138 1133 ··· 1159 1154 while (1) { 1160 1155 unsigned int c_expires = expires; 1161 1156 1162 - ret = ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen, 1157 + ret = ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen, 1163 1158 SIP_HDR_CONTACT, &in_contact, 1164 1159 &matchoff, &matchlen, 1165 1160 &addr, &port); ··· 1198 1193 SIP_HANDLER("REGISTER", process_register_request, process_register_response), 1199 1194 }; 1200 1195 1201 - static int process_sip_response(struct sk_buff *skb, 1196 + static int process_sip_response(struct sk_buff *skb, unsigned int dataoff, 1202 1197 const char **dptr, unsigned int *datalen) 1203 1198 { 1204 1199 enum ip_conntrack_info ctinfo; 1205 1200 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1206 - unsigned int matchoff, matchlen; 1207 - unsigned int code, cseq, dataoff, i; 1201 + unsigned int matchoff, matchlen, matchend; 1202 + unsigned int code, cseq, i; 1208 1203 1209 1204 if (*datalen < strlen("SIP/2.0 200")) 1210 1205 return NF_ACCEPT; ··· 1218 1213 cseq = simple_strtoul(*dptr + matchoff, NULL, 10); 1219 1214 if (!cseq) 1220 1215 return NF_DROP; 1221 - dataoff = matchoff + matchlen + 1; 1216 + matchend = matchoff + matchlen + 1; 1222 1217 1223 1218 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { 1224 1219 const struct sip_handler *handler; ··· 1226 1221 handler = &sip_handlers[i]; 1227 1222 if (handler->response == NULL) 1228 1223 continue; 1229 - if (*datalen < dataoff + handler->len || 1230 - strnicmp(*dptr + dataoff, handler->method, handler->len)) 1224 + if (*datalen < matchend + handler->len || 1225 + strnicmp(*dptr + matchend, handler->method, handler->len)) 1231 1226 continue; 1232 - return handler->response(skb, dptr, datalen, cseq, code); 1227 + return handler->response(skb, dataoff, dptr, datalen, 1228 + cseq, code); 1233 1229 } 1234 1230 return NF_ACCEPT; 1235 1231 } 1236 1232 1237 - static int process_sip_request(struct sk_buff *skb, 1233 + static int process_sip_request(struct sk_buff *skb, unsigned int dataoff, 1238 1234 const char **dptr, unsigned int *datalen) 1239 1235 { 1240 1236 enum ip_conntrack_info ctinfo; ··· 1260 1254 if (!cseq) 1261 1255 return NF_DROP; 1262 1256 1263 - return handler->request(skb, dptr, datalen, cseq); 1257 + return handler->request(skb, dataoff, dptr, datalen, cseq); 1264 1258 } 1265 1259 return NF_ACCEPT; 1266 1260 } ··· 1294 1288 return NF_ACCEPT; 1295 1289 1296 1290 if (strnicmp(dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0) 1297 - ret = process_sip_request(skb, &dptr, &datalen); 1291 + ret = process_sip_request(skb, dataoff, &dptr, &datalen); 1298 1292 else 1299 - ret = process_sip_response(skb, &dptr, &datalen); 1293 + ret = process_sip_response(skb, dataoff, &dptr, &datalen); 1300 1294 1301 1295 if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { 1302 1296 nf_nat_sip = rcu_dereference(nf_nat_sip_hook); 1303 - if (nf_nat_sip && !nf_nat_sip(skb, &dptr, &datalen)) 1297 + if (nf_nat_sip && !nf_nat_sip(skb, dataoff, &dptr, &datalen)) 1304 1298 ret = NF_DROP; 1305 1299 } 1306 1300