68ef45232f3b45e3fee0d161fbdb5ccfb9277b4f
[sip-router] / ip_addr.h
1 /* $Id$
2  *
3  * ip address family related structures
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  * History:
30  * --------
31  *  2003-02-13  added struct dest_info (andrei)
32  *  2003-04-06  all ports are stored/passed in host byte order now (andrei)
33  *  2006-04-20  comp support in recv_info and dest_info (andrei)
34  *  2006-04-21  added init_dst_from_rcv (andrei)
35  *  2007-06-26  added ip_addr_mk_any() (andrei)
36  *  2008-05-21  added su2a(), ip_addr2sbuf(), ip4tosbuf(), ip62sbuf() (andrei)
37  */
38
39 #ifndef ip_addr_h
40 #define ip_addr_h
41
42 #include <string.h>
43 #include <sys/types.h>
44 #include <sys/socket.h>
45 #include <netinet/in.h>
46 #include <netdb.h>
47 #include "str.h"
48 #include "compiler_opt.h"
49 #include "ut.h"
50
51
52 #include "dprint.h"
53
54 enum sip_protos { PROTO_NONE, PROTO_UDP, PROTO_TCP, PROTO_TLS, PROTO_SCTP };
55 #ifdef USE_COMP
56 enum comp_methods { COMP_NONE, COMP_SIGCOMP, COMP_SERGZ };
57 #endif
58
59 struct ip_addr{
60         unsigned int af; /* address family: AF_INET6 or AF_INET */
61         unsigned int len;    /* address len, 16 or 4 */
62         
63         /* 64 bits aligned address */
64         union {
65                 unsigned long  addrl[16/sizeof(long)]; /* long format*/
66                 unsigned int   addr32[4];
67                 unsigned short addr16[8];
68                 unsigned char  addr[16];
69         }u;
70 };
71
72
73
74 struct net{
75         struct ip_addr ip;
76         struct ip_addr mask;
77 };
78
79 union sockaddr_union{
80                 struct sockaddr     s;
81                 struct sockaddr_in  sin;
82         #ifdef USE_IPV6
83                 struct sockaddr_in6 sin6;
84         #endif
85 };
86
87
88
89 enum si_flags { SI_NONE=0, SI_IS_IP=1, SI_IS_LO=2, SI_IS_MCAST=4,
90                                  SI_IS_ANY=8 };
91
92 struct socket_info{
93         int socket;
94         str name; /* name - eg.: foo.bar or 10.0.0.1 */
95         struct ip_addr address; /* ip address */
96         str address_str;        /* ip address converted to string -- optimization*/
97         str port_no_str; /* port number converted to string -- optimization*/
98         enum si_flags flags; /* SI_IS_IP | SI_IS_LO | SI_IS_MCAST */
99         union sockaddr_union su; 
100         struct socket_info* next;
101         struct socket_info* prev;
102         unsigned short port_no;  /* port number */
103         char proto; /* tcp or udp*/
104 };
105
106
107 struct receive_info{
108         struct ip_addr src_ip;
109         struct ip_addr dst_ip;
110         unsigned short src_port; /* host byte order */
111         unsigned short dst_port; /* host byte order */
112         int proto_reserved1; /* tcp stores the connection id here */
113         int proto_reserved2;
114         union sockaddr_union src_su; /* useful for replies*/
115         struct socket_info* bind_address; /* sock_info structure on which 
116                                                                           the msg was received*/
117         char proto;
118 #ifdef USE_COMP
119         short comp; /* compression */
120 #endif
121         /* no need for dst_su yet */
122 };
123
124
125 struct dest_info{
126         struct socket_info* send_sock;
127         union sockaddr_union to;
128         int id; /* tcp stores the connection id here */ 
129         char proto;
130 #ifdef USE_COMP
131         short comp;
132 #endif
133 };
134
135
136 struct socket_id{
137         char* name;
138         int proto;
139         int port;
140         struct socket_id* next;
141 };
142
143
144
145 /* len of the sockaddr */
146 #ifdef HAVE_SOCKADDR_SA_LEN
147 #define sockaddru_len(su)       ((su).s.sa_len)
148 #else
149 #ifdef USE_IPV6
150 #define sockaddru_len(su)       \
151                         (((su).s.sa_family==AF_INET6)?sizeof(struct sockaddr_in6):\
152                                         sizeof(struct sockaddr_in))
153 #else
154 #define sockaddru_len(su)       sizeof(struct sockaddr_in)
155 #endif /*USE_IPV6*/
156 #endif /* HAVE_SOCKADDR_SA_LEN*/
157         
158 /* inits an ip_addr with the addr. info from a hostent structure
159  * ip = struct ip_addr*
160  * he= struct hostent*
161  */
162 #define hostent2ip_addr(ip, he, addr_no) \
163         do{ \
164                 (ip)->af=(he)->h_addrtype; \
165                 (ip)->len=(he)->h_length;  \
166                 memcpy((ip)->u.addr, (he)->h_addr_list[(addr_no)], (ip)->len); \
167         }while(0)
168         
169
170
171
172 /* gets the protocol family corresponding to a specific address family
173  * ( PF_INET - AF_INET, PF_INET6 - AF_INET6, af for others)
174  */
175 #ifdef USE_IPV6
176 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:((af)==AF_INET6)?PF_INET6:(af))
177 #else
178 #define AF2PF(af)   (((af)==AF_INET)?PF_INET:(af))
179 #endif
180
181
182
183
184 struct net* mk_net(struct ip_addr* ip, struct ip_addr* mask);
185 struct net* mk_net_bitlen(struct ip_addr* ip, unsigned int bitlen);
186
187 void print_ip(char* prefix, struct ip_addr* ip, char* suffix);
188 void stdout_print_ip(struct ip_addr* ip);
189 void print_net(struct net* net);
190
191 #ifdef USE_MCAST
192 /* Returns 1 if the given address is a multicast address */
193 int is_mcast(struct ip_addr* ip);
194 #endif /* USE_MCAST */
195
196 /* returns 1 if the given ip address is INADDR_ANY or IN6ADDR_ANY,
197  * 0 otherwise */
198 inline static int ip_addr_any(struct ip_addr* ip)
199 {
200         int r;
201         int l;
202         
203         l=ip->len/4;
204         for (r=0; r<l; r++)
205                 if (ip->u.addr32[r]!=0)
206                         return 0;
207         return 1;
208 }
209
210
211
212 /* creates an ANY ip_addr (filled with 0, af and len properly set) */
213 inline static void ip_addr_mk_any(int af, struct ip_addr* ip)
214 {
215         ip->af=af;
216         if (likely(af==AF_INET)){
217                 ip->len=4;
218                 ip->u.addr32[0]=0;
219         }
220 #ifdef USE_IPV6
221         else{
222                 ip->len=16;
223 #if (defined (ULONG_MAX) && ULONG_MAX > 4294967295) || defined LP64
224                 /* long is 64 bits */
225                 ip->u.addrl[0]=0;
226                 ip->u.addrl[1]=0;
227 #else
228                 ip->u.addr32[0]=0;
229                 ip->u.addr32[1]=0;
230                 ip->u.addr32[2]=0;
231                 ip->u.addr32[3]=0;
232 #endif /* ULONG_MAX */
233         }
234 #endif
235 }
236
237 /* returns 1 if ip & net.mask == net.ip ; 0 otherwise & -1 on error 
238         [ diff. address families ]) */
239 inline static int matchnet(struct ip_addr* ip, struct net* net)
240 {
241         unsigned int r;
242
243         if (ip->af == net->ip.af){
244                 for(r=0; r<ip->len/4; r++){ /* ipv4 & ipv6 addresses are
245                                                                            all multiple of 4*/
246                         if ((ip->u.addr32[r]&net->mask.u.addr32[r])!=
247                                                                                                                  net->ip.u.addr32[r]){
248                                 return 0;
249                         }
250                 }
251                 return 1;
252         };
253         return -1;
254 }
255
256
257
258
259 /* inits an ip_addr pointer from a sockaddr structure*/
260 static inline void sockaddr2ip_addr(struct ip_addr* ip, struct sockaddr* sa)
261 {
262         switch(sa->sa_family){
263         case AF_INET:
264                         ip->af=AF_INET;
265                         ip->len=4;
266                         memcpy(ip->u.addr, &((struct sockaddr_in*)sa)->sin_addr, 4);
267                         break;
268 #ifdef USE_IPV6
269         case AF_INET6:
270                         ip->af=AF_INET6;
271                         ip->len=16;
272                         memcpy(ip->u.addr, &((struct sockaddr_in6*)sa)->sin6_addr, 16);
273                         break;
274 #endif
275         default:
276                         LOG(L_CRIT, "sockaddr2ip_addr: BUG: unknown address family %d\n",
277                                         sa->sa_family);
278         }
279 }
280
281
282
283 /* compare 2 ip_addrs (both args are pointers)*/
284 #define ip_addr_cmp(ip1, ip2) \
285         (((ip1)->af==(ip2)->af)&& \
286                 (memcmp((ip1)->u.addr, (ip2)->u.addr, (ip1)->len)==0))
287
288
289
290 /* compare 2 sockaddr_unions */
291 static inline int su_cmp(union sockaddr_union* s1, union sockaddr_union* s2)
292 {
293         if (s1->s.sa_family!=s2->s.sa_family) return 0;
294         switch(s1->s.sa_family){
295                 case AF_INET:
296                         return (s1->sin.sin_port==s2->sin.sin_port)&&
297                                         (memcmp(&s1->sin.sin_addr, &s2->sin.sin_addr, 4)==0);
298 #ifdef USE_IPV6
299                 case AF_INET6:
300                         return (s1->sin6.sin6_port==s2->sin6.sin6_port)&&
301                                         (memcmp(&s1->sin6.sin6_addr, &s2->sin6.sin6_addr, 16)==0);
302 #endif
303                 default:
304                         LOG(L_CRIT,"su_cmp: BUG: unknown address family %d\n",
305                                                 s1->s.sa_family);
306                         return 0;
307         }
308 }
309
310
311
312 /* gets the port number (host byte order) */
313 static inline unsigned short su_getport(union sockaddr_union* su)
314 {
315         switch(su->s.sa_family){
316                 case AF_INET:
317                         return ntohs(su->sin.sin_port);
318 #ifdef USE_IPV6
319                 case AF_INET6:
320                         return ntohs(su->sin6.sin6_port);
321 #endif
322                 default:
323                         LOG(L_CRIT,"su_get_port: BUG: unknown address family %d\n",
324                                                 su->s.sa_family);
325                         return 0;
326         }
327 }
328
329
330
331 /* sets the port number (host byte order) */
332 static inline void su_setport(union sockaddr_union* su, unsigned short port)
333 {
334         switch(su->s.sa_family){
335                 case AF_INET:
336                         su->sin.sin_port=htons(port);
337                         break;
338 #ifdef USE_IPV6
339                 case AF_INET6:
340                          su->sin6.sin6_port=htons(port);
341                          break;
342 #endif
343                 default:
344                         LOG(L_CRIT,"su_set_port: BUG: unknown address family %d\n",
345                                                 su->s.sa_family);
346         }
347 }
348
349
350
351 /* inits an ip_addr pointer from a sockaddr_union ip address */
352 static inline void su2ip_addr(struct ip_addr* ip, union sockaddr_union* su)
353 {
354         switch(su->s.sa_family){
355         case AF_INET: 
356                                         ip->af=AF_INET;
357                                         ip->len=4;
358                                         memcpy(ip->u.addr, &su->sin.sin_addr, 4);
359                                         break;
360 #ifdef USE_IPV6
361         case AF_INET6:
362                                         ip->af=AF_INET6;
363                                         ip->len=16;
364                                         memcpy(ip->u.addr, &su->sin6.sin6_addr, 16);
365                                         break;
366 #endif
367         default:
368                                         LOG(L_CRIT,"su2ip_addr: BUG: unknown address family %d\n",
369                                                         su->s.sa_family);
370         }
371 }
372
373
374 /* ip_addr2su -> the same as init_su*/
375 #define ip_addr2su init_su
376
377 /* inits a struct sockaddr_union from a struct ip_addr and a port no 
378  * returns 0 if ok, -1 on error (unknown address family)
379  * the port number is in host byte order */
380 static inline int init_su( union sockaddr_union* su,
381                                                         struct ip_addr* ip,
382                                                         unsigned short   port ) 
383 {
384         memset(su, 0, sizeof(union sockaddr_union));/*needed on freebsd*/
385         su->s.sa_family=ip->af;
386         switch(ip->af){
387 #ifdef USE_IPV6
388         case    AF_INET6:
389                 memcpy(&su->sin6.sin6_addr, ip->u.addr, ip->len); 
390                 #ifdef HAVE_SOCKADDR_SA_LEN
391                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
392                 #endif
393                 su->sin6.sin6_port=htons(port);
394                 break;
395 #endif
396         case AF_INET:
397                 memcpy(&su->sin.sin_addr, ip->u.addr, ip->len);
398                 #ifdef HAVE_SOCKADDR_SA_LEN
399                         su->sin.sin_len=sizeof(struct sockaddr_in);
400                 #endif
401                 su->sin.sin_port=htons(port);
402                 break;
403         default:
404                 LOG(L_CRIT, "init_ss: BUG: unknown address family %d\n", ip->af);
405                 return -1;
406         }
407         return 0;
408 }
409
410
411
412 /* inits a struct sockaddr_union from a struct hostent, an address index in
413  * the hostent structure and a port no. (host byte order)
414  * WARNING: no index overflow  checks!
415  * returns 0 if ok, -1 on error (unknown address family) */
416 static inline int hostent2su( union sockaddr_union* su,
417                                                                 struct hostent* he,
418                                                                 unsigned int idx,
419                                                                 unsigned short   port ) 
420 {
421         memset(su, 0, sizeof(union sockaddr_union)); /*needed on freebsd*/
422         su->s.sa_family=he->h_addrtype;
423         switch(he->h_addrtype){
424 #ifdef USE_IPV6
425         case    AF_INET6:
426                 memcpy(&su->sin6.sin6_addr, he->h_addr_list[idx], he->h_length);
427                 #ifdef HAVE_SOCKADDR_SA_LEN
428                         su->sin6.sin6_len=sizeof(struct sockaddr_in6);
429                 #endif
430                 su->sin6.sin6_port=htons(port);
431                 break;
432 #endif
433         case AF_INET:
434                 memcpy(&su->sin.sin_addr, he->h_addr_list[idx], he->h_length);
435                 #ifdef HAVE_SOCKADDR_SA_LEN
436                         su->sin.sin_len=sizeof(struct sockaddr_in);
437                 #endif
438                 su->sin.sin_port=htons(port);
439                 break;
440         default:
441                 LOG(L_CRIT, "hostent2su: BUG: unknown address family %d\n", 
442                                 he->h_addrtype);
443                 return -1;
444         }
445         return 0;
446 }
447
448
449
450 /* maximum size of a str returned by ip_addr2str */
451 #define IP6_MAX_STR_SIZE 39 /*1234:5678:9012:3456:7890:1234:5678:9012*/
452 #define IP4_MAX_STR_SIZE 15 /*123.456.789.012*/
453
454 #ifdef USE_IPV6
455 /* converts a raw ipv6 addr (16 bytes) to ascii */
456 static inline int ip6tosbuf(unsigned char* ip6, char* buff, int len)
457 {
458         int offset;
459         register unsigned char a,b,c;
460         register unsigned char d;
461         register unsigned short hex4;
462         int r;
463         #define HEXDIG(x) (((x)>=10)?(x)-10+'A':(x)+'0')
464         
465         
466         offset=0;
467         if (unlikely(len<IP6_MAX_STR_SIZE))
468                 return 0;
469         for(r=0;r<7;r++){
470                 hex4=((unsigned char)ip6[r*2]<<8)+(unsigned char)ip6[r*2+1];
471                 a=hex4>>12;
472                 b=(hex4>>8)&0xf;
473                 c=(hex4>>4)&0xf;
474                 d=hex4&0xf;
475                 if (a){
476                         buff[offset]=HEXDIG(a);
477                         buff[offset+1]=HEXDIG(b);
478                         buff[offset+2]=HEXDIG(c);
479                         buff[offset+3]=HEXDIG(d);
480                         buff[offset+4]=':';
481                         offset+=5;
482                 }else if(b){
483                         buff[offset]=HEXDIG(b);
484                         buff[offset+1]=HEXDIG(c);
485                         buff[offset+2]=HEXDIG(d);
486                         buff[offset+3]=':';
487                         offset+=4;
488                 }else if(c){
489                         buff[offset]=HEXDIG(c);
490                         buff[offset+1]=HEXDIG(d);
491                         buff[offset+2]=':';
492                         offset+=3;
493                 }else{
494                         buff[offset]=HEXDIG(d);
495                         buff[offset+1]=':';
496                         offset+=2;
497                 }
498         }
499         /* last int16*/
500         hex4=((unsigned char)ip6[r*2]<<8)+(unsigned char)ip6[r*2+1];
501         a=hex4>>12;
502         b=(hex4>>8)&0xf;
503         c=(hex4>>4)&0xf;
504         d=hex4&0xf;
505         if (a){
506                 buff[offset]=HEXDIG(a);
507                 buff[offset+1]=HEXDIG(b);
508                 buff[offset+2]=HEXDIG(c);
509                 buff[offset+3]=HEXDIG(d);
510                 offset+=4;
511         }else if(b){
512                 buff[offset]=HEXDIG(b);
513                 buff[offset+1]=HEXDIG(c);
514                 buff[offset+2]=HEXDIG(d);
515                 offset+=3;
516         }else if(c){
517                 buff[offset]=HEXDIG(c);
518                 buff[offset+1]=HEXDIG(d);
519                 offset+=2;
520         }else{
521                 buff[offset]=HEXDIG(d);
522                 offset+=1;
523         }
524         
525         return offset;
526 }
527 #endif /* USE_IPV6 */
528
529
530
531 /* converts a raw ipv4 addr (4 bytes) to ascii */
532 static inline int ip4tosbuf(unsigned char* ip4, char* buff, int len)
533 {
534         int offset;
535         register unsigned char a,b,c;
536         int r;
537         
538         
539         offset=0;
540         if (unlikely(len<IP4_MAX_STR_SIZE))
541                 return 0;
542         for(r=0;r<3;r++){
543                 a=(unsigned char)ip4[r]/100;
544                 c=(unsigned char)ip4[r]%10;
545                 b=(unsigned char)ip4[r]%100/10;
546                 if (a){
547                         buff[offset]=a+'0';
548                         buff[offset+1]=b+'0';
549                         buff[offset+2]=c+'0';
550                         buff[offset+3]='.';
551                         offset+=4;
552                 }else if (b){
553                         buff[offset]=b+'0';
554                         buff[offset+1]=c+'0';
555                         buff[offset+2]='.';
556                         offset+=3;
557                 }else{
558                         buff[offset]=c+'0';
559                         buff[offset+1]='.';
560                         offset+=2;
561                 }
562         }
563         /* last number */
564         a=(unsigned char)ip4[r]/100;
565         c=(unsigned char)ip4[r]%10;
566         b=(unsigned char)ip4[r]%100/10;
567         if (a){
568                 buff[offset]=a+'0';
569                 buff[offset+1]=b+'0';
570                 buff[offset+2]=c+'0';
571                 offset+=3;
572         }else if (b){
573                 buff[offset]=b+'0';
574                 buff[offset+1]=c+'0';
575                 offset+=2;
576         }else{
577                 buff[offset]=c+'0';
578                 offset+=1;
579         }
580         
581         return offset;
582 }
583
584
585
586 /* fast ip_addr -> string converter;
587  * returns number of bytes written in buf on success, <=0 on error
588  * The buffer must have enough space to hold the maximum size ip address
589  *  of the corresponding address (see IP[46] above) or else the function
590  *  will return error (no detailed might fit checks are made, for example
591  *   if len==7 the function will fail even for 1.2.3.4).
592  */
593 static inline int ip_addr2sbuf(struct ip_addr* ip, char* buff, int len)
594 {
595         switch(ip->af){
596         #ifdef USE_IPV6
597                 case AF_INET6:
598                         return ip6tosbuf(ip->u.addr, buff, len);
599                         break;
600         #endif /* USE_IPV6 */
601                 case AF_INET:
602                         return ip4tosbuf(ip->u.addr, buff, len);
603                         break;
604                 default:
605                         LOG(L_CRIT, "BUG: ip_addr2sbuf: unknown address family %d\n",
606                                         ip->af);
607                         return 0;
608         }
609         return 0;
610 }
611
612
613
614 /* maximum size of a str returned by ip_addr2a (including \0) */
615 #define IP_ADDR_MAX_STR_SIZE (IP6_MAX_STR_SIZE+1) /* ip62ascii +  \0*/
616 /* fast ip_addr -> string converter;
617  * it uses an internal buffer
618  */
619 static inline char* ip_addr2a(struct ip_addr* ip)
620 {
621
622         static char buff[IP_ADDR_MAX_STR_SIZE];
623         int len;
624         
625         
626         len=ip_addr2sbuf(ip, buff, sizeof(buff)-1);
627         buff[len]=0;
628
629         return buff;
630 }
631
632
633
634 #define SU2A_MAX_STR_SIZE  (IP6_MAX_STR_SIZE + 2 /* [] */+\
635                                                                 1 /* : */ + USHORT2SBUF_MAX_LEN + 1 /* \0 */)
636 /* returns an asciiz string containing the ip and the port
637  *  (<ip_addr>:port or [<ipv6_addr>]:port)
638  */
639 static inline char* su2a(union sockaddr_union* su, int su_len)
640 {
641         static char buf[SU2A_MAX_STR_SIZE];
642         int offs;
643         
644 #ifdef USE_IPV6
645         if (unlikely(su->s.sa_family==AF_INET6)){
646                 if (unlikely(su_len<sizeof(su->sin6)))
647                         return "<addr. error>";
648                 buf[0]='[';
649                 offs=1+ip6tosbuf((unsigned char*)&su->sin6.sin6_addr, &buf[1],
650                                                         sizeof(buf)-4);
651                 buf[offs]=']';
652                 offs++;
653         }else
654 #endif /* USE_IPV6*/
655         if (unlikely(su_len<sizeof(su->sin)))
656                 return "<addr. error>";
657         else
658                 offs=ip4tosbuf((unsigned char*)&su->sin.sin_addr, buf, sizeof(buf)-2);
659         buf[offs]=':';
660         offs+=1+ushort2sbuf(su_getport(su), &buf[offs+1], sizeof(buf)-(offs+1)-1);
661         buf[offs]=0;
662         return buf;
663 }
664
665
666
667 /* converts an ip_addr structure to a hostent, returns pointer to internal
668  * statical structure */
669 static inline struct hostent* ip_addr2he(str* name, struct ip_addr* ip)
670 {
671         static struct hostent he;
672         static char hostname[256];
673         static char* p_aliases[1];
674         static char* p_addr[2];
675         static char address[16];
676         
677         p_aliases[0]=0; /* no aliases*/
678         p_addr[1]=0; /* only one address*/
679         p_addr[0]=address;
680         strncpy(hostname, name->s, (name->len<256)?(name->len)+1:256);
681         if (ip->len>16) return 0;
682         memcpy(address, ip->u.addr, ip->len);
683         
684         he.h_addrtype=ip->af;
685         he.h_length=ip->len;
686         he.h_addr_list=p_addr;
687         he.h_aliases=p_aliases;
688         he.h_name=hostname;
689         return &he;
690 }
691
692
693
694 /* init a dest_info structure */
695 #define init_dest_info(dst) \
696         do{ \
697                 memset((dst), 0, sizeof(struct dest_info)); \
698         } while(0) 
699
700
701
702 /* init a dest_info structure from a recv_info structure */
703 inline static void init_dst_from_rcv(struct dest_info* dst,
704                                                                         struct receive_info* rcv)
705 {
706                 dst->send_sock=rcv->bind_address;
707                 dst->to=rcv->src_su;
708                 dst->id=rcv->proto_reserved1;
709                 dst->proto=rcv->proto;
710 #ifdef USE_COMP
711                 dst->comp=rcv->comp;
712 #endif
713 }
714
715
716 #endif