Browse code

- added missing socket_info files

Andrei Pelinescu-Onciul authored on 24/10/2003 20:29:02
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,621 @@
1
+/* $Id$
2
+ *
3
+ * find & manage listen addresses 
4
+ *
5
+ * Copyright (C) 2001-2003 Fhg Fokus
6
+ *
7
+ * This file is part of ser, a free SIP server.
8
+ *
9
+ * ser is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation; either version 2 of the License, or
12
+ * (at your option) any later version
13
+ *
14
+ * For a license to use the ser software under conditions
15
+ * other than those described here, or to purchase support for this
16
+ * software, please contact iptel.org by e-mail at the following addresses:
17
+ *    info@iptel.org
18
+ *
19
+ * ser is distributed in the hope that it will be useful,
20
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
+ * GNU General Public License for more details.
23
+ *
24
+ * You should have received a copy of the GNU General Public License 
25
+ * along with this program; if not, write to the Free Software 
26
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27
+ */
28
+/*
29
+ * This file contains code that initializes and handles ser listen addresses
30
+ * lists (struct socket_info). It is used mainly on startup.
31
+ * 
32
+ * History:
33
+ * --------
34
+ *  2003-10-22  created by andrei
35
+ */
36
+
37
+
38
+#include <string.h>
39
+#include <errno.h>
40
+#include <unistd.h>
41
+#include <sys/types.h>
42
+#include <sys/socket.h>
43
+#include <sys/utsname.h>
44
+#include <stdio.h>
45
+
46
+#include <sys/ioctl.h>
47
+#include <net/if.h>
48
+#ifdef HAVE_SYS_SOCKIO_H
49
+#include <sys/sockio.h>
50
+#endif
51
+
52
+#include "globals.h"
53
+#include "socket_info.h"
54
+#include "dprint.h"
55
+#include "mem/mem.h"
56
+#include "ut.h"
57
+#include "resolve.h"
58
+#include "name_alias.h"
59
+
60
+
61
+
62
+/* list manip. functions (internal use only) */
63
+
64
+
65
+/* append */
66
+#define sock_listadd(head, el) \
67
+	do{\
68
+		if (*(head)==0) *(head)=(el); \
69
+		else{ \
70
+			for((el)->next=*(head); (el)->next->next;\
71
+					(el)->next=(el)->next->next); \
72
+			(el)->next->next=(el); \
73
+			(el)->prev=(el)->next; \
74
+			(el)->next=0; \
75
+		}\
76
+	}while(0)
77
+
78
+
79
+/* insert after "after" */
80
+#define sock_listins(el, after) \
81
+	do{ \
82
+		if ((after)){\
83
+			(el)->next=(after)->next; \
84
+			if ((after)->next) (after)->next->prev=(el); \
85
+			(after)->next=(el); \
86
+			(el)->prev=(after); \
87
+		}else{ /* after==0 = list head */ \
88
+			(after)=(el); \
89
+			(el)->next=(el)->prev=0; \
90
+		}\
91
+	}while(0)
92
+
93
+
94
+#define sock_listrm(head, el) \
95
+	do {\
96
+		if (*(head)==(el)) *(head)=(el)->next; \
97
+		if ((el)->next) (el)->next->prev=(el)->prev; \
98
+		if ((el)->prev) (el)->prev->next=(el)->next; \
99
+	}while(0)
100
+
101
+
102
+
103
+/* another helper function, it just creates a socket_info struct */
104
+static inline struct socket_info* new_sock_info(	char* name,
105
+								unsigned short port, unsigned short proto,
106
+								enum si_flags flags)
107
+{
108
+	struct socket_info* si;
109
+	
110
+	si=(struct socket_info*) pkg_malloc(sizeof(struct socket_info));
111
+	if (si==0) goto error;
112
+	memset(si, 0, sizeof(struct socket_info));
113
+	si->name.len=strlen(name);
114
+	si->name.s=(char*)pkg_malloc(si->name.len+1); /* include \0 */
115
+	if (si->name.s==0) goto error;
116
+	memcpy(si->name.s, name, si->name.len+1);
117
+	/* set port & proto */
118
+	si->port_no=port;
119
+	si->proto=proto;
120
+	si->flags=flags;
121
+	return si;
122
+error:
123
+	LOG(L_ERR, "ERROR: new_sock_info: memory allocation error\n");
124
+	if (si) pkg_free(si);
125
+	return 0;
126
+}
127
+
128
+
129
+
130
+/*  delete a socket_info struct */
131
+static void free_sock_info(struct socket_info* si)
132
+{
133
+	if(si){
134
+		if(si->name.s) pkg_free(si->name.s);
135
+		if(si->address_str.s) pkg_free(si->address_str.s);
136
+		if(si->port_no_str.s) pkg_free(si->port_no_str.s);
137
+	}
138
+}
139
+
140
+
141
+
142
+static char* get_proto_name(unsigned short proto)
143
+{
144
+	switch(proto){
145
+		case PROTO_NONE:
146
+			return "*";
147
+		case PROTO_UDP:
148
+			return "udp";
149
+#ifdef USE_TCP
150
+		case PROTO_TCP:
151
+			return "tcp";
152
+#endif
153
+#ifdef USE_TLS
154
+		case PROTO_TLS:
155
+			return "tls";
156
+#endif
157
+		default:
158
+			return "unknown";
159
+	}
160
+}
161
+
162
+
163
+static struct socket_info** get_sock_info_list(unsigned short proto)
164
+{
165
+	
166
+	switch(proto){
167
+		case PROTO_UDP:
168
+			return &udp_listen;
169
+			break;
170
+#ifdef USE_TCP
171
+		case PROTO_TCP:
172
+			return &tcp_listen;
173
+			break;
174
+#endif
175
+#ifdef USE_TLS
176
+		case PROTO_TLS:
177
+			return &tls_listen;
178
+			break;
179
+#endif
180
+		default:
181
+			LOG(L_CRIT, "BUG: get_sock_info_list: invalid proto %d\n", proto);
182
+	}
183
+	return 0;
184
+}
185
+
186
+
187
+
188
+/* adds a new sock_info structure to the corresponding list
189
+ * return  0 on success, -1 on error */
190
+int new_sock2list(char* name, unsigned short port, unsigned short proto,
191
+						enum si_flags flags, struct socket_info** list)
192
+{
193
+	struct socket_info* si;
194
+	
195
+	si=new_sock_info(name, port, proto, flags);
196
+	if (si==0){
197
+		LOG(L_ERR, "ERROR: add_listen_iface: new_sock_info failed\n");
198
+		goto error;
199
+	}
200
+	sock_listadd(list, si);
201
+	return 0;
202
+error:
203
+	return -1;
204
+}
205
+
206
+
207
+
208
+/* adds a sock_info structure to the corresponding proto list
209
+ * return  0 on success, -1 on error */
210
+int add_listen_iface(char* name, unsigned short port, unsigned short proto,
211
+						enum si_flags flags)
212
+{
213
+	struct socket_info** list;
214
+	unsigned short c_proto;
215
+	
216
+	c_proto=(proto)?proto:PROTO_UDP;
217
+	do{
218
+		list=get_sock_info_list(c_proto);
219
+		if (list==0){
220
+			LOG(L_ERR, "ERROR: add_listen_iface: get_sock_info_list failed\n");
221
+			goto error;
222
+		}
223
+		if (new_sock2list(name, port, c_proto, flags, list)<0){
224
+			LOG(L_ERR, "ERROR: add_listen_iface: new_sock2list failed\n");
225
+			goto error;
226
+		}
227
+	}while( (proto==0) && (c_proto=next_proto(c_proto)));
228
+	return 0;
229
+error:
230
+	return -1;
231
+}
232
+
233
+
234
+
235
+/* add all family type addresses of interface if_name to the socket_info array
236
+ * if if_name==0, adds all addresses on all interfaces
237
+ * WARNING: it only works with ipv6 addresses on FreeBSD
238
+ * return: -1 on error, 0 on success
239
+ */
240
+int add_interfaces(char* if_name, int family, unsigned short port,
241
+					unsigned short proto,
242
+					struct socket_info** list)
243
+{
244
+	struct ifconf ifc;
245
+	struct ifreq ifr;
246
+	struct ifreq ifrcopy;
247
+	char*  last;
248
+	char* p;
249
+	int size;
250
+	int lastlen;
251
+	int s;
252
+	char* tmp;
253
+	struct ip_addr addr;
254
+	int ret;
255
+	enum si_flags flags;
256
+	
257
+#ifdef HAVE_SOCKADDR_SA_LEN
258
+	#ifndef MAX
259
+		#define MAX(a,b) ( ((a)>(b))?(a):(b))
260
+	#endif
261
+#endif
262
+	/* ipv4 or ipv6 only*/
263
+	flags=SI_NONE;
264
+	s=socket(family, SOCK_DGRAM, 0);
265
+	ret=-1;
266
+	lastlen=0;
267
+	ifc.ifc_req=0;
268
+	for (size=10; ; size*=2){
269
+		ifc.ifc_len=size*sizeof(struct ifreq);
270
+		ifc.ifc_req=(struct ifreq*) pkg_malloc(size*sizeof(struct ifreq));
271
+		if (ifc.ifc_req==0){
272
+			LOG(L_ERR, "ERROR: add_interfaces: memory allocation failure\n");
273
+			goto error;
274
+		}
275
+		if (ioctl(s, SIOCGIFCONF, &ifc)==-1){
276
+			if(errno==EBADF) return 0; /* invalid descriptor => no such ifs*/
277
+			LOG(L_ERR, "ERROR: add_interfaces: ioctl failed: %s\n",
278
+					strerror(errno));
279
+			goto error;
280
+		}
281
+		if  ((lastlen) && (ifc.ifc_len==lastlen)) break; /*success,
282
+														   len not changed*/
283
+		lastlen=ifc.ifc_len;
284
+		/* try a bigger array*/
285
+		pkg_free(ifc.ifc_req);
286
+	}
287
+	
288
+	last=(char*)ifc.ifc_req+ifc.ifc_len;
289
+	for(p=(char*)ifc.ifc_req; p<last;
290
+			p+=(sizeof(ifr.ifr_name)+
291
+			#ifdef  HAVE_SOCKADDR_SA_LEN
292
+				MAX(ifr.ifr_addr.sa_len, sizeof(struct sockaddr))
293
+			#else
294
+				( (ifr.ifr_addr.sa_family==AF_INET)?
295
+					sizeof(struct sockaddr_in):
296
+					((ifr.ifr_addr.sa_family==AF_INET6)?
297
+						sizeof(struct sockaddr_in6):sizeof(struct sockaddr)) )
298
+			#endif
299
+				)
300
+		)
301
+	{
302
+		/* copy contents into ifr structure
303
+		 * warning: it might be longer (e.g. ipv6 address) */
304
+		memcpy(&ifr, p, sizeof(ifr));
305
+		if (ifr.ifr_addr.sa_family!=family){
306
+			/*printf("strange family %d skipping...\n",
307
+					ifr->ifr_addr.sa_family);*/
308
+			continue;
309
+		}
310
+		
311
+		/*get flags*/
312
+		ifrcopy=ifr;
313
+		if (ioctl(s, SIOCGIFFLAGS,  &ifrcopy)!=-1){ /* ignore errors */
314
+			/* ignore down ifs only if listening on all of them*/
315
+			if (if_name==0){ 
316
+				/* if if not up, skip it*/
317
+				if (!(ifrcopy.ifr_flags & IFF_UP)) continue;
318
+			}
319
+		}
320
+		
321
+		
322
+		
323
+		if ((if_name==0)||
324
+			(strncmp(if_name, ifr.ifr_name, sizeof(ifr.ifr_name))==0)){
325
+			
326
+			/*add address*/
327
+			sockaddr2ip_addr(&addr, 
328
+					(struct sockaddr*)(p+(long)&((struct ifreq*)0)->ifr_addr));
329
+			if ((tmp=ip_addr2a(&addr))==0) goto error;
330
+			/* check if loopback */
331
+			if (ifrcopy.ifr_flags & IFF_LOOPBACK) 
332
+				flags|=SI_IS_LO;
333
+			/* add it to one of the lists */
334
+			if (new_sock2list(tmp, port, proto, flags, list)!=0){
335
+				LOG(L_ERR, "ERROR: add_interfaces: new_sock2list failed\n");
336
+				goto error;
337
+			}
338
+			ret=0;
339
+		}
340
+			/*
341
+			printf("%s:\n", ifr->ifr_name);
342
+			printf("        ");
343
+			print_sockaddr(&(ifr->ifr_addr));
344
+			printf("        ");
345
+			ls_ifflags(ifr->ifr_name, family, options);
346
+			printf("\n");*/
347
+	}
348
+	pkg_free(ifc.ifc_req); /*clean up*/
349
+	close(s);
350
+	return  ret;
351
+error:
352
+	if (ifc.ifc_req) pkg_free(ifc.ifc_req);
353
+	close(s);
354
+	return -1;
355
+}
356
+
357
+
358
+
359
+/* fixes a socket list => resolve addresses, 
360
+ * interface names, fills missing members, remove duplicates */
361
+static int fix_socket_list(struct socket_info **list)
362
+{
363
+	struct socket_info* si;
364
+	struct socket_info* l;
365
+	struct socket_info* next;
366
+	char* tmp;
367
+	int len;
368
+	struct hostent* he;
369
+	char** h;
370
+	
371
+	/* try to change all the interface names into addresses
372
+	 *  --ugly hack */
373
+	
374
+	for (si=*list;si;){
375
+		next=si->next;
376
+		if (add_interfaces(si->name.s, AF_INET, si->port_no,
377
+							si->proto, list)!=-1){
378
+			/* success => remove current entry (shift the entire array)*/
379
+			sock_listrm(list, si);
380
+			free_sock_info(si);
381
+		}
382
+		si=next;
383
+	}
384
+	/* get ips & fill the port numbers*/
385
+#ifdef EXTRA_DEBUG
386
+	DBG("Listening on \n");
387
+#endif
388
+	for (si=*list;si;si=si->next){
389
+		/* fix port number, port_no should be !=0 here */
390
+		if (si->port_no==0){
391
+#ifdef USE_TLS
392
+			si->port_no= (si->proto==PROTO_TLS)?tls_port_no:port_no;
393
+#else
394
+			si->port_no= port_no;
395
+#endif
396
+		}
397
+		tmp=int2str(si->port_no, &len);
398
+		if (len>=MAX_PORT_LEN){
399
+			LOG(L_ERR, "ERROR: fix_socket_list: bad port number: %d\n", 
400
+						si->port_no);
401
+			goto error;
402
+		}
403
+		si->port_no_str.s=(char*)pkg_malloc(len+1);
404
+		if (si->port_no_str.s==0){
405
+			LOG(L_ERR, "ERROR: fix_socket_list: out of memory.\n");
406
+			goto error;
407
+		}
408
+		strncpy(si->port_no_str.s, tmp, len+1);
409
+		si->port_no_str.len=len;
410
+		
411
+		/* get "official hostnames", all the aliases etc. */
412
+		he=resolvehost(si->name.s);
413
+		if (he==0){
414
+			LOG(L_ERR, "ERROR: fix_socket_list: could not resolve %s\n",
415
+					si->name.s);
416
+			goto error;
417
+		}
418
+		/* check if we got the official name */
419
+		if (strcasecmp(he->h_name, si->name.s)!=0){
420
+			if (add_alias(si->name.s, si->name.len,
421
+							si->port_no, si->proto)<0){
422
+				LOG(L_ERR, "ERROR: fix_socket_list: add_alias failed\n");
423
+			}
424
+			/* change the oficial name */
425
+			pkg_free(si->name.s);
426
+			si->name.s=(char*)pkg_malloc(strlen(he->h_name)+1);
427
+			if (si->name.s==0){
428
+				LOG(L_ERR,  "ERROR: fix_socket_list: out of memory.\n");
429
+				goto error;
430
+			}
431
+			si->name.len=strlen(he->h_name);
432
+			strncpy(si->name.s, he->h_name, si->name.len+1);
433
+		}
434
+		/* add the aliases*/
435
+		for(h=he->h_aliases; h && *h; h++)
436
+			if (add_alias(*h, strlen(*h), si->port_no, si->proto)<0){
437
+				LOG(L_ERR, "ERROR: fix_socket_list: add_alias failed\n");
438
+			}
439
+		hostent2ip_addr(&si->address, he, 0); /*convert to ip_addr 
440
+														 format*/
441
+		if ((tmp=ip_addr2a(&si->address))==0) goto error;
442
+		si->address_str.s=(char*)pkg_malloc(strlen(tmp)+1);
443
+		if (si->address_str.s==0){
444
+			LOG(L_ERR, "ERROR: fix_socket_list: out of memory.\n");
445
+			goto error;
446
+		}
447
+		strncpy(si->address_str.s, tmp, strlen(tmp)+1);
448
+		/* set is_ip (1 if name is an ip address, 0 otherwise) */
449
+		si->address_str.len=strlen(tmp);
450
+		if 	(	(si->address_str.len==si->name.len)&&
451
+				(strncasecmp(si->address_str.s, si->name.s,
452
+								si->address_str.len)==0)
453
+			){
454
+				si->flags|=SI_IS_IP;
455
+				/* do rev. dns on it (for aliases)*/
456
+				he=rev_resolvehost(&si->address);
457
+				if (he==0){
458
+					LOG(L_WARN, "WARNING: fix_socket_list:"
459
+							" could not rev. resolve %s\n",
460
+							si->name.s);
461
+				}else{
462
+					/* add the aliases*/
463
+					if (add_alias(he->h_name, strlen(he->h_name),
464
+									si->port_no, si->proto)<0){
465
+						LOG(L_ERR, "ERROR: fix_socket_list:"
466
+									"add_alias failed\n");
467
+					}
468
+					for(h=he->h_aliases; h && *h; h++)
469
+						if (add_alias(*h,strlen(*h),si->port_no,si->proto)<0){
470
+							LOG(L_ERR, "ERROR: fix_socket_list:"
471
+									" add_alias failed\n");
472
+						}
473
+				}
474
+		}
475
+#ifdef EXTRA_DEBUG
476
+		printf("              %.*s [%s]:%s\n", si->name.len, 
477
+				si->name.s, si->address_str.s, si->port_no_str.s);
478
+#endif
479
+	}
480
+	/* removing duplicate addresses*/
481
+	for (si=*list;si; si=si->next){
482
+		for (l=si->next;l;){
483
+			next=l->next;
484
+			if ((si->port_no==l->port_no) &&
485
+				(si->address.af==l->address.af) &&
486
+				(memcmp(si->address.u.addr, l->address.u.addr, si->address.len)
487
+					== 0)
488
+				){
489
+#ifdef EXTRA_DEBUG
490
+				printf("removing duplicate %s [%s] ==  %s [%s]\n",
491
+						si->name.s, si->address_str.s,
492
+						 l->name.s, l->address_str.s);
493
+#endif
494
+				/* add the name to the alias list*/
495
+				if ((!(l->flags&& SI_IS_IP)) && (
496
+						(l->name.len!=si->name.len)||
497
+						(strncmp(l->name.s, si->name.s, si->name.len)!=0))
498
+					)
499
+					add_alias(l->name.s, l->name.len, l->port_no, l->proto);
500
+						
501
+				/* remove l*/
502
+				sock_listrm(list, l);
503
+				free_sock_info(l);
504
+			}
505
+			l=next;
506
+		}
507
+	}
508
+	return 0;
509
+error:
510
+	return -1;
511
+}
512
+
513
+
514
+
515
+/* fix all 3 socket lists
516
+ * return 0 on success, -1 on error */
517
+int fix_all_socket_lists()
518
+{
519
+	struct utsname myname;
520
+	
521
+	if ((udp_listen==0)
522
+#ifdef USE_TCP
523
+			&& (tcp_listen==0)
524
+#ifdef USE_TLS
525
+			&& (tls_listen==0)
526
+#endif
527
+#endif
528
+		){
529
+		/* get all listening ipv4 interfaces */
530
+		if (add_interfaces(0, AF_INET, 0,  PROTO_UDP, &udp_listen)==0){
531
+			/* if ok, try to add the others too */
532
+#ifdef USE_TCP
533
+			if (add_interfaces(0, AF_INET, 0,  PROTO_TCP, &tcp_listen)!=0)
534
+				goto error;
535
+#ifdef USE_TLS
536
+			if (add_interfaces(0, AF_INET, 0, PROTO_TLS, &tls_listen)!=0)
537
+				goto error;
538
+#endif
539
+#endif
540
+		}else{
541
+			/* if error fall back to get hostname */
542
+			/* get our address, only the first one */
543
+			if (uname (&myname) <0){
544
+				LOG(L_ERR, "ERROR: fix_all_socket_lists: cannot determine"
545
+						" hostname, try -l address\n");
546
+				goto error;
547
+			}
548
+			if (add_listen_iface(myname.nodename, 0, 0, 0)!=0){
549
+				LOG(L_ERR, "ERROR: fix_all_socket_lists: add_listen_iface "
550
+						"failed \n");
551
+				goto error;
552
+			}
553
+		}
554
+	}
555
+	if (fix_socket_list(&udp_listen)!=0){
556
+		LOG(L_ERR, "ERROR: fix_all_socket_lists: fix_socket_list"
557
+				" udp failed\n");
558
+		goto error;
559
+	}
560
+#ifdef USE_TCP
561
+	if (fix_socket_list(&tcp_listen)!=0){
562
+		LOG(L_ERR, "ERROR: fix_all_socket_lists: fix_socket_list"
563
+				" tcp failed\n");
564
+		goto error;
565
+	}
566
+#ifdef USE_TLS
567
+	if (fix_socket_list(&tls_listen)!=0){
568
+		LOG(L_ERR, "ERROR: fix_all_socket_lists: fix_socket_list"
569
+				" tls failed\n");
570
+		goto error;
571
+	}
572
+#endif
573
+#endif
574
+	if ((udp_listen==0)
575
+#ifdef USE_TCP
576
+			&& (tcp_listen==0)
577
+#ifdef USE_TLS
578
+			&& (tls_listen==0)
579
+#endif
580
+#endif
581
+		){
582
+		LOG(L_ERR, "ERROR: fix_all_socket_lists: no listening sockets\n");
583
+		goto error;
584
+	}
585
+	return 0;
586
+error:
587
+	return -1;
588
+}
589
+
590
+
591
+
592
+void print_all_socket_lists()
593
+{
594
+	struct socket_info *si;
595
+	struct socket_info** list;
596
+	unsigned short proto;
597
+	
598
+	
599
+	proto=PROTO_UDP;
600
+	do{
601
+		list=get_sock_info_list(proto);
602
+		for(si=list?*list:0; si; si=si->next){
603
+			printf("             %s: %s [%s]:%s\n", get_proto_name(proto),
604
+						si->name.s, si->address_str.s, si->port_no_str.s);
605
+		}
606
+	}while((proto=next_proto(proto)));
607
+}
608
+
609
+
610
+void print_aliases()
611
+{
612
+	struct host_alias* a;
613
+
614
+	for(a=aliases; a; a=a->next) 
615
+		if (a->port)
616
+			printf("             %s: %.*s:%d\n", get_proto_name(a->proto), 
617
+					a->alias.len, a->alias.s, a->port);
618
+		else
619
+			printf("             %s: %.*s:*\n", get_proto_name(a->proto), 
620
+					a->alias.len, a->alias.s);
621
+}
0 622
new file mode 100644
... ...
@@ -0,0 +1,112 @@
1
+/* $Id$
2
+ *
3
+ * find & manage listen addresses 
4
+ *
5
+ * Copyright (C) 2001-2003 Fhg Fokus
6
+ *
7
+ * This file is part of ser, a free SIP server.
8
+ *
9
+ * ser is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation; either version 2 of the License, or
12
+ * (at your option) any later version
13
+ *
14
+ * For a license to use the ser software under conditions
15
+ * other than those described here, or to purchase support for this
16
+ * software, please contact iptel.org by e-mail at the following addresses:
17
+ *    info@iptel.org
18
+ *
19
+ * ser is distributed in the hope that it will be useful,
20
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
+ * GNU General Public License for more details.
23
+ *
24
+ * You should have received a copy of the GNU General Public License 
25
+ * along with this program; if not, write to" the Free Software 
26
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27
+ */
28
+/*
29
+ * This file contains code that initializes and handles ser listen addresses
30
+ * lists (struct socket_info). It is used mainly on startup.
31
+ * 
32
+ * History:
33
+ * --------
34
+ *  2003-10-22  created by andrei
35
+ */
36
+
37
+
38
+#ifndef socket_info_h
39
+#define socket_info_h
40
+
41
+#include "ip_addr.h" 
42
+#include "dprint.h"
43
+/* struct socket_info is defined in ip_addr.h */
44
+
45
+struct socket_info* udp_listen;
46
+#ifdef USE_TCP
47
+struct socket_info* tcp_listen;
48
+#endif
49
+#ifdef USE_TLS
50
+struct socket_info* tls_listen;
51
+#endif
52
+
53
+
54
+int add_listen_iface(char* name, unsigned short port, unsigned short proto,
55
+							enum si_flags flags);
56
+int fix_all_socket_lists();
57
+void print_all_socket_lists();
58
+void print_aliases();
59
+
60
+
61
+/* helper function:
62
+ * returns next protocol, if the last one is reached return 0
63
+ * usefull for cycling on the supported protocols */
64
+static inline int next_proto(unsigned short proto)
65
+{
66
+	switch(proto){
67
+		case PROTO_NONE:
68
+			return PROTO_UDP;
69
+		case PROTO_UDP:
70
+#ifdef	USE_TCP
71
+			return PROTO_TCP;
72
+#else
73
+			return 0;
74
+#endif
75
+#ifdef USE_TCP
76
+		case PROTO_TCP:
77
+#ifdef USE_TLS
78
+			return PROTO_TLS;
79
+#else
80
+			return 0;
81
+#endif
82
+#endif
83
+#ifdef USE_TLS
84
+		case PROTO_TLS:
85
+			return 0;
86
+#endif
87
+		default:
88
+			LOG(L_ERR, "ERROR: next_proto: unknown proto %d\n", proto);
89
+	}
90
+	return 0;
91
+}
92
+
93
+
94
+
95
+/* gets first non-null socket_info structure
96
+ * (usefull if for. e.g we are not listening on any udp sockets )
97
+ */
98
+inline static struct socket_info* get_first_socket()
99
+{
100
+	if (udp_listen) return udp_listen;
101
+#ifdef USE_TCP
102
+	else if (tcp_listen) return tcp_listen;
103
+#ifdef USE_TLS
104
+	else if (tls_listen) return tls_listen;
105
+#endif
106
+#endif
107
+	return 0;
108
+}
109
+
110
+
111
+
112
+#endif