/*
* $Id: libnet_port_list.c,v 1.1.1.3 2023/09/27 11:11:38 misho Exp $
*
* libnet
* libnet_port_list.c - transport layer port list chaining code
*
* Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include "common.h"
uint16_t *all_lists;
int
libnet_plist_chain_new(libnet_t *l, libnet_plist_t **plist, char *token_list)
{
char libnet_plist_legal_tokens[] = "0123456789,- ";
libnet_plist_t *tmp;
char *tok;
int i, j, valid_token, cur_node;
uint16_t *all_lists_tmp;
static uint8_t cur_id;
if (l == NULL)
{
return (-1);
}
if (token_list == NULL)
{
return (-1);
}
/*
* Make sure we have legal tokens.
*/
for (i = 0; token_list[i]; i++)
{
for (j = 0, valid_token = 0; libnet_plist_legal_tokens[j]; j++)
{
if (libnet_plist_legal_tokens[j] == token_list[i])
{
valid_token = 1;
break;
}
}
if (!valid_token)
{
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
"libnet_build_plist_chain: illegal token # %d (%c)",
i + 1,
token_list[i]);
*plist = NULL;
return (-1);
}
}
/* head node */
*plist = malloc(sizeof (libnet_plist_t));
if (!(*plist))
{
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
"libnet_build_plist_chain: malloc %s", strerror(errno));
*plist = NULL;
return (-1);
}
tmp = *plist;
tmp->node = cur_node = 0;
tmp->next = NULL;
tmp->id = cur_id;
all_lists_tmp = all_lists;
all_lists = realloc(all_lists_tmp, (sizeof(uint16_t) * (cur_id + 1)));
if (!all_lists)
{
all_lists = all_lists_tmp;
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
"libnet_build_plist_chain: realloc %s", strerror(errno));
*plist = NULL;
return(-1);
}
all_lists[cur_id++] = 0;
/*
* Using strtok successively proved problematic. We solve this by
* calling it once, then manually extracting the elements from the token.
* In the case of bport > eport, we swap them.
*/
for (i = 0; (tok = strtok(!i ? token_list : NULL, ",")); i = 1, cur_node++)
{
/*
* The first iteration we will have a head node allocated so we don't
* need to malloc().
*/
if (i)
{
tmp->next = malloc(sizeof (libnet_plist_t));
if (!tmp->next)
{
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
"libnet_build_plist_chain: malloc %s", strerror(errno));
/*
* XXX - potential memory leak if other nodes are allocated
* but not freed.
*/
*plist = NULL;
return(-1);
}
tmp = tmp->next;
tmp->node = cur_node;
tmp->next = NULL;
}
tmp->bport = atoi(tok);
/*
* Step past this port number.
*/
j = 0;
while (isdigit((int)tok[j]))
{
j++;
}
/*
* If we have a delimiting dash and are NOT at the end of the token
* array, we can assume it's the end port, otherwise if we just have
* a dash, we consider it int16_thand for `inclusive of all ports up to
* 65535. Finally, if we have no dash, we assume this token is a
* single port only.
*/
if (tok[j] == '-')
{
tmp->eport = (++j != strlen(tok)) ? atoi(&tok[j]) : 65535;
}
else
{
tmp->eport = tmp->bport;
}
/*
* Do we need to swap the values?
*/
if (tmp->bport > tmp->eport)
{
tmp->bport ^= tmp->eport;
tmp->eport ^= tmp->bport;
tmp->bport ^= tmp->eport;
}
}
/*
* The head node needs to hold the total node count.
*/
(*plist)->node = cur_node;
return (1);
}
int
libnet_plist_chain_next_pair(libnet_plist_t *plist, uint16_t *bport,
uint16_t *eport)
{
uint16_t *node_cnt;
uint16_t tmp_cnt;
if (plist == NULL)
{
return (-1);
}
node_cnt = &(all_lists[plist->id]);
/*
* We are at the end of the list.
*/
if (*node_cnt == plist->node)
{
*node_cnt = 0;
*bport = 0;
*eport = 0;
return (0);
}
for (tmp_cnt = *node_cnt; tmp_cnt; tmp_cnt--, plist = plist->next) ;
*bport = plist->bport;
*eport = plist->eport;
*node_cnt += 1;
return (1);
}
int
libnet_plist_chain_dump(libnet_plist_t *plist)
{
if (plist == NULL)
{
return (-1);
}
for (; plist; plist = plist->next)
{
if (plist->bport == plist->eport)
{
fprintf(stdout, "%d ", plist->bport);
}
else
{
fprintf(stdout, "%d-%d ", plist->bport, plist->eport);
}
}
fprintf(stdout, "\n");
return (1);
}
char *
libnet_plist_chain_dump_string(libnet_plist_t *plist)
{
char buf[BUFSIZ] = {0};
int i, j;
if (plist == NULL)
{
return (NULL);
}
for (i = 0, j = 0; plist; plist = plist->next)
{
if (plist->bport == plist->eport)
{
i = snprintf(&buf[j], BUFSIZ, "%d", plist->bport);
}
else
{
i = snprintf(&buf[j], BUFSIZ, "%d-%d", plist->bport, plist->eport);
}
j += i;
if (plist->next)
{
snprintf(&buf[j++], BUFSIZ, ",");
}
}
return (strdup(buf)); /* XXX - reentrancy == no */
}
int
libnet_plist_chain_free(libnet_plist_t *plist)
{
uint16_t i;
libnet_plist_t *tmp;
if (plist == NULL)
{
return (-1);
}
for (i = plist->node; i; i--)
{
tmp = plist;
plist = plist->next;
free(tmp);
}
plist = NULL;
return (1);
}
/**
* Local Variables:
* indent-tabs-mode: nil
* c-file-style: "stroustrup"
* End:
*/
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>