06cb2b771bf95332469e0298cce1cba6c2539156
[sip-router] / route.c
1 /*
2  * $Id$
3  *
4  * SIP routing engine
5  *
6  */
7  
8 #include <sys/types.h>
9 #include <regex.h>
10 #include <netdb.h>
11 #include <string.h>
12
13 #include "route.h"
14 #include "cfg_parser.h"
15 #include "dprint.h"
16
17 /* main routing list */
18 struct route_elem* rlist=0;
19
20
21
22 void free_re(struct route_elem* r)
23 {
24         int i;
25         if (r){
26                         regfree(&(r->method));
27                         regfree(&(r->uri));
28                         
29                         if (r->host.h_name)      free(r->host.h_name);
30                         if (r->host.h_aliases){
31                                 for (i=0; r->host.h_aliases[i]; i++)
32                                         free(r->host.h_aliases[i]);
33                                 free(r->host.h_aliases);
34                         }
35                         if (r->host.h_addr_list){
36                                 for (i=0; r->host.h_addr_list[i]; i++)
37                                         free(r->host.h_addr_list[i]);
38                                 free(r->host.h_addr_list);
39                         }
40                         free(r);
41         }
42 }
43
44
45
46 struct route_elem* init_re()
47 {
48         struct route_elem* r;
49         r=(struct route_elem *) malloc(sizeof(struct route_elem));
50         if (r==0) return 0;
51         memset((void*)r, 0, sizeof (struct route_elem));
52         return r;
53 }
54
55
56
57 void push(struct route_elem* re, struct route_elem** head)
58 {
59         struct route_elem *t;
60         re->next=0;
61         if (*head==0){
62                 *head=re;
63                 return;
64         }
65         for (t=*head; t->next;t=t->next);
66         t->next=re;
67 }
68
69
70
71 void clear_rlist(struct route_elem** rl)
72 {
73         struct route_elem *t, *u;
74
75         if (*rl==0) return;
76         u=0;
77         for (t=*rl; t; u=t, t=t->next){
78                 if (u) free_re(u);
79         }
80         *rl=0;
81 }
82
83
84
85 int add_rule(struct cfg_line* cl, struct route_elem** head)
86 {
87         
88         struct route_elem* re;
89         struct hostent * he;
90         int ret;
91         int i,len, len2;
92
93
94         re=init_re();
95         if (re==0) return E_OUT_OF_MEM;
96
97         if (regcomp(&(re->method), cl->method, REG_EXTENDED|REG_NOSUB|REG_ICASE)){
98                 DPrint("ERROR: bad re \"%s\"\n", cl->method);
99                 ret=E_BAD_RE;
100                 goto error;
101         }
102         if (regcomp(&(re->uri), cl->uri, REG_EXTENDED|REG_NOSUB|REG_ICASE) ){
103                 DPrint("ERROR: bad re \"%s\"\n", cl->uri);
104                 ret=E_BAD_RE;
105                 goto error;
106         }
107
108         
109         he=gethostbyname(cl->address);
110         if (he==0){
111                 DPrint("ERROR: cannot resolve \"%s\"\n", cl->address);
112                 ret=E_BAD_ADDRESS;
113                 goto error;
114         }
115         
116         /* start copying the host entry.. */
117         /* copy h_name */
118         len=strlen(he->h_name)+1;
119         re->host.h_name=(char*)malloc(len);
120         if (re->host.h_name) strncpy(re->host.h_name, he->h_name, len);
121         else{
122                 ret=E_OUT_OF_MEM;
123                 goto error;
124         }
125
126         /* copy h_aliases */
127         for (len=0;he->h_aliases[len];len++);
128         re->host.h_aliases=(char**)malloc(len+1);
129         if (re->host.h_aliases==0){
130                 ret=E_OUT_OF_MEM;
131                 goto error;
132         }
133         memset((void*)re->host.h_aliases, 0, sizeof(char*) * (len+1) );
134         for (i=0;i<len;i++){
135                 len2=strlen(he->h_aliases[i])+1;
136                 re->host.h_aliases[i]=(char*)malloc(len2);
137                 if (re->host.h_aliases==0){
138                         ret=E_OUT_OF_MEM;
139                         goto error;
140                 }
141                 strncpy(re->host.h_aliases[i], he->h_aliases[i], len2);
142         }
143         /* copy h_addr_list */
144         for (len=0;he->h_addr_list[len];len++);
145         re->host.h_addr_list=(char**)malloc(len+1);
146         if (re->host.h_addr_list==0){
147                 ret=E_OUT_OF_MEM;
148                 goto error;
149         }
150         memset((void*)re->host.h_addr_list, 0, sizeof(char*) * (len+1) );
151         for (i=0;i<len;i++){
152                 re->host.h_addr_list[i]=(char*)malloc(he->h_length+1);
153                 if (re->host.h_addr_list==0){
154                         ret=E_OUT_OF_MEM;
155                         goto error;
156                 }
157                 memcpy(re->host.h_addr_list[i], he->h_addr_list[i], he->h_length+1);
158         }
159         /* copy h_addr_type & length */
160         re->host.h_addrtype=he->h_addrtype;
161         re->host.h_length=he->h_length;
162         /*finished hostent copy */
163
164         
165         
166         re->current_addr_idx=0;
167         re->ok=1;
168
169         push(re,head);
170         return 0;
171         
172 error:
173                 free_re(re);
174                 return ret;
175 }
176
177
178
179 struct route_elem* route_match(char* method, char* uri, struct route_elem** rl)
180 {
181         struct route_elem* t;
182         if (*rl==0){
183                 DPrint("WARNING: empty routing table\n");
184                 return 0;
185         }
186         for (t=*rl; t; t=t->next){
187                 if (regexec(&(t->method), method, 0, 0, 0)==0){
188                         /* we have a method mach !!! */
189                         if (regexec(&(t->uri), uri, 0, 0, 0)==0){
190                                 /* we have a full match */
191                                 return t;
192                         }
193                 }
194         }
195         /* no match :( */
196         return 0;
197 }
198
199
200
201 /* debug function, prints main routing table */
202 void print_rl()
203 {
204         struct route_elem* t;
205         int i,j;
206
207         if (rlist==0){
208                 DPrint("the routing table is emty\n");
209                 return;
210         }
211         
212         for (t=rlist,i=0; t; i++, t=t->next){
213                 DPrint("%2d.to=%s ; route ok=%d\n", i,
214                                 t->host.h_name, t->ok);
215                 DPrint("   ips: ");
216                 for (j=0; t->host.h_addr_list[j]; j++)
217                         DPrint("%d.%d.%d.%d ",
218                                 (unsigned char) t->host.h_addr_list[j][0],
219                                 (unsigned char) t->host.h_addr_list[j][1],
220                             (unsigned char) t->host.h_addr_list[j][2],
221                                 (unsigned char) t->host.h_addr_list[j][3]
222                                   );
223                                 
224                 DPrint("\n   Statistics: tx=%d, errors=%d, tx_bytes=%d, idx=%d\n",
225                                 t->tx, t->errors, t->tx_bytes, t->current_addr_idx);
226         }
227
228 }
229
230