/*
---------------------------------------------------------------------------
$Id: xml_tun.c,v 1.14 2007/04/25 19:31:54 cnepveu Exp $
---------------------------------------------------------------------------
Copyright (c) 2001-2007 Hexago Inc. All rights reserved
LICENSE NOTICE: You may use and modify this source code only if you
have executed a valid license agreement with Hexago Inc. granting
you the right to do so, the said license agreement governing such
use and modifications. Copyright or other intellectual property
notices are not to be removed from the source code.
---------------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "platform.h"
#include "xmlparse.h"
#define XMLTUN
#include "xml_tun.h"
#define TEST 0
/*
* Here are declarations of the appropriate treatment functions, taking care
* of the content of the nodes parsed. This is required to insure binding to the
* procedures in the node structure.
*
* Use the PROC macro to help insure proper declaration.
*/
PROC(tunnel);
PROC(server);
PROC(client);
PROC(broker);
PROC(address);
PROC(dns_server);
PROC(router);
PROC(prefix);
PROC(as);
PROC(keepalive);
/*
* Here we define a simple node structure containing only one entry
* corresponding to the root node.
*
* Such a structure must be created for each level of information that
* is part of the expected xml content.
*/
tNode Root[] =
STARTLIST
NODE(tunnel) ATTR(action) ATTR(type) ATTR(lifetime) ATTR(proxy) ATTR(mtu) ENDNODE
ENDLIST
tNode Tunnel[] =
STARTLIST
NODE(server) ENDNODE
NODE(client) ENDNODE
NODE(broker) ENDNODE
ENDLIST
tNode Server[] =
STARTLIST
NODE(address) ATTR(type) ENDNODE
NODE(router) ATTR(protocol) ENDNODE
ENDLIST
tNode Client[] =
STARTLIST
NODE(address) ATTR(type) ENDNODE
NODE(router) ATTR(protocol) ENDNODE
NODE(keepalive) ATTR(interval) ENDNODE
ENDLIST
tNode Router[] =
STARTLIST
NODE(prefix) ATTR(length) ENDNODE
NODE(dns_server) ATTR(type) ENDNODE
NODE(as) ATTR(number) ENDNODE
ENDLIST
tNode DNSServer[] =
STARTLIST
NODE(address) ATTR(type) ENDNODE
ENDLIST
tNode Broker[] =
STARTLIST
NODE(address) ATTR(type) ENDNODE
ENDLIST
tNode Keepalive[] =
STARTLIST
NODE(address) ATTR(type) ENDNODE
ENDLIST
/*
* Support functions
*/
static int Assign(char *str, char **toStr)
{
char *tol;
if (str == NULL) return 0;
/* turn answer to lower case */
/* should help homogenize */
/* scripting */
tol = str;
while (*tol != '\0') {
*tol = tolower(*tol);
tol++;
}
*toStr = (char *) malloc(strlen(str) + 1);
if (*toStr == NULL) {
printf("Assign: Memory allocation error!\n");
return -1;
}
strcpy(*toStr, str);
return 0;
}
static int AssignToList(char *str, tLinkedList **toList)
{
tLinkedList *ll;
if (str == NULL) return 0;
ll = (tLinkedList *) malloc(sizeof(tLinkedList));
if (ll == NULL) {
printf("AssignToList: Memory allocation error!\n");
return -1;
}
ll->Value = (char *) malloc(strlen(str) + 1);
if (ll->Value == NULL) {
printf("AssignToList: Memory allocation error!\n");
return -1;
}
strcpy(ll->Value, str);
ll->next = *toList;
*toList = ll;
return 0;
}
/*
* Here are defined every treatment functions required. use the PROC
* macro to help insure proper declaration.
*
* These event functions update the contain of the tTunnel instance with the
* information that is part of the XML structure.
*/
static tTunnel *theTunnelInfo;
static int
client,
server,
router,
dns_server,
broker,
keepalive;
PROC(default)
{
printf("Found <%s>%.10s%s</%s>\n", n->name, content, strlen(content) > 10 ? "..." : "", n->name);
return 0;
}
PROC(tunnel)
{
Assign(n->attributes[0].value, &theTunnelInfo->action );
Assign(n->attributes[1].value, &theTunnelInfo->type );
Assign(n->attributes[2].value, &theTunnelInfo->lifetime);
Assign(n->attributes[3].value, &theTunnelInfo->proxy );
Assign(n->attributes[4].value, &theTunnelInfo->mtu );
return XMLParse(content, Tunnel);
}
PROC(server)
{
int res;
server = 1;
res = XMLParse(content, Server);
server = 0;
return res;
}
PROC(broker)
{
int res;
broker = 1;
res = XMLParse(content, Broker);
broker = 0;
return res;
}
PROC(client)
{
int res;
client = 1;
res = XMLParse(content, Client);
client = 0;
return res;
}
PROC(dns_server)
{
int res;
dns_server = 1;
res = XMLParse(content, DNSServer);
dns_server = 0;
return res;
}
PROC(router)
{
int res;
router = 1;
Assign(n->attributes[0].value, &theTunnelInfo->router_protocol);
res = XMLParse(content, Router);
router = 0;
return res;
}
PROC(as)
{
if (client) {
Assign(n->attributes[0].value, &theTunnelInfo->client_as);
} else if (server) {
Assign(n->attributes[0].value, &theTunnelInfo->server_as);
}
return 0;
}
PROC(keepalive)
{
int res;
Assign(n->attributes[0].value, &theTunnelInfo->keepalive_interval);
keepalive = 1;
res = XMLParse(content, Keepalive);
keepalive = 0;
return res;
}
PROC(prefix) {
Assign(n->attributes[0].value, &theTunnelInfo->prefix_length);
Assign(content, &theTunnelInfo->prefix);
return 0;
}
PROC(address)
{
if (client) {
if (keepalive) {
if ((!strcmp(n->attributes[0].value, "ipv6")) ||
(!strcmp(n->attributes[0].value, "ipv4"))) {
Assign(content, &theTunnelInfo->keepalive_address);
}
}
else if (router) {
if (dns_server) {
if (!strcmp(n->attributes[0].value, "ipv4")) {
AssignToList(content, &theTunnelInfo->dns_server_address_ipv4);
} else if (!strcmp(n->attributes[0].value, "ipv6")) {
AssignToList(content, &theTunnelInfo->dns_server_address_ipv6);
}
}
} else {
if (!strcmp(n->attributes[0].value, "ipv4")) {
Assign(content, &theTunnelInfo->client_address_ipv4);
} else if (!strcmp(n->attributes[0].value, "ipv6")) {
Assign(content, &theTunnelInfo->client_address_ipv6);
} else if (!strcmp(n->attributes[0].value, "dn")) {
Assign(content, &theTunnelInfo->client_dns_name);
}
}
} else if (server) {
if (!strcmp(n->attributes[0].value, "ipv4")) {
Assign(content, &theTunnelInfo->server_address_ipv4);
} else if (!strcmp(n->attributes[0].value, "ipv6")) {
Assign(content, &theTunnelInfo->server_address_ipv6);
}
} else if (broker) {
if (!strcmp(n->attributes[0].value, "ipv4")) {
AssignToList(content, &theTunnelInfo->broker_redirect_ipv4);
}
else if (!strcmp(n->attributes[0].value, "ipv6")) {
AssignToList(content, &theTunnelInfo->broker_redirect_ipv6);
}
else if (!strcmp(n->attributes[0].value, "dn")) {
AssignToList(content, &theTunnelInfo->broker_redirect_dn);
}
}
return 0;
}
/* Put here any relevant code... */
void tspFree(char *var)
{
if (var) free(var);
}
void tspFreeLinkedList(tLinkedList *list)
{
if(list) {
if(list->next) {
tspFreeLinkedList(list->next);
free(list->next);
list->next = NULL;
}
if(list->Value) {
free(list->Value);
list->Value = NULL;
}
}
}
void tspClearTunnelInfo(tTunnel *Tunnel)
{
if (Tunnel) {
tspFree(Tunnel->action);
tspFree(Tunnel->type);
tspFree(Tunnel->lifetime);
tspFree(Tunnel->proxy);
tspFree(Tunnel->mtu);
tspFree(Tunnel->client_address_ipv4);
tspFree(Tunnel->client_address_ipv6);
tspFree(Tunnel->client_dns_name);
tspFree(Tunnel->server_address_ipv4);
tspFree(Tunnel->server_address_ipv6);
tspFree(Tunnel->router_protocol);
tspFree(Tunnel->prefix_length);
tspFree(Tunnel->prefix);
tspFree(Tunnel->client_as);
tspFree(Tunnel->server_as);
tspFree(Tunnel->keepalive_interval);
tspFree(Tunnel->keepalive_address);
tspFreeLinkedList(Tunnel->dns_server_address_ipv4);
tspFreeLinkedList(Tunnel->dns_server_address_ipv6);
tspFreeLinkedList(Tunnel->broker_address_ipv4);
tspFreeLinkedList(Tunnel->broker_redirect_ipv4);
tspFreeLinkedList(Tunnel->broker_redirect_ipv6);
tspFreeLinkedList(Tunnel->broker_redirect_dn);
}
}
void ShowList(tLinkedList *l)
{
int first = 1;
while (l != NULL) {
if (!first) printf(", ");
if (l->Value != NULL) printf("%s", l->Value);
l = l->next;
first = 0;
}
}
void tspXMLShowInfo(tTunnel *Tunnel)
{
printf("Parsed Info:\n\n");
printf(" action = [%s]\n", Tunnel->action == NULL ? "" : Tunnel->action );
printf(" type = [%s]\n", Tunnel->type == NULL ? "" : Tunnel->type );
printf(" lifetime = [%s]\n", Tunnel->lifetime == NULL ? "" : Tunnel->lifetime );
printf(" proxy = [%s]\n", Tunnel->proxy == NULL ? "" : Tunnel->proxy );
printf(" mtu = [%s]\n", Tunnel->mtu == NULL ? "" : Tunnel->mtu );
printf(" client address ipv4 = [%s]\n", Tunnel->client_address_ipv4 == NULL ? "" : Tunnel->client_address_ipv4);
printf(" client address ipv6 = [%s]\n", Tunnel->client_address_ipv6 == NULL ? "" : Tunnel->client_address_ipv6);
printf(" client dns name = [%s]\n", Tunnel->client_dns_name == NULL ? "" : Tunnel->client_dns_name );
printf(" server address ipv4 = [%s]\n", Tunnel->server_address_ipv4 == NULL ? "" : Tunnel->server_address_ipv4);
printf(" server address ipv6 = [%s]\n", Tunnel->server_address_ipv6 == NULL ? "" : Tunnel->server_address_ipv6);
printf(" router protocol = [%s]\n", Tunnel->router_protocol == NULL ? "" : Tunnel->router_protocol );
printf(" prefix length = [%s]\n", Tunnel->prefix_length == NULL ? "" : Tunnel->prefix_length );
printf(" prefix = [%s]\n", Tunnel->prefix == NULL ? "" : Tunnel->prefix );
printf(" client as number = [%s]\n", Tunnel->client_as == NULL ? "" : Tunnel->client_as );
printf(" server as number = [%s]\n", Tunnel->server_as == NULL ? "" : Tunnel->server_as );
printf(" keepalive interval = [%s]\n", Tunnel->keepalive_interval == NULL ? "" : Tunnel->keepalive_interval );
printf(" keepalive address = [%s]\n", Tunnel->keepalive_address == NULL ? "" : Tunnel->keepalive_address);
printf(" dns server addresse(s) ipv4 = ["); ShowList(Tunnel->dns_server_address_ipv4); printf("]\n");
printf(" dns server addresse(s) ipv6 = ["); ShowList(Tunnel->dns_server_address_ipv6); printf("]\n");
printf(" broker addresse(s) ipv4 = ["); ShowList(Tunnel->broker_address_ipv4); printf("]\n");
printf(" broker redirect ipv4 = ["); ShowList(Tunnel->broker_redirect_ipv4); printf("]\n");
printf(" broker redirect ipv6 = ["); ShowList(Tunnel->broker_redirect_ipv6); printf("]\n");
printf(" broker redirect dn = ["); ShowList(Tunnel->broker_redirect_dn); printf("]\n");
}
int tspXMLParse(char *Data, tTunnel *Tunnel)
{
tspClearTunnelInfo(Tunnel);
client = server = router = dns_server = broker = 0;
theTunnelInfo = Tunnel;
return XMLParse(Data, Root);
}
#if TEST
char *testData =
" <tunnel action=\"info\" type=\"v6v4\" lifetime=\"1440\" proxy=\"yes\" mtu=\"1280\">\n"
" <server>\n"
" <address type=\"ipv4\">206.123.31.114</address>\n"
" <address type=\"ipv6\">3ffe:b00:c18:ffff:0000:0000:0000:0000</address>\n"
" <router protocol=\"bgp\">\n"
" <as number=\"23456\"/>\n"
" </router>\n"
" </server>\n"
" <client>\n"
" <address type=\"ipv4\">1.1.1.1</address>\n"
" <address type=\"ipv6\">3ffe:b00:c18:ffff::0000:0000:0000:0001</address>\n"
" <address type=\"dn\">userid.domain</address>\n"
" <router protocol=\"bgp\">\n"
" <prefix length=\"48\">3ffe:0b00:c18:1234::</prefix>\n"
" <as number=\"12345\"/>\n"
" <dns_server>\n"
" <address type=\"ipv4\">2.3.4.5</address>\n"
" <address type=\"ipv4\">2.3.4.6</address>\n"
" <address type=\"ipv6\">3ffe:0c00::1</address>\n"
" </dns_server>\n"
" </router>\n"
" <keepalive interval=\"30\"><address type=\"ipv6\">::</address></keepalive>\n"
" </client>\n"
" </tunnel>\n";
main()
{
tTunnel t;
static char string[5000];
int res;
printf("Start....\n");
memset(&t, 0, sizeof(t));
strcpy(string, testData);
res = tspXMLParse(string, &t);
if (res != 0) {
printf("Result = %d\n", res);
}
tspXMLShowInfo(&t);
return 0;
}
#endif
/*----- xmltsp.c -----------------------------------------------------------------------*/
syntax highlighted by Code2HTML, v. 0.9.1