Navigation


Changeset 220:5f2ce627db3c in freeDiameter


Ignore:
Timestamp:
Feb 19, 2010, 6:09:43 PM (14 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Try to fix the old bug on sctp_getpaddrs

Location:
freeDiameter
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • freeDiameter/cnxctx.c

    r214 r220  
    122122        if (sa->sa_family == AF_INET) {
    123123                ((sSA4 *)sa)->sin_port = htons(port);
     124                cnx->cc_family = AF_INET;
    124125        } else {
    125126                ((sSA6 *)sa)->sin6_port = htons(port);
     127                cnx->cc_family = AF_INET6;
    126128        }
    127129
     
    167169        CHECK_MALLOC_DO( cnx = fd_cnx_init(0), return NULL );
    168170
     171        if (fd_g_config->cnf_flags.no_ip6) {
     172                cnx->cc_family = AF_INET;
     173        } else {
     174                cnx->cc_family = AF_INET6; /* can create socket for both IP and IPv6 */
     175        }
     176       
    169177        /* Create the socket */
    170         CHECK_FCT_DO( fd_sctp_create_bind_server( &cnx->cc_socket, ep_list, port ), goto error );
     178        CHECK_FCT_DO( fd_sctp_create_bind_server( &cnx->cc_socket, cnx->cc_family, ep_list, port ), goto error );
    171179
    172180        /* Generate the name for the connection object */
     
    229237        CHECK_MALLOC_DO( cli = fd_cnx_init(1), { shutdown(cli_sock, SHUT_RDWR); close(cli_sock); return NULL; } );
    230238        cli->cc_socket = cli_sock;
     239        cli->cc_family = serv->cc_family;
    231240        cli->cc_proto = serv->cc_proto;
    232241       
     
    297306       
    298307        cnx->cc_socket = sock;
     308        cnx->cc_family = sa->sa_family;
    299309        cnx->cc_proto  = IPPROTO_TCP;
    300310       
     
    347357       
    348358        cnx->cc_socket = sock;
     359        cnx->cc_family = no_ip6 ? AF_INET : AF_INET6;
    349360        cnx->cc_proto  = IPPROTO_SCTP;
    350361       
  • freeDiameter/cnxctx.h

    r209 r220  
    4646        int             cc_socket;      /* The socket object of the connection -- <=0 if no socket is created */
    4747
     48        int             cc_family;      /* AF_INET or AF_INET6 (mixed) */
    4849        int             cc_proto;       /* IPPROTO_TCP or IPPROTO_SCTP */
    4950        uint32_t        cc_status;      /* True if the object is being destroyed: we don't send events anymore */
     
    102103#ifndef DISABLE_SCTP
    103104/* SCTP */
    104 int fd_sctp_create_bind_server( int * sock, struct fd_list * list, uint16_t port );
     105int fd_sctp_create_bind_server( int * sock, int family, struct fd_list * list, uint16_t port );
    105106int fd_sctp_listen( int sock );
    106107int fd_sctp_client( int *sock, int no_ip6, uint16_t port, struct fd_list * list );
    107 int fd_sctp_get_local_ep(int sock, struct fd_list * list);
     108int fd_sctp_get_local_ep(int sock,  struct fd_list * list);
    108109int fd_sctp_get_remote_ep(int sock, struct fd_list * list);
    109110int fd_sctp_get_str_info( int sock, uint16_t *in, uint16_t *out, sSS *primary );
  • freeDiameter/sctp.c

    r209 r220  
    586586}
    587587
     588/* Add addresses from a list to an array, with filter on the flags */
     589static int add_addresses_from_list_mask(uint8_t ** array, size_t * size, int * addr_count, int target_family, uint16_t port, struct fd_list * list, uint32_t mask, uint32_t val)
     590{
     591        struct fd_list * li;
     592        int to_add4 = 0;
     593        int to_add6 = 0;
     594        union {
     595                uint8_t *buf;
     596                sSA4    *sin;
     597                sSA6    *sin6;
     598        } ptr;
     599        size_t sz;
     600       
     601        /* First, count the number of addresses to add */
     602        for (li = list->next; li != list; li = li->next) {
     603                struct fd_endpoint * ep = (struct fd_endpoint *) li;
     604               
     605                /* Do the flag match ? */
     606                if ((val & mask) != (ep->flags & mask))
     607                        continue;
     608               
     609                if (ep->sa.sa_family == AF_INET) {
     610                        to_add4 ++;
     611                } else {
     612                        to_add6 ++;
     613                }
     614        }
     615       
     616        if ((to_add4 + to_add6) == 0)
     617                return 0; /* nothing to do */
     618       
     619        /* The size to add */
     620        if (target_family == AF_INET) {
     621                sz = to_add4 * sizeof(sSA4);
     622        } else {
     623                #ifndef SCTP_USE_MAPPED_ADDRESSES
     624                        sz = (to_add4 * sizeof(sSA4)) + (to_add6 * sizeof(sSA6));
     625                #else /* SCTP_USE_MAPPED_ADDRESSES */
     626                        sz = (to_add4 + to_add6) * sizeof(sSA6);
     627                #endif /* SCTP_USE_MAPPED_ADDRESSES */
     628        }
     629       
     630        /* Now, (re)alloc the array to store the new addresses */
     631        CHECK_MALLOC( *array = realloc(*array, *size + sz) );
     632       
     633        /* Finally, add the addresses */
     634        for (li = list->next; li != list; li = li->next) {
     635                struct fd_endpoint * ep = (struct fd_endpoint *) li;
     636               
     637                /* Skip v6 addresses for v4 socket */
     638                if ((target_family == AF_INET) && (ep->sa.sa_family == AF_INET6))
     639                        continue;
     640               
     641                /* Are the flags matching ? */
     642                if ((val & mask) != (ep->flags & mask))
     643                        continue;
     644               
     645                /* Size of the new SA we are adding (array may contain a mix of sockaddr_in and sockaddr_in6) */
     646                #ifndef SCTP_USE_MAPPED_ADDRESSES
     647                if (ep->sa.sa_family == AF_INET6)
     648                #else /* SCTP_USE_MAPPED_ADDRESSES */
     649                if (target_family == AF_INET6) {
     650                #endif /* SCTP_USE_MAPPED_ADDRESSES */
     651                        sz = sizeof(sSA6);
     652                else
     653                        sz = sizeof(sSA4);
     654               
     655                /* Place where we add the new address */
     656                ptr.buf = *array + *size; /* place of the new SA */
     657               
     658                /* Update other information */
     659                *size += sz;
     660                *addr_count += 1;
     661               
     662                /* And write the addr in the buffer */
     663                if (sz == sizeof(sSA4)) {
     664                        memcpy(ptr.buf, &ep->sin, sz);
     665                        ptr.sin->sin_port = port;
     666                } else {
     667                        if (ep->sa.sa_family == AF_INET) { /* We must map the address */
     668                                memset(ptr.buf, 0, sz);
     669                                ptr.sin6->sin6_family = AF_INET6;
     670                                IN6_ADDR_V4MAP( &ptr.sin6->sin6_addr.s6_addr, ep->sin.sin_addr.s_addr );
     671                        } else {
     672                                memcpy(ptr.sin6, &ep->sin6, sz);
     673                        }
     674                        ptr.sin6->sin6_port = port;
     675                }
     676        }
     677       
     678        return 0;
     679}
     680
    588681/* Create a socket server and bind it according to daemon s configuration */
    589 int fd_sctp_create_bind_server( int * sock, struct fd_list * list, uint16_t port )
     682int fd_sctp_create_bind_server( int * sock, int family, struct fd_list * list, uint16_t port )
    590683{
    591         int family;
    592684        int bind_default;
    593685       
    594         TRACE_ENTRY("%p %p %hu", sock, list, port);
     686        TRACE_ENTRY("%p %i %p %hu", sock, family, list, port);
    595687        CHECK_PARAMS(sock);
    596        
    597         if (fd_g_config->cnf_flags.no_ip6) {
    598                 family = AF_INET;
    599         } else {
    600                 family = AF_INET6; /* can create socket for both IP and IPv6 */
    601         }
    602688       
    603689        /* Create the socket */
     
    633719                /* Explicit endpoints to bind to from config */
    634720               
    635                 union {
    636                         sSA     * sa;
    637                         sSA4    *sin;
    638                         sSA6    *sin6;
    639                         uint8_t *buf;
    640                 } ptr;
    641                 union {
    642                         sSA     * sa;
    643                         uint8_t * buf;
    644                 } sar;
    645                 int count = 0; /* number of sock addr in sar array */
    646                 size_t offset = 0;
    647                 struct fd_list * li;
    648                
    649                 sar.buf = NULL;
    650                
    651                 /* Create a flat array from the list of configured addresses */
    652                 for (li = list->next; li != list; li = li->next) {
    653                         struct fd_endpoint * ep = (struct fd_endpoint *)li;
    654                         size_t sz = 0;
    655                        
    656                         if (! (ep->flags & EP_FL_CONF))
    657                                 continue;
    658                        
    659                         count++;
    660                        
    661                         /* Size of the new SA we are adding (sar may contain a mix of sockaddr_in and sockaddr_in6) */
    662 #ifndef SCTP_USE_MAPPED_ADDRESSES
    663                         if (ep->sa.sa_family == AF_INET6)
    664 #else /* SCTP_USE_MAPPED_ADDRESSES */
    665                         if (family == AF_INET6)
    666 #endif /* SCTP_USE_MAPPED_ADDRESSES */
    667                                 sz = sizeof(sSA6);
    668                         else
    669                                 sz = sizeof(sSA4);
    670                        
    671                         /* augment sar to contain the additional info */
    672                         CHECK_MALLOC( sar.buf = realloc(sar.buf, offset + sz)  );
    673                        
    674                         ptr.buf = sar.buf + offset; /* place of the new SA */
    675                         offset += sz; /* update to end of sar */
    676                        
    677                         if (sz == sizeof(sSA4)) {
    678                                 memcpy(ptr.buf, &ep->sin, sz);
    679                                 ptr.sin->sin_port = htons(port);
    680                         } else {
    681                                 if (ep->sa.sa_family == AF_INET) { /* We must map the address */
    682                                         memset(ptr.buf, 0, sz);
    683                                         ptr.sin6->sin6_family = AF_INET6;
    684                                         IN6_ADDR_V4MAP( &ptr.sin6->sin6_addr.s6_addr, ep->sin.sin_addr.s_addr );
    685                                 } else {
    686                                         memcpy(ptr.sin6, &ep->sin6, sz);
    687                                 }
    688                                 ptr.sin6->sin6_port = htons(port);
    689                         }
    690                 }
     721                sSA * sar = NULL; /* array of addresses */
     722                size_t sz = 0; /* size of the array */
     723                int count = 0; /* number of sock addr in the array */
     724               
     725                /* Create the array of configured addresses */
     726                CHECK_FCT( add_addresses_from_list_mask((void *)&sar, &sz, &count, family, port, list, EP_FL_CONF, EP_FL_CONF) );
    691727               
    692728                if (!count) {
     
    697733               
    698734                if (TRACE_BOOL(SCTP_LEVEL)) {
     735                        union {
     736                                sSA     *sa;
     737                                uint8_t *buf;
     738                        } ptr;
    699739                        int i;
    700                         ptr.buf = sar.buf;
     740                        ptr.sa = sar;
    701741                        fd_log_debug("Calling sctp_bindx with the following address array:\n");
    702742                        for (i = 0; i < count; i++) {
     
    707747               
    708748                /* Bind to this array */
    709                 CHECK_SYS(  sctp_bindx(*sock, sar.sa, count, SCTP_BINDX_ADD_ADDR)  );
     749                CHECK_SYS(  sctp_bindx(*sock, sar, count, SCTP_BINDX_ADD_ADDR)  );
    710750               
    711751                /* We don't need sar anymore */
    712                 free(sar.buf);
     752                free(sar);
    713753        }
    714754       
     
    745785}
    746786
    747 /* Add addresses from the list that match the flags to the array */
    748 static int add_addresses_from_list_mask(uint8_t ** array, int * count, size_t * offset, uint16_t port, struct fd_list * list, uint32_t mask, uint32_t val)
    749 {
    750         size_t sz;
    751         struct fd_list * li;
    752         union {
    753                 uint8_t *buf;
    754                 sSA4    *sin;
    755                 sSA6    *sin6;
    756         } ptr;
    757        
    758         for (li = list->next; li != list; li = li->next) {
    759                 struct fd_endpoint * ep = (struct fd_endpoint *) li;
    760                
    761                 /* Do the flag match ? */
    762                 if ((val & mask) != (ep->flags & mask))
    763                         continue;
    764                
    765                 /* We add this endpoint at the end of array */
    766                 (*count)++;
    767                
    768                 /* Size of the new SA we are adding (array may contain a mix of sockaddr_in and sockaddr_in6) */
    769 #ifndef SCTP_USE_MAPPED_ADDRESSES
    770                 if (ep->sa.sa_family == AF_INET6)
    771 #else /* SCTP_USE_MAPPED_ADDRESSES */
    772                 if (family == AF_INET6)
    773 #endif /* SCTP_USE_MAPPED_ADDRESSES */
    774                         sz = sizeof(sSA6);
    775                 else
    776                         sz = sizeof(sSA4);
    777                
    778                 /* augment array to contain the additional info */
    779                 CHECK_MALLOC( *array = realloc(*array, (*offset) + sz) );
    780 
    781                 ptr.buf = *array + *offset; /* place of the new SA */
    782                 (*offset) += sz; /* update to end of sar */
    783                        
    784                 if (sz == sizeof(sSA4)) {
    785                         memcpy(ptr.buf, &ep->sin, sz);
    786                         ptr.sin->sin_port = port;
    787                 } else {
    788                         if (ep->sa.sa_family == AF_INET) { /* We must map the address */
    789                                 memset(ptr.buf, 0, sz);
    790                                 ptr.sin6->sin6_family = AF_INET6;
    791                                 IN6_ADDR_V4MAP( &ptr.sin6->sin6_addr.s6_addr, ep->sin.sin_addr.s_addr );
    792                         } else {
    793                                 memcpy(ptr.sin6, &ep->sin6, sz);
    794                         }
    795                         ptr.sin6->sin6_port = port;
    796                 }
    797         }
    798        
    799         return 0;
    800 }
    801 
    802787/* Create a client socket and connect to remote server */
    803788int fd_sctp_client( int *sock, int no_ip6, uint16_t port, struct fd_list * list )
    804789{
    805790        int family;
    806         int count = 0;
    807         size_t offset = 0;
    808791        union {
    809792                uint8_t *buf;
    810793                sSA     *sa;
    811794        } sar;
     795        size_t size = 0;
     796        int count = 0;
    812797        int ret;
    813798       
     
    833818       
    834819        /* Create the array of addresses, add first the configured addresses, then the discovered, then the other ones */
    835         CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &count, &offset, htons(port), list, EP_FL_CONF,              EP_FL_CONF      ), goto fail );
    836         CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &count, &offset, htons(port), list, EP_FL_CONF | EP_FL_DISC, EP_FL_DISC      ), goto fail );
    837         CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &count, &offset, htons(port), list, EP_FL_CONF | EP_FL_DISC, 0               ), goto fail );
     820        CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF,              EP_FL_CONF        ), goto fail );
     821        CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF | EP_FL_DISC, EP_FL_DISC        ), goto fail );
     822        CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF | EP_FL_DISC, 0         ), goto fail );
    838823       
    839824        /* Try connecting */
     
    860845        CHECK_SYS_DO( sctp_connectx(*sock, sar.sa, count), { ret = errno; goto fail; } );
    861846#endif /* SCTP_CONNECTX_4_ARGS */
    862        
    863         /*****************
    864          BUG : received "EINVAL" at reconnection attempt... Should probably filter what is in that list !
    865          *****************/
    866847       
    867848        free(sar.buf); sar.buf = NULL;
     
    937918        } ptr;
    938919       
    939         sSA * data;
     920        sSA * data = NULL;
    940921        int count;
    941922       
     
    954935                        default:
    955936                                TRACE_DEBUG(INFO, "Unkown address family returned in sctp_getladdrs: %d", ptr.sa->sa_family);
     937                                TRACE_DEBUG_BUFFER(NONE, "DEBUG: Parsed data : [", data, ptr.buf - (uint8_t *)data, "]" );
     938                                TRACE_DEBUG(NONE, "DEBUG: Remaining %d addresses to parse in :", count)
     939                                TRACE_DEBUG_BUFFER(NONE, "DEBUG: Unable to parse [", ptr.buf, count * sizeof(sSA), "]" );
     940                                goto stop;
    956941                }
    957942                               
     
    960945                count --;
    961946        }
    962        
     947stop:
    963948        /* Free the list */
    964949        sctp_freeladdrs(data);
     
    994979        ptr.sa = data;
    995980       
    996         TRACE_DEBUG(NONE, "DEBUG: count = %d", count);
    997         TRACE_DEBUG_BUFFER(NONE, "DEBUG: data = ", ptr.buf, count * sizeof(sSA4), "" );
    998        
    999981        while (count) {
    1000982                socklen_t sl;
     
    1004986                        default:
    1005987                                TRACE_DEBUG(INFO, "Unkown address family returned in sctp_getpaddrs: %d, skip", ptr.sa->sa_family);
    1006                                 goto next;
     988                                TRACE_DEBUG_BUFFER(NONE, "DEBUG: Parsed data : [", data, ptr.buf - (uint8_t *)data, "]" );
     989                                TRACE_DEBUG(NONE, "DEBUG: Remaining %d addresses to parse in :", count)
     990                                TRACE_DEBUG_BUFFER(NONE, "DEBUG: Unable to parse [", ptr.buf, count * sizeof(sSA), "]" );
     991                                goto stop;
    1007992                }
    1008993                               
     
    1011996                count --;
    1012997        }
    1013 next:   
     998stop:   
    1014999        /* Free the list */
    10151000        sctp_freepaddrs(data);
Note: See TracChangeset for help on using the changeset viewer.