import from HEAD:
[freeradius.git] / src / main / radclient.c
index 6ffd200..cd1d937 100644 (file)
@@ -66,7 +66,7 @@ static int totallost = 0;
 
 static int server_port = 0;
 static int packet_code = 0;
-static lrad_ipaddr_t server_ipaddr;
+static uint32_t server_ipaddr = 0;
 static int resend_count = 1;
 static int done = 1;
 
@@ -98,7 +98,7 @@ static radclient_t *radclient_head = NULL;
 static radclient_t *radclient_tail = NULL;
 
 
-static void usage(void)
+static void NEVER_RETURNS usage(void)
 {
        fprintf(stderr, "Usage: radclient [options] server[:port] <command> [<secret>]\n");
 
@@ -116,8 +116,6 @@ static void usage(void)
        fprintf(stderr, "  -t timeout  Wait 'timeout' seconds before retrying (may be a floating point number).\n");
        fprintf(stderr, "  -v          Show program version information.\n");
        fprintf(stderr, "  -x          Debugging mode.\n");
-       fprintf(stderr, "  -4          Use IPv4 address of server\n");
-       fprintf(stderr, "  -6          Use IPv6 address of server.\n");
 
        exit(1);
 }
@@ -221,12 +219,12 @@ static radclient_t *radclient_init(const char *filename)
                 *      Keep a copy of the the User-Password attribute.
                 */
                if ((vp = pairfind(radclient->request->vps, PW_PASSWORD)) != NULL) {
-                       strNcpy(radclient->password, (char *)vp->strvalue, sizeof(vp->strvalue));
+                       strNcpy(radclient->password, (char *)vp->strvalue, sizeof(radclient->password));
                        /*
                         *      Otherwise keep a copy of the CHAP-Password attribute.
                         */
                } else if ((vp = pairfind(radclient->request->vps, PW_CHAP_PASSWORD)) != NULL) {
-                       strNcpy(radclient->password, (char *)vp->strvalue, sizeof(vp->strvalue));
+                       strNcpy(radclient->password, (char *)vp->strvalue, sizeof(radclient->password));
                } else {
                        radclient->password[0] = '\0';
                }
@@ -251,34 +249,6 @@ static radclient_t *radclient_init(const char *filename)
                                radclient->request->dst_port = (vp->lvalue & 0xffff);
                                break;
 
-                       case PW_PACKET_DST_IP_ADDRESS:
-                               radclient->request->dst_ipaddr.af = AF_INET;
-                               radclient->request->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->lvalue;
-                               break;
-
-                       case PW_PACKET_DST_IPV6_ADDRESS:
-                               radclient->request->dst_ipaddr.af = AF_INET6;
-                               memcpy(&radclient->request->dst_ipaddr.ipaddr.ip6addr,
-                                      vp->strvalue,
-                                      sizeof(radclient->request->dst_ipaddr.ipaddr.ip6addr));
-                               break;
-
-                       case PW_PACKET_SRC_PORT:
-                               radclient->request->src_port = (vp->lvalue & 0xffff);
-                               break;
-
-                       case PW_PACKET_SRC_IP_ADDRESS:
-                               radclient->request->src_ipaddr.af = AF_INET;
-                               radclient->request->src_ipaddr.ipaddr.ip4addr.s_addr = vp->lvalue;
-                               break;
-
-                       case PW_PACKET_SRC_IPV6_ADDRESS:
-                               radclient->request->src_ipaddr.af = AF_INET6;
-                               memcpy(&radclient->request->src_ipaddr.ipaddr.ip6addr,
-                                      vp->strvalue,
-                                      sizeof(radclient->request->src_ipaddr.ipaddr.ip6addr));
-                               break;
-
                        case PW_DIGEST_REALM:
                        case PW_DIGEST_NONCE:
                        case PW_DIGEST_METHOD:
@@ -326,14 +296,8 @@ static int radclient_sane(radclient_t *radclient)
        if (radclient->request->dst_port == 0) {
                radclient->request->dst_port = server_port;
        }
-       if (radclient->request->dst_ipaddr.af == AF_UNSPEC) {
-               if (server_ipaddr.af == AF_UNSPEC) {
-                       fprintf(stderr, "radclient: No server was given, but request %d in file %s did not contain Packet-Dst-IP-Address\n",
-                               radclient->packet_number, radclient->filename);
-                       return -1;
-               }
-               radclient->request->dst_ipaddr = server_ipaddr;
-       }
+       radclient->request->dst_ipaddr = server_ipaddr;
+
        if (radclient->request->code == 0) {
                if (packet_code == -1) {
                        fprintf(stderr, "radclient: Request was \"auto\", but request %d in file %s did not contain Packet-Type\n",
@@ -399,7 +363,6 @@ static int filename_walk(void *context, void *data)
  */
 static int request_cmp(const void *one, const void *two)
 {
-       int rcode;
        const radclient_t *a = one;
        const radclient_t *b = two;
 
@@ -410,25 +373,8 @@ static int request_cmp(const void *one, const void *two)
        if (a->request->id < b->request->id) return -1;
        if (a->request->id > b->request->id) return +1;
 
-       if (a->request->dst_ipaddr.af < b->request->dst_ipaddr.af) return -1;
-       if (a->request->dst_ipaddr.af > b->request->dst_ipaddr.af) return +1;
-
-       switch (a->request->dst_ipaddr.af) {
-       case AF_INET:
-               rcode = memcmp(&a->request->dst_ipaddr.ipaddr.ip4addr,
-                              &b->request->dst_ipaddr.ipaddr.ip4addr,
-                              sizeof(a->request->dst_ipaddr.ipaddr.ip4addr));
-               break;
-       case AF_INET6:
-               rcode = memcmp(&a->request->dst_ipaddr.ipaddr.ip6addr,
-                              &b->request->dst_ipaddr.ipaddr.ip6addr,
-                              sizeof(a->request->dst_ipaddr.ipaddr.ip6addr));
-               break;
-       default:                /* FIXME: die! */
-               return -1;
-               break;
-       }
-       if (rcode != 0) return rcode;
+       if (a->request->dst_ipaddr < b->request->dst_ipaddr) return -1;
+       if (a->request->dst_ipaddr > b->request->dst_ipaddr) return +1;
 
        if (a->request->dst_port < b->request->dst_port) return -1;
        if (a->request->dst_port > b->request->dst_port) return +1;
@@ -535,12 +481,12 @@ static int send_one_packet(radclient_t *radclient)
                        VALUE_PAIR *vp;
 
                        if ((vp = pairfind(radclient->request->vps, PW_PASSWORD)) != NULL) {
-                               strNcpy((char *)vp->strvalue, radclient->password, strlen(radclient->password) + 1);
-                               vp->length = strlen(radclient->password);
+                               strNcpy((char *)vp->strvalue, radclient->password, sizeof(vp->strvalue));
+                               vp->length = strlen(vp->strvalue);
 
                        } else if ((vp = pairfind(radclient->request->vps, PW_CHAP_PASSWORD)) != NULL) {
-                               strNcpy((char *)vp->strvalue, radclient->password, strlen(radclient->password) + 1);
-                               vp->length = strlen(radclient->password);
+                               strNcpy((char *)vp->strvalue, radclient->password, sizeof(vp->strvalue));
+                               vp->length = strlen(vp->strvalue);
 
                                rad_chap_encode(radclient->request, (char *) vp->strvalue, radclient->request->id, vp);
                                vp->length = 17;
@@ -623,7 +569,10 @@ static int send_one_packet(radclient_t *radclient)
        /*
         *      Send the packet.
         */
-       rad_send(radclient->request, NULL, secret);
+       if (rad_send(radclient->request, NULL, secret) < 0) {
+               fprintf(stderr, "radclient: Failed to send packet for ID %d: %s\n",
+                       radclient->request->id, librad_errstr);
+       }
 
        return 0;
 }
@@ -663,8 +612,7 @@ static int recv_one_packet(int wait_time)
         */
        reply = rad_recv(sockfd);
        if (!reply) {
-               fprintf(stderr, "radclient: received bad packet: %s\n",
-                       librad_errstr);
+               fprintf(stderr, "radclient: received bad packet\n");
                return -1;      /* bad packet */
        }
 
@@ -676,6 +624,7 @@ static int recv_one_packet(int wait_time)
        node = rbtree_find(request_tree, &myclient);
        if (!node) {
                fprintf(stderr, "radclient: received response to request we did not send.\n");
+               rad_free(&reply);
                return -1;      /* got reply to packet we didn't send */
        }
 
@@ -694,7 +643,7 @@ static int recv_one_packet(int wait_time)
        if (rad_decode(reply, radclient->request, secret) != 0) {
                librad_perror("rad_decode");
                totallost++;
-               return -1;
+               goto packet_done; /* shared secret is incorrect */
        }
 
        /* libradius debug already prints out the value pairs for us */
@@ -709,7 +658,8 @@ static int recv_one_packet(int wait_time)
                totaldeny++;
        }
 
-       if (radclient->reply) rad_free(&radclient->reply);
+packet_done:
+       rad_free(&radclient->reply);
 
        /*
         *      Once we've sent the packet as many times as requested,
@@ -723,7 +673,6 @@ static int recv_one_packet(int wait_time)
        return 0;
 }
 
-
 static int getport(const char *name)
 {
        struct  servent         *svp;
@@ -747,10 +696,6 @@ int main(int argc, char **argv)
        int persec = 0;
        int parallel = 1;
        radclient_t     *this;
-       int force_af = AF_UNSPEC;
-       int len = 0;
-        struct sockaddr_storage ss;
-        struct sockaddr_in *s4;
 
        librad_debug = 0;
 
@@ -766,13 +711,7 @@ int main(int argc, char **argv)
                exit(1);
        }
 
-       while ((c = getopt(argc, argv, "46c:d:f:hi:n:p:qr:sS:t:vx")) != EOF) switch(c) {
-               case '4':
-                       force_af = AF_INET;
-                       break;
-               case '6':
-                       force_af = AF_INET6;
-                       break;
+       while ((c = getopt(argc, argv, "c:d:f:hi:n:p:qr:sS:t:vx")) != EOF) switch(c) {
                case 'c':
                        if (!isdigit((int) *optarg))
                                usage();
@@ -874,46 +813,20 @@ int main(int argc, char **argv)
        }
 
        /*
-        *      Resolve hostname.
+        *      Strip port from hostname if needed.
         */
-       server_ipaddr.af = force_af;
-       if (strcmp(argv[1], "-") != 0) {
-               const char *hostname = argv[1];
-               const char *portname = argv[1];
-               char buffer[256];
-
-               if (*argv[1] == '[') { /* IPv6 URL encoded */
-                       p = strchr(argv[1], ']');
-                       if ((p - argv[1]) >= sizeof(buffer)) {
-                               usage();
-                       }
-                       
-                       memcpy(buffer, argv[1] + 1, p - argv[1] - 1);
-                       buffer[p - argv[1] - 1] = '\0';
-
-                       hostname = buffer;
-                       portname = p + 1;
-
-               }
-               p = strchr(portname, ':');
-               if (p && (strchr(p + 1, ':') == NULL)) {
-                       *p = '\0';
-                       portname = p + 1;
-               } else {
-                       portname = NULL;
-               }
-
-               if (ip_hton(hostname, force_af, &server_ipaddr) < 0) {
-                       fprintf(stderr, "radclient: Failed to find IP address for host %s: %s\n", argv[1], strerror(errno));
-                       exit(1);
-               }
-
-               /*
-                *      Strip port from hostname if needed.
-                */
-               if (portname) server_port = atoi(portname);
+       if ((p = strchr(argv[1], ':')) != NULL) {
+               *p++ = 0;
+               server_port = atoi(p);
        }
 
+       /*
+        *      Grab the socket.
+        */
+       if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+               perror("radclient: socket: ");
+               exit(1);
+       }
        memset(radius_id, 0, sizeof(radius_id));
 
        /*
@@ -956,6 +869,15 @@ int main(int argc, char **argv)
        }
 
        /*
+        *      Resolve hostname.
+        */
+       server_ipaddr = ip_getaddr(argv[1]);
+       if (server_ipaddr == INADDR_NONE) {
+               fprintf(stderr, "radclient: Failed to find IP address for host %s\n", argv[1]);
+               exit(1);
+       }
+
+       /*
         *      Add the secret.
         */
        if (argv[3]) secret = argv[3];
@@ -983,57 +905,6 @@ int main(int argc, char **argv)
        }
 
        /*
-        * Bind only if Packet-Src-IP(v6)Address Attribute is found
-        */
-       switch (radclient_head->request->src_ipaddr.af) {
-       case AF_UNSPEC:
-       default:
-               /*
-                *      Grab the socket.
-                */
-               if ((sockfd = socket(server_ipaddr.af, SOCK_DGRAM, 0)) < 0) {
-                       perror("radclient: socket: ");
-                       exit(1);
-               }
-               break;
-
-#ifdef HAVE_STRUCT_SOCKADDR_IN6
-       case AF_INET6:
-               {
-                       struct sockaddr_in6 *s6;
-                       s6 = (struct sockaddr_in6 *)&ss;
-                       len = sizeof(struct sockaddr_in6);
-                       s6->sin6_family = AF_INET6;
-                       s6->sin6_flowinfo = 0;
-                       s6->sin6_port = htons(radclient_head->request->src_port);
-                       memcpy(&s6->sin6_addr, &radclient_head->request->src_ipaddr.ipaddr, 16);
-               }
-               goto sock_bind;
-#endif
-
-       case AF_INET:
-               s4 = (struct sockaddr_in *)&ss;
-               len = sizeof(struct sockaddr_in);
-               s4->sin_family = AF_INET;
-               s4->sin_port = htons(radclient_head->request->src_port);
-               memcpy(&s4->sin_addr, &radclient_head->request->src_ipaddr.ipaddr, 4);
-               goto sock_bind;
-
-       sock_bind:
-               if ((sockfd = socket(radclient_head->request->src_ipaddr.af,
-                                SOCK_DGRAM, 0)) < 0) {
-
-                       perror("radclient: socket: ");
-                       exit(1);
-               }
-               if (bind(sockfd, (struct sockaddr *)&ss, len) < 0) {
-                       perror("radclient: bind: ");
-                       exit(1);
-               }
-               break;
-       }
-
-       /*
         *      Walk over the list of packets, sanity checking
         *      everything.
         */