/****************************************************************************
** File: ns_labels.c
**
** Author: Mike Borella
**
** Comments: Encapsulation for ugly NS label manipulation
**
** $Id: ns_labels.c,v 1.3 2000/08/29 21:59:02 mborella Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Library General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
*****************************************************************************/
#include "ns_labels.h"
#define NUM_LABELS 128
int current_label = -1;
ns_label_t nslabels[NUM_LABELS];
/*----------------------------------------------------------------------------
**
** reset_nslabels()
**
** Initialize the NS labels structures
**
**----------------------------------------------------------------------------
*/
void reset_nslabels(void)
{
int i;
current_label = -1;
for (i=0; i<NUM_LABELS; i++)
{
nslabels[i].offset = 0;
nslabels[i].label[0] = '\0';
nslabels[i].next = -1;
}
}
/*----------------------------------------------------------------------------
**
** new_nslabel()
**
** A define a new NS label
**
**----------------------------------------------------------------------------
*/
void new_nslabel(void)
{
current_label++;
nslabels[current_label].offset = 0;
nslabels[current_label].label[0] = '\0';
nslabels[current_label].next = -1;
}
/*----------------------------------------------------------------------------
**
** set_nslabel_offset()
**
** Set the offset of a NS label
**
**----------------------------------------------------------------------------
*/
void set_nslabel_offset(int32_t o)
{
nslabels[current_label].offset = o;
}
/*----------------------------------------------------------------------------
**
** set_nslabel_label()
**
** Set a NS label
**
**----------------------------------------------------------------------------
*/
void set_nslabel_label(char *s)
{
strcpy(nslabels[current_label].label, s);
}
/*----------------------------------------------------------------------------
**
** set_nslabel_next()
**
** Set the next label
**
**----------------------------------------------------------------------------
*/
void set_nslabel_next(void)
{
nslabels[current_label].next = current_label+1;
}
/*----------------------------------------------------------------------------
**
** get_nslabel()
**
** Get a NS label and follow the chain of next pointers
**
**----------------------------------------------------------------------------
*/
void get_nslabel(int32_t o, char *s)
{
int i;
strcpy(s,"\0");
for (i=0; i<=current_label; i++)
if (nslabels[i].offset == o)
{
strcpy(s, nslabels[i].label);
if (nslabels[i].next >= 0)
{
strcat(s, ".");
get_nslabel(nslabels[nslabels[i].next].offset,
s+strlen(s));
}
strcat(s, "\0");
break;
}
}
/*----------------------------------------------------------------------------
**
** parse_ns_labels()
**
** Recursively parse a label entry in a DNS packet. We assume that the
** current byte of the packet points to the first label count. Store
** the DNS name in the string passed in, and let's assume that this string
** is big enough.
**
**----------------------------------------------------------------------------
*/
void parse_ns_labels(packet_t *pkt, char *name)
{
u_int8_t count;
u_int16_t offset;
int read_a_label = 0;
char label[MAX_LABEL_SIZE];
int first_offset = 0;
while(1)
{
if (get_packet_bytes((u_int8_t *) &count, pkt, 1) == 0)
return;
/*
* A count of 0 indicates an "end of string", so quit
*/
if (count == 0)
break;
/*
* Make sure that we don't run past the ned of label space in
* our structure - this should NOT be an issue, but if for some
* reason it is, it will cause *nasty* bugs...
*/
if (count > MAX_LABEL_SIZE && count < 192)
count = MAX_LABEL_SIZE;
/*
* This is a new label, so let's mark it as such
*/
if (read_a_label)
set_nslabel_next();
new_nslabel();
if (!first_offset)
{
first_offset = get_packet_markdistance(pkt)-1;
}
set_nslabel_offset(get_packet_markdistance(pkt)-1);
/*
* A count > 192 indicates a pointer. What an ugly way of
* saving a few bytes
*/
if (count >= 192)
{
/*
* There's a pointer in this label. Sigh. Let's grab the
* 14 low-order bits and run with them...
*/
offset = count - 192;
offset = offset << 8;
if (get_packet_bytes((u_int8_t *) &count, pkt, 1) == 0)
return;
offset = offset + count;
get_nslabel(offset, name);
set_nslabel_label(name);
return;
}
/*
* This is normal behavior, if anything is "normal" for DNS.
* Grab count bytes and stick them in the label string, follow it
* up with a "." to separate the hierarchy
*/
if (get_packet_bytes((u_int8_t *) &label, pkt, count ) == 0)
return;
label[count] = '\0';
set_nslabel_label(label);
read_a_label = 1;
}
get_nslabel(first_offset, name);
return;
}
syntax highlighted by Code2HTML, v. 0.9.1