net_udp.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:26k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * FILE:     net_udp.c
  3.  * AUTHOR:   Colin Perkins 
  4.  * MODIFIED: Orion Hodson & Piers O'Hanlon
  5.  * 
  6.  * Copyright (c) 1998-2000 University College London
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, is permitted provided that the following conditions 
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *      This product includes software developed by the Computer Science
  20.  *      Department at University College London
  21.  * 4. Neither the name of the University nor of the Department may be used
  22.  *    to endorse or promote products derived from this software without
  23.  *    specific prior written permission.
  24.  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36. /* If this machine supports IPv6 the symbol HAVE_IPv6 should */
  37. /* be defined in either config_unix.h or config_win32.h. The */
  38. /* appropriate system header files should also be included   */
  39. /* by those files.                                           */
  40. #include "config_unix.h"
  41. #include "config_win32.h"
  42. #include "debug.h"
  43. #include "memory.h"
  44. #include "inet_pton.h"
  45. #include "inet_ntop.h"
  46. #include "vsnprintf.h"
  47. #include "net_udp.h"
  48. #ifdef NEED_ADDRINFO_H
  49. #include "addrinfo.h"
  50. #endif
  51. #define IPv4 4
  52. #define IPv6 6
  53. #ifdef WIN2K_IPV6
  54. const struct in6_addr in6addr_any = {IN6ADDR_ANY_INIT};
  55. #endif
  56. /* This is pretty nasty but it's the simplest way to get round */
  57. /* the Detexis bug that means their MUSICA IPv6 stack uses     */
  58. /* IPPROTO_IP instead of IPPROTO_IPV6 in setsockopt calls      */
  59. /* We also need to define in6addr_any */
  60. #ifdef  MUSICA_IPV6
  61. #define IPPROTO_IPV6 IPPROTO_IP
  62. struct in6_addr in6addr_any = {IN6ADDR_ANY_INIT};
  63. /* These DEF's are required as MUSICA's winsock6.h causes a clash with some of the 
  64.  * standard ws2tcpip.h definitions (eg struct in_addr6).
  65.  * Note: winsock6.h defines AF_INET6 as 24 NOT 23 as in winsock2.h - I have left it
  66.  * set to the MUSICA value as this is used in some of their function calls. 
  67.  */
  68. //#define AF_INET6        23
  69. #define IP_MULTICAST_LOOP      11 /*set/get IP multicast loopback */
  70. #define IP_MULTICAST_IF 9 /* set/get IP multicast i/f  */
  71. #define IP_MULTICAST_TTL       10 /* set/get IP multicast ttl */
  72. #define IP_MULTICAST_LOOP      11 /*set/get IP multicast loopback */
  73. #define IP_ADD_MEMBERSHIP      12 /* add an IP group membership */
  74. #define IP_DROP_MEMBERSHIP     13/* drop an IP group membership */
  75. #define IN6_IS_ADDR_UNSPECIFIED(a) (((a)->s6_addr32[0] == 0) && 
  76. ((a)->s6_addr32[1] == 0) && 
  77. ((a)->s6_addr32[2] == 0) && 
  78. ((a)->s6_addr32[3] == 0))
  79. struct ip_mreq {
  80. struct in_addr imr_multiaddr; /* IP multicast address of group */
  81. struct in_addr imr_interface; /* local IP address of interface */
  82. };
  83. #endif
  84. #ifndef INADDR_NONE
  85. #define INADDR_NONE 0xffffffff
  86. #endif
  87. struct _socket_udp {
  88. int    mode; /* IPv4 or IPv6 */
  89.         char         *addr;
  90. uint16_t  rx_port;
  91. uint16_t  tx_port;
  92. ttl_t    ttl;
  93. fd_t    fd;
  94. struct in_addr  addr4;
  95. #ifdef HAVE_IPv6
  96. struct in6_addr  addr6;
  97. #endif /* HAVE_IPv6 */
  98. };
  99. #ifdef WIN32
  100. /* Want to use both Winsock 1 and 2 socket options, but since
  101. * IPv6 support requires Winsock 2 we have to add own backwards
  102. * compatibility for Winsock 1.
  103. */
  104. #define SETSOCKOPT winsock_versions_setsockopt
  105. #else
  106. #define SETSOCKOPT setsockopt
  107. #endif /* WIN32 */
  108. /*****************************************************************************/
  109. /* Support functions...                                                      */
  110. /*****************************************************************************/
  111. static void
  112. socket_error(const char *msg, ...)
  113. {
  114. char buffer[255];
  115. uint32_t blen = sizeof(buffer) / sizeof(buffer[0]);
  116. va_list ap;
  117. #ifdef WIN32
  118. #define WSERR(x) {#x,x}
  119. struct wse {
  120. char  errname[20];
  121. int my_errno;
  122. };
  123. struct wse ws_errs[] = {
  124. WSERR(WSANOTINITIALISED), WSERR(WSAENETDOWN),     WSERR(WSAEACCES),
  125. WSERR(WSAEINVAL),         WSERR(WSAEINTR),        WSERR(WSAEINPROGRESS),
  126. WSERR(WSAEFAULT),         WSERR(WSAENETRESET),    WSERR(WSAENOBUFS),
  127. WSERR(WSAENOTCONN),       WSERR(WSAENOTSOCK),     WSERR(WSAEOPNOTSUPP),
  128. WSERR(WSAESHUTDOWN),      WSERR(WSAEWOULDBLOCK),  WSERR(WSAEMSGSIZE),
  129. WSERR(WSAEHOSTUNREACH),   WSERR(WSAECONNABORTED), WSERR(WSAECONNRESET),
  130. WSERR(WSAEADDRNOTAVAIL),  WSERR(WSAEAFNOSUPPORT), WSERR(WSAEDESTADDRREQ),
  131. WSERR(WSAENETUNREACH),    WSERR(WSAETIMEDOUT),    WSERR(0)
  132. };
  133. int i, e = WSAGetLastError();
  134. i = 0;
  135. while(ws_errs[i].my_errno && ws_errs[i].my_errno != e) {
  136. i++;
  137. }
  138. va_start(ap, msg);
  139. _vsnprintf(buffer, blen, msg, ap);
  140. va_end(ap);
  141. printf("ERROR: %s, (%d - %s)n", msg, e, ws_errs[i].errname);
  142. #else
  143. uint32_t retlen;
  144. va_start(ap, msg);
  145. retlen = vsnprintf(buffer, blen, msg, ap);
  146. va_end(ap);
  147. blen -= retlen;
  148. snprintf(buffer + retlen, blen, ":%s", strerror(errno));
  149. rtp_message(LOG_ALERT, buffer);
  150. #endif
  151. }
  152. #ifdef WIN32
  153. /* ws2tcpip.h defines these constants with different values from
  154. * winsock.h so files that use winsock 2 values but try to use 
  155. * winsock 1 fail.  So what was the motivation in changing the
  156. * constants ?
  157. */
  158. #define WS1_IP_MULTICAST_IF     2 /* set/get IP multicast interface   */
  159. #define WS1_IP_MULTICAST_TTL    3 /* set/get IP multicast timetolive  */
  160. #define WS1_IP_MULTICAST_LOOP   4 /* set/get IP multicast loopback    */
  161. #define WS1_IP_ADD_MEMBERSHIP   5 /* add  an IP group membership      */
  162. #define WS1_IP_DROP_MEMBERSHIP  6 /* drop an IP group membership      */
  163. /* winsock_versions_setsockopt tries 1 winsock version of option 
  164. * optname and then winsock 2 version if that failed.
  165. */
  166. static int
  167. winsock_versions_setsockopt(SOCKET s, int level, int optname, const char FAR * optval, int optlen)
  168. {
  169. int success = -1;
  170. switch (optname) {
  171. case IP_MULTICAST_IF:
  172. success = setsockopt(s, level, WS1_IP_MULTICAST_IF, optval, optlen);
  173. break;
  174. case IP_MULTICAST_TTL:
  175. success = setsockopt(s, level, WS1_IP_MULTICAST_TTL, optval, optlen);
  176. break;
  177. case IP_MULTICAST_LOOP:
  178. success = setsockopt(s, level, WS1_IP_MULTICAST_LOOP, optval, optlen);
  179. break;
  180. case IP_ADD_MEMBERSHIP: 
  181. success = setsockopt(s, level, WS1_IP_ADD_MEMBERSHIP, optval, optlen);
  182. break;
  183. case IP_DROP_MEMBERSHIP: 
  184. success = setsockopt(s, level, WS1_IP_DROP_MEMBERSHIP, optval, optlen);
  185. break;
  186. }
  187. if (success != -1) {
  188. return success;
  189. }
  190. return setsockopt(s, level, optname, optval, optlen);
  191. }
  192. #endif
  193. #ifdef NEED_INET_ATON
  194. #ifdef NEED_INET_ATON_STATIC
  195. static 
  196. #endif
  197. int inet_aton(const char *name, struct in_addr *addr)
  198. {
  199. addr->s_addr = inet_addr(name);
  200. return (addr->s_addr != (in_addr_t) INADDR_NONE);
  201. }
  202. #endif
  203. #ifdef NEED_IN6_IS_ADDR_MULTICAST
  204. #define IN6_IS_ADDR_MULTICAST(addr) ((addr)->s6_addr[0] == 0xffU)
  205. #endif
  206. #if defined(NEED_IN6_IS_ADDR_UNSPECIFIED) && defined(MUSICA_IPV6)
  207. #define IN6_IS_ADDR_UNSPECIFIED(addr) IS_UNSPEC_IN6_ADDR(*addr)
  208. #endif
  209. /*****************************************************************************/
  210. /* IPv4 specific functions...                                                */
  211. /*****************************************************************************/
  212. static int udp_addr_valid4(const char *dst)
  213. {
  214.         struct in_addr addr4;
  215. struct hostent *h;
  216. if (inet_pton(AF_INET, dst, &addr4)) {
  217. return TRUE;
  218. h = gethostbyname(dst);
  219. if (h != NULL) {
  220. return TRUE;
  221. }
  222. socket_error("Can't resolve IP address for %s", dst);
  223.         return FALSE;
  224. }
  225. static socket_udp *udp_init4(const char *addr, const char *iface, uint16_t rx_port, uint16_t tx_port, int ttl)
  226. {
  227. int                   reuse = 1;
  228. struct sockaddr_in    s_in;
  229. struct in_addr  iface_addr;
  230. #ifdef WIN32
  231. int recv_buf_size = 65536;
  232. #endif
  233. socket_udp          *s = (socket_udp *)malloc(sizeof(socket_udp));
  234. s->mode    = IPv4;
  235. s->addr    = NULL;
  236. s->rx_port = rx_port;
  237. s->tx_port = tx_port;
  238. s->ttl     = ttl;
  239. if (inet_pton(AF_INET, addr, &s->addr4) != 1) {
  240. struct hostent *h = gethostbyname(addr);
  241. if (h == NULL) {
  242. socket_error("Can't resolve IP address for %s", addr);
  243.                         free(s);
  244. return NULL;
  245. }
  246. memcpy(&(s->addr4), h->h_addr_list[0], sizeof(s->addr4));
  247. }
  248. if (iface != NULL) {
  249. if (inet_pton(AF_INET, iface, &iface_addr) != 1) {
  250. rtp_message(LOG_ERR, "Illegal interface specification");
  251.                         free(s);
  252. return NULL;
  253. }
  254. } else {
  255. iface_addr.s_addr = 0;
  256. }
  257. s->fd = socket(AF_INET, SOCK_DGRAM, 0);
  258. if (s->fd < 0) {
  259. socket_error("socket");
  260. return NULL;
  261. }
  262. #ifdef WIN32
  263. if (SETSOCKOPT(s->fd, SOL_SOCKET, SO_RCVBUF, (char *)&recv_buf_size, sizeof(int)) != 0) {
  264.   socket_error("setsockopt SO_RCVBUF");
  265.   return NULL;
  266. }
  267. #endif
  268. if (SETSOCKOPT(s->fd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse, sizeof(reuse)) != 0) {
  269. socket_error("setsockopt SO_REUSEADDR");
  270. return NULL;
  271. }
  272. #ifdef SO_REUSEPORT
  273. if (SETSOCKOPT(s->fd, SOL_SOCKET, SO_REUSEPORT, (char *) &reuse, sizeof(reuse)) != 0) {
  274. socket_error("setsockopt SO_REUSEPORT");
  275. return NULL;
  276. }
  277. #endif
  278. s_in.sin_family      = AF_INET;
  279. s_in.sin_addr.s_addr = INADDR_ANY;
  280. s_in.sin_port        = htons(rx_port);
  281. if (bind(s->fd, (struct sockaddr *) &s_in, sizeof(s_in)) != 0) {
  282. socket_error("bind: port %d", rx_port);
  283. return NULL;
  284. }
  285. if (IN_MULTICAST(ntohl(s->addr4.s_addr))) {
  286. char            loop = 1;
  287. struct ip_mreq  imr;
  288. imr.imr_multiaddr.s_addr = s->addr4.s_addr;
  289. imr.imr_interface.s_addr = iface_addr.s_addr;
  290. if (SETSOCKOPT(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &imr, sizeof(struct ip_mreq)) != 0) {
  291. socket_error("setsockopt IP_ADD_MEMBERSHIP");
  292. return NULL;
  293. }
  294. #ifndef WIN32
  295. if (SETSOCKOPT(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) != 0) {
  296. socket_error("setsockopt IP_MULTICAST_LOOP");
  297. return NULL;
  298. }
  299. #endif
  300. if (SETSOCKOPT(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &s->ttl, sizeof(s->ttl)) != 0) {
  301. socket_error("setsockopt IP_MULTICAST_TTL");
  302. return NULL;
  303. }
  304. if (iface_addr.s_addr != 0) {
  305. if (SETSOCKOPT(s->fd, IPPROTO_IP, IP_MULTICAST_IF, (char *) &iface_addr, sizeof(iface_addr)) != 0) {
  306. socket_error("setsockopt IP_MULTICAST_IF");
  307. return NULL;
  308. }
  309. }
  310. }
  311.         s->addr = strdup(addr);
  312. return s;
  313. }
  314. static void udp_exit4(socket_udp *s)
  315. {
  316. if (IN_MULTICAST(ntohl(s->addr4.s_addr))) {
  317. struct ip_mreq  imr;
  318. imr.imr_multiaddr.s_addr = s->addr4.s_addr;
  319. imr.imr_interface.s_addr = INADDR_ANY;
  320. if (SETSOCKOPT(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *) &imr, sizeof(struct ip_mreq)) != 0) {
  321. socket_error("setsockopt IP_DROP_MEMBERSHIP");
  322. abort();
  323. }
  324. rtp_message(LOG_INFO,  "Dropped membership of multicast group");
  325. }
  326. close(s->fd);
  327.         free(s->addr);
  328. free(s);
  329. }
  330. static int udp_send4(socket_udp *s, uint8_t *buffer, int buflen)
  331. {
  332. struct sockaddr_in s_in;
  333. ASSERT(s != NULL);
  334. ASSERT(s->mode == IPv4);
  335. ASSERT(buffer != NULL);
  336. ASSERT(buflen > 0);
  337. s_in.sin_family      = AF_INET;
  338. s_in.sin_addr.s_addr = s->addr4.s_addr;
  339. s_in.sin_port        = htons(s->tx_port);
  340. return sendto(s->fd, buffer, buflen, 0, (struct sockaddr *) &s_in, sizeof(s_in));
  341. }
  342. #ifndef _WIN32
  343. static int udp_send_iov4(socket_udp *s, struct iovec *iov, int count)
  344. {
  345. struct sockaddr_in s_in;
  346. struct msghdr  msg;
  347. ASSERT(s != NULL);
  348. ASSERT(s->mode == IPv4);
  349. ASSERT(iov != NULL);
  350. ASSERT(count > 0);
  351. s_in.sin_family      = AF_INET;
  352. s_in.sin_addr.s_addr = s->addr4.s_addr;
  353. s_in.sin_port        = htons(s->tx_port);
  354. memset(&msg, 0, sizeof(msg));
  355. msg.msg_name   = (void *)&s_in;
  356. msg.msg_namelen   = sizeof(s_in);
  357. msg.msg_iov   = iov;
  358. msg.msg_iovlen   = count;
  359. return sendmsg(s->fd, &msg, 0);
  360. }
  361. #endif
  362. static char *udp_host_addr4(void)
  363. {
  364.   char      hname[MAXHOSTNAMELEN];
  365.   struct hostent  *hent;
  366.   struct in_addr    iaddr;
  367. if (gethostname(hname, MAXHOSTNAMELEN) != 0) {
  368. rtp_message(LOG_ERR, "Cannot get hostname!");
  369. abort();
  370. }
  371. hent = gethostbyname(hname);
  372. if (hent == NULL) {
  373. socket_error("Can't resolve IP address for %s", hname);
  374. return NULL;
  375. }
  376. ASSERT(hent->h_addrtype == AF_INET);
  377. memcpy(&iaddr.s_addr, hent->h_addr, sizeof(iaddr.s_addr));
  378. strncpy(hname, inet_ntoa(iaddr), MAXHOSTNAMELEN);
  379. return xstrdup(hname);
  380. }
  381. /*****************************************************************************/
  382. /* IPv6 specific functions...                                                */
  383. /*****************************************************************************/
  384. static int udp_addr_valid6(const char *dst)
  385. {
  386. #ifdef HAVE_IPv6
  387.         struct in6_addr addr6;
  388. switch (inet_pton(AF_INET6, dst, &addr6)) {
  389.         case 1:  
  390.                 return TRUE;
  391.                 break;
  392.         case 0: 
  393.                 return FALSE;
  394.                 break;
  395.         case -1: 
  396.                 rtp_message(LOG_ERR, "inet_pton failed");
  397.                 errno = 0;
  398.         }
  399. #endif /* HAVE_IPv6 */
  400.         UNUSED(dst);
  401.         return FALSE;
  402. }
  403. static socket_udp *udp_init6(const char *addr, const char *iface, uint16_t rx_port, uint16_t tx_port, int ttl)
  404. {
  405. #ifdef HAVE_IPv6
  406. int                 reuse = 1;
  407. struct sockaddr_in6 s_in;
  408. socket_udp         *s = (socket_udp *) malloc(sizeof(socket_udp));
  409. s->mode    = IPv6;
  410. s->addr    = NULL;
  411. s->rx_port = rx_port;
  412. s->tx_port = tx_port;
  413. s->ttl     = ttl;
  414. if (iface != NULL) {
  415. debug_msg("Not yet implementedn");
  416. abort();
  417. }
  418. if (inet_pton(AF_INET6, addr, &s->addr6) != 1) {
  419. /* We should probably try to do a DNS lookup on the name */
  420. /* here, but I'm trying to get the basics going first... */
  421. debug_msg("IPv6 address conversion failedn");
  422.                 free(s);
  423. return NULL;
  424. }
  425. s->fd = socket(AF_INET6, SOCK_DGRAM, 0);
  426. if (s->fd < 0) {
  427. socket_error("socket");
  428. return NULL;
  429. }
  430. if (SETSOCKOPT(s->fd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse, sizeof(reuse)) != 0) {
  431. socket_error("setsockopt SO_REUSEADDR");
  432. return NULL;
  433. }
  434. #ifdef SO_REUSEPORT
  435. if (SETSOCKOPT(s->fd, SOL_SOCKET, SO_REUSEPORT, (char *) &reuse, sizeof(reuse)) != 0) {
  436. socket_error("setsockopt SO_REUSEPORT");
  437. return NULL;
  438. }
  439. #endif
  440. memset((char *)&s_in, 0, sizeof(s_in));
  441. s_in.sin6_family = AF_INET6;
  442. s_in.sin6_port   = htons(rx_port);
  443. #ifdef HAVE_SIN6_LEN
  444. s_in.sin6_len    = sizeof(s_in);
  445. #endif
  446. s_in.sin6_addr = in6addr_any;
  447. if (bind(s->fd, (struct sockaddr *) &s_in, sizeof(s_in)) != 0) {
  448. socket_error("bind");
  449. return NULL;
  450. }
  451. if (IN6_IS_ADDR_MULTICAST(&(s->addr6))) {
  452. unsigned int      loop = 1;
  453. struct ipv6_mreq  imr;
  454. #ifdef MUSICA_IPV6
  455. imr.i6mr_interface = 1;
  456. imr.i6mr_multiaddr = s->addr6;
  457. #else
  458. imr.ipv6mr_multiaddr = s->addr6;
  459. imr.ipv6mr_interface = 0;
  460. #endif
  461. if (SETSOCKOPT(s->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *) &imr, sizeof(struct ipv6_mreq)) != 0) {
  462. socket_error("setsockopt IPV6_ADD_MEMBERSHIP");
  463. return NULL;
  464. }
  465. if (SETSOCKOPT(s->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &loop, sizeof(loop)) != 0) {
  466. socket_error("setsockopt IPV6_MULTICAST_LOOP");
  467. return NULL;
  468. }
  469. if (SETSOCKOPT(s->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &ttl, sizeof(ttl)) != 0) {
  470. socket_error("setsockopt IPV6_MULTICAST_HOPS");
  471. return NULL;
  472. }
  473. }
  474. ASSERT(s != NULL);
  475.         s->addr = strdup(addr);
  476. return s;
  477. #else
  478. UNUSED(addr);
  479. UNUSED(iface);
  480. UNUSED(rx_port);
  481. UNUSED(tx_port);
  482. UNUSED(ttl);
  483. return NULL;
  484. #endif
  485. }
  486. static void udp_exit6(socket_udp *s)
  487. {
  488. #ifdef HAVE_IPv6
  489. if (IN6_IS_ADDR_MULTICAST(&(s->addr6))) {
  490. struct ipv6_mreq  imr;
  491. #ifdef MUSICA_IPV6
  492. imr.i6mr_interface = 1;
  493. imr.i6mr_multiaddr = s->addr6;
  494. #else
  495. imr.ipv6mr_multiaddr = s->addr6;
  496. imr.ipv6mr_interface = 0;
  497. #endif
  498. if (SETSOCKOPT(s->fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (char *) &imr, sizeof(struct ipv6_mreq)) != 0) {
  499. socket_error("setsockopt IPV6_DROP_MEMBERSHIP");
  500. abort();
  501. }
  502. }
  503. close(s->fd);
  504.         free(s->addr);
  505. free(s);
  506. #else
  507. UNUSED(s);
  508. #endif  /* HAVE_IPv6 */
  509. }
  510. static int udp_send6(socket_udp *s, uint8_t *buffer, int buflen)
  511. {
  512. #ifdef HAVE_IPv6
  513. struct sockaddr_in6 s_in;
  514. ASSERT(s != NULL);
  515. ASSERT(s->mode == IPv6);
  516. ASSERT(buffer != NULL);
  517. ASSERT(buflen > 0);
  518. memset((char *)&s_in, 0, sizeof(s_in));
  519. s_in.sin6_family = AF_INET6;
  520. s_in.sin6_addr   = s->addr6;
  521. s_in.sin6_port   = htons(s->tx_port);
  522. #ifdef HAVE_SIN6_LEN
  523. s_in.sin6_len    = sizeof(s_in);
  524. #endif
  525. return sendto(s->fd, buffer, buflen, 0, (struct sockaddr *) &s_in, sizeof(s_in));
  526. #else
  527. UNUSED(s);
  528. UNUSED(buffer);
  529. UNUSED(buflen);
  530. return -1;
  531. #endif
  532. }
  533. #ifndef _WIN32
  534. static int udp_send_iov6(socket_udp *s, struct iovec *iov, int count)
  535. {
  536. #ifdef HAVE_IPv6
  537. struct sockaddr_in6 s_in;
  538. struct msghdr msg;
  539. ASSERT(s != NULL);
  540. ASSERT(s->mode == IPv6);
  541. memset((char *)&s_in, 0, sizeof(s_in));
  542. s_in.sin6_family = AF_INET6;
  543. s_in.sin6_addr   = s->addr6;
  544. s_in.sin6_port   = htons(s->tx_port);
  545. #ifdef HAVE_SIN6_LEN
  546. s_in.sin6_len    = sizeof(s_in);
  547. #endif
  548. msg.msg_name   = &s_in;
  549. msg.msg_namelen   = sizeof(s_in);
  550. msg.msg_iov   = iov;
  551. msg.msg_iovlen   = count;
  552. msg.msg_control   = NULL;
  553. msg.msg_controllen   = 0;
  554. msg.msg_flags   = 0;
  555. return sendmsg(s->fd, &msg, 0);
  556. #else
  557. UNUSED(s);
  558. UNUSED(iov);
  559. UNUSED(count);
  560. return -1;
  561. #endif
  562. }
  563. #endif
  564. static char *udp_host_addr6(socket_udp *s)
  565. {
  566. #ifdef HAVE_IPv6
  567. char  hname[MAXHOSTNAMELEN];
  568. int   gai_err, newsock;
  569. struct addrinfo   hints, *ai;
  570. struct sockaddr_in6   local, addr6;
  571. int len = sizeof(local), result = 0;
  572. newsock=socket(AF_INET6, SOCK_DGRAM,0);
  573.     memset ((char *)&addr6, 0, len);
  574.     addr6.sin6_family = AF_INET6;
  575. #ifdef HAVE_SIN6_LEN
  576.     addr6.sin6_len    = len;
  577. #endif
  578.     bind (newsock, (struct sockaddr *) &addr6, len);
  579.     addr6.sin6_addr = s->addr6;
  580.     addr6.sin6_port = htons (s->rx_port);
  581.     connect (newsock, (struct sockaddr *) &addr6, len);
  582.     memset ((char *)&local, 0, len);
  583. if ((result = getsockname(newsock,(struct sockaddr *)&local, &len)) < 0){
  584. local.sin6_addr = in6addr_any;
  585. local.sin6_port = 0;
  586. debug_msg("getsockname failedn");
  587. }
  588. close (newsock);
  589. if (IN6_IS_ADDR_UNSPECIFIED(&local.sin6_addr) || IN6_IS_ADDR_MULTICAST(&local.sin6_addr)) {
  590. if (gethostname(hname, MAXHOSTNAMELEN) != 0) {
  591. debug_msg("gethostname failedn");
  592. abort();
  593. }
  594. hints.ai_protocol  = 0;
  595. hints.ai_flags     = 0;
  596. hints.ai_family    = AF_INET6;
  597. hints.ai_socktype  = SOCK_DGRAM;
  598. hints.ai_addrlen   = 0;
  599. hints.ai_canonname = NULL;
  600. hints.ai_addr      = NULL;
  601. hints.ai_next      = NULL;
  602. if ((gai_err = getaddrinfo(hname, NULL, &hints, &ai))) {
  603. debug_msg("getaddrinfo: %s: %sn", hname, gai_strerror(gai_err));
  604. abort();
  605. }
  606. if (inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)(ai->ai_addr))->sin6_addr), hname, MAXHOSTNAMELEN) == NULL) {
  607. debug_msg("inet_ntop: %s: n", hname);
  608. abort();
  609. }
  610. freeaddrinfo(ai);
  611. return xstrdup(hname);
  612. }
  613. if (inet_ntop(AF_INET6, &local.sin6_addr, hname, MAXHOSTNAMELEN) == NULL) {
  614. debug_msg("inet_ntop: %s: n", hname);
  615. abort();
  616. }
  617. return xstrdup(hname);
  618. #else  /* HAVE_IPv6 */
  619. UNUSED(s);
  620. return xstrdup("::"); /* The unspecified address... */
  621. #endif /* HAVE_IPv6 */
  622. }
  623. /*****************************************************************************/
  624. /* Generic functions, which call the appropriate protocol specific routines. */
  625. /*****************************************************************************/
  626. /**
  627.  * udp_addr_valid:
  628.  * @addr: string representation of IPv4 or IPv6 network address.
  629.  *
  630.  * Returns TRUE if @addr is valid, FALSE otherwise.
  631.  **/
  632. int udp_addr_valid(const char *addr)
  633. {
  634.         return udp_addr_valid4(addr) | udp_addr_valid6(addr);
  635. }
  636. /**
  637.  * udp_init:
  638.  * @addr: character string containing an IPv4 or IPv6 network address.
  639.  * @rx_port: receive port.
  640.  * @tx_port: transmit port.
  641.  * @ttl: time-to-live value for transmitted packets.
  642.  *
  643.  * Creates a session for sending and receiving UDP datagrams over IP
  644.  * networks. 
  645.  *
  646.  * Returns: a pointer to a valid socket_udp structure on success, NULL otherwise.
  647.  **/
  648. socket_udp *udp_init(const char *addr, uint16_t rx_port, uint16_t tx_port, int ttl)
  649. {
  650. return udp_init_if(addr, NULL, rx_port, tx_port, ttl);
  651. }
  652. /**
  653.  * udp_init_if:
  654.  * @addr: character string containing an IPv4 or IPv6 network address.
  655.  * @iface: character string containing an interface name.
  656.  * @rx_port: receive port.
  657.  * @tx_port: transmit port.
  658.  * @ttl: time-to-live value for transmitted packets.
  659.  *
  660.  * Creates a session for sending and receiving UDP datagrams over IP
  661.  * networks.  The session uses @iface as the interface to send and
  662.  * receive datagrams on.
  663.  * 
  664.  * Return value: a pointer to a socket_udp structure on success, NULL otherwise.
  665.  **/
  666. socket_udp *udp_init_if(const char *addr, const char *iface, uint16_t rx_port, uint16_t tx_port, int ttl)
  667. {
  668. socket_udp *res;
  669. if (strchr(addr, ':') == NULL) {
  670. res = udp_init4(addr, iface, rx_port, tx_port, ttl);
  671. } else {
  672. res = udp_init6(addr, iface, rx_port, tx_port, ttl);
  673. }
  674. return res;
  675. }
  676. /**
  677.  * udp_exit:
  678.  * @s: UDP session to be terminated.
  679.  *
  680.  * Closes UDP session.
  681.  * 
  682.  **/
  683. void udp_exit(socket_udp *s)
  684. {
  685.     switch(s->mode) {
  686.     case IPv4 : udp_exit4(s); break;
  687.     case IPv6 : udp_exit6(s); break;
  688.     default   : abort();
  689.     }
  690. }
  691. /**
  692.  * udp_send:
  693.  * @s: UDP session.
  694.  * @buffer: pointer to buffer to be transmitted.
  695.  * @buflen: length of @buffer.
  696.  * 
  697.  * Transmits a UDP datagram containing data from @buffer.
  698.  * 
  699.  * Return value: 0 on success, -1 on failure.
  700.  **/
  701. int udp_send(socket_udp *s, uint8_t *buffer, int buflen)
  702. {
  703. switch (s->mode) {
  704. case IPv4 : return udp_send4(s, buffer, buflen);
  705. case IPv6 : return udp_send6(s, buffer, buflen);
  706. default   : abort(); /* Yuk! */
  707. }
  708. return -1;
  709. }
  710. #ifndef _WIN32
  711. int udp_send_iov(socket_udp *s, struct iovec *iov, int count)
  712. {
  713. switch (s->mode) {
  714. case IPv4 : return udp_send_iov4(s, iov, count);
  715. case IPv6 : return udp_send_iov6(s, iov, count);
  716. default   : abort();
  717. }
  718. return -1;
  719. }
  720. #endif
  721. /**
  722.  * udp_recv:
  723.  * @s: UDP session.
  724.  * @buffer: buffer to read data into.
  725.  * @buflen: length of @buffer.
  726.  * 
  727.  * Reads from datagram queue associated with UDP session.
  728.  *
  729.  * Return value: number of bytes read, returns 0 if no data is available.
  730.  **/
  731. int udp_recv(socket_udp *s, uint8_t *buffer, int buflen)
  732. {
  733. /* Reads data into the buffer, returning the number of bytes read.   */
  734. /* If no data is available, this returns the value zero immediately. */
  735. /* Note: since we don't care about the source address of the packet  */
  736. /* we receive, this function becomes protocol independent.           */
  737. int len;
  738. ASSERT(buffer != NULL);
  739. ASSERT(buflen > 0);
  740. len = recvfrom(s->fd, buffer, buflen, 0, 0, 0);
  741. if (len > 0) {
  742. return len;
  743. }
  744. if (errno != ECONNREFUSED) {
  745. socket_error("recvfrom");
  746. }
  747. return 0;
  748. }
  749. static fd_set rfd;
  750. static fd_t max_fd;
  751. /**
  752.  * udp_fd_zero:
  753.  * 
  754.  * Clears file descriptor from set associated with UDP sessions (see select(2)).
  755.  * 
  756.  **/
  757. void udp_fd_zero(void)
  758. {
  759. FD_ZERO(&rfd);
  760. max_fd = 0;
  761. }
  762. /**
  763.  * udp_fd_set:
  764.  * @s: UDP session.
  765.  * 
  766.  * Adds file descriptor associated of @s to set associated with UDP sessions.
  767.  **/
  768. void udp_fd_set(socket_udp *s)
  769. {
  770. FD_SET(s->fd, &rfd);
  771. if (s->fd > (fd_t)max_fd) {
  772. max_fd = s->fd;
  773. }
  774. }
  775. /**
  776.  * udp_fd_isset:
  777.  * @s: UDP session.
  778.  * 
  779.  * Checks if file descriptor associated with UDP session is ready for
  780.  * reading.  This function should be called after udp_select().
  781.  *
  782.  * Returns: non-zero if set, zero otherwise.
  783.  **/
  784. int udp_fd_isset(socket_udp *s)
  785. {
  786. return FD_ISSET(s->fd, &rfd);
  787. }
  788. /**
  789.  * udp_select:
  790.  * @timeout: maximum period to wait for data to arrive.
  791.  * 
  792.  * Waits for data to arrive for UDP sessions.
  793.  * 
  794.  * Return value: number of UDP sessions ready for reading.
  795.  **/
  796. int udp_select(struct timeval *timeout)
  797. {
  798. return select(max_fd + 1, &rfd, NULL, NULL, timeout);
  799. }
  800. /**
  801.  * udp_host_addr:
  802.  * @s: UDP session.
  803.  * 
  804.  * Return value: character string containing network address
  805.  * associated with session @s.
  806.  **/
  807. char *udp_host_addr(socket_udp *s)
  808. {
  809.   if (s && s->mode == IPv6) {
  810.     return udp_host_addr6(s);
  811.   } 
  812.   return udp_host_addr4();
  813. }
  814. /**
  815.  * udp_fd:
  816.  * @s: UDP session.
  817.  * 
  818.  * This function allows applications to apply their own socketopt()'s
  819.  * and ioctl()'s to the UDP session.
  820.  * 
  821.  * Return value: file descriptor of socket used by session @s.
  822.  **/
  823. int udp_fd(socket_udp *s)
  824. {
  825. if (s && s->fd > 0) {
  826. return s->fd;
  827. return 0;
  828. }