newvector should be a bool
[freeradius.git] / src / lib / tcp.c
index 88720b3..186198c 100644 (file)
  * Copyright (C) 2009 Dante http://dante.net
  */
 
-#include       <freeradius-devel/ident.h>
 RCSID("$Id$")
 
 #include       <freeradius-devel/libradius.h>
-#include       <freeradius-devel/tcp.h>
 
 #ifdef WITH_TCP
 
@@ -32,96 +30,15 @@ RCSID("$Id$")
 #define MAX_PACKET_LEN 4096
 
 /*
- *     Open a socket on the given IP and port.
- */
-int fr_tcp_socket(fr_ipaddr_t *ipaddr, int port)
-{
-       int sockfd;
-       int on = 1;
-       struct sockaddr_storage salocal;
-       socklen_t       salen;
-
-       if ((port < 0) || (port > 65535)) {
-               fr_strerror_printf("Port %d is out of allowed bounds", port);
-               return -1;
-       }
-
-       sockfd = socket(ipaddr->af, SOCK_STREAM, 0);
-       if (sockfd < 0) {
-               return sockfd;
-       }
-
-       if (fr_nonblock(sockfd) < 0) {
-               close(sockfd);
-               return -1;
-       }
-
-       if (!fr_ipaddr2sockaddr(ipaddr, port, &salocal, &salen)) {
-               close(sockfd);
-               return -1;
-       }
-
-#ifdef HAVE_STRUCT_SOCKADDR_IN6
-       if (ipaddr->af == AF_INET6) {
-               /*
-                *      Listening on '::' does NOT get you IPv4 to
-                *      IPv6 mapping.  You've got to listen on an IPv4
-                *      address, too.  This makes the rest of the server
-                *      design a little simpler.
-                */
-#ifdef IPV6_V6ONLY
-
-               if (IN6_IS_ADDR_UNSPECIFIED(&ipaddr->ipaddr.ip6addr)) {
-                       if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
-                                      (char *)&on, sizeof(on)) < 0) {
-                               fr_strerror_printf("Failed in setsockopt(): %s",
-                                                  strerror(errno));
-                               close(sockfd);       
-                               return -1;
-                       } 
-               }
-#endif /* IPV6_V6ONLY */
-       }
-#endif /* HAVE_STRUCT_SOCKADDR_IN6 */
-
-       if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
-               fr_strerror_printf("Failed in setsockopt(): %s", strerror(errno));
-               close(sockfd);
-               return -1;
-       }
-       if (bind(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
-               fr_strerror_printf("Failed in bind(): %s", strerror(errno));
-               close(sockfd);
-               return -1;
-       }
-
-       if (listen(sockfd, 8) < 0) {
-               fr_strerror_printf("Failed in listen(): %s", strerror(errno));
-               close(sockfd);
-               return -1;
-       }
-
-       return sockfd;
-}
-
-
-/*
  *     Open a socket TO the given IP and port.
  */
 int fr_tcp_client_socket(fr_ipaddr_t *src_ipaddr,
-                        fr_ipaddr_t *dst_ipaddr, int dst_port)
+                        fr_ipaddr_t *dst_ipaddr, uint16_t dst_port)
 {
        int sockfd;
        struct sockaddr_storage salocal;
        socklen_t       salen;
 
-       if ((dst_port < 0) || (dst_port > 65535)) {
-               fr_strerror_printf("Port %d is out of allowed bounds",
-                                  dst_port);
-               return -1;
-       }
-
        if (!dst_ipaddr) return -1;
 
        sockfd = socket(dst_ipaddr->af, SOCK_STREAM, 0);
@@ -129,28 +46,6 @@ int fr_tcp_client_socket(fr_ipaddr_t *src_ipaddr,
                return sockfd;
        }
 
-#if 0
-#ifdef O_NONBLOCK
-       {
-               int flags;
-               
-               if ((flags = fcntl(sockfd, F_GETFL, NULL)) < 0)  {
-                       fr_strerror_printf("Failure getting socket flags: %s",
-                                  strerror(errno));
-                       close(sockfd);
-                       return -1;
-               }
-               
-               flags |= O_NONBLOCK;
-               if( fcntl(sockfd, F_SETFL, flags) < 0) {
-                       fr_strerror_printf("Failure setting socket flags: %s",
-                                  strerror(errno));
-                       close(sockfd);
-                       return -1;
-               }
-       }
-#endif
-#endif
        /*
         *      Allow the caller to bind us to a specific source IP.
         */
@@ -159,17 +54,17 @@ int fr_tcp_client_socket(fr_ipaddr_t *src_ipaddr,
                        close(sockfd);
                        return -1;
                }
-               
+
                if (bind(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
                        fr_strerror_printf("Failure binding to IP: %s",
-                                          strerror(errno));
+                                          fr_syserror(errno));
                        close(sockfd);
                        return -1;
                }
        }
 
        if (!fr_ipaddr2sockaddr(dst_ipaddr, dst_port, &salocal, &salen)) {
-                       close(sockfd);
+               close(sockfd);
                return -1;
        }
 
@@ -179,7 +74,7 @@ int fr_tcp_client_socket(fr_ipaddr_t *src_ipaddr,
         *      socket is ready...
         */
        if (connect(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
-               fr_strerror_printf("Failed in connect(): %s", strerror(errno));
+               fr_strerror_printf("Failed in connect(): %s", fr_syserror(errno));
                close(sockfd);
                return -1;
        }
@@ -190,7 +85,7 @@ int fr_tcp_client_socket(fr_ipaddr_t *src_ipaddr,
 
 RADIUS_PACKET *fr_tcp_recv(int sockfd, int flags)
 {
-       RADIUS_PACKET *packet = rad_alloc(0);
+       RADIUS_PACKET *packet = rad_alloc(NULL, false);
 
        if (!packet) return NULL;
 
@@ -241,7 +136,7 @@ int fr_tcp_read_packet(RADIUS_PACKET *packet, int flags)
 
                if (len < 0) {
                        fr_strerror_printf("Error receiving packet: %s",
-                                  strerror(errno));
+                                  fr_syserror(errno));
                        return -1;
                }
 
@@ -253,7 +148,7 @@ int fr_tcp_read_packet(RADIUS_PACKET *packet, int flags)
                packet_len = (packet->vector[2] << 8) | packet->vector[3];
 
                if (packet_len < AUTH_HDR_LEN) {
-                       fr_strerror_printf("Discarding packet: Smaller than RFC minimum of 20 bytes.");
+                       fr_strerror_printf("Discarding packet: Smaller than RFC minimum of 20 bytes");
                        return -1;
                }
 
@@ -261,11 +156,11 @@ int fr_tcp_read_packet(RADIUS_PACKET *packet, int flags)
                 *      If the packet is too big, then the socket is bad.
                 */
                if (packet_len > MAX_PACKET_LEN) {
-                       fr_strerror_printf("Discarding packet: Larger than RFC limitation of 4096 bytes.");
+                       fr_strerror_printf("Discarding packet: Larger than RFC limitation of 4096 bytes");
                        return -1;
                }
-               
-               packet->data = malloc(packet_len);
+
+               packet->data = talloc_array(packet, uint8_t, packet_len);
                if (!packet->data) {
                        fr_strerror_printf("Out of memory");
                        return -1;
@@ -290,7 +185,7 @@ int fr_tcp_read_packet(RADIUS_PACKET *packet, int flags)
 #endif
 
        if (len < 0) {
-               fr_strerror_printf("Error receiving packet: %s", strerror(errno));
+               fr_strerror_printf("Error receiving packet: %s", fr_syserror(errno));
                return -1;
        }
 
@@ -303,7 +198,7 @@ int fr_tcp_read_packet(RADIUS_PACKET *packet, int flags)
        /*
         *      See if it's a well-formed RADIUS packet.
         */
-       if (!rad_packet_ok(packet, flags)) {
+       if (!rad_packet_ok(packet, flags, NULL)) {
                return -1;
        }
 
@@ -327,11 +222,11 @@ int fr_tcp_read_packet(RADIUS_PACKET *packet, int flags)
                }
 
 
-               if ((packet->code > 0) && (packet->code < FR_MAX_PACKET_CODE)) {
-                       DEBUG("rad_recv: %s packet from %s",
+               if (is_radius_code(packet->code)) {
+                       DEBUG("Received %s packet from %s",
                              fr_packet_codes[packet->code], buffer);
                } else {
-                       DEBUG("rad_recv: Packet from %s code=%d",
+                       DEBUG("Received packet from %s code %d",
                              buffer, packet->code);
                }
                DEBUG(", id=%d, length=%zu\n", packet->id, packet->data_len);
@@ -340,91 +235,4 @@ int fr_tcp_read_packet(RADIUS_PACKET *packet, int flags)
        return 1;               /* done reading the packet */
 }
 
-RADIUS_PACKET *fr_tcp_accept(int sockfd)
-{
-       int newfd;
-       socklen_t salen;
-       RADIUS_PACKET *packet;
-       struct sockaddr_storage src;
-       
-       salen = sizeof(src);
-
-       newfd = accept(sockfd, (struct sockaddr *) &src, &salen);
-       if (newfd < 0) {
-               /*
-                *      Non-blocking sockets must handle this.
-                */
-#ifdef EWOULDBLOCK
-               if (errno == EWOULDBLOCK) {
-                       packet = rad_alloc(0);
-                       if (!packet) return NULL;
-
-                       packet->sockfd = sockfd;
-                       packet->src_ipaddr.af = AF_UNSPEC;
-                       return packet;
-               }
-#endif
-
-               return NULL;
-       }
-               
-       packet = rad_alloc(0);
-       if (!packet) return NULL;
-
-       if (src.ss_family == AF_INET) {
-               struct sockaddr_in      s4;
-
-               memcpy(&s4, &src, sizeof(s4));
-               packet->src_ipaddr.af = AF_INET;
-               packet->src_ipaddr.ipaddr.ip4addr = s4.sin_addr;
-               packet->src_port = ntohs(s4.sin_port);
-
-#ifdef HAVE_STRUCT_SOCKADDR_IN6
-       } else if (src.ss_family == AF_INET6) {
-               struct sockaddr_in6     s6;
-
-               memcpy(&s6, &src, sizeof(s6));
-               packet->src_ipaddr.af = AF_INET6;
-               packet->src_ipaddr.ipaddr.ip6addr = s6.sin6_addr;
-               packet->src_port = ntohs(s6.sin6_port);
-
-#endif
-       } else {
-               rad_free(&packet);
-               close(newfd);
-               return NULL;
-       }
-
-       packet->sockfd = newfd;
-
-       /*
-        *      Note: Caller has to set dst_ipaddr && dst_port.
-        */
-       return packet;
-}
-
-
-/*
- *     Writes a packet, assuming it's already been encoded.
- *
- *     It returns the number of bytes written, which MAY be less than
- *     the packet size (data_len).  It is the caller's responsibility
- *     to check the return code, and to schedule writes again.
- */
-ssize_t fr_tcp_write_packet(RADIUS_PACKET *packet)
-{
-       ssize_t rcode;
-
-       if (!packet || !packet->data) return 0;
-
-       if (packet->partial >= packet->data_len) return packet->data_len;
-
-       rcode = write(packet->sockfd, packet->data + packet->partial,
-                     packet->data_len - packet->partial);
-       if (rcode < 0) return packet->partial; /* ignore most errors */
-
-       packet->partial += rcode;
-
-       return packet->partial;
-}
 #endif /* WITH_TCP */