update hash based on client port, too
authorAlan T. DeKok <aland@freeradius.org>
Sun, 5 Feb 2017 14:38:34 +0000 (09:38 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Sun, 5 Feb 2017 14:38:34 +0000 (09:38 -0500)
src/main/detail.c
src/main/realms.c

index fdc9e6d..633364f 100644 (file)
@@ -433,6 +433,7 @@ int detail_recv(rad_listen_t *listener)
 
 static RADIUS_PACKET *detail_poll(rad_listen_t *listener)
 {
+       int             y;
        char            key[256], op[8], value[1024];
        vp_cursor_t     cursor;
        VALUE_PAIR      *vp;
@@ -553,7 +554,28 @@ open_file:
                /*
                 *      Else go read something.
                 */
-               break;
+               if (!fgets(buffer, sizeof(buffer), data->fp)) {
+                       DEBUG("detail (%s): Failed reading header from file - %s",
+                             data->name, data->filename_work);
+                       goto cleanup;
+               }
+
+               /*
+                *      Badly formatted file: delete it.
+                */
+               if (!strchr(buffer, '\n')) {
+                       DEBUG("detail (%s): Invalid line without trailing LF - %s", data->name, buffer);
+                       goto cleanup;
+               }
+
+               if (!sscanf(buffer, "%*s %*s %*d %*d:%*d:%*d %d", &y)) {
+                       DEBUG("detail (%s): Failed reading detail file header in line - %s", data->name, buffer);
+                       goto cleanup;
+               }
+
+               data->state = STATE_READING;
+               /* FALL-THROUGH */
+
 
        /*
         *      Read more value-pair's, unless we're
@@ -561,10 +583,145 @@ open_file:
         *      we have.
         */
        case STATE_READING:
-               if (data->fp && !feof(data->fp)) break;
-               data->state = STATE_QUEUED;
+               rad_assert(data->fp != NULL);
 
-               /* FALL-THROUGH */
+               fr_cursor_init(&cursor, &data->vps);
+
+               /*
+                *      Read a header, OR a value-pair.
+                */
+               while (fgets(buffer, sizeof(buffer), data->fp)) {
+                       data->last_offset = data->offset;
+                       data->offset = ftell(data->fp); /* for statistics */
+
+                       /*
+                        *      Badly formatted file: delete it.
+                        */
+                       if (!strchr(buffer, '\n')) {
+                               WARN("detail (%s): Skipping line without trailing LF - %s", data->name, buffer);
+                               fr_pair_list_free(&data->vps);
+                               goto cleanup;
+                       }
+
+                       /*
+                        *      We're reading VP's, and got a blank line.
+                        *      That indicates the end of an entry.  Queue the
+                        *      packet.
+                        */
+                       if (buffer[0] == '\n') {
+                               data->state = STATE_QUEUED;
+                               data->tries = 0;
+                               data->packets++;
+                               goto alloc_packet;
+                       }
+
+                       /*
+                        *      We have a full "attribute = value" line.
+                        *      If it doesn't look reasonable, skip it.
+                        *
+                        *      FIXME: print an error for badly formatted attributes?
+                        */
+                       if (sscanf(buffer, "%255s %7s %1023s", key, op, value) != 3) {
+                               DEBUG("detail (%s): Skipping badly formatted line - %s", data->name, buffer);
+                               continue;
+                       }
+
+                       /*
+                        *      Should be =, :=, +=, ...
+                        */
+                       if (!strchr(op, '=')) {
+                               DEBUG("detail (%s): Skipping line without operator - %s", data->name, buffer);
+                               continue;
+                       }
+
+                       /*
+                        *      Skip non-protocol attributes.
+                        */
+                       if (!strcasecmp(key, "Request-Authenticator")) continue;
+
+                       /*
+                        *      Set the original client IP address, based on
+                        *      what's in the detail file.
+                        *
+                        *      Hmm... we don't set the server IP address.
+                        *      or port.  Oh well.
+                        */
+                       if (!strcasecmp(key, "Client-IP-Address")) {
+                               data->client_ip.af = AF_INET;
+                               if (ip_hton(&data->client_ip, AF_INET, value, false) < 0) {
+                                       DEBUG("detail (%s): Failed parsing Client-IP-Address", data->name);
+                                       fr_pair_list_free(&data->vps);
+                                       goto cleanup;
+                               }
+                               continue;
+                       }
+
+                       /*
+                        *      The original time at which we received the
+                        *      packet.  We need this to properly calculate
+                        *      Acct-Delay-Time.
+                        */
+                       if (!strcasecmp(key, "Timestamp")) {
+                               data->timestamp = atoi(value);
+                               data->timestamp_offset = data->last_offset;
+
+                               vp = fr_pair_afrom_num(data, PW_PACKET_ORIGINAL_TIMESTAMP, 0);
+                               if (vp) {
+                                       vp->vp_date = (uint32_t) data->timestamp;
+                                       vp->type = VT_DATA;
+                                       fr_cursor_insert(&cursor, vp);
+                               }
+                               continue;
+                       }
+
+                       if (!strcasecmp(key, "Donestamp")) {
+                               data->timestamp = atoi(value);
+                               data->done_entry = true;
+                               continue;
+                       }
+
+                       DEBUG3("detail (%s): Trying to read VP from line - %s", data->name, buffer);
+
+                       /*
+                        *      Read one VP.
+                        *
+                        *      FIXME: do we want to check for non-protocol
+                        *      attributes like radsqlrelay does?
+                        */
+                       vp = NULL;
+                       if ((fr_pair_list_afrom_str(data, buffer, &vp) > 0) &&
+                           (vp != NULL)) {
+                               fr_cursor_merge(&cursor, vp);
+                       } else {
+                               DEBUG("detail (%s): Failed reading VP from line - %s", data->name, buffer);
+                               goto cleanup;
+                       }
+               }
+
+               /*
+                *      The writer doesn't check that the
+                *      record was completely written.  If the
+                *      disk is full, this can result in a
+                *      truncated record which has no trailing
+                *      blank line.  When that happens, it's a
+                *      bad record, and we ignore it.
+                */
+               if (feof(data->fp)) {
+                       DEBUG("detail (%s): Truncated record: treating it as EOF for detail file %s",
+                             data->name, data->filename_work);
+                       fr_pair_list_free(&data->vps);
+                       goto cleanup;
+               }
+
+               /*
+                *      Some kind of non-eof error.
+                *
+                *      FIXME: Leave the file in-place, and warn the
+                *      administrator?
+                */
+               DEBUG("detail (%s): Unknown error, deleting detail file %s",
+                     data->name, data->filename_work);
+               goto cleanup;
 
        case STATE_QUEUED:
                goto alloc_packet;
@@ -600,18 +757,18 @@ open_file:
                        rad_assert(data->fp != NULL);
 
                        if (fseek(data->fp, data->timestamp_offset, SEEK_SET) < 0) {
-                               WARN("detail (%s): Failed seeking to timestamp offset: %s",
+                               DEBUG("detail (%s): Failed seeking to timestamp offset: %s",
                                     data->name, fr_syserror(errno));
                        } else if (fwrite("\tDone", 1, 5, data->fp) < 5) {
-                               WARN("detail (%s): Failed marking request as done: %s",
+                               DEBUG("detail (%s): Failed marking request as done: %s",
                                     data->name, fr_syserror(errno));
                        } else if (fflush(data->fp) != 0) {
-                               WARN("detail (%s): Failed flushing marked detail file to disk: %s",
+                               DEBUG("detail (%s): Failed flushing marked detail file to disk: %s",
                                     data->name, fr_syserror(errno));
                        }
 
                        if (fseek(data->fp, data->offset, SEEK_SET) < 0) {
-                               WARN("detail (%s): Failed seeking to next detail request: %s",
+                               DEBUG("detail (%s): Failed seeking to next detail request: %s",
                                     data->name, fr_syserror(errno));
                        }
                }
@@ -621,143 +778,6 @@ open_file:
                goto do_header;
        }
 
-       fr_cursor_init(&cursor, &data->vps);
-
-       /*
-        *      Read a header, OR a value-pair.
-        */
-       while (fgets(buffer, sizeof(buffer), data->fp)) {
-               data->last_offset = data->offset;
-               data->offset = ftell(data->fp); /* for statistics */
-
-               /*
-                *      Badly formatted file: delete it.
-                *
-                *      FIXME: Maybe flag an error?
-                */
-               if (!strchr(buffer, '\n')) {
-                       fr_pair_list_free(&data->vps);
-                       goto cleanup;
-               }
-
-               /*
-                *      We're reading VP's, and got a blank line.
-                *      Queue the packet.
-                */
-               if ((data->state == STATE_READING) &&
-                   (buffer[0] == '\n')) {
-                       data->state = STATE_QUEUED;
-                       break;
-               }
-
-               /*
-                *      Look for date/time header, and read VP's if
-                *      found.  If not, keep reading lines until we
-                *      find one.
-                */
-               if (data->state == STATE_HEADER) {
-                       int y;
-
-                       if (sscanf(buffer, "%*s %*s %*d %*d:%*d:%*d %d", &y)) {
-                               data->state = STATE_READING;
-                       }
-                       continue;
-               }
-
-               /*
-                *      We have a full "attribute = value" line.
-                *      If it doesn't look reasonable, skip it.
-                *
-                *      FIXME: print an error for badly formatted attributes?
-                */
-               if (sscanf(buffer, "%255s %7s %1023s", key, op, value) != 3) {
-                       WARN("detail (%s): Skipping badly formatted line - %s", data->name, buffer);
-                       continue;
-               }
-
-               /*
-                *      Should be =, :=, +=, ...
-                */
-               if (!strchr(op, '=')) {
-                       WARN("detail (%s): Skipping line without operator - %s", data->name, buffer);
-                       continue;
-               }
-
-               /*
-                *      Skip non-protocol attributes.
-                */
-               if (!strcasecmp(key, "Request-Authenticator")) continue;
-
-               /*
-                *      Set the original client IP address, based on
-                *      what's in the detail file.
-                *
-                *      Hmm... we don't set the server IP address.
-                *      or port.  Oh well.
-                */
-               if (!strcasecmp(key, "Client-IP-Address")) {
-                       data->client_ip.af = AF_INET;
-                       if (ip_hton(&data->client_ip, AF_INET, value, false) < 0) {
-                               ERROR("detail (%s): Failed parsing Client-IP-Address", data->name);
-
-                               fr_pair_list_free(&data->vps);
-                               goto cleanup;
-                       }
-                       continue;
-               }
-
-               /*
-                *      The original time at which we received the
-                *      packet.  We need this to properly calculate
-                *      Acct-Delay-Time.
-                */
-               if (!strcasecmp(key, "Timestamp")) {
-                       data->timestamp = atoi(value);
-                       data->timestamp_offset = data->last_offset;
-
-                       vp = fr_pair_afrom_num(data, PW_PACKET_ORIGINAL_TIMESTAMP, 0);
-                       if (vp) {
-                               vp->vp_date = (uint32_t) data->timestamp;
-                               vp->type = VT_DATA;
-                               fr_cursor_insert(&cursor, vp);
-                       }
-                       continue;
-               }
-
-               if (!strcasecmp(key, "Donestamp")) {
-                       data->timestamp = atoi(value);
-                       data->done_entry = true;
-                       continue;
-               }
-
-               DEBUG3("detail (%s): Trying to read VP from line - %s", data->name, buffer);
-
-               /*
-                *      Read one VP.
-                *
-                *      FIXME: do we want to check for non-protocol
-                *      attributes like radsqlrelay does?
-                */
-               vp = NULL;
-               if ((fr_pair_list_afrom_str(data, buffer, &vp) > 0) &&
-                   (vp != NULL)) {
-                       fr_cursor_merge(&cursor, vp);
-               } else {
-                       WARN("detail (%s): Failed reading VP from line - %s", data->name, buffer);
-               }
-       }
-
-       /*
-        *      Some kind of error.
-        *
-        *      FIXME: Leave the file in-place, and warn the
-        *      administrator?
-        */
-       if (ferror(data->fp)) goto cleanup;
-
-       data->tries = 0;
-       data->packets++;
-
        /*
         *      Process the packet.
         */
@@ -772,19 +792,6 @@ open_file:
        data->tries++;
 
        /*
-        *      The writer doesn't check that the record was
-        *      completely written.  If the disk is full, this can
-        *      result in a truncated record.  When that happens,
-        *      treat it as EOF.
-        */
-       if (data->state != STATE_QUEUED) {
-               ERROR("detail (%s): Truncated record: treating it as EOF for detail file %s",
-                     data->name, data->filename_work);
-               fr_pair_list_free(&data->vps);
-               goto cleanup;
-       }
-
-       /*
         *      We're done reading the file, but we didn't read
         *      anything.  Clean up, and don't return anything.
         */
@@ -792,7 +799,6 @@ open_file:
                WARN("detail (%s): Read empty packet from file %s",
                     data->name, data->filename_work);
                data->state = STATE_HEADER;
-               if (!data->fp || feof(data->fp)) goto cleanup;
                return NULL;
        }
 
index 738e69a..9275512 100644 (file)
@@ -2443,8 +2443,8 @@ home_server_t *home_server_ldb(char const *realmname,
                        hash = 0;
                        break;
                }
-               fr_hash_update(&request->packet->src_port,
-                                sizeof(request->packet->src_port), hash);
+               hash = fr_hash_update(&request->packet->src_port,
+                                     sizeof(request->packet->src_port), hash);
                start = hash % pool->num_home_servers;
                break;