1dnl RACOON_PATH_LIBS(FUNCTION, LIB, SEARCH-PATHS [, ACTION-IF-FOUND
2dnl            [, ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]])
3dnl Search for a library defining FUNC, if it's not already available.
4
5AC_DEFUN([RACOON_PATH_LIBS],
6[AC_PREREQ([2.13])
7AC_CACHE_CHECK([for $2 containing $1], [ac_cv_search_$1],
8[ac_func_search_save_LIBS="$LIBS"
9ac_cv_search_$1="no"
10AC_TRY_LINK_FUNC([$1], [ac_cv_search_$1="none required"],
11          [LIBS="-l$2 $LIBS"
12          AC_TRY_LINK_FUNC([$1], [ac_cv_search_$1="-l$2"], [])])
13LIBS="$ac_func_search_save_LIBS"
14ifelse("x$3", "x", , [ test "$ac_cv_search_$1" = "no" && for i in $3; do
15  LIBS="-L$i -l$2 $ac_func_search_save_LIBS"
16  AC_TRY_LINK_FUNC([$1],
17  [ac_cv_search_$1="-L$i -l$2"
18  break])
19  done
20LIBS="$ac_func_search_save_LIBS" ]) ])
21if test "$ac_cv_search_$1" != "no"; then
22  test "$ac_cv_search_$1" = "none required" || LIBS="$ac_cv_search_$1 $LIBS"
23  $4
24else :
25  $5
26fi])
27
28dnl  Check if either va_copy() or __va_copy() is available. On linux systems
29dnl  at least one of these should be present.
30AC_DEFUN([RACOON_CHECK_VA_COPY], [
31          saved_CFLAGS=$CFLAGS
32          CFLAGS="-Wall -O2"
33          AC_CACHE_CHECK([for an implementation of va_copy()],
34                    ac_cv_va_copy,[
35                    AC_TRY_RUN([#include <stdarg.h>
36                    void func (int i, ...) {
37                              va_list args1, args2;
38                              va_start (args1, i);
39                              va_copy (args2, args1);
40                              if (va_arg (args1, int) != 1 || va_arg (args2, int) != 1)
41                                        exit (1);
42                              va_end (args1);
43                              va_end (args2);
44                    }
45                    int main() {
46                              func (0, 1);
47                              return 0;
48                    }],
49                    [ac_cv_va_copy=yes],
50                    [ac_cv_va_copy=no],
51                    AC_MSG_WARN(Cross compiling... Unable to test va_copy)
52                    [ac_cv_va_copy=no])
53          ])
54          if test x$ac_cv_va_copy != xyes; then
55                    AC_CACHE_CHECK([for an implementation of __va_copy()],
56                              ac_cv___va_copy,[
57                              AC_TRY_RUN([#include <stdarg.h>
58                              void func (int i, ...) {
59                                        va_list args1, args2;
60                                        va_start (args1, i);
61                                        __va_copy (args2, args1);
62                                        if (va_arg (args1, int) != 1 || va_arg (args2, int) != 1)
63                                                  exit (1);
64                                        va_end (args1);
65                                        va_end (args2);
66                              }
67                              int main() {
68                                        func (0, 1);
69                                        return 0;
70                              }],
71                              [ac_cv___va_copy=yes],
72                              [ac_cv___va_copy=no],
73                              AC_MSG_WARN(Cross compiling... Unable to test __va_copy)
74                              [ac_cv___va_copy=no])
75                    ])
76          fi
77
78          if test "x$ac_cv_va_copy" = "xyes"; then
79                    va_copy_func=va_copy
80          elif test "x$ac_cv___va_copy" = "xyes"; then
81                    va_copy_func=__va_copy
82          fi
83
84          if test -n "$va_copy_func"; then
85                    AC_DEFINE_UNQUOTED(VA_COPY,$va_copy_func,
86                              [A 'va_copy' style function])
87          else
88                    AC_MSG_WARN([Hmm, neither va_copy() nor __va_copy() found.])
89                    AC_MSG_WARN([Using a generic fallback.])
90          fi
91          CFLAGS=$saved_CFLAGS
92          unset saved_CFLAGS
93])
94
95AC_DEFUN([RACOON_CHECK_BUGGY_GETADDRINFO], [
96          AC_MSG_CHECKING(getaddrinfo bug)
97          saved_CFLAGS=$CFLAGS
98          CFLAGS="-Wall -O2"
99          AC_TRY_RUN([
100          #include <sys/types.h>
101          #include <sys/socket.h>
102          #include <netdb.h>
103          #include <stdlib.h>
104          #include <string.h>
105          #include <netinet/in.h>
106
107          int main()
108          {
109            int passive, gaierr, inet4 = 0, inet6 = 0;
110            struct addrinfo hints, *ai, *aitop;
111            char straddr[INET6_ADDRSTRLEN], strport[16];
112
113            for (passive = 0; passive <= 1; passive++) {
114              memset(&hints, 0, sizeof(hints));
115              hints.ai_family = AF_UNSPEC;
116              hints.ai_flags = passive ? AI_PASSIVE : 0;
117              hints.ai_protocol = IPPROTO_TCP;
118              hints.ai_socktype = SOCK_STREAM;
119              if ((gaierr = getaddrinfo(NULL, "54321", &hints, &aitop)) != 0) {
120                (void)gai_strerror(gaierr);
121                goto bad;
122              }
123              for (ai = aitop; ai; ai = ai->ai_next) {
124                if (ai->ai_addr == NULL ||
125                    ai->ai_addrlen == 0 ||
126                    getnameinfo(ai->ai_addr, ai->ai_addrlen,
127                                straddr, sizeof(straddr), strport, sizeof(strport),
128                                NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
129                  goto bad;
130                }
131                switch (ai->ai_family) {
132                case AF_INET:
133                    if (strcmp(strport, "54321") != 0) {
134                      goto bad;
135                    }
136                  if (passive) {
137                    if (strcmp(straddr, "0.0.0.0") != 0) {
138                      goto bad;
139                    }
140                  } else {
141                    if (strcmp(straddr, "127.0.0.1") != 0) {
142                      goto bad;
143                    }
144                  }
145                  inet4++;
146                  break;
147                case AF_INET6:
148                    if (strcmp(strport, "54321") != 0) {
149                      goto bad;
150                    }
151                  if (passive) {
152                    if (strcmp(straddr, "::") != 0) {
153                      goto bad;
154                    }
155                  } else {
156                    if (strcmp(straddr, "::1") != 0) {
157                      goto bad;
158                    }
159                  }
160                  inet6++;
161                  break;
162                case AF_UNSPEC:
163                  goto bad;
164                  break;
165                default:
166                  /* another family support? */
167                  break;
168                }
169              }
170            }
171
172            if (!(inet4 == 0 || inet4 == 2))
173              goto bad;
174            if (!(inet6 == 0 || inet6 == 2))
175              goto bad;
176
177            if (aitop)
178              freeaddrinfo(aitop);
179            exit(0);
180
181           bad:
182            if (aitop)
183              freeaddrinfo(aitop);
184            exit(1);
185          }
186          ],
187          AC_MSG_RESULT(good)
188          buggygetaddrinfo=no,
189          AC_MSG_RESULT(buggy)
190          buggygetaddrinfo=yes,
191          AC_MSG_RESULT(Cross compiling ... Assuming getaddrinfo is not buggy.)
192          buggygetaddrinfo=no)
193          CFLAGS=$saved_CFLAGS
194          unset saved_CFLAGS
195])
196