... | ... |
@@ -38,6 +38,7 @@ int do_action(struct action* a, struct sip_msg* msg) |
38 | 38 |
int ret; |
39 | 39 |
int v; |
40 | 40 |
union sockaddr_union* to; |
41 |
+ struct socket_info* send_sock; |
|
41 | 42 |
struct proxy_l* p; |
42 | 43 |
char* tmp; |
43 | 44 |
char *new_uri, *end, *crt; |
... | ... |
@@ -144,8 +145,13 @@ int do_action(struct action* a, struct sip_msg* msg) |
144 | 145 |
if (ret==0){ |
145 | 146 |
p->tx++; |
146 | 147 |
p->tx_bytes+=msg->len; |
147 |
- ret=udp_send(msg->orig, msg->len, to, |
|
148 |
- sizeof(union sockaddr_union)); |
|
148 |
+ send_sock=get_send_socket(to); |
|
149 |
+ if (send_sock!=0){ |
|
150 |
+ ret=udp_send(send_sock, msg->orig, msg->len, to, |
|
151 |
+ sizeof(union sockaddr_union)); |
|
152 |
+ }else{ |
|
153 |
+ ret=-1; |
|
154 |
+ } |
|
149 | 155 |
} |
150 | 156 |
free(to); |
151 | 157 |
if (ret<0){ |
... | ... |
@@ -25,7 +25,7 @@ |
25 | 25 |
|
26 | 26 |
static int comment_nest=0; |
27 | 27 |
static int state=0; |
28 |
- static char* str=0; |
|
28 |
+ static char* tstr=0; |
|
29 | 29 |
int line=1; |
30 | 30 |
int column=1; |
31 | 31 |
int startcolumn=1; |
... | ... |
@@ -219,29 +219,29 @@ EAT_ABLE [\ \t\b\r] |
219 | 219 |
|
220 | 220 |
<STRING1>{QUOTES} { count(); state=INITIAL_S; BEGIN(INITIAL); |
221 | 221 |
yytext[yyleng-1]=0; yyleng--; |
222 |
- addstr(yytext, &str); |
|
223 |
- yylval.strval=str; str=0; |
|
222 |
+ addstr(yytext, &tstr); |
|
223 |
+ yylval.strval=tstr; tstr=0; |
|
224 | 224 |
return STRING; |
225 | 225 |
} |
226 | 226 |
<STRING2>{TICK} { count(); state=INITIAL_S; BEGIN(INITIAL); |
227 | 227 |
yytext[yyleng-1]=0; yyleng--; |
228 |
- addstr(yytext, &str); |
|
229 |
- yylval.strval=str; |
|
230 |
- str=0; |
|
228 |
+ addstr(yytext, &tstr); |
|
229 |
+ yylval.strval=tstr; |
|
230 |
+ tstr=0; |
|
231 | 231 |
return STRING; |
232 | 232 |
} |
233 | 233 |
<STRING2>.|{EAT_ABLE}|{CR} { yymore(); } |
234 | 234 |
|
235 | 235 |
<STRING1>\\n { count(); yytext[yyleng-2]='\n';yytext[yyleng-1]=0; |
236 |
- yyleng--; addstr(yytext, &str); } |
|
236 |
+ yyleng--; addstr(yytext, &tstr); } |
|
237 | 237 |
<STRING1>\\r { count(); yytext[yyleng-2]='\r';yytext[yyleng-1]=0; |
238 |
- yyleng--; addstr(yytext, &str); } |
|
238 |
+ yyleng--; addstr(yytext, &tstr); } |
|
239 | 239 |
<STRING1>\\a { count(); yytext[yyleng-2]='\a';yytext[yyleng-1]=0; |
240 |
- yyleng--; addstr(yytext, &str); } |
|
240 |
+ yyleng--; addstr(yytext, &tstr); } |
|
241 | 241 |
<STRING1>\\t { count(); yytext[yyleng-2]='\t';yytext[yyleng-1]=0; |
242 |
- yyleng--; addstr(yytext, &str); } |
|
242 |
+ yyleng--; addstr(yytext, &tstr); } |
|
243 | 243 |
<STRING1>\\\\ { count(); yytext[yyleng-2]='\\';yytext[yyleng-1]=0; |
244 |
- yyleng--; addstr(yytext, &str); } |
|
244 |
+ yyleng--; addstr(yytext, &tstr); } |
|
245 | 245 |
<STRING1>.|{EAT_ABLE}|{CR} { yymore(); } |
246 | 246 |
|
247 | 247 |
|
... | ... |
@@ -257,8 +257,8 @@ EAT_ABLE [\ \t\b\r] |
257 | 257 |
|
258 | 258 |
<INITIAL>{COM_LINE}.*{CR} { count(); } |
259 | 259 |
|
260 |
-<INITIAL>{ID} { count(); addstr(yytext, &str); |
|
261 |
- yylval.strval=str; str=0; return ID; } |
|
260 |
+<INITIAL>{ID} { count(); addstr(yytext, &tstr); |
|
261 |
+ yylval.strval=tstr; tstr=0; return ID; } |
|
262 | 262 |
|
263 | 263 |
|
264 | 264 |
<<EOF>> { |
... | ... |
@@ -266,7 +266,7 @@ EAT_ABLE [\ \t\b\r] |
266 | 266 |
case STRING_S: |
267 | 267 |
LOG(L_CRIT, "ERROR: cfg. parser: unexpected EOF in" |
268 | 268 |
" unclosed string\n"); |
269 |
- if (str) {free(str); str=0;} |
|
269 |
+ if (tstr) {free(tstr); tstr=0;} |
|
270 | 270 |
break; |
271 | 271 |
case COMMENT_S: |
272 | 272 |
LOG(L_CRIT, "ERROR: cfg. parser: unexpected EOF:" |
... | ... |
@@ -164,7 +164,10 @@ assign_stm: DEBUG EQUAL NUMBER { debug=$3; } |
164 | 164 |
| DNS EQUAL error { yyerror("boolean value expected"); } |
165 | 165 |
| REV_DNS EQUAL NUMBER { received_dns|= ($3)?DO_REV_DNS:0; } |
166 | 166 |
| REV_DNS EQUAL error { yyerror("boolean value expected"); } |
167 |
- | PORT EQUAL NUMBER { port_no=$3; } |
|
167 |
+ | PORT EQUAL NUMBER { port_no=$3; |
|
168 |
+ if (sock_no>0) |
|
169 |
+ sock_info[sock_no-1].port_no=port_no; |
|
170 |
+ } |
|
168 | 171 |
| STAT EQUAL STRING { |
169 | 172 |
#ifdef STATS |
170 | 173 |
stat_file=$3; |
... | ... |
@@ -180,7 +183,7 @@ assign_stm: DEBUG EQUAL NUMBER { debug=$3; } |
180 | 183 |
| LOOP_CHECKS EQUAL NUMBER { loop_checks=$3; } |
181 | 184 |
| LOOP_CHECKS EQUAL error { yyerror("boolean value expected"); } |
182 | 185 |
| LISTEN EQUAL ip { |
183 |
- if (addresses_no < MAX_LISTEN){ |
|
186 |
+ if (sock_no< MAX_LISTEN){ |
|
184 | 187 |
tmp=ip_addr2a($3); |
185 | 188 |
/* tmp=inet_ntoa(*(struct in_addr*)&$3);*/ |
186 | 189 |
if (tmp==0){ |
... | ... |
@@ -188,15 +191,19 @@ assign_stm: DEBUG EQUAL NUMBER { debug=$3; } |
188 | 191 |
" bad ip address: %s\n", |
189 | 192 |
strerror(errno)); |
190 | 193 |
}else{ |
191 |
- names[addresses_no]= |
|
194 |
+ sock_info[sock_no].name.s= |
|
192 | 195 |
(char*)malloc(strlen(tmp)+1); |
193 |
- if (names[addresses_no]==0){ |
|
196 |
+ if (sock_info[sock_no].name.s==0){ |
|
194 | 197 |
LOG(L_CRIT, "ERROR: cfg. parser: " |
195 | 198 |
"out of memory.\n"); |
196 | 199 |
}else{ |
197 |
- strncpy(names[addresses_no], tmp, |
|
198 |
- strlen(tmp)+1); |
|
199 |
- addresses_no++; |
|
200 |
+ strncpy(sock_info[sock_no].name.s, |
|
201 |
+ tmp, strlen(tmp)+1); |
|
202 |
+ sock_info[sock_no].name.len= |
|
203 |
+ strlen(tmp); |
|
204 |
+ sock_info[sock_no].port_no= |
|
205 |
+ port_no; |
|
206 |
+ sock_no++; |
|
200 | 207 |
} |
201 | 208 |
} |
202 | 209 |
}else{ |
... | ... |
@@ -206,16 +213,18 @@ assign_stm: DEBUG EQUAL NUMBER { debug=$3; } |
206 | 213 |
} |
207 | 214 |
} |
208 | 215 |
| LISTEN EQUAL ID { |
209 |
- if (addresses_no < MAX_LISTEN){ |
|
210 |
- names[addresses_no]= |
|
216 |
+ if (sock_no < MAX_LISTEN){ |
|
217 |
+ sock_info[sock_no].name.s= |
|
211 | 218 |
(char*)malloc(strlen($3)+1); |
212 |
- if (names[addresses_no]==0){ |
|
219 |
+ if (sock_info[sock_no].name.s==0){ |
|
213 | 220 |
LOG(L_CRIT, "ERROR: cfg. parser:" |
214 | 221 |
" out of memory.\n"); |
215 | 222 |
}else{ |
216 |
- strncpy(names[addresses_no], $3, |
|
223 |
+ strncpy(sock_info[sock_no].name.s, $3, |
|
217 | 224 |
strlen($3)+1); |
218 |
- addresses_no++; |
|
225 |
+ sock_info[sock_no].name.len=strlen($3); |
|
226 |
+ sock_info[sock_no].port_no= port_no; |
|
227 |
+ sock_no++; |
|
219 | 228 |
} |
220 | 229 |
}else{ |
221 | 230 |
LOG(L_CRIT, "ERROR: cfg. parser: " |
... | ... |
@@ -224,16 +233,18 @@ assign_stm: DEBUG EQUAL NUMBER { debug=$3; } |
224 | 233 |
} |
225 | 234 |
} |
226 | 235 |
| LISTEN EQUAL STRING { |
227 |
- if (addresses_no < MAX_LISTEN){ |
|
228 |
- names[addresses_no]= |
|
236 |
+ if (sock_no < MAX_LISTEN){ |
|
237 |
+ sock_info[sock_no].name.s= |
|
229 | 238 |
(char*)malloc(strlen($3)+1); |
230 |
- if (names[addresses_no]==0){ |
|
239 |
+ if (sock_info[sock_no].name.s==0){ |
|
231 | 240 |
LOG(L_CRIT, "ERROR: cfg. parser:" |
232 | 241 |
" out of memory.\n"); |
233 | 242 |
}else{ |
234 |
- strncpy(names[addresses_no], $3, |
|
243 |
+ strncpy(sock_info[sock_no].name.s, $3, |
|
235 | 244 |
strlen($3)+1); |
236 |
- addresses_no++; |
|
245 |
+ sock_info[sock_no].name.len=strlen($3); |
|
246 |
+ sock_info[sock_no].port_no=port_no; |
|
247 |
+ sock_no++; |
|
237 | 248 |
} |
238 | 249 |
}else{ |
239 | 250 |
LOG(L_CRIT, "ERROR: cfg. parser: " |
... | ... |
@@ -34,29 +34,50 @@ |
34 | 34 |
|
35 | 35 |
|
36 | 36 |
|
37 |
+/* returns a socket_info pointer to the sending socket or 0 on error |
|
38 |
+ * params: destination socke_union pointer |
|
39 |
+ */ |
|
40 |
+struct socket_info* get_send_socket(union sockaddr_union* to) |
|
41 |
+{ |
|
42 |
+ struct socket_info* send_sock; |
|
43 |
+ |
|
44 |
+ send_sock=0; |
|
45 |
+ /* check if we need to change the socket (different address families - |
|
46 |
+ * eg: ipv4 -> ipv6 or ipv6 -> ipv4) */ |
|
47 |
+ if (to->s.sa_family!=bind_address->address.af){ |
|
48 |
+ switch(to->s.sa_family){ |
|
49 |
+ case AF_INET: send_sock=sendipv4; |
|
50 |
+ break; |
|
51 |
+#ifdef USE_IPV6 |
|
52 |
+ case AF_INET6: send_sock=sendipv6; |
|
53 |
+ break; |
|
54 |
+#endif |
|
55 |
+ default: LOG(L_ERR, "get_send_socket: BUG: don't know how" |
|
56 |
+ " to forward to af %d\n", to->s.sa_family); |
|
57 |
+ } |
|
58 |
+ }else send_sock=bind_address; |
|
59 |
+ return send_sock; |
|
60 |
+} |
|
61 |
+ |
|
62 |
+ |
|
63 |
+ |
|
37 | 64 |
int forward_request( struct sip_msg* msg, struct proxy_l * p) |
38 | 65 |
{ |
39 | 66 |
unsigned int len; |
40 | 67 |
char* buf; |
41 | 68 |
union sockaddr_union* to; |
42 |
- |
|
69 |
+ struct socket_info* send_sock; |
|
70 |
+ |
|
43 | 71 |
to=0; |
44 |
- buf = build_req_buf_from_sip_req( msg, &len); |
|
45 |
- if (!buf){ |
|
46 |
- LOG(L_ERR, "ERROR: forward_reply: building failed\n"); |
|
47 |
- goto error; |
|
48 |
- } |
|
49 |
- |
|
72 |
+ buf=0; |
|
73 |
+ |
|
50 | 74 |
to=(union sockaddr_union*)malloc(sizeof(union sockaddr_union)); |
51 | 75 |
if (to==0){ |
52 | 76 |
LOG(L_ERR, "ERROR: forward_request: out of memory\n"); |
53 | 77 |
goto error; |
54 | 78 |
} |
55 |
- |
|
56 |
- /* send it! */ |
|
57 |
- DBG("Sending:\n%s.\n", buf); |
|
58 |
- DBG("orig. len=%d, new_len=%d\n", msg->len, len ); |
|
59 |
- |
|
79 |
+ |
|
80 |
+ |
|
60 | 81 |
/* if error try next ip address if possible */ |
61 | 82 |
if (p->ok==0){ |
62 | 83 |
if (p->host.h_addr_list[p->addr_idx+1]) |
... | ... |
@@ -64,13 +85,31 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p) |
64 | 85 |
else p->addr_idx=0; |
65 | 86 |
p->ok=1; |
66 | 87 |
} |
67 |
- |
|
88 |
+ |
|
68 | 89 |
hostent2su(to, &p->host, p->addr_idx, |
69 | 90 |
(p->port)?htons(p->port):htons(SIP_PORT)); |
70 | 91 |
p->tx++; |
71 | 92 |
p->tx_bytes+=len; |
93 |
+ |
|
72 | 94 |
|
73 |
- if (udp_send( buf, len, to, sizeof(union sockaddr_union))==-1){ |
|
95 |
+ send_sock=get_send_socket(to); |
|
96 |
+ if (send_sock==0){ |
|
97 |
+ LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d " |
|
98 |
+ "no coresponding listening socket\n", to->s.sa_family); |
|
99 |
+ goto error; |
|
100 |
+ } |
|
101 |
+ |
|
102 |
+ buf = build_req_buf_from_sip_req( msg, &len, send_sock); |
|
103 |
+ if (!buf){ |
|
104 |
+ LOG(L_ERR, "ERROR: forward_reply: building failed\n"); |
|
105 |
+ goto error; |
|
106 |
+ } |
|
107 |
+ /* send it! */ |
|
108 |
+ DBG("Sending:\n%s.\n", buf); |
|
109 |
+ DBG("orig. len=%d, new_len=%d\n", msg->len, len ); |
|
110 |
+ |
|
111 |
+ if (udp_send( send_sock, buf, len, to, |
|
112 |
+ sizeof(union sockaddr_union))==-1){ |
|
74 | 113 |
p->errors++; |
75 | 114 |
p->ok=0; |
76 | 115 |
STATS_TX_DROPS; |
... | ... |
@@ -145,6 +184,7 @@ int forward_reply(struct sip_msg* msg) |
145 | 184 |
int r; |
146 | 185 |
char* new_buf; |
147 | 186 |
union sockaddr_union* to; |
187 |
+ struct socket_info* send_sock; |
|
148 | 188 |
unsigned int new_len; |
149 | 189 |
struct sr_module *mod; |
150 | 190 |
|
... | ... |
@@ -152,11 +192,14 @@ int forward_reply(struct sip_msg* msg) |
152 | 192 |
new_buf=0; |
153 | 193 |
/*check if first via host = us */ |
154 | 194 |
if (check_via){ |
155 |
- for (r=0; r<addresses_no; r++) |
|
156 |
- if(strcmp(msg->via1->host.s, names[r])==0) break; |
|
157 |
- if (r==addresses_no){ |
|
195 |
+ for (r=0; r<sock_no; r++) |
|
196 |
+ if ( (msg->via1->host.len==sock_info[r].name.len) && |
|
197 |
+ (memcmp(msg->via1->host.s, sock_info[r].name.s, |
|
198 |
+ sock_info[r].name.len)==0) ) |
|
199 |
+ break; |
|
200 |
+ if (r==sock_no){ |
|
158 | 201 |
LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :" |
159 |
- " %s\n", msg->via1->host.s); |
|
202 |
+ " %.*s\n", msg->via1->host.len, msg->via1->host.s); |
|
160 | 203 |
/* send error msg back? */ |
161 | 204 |
goto error; |
162 | 205 |
} |
... | ... |
@@ -192,8 +235,13 @@ int forward_reply(struct sip_msg* msg) |
192 | 235 |
} |
193 | 236 |
|
194 | 237 |
if (update_sock_struct_from_via( to, msg->via2 )==-1) goto error; |
238 |
+ send_sock=get_send_socket(to); |
|
239 |
+ if (send_sock==0){ |
|
240 |
+ LOG(L_ERR, "forward_reply: ERROR: no sending socket found\n"); |
|
241 |
+ goto error; |
|
242 |
+ } |
|
195 | 243 |
|
196 |
- if (udp_send(new_buf,new_len, to, |
|
244 |
+ if (udp_send(send_sock, new_buf,new_len, to, |
|
197 | 245 |
sizeof(union sockaddr_union))==-1) |
198 | 246 |
{ |
199 | 247 |
STATS_TX_DROPS; |
... | ... |
@@ -9,8 +9,10 @@ |
9 | 9 |
#include "parser/msg_parser.h" |
10 | 10 |
#include "route.h" |
11 | 11 |
#include "proxy.h" |
12 |
+#include "ip_addr.h" |
|
12 | 13 |
|
13 | 14 |
|
15 |
+struct socket_info* get_send_socket(union sockaddr_union* su); |
|
14 | 16 |
int forward_request( struct sip_msg* msg, struct proxy_l* p); |
15 | 17 |
int update_sock_struct_from_via( union sockaddr_union* to, |
16 | 18 |
struct via_body* via ); |
... | ... |
@@ -11,23 +11,35 @@ |
11 | 11 |
|
12 | 12 |
#include "types.h" |
13 | 13 |
#include "ip_addr.h" |
14 |
+#include "str.h" |
|
14 | 15 |
|
15 | 16 |
#define NO_DNS 0 |
16 | 17 |
#define DO_DNS 1 |
17 | 18 |
#define DO_REV_DNS 2 |
18 | 19 |
|
19 | 20 |
|
21 |
+ |
|
20 | 22 |
extern char * cfg_file; |
21 | 23 |
extern char *stat_file; |
24 |
+extern struct socket_info sock_info[]; /* all addresses we listen/send from*/ |
|
25 |
+extern int sock_no; /* number of addresses/open sockets*/ |
|
22 | 26 |
extern unsigned short port_no; |
27 |
+/* |
|
23 | 28 |
extern char port_no_str[]; |
24 | 29 |
extern int port_no_str_len; |
25 |
-extern unsigned int maxbuffer; |
|
30 |
+*/ |
|
31 |
+/* |
|
26 | 32 |
extern char * names[]; |
27 | 33 |
extern int names_len[]; |
28 | 34 |
extern struct ip_addr addresses[]; |
29 | 35 |
extern int addresses_no; |
30 |
-extern struct ip_addr* bind_address; |
|
36 |
+*/ |
|
37 |
+extern struct socket_info* bind_address; /* pointer to the crt. proc. listening address */ |
|
38 |
+extern int bind_idx; /* same as above but index in the bound[] array */ |
|
39 |
+extern struct socket_info* sendipv4; /* ipv4 socket to use when msg. comes from ipv6*/ |
|
40 |
+extern struct socket_info* sendipv6; /* same as above for ipv6 */ |
|
41 |
+ |
|
42 |
+extern unsigned int maxbuffer; |
|
31 | 43 |
extern int children_no; |
32 | 44 |
extern int dont_fork; |
33 | 45 |
extern int check_via; |
... | ... |
@@ -9,6 +9,7 @@ |
9 | 9 |
#include <string.h> |
10 | 10 |
#include <netinet/in.h> |
11 | 11 |
#include <netdb.h> |
12 |
+#include "str.h" |
|
12 | 13 |
|
13 | 14 |
#ifdef USE_IPV6 |
14 | 15 |
#ifdef FreeBSD /* freebsd is brain damaged and needs a different |
... | ... |
@@ -49,6 +50,15 @@ union sockaddr_union{ |
49 | 50 |
}; |
50 | 51 |
|
51 | 52 |
|
53 |
+struct socket_info{ |
|
54 |
+ int socket; |
|
55 |
+ str name; /* name - eg.: foo.bar or 10.0.0.1 */ |
|
56 |
+ struct ip_addr address; /* ip address */ |
|
57 |
+ str address_str; /* ip address converted to string -- optimization*/ |
|
58 |
+ unsigned short port_no; /* port number */ |
|
59 |
+ str port_no_str; /* port number converted to string -- optimization*/ |
|
60 |
+}; |
|
61 |
+ |
|
52 | 62 |
|
53 | 63 |
|
54 | 64 |
/* inits an ip_addr with the addr. info from a hostent structure |
... | ... |
@@ -215,6 +225,7 @@ static inline char* ip_addr2a(struct ip_addr* ip) |
215 | 225 |
register unsigned char a,b,c; |
216 | 226 |
#ifdef USE_IPV6 |
217 | 227 |
register unsigned char d; |
228 |
+ register unsigned short hex4; |
|
218 | 229 |
#endif |
219 | 230 |
int r; |
220 | 231 |
#define HEXDIG(x) (((x)>=10)?(x)-10+'A':(x)+'0') |
... | ... |
@@ -225,10 +236,11 @@ static inline char* ip_addr2a(struct ip_addr* ip) |
225 | 236 |
#ifdef USE_IPV6 |
226 | 237 |
case AF_INET6: |
227 | 238 |
for(r=0;r<7;r++){ |
228 |
- a=ip->u.addr16[r]>>12; |
|
229 |
- b=(ip->u.addr16[r]>>8)&0xf; |
|
230 |
- c=(ip->u.addr16[r]>>4)&0xf; |
|
231 |
- d=ip->u.addr16[r]&0xf; |
|
239 |
+ hex4=ntohs(ip->u.addr16[r]); |
|
240 |
+ a=hex4>>12; |
|
241 |
+ b=(hex4>>8)&0xf; |
|
242 |
+ c=(hex4>>4)&0xf; |
|
243 |
+ d=hex4&0xf; |
|
232 | 244 |
if (a){ |
233 | 245 |
buff[offset]=HEXDIG(a); |
234 | 246 |
buff[offset+1]=HEXDIG(b); |
... | ... |
@@ -254,10 +266,11 @@ static inline char* ip_addr2a(struct ip_addr* ip) |
254 | 266 |
} |
255 | 267 |
} |
256 | 268 |
/* last int16*/ |
257 |
- a=ip->u.addr16[r]>>12; |
|
258 |
- b=(ip->u.addr16[r]>>8)&0xf; |
|
259 |
- c=(ip->u.addr16[r]>>4)&0xf; |
|
260 |
- d=ip->u.addr16[r]&0xf; |
|
269 |
+ hex4=ntohs(ip->u.addr16[r]); |
|
270 |
+ a=hex4>>12; |
|
271 |
+ b=(hex4>>8)&0xf; |
|
272 |
+ c=(hex4>>4)&0xf; |
|
273 |
+ d=hex4&0xf; |
|
261 | 274 |
if (a){ |
262 | 275 |
buff[offset]=HEXDIG(a); |
263 | 276 |
buff[offset+1]=HEXDIG(b); |
... | ... |
@@ -122,11 +122,13 @@ static char flags[]= |
122 | 122 |
; |
123 | 123 |
|
124 | 124 |
static char help_msg[]= "\ |
125 |
-Usage: " NAME " -l address [-l address] [options]\n\ |
|
125 |
+Usage: " NAME " -l address [-p port] [-l address [-p port]...] [options]\n\ |
|
126 | 126 |
Options:\n\ |
127 | 127 |
-c Perform loop checks and compute branches\n\ |
128 | 128 |
-f file Configuration file (default " CFG_FILE ")\n\ |
129 | 129 |
-p port Listen on the specified port (default: 5060)\n\ |
130 |
+ applies to the last address in -l and to all \n\ |
|
131 |
+ following that do not have a corespponding -p\n\ |
|
130 | 132 |
-l address Listen on the specified address (multiple -l mean\n\ |
131 | 133 |
listening on more addresses). The default behaviour\n\ |
132 | 134 |
is to listen on the addresses returned by uname(2)\n\ |
... | ... |
@@ -195,9 +197,6 @@ void receive_stdin_loop() |
195 | 197 |
/* global vars */ |
196 | 198 |
|
197 | 199 |
char* cfg_file = 0; |
198 |
-unsigned short port_no = 0; /* port on which we listen */ |
|
199 |
-char port_no_str[MAX_PORT_LEN]; |
|
200 |
-int port_no_str_len=0; |
|
201 | 200 |
unsigned int maxbuffer = MAX_RECV_BUFFER_SIZE; /* maximum buffer size we do |
202 | 201 |
not want to exceed durig the |
203 | 202 |
auto-probing procedure; may |
... | ... |
@@ -217,11 +216,20 @@ char* chroot_dir = 0; |
217 | 216 |
int uid = 0; |
218 | 217 |
int gid = 0; |
219 | 218 |
|
219 |
+#if 0 |
|
220 | 220 |
char* names[MAX_LISTEN]; /* our names */ |
221 | 221 |
int names_len[MAX_LISTEN]; /* lengths of the names*/ |
222 | 222 |
struct ip_addr addresses[MAX_LISTEN]; /* our ips */ |
223 | 223 |
int addresses_no=0; /* number of names/ips */ |
224 |
-struct ip_addr* bind_address; /* listen address of the crt. process */ |
|
224 |
+#endif |
|
225 |
+struct socket_info sock_info[MAX_LISTEN]; /* all addresses we listen/send from*/ |
|
226 |
+int sock_no=0; /* number of addresses/open sockets*/ |
|
227 |
+struct socket_info* bind_address; /* pointer to the crt. proc. listening address */ |
|
228 |
+int bind_idx; /* same as above but index in the bound[] array */ |
|
229 |
+struct socket_info* sendipv4; /* ipv4 socket to use when msg. comes from ipv6*/ |
|
230 |
+struct socket_info* sendipv6; /* same as above for ipv6 */ |
|
231 |
+ |
|
232 |
+unsigned short port_no=0; /* default port*/ |
|
225 | 233 |
|
226 | 234 |
/* ipc related globals */ |
227 | 235 |
int process_no = 0; |
... | ... |
@@ -246,7 +254,6 @@ extern int yyparse(); |
246 | 254 |
static int is_main=0; /* flag = is this the "main" process? */ |
247 | 255 |
|
248 | 256 |
char* pid_file = 0; /* filename as asked by use */ |
249 |
-char *pid_fn = 0; /* and with port number appended */ |
|
250 | 257 |
|
251 | 258 |
/* daemon init, return 0 on success, -1 on error */ |
252 | 259 |
int daemonize(char* name) |
... | ... |
@@ -255,7 +262,6 @@ int daemonize(char* name) |
255 | 262 |
pid_t pid; |
256 | 263 |
int r, p; |
257 | 264 |
|
258 |
- int pid_fn_len; |
|
259 | 265 |
|
260 | 266 |
p=-1; |
261 | 267 |
|
... | ... |
@@ -288,8 +294,7 @@ int daemonize(char* name) |
288 | 294 |
if ((pid=fork())<0){ |
289 | 295 |
LOG(L_CRIT, "Cannot fork:%s\n", strerror(errno)); |
290 | 296 |
goto error; |
291 |
- } |
|
292 |
- if (pid!=0){ |
|
297 |
+ }else if (pid!=0){ |
|
293 | 298 |
/* parent process => exit*/ |
294 | 299 |
exit(0); |
295 | 300 |
} |
... | ... |
@@ -301,49 +306,34 @@ int daemonize(char* name) |
301 | 306 |
if ((pid=fork())<0){ |
302 | 307 |
LOG(L_CRIT, "Cannot fork:%s\n", strerror(errno)); |
303 | 308 |
goto error; |
304 |
- } |
|
305 |
- if (pid!=0){ |
|
309 |
+ }else if (pid!=0){ |
|
306 | 310 |
/*parent process => exit */ |
307 | 311 |
exit(0); |
308 | 312 |
} |
309 | 313 |
|
310 | 314 |
/* added by noh: create a pid file for the main process */ |
311 | 315 |
if (pid_file!=0){ |
312 |
- |
|
313 |
- /* added port number; -jiri */ |
|
314 |
- pid_fn_len = strlen(pid_file) + 5 /* long port number */ |
|
315 |
- + 1 /* dot */ + 1 /* ZT */ ; |
|
316 |
- pid_fn = malloc( pid_fn_len ); |
|
317 |
- if (!pid_fn) { |
|
318 |
- LOG(L_ERR, "ERROR: There is really no memory for ser\n"); |
|
319 |
- goto error; |
|
320 |
- } |
|
321 |
- if (snprintf(pid_fn, pid_fn_len, "%s.%d", pid_file, port_no )==-1) { |
|
322 |
- LOG(L_ERR, "ERROR: pidfile printig failed -- perhaps too high port?\n"); |
|
323 |
- goto error; |
|
324 |
- } |
|
325 | 316 |
|
326 |
- |
|
327 |
- if ((pid_stream=fopen(pid_fn, "r"))!=NULL){ |
|
317 |
+ if ((pid_stream=fopen(pid_file, "r"))!=NULL){ |
|
328 | 318 |
fscanf(pid_stream, "%d", &p); |
329 | 319 |
fclose(pid_stream); |
330 | 320 |
if (p==-1){ |
331 | 321 |
LOG(L_CRIT, "pid file %s exists, but doesn't contain a valid" |
332 |
- " pid number\n", pid_fn); |
|
322 |
+ " pid number\n", pid_file); |
|
333 | 323 |
goto error; |
334 | 324 |
} |
335 | 325 |
if (kill((pid_t)p, 0)==0 || errno==EPERM){ |
336 | 326 |
LOG(L_CRIT, "running process found in the pid file %s\n", |
337 |
- pid_fn); |
|
327 |
+ pid_file); |
|
338 | 328 |
goto error; |
339 | 329 |
}else{ |
340 | 330 |
LOG(L_WARN, "pid file contains old pid, replacing pid\n"); |
341 | 331 |
} |
342 | 332 |
} |
343 | 333 |
pid=getpid(); |
344 |
- if ((pid_stream=fopen(pid_fn, "w"))==NULL){ |
|
334 |
+ if ((pid_stream=fopen(pid_file, "w"))==NULL){ |
|
345 | 335 |
LOG(L_WARN, "unable to create pid file %s: %s\n", |
346 |
- pid_fn, strerror(errno)); |
|
336 |
+ pid_file, strerror(errno)); |
|
347 | 337 |
goto error; |
348 | 338 |
}else{ |
349 | 339 |
fprintf(pid_stream, "%i\n", (int)pid); |
... | ... |
@@ -378,14 +368,19 @@ int main_loop() |
378 | 368 |
#ifdef STATS |
379 | 369 |
setstats( 0 ); |
380 | 370 |
#endif |
381 |
- /* only one address */ |
|
382 |
- if (udp_init(&addresses[0],port_no)==-1) goto error; |
|
371 |
+ /* only one address, we ignore all the others */ |
|
372 |
+ if (udp_init(&sock_info[0])==-1) goto error; |
|
373 |
+ bind_address=&sock_info[0]; |
|
374 |
+ bind_idx=0; |
|
375 |
+ if (sock_no>1){ |
|
376 |
+ LOG(L_WARN, "WARNING: using only the first listen address (no fork)\n"); |
|
377 |
+ } |
|
383 | 378 |
|
384 | 379 |
/* we need another process to act as the timer*/ |
385 | 380 |
if (timer_list){ |
386 | 381 |
process_no++; |
387 | 382 |
if ((pid=fork())<0){ |
388 |
- LOG(L_CRIT, "ERRROR: main_loop: Cannot fork\n"); |
|
383 |
+ LOG(L_CRIT, "ERROR: main_loop: Cannot fork\n"); |
|
389 | 384 |
goto error; |
390 | 385 |
} |
391 | 386 |
|
... | ... |
@@ -418,17 +413,28 @@ int main_loop() |
418 | 413 |
|
419 | 414 |
return udp_rcv_loop(); |
420 | 415 |
}else{ |
421 |
- for(r=0;r<addresses_no;r++){ |
|
416 |
+ for(r=0;r<sock_no;r++){ |
|
422 | 417 |
/* create the listening socket (for each address)*/ |
423 |
- if (udp_init(&addresses[r], port_no)==-1) goto error; |
|
418 |
+ if (udp_init(&sock_info[r])==-1) goto error; |
|
419 |
+ /* get first ipv4/ipv6 socket*/ |
|
420 |
+ if ((sendipv4==0)&&(sock_info[r].address.af==AF_INET)) |
|
421 |
+ sendipv4=&sock_info[r]; |
|
422 |
+ #ifdef USE_IPV6 |
|
423 |
+ if((sendipv6==0)&&(sock_info[r].address.af==AF_INET6)) |
|
424 |
+ sendipv6=&sock_info[r]; |
|
425 |
+ #endif |
|
426 |
+ /* all procs should have access to all the sockets (for sending) |
|
427 |
+ * so we open all first*/ |
|
428 |
+ } |
|
429 |
+ for(r=0; r<sock_no;r++){ |
|
424 | 430 |
for(i=0;i<children_no;i++){ |
425 | 431 |
if ((pid=fork())<0){ |
426 | 432 |
LOG(L_CRIT, "main_loop: Cannot fork\n"); |
427 | 433 |
goto error; |
428 |
- } |
|
429 |
- if (pid==0){ |
|
434 |
+ }else if (pid==0){ |
|
430 | 435 |
/* child */ |
431 |
- |
|
436 |
+ bind_address=&sock_info[r]; /* shortcut */ |
|
437 |
+ bind_idx=r; |
|
432 | 438 |
if (init_child(i) < 0) { |
433 | 439 |
LOG(L_ERR, "init_child failed\n"); |
434 | 440 |
goto error; |
... | ... |
@@ -452,6 +458,9 @@ int main_loop() |
452 | 458 |
pids[process_no]=getpid(); |
453 | 459 |
process_bit = 0; |
454 | 460 |
is_main=1; |
461 |
+ bind_address=&sock_info[0]; /* main proc -> it shoudln't send anything, if it does */ |
|
462 |
+ bind_idx=0; /* it will use the first address */ |
|
463 |
+ |
|
455 | 464 |
if (timer_list){ |
456 | 465 |
for(;;){ |
457 | 466 |
/* debug: instead of doing something usefull */ |
... | ... |
@@ -461,7 +470,7 @@ int main_loop() |
461 | 470 |
timer_ticker(); |
462 | 471 |
} |
463 | 472 |
}else{ |
464 |
- for(;;) sleep(LONG_SLEEP); |
|
473 |
+ for(;;) pause(); |
|
465 | 474 |
} |
466 | 475 |
|
467 | 476 |
/*return 0; */ |
... | ... |
@@ -474,8 +483,7 @@ int main_loop() |
474 | 483 |
/* added by jku; allows for regular exit on a specific signal; |
475 | 484 |
good for profiling which only works if exited regularly and |
476 | 485 |
not by default signal handlers |
477 |
-*/ |
|
478 |
- |
|
486 |
+*/ |
|
479 | 487 |
static void sig_usr(int signo) |
480 | 488 |
{ |
481 | 489 |
pid_t chld; |
... | ... |
@@ -508,6 +516,8 @@ static void sig_usr(int signo) |
508 | 516 |
} |
509 | 517 |
#endif |
510 | 518 |
dprint("Thank you for flying " NAME "\n"); |
519 |
+ /* kill children also*/ |
|
520 |
+ kill(0, SIGTERM); |
|
511 | 521 |
exit(0); |
512 | 522 |
} else if (signo==SIGTERM) { /* exit gracefully as daemon */ |
513 | 523 |
DPrint("TERM received, program terminates\n"); |
... | ... |
@@ -515,11 +525,11 @@ static void sig_usr(int signo) |
515 | 525 |
#ifdef STATS |
516 | 526 |
dump_all_statistic(); |
517 | 527 |
#endif |
518 |
- if (pid_fn) { |
|
519 |
- unlink(pid_fn); |
|
520 |
- free(pid_fn); |
|
528 |
+ if (pid_file) { |
|
529 |
+ unlink(pid_file); |
|
521 | 530 |
} |
522 | 531 |
} |
532 |
+ kill(0, SIGTERM); |
|
523 | 533 |
exit(0); |
524 | 534 |
} else if (signo==SIGUSR1) { /* statistic */ |
525 | 535 |
#ifdef STATS |
... | ... |
@@ -549,6 +559,9 @@ static void sig_usr(int signo) |
549 | 559 |
LOG(L_INFO, "child process %d stopped by a signal %d\n", |
550 | 560 |
chld, WSTOPSIG(chld_status)); |
551 | 561 |
} |
562 |
+ /* exit */ |
|
563 |
+ kill(0, SIGTERM); |
|
564 |
+ exit(0); |
|
552 | 565 |
} |
553 | 566 |
} |
554 | 567 |
|
... | ... |
@@ -564,6 +577,8 @@ int main(int argc, char** argv) |
564 | 577 |
char *tmp; |
565 | 578 |
struct utsname myname; |
566 | 579 |
char *options; |
580 |
+ char port_no_str[MAX_PORT_LEN]; |
|
581 |
+ int port_no_str_len=0; |
|
567 | 582 |
|
568 | 583 |
/* added by jku: add exit handler */ |
569 | 584 |
if (signal(SIGINT, sig_usr) == SIG_ERR ) { |
... | ... |
@@ -589,9 +604,6 @@ int main(int argc, char** argv) |
589 | 604 |
goto error; |
590 | 605 |
} |
591 | 606 |
|
592 |
- //memtest(); |
|
593 |
- //hashtest(); |
|
594 |
- |
|
595 | 607 |
/* process command line (get port no, cfg. file path etc) */ |
596 | 608 |
opterr=0; |
597 | 609 |
options= |
... | ... |
@@ -616,34 +628,43 @@ int main(int argc, char** argv) |
616 | 628 |
fprintf(stderr, "bad port number: -p %s\n", optarg); |
617 | 629 |
goto error; |
618 | 630 |
} |
631 |
+ if (sock_no>0) sock_info[sock_no-1].port_no=port_no; |
|
619 | 632 |
break; |
620 | 633 |
|
621 | 634 |
case 'm': |
622 | 635 |
shm_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024; |
623 | 636 |
if (tmp &&(*tmp)){ |
624 |
- fprintf(stderr, "bad shmem size number: -m %s\n", optarg); |
|
637 |
+ fprintf(stderr, "bad shmem size number: -m %s\n", |
|
638 |
+ optarg); |
|
625 | 639 |
goto error; |
626 | 640 |
}; |
627 |
- LOG(L_INFO, "ser: shared memory allocated: %d MByte\n", shm_mem_size ); |
|
641 |
+ LOG(L_INFO, "ser: shared memory allocated: %d MByte\n", |
|
642 |
+ shm_mem_size ); |
|
628 | 643 |
break; |
629 | 644 |
|
630 | 645 |
case 'b': |
631 | 646 |
maxbuffer=strtol(optarg, &tmp, 10); |
632 | 647 |
if (tmp &&(*tmp)){ |
633 |
- fprintf(stderr, "bad max buffer size number: -p %s\n", optarg); |
|
634 |
- goto error; |
|
635 |
- } |
|
636 |
- break; |
|
648 |
+ fprintf(stderr, "bad max buffer size number: -p %s\n", |
|
649 |
+ optarg); |
|
650 |
+ goto error; |
|
651 |
+ } |
|
652 |
+ break; |
|
637 | 653 |
case 'l': |
638 | 654 |
/* add a new addr. to our address list */ |
639 |
- if (addresses_no < MAX_LISTEN){ |
|
640 |
- names[addresses_no]=(char*)malloc(strlen(optarg)+1); |
|
641 |
- if (names[addresses_no]==0){ |
|
655 |
+ if (sock_no < MAX_LISTEN){ |
|
656 |
+ sock_info[sock_no].name.s= |
|
657 |
+ (char*)malloc(strlen(optarg)+1); |
|
658 |
+ if (sock_info[sock_no].name.s==0){ |
|
642 | 659 |
fprintf(stderr, "Out of memory.\n"); |
643 | 660 |
goto error; |
644 | 661 |
} |
645 |
- strncpy(names[addresses_no], optarg, strlen(optarg)+1); |
|
646 |
- addresses_no++; |
|
662 |
+ strncpy(sock_info[sock_no].name.s, optarg, |
|
663 |
+ strlen(optarg)+1); |
|
664 |
+ sock_info[sock_no].name.len=strlen(optarg); |
|
665 |
+ /* set default port */ |
|
666 |
+ sock_info[sock_no].port_no=port_no; |
|
667 |
+ sock_no++; |
|
647 | 668 |
}else{ |
648 | 669 |
fprintf(stderr, |
649 | 670 |
"Too many addresses (max. %d).\n", |
... | ... |
@@ -654,7 +675,8 @@ int main(int argc, char** argv) |
654 | 675 |
case 'n': |
655 | 676 |
children_no=strtol(optarg, &tmp, 10); |
656 | 677 |
if ((tmp==0) ||(*tmp)){ |
657 |
- fprintf(stderr, "bad process number: -n %s\n", optarg); |
|
678 |
+ fprintf(stderr, "bad process number: -n %s\n", |
|
679 |
+ optarg); |
|
658 | 680 |
goto error; |
659 | 681 |
} |
660 | 682 |
break; |
... | ... |
@@ -784,16 +806,6 @@ int main(int argc, char** argv) |
784 | 806 |
|
785 | 807 |
/* fix parameters */ |
786 | 808 |
if (port_no<=0) port_no=SIP_PORT; |
787 |
- port_no_str_len=snprintf(port_no_str, MAX_PORT_LEN, ":%d", |
|
788 |
- (unsigned short) port_no); |
|
789 |
- if (port_no_str_len<0){ |
|
790 |
- fprintf(stderr, "ERROR: bad port number: %d\n", port_no); |
|
791 |
- goto error; |
|
792 |
- } |
|
793 |
- /* on some system snprintf return really strange things if it does not |
|
794 |
- have enough space */ |
|
795 |
- port_no_str_len= |
|
796 |
- (port_no_str_len<MAX_PORT_LEN)?port_no_str_len:MAX_PORT_LEN; |
|
797 | 809 |
|
798 | 810 |
|
799 | 811 |
if (children_no<=0) children_no=CHILD_NO; |
... | ... |
@@ -817,42 +829,63 @@ int main(int argc, char** argv) |
817 | 829 |
} |
818 | 830 |
memset(pids, 0, sizeof(int)*(children_no+1)); |
819 | 831 |
|
820 |
- if (addresses_no==0) { |
|
832 |
+ if (sock_no==0) { |
|
821 | 833 |
/* get our address, only the first one */ |
822 | 834 |
if (uname (&myname) <0){ |
823 | 835 |
fprintf(stderr, "cannot determine hostname, try -l address\n"); |
824 | 836 |
goto error; |
825 | 837 |
} |
826 |
- names[addresses_no]=(char*)malloc(strlen(myname.nodename)+1); |
|
827 |
- if (names[addresses_no]==0){ |
|
838 |
+ sock_info[sock_no].name.s=(char*)malloc(strlen(myname.nodename)+1); |
|
839 |
+ if (sock_info[sock_no].name.s==0){ |
|
828 | 840 |
fprintf(stderr, "Out of memory.\n"); |
829 | 841 |
goto error; |
830 | 842 |
} |
831 |
- strncpy(names[addresses_no], myname.nodename, |
|
843 |
+ strncpy(sock_info[sock_no].name.s, myname.nodename, |
|
832 | 844 |
strlen(myname.nodename)+1); |
833 |
- addresses_no++; |
|
845 |
+ sock_info[sock_no].name.len=strlen(myname.nodename); |
|
846 |
+ sock_no++; |
|
834 | 847 |
} |
835 | 848 |
|
836 |
- /*get name lens*/ |
|
837 |
- for(r=0; r<addresses_no; r++){ |
|
838 |
- names_len[r]=strlen(names[r]); |
|
839 |
- } |
|
840 |
- |
|
841 |
- |
|
842 |
- /* get ips */ |
|
849 |
+ /* get ips & fill the port numbers*/ |
|
843 | 850 |
printf("Listening on "); |
844 |
- for (r=0; r<addresses_no;r++){ |
|
845 |
- he=resolvehost(names[r]); |
|
851 |
+ for (r=0; r<sock_no;r++){ |
|
852 |
+ he=resolvehost(sock_info[r].name.s); |
|
846 | 853 |
if (he==0){ |
847 |
- DPrint("ERROR: could not resolve %s\n", names[r]); |
|
854 |
+ DPrint("ERROR: could not resolve %s\n", sock_info[r].name.s); |
|
848 | 855 |
goto error; |
849 | 856 |
} |
850 |
- hostent2ip_addr(&addresses[r], he, 0); /*convert to ip_addr format*/ |
|
851 |
- /*memcpy(&addresses[r], he->h_addr_list[0], sizeof(int));*/ |
|
852 |
- /*addresses[r]=*((long*)he->h_addr_list[0]);*/ |
|
853 |
- printf("%s [",names[r]); |
|
854 |
- stdout_print_ip(&addresses[r]); |
|
855 |
- printf("]:%d\n", (unsigned short)port_no); |
|
857 |
+ hostent2ip_addr(&sock_info[r].address, he, 0); /*convert to ip_addr format*/ |
|
858 |
+ tmp=ip_addr2a(&sock_info[r].address); |
|
859 |
+ sock_info[r].address_str.s=(char*)malloc(strlen(tmp)+1); |
|
860 |
+ if (sock_info[r].address_str.s==0){ |
|
861 |
+ fprintf(stderr, "Out of memory.\n"); |
|
862 |
+ goto error; |
|
863 |
+ } |
|
864 |
+ strncpy(sock_info[r].address_str.s, tmp, strlen(tmp)+1); |
|
865 |
+ sock_info[r].address_str.len=strlen(tmp); |
|
866 |
+ |
|
867 |
+ if (sock_info[r].port_no==0) sock_info[r].port_no=port_no; |
|
868 |
+ port_no_str_len=snprintf(port_no_str, MAX_PORT_LEN, ":%d", |
|
869 |
+ (unsigned short) sock_info[r].port_no); |
|
870 |
+ if (port_no_str_len<0){ |
|
871 |
+ fprintf(stderr, "ERROR: bad port number: %d\n", |
|
872 |
+ sock_info[r].port_no); |
|
873 |
+ goto error; |
|
874 |
+ } |
|
875 |
+ /* on some system snprintf return really strange things if it does not |
|
876 |
+ have enough space */ |
|
877 |
+ port_no_str_len= |
|
878 |
+ (port_no_str_len<MAX_PORT_LEN)?port_no_str_len:MAX_PORT_LEN; |
|
879 |
+ sock_info[r].port_no_str.s=(char*)malloc(strlen(port_no_str)+1); |
|
880 |
+ if (sock_info[r].port_no_str.s==0){ |
|
881 |
+ fprintf(stderr, "Out of memory.\n"); |
|
882 |
+ goto error; |
|
883 |
+ } |
|
884 |
+ strncpy(sock_info[r].port_no_str.s, port_no_str, strlen(port_no_str)+1); |
|
885 |
+ sock_info[r].port_no_str.len=strlen(port_no_str); |
|
886 |
+ |
|
887 |
+ printf("%s [%s]:%s\n",sock_info[r].name.s, sock_info[r].address_str.s, |
|
888 |
+ sock_info[r].port_no_str.s); |
|
856 | 889 |
} |
857 | 890 |
|
858 | 891 |
#ifdef STATS |
... | ... |
@@ -89,30 +89,45 @@ int check_address(struct ip_addr* ip, char *name, int resolver) |
89 | 89 |
|
90 | 90 |
|
91 | 91 |
|
92 |
-char* via_builder( struct sip_msg *msg , unsigned int *len ) |
|
92 |
+char* via_builder( struct sip_msg *msg , unsigned int *len, |
|
93 |
+ struct socket_info* send_sock ) |
|
93 | 94 |
{ |
94 |
- unsigned int via_len, branch_len; |
|
95 |
+ unsigned int via_len, branch_len, extra_len;; |
|
95 | 96 |
char *line_buf; |
96 | 97 |
|
97 | 98 |
line_buf=0; |
99 |
+ extra_len=0; |
|
98 | 100 |
|
99 | 101 |
line_buf=pkg_malloc(sizeof(char)*MAX_VIA_LINE_SIZE); |
100 | 102 |
if (line_buf==0){ |
101 | 103 |
LOG(L_ERR, "ERROR: via_builder: out of memory\n"); |
102 | 104 |
goto error; |
103 | 105 |
} |
104 |
- via_len=MY_VIA_LEN+names_len[0]; /* space included in MY_VIA*/ |
|
106 |
+ via_len=MY_VIA_LEN+send_sock->address_str.len; /*space included in MY_VIA*/ |
|
107 |
+#ifdef USE_IPV6 |
|
108 |
+ if (send_sock->address.af==AF_INET6) via_len+=2; /* [ ]*/ |
|
109 |
+#endif |
|
105 | 110 |
|
106 | 111 |
/* jku: if we compute branches using MD5 it will take 32 bytes */ |
107 | 112 |
branch_len= (loop_checks ? MY_BRANCH_LEN : MY_BRANCH_LEN -1 + MD5_LEN)+ |
108 | 113 |
msg->add_to_branch_len; |
109 | 114 |
|
110 |
- if ((via_len+port_no_str_len+branch_len+CRLF_LEN)<MAX_VIA_LINE_SIZE){ |
|
115 |
+ if ((via_len+send_sock->port_no_str.len+branch_len |
|
116 |
+ +CRLF_LEN)<MAX_VIA_LINE_SIZE){ |
|
111 | 117 |
memcpy(line_buf, MY_VIA, MY_VIA_LEN); |
112 |
- memcpy(line_buf+MY_VIA_LEN, names[0], names_len[0]); |
|
113 |
- if (port_no!=SIP_PORT){ |
|
114 |
- memcpy(line_buf+via_len, port_no_str, port_no_str_len); |
|
115 |
- via_len+=port_no_str_len; |
|
118 |
+#ifdef USE_IPV6 |
|
119 |
+ if (send_sock->address.af==AF_INET6) { |
|
120 |
+ line_buf[MY_VIA_LEN]='['; |
|
121 |
+ line_buf[MY_VIA_LEN+1+send_sock->address_str.len]=']'; |
|
122 |
+ extra_len=1; |
|
123 |
+ } |
|
124 |
+#endif |
|
125 |
+ memcpy(line_buf+MY_VIA_LEN+extra_len, send_sock->address_str.s, |
|
126 |
+ send_sock->address_str.len); |
|
127 |
+ if (send_sock->port_no!=SIP_PORT){ |
|
128 |
+ memcpy(line_buf+via_len, send_sock->port_no_str.s, |
|
129 |
+ send_sock->port_no_str.len); |
|
130 |
+ via_len+=send_sock->port_no_str.len; |
|
116 | 131 |
} |
117 | 132 |
|
118 | 133 |
/* jku: branch parameter */ |
... | ... |
@@ -222,7 +237,8 @@ done: |
222 | 237 |
|
223 | 238 |
|
224 | 239 |
char * build_req_buf_from_sip_req( struct sip_msg* msg, |
225 |
- unsigned int *returned_len) |
|
240 |
+ unsigned int *returned_len, |
|
241 |
+ struct socket_info* send_sock) |
|
226 | 242 |
{ |
227 | 243 |
unsigned int len, new_len, received_len, uri_len, via_len, extra_len; |
228 | 244 |
char* line_buf; |
... | ... |
@@ -249,7 +265,7 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg, |
249 | 265 |
extra_len=0; |
250 | 266 |
|
251 | 267 |
|
252 |
- line_buf = via_builder( msg, &via_len ); |
|
268 |
+ line_buf = via_builder( msg, &via_len, send_sock); |
|
253 | 269 |
if (!line_buf){ |
254 | 270 |
LOG(L_ERR,"ERROR: build_req_buf_from_sip_req: no via received!\n"); |
255 | 271 |
goto error1; |
... | ... |
@@ -9,9 +9,10 @@ |
9 | 9 |
#define MY_HF_SEP_LEN 2 |
10 | 10 |
|
11 | 11 |
#include "parser/msg_parser.h" |
12 |
+#include "ip_addr.h" |
|
12 | 13 |
|
13 | 14 |
char * build_req_buf_from_sip_req ( struct sip_msg* msg, |
14 |
- unsigned int *returned_len); |
|
15 |
+ unsigned int *returned_len, struct socket_info* send_sock); |
|
15 | 16 |
|
16 | 17 |
char * build_res_buf_from_sip_res( struct sip_msg* msg, |
17 | 18 |
unsigned int *returned_len); |
... | ... |
@@ -23,7 +24,7 @@ char * build_res_buf_from_sip_req( unsigned int code , |
23 | 24 |
struct sip_msg* msg, |
24 | 25 |
unsigned int *returned_len); |
25 | 26 |
char* via_builder( struct sip_msg *msg , |
26 |
- unsigned int *len ); |
|
27 |
+ unsigned int *len, struct socket_info* send_sock); |
|
27 | 28 |
|
28 | 29 |
|
29 | 30 |
#endif |
... | ... |
@@ -43,7 +43,7 @@ int receive_msg(char* buf, unsigned int len, union sockaddr_union* src_su) |
43 | 43 |
msg->buf=buf; |
44 | 44 |
msg->len=len; |
45 | 45 |
su2ip_addr(&msg->src_ip, src_su); |
46 |
- msg->dst_ip=*bind_address; /* won't work if listening on 0.0.0.0 */ |
|
46 |
+ msg->dst_ip=bind_address->address; /* won't work if listening on 0.0.0.0 */ |
|
47 | 47 |
msg->id=msg_no; |
48 | 48 |
/* make a copy of the message */ |
49 | 49 |
msg->orig=(char*) pkg_malloc(len+1); |
... | ... |
@@ -23,7 +23,6 @@ |
23 | 23 |
#include <mem/dmalloc.h> |
24 | 24 |
#endif |
25 | 25 |
|
26 |
-int udp_sock; |
|
27 | 26 |
|
28 | 27 |
int probe_max_receive_buffer( int udp_sock ) |
29 | 28 |
{ |
... | ... |
@@ -107,7 +106,7 @@ int probe_max_receive_buffer( int udp_sock ) |
107 | 106 |
/* EoJKU */ |
108 | 107 |
} |
109 | 108 |
|
110 |
-int udp_init(struct ip_addr* ip, unsigned short port) |
|
109 |
+int udp_init(struct socket_info* sock_info) |
|
111 | 110 |
{ |
112 | 111 |
union sockaddr_union* addr; |
113 | 112 |
int optval; |
... | ... |
@@ -119,7 +118,7 @@ int udp_init(struct ip_addr* ip, unsigned short port) |
119 | 118 |
goto error; |
120 | 119 |
} |
121 | 120 |
|
122 |
- if (init_su(addr, ip, htons(port))<0){ |
|
121 |
+ if (init_su(addr, &sock_info->address, htons(sock_info->port_no))<0){ |
|
123 | 122 |
LOG(L_ERR, "ERROR: udp_init: could not init sockaddr_union\n"); |
124 | 123 |
goto error; |
125 | 124 |
} |
... | ... |
@@ -130,25 +129,33 @@ int udp_init(struct ip_addr* ip, unsigned short port) |
130 | 129 |
*/ |
131 | 130 |
|
132 | 131 |
|
133 |
- udp_sock = socket(AF2PF(addr->s.sa_family), SOCK_DGRAM, 0); |
|
134 |
- if (udp_sock==-1){ |
|
132 |
+ sock_info->socket = socket(AF2PF(addr->s.sa_family), SOCK_DGRAM, 0); |
|
133 |
+ if (sock_info->socket==-1){ |
|
135 | 134 |
LOG(L_ERR, "ERROR: udp_init: socket: %s\n", strerror(errno)); |
136 | 135 |
goto error; |
137 | 136 |
} |
138 | 137 |
/* set sock opts? */ |
139 | 138 |
optval=1; |
140 |
- if (setsockopt(udp_sock, SOL_SOCKET, SO_REUSEADDR , |
|
139 |
+ if (setsockopt(sock_info->socket, SOL_SOCKET, SO_REUSEADDR , |
|
141 | 140 |
(void*)&optval, sizeof(optval)) ==-1) |
142 | 141 |
{ |
143 | 142 |
LOG(L_ERR, "ERROR: udp_init: setsockopt: %s\n", strerror(errno)); |
144 | 143 |
goto error; |
145 | 144 |
} |
146 | 145 |
|
147 |
- if ( probe_max_receive_buffer(udp_sock)==-1) goto error; |
|
148 |
- bind_address=ip; |
|
149 |
- |
|
150 |
- if (bind(udp_sock, &addr->s, sizeof(union sockaddr_union))==-1){ |
|
151 |
- LOG(L_ERR, "ERROR: udp_init: bind: %s\n", strerror(errno)); |
|
146 |
+ if ( probe_max_receive_buffer(sock_info->socket)==-1) goto error; |
|
147 |
+ |
|
148 |
+ if (bind(sock_info->socket, &addr->s, sizeof(union sockaddr_union))==-1){ |
|
149 |
+ LOG(L_ERR, "ERROR: udp_init: bind(%x, %p, %d) on %s: %s\n", |
|
150 |
+ sock_info->socket, &addr->s, |
|
151 |
+ sizeof(union sockaddr_union), |
|
152 |
+ sock_info->address_str.s, |
|
153 |
+ strerror(errno)); |
|
154 |
+ #ifdef USE_IPV6 |
|
155 |
+ if (addr->s.sa_family==AF_INET6) |
|
156 |
+ LOG(L_ERR, "ERROR: udp_init: might be caused by using a link " |
|
157 |
+ " local address, try site local or global\n"); |
|
158 |
+ #endif |
|
152 | 159 |
goto error; |
153 | 160 |
} |
154 | 161 |
|
... | ... |
@@ -191,8 +198,8 @@ int udp_rcv_loop() |
191 | 198 |
} |
192 | 199 |
#endif |
193 | 200 |
fromlen=sizeof(union sockaddr_union); |
194 |
- len=recvfrom(udp_sock, buf, BUF_SIZE, 0, &from->s, |
|
195 |
- &fromlen); |
|
201 |
+ len=recvfrom(bind_address->socket, buf, BUF_SIZE, 0, &from->s, |
|
202 |
+ &fromlen); |
|
196 | 203 |
if (len==-1){ |
197 | 204 |
LOG(L_ERR, "ERROR: udp_rcv_loop:recvfrom:[%d] %s\n", |
198 | 205 |
errno, strerror(errno)); |
... | ... |
@@ -222,15 +229,15 @@ error: |
222 | 229 |
|
223 | 230 |
|
224 | 231 |
/* which socket to use? main socket or new one? */ |
225 |
-int udp_send(char *buf, unsigned len, union sockaddr_union* to, |
|
226 |
- unsigned tolen) |
|
232 |
+int udp_send(struct socket_info *source, char *buf, unsigned len, |
|
233 |
+ union sockaddr_union* to, unsigned tolen) |
|
227 | 234 |
{ |
228 | 235 |
|
229 | 236 |
int n; |
230 | 237 |
|
231 | 238 |
|
232 | 239 |
again: |
233 |
- n=sendto(udp_sock, buf, len, 0, &to->s, tolen); |
|
240 |
+ n=sendto(source->socket, buf, len, 0, &to->s, tolen); |
|
234 | 241 |
if (n==-1){ |
235 | 242 |
LOG(L_ERR, "ERROR: udp_send: sendto(sock,%p,%d,0,%p,%d): %s(%d)\n", |
236 | 243 |
buf,len,to,tolen, |
... | ... |
@@ -12,11 +12,10 @@ |
12 | 12 |
#define MAX_RECV_BUFFER_SIZE 256*1024 |
13 | 13 |
#define BUFFER_INCREMENT 2048 |
14 | 14 |
|
15 |
-extern int udp_sock; |
|
16 | 15 |
|
17 |
-int udp_init(struct ip_addr* ip, unsigned short port); |
|
18 |
-int udp_send(char *buf, unsigned len, union sockaddr_union* to, |
|
19 |
- unsigned tolen); |
|
16 |
+int udp_init(struct socket_info* si); |
|
17 |
+int udp_send(struct socket_info* source,char *buf, unsigned len, |
|
18 |
+ union sockaddr_union* to, unsigned tolen); |
|
20 | 19 |
int udp_rcv_loop(); |
21 | 20 |
|
22 | 21 |
|