Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion include/zone.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ struct zone_string {
const char *data;
};

// FIXME: probably best to rename this to mnemonic to stay with DNS terminology?
typedef struct zone_symbol zone_symbol_t;
struct zone_symbol {
struct {
Expand Down Expand Up @@ -230,7 +231,8 @@ typedef enum {
// ZONE_EUI64 (ZONE_HEX8?)
// miscellaneous fields
ZONE_SVC_PARAM, /**< SVCB service parameter */
ZONE_TYPE_BITMAP /**< NSEC type bitmap */
ZONE_TYPE_BITMAP, /**< NSEC type bitmap */
ZONE_SERVICE_BITMAP /**< WKS service bitmap */
} zone_type_t;

/**
Expand Down
1 change: 1 addition & 0 deletions src/fallback/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "fallback/eui.h"
#include "fallback/nsap.h"
#include "generic/wks.h"
#include "generic/loc.h"
#include "types.h"
#include "fallback/type.h"
#include "parser.h"
Expand Down
249 changes: 249 additions & 0 deletions src/generic/loc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
/*
* loc.h -- Location Information (RFC1876) parser
*
* Copyright (c) 2023, NLnet Labs. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef LOC_H
#define LOC_H

zone_nonnull_all
static zone_really_inline int32_t scan_degrees(
const char *text, size_t length, uint32_t *degrees)
{
uint8_t digits[3];

digits[0] = (uint8_t)text[0] - '0';
digits[1] = (uint8_t)text[1] - '0';
digits[2] = (uint8_t)text[2] - '0';

switch (length) {
case 1:
*degrees = digits[0] * 3600000;
if (digits[0] > 9)
return -1;
return 0;
case 2:
*degrees = digits[0] * 36000000 + digits[1] * 3600000;
if (digits[0] > 9 || digits[1] > 9)
return -1;
return 0;
case 3:
*degrees = digits[0] * 360000000 +
digits[1] * 36000000 +
digits[2] * 3600000;
if (*degrees > 648000000u)
return -1;
if (digits[0] > 9 || digits[1] > 9 || digits[2] > 9)
return -1;
return 0;
default:
return -1;
}
}

zone_nonnull_all
static zone_really_inline int64_t scan_minutes(
const char *text, size_t length, uint32_t *minutes)
{
uint8_t digits[2];

digits[0] = (uint8_t)text[0] - '0';
digits[1] = (uint8_t)text[1] - '0';

switch (length) {
case 1:
*minutes = digits[0] * 60000;
if (digits[0] > 9)
return -1;
return 0;
case 2:
*minutes = digits[0] * 600000 + digits[1] * 60000;
if (*minutes > 3600000 || digits[0] > 9 || digits[1] > 9)
return -1;
return 0;
default:
return -1;
}
}

zone_nonnull_all
static zone_really_inline int64_t scan_seconds(
const char *text, size_t length, uint32_t *seconds)
{
uint8_t digits[3];
size_t count;

digits[0] = (uint8_t)text[0] - '0';
digits[1] = (uint8_t)text[1] - '0';

if (length == 1 || text[1] == '.') {
count = 1;
*seconds = digits[0] * 1000;
if (digits[0] > 9)
return -1;
digits[0] = (uint8_t)text[2] - '0';
digits[1] = (uint8_t)text[3] - '0';
digits[2] = (uint8_t)text[4] - '0';
} else if (length == 2 || text[2] == '.') {
count = 2;
*seconds = digits[0] * 10000 + digits[1] * 1000;
if (*seconds > 60000 || digits[0] > 5 || digits[1] > 9)
return -1;
digits[0] = (uint8_t)text[3] - '0';
digits[1] = (uint8_t)text[4] - '0';
digits[2] = (uint8_t)text[5] - '0';
} else {
return -1;
}

switch (length - count) {
case 0:
return 0;
case 1:
return -1;
case 2:
*seconds += digits[0] * 100u;
if (digits[0] > 9)
return -1;
return 0;
case 3:
*seconds += digits[0] * 100u + digits[1] * 10u;
if (digits[0] > 9 || digits[1] > 9)
return -1;
return 0;
case 4:
*seconds += digits[0] * 100u + digits[1] * 10u + digits[2];
if (digits[0] > 9 || digits[1] > 9 || digits[0] > 9)
return -1;
return 0;
default:
return -1;
}
}

zone_nonnull((1,3))
static zone_really_inline int32_t scan_altitude(
const char *text, size_t length, uint32_t *altitude)
{
uint64_t negative = 0, limit = 11, maximum = 4284967295llu;

if (text[0] == '-')
(void)(negative = 1), (void)(limit = 8), maximum = 10000000llu;

length -= (text[length - 1] == 'm');

uint64_t meters = 0, index = negative;
for (;; index++) {
const uint8_t digit = (uint8_t)text[index] - '0';
if (digit > 9)
break;
meters = meters * 10 + digit;
}

uint64_t centimeters = meters * 100u; // convert to centimeters
if (text[index] == '.') {
uint8_t digits[2];
limit += 1;
digits[0] = (uint8_t)text[index+1] - '0';
digits[1] = (uint8_t)text[index+2] - '0';
switch (length - index) {
case 1:
index += 1;
break;
case 2:
if (digits[0] > 9)
return -1;
centimeters += (uint64_t)digits[0] * 10u;
index += 2;
break;
case 3:
if (digits[0] > 9 || digits[1] > 9)
return -1;
centimeters += (uint64_t)digits[0] * 10u + (uint64_t)digits[1];
index += 3;
break;
default:
return -1;
}
}

if (index == negative || index > limit || index != length || centimeters > maximum)
return -1;

if (negative)
*altitude = (uint32_t)(10000000llu - centimeters);
else
*altitude = (uint32_t)(10000000llu + centimeters);

return 0;
}

// converts ascii size/precision X * 10**Y(cm) to 0xXY
zone_nonnull((1,3))
static zone_really_inline int32_t scan_precision(
const char *text, size_t length, uint8_t *scientific)
{
uint64_t meters = 0, centimeters;

// RFC1876 conversion routines
static uint64_t poweroften[10] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};

length -= text[length - 1] == 'm';

size_t index = 0;
for (;; index++) {
const uint8_t digit = (uint8_t)text[index] - '0';
if (digit > 9)
break;
meters = meters * 10 + digit;
}

if (index == 0 || index > 8) // 0 .. 90000000.00
return -1; // syntax error

centimeters = meters * 100; // convert to centimeters
if (text[index] == '.') {
uint8_t digits[2];
digits[0] = (uint8_t)text[index+1] - '0';
digits[1] = (uint8_t)text[index+2] - '0';
switch (length - index) {
case 1:
index += 1;
break;
case 2:
if (digits[0] > 9)
return -1;
index += 2;
centimeters += digits[0] * 10;
break;
case 3:
if (digits[0] > 9 || digits[1] > 9)
return -1;
index += 3;
centimeters += digits[0] * 10 + digits[1];
break;
default:
return -1;
}
}

if (index != length)
return -1; // syntax error

uint8_t exponent = 0;
while (centimeters > poweroften[exponent+1] && exponent < 9)
exponent++;

uint8_t mantissa = (uint8_t)(centimeters / poweroften[exponent]);
if (mantissa > 9u)
mantissa = 9u;

*scientific = (uint8_t)(mantissa << 4) | exponent;
return 0;
}

#endif // LOC_H
1 change: 1 addition & 0 deletions src/haswell/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "fallback/eui.h"
#include "fallback/nsap.h"
#include "generic/wks.h"
#include "generic/loc.h"
#include "types.h"
#include "westmere/type.h"
#include "parser.h"
Expand Down
Loading