Changeset 1612 for pjproject/trunk


Ignore:
Timestamp:
Dec 3, 2007 4:03:17 AM (17 years ago)
Author:
bennylp
Message:

Fixed IP interface enumeration Linux to work with IPv6 (see ticket #415)

Location:
pjproject/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/aconfigure

    r1585 r1612  
    58405840  cat >>confdefs.h <<\_ACEOF 
    58415841#define PJ_HAS_NET_IF_H 1 
     5842_ACEOF 
     5843 
     5844fi 
     5845 
     5846 
     5847if test "${ac_cv_header_ifaddrs_h+set}" = set; then 
     5848  echo "$as_me:$LINENO: checking for ifaddrs.h" >&5 
     5849echo $ECHO_N "checking for ifaddrs.h... $ECHO_C" >&6 
     5850if test "${ac_cv_header_ifaddrs_h+set}" = set; then 
     5851  echo $ECHO_N "(cached) $ECHO_C" >&6 
     5852fi 
     5853echo "$as_me:$LINENO: result: $ac_cv_header_ifaddrs_h" >&5 
     5854echo "${ECHO_T}$ac_cv_header_ifaddrs_h" >&6 
     5855else 
     5856  # Is the header compilable? 
     5857echo "$as_me:$LINENO: checking ifaddrs.h usability" >&5 
     5858echo $ECHO_N "checking ifaddrs.h usability... $ECHO_C" >&6 
     5859cat >conftest.$ac_ext <<_ACEOF 
     5860/* confdefs.h.  */ 
     5861_ACEOF 
     5862cat confdefs.h >>conftest.$ac_ext 
     5863cat >>conftest.$ac_ext <<_ACEOF 
     5864/* end confdefs.h.  */ 
     5865$ac_includes_default 
     5866#include <ifaddrs.h> 
     5867_ACEOF 
     5868rm -f conftest.$ac_objext 
     5869if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 
     5870  (eval $ac_compile) 2>conftest.er1 
     5871  ac_status=$? 
     5872  grep -v '^ *+' conftest.er1 >conftest.err 
     5873  rm -f conftest.er1 
     5874  cat conftest.err >&5 
     5875  echo "$as_me:$LINENO: \$? = $ac_status" >&5 
     5876  (exit $ac_status); } && 
     5877         { ac_try='test -z "$ac_c_werror_flag" 
     5878                         || test ! -s conftest.err' 
     5879  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 
     5880  (eval $ac_try) 2>&5 
     5881  ac_status=$? 
     5882  echo "$as_me:$LINENO: \$? = $ac_status" >&5 
     5883  (exit $ac_status); }; } && 
     5884         { ac_try='test -s conftest.$ac_objext' 
     5885  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 
     5886  (eval $ac_try) 2>&5 
     5887  ac_status=$? 
     5888  echo "$as_me:$LINENO: \$? = $ac_status" >&5 
     5889  (exit $ac_status); }; }; then 
     5890  ac_header_compiler=yes 
     5891else 
     5892  echo "$as_me: failed program was:" >&5 
     5893sed 's/^/| /' conftest.$ac_ext >&5 
     5894 
     5895ac_header_compiler=no 
     5896fi 
     5897rm -f conftest.err conftest.$ac_objext conftest.$ac_ext 
     5898echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 
     5899echo "${ECHO_T}$ac_header_compiler" >&6 
     5900 
     5901# Is the header present? 
     5902echo "$as_me:$LINENO: checking ifaddrs.h presence" >&5 
     5903echo $ECHO_N "checking ifaddrs.h presence... $ECHO_C" >&6 
     5904cat >conftest.$ac_ext <<_ACEOF 
     5905/* confdefs.h.  */ 
     5906_ACEOF 
     5907cat confdefs.h >>conftest.$ac_ext 
     5908cat >>conftest.$ac_ext <<_ACEOF 
     5909/* end confdefs.h.  */ 
     5910#include <ifaddrs.h> 
     5911_ACEOF 
     5912if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 
     5913  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 
     5914  ac_status=$? 
     5915  grep -v '^ *+' conftest.er1 >conftest.err 
     5916  rm -f conftest.er1 
     5917  cat conftest.err >&5 
     5918  echo "$as_me:$LINENO: \$? = $ac_status" >&5 
     5919  (exit $ac_status); } >/dev/null; then 
     5920  if test -s conftest.err; then 
     5921    ac_cpp_err=$ac_c_preproc_warn_flag 
     5922    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag 
     5923  else 
     5924    ac_cpp_err= 
     5925  fi 
     5926else 
     5927  ac_cpp_err=yes 
     5928fi 
     5929if test -z "$ac_cpp_err"; then 
     5930  ac_header_preproc=yes 
     5931else 
     5932  echo "$as_me: failed program was:" >&5 
     5933sed 's/^/| /' conftest.$ac_ext >&5 
     5934 
     5935  ac_header_preproc=no 
     5936fi 
     5937rm -f conftest.err conftest.$ac_ext 
     5938echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 
     5939echo "${ECHO_T}$ac_header_preproc" >&6 
     5940 
     5941# So?  What about this header? 
     5942case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in 
     5943  yes:no: ) 
     5944    { echo "$as_me:$LINENO: WARNING: ifaddrs.h: accepted by the compiler, rejected by the preprocessor!" >&5 
     5945echo "$as_me: WARNING: ifaddrs.h: accepted by the compiler, rejected by the preprocessor!" >&2;} 
     5946    { echo "$as_me:$LINENO: WARNING: ifaddrs.h: proceeding with the compiler's result" >&5 
     5947echo "$as_me: WARNING: ifaddrs.h: proceeding with the compiler's result" >&2;} 
     5948    ac_header_preproc=yes 
     5949    ;; 
     5950  no:yes:* ) 
     5951    { echo "$as_me:$LINENO: WARNING: ifaddrs.h: present but cannot be compiled" >&5 
     5952echo "$as_me: WARNING: ifaddrs.h: present but cannot be compiled" >&2;} 
     5953    { echo "$as_me:$LINENO: WARNING: ifaddrs.h:     check for missing prerequisite headers?" >&5 
     5954echo "$as_me: WARNING: ifaddrs.h:     check for missing prerequisite headers?" >&2;} 
     5955    { echo "$as_me:$LINENO: WARNING: ifaddrs.h: see the Autoconf documentation" >&5 
     5956echo "$as_me: WARNING: ifaddrs.h: see the Autoconf documentation" >&2;} 
     5957    { echo "$as_me:$LINENO: WARNING: ifaddrs.h:     section \"Present But Cannot Be Compiled\"" >&5 
     5958echo "$as_me: WARNING: ifaddrs.h:     section \"Present But Cannot Be Compiled\"" >&2;} 
     5959    { echo "$as_me:$LINENO: WARNING: ifaddrs.h: proceeding with the preprocessor's result" >&5 
     5960echo "$as_me: WARNING: ifaddrs.h: proceeding with the preprocessor's result" >&2;} 
     5961    { echo "$as_me:$LINENO: WARNING: ifaddrs.h: in the future, the compiler will take precedence" >&5 
     5962echo "$as_me: WARNING: ifaddrs.h: in the future, the compiler will take precedence" >&2;} 
     5963    ( 
     5964      cat <<\_ASBOX 
     5965## ------------------------------------ ## 
     5966## Report this to the pjproject lists.  ## 
     5967## ------------------------------------ ## 
     5968_ASBOX 
     5969    ) | 
     5970      sed "s/^/$as_me: WARNING:     /" >&2 
     5971    ;; 
     5972esac 
     5973echo "$as_me:$LINENO: checking for ifaddrs.h" >&5 
     5974echo $ECHO_N "checking for ifaddrs.h... $ECHO_C" >&6 
     5975if test "${ac_cv_header_ifaddrs_h+set}" = set; then 
     5976  echo $ECHO_N "(cached) $ECHO_C" >&6 
     5977else 
     5978  ac_cv_header_ifaddrs_h=$ac_header_preproc 
     5979fi 
     5980echo "$as_me:$LINENO: result: $ac_cv_header_ifaddrs_h" >&5 
     5981echo "${ECHO_T}$ac_cv_header_ifaddrs_h" >&6 
     5982 
     5983fi 
     5984if test $ac_cv_header_ifaddrs_h = yes; then 
     5985  cat >>confdefs.h <<\_ACEOF 
     5986#define PJ_HAS_IFADDRS_H 1 
    58425987_ACEOF 
    58435988 
  • pjproject/trunk/aconfigure.ac

    r1585 r1612  
    145145AC_CHECK_HEADER(netinet/ip.h,[AC_DEFINE(PJ_HAS_NETINET_IP_H,1)]) 
    146146AC_CHECK_HEADER(net/if.h,[AC_DEFINE(PJ_HAS_NET_IF_H,1)]) 
     147AC_CHECK_HEADER(ifaddrs.h,[AC_DEFINE(PJ_HAS_IFADDRS_H,1)]) 
    147148AC_CHECK_HEADER(setjmp.h,[AC_DEFINE(PJ_HAS_SETJMP_H,1)]) 
    148149AC_CHECK_HEADER(stdarg.h,[AC_DEFINE(PJ_HAS_STDARG_H,1)]) 
  • pjproject/trunk/pjlib/include/pj/compat/os_auto.h.in

    r1585 r1612  
    5353#undef PJ_HAS_NETINET_IP_H 
    5454#undef PJ_HAS_NET_IF_H 
     55#undef PJ_HAS_IFADDRS_H 
    5556#undef PJ_HAS_SETJMP_H 
    5657#undef PJ_HAS_STDARG_H 
  • pjproject/trunk/pjlib/include/pj/compat/socket.h

    r1611 r1612  
    100100/* For interface enumeration in ip_helper */ 
    101101#   include <net/if.h> 
     102#endif 
     103 
     104#if defined(PJ_HAS_IFADDRS_H) && PJ_HAS_IFADDRS_H != 0 
     105/* Interface enum with getifaddrs() which works with IPv6 */ 
     106#   include <ifaddrs.h> 
    102107#endif 
    103108 
  • pjproject/trunk/pjlib/src/pj/ip_helper_generic.c

    r1611 r1612  
    2323#include <pj/string.h> 
    2424#include <pj/compat/socket.h> 
    25  
    26 static pj_status_t dummy_enum_ip_interface(int af, 
    27                                            unsigned *p_cnt, 
    28                                            pj_sockaddr ifs[]) 
    29 { 
    30     pj_status_t status; 
    31  
    32     PJ_ASSERT_RETURN(p_cnt && *p_cnt > 0 && ifs, PJ_EINVAL); 
    33  
    34     pj_bzero(ifs, sizeof(ifs[0]) * (*p_cnt)); 
    35  
    36     /* Just get one default route */ 
    37     status = pj_getdefaultipinterface(af, &ifs[0]); 
    38     if (status != PJ_SUCCESS) 
    39         return status; 
    40  
    41     *p_cnt = 1; 
    42     return PJ_SUCCESS; 
    43 } 
    44  
    45 #ifdef SIOCGIFCONF 
    46 static pj_status_t sock_enum_ip_interface(int af, 
    47                                           unsigned *p_cnt, 
    48                                           pj_sockaddr ifs[]) 
     25#include <pj/sock.h> 
     26 
     27/* Set to 1 to enable tracing */ 
     28#if 0 
     29#   include <pj/log.h> 
     30#   define THIS_FILE    "ip_helper_generic.c" 
     31#   define TRACE_(exp)  PJ_LOG(5,exp) 
     32    static const char *get_os_errmsg(void) 
     33    { 
     34        static char errmsg[PJ_ERR_MSG_SIZE]; 
     35        pj_strerror(pj_get_os_error(), errmsg, sizeof(errmsg)); 
     36        return errmsg; 
     37    } 
     38    static const char *get_addr(void *addr) 
     39    { 
     40        static char txt[PJ_INET6_ADDRSTRLEN]; 
     41        struct sockaddr *ad = (struct sockaddr*)addr; 
     42        if (ad->sa_family != PJ_AF_INET && ad->sa_family != PJ_AF_INET6) 
     43            return "?"; 
     44        return pj_inet_ntop2(ad->sa_family, pj_sockaddr_get_addr(ad),  
     45                             txt, sizeof(txt)); 
     46    } 
     47#else 
     48#   define TRACE_(exp) 
     49#endif 
     50 
     51 
     52#if 0 
     53    /* dummy */ 
     54 
     55#elif defined(PJ_HAS_IFADDRS_H) && PJ_HAS_IFADDRS_H != 0 
     56/* Using getifaddrs() is preferred since it can work with both IPv4 and IPv6 */ 
     57static pj_status_t if_enum_by_af(int af, 
     58                                 unsigned *p_cnt, 
     59                                 pj_sockaddr ifs[]) 
     60{ 
     61    struct ifaddrs *ifap = NULL, *it; 
     62    unsigned max; 
     63 
     64    PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EINVAL); 
     65     
     66    TRACE_((THIS_FILE, "Starting interface enum with getifaddrs() for af=%d", 
     67            af)); 
     68 
     69    if (getifaddrs(&ifap) != 0) { 
     70        TRACE_((THIS_FILE, " getifarrds() failed: %s", get_os_errmsg())); 
     71        return PJ_RETURN_OS_ERROR(pj_get_netos_error()); 
     72    } 
     73 
     74    it = ifap; 
     75    max = *p_cnt; 
     76    *p_cnt = 0; 
     77    for (; it!=NULL && *p_cnt < max; it = it->ifa_next) { 
     78        struct sockaddr *ad = it->ifa_addr; 
     79 
     80        TRACE_((THIS_FILE, " checking %s", it->ifa_name)); 
     81 
     82        if ((it->ifa_flags & IFF_UP)==0) { 
     83            TRACE_((THIS_FILE, "  interface is down")); 
     84            continue; /* Skip when interface is down */ 
     85        } 
     86 
     87        if (it->ifa_flags & IFF_LOOPBACK) { 
     88            TRACE_((THIS_FILE, "  loopback interface")); 
     89            continue; /* Skip loopback interface */ 
     90        } 
     91 
     92        if (ad->sa_family != af) { 
     93            TRACE_((THIS_FILE, "  address %s ignored (af=%d)",  
     94                    get_addr(ad), ad->sa_family)); 
     95            continue; /* Skip when interface is down */ 
     96        } 
     97 
     98        TRACE_((THIS_FILE, "  address %s (af=%d) added at index %d",  
     99                get_addr(ad), ad->sa_family, *p_cnt)); 
     100 
     101        pj_bzero(&ifs[*p_cnt], sizeof(ifs[0])); 
     102        pj_memcpy(&ifs[*p_cnt], ad, pj_sockaddr_get_len(ad)); 
     103        (*p_cnt)++; 
     104    } 
     105 
     106    freeifaddrs(ifap); 
     107    TRACE_((THIS_FILE, "done, found %d address(es)", *p_cnt)); 
     108    return (*p_cnt != 0) ? PJ_SUCCESS : PJ_ENOTFOUND; 
     109} 
     110 
     111#elif defined(SIOCGIFCONF) 
     112/* Note: this does not work with IPv6 */ 
     113static pj_status_t if_enum_by_af(int af, 
     114                                 unsigned *p_cnt, 
     115                                 pj_sockaddr ifs[]) 
    49116{ 
    50117    pj_sock_t sock; 
     
    57124    PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EINVAL); 
    58125     
     126    TRACE_((THIS_FILE, "Starting interface enum with SIOCGIFCONF for af=%d", 
     127            af)); 
     128 
    59129    status = pj_sock_socket(af, PJ_SOCK_DGRAM, 0, &sock); 
    60130    if (status != PJ_SUCCESS) 
     
    67137    if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { 
    68138        int oserr = pj_get_netos_error(); 
     139        TRACE_((THIS_FILE, " ioctl(SIOCGIFCONF) failed: %s", get_os_errmsg())); 
    69140        pj_sock_close(sock); 
    70141        return PJ_RETURN_OS_ERROR(oserr); 
     
    79150    if (count > *p_cnt) 
    80151        count = *p_cnt; 
    81     else 
    82         *p_cnt = count; 
     152 
     153    *p_cnt = 0; 
    83154    for (i=0; i<count; ++i) { 
    84155        struct ifreq *itf = &ifr[i]; 
    85156        struct sockaddr *ad = &itf->ifr_addr; 
    86157         
    87         ifs[i].addr.sa_family = ad->sa_family; 
    88         pj_memcpy(pj_sockaddr_get_addr(&ifs[i]), 
    89                   pj_sockaddr_get_addr(ad), 
    90                   pj_sockaddr_get_addr_len(ad)); 
    91     } 
    92  
     158        TRACE_((THIS_FILE, " checking interface %s", itf->ifr_name)); 
     159 
     160        /* Skip address with different family */ 
     161        if (ad->sa_family != af) { 
     162            TRACE_((THIS_FILE, "  address %s (af=%d) ignored", 
     163                    get_addr(ad), (int)ad->sa_family)); 
     164            continue; 
     165        } 
     166 
     167        if ((itf->ifr_flags & IFF_UP)==0) { 
     168            TRACE_((THIS_FILE, "  interface is down")); 
     169            continue; /* Skip when interface is down */ 
     170        } 
     171 
     172        if (itf->ifr_flags & IFF_LOOPBACK) { 
     173            TRACE_((THIS_FILE, "  loopback interface")); 
     174            continue; /* Skip loopback interface */ 
     175        } 
     176 
     177        TRACE_((THIS_FILE, "  address %s (af=%d) added at index %d",  
     178                get_addr(ad), ad->sa_family, *p_cnt)); 
     179 
     180        pj_bzero(&ifs[*p_cnt], sizeof(ifs[0])); 
     181        pj_memcpy(&ifs[*p_cnt], ad, pj_sockaddr_get_len(ad)); 
     182        (*p_cnt)++; 
     183    } 
     184 
     185    TRACE_((THIS_FILE, "done, found %d address(es)", *p_cnt)); 
     186    return (*p_cnt != 0) ? PJ_SUCCESS : PJ_ENOTFOUND; 
     187} 
     188 
     189#elif defined(PJ_HAS_NET_IF_H) && PJ_HAS_NET_IF_H != 0 
     190/* Note: this does not work with IPv6 */ 
     191static pj_status_t if_enum_by_af(int af, unsigned *p_cnt, pj_sockaddr ifs[]) 
     192{ 
     193    struct if_nameindex *if_list; 
     194    struct ifreq ifreq; 
     195    pj_sock_t sock; 
     196    unsigned i, max_count; 
     197    pj_status_t status; 
     198 
     199    PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EINVAL); 
     200 
     201    TRACE_((THIS_FILE, "Starting if_nameindex() for af=%d", af)); 
     202 
     203    status = pj_sock_socket(af, PJ_SOCK_DGRAM, 0, &sock); 
     204    if (status != PJ_SUCCESS) 
     205        return status; 
     206 
     207    if_list = if_nameindex(); 
     208    if (if_list == NULL) 
     209        return PJ_ENOTFOUND; 
     210 
     211    max_count = *p_cnt; 
     212    *p_cnt = 0; 
     213    for (i=0; if_list[i].if_index && *p_cnt<max_count; ++i) { 
     214        int rc; 
     215 
     216        strncpy(ifreq.ifr_name, if_list[i].if_name, IFNAMSIZ); 
     217 
     218        TRACE_((THIS_FILE, " checking interface %s", ifreq.ifr_name)); 
     219 
     220        if ((rc=ioctl(sock, SIOCGIFFLAGS, &ifreq)) != 0) { 
     221            TRACE_((THIS_FILE, "  ioctl(SIOCGIFFLAGS) failed: %s", 
     222                    get_os_errmsg())); 
     223            continue;   /* Failed to get flags, continue */ 
     224        } 
     225 
     226        if ((ifreq.ifr_flags & IFF_UP)==0) { 
     227            TRACE_((THIS_FILE, "  interface is down")); 
     228            continue; /* Skip when interface is down */ 
     229        } 
     230 
     231        if (ifreq.ifr_flags & IFF_LOOPBACK) { 
     232            TRACE_((THIS_FILE, "  loopback interface")); 
     233            continue; /* Skip loopback interface */ 
     234        } 
     235 
     236        /* Note: SIOCGIFADDR does not work for IPv6! */ 
     237        if ((rc=ioctl(sock, SIOCGIFADDR, &ifreq)) != 0) { 
     238            TRACE_((THIS_FILE, "  ioctl(SIOCGIFADDR) failed: %s", 
     239                    get_os_errmsg())); 
     240            continue;   /* Failed to get address, continue */ 
     241        } 
     242 
     243        if (ifreq.ifr_addr.sa_family != af) { 
     244            TRACE_((THIS_FILE, "  address %s family %d ignored",  
     245                               get_addr(&ifreq.ifr_addr), 
     246                               ifreq.ifr_addr.sa_family)); 
     247            continue;   /* Not address family that we want, continue */ 
     248        } 
     249 
     250        /* Got an address ! */ 
     251        TRACE_((THIS_FILE, "  address %s (af=%d) added at index %d",  
     252                get_addr(&ifreq.ifr_addr), ifreq.ifr_addr.sa_family, *p_cnt)); 
     253 
     254        pj_bzero(&ifs[*p_cnt], sizeof(ifs[0])); 
     255        pj_memcpy(&ifs[*p_cnt], &ifreq.ifr_addr,  
     256                  pj_sockaddr_get_len(&ifreq.ifr_addr)); 
     257        (*p_cnt)++; 
     258    } 
     259 
     260    if_freenameindex(if_list); 
     261    pj_sock_close(sock); 
     262 
     263    TRACE_((THIS_FILE, "done, found %d address(es)", *p_cnt)); 
     264    return (*p_cnt != 0) ? PJ_SUCCESS : PJ_ENOTFOUND; 
     265} 
     266 
     267#else 
     268static pj_status_t if_enum_by_af(int af, 
     269                                 unsigned *p_cnt, 
     270                                 pj_sockaddr ifs[]) 
     271{ 
     272    pj_status_t status; 
     273 
     274    PJ_ASSERT_RETURN(p_cnt && *p_cnt > 0 && ifs, PJ_EINVAL); 
     275 
     276    PJ_UNUSED_ARG(&get_addr); 
     277    PJ_UNUSED_ARG(&get_os_errmsg); 
     278 
     279    pj_bzero(ifs, sizeof(ifs[0]) * (*p_cnt)); 
     280 
     281    /* Just get one default route */ 
     282    status = pj_getdefaultipinterface(af, &ifs[0]); 
     283    if (status != PJ_SUCCESS) 
     284        return status; 
     285 
     286    *p_cnt = 1; 
    93287    return PJ_SUCCESS; 
    94288} 
     
    102296                                         pj_sockaddr ifs[]) 
    103297{ 
    104 #ifdef SIOCGIFCONF 
    105     if (sock_enum_ip_interface(af, p_cnt, ifs) == PJ_SUCCESS) 
    106         return PJ_SUCCESS; 
    107 #endif 
    108     return dummy_enum_ip_interface(af, p_cnt, ifs); 
     298    unsigned start; 
     299    pj_status_t status; 
     300 
     301    start = 0; 
     302    if (af==PJ_AF_INET6 || af==PJ_AF_UNSPEC) { 
     303        unsigned max = *p_cnt; 
     304        status = if_enum_by_af(PJ_AF_INET6, &max, &ifs[start]); 
     305        if (status == PJ_SUCCESS) { 
     306            start += max; 
     307            (*p_cnt) -= max; 
     308        } 
     309    } 
     310 
     311    if (af==PJ_AF_INET || af==PJ_AF_UNSPEC) { 
     312        unsigned max = *p_cnt; 
     313        status = if_enum_by_af(PJ_AF_INET, &max, &ifs[start]); 
     314        if (status == PJ_SUCCESS) { 
     315            start += max; 
     316            (*p_cnt) -= max; 
     317        } 
     318    } 
     319 
     320    *p_cnt = start; 
     321 
     322    return (*p_cnt != 0) ? PJ_SUCCESS : PJ_ENOTFOUND; 
    109323} 
    110324 
Note: See TracChangeset for help on using the changeset viewer.