#include "parser.h" #include static xmlParserCtxtPtr ctxt; /* the parser context */ static xmlDocPtr doc; /* the resulting document tree */ static xmlXPathContextPtr xpctxt;/* the xpath context of main config file*/ /*Clear xml structures in memory*/ void free_xml() { xmlXPathFreeContext (xpctxt); xmlFreeDoc(doc); xmlFreeParserCtxt(ctxt); } /* Write value to proc entry * Return: 0 is ok */ static int write_proc(const char *file, const char *value) { int fd; ssize_t ret; if (file == NULL || value == NULL) return -1; fd = open(file,O_WRONLY); if (fd < 0) return -1; ret = write(fd,value,strlen(value)); if (ret < 0) { char error[100]; snprintf(error, sizeof(error)-1, "Error while trying to set proc entry %s to %s", file, value); perror(error); close(fd); exit(1); } close(fd); return 0; } /* If the tag ignor_autoconf if set, disable this feature by * setting the variables * /proc/sys/net/ipv6/conf/all/autoconf * /proc/sys/net/ipv6/conf/all/accept_ra * /proc/sys/net/ipv6/conf/all/accept_ra_defrtr * /proc/sys/net/ipv6/conf/all/accept_ra_pinfo * /proc/sys/net/ipv6/conf/all/accept_redirects * to 0 to avoid the monitoring host to be attacked */ void autoconf() { char *request ="/config_ndpmon/ignor_autoconf/text()"; char *flag; xmlXPathObjectPtr xmlobject = xmlXPathEval ((xmlChar*)request, xpctxt); flag = (char *)xmlobject->nodesetval->nodeTab[0]->content; ignor_autoconf = atoi(flag); /* Not working for BSD */ #ifdef _LINUX_ if( xmlobject != NULL) { /** note: it may be a good option to save values, and restore * them when exiting */ write_proc("/proc/sys/net/ipv6/conf/all/autoconf",flag); write_proc("/proc/sys/net/ipv6/conf/all/accept_ra",flag); write_proc("/proc/sys/net/ipv6/conf/all/accept_ra_defrtr",flag); write_proc("/proc/sys/net/ipv6/conf/all/accept_ra_pinfo",flag); write_proc("/proc/sys/net/ipv6/conf/all/accept_redirects",flag); } #endif xmlXPathFreeObject (xmlobject); return; } /* Parse settings for what to perform on what action */ void parse_actions() { char* request; xmlXPathObjectPtr xmlobject; request ="/config_ndpmon/actions_low_pri/sendmail/text()"; xmlobject = xmlXPathEval ((xmlChar*)request, xpctxt); if ((xmlobject->nodesetval==NULL) || (strcmp("1", (char*)xmlobject->nodesetval->nodeTab[0]->content)!=0)) action_low_pri.sendmail=0; else action_low_pri.sendmail=1; xmlXPathFreeObject (xmlobject); request ="/config_ndpmon/actions_low_pri/syslog/text()"; xmlobject = xmlXPathEval ((xmlChar*)request, xpctxt); if ((xmlobject->nodesetval==NULL) || (strcmp("1", (char*)xmlobject->nodesetval->nodeTab[0]->content)!=0)) action_low_pri.syslog=0; else action_low_pri.syslog=1; xmlXPathFreeObject (xmlobject); request ="/config_ndpmon/actions_low_pri/exec_pipe_program/text()"; xmlobject = xmlXPathEval ((xmlChar*)request, xpctxt); if (xmlobject->nodesetval==NULL) action_low_pri.exec_pipe_program=""; else action_low_pri.exec_pipe_program=strdup((char*)xmlobject->nodesetval->nodeTab[0]->content); xmlXPathFreeObject (xmlobject); request ="/config_ndpmon/actions_high_pri/sendmail/text()"; xmlobject = xmlXPathEval ((xmlChar*)request, xpctxt); if ((xmlobject->nodesetval==NULL) || (strcmp("1", (char*)xmlobject->nodesetval->nodeTab[0]->content)!=0)) action_high_pri.sendmail=0; else action_high_pri.sendmail=1; xmlXPathFreeObject (xmlobject); request ="/config_ndpmon/actions_high_pri/syslog/text()"; xmlobject = xmlXPathEval ((xmlChar*)request, xpctxt); if ((xmlobject->nodesetval==NULL) || (strcmp("1", (char*)xmlobject->nodesetval->nodeTab[0]->content)!=0)) action_high_pri.syslog=0; else action_high_pri.syslog=1; xmlXPathFreeObject (xmlobject); request ="/config_ndpmon/actions_high_pri/exec_pipe_program/text()"; xmlobject = xmlXPathEval ((xmlChar*)request, xpctxt); if (xmlobject->nodesetval==NULL) action_high_pri.exec_pipe_program=NULL; else action_high_pri.exec_pipe_program=strdup((char*)xmlobject->nodesetval->nodeTab[0]->content); xmlXPathFreeObject (xmlobject); return; } /* Should we do reverse DNS lookups on an action that is logged? */ void get_use_reverse_hostlookups() { char* request ="/config_ndpmon/use_reverse_hostlookups/text()"; xmlXPathObjectPtr xmlobject = xmlXPathEval ((xmlChar*)request, xpctxt); if ((xmlobject->nodesetval==NULL) || (strcmp("1", (char*)xmlobject->nodesetval->nodeTab[0]->content)!=0)) use_reverse_hostlookups=0; else use_reverse_hostlookups=1; xmlXPathFreeObject (xmlobject); return; } /*Admin mail from the config file to send warnings */ void get_mail() { char* request ="/config_ndpmon/admin_mail/text()"; xmlXPathObjectPtr xmlobject = xmlXPathEval ((xmlChar*)request, xpctxt); strcpy(admin_mail,(char*)xmlobject->nodesetval->nodeTab[0]->content); xmlXPathFreeObject (xmlobject); return; } /* Initialize the syslogging */ void init_syslog() { char *request ="/config_ndpmon/syslog_facility/text()"; char *value; int facility = -1; xmlXPathObjectPtr xmlobject = xmlXPathEval ((xmlChar*)request, xpctxt); value = (char *)xmlobject->nodesetval->nodeTab[0]->content; strcpy(syslog_facility,(char *)xmlobject->nodesetval->nodeTab[0]->content); if( !STRCMP(value,"LOG_LOCAL0") ) { facility = LOG_LOCAL0; } else if( !STRCMP(value,"LOG_LOCAL0") ) { facility = LOG_LOCAL0; } else if( !STRCMP(value,"LOG_LOCAL1") ) { facility = LOG_LOCAL1; } else if( !STRCMP(value,"LOG_LOCAL2") ) { facility = LOG_LOCAL2; } else if( !STRCMP(value,"LOG_LOCAL3") ) { facility = LOG_LOCAL3; } else if( !STRCMP(value,"LOG_LOCAL4") ) { facility = LOG_LOCAL4; } else if( !STRCMP(value,"LOG_LOCAL5") ) { facility = LOG_LOCAL5; } else if( !STRCMP(value,"LOG_LOCAL6") ) { facility = LOG_LOCAL6; } else if( !STRCMP(value,"LOG_LOCAL7") ) { facility = LOG_LOCAL7; } else if( !STRCMP(value,"LOG_USER") ) { facility = LOG_USER; } else if( !STRCMP(value,"LOG_MAIL") ) { facility = LOG_MAIL; } else if( !STRCMP(value,"LOG_DAEMON") ) { facility = LOG_DAEMON; } else if( !STRCMP(value,"LOG_AUTH") ) { facility = LOG_AUTH; } else if( !STRCMP(value,"LOG_SYSLOG") ) { facility = LOG_SYSLOG; } else if( !STRCMP(value,"LOG_LPR") ) { facility = LOG_LPR; } else if( !STRCMP(value,"LOG_NEWS") ) { facility = LOG_NEWS; } else if( !STRCMP(value,"LOG_UUCP") ) { facility = LOG_UUCP; } else if( !STRCMP(value,"LOG_CRON") ) { facility = LOG_CRON; } else if( !STRCMP(value,"LOG_AUTHPRIV") ) { facility = LOG_AUTHPRIV; } else if( !STRCMP(value,"LOG_FTP") ) { facility = LOG_FTP; } if (facility == -1) return; openlog ("NDPMon", LOG_NDELAY|LOG_CONS|LOG_PID, facility); syslog (LOG_NOTICE, "Program started by User %d", getuid ()); xmlXPathFreeObject (xmlobject); return; } /* * Routers * */ void parse_routers() { xmlDoc *doc = NULL; xmlNode *root_element = NULL; xmlNode *current = NULL; char* c; /*parse the file and get the DOM */ doc = xmlReadFile(config_path, NULL, 0); /*Get the root element node */ root_element = xmlDocGetRootElement(doc); current = root_element->children; while(current != NULL) { if (current->type == XML_ELEMENT_NODE) { if( !STRCMP(current->name,"routers") ) { xmlNode *router = current->children; while(router != NULL) { if (router->type == XML_ELEMENT_NODE) { if( !STRCMP(router->name,"router") ) { struct in6_addr lla; struct ether_addr mac; xmlNode *param = router->children; while(param != NULL) { if (param->type == XML_ELEMENT_NODE) { if( !STRCMP(param->name,"mac") ) { memcpy(&mac,ether_aton((char *)XML_GET_CONTENT(param->children)),sizeof(struct ether_addr)); } else if( !STRCMP(param->name,"lla") ) { inet_pton(AF_INET6,(char *)XML_GET_CONTENT(param->children), &lla); add_router(&routers, lla, mac); } else if( !STRCMP(param->name,"addresses") ) { xmlNode *address = param->children; while(address != NULL) { if (address->type == XML_ELEMENT_NODE) { if( !STRCMP(address->name,"address") ) { struct in6_addr addr; inet_pton(AF_INET6,(char *)XML_GET_CONTENT(address->children), &addr); add_router_address(&routers, mac, addr); } } address = address->next; } } else if( !STRCMP(param->name,"prefixes") ) { xmlNode *prefix = param->children; while(prefix != NULL) { if (prefix->type == XML_ELEMENT_NODE) { if( !STRCMP(prefix->name,"prefix") ) { struct in6_addr addr; int mask=0; char buffer[INET6_ADDRSTRLEN]; struct _xmlAttr *attr = prefix->properties; while(attr != NULL) { if (attr->type == XML_ATTRIBUTE_NODE) { if( !STRCMP(attr->name,"mask") ) { c=(char *)XML_GET_CONTENT(attr->children); mask = atoi(c); /* mask = atoi((char *)XML_GET_CONTENT(attr->children)); */ } } attr = attr->next; } c=(char *)XML_GET_CONTENT(prefix->children); strcpy(buffer,c); /* strcpy(buffer,(char *)XML_GET_CONTENT(prefix->children)); */ inet_pton(AF_INET6,buffer, &addr); add_prefix(&routers, lla, mac, addr,mask); } } prefix = prefix->next; } } } param = param->next; } } } router = router->next; } } } current = current->next; } xmlFreeDoc(doc); return; } void parse_config() { FILE *f = NULL; fprintf(stderr,"Opening config file: %s\n",config_path); if( (f=fopen (config_path, "r")) == NULL ) { perror("fopen"); exit(1); } LIBXML_TEST_VERSION; /* create a parser context */ ctxt = xmlNewParserCtxt(); if (ctxt == NULL) { fprintf(stderr, "Failed to allocate parser context\n"); return; } /* parse the file, activating the DTD validation option */ doc = xmlCtxtReadFile(ctxt, config_path, NULL, XML_PARSE_DTDVALID); /* check if parsing suceeded */ if (doc == NULL) { fprintf(stderr, "Failed to parse %s\n", config_path); } else { /* check if validation suceeded */ if (ctxt->valid == 0) fprintf(stderr, "Failed to validate %s\n", config_path); /* free up the resulting document */ else { xmlXPathInit(); xpctxt= xmlXPathNewContext(doc); } } autoconf(); get_mail(); init_syslog(); parse_routers(); parse_actions(); free_xml(); fclose(f); } void parse_cache(char *filename) { xmlDoc *doc = NULL; xmlNode *root_element = NULL; xmlNode *neighbor = NULL; char *c; LIBXML_TEST_VERSION; /*parse the file and get the DOM */ doc = xmlReadFile(cache_path, NULL, 0); /*Get the root element node */ root_element = xmlDocGetRootElement(doc); neighbor = root_element->children; while(neighbor != NULL) { if( !STRCMP(neighbor->name,"neighbor") ) { struct in6_addr lla; struct ether_addr mac, eth; xmlNode *param = neighbor->children; while(param != NULL) { if (param->type == XML_ELEMENT_NODE) { if( !STRCMP(param->name,"mac") ) { c=(char *)XML_GET_CONTENT(param->children); memcpy(&mac,ether_aton(c),sizeof(struct ether_addr)); /* memcpy(&mac,ether_aton((char *)XML_GET_CONTENT(param->children)),sizeof(struct ether_addr)); */ add_neighbor(&neighbors, mac); } else if( !STRCMP(param->name,"time") ) { c=(char *)XML_GET_CONTENT(param->children); set_neighbor_timer(&neighbors, mac,atoi(c)); /* set_neighbor_timer(&neighbors, mac,atoi((char *)XML_GET_CONTENT(param->children))); */ } else if( !STRCMP(param->name,"lla") ) { if(param->children != NULL) { inet_pton(AF_INET6,(char *)XML_GET_CONTENT(param->children), &lla); set_neighbor_lla(&neighbors, mac, lla); } } else if( !STRCMP(param->name,"addresses") ) { xmlNode *address = param->children; while(address != NULL) { if (address->type == XML_ELEMENT_NODE) { if( !STRCMP(address->name,"address") ) { struct in6_addr addr; inet_pton(AF_INET6,(char *)XML_GET_CONTENT(address->children), &addr); add_neighbor_ip(&neighbors, mac, addr); } } address = address->next; } } else if( !STRCMP(param->name,"old_mac") ) { xmlNode *old = param->children; while(old != NULL) { if (old->type == XML_ELEMENT_NODE) { if( !STRCMP(old->name,"mac") ) { struct _xmlAttr *attr = old->properties; memcpy(ð,ether_aton((char *)XML_GET_CONTENT(old->children)),sizeof(struct ether_addr)); add_neighbor_old_mac(&neighbors, lla, eth); while(attr != NULL) { if (attr->type == XML_ATTRIBUTE_NODE) { if( !STRCMP(attr->name,"last") ) { neighbor_set_last_mac(&neighbors, lla, eth); } } attr = attr->next; } } } old = old->next; } } } param = param->next; } } neighbor = neighbor->next; } xmlFreeDoc(doc); return; } void write_config() { const char *uri=config_path; int rc; char str_ip[IP6_STR_SIZE]; xmlTextWriterPtr writer; router_list_t *tmp = routers; printf("Writing config...\n"); print_routers(routers); /* Create a new XmlWriter for uri, with no compression. */ writer = xmlNewTextWriterFilename(uri, 0); if (writer == NULL) { printf("testXmlwriterFilename: Error creating the xml writer\n"); return; } xmlTextWriterSetIndent(writer, 1); /* Start the document with the xml default for the version, * encoding ISO 8859-1 and the default for the standalone * declaration. */ rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterStartDocument\n"); return; } xmlTextWriterStartDTD (writer, (xmlChar*)"config_ndpmon", NULL, (xmlChar*)dtd_config_path); xmlTextWriterEndDTD (writer); /* Give the stylesheet for display in the web interface */ xmlTextWriterWriteRaw(writer, (xmlChar*)"\n"); /* Start an element named "config_ndpmon". Since this is the first * element, this will be the root element of the document. */ rc = xmlTextWriterStartElement(writer, BAD_CAST "config_ndpmon"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterStartElement\n"); return; } /* Attribute ignor_autoconf */ rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ignor_autoconf", "%d", ignor_autoconf); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Attribute syslog_facility */ rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "syslog_facility", "%s", syslog_facility); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Attribute admin_mail */ rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "admin_mail", "%s", admin_mail); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Elements of actions_low_pri */ rc = xmlTextWriterStartElement(writer, BAD_CAST "actions_low_pri"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Attribute sendmail */ rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "sendmail", "%d", action_low_pri.sendmail); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Attribute syslog */ rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "syslog", "%d", action_low_pri.syslog); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Attribute exec_pipe_program */ rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "exec_pipe_program", "%s", action_low_pri.exec_pipe_program); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Close actions_low_pri */ rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } /* Elements of actions_high_pri */ rc = xmlTextWriterStartElement(writer, BAD_CAST "actions_high_pri"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Attribute sendmail */ rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "sendmail", "%d", action_high_pri.sendmail); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Attribute syslog */ rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "syslog", "%d", action_high_pri.syslog); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Attribute exec_pipe_program */ rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "exec_pipe_program", "%s", action_high_pri.exec_pipe_program); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Close actions_high_pri */ rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } /* Attribute use_reverse_hostlookups */ rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "use_reverse_hostlookups", "%d", use_reverse_hostlookups); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Start an element named routers containing the routers' definition */ rc = xmlTextWriterStartElement(writer, BAD_CAST "routers"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterStartElement\n"); return; } /*for each router a new neighbor with its attributes is created in the file */ while(tmp != NULL) { address_t *atmp = tmp->addresses; prefix_t *etmp = tmp->prefixes; /* Start an element named "neighbor" as child of neighbor_list. */ rc = xmlTextWriterStartElement(writer, BAD_CAST "router"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterStartElement\n"); return; } /* Attribute mac */ rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "mac", "%s", ether_ntoa(&(tmp->mac))); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Attribute lla */ ipv6_ntoa(str_ip, tmp->lla); rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "lla", "%s", str_ip); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Start an element named prefixes */ rc = xmlTextWriterStartElement(writer, BAD_CAST "prefixes"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterStartElement\n"); return; } while(etmp != NULL) { ipv6_ntoa(str_ip, etmp->prefix); rc = xmlTextWriterStartElement(writer, BAD_CAST "prefix"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } rc = xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "mask", "%d", etmp->mask); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteAttribute %d\n",rc); } rc = xmlTextWriterWriteRaw(writer, BAD_CAST str_ip ); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } etmp = etmp->next; } rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } /* Addresses */ rc = xmlTextWriterStartElement(writer, BAD_CAST "addresses"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } while(atmp != NULL) { ipv6_ntoa(str_ip, atmp->address); rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "address", "%s", str_ip); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } atmp = atmp->next; } /* close addresses */ rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } /* close router */ rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } tmp = tmp->next; } /* Close routers */ rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } /* Close config_ndpmon */ rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } xmlFreeTextWriter(writer); return; } void write_cache() { const char *uri=cache_path; int rc; char str_ip[IP6_STR_SIZE]; xmlTextWriterPtr writer; neighbor_list_t *tmp = neighbors; FILE *dat = NULL; printf("Writing cache...\n"); /* Create a new XmlWriter for uri, with no compression. */ writer = xmlNewTextWriterFilename(uri, 0); if (writer == NULL) { printf("testXmlwriterFilename: Error creating the xml writer\n"); return; } xmlTextWriterSetIndent(writer, 1); /* Start the document with the xml default for the version, * encoding ISO 8859-1 and the default for the standalone * declaration. */ rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterStartDocument\n"); return; } xmlTextWriterStartDTD (writer, (xmlChar*)"neighbor_list", NULL, (xmlChar*)dtd_path); xmlTextWriterEndDTD (writer); /* Give the stylesheet for display in the web interface */ xmlTextWriterWriteRaw(writer, (xmlChar*)"\n"); /* Start an element named "neighbor_list". Since this is the first * element, this will be the root element of the document. */ rc = xmlTextWriterStartElement(writer, BAD_CAST "neighbor_list"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterStartElement\n"); return; } /*for each neighbor in the cache a new neighbor element with its *attributes is created in the file */ while(tmp != NULL) { address_t *atmp = tmp->addresses; ethernet_t *etmp = tmp->old_mac; /* Start an element named "neighbor" as child of neighbor_list. */ rc = xmlTextWriterStartElement(writer, BAD_CAST "neighbor"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterStartElement\n"); return; } /* Attribute mac */ rc = xmlTextWriterStartElement(writer, BAD_CAST "mac"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } #ifdef _MACRESOLUTION_ rc = xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "vendor", "%s", tmp->vendor); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteAttribute %d\n",rc); } #endif rc = xmlTextWriterWriteRaw(writer, BAD_CAST ether_ntoa(&(tmp->mac))); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } /* rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "mac", "%s", ether_ntoa(&(tmp->mac))); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } */ /* Attribute lla */ ipv6_ntoa(str_ip, tmp->lla); rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "lla", "%s", str_ip); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Attribute time */ rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "time", "%d",tmp->timer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } /* Addresses */ /* rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "adresses", NULL, NULL); */ rc = xmlTextWriterStartElement(writer, BAD_CAST "addresses"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } while(atmp != NULL) { ipv6_ntoa(str_ip, atmp->address); rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "address", "%s", str_ip); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } atmp = atmp->next; } rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } /* Old Mac */ rc = xmlTextWriterStartElement(writer, BAD_CAST "old_mac"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } while(etmp != NULL) { rc = xmlTextWriterStartElement(writer, BAD_CAST "mac"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } if(!MEMCMP(&(etmp->mac),&(tmp->previous_mac), sizeof(struct ether_addr))) { rc = xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "last", "%s", "true"); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteAttribute %d\n",rc); } } #ifdef _MACRESOLUTION_ rc = xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "vendor", "%s", etmp->vendor); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteAttribute %d\n",rc); } #endif rc = xmlTextWriterWriteRaw(writer, BAD_CAST ether_ntoa(&(etmp->mac))); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n"); return; } rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } etmp = etmp->next; } rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } /* Close neighbor */ rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } tmp = tmp->next; } /* Close neighbor_list */ rc = xmlTextWriterEndElement(writer); if (rc < 0) { printf("testXmlwriterFilename: Error at xmlTextWriterEndElement\n"); return; } xmlFreeTextWriter(writer); /* Write in discovery_history.dat the number of neighbors in the cache for statistics */ if( (dat = fopen(discovery_history_path,"a")) != NULL) { fprintf(dat,"%d %d\n", (int)time(NULL), nb_neighbor(neighbors) ); fclose(dat); } }