os-ip.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265
  1. /* os-ip.c -- platform-specific TCP & UDP related code */
  2. /* $OpenLDAP$ */
  3. /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  4. *
  5. * Copyright 1998-2022 The OpenLDAP Foundation.
  6. * Portions Copyright 1999 Lars Uffmann.
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted only as authorized by the OpenLDAP
  11. * Public License.
  12. *
  13. * A copy of this license is available in the file LICENSE in the
  14. * top-level directory of the distribution or, alternatively, at
  15. * <http://www.OpenLDAP.org/license.html>.
  16. */
  17. /* Portions Copyright (c) 1995 Regents of the University of Michigan.
  18. * All rights reserved.
  19. */
  20. /* Significant additional contributors include:
  21. * Lars Uffman
  22. */
  23. #include "portable.h"
  24. #include <stdio.h>
  25. #include <ac/stdlib.h>
  26. #include <ac/errno.h>
  27. #include <ac/socket.h>
  28. #include <ac/string.h>
  29. #include <ac/time.h>
  30. #include <ac/unistd.h>
  31. #ifdef HAVE_IO_H
  32. #include <io.h>
  33. #endif /* HAVE_IO_H */
  34. #ifdef HAVE_FCNTL_H
  35. #include <fcntl.h>
  36. #endif
  37. #include "ldap-int.h"
  38. #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
  39. # ifdef LDAP_PF_INET6
  40. int ldap_int_inet4or6 = AF_UNSPEC;
  41. # else
  42. int ldap_int_inet4or6 = AF_INET;
  43. # endif
  44. #endif
  45. static void
  46. ldap_pvt_set_errno(int err)
  47. {
  48. sock_errset(err);
  49. }
  50. int
  51. ldap_int_timeval_dup( struct timeval **dest, const struct timeval *src )
  52. {
  53. struct timeval *new;
  54. assert( dest != NULL );
  55. if (src == NULL) {
  56. *dest = NULL;
  57. return 0;
  58. }
  59. new = (struct timeval *) LDAP_MALLOC(sizeof(struct timeval));
  60. if( new == NULL ) {
  61. *dest = NULL;
  62. return 1;
  63. }
  64. AC_MEMCPY( (char *) new, (const char *) src, sizeof(struct timeval));
  65. *dest = new;
  66. return 0;
  67. }
  68. static int
  69. ldap_pvt_ndelay_on(LDAP *ld, int fd)
  70. {
  71. Debug1(LDAP_DEBUG_TRACE, "ldap_ndelay_on: %d\n",fd );
  72. return ber_pvt_socket_set_nonblock( fd, 1 );
  73. }
  74. static int
  75. ldap_pvt_ndelay_off(LDAP *ld, int fd)
  76. {
  77. Debug1(LDAP_DEBUG_TRACE, "ldap_ndelay_off: %d\n",fd );
  78. return ber_pvt_socket_set_nonblock( fd, 0 );
  79. }
  80. static ber_socket_t
  81. ldap_int_socket(LDAP *ld, int family, int type )
  82. {
  83. ber_socket_t s = socket(family, type, 0);
  84. Debug1(LDAP_DEBUG_TRACE, "ldap_new_socket: %d\n",s );
  85. #ifdef FD_CLOEXEC
  86. fcntl(s, F_SETFD, FD_CLOEXEC);
  87. #endif
  88. return ( s );
  89. }
  90. static int
  91. ldap_pvt_close_socket(LDAP *ld, int s)
  92. {
  93. Debug1(LDAP_DEBUG_TRACE, "ldap_close_socket: %d\n",s );
  94. return tcp_close(s);
  95. }
  96. static int
  97. ldap_int_prepare_socket(LDAP *ld, int s, int proto )
  98. {
  99. Debug1(LDAP_DEBUG_TRACE, "ldap_prepare_socket: %d\n", s );
  100. #if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY ) || defined( TCP_USER_TIMEOUT )
  101. if ( proto == LDAP_PROTO_TCP ) {
  102. int dummy = 1;
  103. #ifdef SO_KEEPALIVE
  104. if ( setsockopt( s, SOL_SOCKET, SO_KEEPALIVE,
  105. (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR )
  106. {
  107. Debug1(LDAP_DEBUG_TRACE, "ldap_prepare_socket: "
  108. "setsockopt(%d, SO_KEEPALIVE) failed (ignored).\n",
  109. s );
  110. }
  111. if ( ld->ld_options.ldo_keepalive_idle > 0 )
  112. {
  113. #ifdef TCP_KEEPIDLE
  114. if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPIDLE,
  115. (void*) &ld->ld_options.ldo_keepalive_idle,
  116. sizeof(ld->ld_options.ldo_keepalive_idle) ) == AC_SOCKET_ERROR )
  117. {
  118. Debug1(LDAP_DEBUG_TRACE,
  119. "ldap_prepare_socket: "
  120. "setsockopt(%d, TCP_KEEPIDLE) failed (ignored).\n",
  121. s );
  122. }
  123. #else
  124. Debug0(LDAP_DEBUG_TRACE, "ldap_prepare_socket: "
  125. "sockopt TCP_KEEPIDLE not supported on this system.\n" );
  126. #endif /* TCP_KEEPIDLE */
  127. }
  128. if ( ld->ld_options.ldo_keepalive_probes > 0 )
  129. {
  130. #ifdef TCP_KEEPCNT
  131. if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPCNT,
  132. (void*) &ld->ld_options.ldo_keepalive_probes,
  133. sizeof(ld->ld_options.ldo_keepalive_probes) ) == AC_SOCKET_ERROR )
  134. {
  135. Debug1(LDAP_DEBUG_TRACE,
  136. "ldap_prepare_socket: "
  137. "setsockopt(%d, TCP_KEEPCNT) failed (ignored).\n",
  138. s );
  139. }
  140. #else
  141. Debug0(LDAP_DEBUG_TRACE, "ldap_prepare_socket: "
  142. "sockopt TCP_KEEPCNT not supported on this system.\n" );
  143. #endif /* TCP_KEEPCNT */
  144. }
  145. if ( ld->ld_options.ldo_keepalive_interval > 0 )
  146. {
  147. #ifdef TCP_KEEPINTVL
  148. if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPINTVL,
  149. (void*) &ld->ld_options.ldo_keepalive_interval,
  150. sizeof(ld->ld_options.ldo_keepalive_interval) ) == AC_SOCKET_ERROR )
  151. {
  152. Debug1(LDAP_DEBUG_TRACE,
  153. "ldap_prepare_socket: "
  154. "setsockopt(%d, TCP_KEEPINTVL) failed (ignored).\n",
  155. s );
  156. }
  157. #else
  158. Debug0(LDAP_DEBUG_TRACE, "ldap_prepare_socket: "
  159. "sockopt TCP_KEEPINTVL not supported on this system.\n" );
  160. #endif /* TCP_KEEPINTVL */
  161. }
  162. #endif /* SO_KEEPALIVE */
  163. #ifdef TCP_NODELAY
  164. if ( setsockopt( s, IPPROTO_TCP, TCP_NODELAY,
  165. (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR )
  166. {
  167. Debug1(LDAP_DEBUG_TRACE, "ldap_prepare_socket: "
  168. "setsockopt(%d, TCP_NODELAY) failed (ignored).\n",
  169. s );
  170. }
  171. #endif /* TCP_NODELAY */
  172. if ( ld->ld_options.ldo_tcp_user_timeout > 0 )
  173. {
  174. #ifdef TCP_USER_TIMEOUT
  175. if ( setsockopt( s, IPPROTO_TCP, TCP_USER_TIMEOUT,
  176. (void*) &ld->ld_options.ldo_tcp_user_timeout,
  177. sizeof(ld->ld_options.ldo_tcp_user_timeout) ) == AC_SOCKET_ERROR )
  178. {
  179. Debug1(LDAP_DEBUG_TRACE,
  180. "ldap_prepare_socket: "
  181. "setsockopt(%d, TCP_USER_TIMEOUT) failed (ignored).\n",
  182. s );
  183. }
  184. #else
  185. Debug0(LDAP_DEBUG_TRACE, "ldap_prepare_socket: "
  186. "sockopt TCP_USER_TIMEOUT not supported on this system.\n" );
  187. #endif /* TCP_USER_TIMEOUT */
  188. }
  189. }
  190. #endif /* SO_KEEPALIVE || TCP_NODELAY || TCP_USER_TIMEOUT */
  191. return 0;
  192. }
  193. #ifndef HAVE_WINSOCK
  194. #undef TRACE
  195. #define TRACE do { \
  196. char ebuf[128]; \
  197. int saved_errno = errno; \
  198. Debug3(LDAP_DEBUG_TRACE, "ldap_is_socket_ready: error on socket %d: errno: %d (%s)\n", \
  199. s, \
  200. saved_errno, \
  201. sock_errstr(saved_errno, ebuf, sizeof(ebuf)) ); \
  202. } while( 0 )
  203. /*
  204. * check the socket for errors after select returned.
  205. */
  206. static int
  207. ldap_pvt_is_socket_ready(LDAP *ld, int s)
  208. {
  209. Debug1(LDAP_DEBUG_TRACE, "ldap_is_sock_ready: %d\n",s );
  210. #if defined( notyet ) /* && defined( SO_ERROR ) */
  211. {
  212. int so_errno;
  213. ber_socklen_t dummy = sizeof(so_errno);
  214. if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy )
  215. == AC_SOCKET_ERROR )
  216. {
  217. return -1;
  218. }
  219. if ( so_errno ) {
  220. ldap_pvt_set_errno(so_errno);
  221. TRACE;
  222. return -1;
  223. }
  224. return 0;
  225. }
  226. #else
  227. {
  228. /* error slippery */
  229. #ifdef LDAP_PF_INET6
  230. struct sockaddr_storage sin;
  231. #else
  232. struct sockaddr_in sin;
  233. #endif
  234. char ch;
  235. ber_socklen_t dummy = sizeof(sin);
  236. if ( getpeername( s, (struct sockaddr *) &sin, &dummy )
  237. == AC_SOCKET_ERROR )
  238. {
  239. /* XXX: needs to be replace with ber_stream_read() */
  240. (void)!read(s, &ch, 1);
  241. TRACE;
  242. return -1;
  243. }
  244. return 0;
  245. }
  246. #endif
  247. return -1;
  248. }
  249. #undef TRACE
  250. #endif /* HAVE_WINSOCK */
  251. /* NOTE: this is identical to analogous code in os-local.c */
  252. int
  253. ldap_int_poll(
  254. LDAP *ld,
  255. ber_socket_t s,
  256. struct timeval *tvp,
  257. int wr )
  258. {
  259. int rc;
  260. Debug2(LDAP_DEBUG_TRACE, "ldap_int_poll: fd: %d tm: %ld\n",
  261. s, tvp ? tvp->tv_sec : -1L );
  262. #ifdef HAVE_POLL
  263. {
  264. struct pollfd fd;
  265. int timeout = INFTIM;
  266. short event = wr ? POLL_WRITE : POLL_READ;
  267. fd.fd = s;
  268. fd.events = event;
  269. if ( tvp != NULL ) {
  270. timeout = TV2MILLISEC( tvp );
  271. }
  272. do {
  273. fd.revents = 0;
  274. rc = poll( &fd, 1, timeout );
  275. } while ( rc == AC_SOCKET_ERROR && errno == EINTR &&
  276. LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) );
  277. if ( rc == AC_SOCKET_ERROR ) {
  278. return rc;
  279. }
  280. if ( timeout == 0 && rc == 0 ) {
  281. return -2;
  282. }
  283. if ( fd.revents & event ) {
  284. if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) {
  285. return -1;
  286. }
  287. if ( ldap_pvt_ndelay_off( ld, s ) == -1 ) {
  288. return -1;
  289. }
  290. return 0;
  291. }
  292. }
  293. #else
  294. {
  295. fd_set wfds, *z = NULL;
  296. #ifdef HAVE_WINSOCK
  297. fd_set efds;
  298. #endif
  299. struct timeval tv = { 0 };
  300. #if defined( FD_SETSIZE ) && !defined( HAVE_WINSOCK )
  301. if ( s >= FD_SETSIZE ) {
  302. rc = AC_SOCKET_ERROR;
  303. tcp_close( s );
  304. ldap_pvt_set_errno( EMFILE );
  305. return rc;
  306. }
  307. #endif
  308. if ( tvp != NULL ) {
  309. tv = *tvp;
  310. }
  311. do {
  312. FD_ZERO(&wfds);
  313. FD_SET(s, &wfds );
  314. #ifdef HAVE_WINSOCK
  315. FD_ZERO(&efds);
  316. FD_SET(s, &efds );
  317. #endif
  318. rc = select( ldap_int_tblsize, z, &wfds,
  319. #ifdef HAVE_WINSOCK
  320. &efds,
  321. #else
  322. z,
  323. #endif
  324. tvp ? &tv : NULL );
  325. } while ( rc == AC_SOCKET_ERROR && errno == EINTR &&
  326. LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) );
  327. if ( rc == AC_SOCKET_ERROR ) {
  328. return rc;
  329. }
  330. if ( rc == 0 && tvp && tvp->tv_sec == 0 && tvp->tv_usec == 0 ) {
  331. return -2;
  332. }
  333. #ifdef HAVE_WINSOCK
  334. /* This means the connection failed */
  335. if ( FD_ISSET(s, &efds) ) {
  336. int so_errno;
  337. ber_socklen_t dummy = sizeof(so_errno);
  338. if ( getsockopt( s, SOL_SOCKET, SO_ERROR,
  339. (char *) &so_errno, &dummy ) == AC_SOCKET_ERROR || !so_errno )
  340. {
  341. /* impossible */
  342. so_errno = WSAGetLastError();
  343. }
  344. ldap_pvt_set_errno( so_errno );
  345. Debug3(LDAP_DEBUG_TRACE,
  346. "ldap_int_poll: error on socket %d: "
  347. "errno: %d (%s)\n", s, so_errno, sock_errstr( so_errno, dummy, dummy ));
  348. return -1;
  349. }
  350. #endif
  351. if ( FD_ISSET(s, &wfds) ) {
  352. #ifndef HAVE_WINSOCK
  353. if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) {
  354. return -1;
  355. }
  356. #endif
  357. if ( ldap_pvt_ndelay_off(ld, s) == -1 ) {
  358. return -1;
  359. }
  360. return 0;
  361. }
  362. }
  363. #endif
  364. Debug0(LDAP_DEBUG_TRACE, "ldap_int_poll: timed out\n" );
  365. ldap_pvt_set_errno( ETIMEDOUT );
  366. return -1;
  367. }
  368. static int
  369. ldap_pvt_connect(LDAP *ld, ber_socket_t s,
  370. struct sockaddr *sin, ber_socklen_t addrlen,
  371. int async)
  372. {
  373. int rc, err;
  374. struct timeval tv, *opt_tv = NULL;
  375. #ifdef LDAP_CONNECTIONLESS
  376. /* We could do a connect() but that would interfere with
  377. * attempts to poll a broadcast address
  378. */
  379. if (LDAP_IS_UDP(ld)) {
  380. if (ld->ld_options.ldo_peer)
  381. ldap_memfree(ld->ld_options.ldo_peer);
  382. ld->ld_options.ldo_peer=ldap_memcalloc(1, sizeof(struct sockaddr_storage));
  383. AC_MEMCPY(ld->ld_options.ldo_peer,sin,addrlen);
  384. return ( 0 );
  385. }
  386. #endif
  387. if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) {
  388. tv = ld->ld_options.ldo_tm_net;
  389. opt_tv = &tv;
  390. }
  391. Debug3(LDAP_DEBUG_TRACE,
  392. "ldap_pvt_connect: fd: %d tm: %ld async: %d\n",
  393. s, opt_tv ? tv.tv_sec : -1L, async);
  394. if ( opt_tv && ldap_pvt_ndelay_on(ld, s) == -1 )
  395. return ( -1 );
  396. do{
  397. Debug0(LDAP_DEBUG_TRACE, "attempting to connect: \n" );
  398. if ( connect(s, sin, addrlen) != AC_SOCKET_ERROR ) {
  399. Debug0(LDAP_DEBUG_TRACE, "connect success\n" );
  400. if ( !async && opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 )
  401. return ( -1 );
  402. return ( 0 );
  403. }
  404. err = sock_errno();
  405. Debug1(LDAP_DEBUG_TRACE, "connect errno: %d\n", err );
  406. } while(err == EINTR &&
  407. LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ));
  408. if ( err != EINPROGRESS && err != EWOULDBLOCK ) {
  409. return ( -1 );
  410. }
  411. if ( async ) {
  412. /* caller will call ldap_int_poll() as appropriate? */
  413. return ( -2 );
  414. }
  415. rc = ldap_int_poll( ld, s, opt_tv, 1 );
  416. Debug1(LDAP_DEBUG_TRACE, "ldap_pvt_connect: %d\n", rc );
  417. return rc;
  418. }
  419. #ifndef HAVE_INET_ATON
  420. int
  421. ldap_pvt_inet_aton( const char *host, struct in_addr *in)
  422. {
  423. unsigned long u = inet_addr( host );
  424. #ifdef INADDR_NONE
  425. if ( u == INADDR_NONE ) return 0;
  426. #endif
  427. if ( u == 0xffffffffUL || u == (unsigned long) -1L ) return 0;
  428. in->s_addr = u;
  429. return 1;
  430. }
  431. #endif
  432. int
  433. ldap_validate_and_fill_sourceip (char** source_ip_lst, ldapsourceip* temp_source_ip )
  434. {
  435. int i = 0;
  436. int rc = LDAP_PARAM_ERROR;
  437. for ( i = 0; source_ip_lst[i] != NULL; i++ ) {
  438. Debug1( LDAP_DEBUG_TRACE,
  439. "ldap_validate_and_fill_sourceip(%s)\n",
  440. source_ip_lst[i] );
  441. if ( !temp_source_ip->has_ipv4 ) {
  442. if ( inet_aton( source_ip_lst[i], &temp_source_ip->ip4_addr ) ) {
  443. temp_source_ip->has_ipv4 = 1;
  444. rc = LDAP_OPT_SUCCESS;
  445. continue;
  446. }
  447. }
  448. #ifdef LDAP_PF_INET6
  449. if ( !temp_source_ip->has_ipv6 ) {
  450. if ( inet_pton( AF_INET6, source_ip_lst[i],
  451. & temp_source_ip->ip6_addr ) ) {
  452. temp_source_ip->has_ipv6 = 1;
  453. rc = LDAP_OPT_SUCCESS;
  454. continue;
  455. }
  456. }
  457. #endif
  458. memset( temp_source_ip, 0, sizeof( * (temp_source_ip ) ) );
  459. Debug1( LDAP_DEBUG_TRACE,
  460. "ldap_validate_and_fill_sourceip: validation failed for (%s)\n",
  461. source_ip_lst[i] );
  462. break;
  463. }
  464. return rc;
  465. }
  466. int
  467. ldap_int_connect_cbs(LDAP *ld, Sockbuf *sb, ber_socket_t *s, LDAPURLDesc *srv, struct sockaddr *addr)
  468. {
  469. struct ldapoptions *lo;
  470. ldaplist *ll;
  471. ldap_conncb *cb;
  472. int rc;
  473. ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, s );
  474. /* Invoke all handle-specific callbacks first */
  475. lo = &ld->ld_options;
  476. for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
  477. cb = ll->ll_data;
  478. rc = cb->lc_add( ld, sb, srv, addr, cb );
  479. /* on any failure, call the teardown functions for anything
  480. * that previously succeeded
  481. */
  482. if ( rc ) {
  483. ldaplist *l2;
  484. for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) {
  485. cb = l2->ll_data;
  486. cb->lc_del( ld, sb, cb );
  487. }
  488. /* a failure might have implicitly closed the fd */
  489. ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s );
  490. return rc;
  491. }
  492. }
  493. lo = LDAP_INT_GLOBAL_OPT();
  494. for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
  495. cb = ll->ll_data;
  496. rc = cb->lc_add( ld, sb, srv, addr, cb );
  497. if ( rc ) {
  498. ldaplist *l2;
  499. for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) {
  500. cb = l2->ll_data;
  501. cb->lc_del( ld, sb, cb );
  502. }
  503. lo = &ld->ld_options;
  504. for (l2 = lo->ldo_conn_cbs; l2; l2 = l2->ll_next) {
  505. cb = l2->ll_data;
  506. cb->lc_del( ld, sb, cb );
  507. }
  508. ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s );
  509. return rc;
  510. }
  511. }
  512. return 0;
  513. }
  514. int
  515. ldap_connect_to_host(LDAP *ld, Sockbuf *sb,
  516. int proto, LDAPURLDesc *srv,
  517. int async )
  518. {
  519. int rc;
  520. int socktype, port;
  521. ber_socket_t s = AC_SOCKET_INVALID;
  522. char *host;
  523. #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
  524. char serv[7];
  525. int err;
  526. struct addrinfo hints, *res, *sai;
  527. #else
  528. int i;
  529. int use_hp = 0;
  530. struct hostent *hp = NULL;
  531. struct hostent he_buf;
  532. struct in_addr in;
  533. char *ha_buf=NULL;
  534. #endif
  535. if ( srv->lud_host == NULL || *srv->lud_host == 0 ) {
  536. host = "localhost";
  537. } else {
  538. host = srv->lud_host;
  539. }
  540. port = srv->lud_port;
  541. if( !port ) {
  542. if( strcmp(srv->lud_scheme, "ldaps") == 0 ) {
  543. port = LDAPS_PORT;
  544. } else {
  545. port = LDAP_PORT;
  546. }
  547. }
  548. switch(proto) {
  549. case LDAP_PROTO_TCP: socktype = SOCK_STREAM;
  550. Debug2(LDAP_DEBUG_TRACE, "ldap_connect_to_host: TCP %s:%d\n",
  551. host, port );
  552. break;
  553. case LDAP_PROTO_UDP: socktype = SOCK_DGRAM;
  554. Debug2(LDAP_DEBUG_TRACE, "ldap_connect_to_host: UDP %s:%d\n",
  555. host, port );
  556. break;
  557. default:
  558. Debug1(LDAP_DEBUG_TRACE,
  559. "ldap_connect_to_host: unknown proto: %d\n",
  560. proto );
  561. return -1;
  562. }
  563. #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
  564. memset( &hints, '\0', sizeof(hints) );
  565. #ifdef USE_AI_ADDRCONFIG /* FIXME: configure test needed */
  566. /* Use AI_ADDRCONFIG only on systems where its known to be needed. */
  567. hints.ai_flags = AI_ADDRCONFIG;
  568. #endif
  569. hints.ai_family = ldap_int_inet4or6;
  570. hints.ai_socktype = socktype;
  571. snprintf(serv, sizeof serv, "%d", port );
  572. /* most getaddrinfo(3) use non-threadsafe resolver libraries */
  573. LDAP_MUTEX_LOCK(&ldap_int_resolv_mutex);
  574. err = getaddrinfo( host, serv, &hints, &res );
  575. LDAP_MUTEX_UNLOCK(&ldap_int_resolv_mutex);
  576. if ( err != 0 ) {
  577. Debug1(LDAP_DEBUG_TRACE,
  578. "ldap_connect_to_host: getaddrinfo failed: %s\n",
  579. AC_GAI_STRERROR(err) );
  580. return -1;
  581. }
  582. rc = -1;
  583. for( sai=res; sai != NULL; sai=sai->ai_next) {
  584. unsigned short bind_success = 1;
  585. if( sai->ai_addr == NULL ) {
  586. Debug0(LDAP_DEBUG_TRACE,
  587. "ldap_connect_to_host: getaddrinfo "
  588. "ai_addr is NULL?\n" );
  589. continue;
  590. }
  591. #ifndef LDAP_PF_INET6
  592. if ( sai->ai_family == AF_INET6 ) continue;
  593. #endif
  594. /* we assume AF_x and PF_x are equal for all x */
  595. s = ldap_int_socket( ld, sai->ai_family, socktype );
  596. if ( s == AC_SOCKET_INVALID ) {
  597. continue;
  598. }
  599. if ( ldap_int_prepare_socket(ld, s, proto ) == -1 ) {
  600. ldap_pvt_close_socket(ld, s);
  601. break;
  602. }
  603. switch (sai->ai_family) {
  604. #ifdef LDAP_PF_INET6
  605. case AF_INET6: {
  606. char addr[INET6_ADDRSTRLEN];
  607. inet_ntop( AF_INET6,
  608. &((struct sockaddr_in6 *)sai->ai_addr)->sin6_addr,
  609. addr, sizeof addr);
  610. Debug2(LDAP_DEBUG_TRACE,
  611. "ldap_connect_to_host: Trying %s %s\n",
  612. addr, serv );
  613. if( ld->ld_options.ldo_local_ip_addrs.has_ipv6 ) {
  614. struct sockaddr_in6 ip6addr;
  615. char bind_addr[INET6_ADDRSTRLEN];
  616. ip6addr.sin6_family = AF_INET6;
  617. ip6addr.sin6_port = 0;
  618. ip6addr.sin6_addr = ld->ld_options.ldo_local_ip_addrs.ip6_addr;
  619. inet_ntop( AF_INET6,
  620. &(ip6addr.sin6_addr),
  621. bind_addr, sizeof bind_addr );
  622. Debug1( LDAP_DEBUG_TRACE,
  623. "ldap_connect_to_host: From source address %s\n",
  624. bind_addr );
  625. if ( bind( s, ( struct sockaddr* ) &ip6addr, sizeof ip6addr ) != 0 ) {
  626. Debug1( LDAP_DEBUG_TRACE,
  627. "ldap_connect_to_host: Failed to bind source address %s\n",
  628. bind_addr );
  629. bind_success = 0;
  630. }
  631. }
  632. } break;
  633. #endif
  634. case AF_INET: {
  635. char addr[INET_ADDRSTRLEN];
  636. inet_ntop( AF_INET,
  637. &((struct sockaddr_in *)sai->ai_addr)->sin_addr,
  638. addr, sizeof addr);
  639. Debug2(LDAP_DEBUG_TRACE,
  640. "ldap_connect_to_host: Trying %s:%s\n",
  641. addr, serv );
  642. if( ld->ld_options.ldo_local_ip_addrs.has_ipv4 ) {
  643. struct sockaddr_in ip4addr;
  644. char bind_addr[INET_ADDRSTRLEN];
  645. ip4addr.sin_family = AF_INET;
  646. ip4addr.sin_port = 0;
  647. ip4addr.sin_addr = ld->ld_options.ldo_local_ip_addrs.ip4_addr;
  648. inet_ntop( AF_INET,
  649. &(ip4addr.sin_addr),
  650. bind_addr, sizeof bind_addr );
  651. Debug1( LDAP_DEBUG_TRACE,
  652. "ldap_connect_to_host: From source address %s\n",
  653. bind_addr );
  654. if ( bind(s, ( struct sockaddr* )&ip4addr, sizeof ip4addr ) != 0 ) {
  655. Debug1( LDAP_DEBUG_TRACE,
  656. "ldap_connect_to_host: Failed to bind source address %s\n",
  657. bind_addr );
  658. bind_success = 0;
  659. }
  660. }
  661. } break;
  662. }
  663. if ( bind_success ) {
  664. rc = ldap_pvt_connect( ld, s,
  665. sai->ai_addr, sai->ai_addrlen, async );
  666. if ( rc == 0 || rc == -2 ) {
  667. err = ldap_int_connect_cbs( ld, sb, &s, srv, sai->ai_addr );
  668. if ( err )
  669. rc = err;
  670. else
  671. break;
  672. }
  673. }
  674. ldap_pvt_close_socket(ld, s);
  675. }
  676. freeaddrinfo(res);
  677. #else
  678. if (! inet_aton( host, &in ) ) {
  679. int local_h_errno;
  680. rc = ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf,
  681. &hp, &local_h_errno );
  682. if ( (rc < 0) || (hp == NULL) ) {
  683. #ifdef HAVE_WINSOCK
  684. ldap_pvt_set_errno( WSAGetLastError() );
  685. #else
  686. /* not exactly right, but... */
  687. ldap_pvt_set_errno( EHOSTUNREACH );
  688. #endif
  689. if (ha_buf) LDAP_FREE(ha_buf);
  690. return -1;
  691. }
  692. use_hp = 1;
  693. }
  694. rc = s = -1;
  695. for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) {
  696. struct sockaddr_in sin;
  697. unsigned short bind_success = 1;
  698. #ifdef HAVE_INET_NTOA_B
  699. char address[INET_ADDR_LEN];
  700. char bind_addr[INET_ADDR_LEN];
  701. #else
  702. char *address;
  703. char *bind_addr;
  704. #endif
  705. s = ldap_int_socket( ld, PF_INET, socktype );
  706. if ( s == AC_SOCKET_INVALID ) {
  707. /* use_hp ? continue : break; */
  708. break;
  709. }
  710. if ( ldap_int_prepare_socket( ld, s, proto ) == -1 ) {
  711. ldap_pvt_close_socket(ld, s);
  712. break;
  713. }
  714. (void)memset((char *)&sin, '\0', sizeof sin);
  715. sin.sin_family = AF_INET;
  716. sin.sin_port = htons((unsigned short) port);
  717. if( use_hp ) {
  718. AC_MEMCPY( &sin.sin_addr, hp->h_addr_list[i],
  719. sizeof(sin.sin_addr) );
  720. } else {
  721. AC_MEMCPY( &sin.sin_addr, &in.s_addr,
  722. sizeof(sin.sin_addr) );
  723. }
  724. #ifdef HAVE_INET_NTOA_B
  725. /* for VxWorks */
  726. inet_ntoa_b( sin.sin_address, address );
  727. #else
  728. address = inet_ntoa( sin.sin_addr );
  729. #endif
  730. Debug2( LDAP_DEBUG_TRACE,
  731. "ldap_connect_to_host: Trying %s:%d\n",
  732. address, port );
  733. if( ld->ld_options.ldo_local_ip_addrs.has_ipv4 ) {
  734. struct sockaddr_in ip4addr;
  735. ip4addr.sin_family = AF_INET;
  736. ip4addr.sin_addr = ld->ld_options.ldo_local_ip_addrs.ip4_addr;
  737. #ifdef HAVE_INET_NTOA_B
  738. inet_ntoa_b( ip4addr.sin_address, bind_addr );
  739. #else
  740. bind_addr = inet_ntoa( ip4addr.sin_addr );
  741. #endif
  742. Debug1( LDAP_DEBUG_TRACE,
  743. "ldap_connect_to_host: From source address %s\n",
  744. bind_addr );
  745. if ( bind( s, (struct sockaddr*)&ip4addr, sizeof ip4addr ) != 0 ) {
  746. Debug1( LDAP_DEBUG_TRACE,
  747. "ldap_connect_to_host: Failed to bind source address %s\n",
  748. bind_addr );
  749. bind_success = 0;
  750. }
  751. }
  752. if ( bind_success ) {
  753. rc = ldap_pvt_connect(ld, s,
  754. (struct sockaddr *)&sin, sizeof(sin),
  755. async);
  756. if ( (rc == 0) || (rc == -2) ) {
  757. int err = ldap_int_connect_cbs( ld, sb, &s, srv, (struct sockaddr *)&sin );
  758. if ( err )
  759. rc = err;
  760. else
  761. break;
  762. }
  763. }
  764. ldap_pvt_close_socket(ld, s);
  765. if (!use_hp) break;
  766. }
  767. if (ha_buf) LDAP_FREE(ha_buf);
  768. #endif
  769. return rc;
  770. }
  771. #if defined( HAVE_CYRUS_SASL )
  772. char *
  773. ldap_host_connected_to( Sockbuf *sb, const char *host )
  774. {
  775. ber_socklen_t len;
  776. #ifdef LDAP_PF_INET6
  777. struct sockaddr_storage sabuf;
  778. #else
  779. struct sockaddr sabuf;
  780. #endif
  781. struct sockaddr *sa = (struct sockaddr *) &sabuf;
  782. ber_socket_t sd;
  783. (void)memset( (char *)sa, '\0', sizeof sabuf );
  784. len = sizeof sabuf;
  785. ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
  786. if ( getpeername( sd, sa, &len ) == -1 ) {
  787. return( NULL );
  788. }
  789. /*
  790. * do a reverse lookup on the addr to get the official hostname.
  791. * this is necessary for kerberos to work right, since the official
  792. * hostname is used as the kerberos instance.
  793. */
  794. switch (sa->sa_family) {
  795. #ifdef LDAP_PF_LOCAL
  796. case AF_LOCAL:
  797. return LDAP_STRDUP( ldap_int_hostname );
  798. #endif
  799. #ifdef LDAP_PF_INET6
  800. case AF_INET6:
  801. {
  802. struct in6_addr localhost = IN6ADDR_LOOPBACK_INIT;
  803. if( memcmp ( &((struct sockaddr_in6 *)sa)->sin6_addr,
  804. &localhost, sizeof(localhost)) == 0 )
  805. {
  806. return LDAP_STRDUP( ldap_int_hostname );
  807. }
  808. }
  809. break;
  810. #endif
  811. case AF_INET:
  812. {
  813. struct in_addr localhost;
  814. localhost.s_addr = htonl( INADDR_ANY );
  815. if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr,
  816. &localhost, sizeof(localhost) ) == 0 )
  817. {
  818. return LDAP_STRDUP( ldap_int_hostname );
  819. }
  820. #ifdef INADDR_LOOPBACK
  821. localhost.s_addr = htonl( INADDR_LOOPBACK );
  822. if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr,
  823. &localhost, sizeof(localhost) ) == 0 )
  824. {
  825. return LDAP_STRDUP( ldap_int_hostname );
  826. }
  827. #endif
  828. }
  829. break;
  830. default:
  831. return( NULL );
  832. break;
  833. }
  834. {
  835. char *herr;
  836. #ifdef NI_MAXHOST
  837. char hbuf[NI_MAXHOST];
  838. #elif defined( MAXHOSTNAMELEN )
  839. char hbuf[MAXHOSTNAMELEN];
  840. #else
  841. char hbuf[256];
  842. #endif
  843. hbuf[0] = 0;
  844. if (ldap_pvt_get_hname( sa, len, hbuf, sizeof(hbuf), &herr ) == 0
  845. && hbuf[0] )
  846. {
  847. return LDAP_STRDUP( hbuf );
  848. }
  849. }
  850. return host ? LDAP_STRDUP( host ) : NULL;
  851. }
  852. #endif
  853. struct selectinfo {
  854. #ifdef HAVE_POLL
  855. /* for UNIX poll(2) */
  856. int si_maxfd;
  857. struct pollfd si_fds[FD_SETSIZE];
  858. #else
  859. /* for UNIX select(2) */
  860. fd_set si_readfds;
  861. fd_set si_writefds;
  862. fd_set si_use_readfds;
  863. fd_set si_use_writefds;
  864. #endif
  865. };
  866. void
  867. ldap_mark_select_write( LDAP *ld, Sockbuf *sb )
  868. {
  869. struct selectinfo *sip;
  870. ber_socket_t sd;
  871. sip = (struct selectinfo *)ld->ld_selectinfo;
  872. ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
  873. #ifdef HAVE_POLL
  874. /* for UNIX poll(2) */
  875. {
  876. int empty=-1;
  877. int i;
  878. for(i=0; i < sip->si_maxfd; i++) {
  879. if( sip->si_fds[i].fd == sd ) {
  880. sip->si_fds[i].events |= POLL_WRITE;
  881. return;
  882. }
  883. if( empty==-1 && sip->si_fds[i].fd == -1 ) {
  884. empty=i;
  885. }
  886. }
  887. if( empty == -1 ) {
  888. if( sip->si_maxfd >= FD_SETSIZE ) {
  889. /* FIXME */
  890. return;
  891. }
  892. empty = sip->si_maxfd++;
  893. }
  894. sip->si_fds[empty].fd = sd;
  895. sip->si_fds[empty].events = POLL_WRITE;
  896. }
  897. #else
  898. /* for UNIX select(2) */
  899. if ( !FD_ISSET( sd, &sip->si_writefds )) {
  900. FD_SET( sd, &sip->si_writefds );
  901. }
  902. #endif
  903. }
  904. void
  905. ldap_mark_select_read( LDAP *ld, Sockbuf *sb )
  906. {
  907. struct selectinfo *sip;
  908. ber_socket_t sd;
  909. sip = (struct selectinfo *)ld->ld_selectinfo;
  910. ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
  911. #ifdef HAVE_POLL
  912. /* for UNIX poll(2) */
  913. {
  914. int empty=-1;
  915. int i;
  916. for(i=0; i < sip->si_maxfd; i++) {
  917. if( sip->si_fds[i].fd == sd ) {
  918. sip->si_fds[i].events |= POLL_READ;
  919. return;
  920. }
  921. if( empty==-1 && sip->si_fds[i].fd == -1 ) {
  922. empty=i;
  923. }
  924. }
  925. if( empty == -1 ) {
  926. if( sip->si_maxfd >= FD_SETSIZE ) {
  927. /* FIXME */
  928. return;
  929. }
  930. empty = sip->si_maxfd++;
  931. }
  932. sip->si_fds[empty].fd = sd;
  933. sip->si_fds[empty].events = POLL_READ;
  934. }
  935. #else
  936. /* for UNIX select(2) */
  937. if ( !FD_ISSET( sd, &sip->si_readfds )) {
  938. FD_SET( sd, &sip->si_readfds );
  939. }
  940. #endif
  941. }
  942. void
  943. ldap_mark_select_clear( LDAP *ld, Sockbuf *sb )
  944. {
  945. struct selectinfo *sip;
  946. ber_socket_t sd;
  947. sip = (struct selectinfo *)ld->ld_selectinfo;
  948. ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
  949. #ifdef HAVE_POLL
  950. /* for UNIX poll(2) */
  951. {
  952. int i;
  953. for(i=0; i < sip->si_maxfd; i++) {
  954. if( sip->si_fds[i].fd == sd ) {
  955. sip->si_fds[i].fd = -1;
  956. }
  957. }
  958. }
  959. #else
  960. /* for UNIX select(2) */
  961. FD_CLR( sd, &sip->si_writefds );
  962. FD_CLR( sd, &sip->si_readfds );
  963. #endif
  964. }
  965. void
  966. ldap_clear_select_write( LDAP *ld, Sockbuf *sb )
  967. {
  968. struct selectinfo *sip;
  969. ber_socket_t sd;
  970. sip = (struct selectinfo *)ld->ld_selectinfo;
  971. ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
  972. #ifdef HAVE_POLL
  973. /* for UNIX poll(2) */
  974. {
  975. int i;
  976. for(i=0; i < sip->si_maxfd; i++) {
  977. if( sip->si_fds[i].fd == sd ) {
  978. sip->si_fds[i].events &= ~POLL_WRITE;
  979. }
  980. }
  981. }
  982. #else
  983. /* for UNIX select(2) */
  984. FD_CLR( sd, &sip->si_writefds );
  985. #endif
  986. }
  987. int
  988. ldap_is_write_ready( LDAP *ld, Sockbuf *sb )
  989. {
  990. struct selectinfo *sip;
  991. ber_socket_t sd;
  992. sip = (struct selectinfo *)ld->ld_selectinfo;
  993. ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
  994. #ifdef HAVE_POLL
  995. /* for UNIX poll(2) */
  996. {
  997. int i;
  998. for(i=0; i < sip->si_maxfd; i++) {
  999. if( sip->si_fds[i].fd == sd ) {
  1000. return sip->si_fds[i].revents & POLL_WRITE;
  1001. }
  1002. }
  1003. return 0;
  1004. }
  1005. #else
  1006. /* for UNIX select(2) */
  1007. return( FD_ISSET( sd, &sip->si_use_writefds ));
  1008. #endif
  1009. }
  1010. int
  1011. ldap_is_read_ready( LDAP *ld, Sockbuf *sb )
  1012. {
  1013. struct selectinfo *sip;
  1014. ber_socket_t sd;
  1015. sip = (struct selectinfo *)ld->ld_selectinfo;
  1016. if (ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL ))
  1017. return 1;
  1018. ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
  1019. #ifdef HAVE_POLL
  1020. /* for UNIX poll(2) */
  1021. {
  1022. int i;
  1023. for(i=0; i < sip->si_maxfd; i++) {
  1024. if( sip->si_fds[i].fd == sd ) {
  1025. return sip->si_fds[i].revents & POLL_READ;
  1026. }
  1027. }
  1028. return 0;
  1029. }
  1030. #else
  1031. /* for UNIX select(2) */
  1032. return( FD_ISSET( sd, &sip->si_use_readfds ));
  1033. #endif
  1034. }
  1035. void *
  1036. ldap_new_select_info( void )
  1037. {
  1038. struct selectinfo *sip;
  1039. sip = (struct selectinfo *)LDAP_CALLOC( 1, sizeof( struct selectinfo ));
  1040. if ( sip == NULL ) return NULL;
  1041. #ifdef HAVE_POLL
  1042. /* for UNIX poll(2) */
  1043. /* sip->si_maxfd=0 */
  1044. #else
  1045. /* for UNIX select(2) */
  1046. FD_ZERO( &sip->si_readfds );
  1047. FD_ZERO( &sip->si_writefds );
  1048. #endif
  1049. return( (void *)sip );
  1050. }
  1051. void
  1052. ldap_free_select_info( void *sip )
  1053. {
  1054. LDAP_FREE( sip );
  1055. }
  1056. #ifndef HAVE_POLL
  1057. int ldap_int_tblsize = 0;
  1058. void
  1059. ldap_int_ip_init( void )
  1060. {
  1061. #if defined( HAVE_SYSCONF )
  1062. long tblsize = sysconf( _SC_OPEN_MAX );
  1063. if( tblsize > INT_MAX ) tblsize = INT_MAX;
  1064. #elif defined( HAVE_GETDTABLESIZE )
  1065. int tblsize = getdtablesize();
  1066. #else
  1067. int tblsize = FD_SETSIZE;
  1068. #endif /* !USE_SYSCONF */
  1069. #ifdef FD_SETSIZE
  1070. if( tblsize > FD_SETSIZE ) tblsize = FD_SETSIZE;
  1071. #endif /* FD_SETSIZE */
  1072. ldap_int_tblsize = tblsize;
  1073. }
  1074. #endif
  1075. int
  1076. ldap_int_select( LDAP *ld, struct timeval *timeout )
  1077. {
  1078. int rc;
  1079. struct selectinfo *sip;
  1080. Debug0( LDAP_DEBUG_TRACE, "ldap_int_select\n" );
  1081. #ifndef HAVE_POLL
  1082. if ( ldap_int_tblsize == 0 ) ldap_int_ip_init();
  1083. #endif
  1084. sip = (struct selectinfo *)ld->ld_selectinfo;
  1085. assert( sip != NULL );
  1086. #ifdef HAVE_POLL
  1087. {
  1088. int to = timeout ? TV2MILLISEC( timeout ) : INFTIM;
  1089. rc = poll( sip->si_fds, sip->si_maxfd, to );
  1090. }
  1091. #else
  1092. sip->si_use_readfds = sip->si_readfds;
  1093. sip->si_use_writefds = sip->si_writefds;
  1094. rc = select( ldap_int_tblsize,
  1095. &sip->si_use_readfds, &sip->si_use_writefds,
  1096. NULL, timeout );
  1097. #endif
  1098. return rc;
  1099. }