@@ -29,95 +29,132 @@ MODULE_DESCRIPTION("SIP NAT helper");
2929#define DEBUGP (format , args ...)
3030#endif
3131
32- static unsigned int mangle_sip_packet (struct sk_buff * * pskb ,
33- enum ip_conntrack_info ctinfo ,
34- struct ip_conntrack * ct ,
35- const char * * dptr , size_t dlen ,
36- char * buffer , int bufflen ,
37- enum sip_header_pos pos )
32+ struct addr_map {
33+ struct {
34+ char src [sizeof ("nnn.nnn.nnn.nnn:nnnnn" )];
35+ char dst [sizeof ("nnn.nnn.nnn.nnn:nnnnn" )];
36+ unsigned int srclen , srciplen ;
37+ unsigned int dstlen , dstiplen ;
38+ } addr [IP_CT_DIR_MAX ];
39+ };
40+
41+ static void addr_map_init (struct ip_conntrack * ct , struct addr_map * map )
3842{
39- unsigned int matchlen , matchoff ;
43+ struct ip_conntrack_tuple * t ;
44+ enum ip_conntrack_dir dir ;
45+ unsigned int n ;
46+
47+ for (dir = 0 ; dir < IP_CT_DIR_MAX ; dir ++ ) {
48+ t = & ct -> tuplehash [dir ].tuple ;
49+
50+ n = sprintf (map -> addr [dir ].src , "%u.%u.%u.%u" ,
51+ NIPQUAD (t -> src .ip ));
52+ map -> addr [dir ].srciplen = n ;
53+ n += sprintf (map -> addr [dir ].src + n , ":%u" ,
54+ ntohs (t -> src .u .udp .port ));
55+ map -> addr [dir ].srclen = n ;
56+
57+ n = sprintf (map -> addr [dir ].dst , "%u.%u.%u.%u" ,
58+ NIPQUAD (t -> dst .ip ));
59+ map -> addr [dir ].dstiplen = n ;
60+ n += sprintf (map -> addr [dir ].dst + n , ":%u" ,
61+ ntohs (t -> dst .u .udp .port ));
62+ map -> addr [dir ].dstlen = n ;
63+ }
64+ }
65+
66+ static int map_sip_addr (struct sk_buff * * pskb , enum ip_conntrack_info ctinfo ,
67+ struct ip_conntrack * ct , const char * * dptr , size_t dlen ,
68+ enum sip_header_pos pos , struct addr_map * map )
69+ {
70+ enum ip_conntrack_dir dir = CTINFO2DIR (ctinfo );
71+ unsigned int matchlen , matchoff , addrlen ;
72+ char * addr ;
4073
4174 if (ct_sip_get_info (* dptr , dlen , & matchoff , & matchlen , pos ) <= 0 )
42- return 0 ;
75+ return 1 ;
76+
77+ if ((matchlen == map -> addr [dir ].srciplen ||
78+ matchlen == map -> addr [dir ].srclen ) &&
79+ memcmp (* dptr + matchoff , map -> addr [dir ].src , matchlen ) == 0 ) {
80+ addr = map -> addr [!dir ].dst ;
81+ addrlen = map -> addr [!dir ].dstlen ;
82+ } else if ((matchlen == map -> addr [dir ].dstiplen ||
83+ matchlen == map -> addr [dir ].dstlen ) &&
84+ memcmp (* dptr + matchoff , map -> addr [dir ].dst , matchlen ) == 0 ) {
85+ addr = map -> addr [!dir ].src ;
86+ addrlen = map -> addr [!dir ].srclen ;
87+ } else
88+ return 1 ;
4389
4490 if (!ip_nat_mangle_udp_packet (pskb , ct , ctinfo ,
45- matchoff , matchlen , buffer , bufflen ))
91+ matchoff , matchlen , addr , addrlen ))
4692 return 0 ;
47-
48- /* We need to reload this. Thanks Patrick. */
4993 * dptr = (* pskb )-> data + (* pskb )-> nh .iph -> ihl * 4 + sizeof (struct udphdr );
5094 return 1 ;
95+
5196}
5297
5398static unsigned int ip_nat_sip (struct sk_buff * * pskb ,
5499 enum ip_conntrack_info ctinfo ,
55100 struct ip_conntrack * ct ,
56101 const char * * dptr )
57102{
58- enum ip_conntrack_dir dir = CTINFO2DIR (ctinfo );
59- char buffer [sizeof ("nnn.nnn.nnn.nnn:nnnnn" )];
60- unsigned int bufflen , dataoff ;
61- __be32 ip ;
62- __be16 port ;
103+ enum sip_header_pos pos ;
104+ struct addr_map map ;
105+ int dataoff , datalen ;
63106
64107 dataoff = (* pskb )-> nh .iph -> ihl * 4 + sizeof (struct udphdr );
108+ datalen = (* pskb )-> len - dataoff ;
109+ if (datalen < sizeof ("SIP/2.0" ) - 1 )
110+ return NF_DROP ;
111+
112+ addr_map_init (ct , & map );
113+
114+ /* Basic rules: requests and responses. */
115+ if (strncmp (* dptr , "SIP/2.0" , sizeof ("SIP/2.0" ) - 1 ) != 0 ) {
116+ /* 10.2: Constructing the REGISTER Request:
117+ *
118+ * The "userinfo" and "@" components of the SIP URI MUST NOT
119+ * be present.
120+ */
121+ if (datalen >= sizeof ("REGISTER" ) - 1 &&
122+ strncmp (* dptr , "REGISTER" , sizeof ("REGISTER" ) - 1 ) == 0 )
123+ pos = POS_REG_REQ_URI ;
124+ else
125+ pos = POS_REQ_URI ;
126+
127+ if (!map_sip_addr (pskb , ctinfo , ct , dptr , datalen , pos , & map ))
128+ return NF_DROP ;
129+ }
65130
66- ip = ct -> tuplehash [!dir ].tuple .dst .ip ;
67- port = ct -> tuplehash [!dir ].tuple .dst .u .udp .port ;
68- bufflen = sprintf (buffer , "%u.%u.%u.%u:%u" , NIPQUAD (ip ), ntohs (port ));
131+ if (!map_sip_addr (pskb , ctinfo , ct , dptr , datalen , POS_FROM , & map ) ||
132+ !map_sip_addr (pskb , ctinfo , ct , dptr , datalen , POS_TO , & map ) ||
133+ !map_sip_addr (pskb , ctinfo , ct , dptr , datalen , POS_VIA , & map ) ||
134+ !map_sip_addr (pskb , ctinfo , ct , dptr , datalen , POS_CONTACT , & map ))
135+ return NF_DROP ;
136+ return NF_ACCEPT ;
137+ }
138+
139+ static unsigned int mangle_sip_packet (struct sk_buff * * pskb ,
140+ enum ip_conntrack_info ctinfo ,
141+ struct ip_conntrack * ct ,
142+ const char * * dptr , size_t dlen ,
143+ char * buffer , int bufflen ,
144+ enum sip_header_pos pos )
145+ {
146+ unsigned int matchlen , matchoff ;
69147
70- /* short packet ? */
71- if (((* pskb )-> len - dataoff ) < (sizeof ("SIP/2.0" ) - 1 ))
148+ if (ct_sip_get_info (* dptr , dlen , & matchoff , & matchlen , pos ) <= 0 )
72149 return 0 ;
73150
74- /* Basic rules: requests and responses. */
75- if (memcmp (* dptr , "SIP/2.0" , sizeof ("SIP/2.0" ) - 1 ) == 0 ) {
76- const char * aux ;
77-
78- if ((ctinfo ) < IP_CT_IS_REPLY ) {
79- mangle_sip_packet (pskb , ctinfo , ct , dptr ,
80- (* pskb )-> len - dataoff ,
81- buffer , bufflen , POS_CONTACT );
82- return 1 ;
83- }
151+ if (!ip_nat_mangle_udp_packet (pskb , ct , ctinfo ,
152+ matchoff , matchlen , buffer , bufflen ))
153+ return 0 ;
84154
85- if (!mangle_sip_packet (pskb , ctinfo , ct , dptr ,
86- (* pskb )-> len - dataoff ,
87- buffer , bufflen , POS_VIA ))
88- return 0 ;
89-
90- aux = ct_sip_search ("CSeq:" , * dptr , sizeof ("CSeq:" ) - 1 ,
91- (* pskb )-> len - dataoff , 0 );
92- if (!aux )
93- return 0 ;
94-
95- if (!ct_sip_search ("REGISTER" , aux , sizeof ("REGISTER" ),
96- ct_sip_lnlen (aux ,
97- * dptr + (* pskb )-> len - dataoff ),
98- 1 ))
99- return 1 ;
100-
101- return mangle_sip_packet (pskb , ctinfo , ct , dptr ,
102- (* pskb )-> len - dataoff ,
103- buffer , bufflen , POS_CONTACT );
104- }
105- if ((ctinfo ) < IP_CT_IS_REPLY ) {
106- if (!mangle_sip_packet (pskb , ctinfo , ct , dptr ,
107- (* pskb )-> len - dataoff ,
108- buffer , bufflen , POS_VIA ))
109- return 0 ;
110-
111- /* Mangle Contact if exists only. - watch udp_nat_mangle()! */
112- mangle_sip_packet (pskb , ctinfo , ct , dptr , (* pskb )-> len - dataoff ,
113- buffer , bufflen , POS_CONTACT );
114- return 1 ;
115- }
116- /* This mangle requests headers. */
117- return mangle_sip_packet (pskb , ctinfo , ct , dptr ,
118- ct_sip_lnlen (* dptr ,
119- * dptr + (* pskb )-> len - dataoff ),
120- buffer , bufflen , POS_REQ_HEADER );
155+ /* We need to reload this. Thanks Patrick. */
156+ * dptr = (* pskb )-> data + (* pskb )-> nh .iph -> ihl * 4 + sizeof (struct udphdr );
157+ return 1 ;
121158}
122159
123160static int mangle_content_len (struct sk_buff * * pskb ,
0 commit comments