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