/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcpc6_attr.c,v $ $Revision: 1.22.16.2 $ * $Source: /home/interpeak/CVSRoot/ipdhcpc6/src/ipdhcpc6_attr.c,v $ * $Author: fguo $ * $State: Exp $ $Locker: $ * * Copyright 2000-2007 Interpeak AB (http://www.interpeak.se). All rights reserved. * Design and implementation by Joel Hortelius ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipdhcpc6_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include #include #include #include "ipdhcpc6.h" #include "ipdhcpc6_h.h" #include "ipdhcpc6_msg.h" #include "ipdhcpc6_if.h" #include "ipdhcpc6_ia.h" #include "ipdhcpc6_attr.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* **************************************************************************** * 5 TYPES **************************************************************************** */ typedef struct Ipdhcpc6_attr_pargs { void *obj; Ip_u32 mask; } Ipdhcpc6_attr_pargs_t; /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ char *ipdhcpc6_attr_if_link_state_name[] = { "uninitialized", "detached", "down", "up" }; char *ipdhcpc6_attr_mode_name[] = { "", "disabled", "enabled", "automatic" }; /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipdhcpc6_attr_binding_attr *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipdhcpc6_attr_binding_attr(void *bobjp, Ipdhcpc6_tagcomm_tag_t *tag) { Ipdhcpc6_attr_binding_t *bobj = bobjp; switch (tag->tag) { case IPDHCPC6_IA_ATTR_ADDRESS: ipdhcpc6_tagcomm_tag_in6_addr(tag, &bobj->prefix.addr); break; case IPDHCPC6_IA_ATTR_BINDING_PREFIX_PLEN: ipdhcpc6_tagcomm_tag_u32(tag, &bobj->prefix.plen); break; case IPDHCPC6_IA_ATTR_BINDING_PREFIX_PREFERRED: ipdhcpc6_tagcomm_tag_u32(tag, &bobj->preferred); break; case IPDHCPC6_IA_ATTR_BINDING_PREFIX_VALID: ipdhcpc6_tagcomm_tag_u32(tag, &bobj->valid); break; case IPDHCPC6_IA_ATTR_BINDING_PREFIX_STATUS: ipdhcpc6_tagcomm_tag_u32(tag, &bobj->status); break; case IPDHCPC6_IA_ATTR_TIMESTAMP: ipdhcpc6_tagcomm_tag_u32(tag, &bobj->timestamp); break; } return 0; } /* *=========================================================================== * ipdhcpc6_attr_ia_state_attr *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipdhcpc6_attr_ia_state_attr(void *bobjp, Ipdhcpc6_tagcomm_tag_t *tag) { Ipdhcpc6_attr_ia_state_t *state = bobjp; switch (tag->tag) { case IPDHCPC6_IA_ATTR_STATE_ACTION: ipdhcpc6_tagcomm_tag_u32(tag, &state->action); break; case IPDHCPC6_IA_ATTR_STATE_STATUS: ipdhcpc6_tagcomm_tag_u32(tag, &state->state); break; case IPDHCPC6_IA_ATTR_TIMESTAMP: ipdhcpc6_tagcomm_tag_u32(tag, &state->timestamp); break; } return 0; } /* *=========================================================================== * ipdhcpc6_attr_ia_state_parse *=========================================================================== * Description: Parse an state object * Parameters: tag - The tag. * state - Where to store the state. * Returns: * */ IP_STATIC void ipdhcpc6_attr_ia_state_parse(Ipdhcpc6_tagcomm_tag_t *tag, Ipdhcpc6_attr_ia_state_t *state) { ipdhcpc6_tagcomm_parse_attributes(ipdhcpc6_attr_ia_state_attr, tag, state); } /* *=========================================================================== * ipdhcpc6_attr_ia_state_attr *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipdhcpc6_attr_ia_history_attr(void *bobjp, Ipdhcpc6_tagcomm_tag_t *tag) { Ipdhcpc6_attr_array_t *array = bobjp; Ipdhcpc6_attr_ia_state_t state; switch (tag->tag) { case IPDHCPC6_IA_OBJECT_STATE: ipdhcpc6_attr_ia_state_parse(tag, &state); ipdhcpc6_attr_array_add(array, &state, sizeof(state)); break; } return 0; } /* *=========================================================================== * ipdhcpc6_attr_ia_history_parse *=========================================================================== * Description: Parse an state object * Parameters: tag - The tag. * array - Where to store the history * Returns: * */ IP_STATIC void ipdhcpc6_attr_ia_history_parse(Ipdhcpc6_tagcomm_tag_t *tag, Ipdhcpc6_attr_array_t *array) { ipdhcpc6_tagcomm_parse_objects(ipdhcpc6_attr_ia_history_attr, tag, array); } /* *=========================================================================== * ipdhcpc6_attr_ia_attr *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipdhcpc6_attr_ia_attr(void *pargsp, Ipdhcpc6_tagcomm_tag_t *tag) { Ipdhcpc6_attr_pargs_t *pargs = pargsp; Ipdhcpc6_attr_ia_t *iaobj = pargs->obj; Ipdhcpc6_attr_binding_t *bobj = IP_NULL; switch (tag->tag) { /* IDENTITIES */ case IPDHCPC6_IA_IDENT_IA_IANAME: if (ipdhcpc6_tagcomm_tag_string(tag, &iaobj->ianame)) iaobj->ianame = ipcom_strdup(iaobj->ianame); break; case IPDHCPC6_IA_IDENT_IA_IAID: ipdhcpc6_tagcomm_tag_u32(tag, &iaobj->iaid); break; case IPDHCPC6_IA_IDENT_IA_IATYPE: ipdhcpc6_tagcomm_tag_u32(tag, &iaobj->iatype); break; /* ATTRIBUTES */ case IPDHCPC6_IA_ATTR_IA_T1: ipdhcpc6_tagcomm_tag_u32(tag, &iaobj->bindings.T1); break; case IPDHCPC6_IA_ATTR_IA_T2: ipdhcpc6_tagcomm_tag_u32(tag, &iaobj->bindings.T2); break; case IPDHCPC6_IA_ATTR_TIMESTAMP: ipdhcpc6_tagcomm_tag_u32(tag, &iaobj->bindings.timestamp); break; case IPDHCPC6_IA_ATTR_IA_T1_HINT: ipdhcpc6_tagcomm_tag_u32(tag, &iaobj->hints.T1); break; case IPDHCPC6_IA_ATTR_IA_T2_HINT: ipdhcpc6_tagcomm_tag_u32(tag, &iaobj->hints.T2); break; /* OBJECTS */ case IPDHCPC6_IA_OBJECT_STATE: ipdhcpc6_attr_ia_state_parse(tag, &iaobj->state); break; case IPDHCPC6_IA_OBJECT_HISTORY: ipdhcpc6_attr_ia_history_parse(tag, &iaobj->history); break; case IPDHCPC6_IA_OBJECT_SERVER: ipdhcpc6_attr_if_server_free(&iaobj->router); iaobj->router = ipdhcpc6_attr_if_server_parse(tag, pargs->mask); break; case IPDHCPC6_IA_OBJECT_BINDING_HINT: bobj = ipdhcpc6_attr_binding_parse(tag); if (bobj) ipdhcpc6_attr_array_add(&iaobj->hints.binding, bobj, 0); break; case IPDHCPC6_IA_OBJECT_BINDING: bobj = ipdhcpc6_attr_binding_parse(tag); if (bobj) ipdhcpc6_attr_array_add(&iaobj->bindings.binding, bobj, 0); break; default: break; } return 0; } /* *=========================================================================== * ipdhcpc6_attr_if_config_attr *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipdhcpc6_attr_if_config_attr(void *pargsp, Ipdhcpc6_tagcomm_tag_t *tag) { Ipdhcpc6_attr_pargs_t *pargs = pargsp; Ipdhcpc6_attr_if_config_t *ifconfig = pargs->obj; switch (tag->tag) { /* IDENTITIES */ /* ATTRIBUTES */ case IPDHCPC6_IA_ATTR_IF_CONFIG_RAPID_COMMIT: ipdhcpc6_tagcomm_tag_u32(tag, &ifconfig->rapid_commit); break; case IPDHCPC6_IA_ATTR_IF_CONFIG_INFO_ONLY: ipdhcpc6_tagcomm_tag_u32(tag, &ifconfig->information_only); break; case IPDHCPC6_IA_ATTR_IF_CONFIG_DNS: ipdhcpc6_tagcomm_tag_u32(tag, &ifconfig->dns); break; case IPDHCPC6_IA_ATTR_IF_CONFIG_SNTP: ipdhcpc6_tagcomm_tag_u32(tag, &ifconfig->sntp); break; case IPDHCPC6_IA_ATTR_IF_CONFIG_INFO_REFRESH: ipdhcpc6_tagcomm_tag_u32(tag, &ifconfig->info_refresh); break; case IPDHCPC6_IA_ATTR_IF_CONFIG_SIP: ipdhcpc6_tagcomm_tag_u32(tag, &ifconfig->sip); break; case IPDHCPC6_IA_ATTR_IF_CONFIG_FQDN: ipdhcpc6_tagcomm_tag_u32(tag, &ifconfig->fqdn.fqdn); break; /* OBJECTS */ default: break; } return 0; } /* *=========================================================================== * ipdhcpc6_attr_if_automatic_attr *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipdhcpc6_attr_if_automatic_attr(void *pargsp, Ipdhcpc6_tagcomm_tag_t *tag) { Ipdhcpc6_attr_pargs_t *pargs = pargsp; Ipdhcpc6_attr_if_automatic_t *ifauto = pargs->obj; Ipdhcpc6_attr_if_server_t *ifsrv; switch (tag->tag) { /* IDENTITIES */ /* ATTRIBUTES */ case IPDHCPC6_IA_OBJECT_SERVER: ifsrv = ipdhcpc6_attr_if_server_parse(tag, pargs->mask); if (ifsrv) { ipcom_memcpy(&ifauto->rtr, &ifsrv->address, sizeof(ifauto->rtr)); ipdhcpc6_attr_if_server_free(&ifsrv); } break; case IPDHCPC6_IA_ATTR_IF_AUTOMATIC_MANAGED: ipdhcpc6_tagcomm_tag_u32(tag, &ifauto->runtime.managed); break; case IPDHCPC6_IA_ATTR_IF_AUTOMATIC_OTHER: ipdhcpc6_tagcomm_tag_u32(tag, &ifauto->runtime.other); break; /* OBJECTS */ default: break; } return 0; } /* *=========================================================================== * ipdhcpc6_attr_if_server_attr *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipdhcpc6_attr_if_server_attr(void *pargsp, Ipdhcpc6_tagcomm_tag_t *tag) { Ipdhcpc6_attr_pargs_t *pargs = pargsp; Ipdhcpc6_attr_if_server_t *ifsrv = pargs->obj; struct Ip_in6_addr addr; char *str; switch (tag->tag) { /* IDENTITIES */ case IPDHCPC6_IA_IDENT_DUID: if (IPDHCPC6_TAGCOMM_TAG_SIZE(tag) != 0) { ipdhcpc6_util_free(&ifsrv->id_vector); ifsrv->id_size = IPDHCPC6_TAGCOMM_TAG_SIZE(tag); ifsrv->id_vector = ipcom_malloc(ifsrv->id_size); ipcom_memcpy(ifsrv->id_vector, IPDHCPC6_TAGCOMM_TAG_DATA(tag), ifsrv->id_size); } break; /* ATTRIBUTES */ case IPDHCPC6_IA_ATTR_ADDRESS: ipdhcpc6_tagcomm_tag_in6_addr(tag, &ifsrv->address); break; case IPDHCPC6_IA_ATTR_SERVER_UNICAST: ipdhcpc6_tagcomm_tag_in6_addr(tag, &ifsrv->unicast); break; case IPDHCPC6_IA_ATTR_SERVER_INFO_REFRESH: ipdhcpc6_tagcomm_tag_u32(tag, &ifsrv->info_refresh); break; case IPDHCPC6_IA_ATTR_SERVER_DNS_SERVER: ipdhcpc6_tagcomm_tag_in6_addr(tag, &addr); ipdhcpc6_attr_array_add(&ifsrv->dns, &addr, sizeof(addr)); break; case IPDHCPC6_IA_ATTR_SERVER_SNTP_SERVER: ipdhcpc6_tagcomm_tag_in6_addr(tag, &addr); ipdhcpc6_attr_array_add(&ifsrv->sntp, &addr, sizeof(addr)); break; case IPDHCPC6_IA_ATTR_SERVER_DOMAIN_LIST: if (ipdhcpc6_tagcomm_tag_string(tag, &str)) ipdhcpc6_attr_array_add(&ifsrv->domain, str, ipcom_strlen(str) + 1); break; case IPDHCPC6_IA_ATTR_SERVER_SIP_D: if (ipdhcpc6_tagcomm_tag_string(tag, &str)) ipdhcpc6_attr_array_add(&ifsrv->sip_d, str, ipcom_strlen(str) + 1); break; case IPDHCPC6_IA_ATTR_SERVER_SIP_A: if (ipdhcpc6_tagcomm_tag_in6_addr(tag, &addr)) ipdhcpc6_attr_array_add(&ifsrv->sip_a, &addr, sizeof(addr)); break; case IPDHCPC6_IA_ATTR_SERVER_FQDN: if (ipdhcpc6_tagcomm_tag_string(tag, &str)) ipdhcpc6_attr_array_add(&ifsrv->fqdn, str, ipcom_strlen(str) + 1); break; /* OBJECTS */ default: break; } return 0; } /* *=========================================================================== * ipdhcpc6_attr_if_attr *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipdhcpc6_attr_if_attr(void *pargsp, Ipdhcpc6_tagcomm_tag_t *tag) { Ipdhcpc6_attr_pargs_t *pargs = pargsp; Ipdhcpc6_attr_if_t *ifobj = pargs->obj; Ipdhcpc6_attr_ia_t *iaobj = IP_NULL; Ipdhcpc6_attr_if_server_t *ifsrv; switch (tag->tag) { /* IDENTITITIES */ case IPDHCPC6_IA_IDENT_NAME: if (ipdhcpc6_tagcomm_tag_string(tag, &ifobj->ifname)) ifobj->ifname = ipcom_strdup(ifobj->ifname); break; /* ATTRIBUTES */ case IPDHCPC6_IA_ATTR_IF_MODE: ipdhcpc6_tagcomm_tag_u32(tag, &ifobj->mode); break; case IPDHCPC6_IA_ATTR_IF_LINK_STATE: ipdhcpc6_tagcomm_tag_u32(tag, &ifobj->state); break; case IPDHCPC6_IA_ATTR_IF_VR: ipdhcpc6_tagcomm_tag_u32(tag, (Ip_u32 *)&ifobj->vr); break; /* OBJECTS */ case IPDHCPC6_IA_OBJECT_IF_CONFIG: ipdhcpc6_attr_if_config_free(&ifobj->config); ifobj->config = ipdhcpc6_attr_if_config_parse(tag, pargs->mask); break; case IPDHCPC6_IA_OBJECT_IF_AUTOMATIC: ipdhcpc6_attr_if_automatic_free(&ifobj->automatic); ifobj->automatic= ipdhcpc6_attr_if_automatic_parse(tag, pargs->mask); break; case IPDHCPC6_IA_OBJECT_IA: iaobj = ipdhcpc6_attr_ia_parse(tag, pargs->mask); if (iaobj) ipdhcpc6_attr_array_add(&ifobj->ias, iaobj, 0); break; case IPDHCPC6_IA_OBJECT_SERVER: ifsrv = ipdhcpc6_attr_if_server_parse(tag, pargs->mask); if (ifsrv) ipdhcpc6_attr_array_add(&ifobj->servers, ifsrv, 0); break; } return 0; } /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipdhcpc6_attr_binding_parse *=========================================================================== * Description: Parse an IPDHCPC6_IA_OBJECT_BINDING or * IPDHCPC6_IA_OBJECT_BINDING_HINT tag. * Parameters: tag - The tag. * Returns: The binding object * */ IP_GLOBAL Ipdhcpc6_attr_binding_t * ipdhcpc6_attr_binding_parse(Ipdhcpc6_tagcomm_tag_t *tag) { Ipdhcpc6_attr_binding_t *bobj = ipcom_calloc(1, sizeof(*bobj)); if (bobj) ipdhcpc6_tagcomm_parse_attributes(ipdhcpc6_attr_binding_attr, tag, bobj); return bobj; } /* *=========================================================================== * ipdhcpc6_attr_binding_free *=========================================================================== * Description: Free any resources previously allocated by parse. * Parameters: bobjp - The binding object. * Returns: * */ IP_GLOBAL void ipdhcpc6_attr_binding_free(Ipdhcpc6_attr_binding_t **bobjp) { Ipdhcpc6_attr_binding_t *bobj = *bobjp; if (bobj) { ipdhcpc6_util_free(&bobj); } *bobjp = IP_NULL; } /* *=========================================================================== * ipdhcpc6_attr_ia_parse *=========================================================================== * Description: Parse an IPDHCPC6_ATTR_IA_IF_IA_OBJECT tag. * Parameters: tag - The tag. * mask - The type of objects we'll parse; 0 = all. * Returns: The identity association pointer with its associated BINDINGS. * */ IP_GLOBAL Ipdhcpc6_attr_ia_t * ipdhcpc6_attr_ia_parse(Ipdhcpc6_tagcomm_tag_t *tag, Ip_u32 mask) { Ipdhcpc6_attr_ia_t *iaobj = ipcom_calloc(1, sizeof(*iaobj)); if (mask == 0) mask = IPDHCPC6_TAGCOMM_TAG_MASK; if (iaobj) { Ipdhcpc6_attr_pargs_t pargs; pargs.mask = mask; pargs.obj = iaobj; iaobj->status = tag->status; if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_IDENTITY)) ipdhcpc6_tagcomm_parse_identities(ipdhcpc6_attr_ia_attr, tag, &pargs); if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_ATTRIBUTE)) ipdhcpc6_tagcomm_parse_attributes(ipdhcpc6_attr_ia_attr, tag, &pargs); if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_OBJECT)) ipdhcpc6_tagcomm_parse_objects(ipdhcpc6_attr_ia_attr, tag, &pargs); } return iaobj; } /* *=========================================================================== * ipdhcpc6_attr_ia_free *=========================================================================== * Description: Free any resources previously allocated by parse. Will also * free any bindings * Parameters: iaobjp - The IA object. * Returns: * */ IP_GLOBAL void ipdhcpc6_attr_ia_free(Ipdhcpc6_attr_ia_t **iaobjp) { Ipdhcpc6_attr_ia_t *iaobj = *iaobjp; if (iaobj) { if (iaobj->ianame) { ipdhcpc6_util_free(&iaobj->ianame); } ipdhcpc6_attr_if_server_free(&iaobj->router); ipdhcpc6_attr_array_free(&iaobj->history, (Ipdhcpc6_attr_array_free_t)ipdhcpc6_util_free); ipdhcpc6_attr_array_free(&iaobj->bindings.binding, (Ipdhcpc6_attr_array_free_t)ipdhcpc6_attr_binding_free); ipdhcpc6_attr_array_free(&iaobj->hints.binding, (Ipdhcpc6_attr_array_free_t)ipdhcpc6_attr_binding_free); ipdhcpc6_util_free(&iaobj); } *iaobjp = IP_NULL; } /* *=========================================================================== * ipdhcpc6_attr_if_automatic_parse *=========================================================================== * Description: Parse an IPDHCPC6_IA_OBJECT_IF_AUTOMATIC tag. * Parameters: tag - The tag. * mask - The type of objects we'll parse; 0 = all. * Returns: The interface config pointer * */ IP_GLOBAL Ipdhcpc6_attr_if_automatic_t * ipdhcpc6_attr_if_automatic_parse(Ipdhcpc6_tagcomm_tag_t *tag, Ip_u32 mask) { Ipdhcpc6_attr_if_automatic_t *ifauto = ipcom_calloc(1, sizeof(*ifauto)); if (mask == 0) mask = IPDHCPC6_TAGCOMM_TAG_MASK; if (ifauto) { Ipdhcpc6_attr_pargs_t pargs; pargs.mask = mask; pargs.obj = ifauto; if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_IDENTITY)) ipdhcpc6_tagcomm_parse_identities(ipdhcpc6_attr_if_automatic_attr, tag, &pargs); if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_ATTRIBUTE)) ipdhcpc6_tagcomm_parse_attributes(ipdhcpc6_attr_if_automatic_attr, tag, &pargs); if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_OBJECT)) ipdhcpc6_tagcomm_parse_objects(ipdhcpc6_attr_if_automatic_attr, tag, &pargs); } return ifauto; } /* *=========================================================================== * ipdhcpc6_attr_if_automatic_free *=========================================================================== * Description: Free any resources previously allocated by parse. * Parameters: ifautop - The interface automatic object. * Returns: * */ IP_GLOBAL void ipdhcpc6_attr_if_automatic_free(Ipdhcpc6_attr_if_automatic_t **ifautop) { Ipdhcpc6_attr_if_automatic_t *ifauto = *ifautop; if (ifauto) { ipdhcpc6_util_free(&ifauto); } *ifautop = IP_NULL; } /* *=========================================================================== * ipdhcpc6_attr_if_server_parse *=========================================================================== * Description: Parse an IPDHCPC6_IA_OBJECT_SERVER tag. * Parameters: tag - The tag. * mask - The type of objects we'll parse; 0 = all. * Returns: The interface server pointer * */ IP_GLOBAL Ipdhcpc6_attr_if_server_t * ipdhcpc6_attr_if_server_parse(Ipdhcpc6_tagcomm_tag_t *tag, Ip_u32 mask) { Ipdhcpc6_attr_if_server_t *ifsrv = ipcom_calloc(1, sizeof(*ifsrv)); if (mask == 0) mask = IPDHCPC6_TAGCOMM_TAG_MASK; if (ifsrv) { Ipdhcpc6_attr_pargs_t pargs; pargs.mask = mask; pargs.obj = ifsrv; if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_IDENTITY)) ipdhcpc6_tagcomm_parse_identities(ipdhcpc6_attr_if_server_attr, tag, &pargs); if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_ATTRIBUTE)) ipdhcpc6_tagcomm_parse_attributes(ipdhcpc6_attr_if_server_attr, tag, &pargs); if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_OBJECT)) ipdhcpc6_tagcomm_parse_objects(ipdhcpc6_attr_if_server_attr, tag, &pargs); } return ifsrv; } /* *=========================================================================== * ipdhcpc6_attr_if_server_free *=========================================================================== * Description: Free any resources previously allocated by parse. * Parameters: ifsrvp - The interface server object. * Returns: * */ IP_GLOBAL void ipdhcpc6_attr_if_server_free(Ipdhcpc6_attr_if_server_t **ifsrvp) { Ipdhcpc6_attr_if_server_t *ifsrv = *ifsrvp; if (ifsrv) { ipdhcpc6_attr_array_free(&ifsrv->dns, (Ipdhcpc6_attr_array_free_t)ipdhcpc6_util_free); ipdhcpc6_attr_array_free(&ifsrv->domain, (Ipdhcpc6_attr_array_free_t)ipdhcpc6_util_free); ipdhcpc6_attr_array_free(&ifsrv->sntp, (Ipdhcpc6_attr_array_free_t)ipdhcpc6_util_free); ipdhcpc6_attr_array_free(&ifsrv->sip_d, (Ipdhcpc6_attr_array_free_t)ipdhcpc6_util_free); ipdhcpc6_attr_array_free(&ifsrv->sip_a, (Ipdhcpc6_attr_array_free_t)ipdhcpc6_util_free); /*Free the fqdn stored before*/ ipdhcpc6_attr_array_free (&ifsrv->fqdn, (Ipdhcpc6_attr_array_free_t)ipdhcpc6_util_free); ipdhcpc6_util_free(&ifsrv->id_vector); ipdhcpc6_util_free(&ifsrv); } *ifsrvp = IP_NULL; } /* *=========================================================================== * ipdhcpc6_attr_if_config_parse *=========================================================================== * Description: Parse an IPDHCPC6_IA_OBJECT_IF_CONFIG tag. * Parameters: tag - The tag. * mask - The type of objects we'll parse; 0 = all. * Returns: The interface config pointer * */ IP_GLOBAL Ipdhcpc6_attr_if_config_t * ipdhcpc6_attr_if_config_parse(Ipdhcpc6_tagcomm_tag_t *tag, Ip_u32 mask) { Ipdhcpc6_attr_if_config_t *ifconfig = ipcom_calloc(1, sizeof(*ifconfig)); if (mask == 0) mask = IPDHCPC6_TAGCOMM_TAG_MASK; if (ifconfig) { Ipdhcpc6_attr_pargs_t pargs; pargs.mask = mask; pargs.obj = ifconfig; if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_IDENTITY)) ipdhcpc6_tagcomm_parse_identities(ipdhcpc6_attr_if_config_attr, tag, &pargs); if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_ATTRIBUTE)) ipdhcpc6_tagcomm_parse_attributes(ipdhcpc6_attr_if_config_attr, tag, &pargs); if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_OBJECT)) ipdhcpc6_tagcomm_parse_objects(ipdhcpc6_attr_if_config_attr, tag, &pargs); } return ifconfig; } /* *=========================================================================== * ipdhcpc6_attr_if_config_free *=========================================================================== * Description: Free any resources previously allocated by parse. * Parameters: ifconfigp - The interface config object. * Returns: * */ IP_GLOBAL void ipdhcpc6_attr_if_config_free(Ipdhcpc6_attr_if_config_t **ifconfigp) { Ipdhcpc6_attr_if_config_t *ifconfig = *ifconfigp; if (ifconfig) { ipdhcpc6_util_free(&ifconfig); } *ifconfigp = IP_NULL; } /* *=========================================================================== * ipdhcpc6_attr_if_parse *=========================================================================== * Description: Parse an IPDHCPC6_ATTR_IA_IF_OBJECT tag. * Parameters: tag - The tag. * mask - The type of objects we'll parse; 0 = all. * Returns: The interface pointer with its associated IA/BINDINGS. * */ IP_GLOBAL Ipdhcpc6_attr_if_t * ipdhcpc6_attr_if_parse(Ipdhcpc6_tagcomm_tag_t *tag, Ip_u32 mask) { Ipdhcpc6_attr_if_t *ifobj = ipcom_calloc(1, sizeof(*ifobj)); if (mask == 0) mask = IPDHCPC6_TAGCOMM_TAG_MASK; if (ifobj) { Ipdhcpc6_attr_pargs_t pargs; pargs.mask = mask; pargs.obj = ifobj; ifobj->status = tag->status; if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_IDENTITY)) ipdhcpc6_tagcomm_parse_identities(ipdhcpc6_attr_if_attr, tag, &pargs); if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_ATTRIBUTE)) ipdhcpc6_tagcomm_parse_attributes(ipdhcpc6_attr_if_attr, tag, &pargs); if (IP_BIT_ISSET(mask, IPDHCPC6_TAGCOMM_TAG_OBJECT)) ipdhcpc6_tagcomm_parse_objects(ipdhcpc6_attr_if_attr, tag, &pargs); } return ifobj; } /* *=========================================================================== * ipdhcpc6_attr_if_free *=========================================================================== * Description: Free any resources previously allocated by parse. Will also * free any ias * Parameters: ifobjp - The interface object. * Returns: * */ IP_GLOBAL void ipdhcpc6_attr_if_free(Ipdhcpc6_attr_if_t **ifobjp) { Ipdhcpc6_attr_if_t *ifobj = *ifobjp; if (ifobj) { ipdhcpc6_util_free(&ifobj->ifname); ipdhcpc6_attr_if_automatic_free(&ifobj->automatic); ipdhcpc6_attr_if_config_free(&ifobj->config); ipdhcpc6_attr_array_free(&ifobj->ias, (Ipdhcpc6_attr_array_free_t) ipdhcpc6_attr_ia_free); ipdhcpc6_attr_array_free(&ifobj->servers, (Ipdhcpc6_attr_array_free_t) ipdhcpc6_attr_if_server_free); ipdhcpc6_util_free(&ifobj); } *ifobjp = IP_NULL; } /* *=========================================================================== * ipdhcpc6_attr_read *=========================================================================== * Description: Read the number of bytes specified by rbuf * Parameters: fd - The filedescriptor to read from * rbuf - The read buffer * block - Block until the entire command is read. * Returns: The number of remaining bytes to read. * */ IP_GLOBAL int ipdhcpc6_attr_read(Ip_fd fd, Ipdhcpc6_attr_readbuf_t *rbuf, Ip_bool block) { do { int bytes; /* Read it all? */ if (rbuf->read_size == rbuf->total_size) return 0; bytes = ipcom_recv(fd, &rbuf->buffer[rbuf->read_size], rbuf->total_size - rbuf->read_size, 0); /* Failed? */ if (bytes <= 0) return -1; rbuf->read_size += bytes; /* Only continue if they specified that we wait for it */ } while (block); /* return remaining */ return (int)(rbuf->total_size - rbuf->read_size); } /* *=========================================================================== * ipdhcpc6_attr_sendmsg *=========================================================================== * Description: Send a message over fd * Parameters: fd - File descriptor. * buf - Pointer to buffer. * Returns: IP_TRUE if successful. * */ IP_GLOBAL Ip_bool ipdhcpc6_attr_sendmsg(Ip_fd fd, Ipdhcpc6_tagcomm_buffer_t *buf) { Ip_bool ret = IP_FALSE; if (buf) { if (ipcom_send(fd, buf->head, buf->offset, 0) == buf->offset) ret = IP_TRUE; } return ret; } /* *=========================================================================== * ipdhcpc6_attr_recvhdr *=========================================================================== * Description: Read the header of a command, and allocate the required * buffer space. * Parameters: fd - File descriptor * rbuf - Read buffer. * Returns: IP_TRUE if successful. * */ IP_GLOBAL Ip_bool ipdhcpc6_attr_recvhdr(Ip_fd fd, Ipdhcpc6_attr_readbuf_t *rbuf) { Ipdhcpc6_tagcomm_tag_t tag; Ipdhcpc6_tagcomm_tag_t *ptag; ipcom_memset(rbuf, 0, sizeof(*rbuf)); rbuf->buffer = (Ip_u8 *)&tag; rbuf->total_size = sizeof(tag); /* Read the TAG header */ if (ipdhcpc6_attr_read(fd, rbuf, IP_TRUE) < 0 || tag.length < sizeof(tag)) { rbuf->buffer = IP_NULL; return IP_FALSE; } rbuf->total_size = tag.length + sizeof(tag); rbuf->read_size = sizeof(tag) * 2; rbuf->buffer = ipcom_malloc(rbuf->total_size + sizeof(tag)); if (rbuf->buffer == IP_NULL) return IP_FALSE; ptag = (Ipdhcpc6_tagcomm_tag_t *) rbuf->buffer; ptag->length = (Ip_u16)rbuf->total_size; ptag->tag = 0; ptag->status = 0; ipcom_memcpy(rbuf->buffer + sizeof(tag), &tag, sizeof(tag)); return IP_TRUE; } /* *=========================================================================== * ipdhcpc6_attr_recvmsg *=========================================================================== * Description: Read a message. A buffer holding the entire message will * be dynamically allocated on success. * Parameters: fd - File descriptor. * rbuf - Pointer to buffer pointer. Will hold the * dynamically allocated buffer on success. * Returns: IP_TRUE if successful. * */ IP_GLOBAL Ip_bool ipdhcpc6_attr_recvmsg(Ip_fd fd, Ipdhcpc6_attr_readbuf_t *rbuf) { if (ipdhcpc6_attr_recvhdr(fd, rbuf) == IP_FALSE) return IP_FALSE; if (ipdhcpc6_attr_read(fd, rbuf, IP_TRUE) < 0) { ipdhcpc6_util_free(&rbuf->buffer); return IP_FALSE; } return IP_TRUE; } /* *=========================================================================== * ipdhcpc6_attr_connect *=========================================================================== * Description: Create a TCP connection to the DHCPv6 Client * Parameters: * Returns: A file descriptor if successful, IP_INVALID_SOCKET otherwise. * */ IP_GLOBAL Ip_fd ipdhcpc6_attr_connect(void) { Ip_fd fd; struct Ip_sockaddr_in6 sin6; /* Create the API socket */ fd = ipcom_socket(IP_AF_INET6, IP_SOCK_STREAM, IP_IPPROTO_TCP); if (fd != IP_INVALID_SOCKET) { ipcom_memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = IP_AF_INET6; sin6.sin6_len = sizeof(sin6); sin6.sin6_port = ip_htons(IPDHCPC6_CLIENT_PORT); sin6.sin6_addr = ip_in6addr_loopback; /* Do connect */ if (ipcom_connect(fd, (struct Ip_sockaddr *)&sin6, sizeof(sin6)) < 0) { ipcom_socketclose(fd); return IP_INVALID_SOCKET; } } return fd; } /* *=========================================================================== * ipdhcpc6_attr_errno *=========================================================================== * Description: Return human readable string representation for error * Parameters: errcode - The errcode * Returns: The human readable string * */ IP_GLOBAL const char * ipdhcpc6_attr_errno(Ip_u32 errcode) { switch (errcode) { case IPDHCPC6_TAGCOMM_STATUS_UNKNOWN_TAG: return "unknown tag"; case IPDHCPC6_TAGCOMM_STATUS_PARSE_FAILED: return "parse failed"; case IPDHCPC6_ATTR_TAG_STATUS_UNKNOWN_INTERFACE: return "unknown interface"; case IPDHCPC6_ATTR_TAG_STATUS_UNKNOWN_IA: return "unknown identity association (IA)"; default: return "unknown error"; } } /* *=========================================================================== * ipdhcpc6_attr_ia_status *=========================================================================== * Description: Return the human readable name of the status * Parameters: status - The status * Returns: The human readable name * */ IP_GLOBAL const char * ipdhcpc6_attr_ia_status(Ip_u32 status) { switch (status) { case IPDHCPC6_IA_STATE_SOLICIT: return "solicit"; case IPDHCPC6_IA_STATE_BOUND: return "bound"; } return ""; } /* *=========================================================================== * ipdhcpc6_attr_ia_action *=========================================================================== * Description: Return the human readable name of the action * Parameters: action - The action * Returns: The human readable name * */ IP_GLOBAL const char * ipdhcpc6_attr_ia_action(Ip_u32 action) { switch (action) { case IPDHCPC6_IA_ACTION_IDLE: return "idle"; case IPDHCPC6_IA_ACTION_SOLICIT: return "solicit"; case IPDHCPC6_IA_ACTION_REQUEST: return "request"; case IPDHCPC6_IA_ACTION_RENEW: return "renew"; case IPDHCPC6_IA_ACTION_REBIND: case IPDHCPC6_IA_ACTION_REBINDCONF: return "rebind"; case IPDHCPC6_IA_ACTION_CONFIRM: return "confirm"; case IPDHCPC6_IA_ACTION_RELEASE: return "release"; case IPDHCPC6_IA_ACTION_DECLINE: return "decline"; case IPDHCPC6_IA_ACTION_SOLICITING: return "soliciting"; case IPDHCPC6_IA_ACTION_REQUESTING: return "requesting"; case IPDHCPC6_IA_ACTION_RENEWING: return "renewing"; case IPDHCPC6_IA_ACTION_REBINDING: case IPDHCPC6_IA_ACTION_REBINDCONFING: return "rebinding"; case IPDHCPC6_IA_ACTION_CONFIRMING: return "confirming"; case IPDHCPC6_IA_ACTION_RELEASING: return "releasing"; case IPDHCPC6_IA_ACTION_DECLINEING: return "declining"; } return ""; } /* *=========================================================================== * ipdhcpc6_attr_array_add *=========================================================================== * Description: Add an element to an array; allocate the array or increase * it if required. * Parameters: array - Pointer to the array * object - Object * size - Size of object; if zero, don't copy. Store as is. * Returns: * */ IP_GLOBAL void ipdhcpc6_attr_array_add(Ipdhcpc6_attr_array_t *array, void *object, Ip_size_t size) { Ip_u32 remain = array->size - array->num; /* Increase the array size? */ if (remain == 0) { Ip_size_t nsize = IP_MAX(3, array->size) * 2; void **narr = ipcom_calloc(nsize, sizeof(*narr)); if (narr == IP_NULL) return; if (array->num) ipcom_memmove(narr, array->array, sizeof(void *) * array->num); ipdhcpc6_util_free(&array->array); array->array = narr; array->size = (Ip_u32)nsize; } /* Do I want to copy the object? */ if (size) { void *nobj = ipcom_malloc(size); if (nobj == IP_NULL) return; ipcom_memcpy(nobj, object, size); object = nobj; } array->array[array->num++] = object; } /* *=========================================================================== * ipdhcpc6_attr_array_free *=========================================================================== * Description: Free the array and its elements. * Parameters: array - The array * freefunc - Option function to invoke per element. * Returns: * */ IP_GLOBAL void ipdhcpc6_attr_array_free(Ipdhcpc6_attr_array_t *array, Ipdhcpc6_attr_array_free_t freefunc) { if (array->size) { if (freefunc) { int i; for (i = 0; i < (int)array->num; i++) (*freefunc) (&array->array[i]); } ipdhcpc6_util_free(&array->array); array->size = 0; array->num = 0; } } /* *=========================================================================== * ipdhcpc6_attr_array_remove *=========================================================================== * Description: Remove a particular element from the array * Parameters: array - The array * obj - The object * freefunc - The free function. * Returns: * */ IP_GLOBAL void ipdhcpc6_attr_array_remove(Ipdhcpc6_attr_array_t *array, void *obj, Ipdhcpc6_attr_array_free_t freefunc) { int i; for (i = 0; i < (int)array->num; i++) { if (array->array[i] == obj) { array->num--; if (((int)array->num - i) > 0) ipcom_memmove(&array->array[i], &array->array[i + 1], (array->num - i) * sizeof(obj)); if (freefunc) (*freefunc) (&obj); } } } /* *=========================================================================== * ipdhcpc6_attr_server_set_unicast *=========================================================================== * Description: Set a unicast address * Parameters: srv - The server attributes * addr - Address * Returns: * */ IP_GLOBAL void ipdhcpc6_attr_server_set_unicast(Ipdhcpc6_attr_if_server_t *srv, const struct Ip_in6_addr *addr) { if (addr == IP_NULL) addr = &ip_in6addr_any; ipcom_memcpy(&srv->unicast, addr, sizeof(*addr)); } /* *=========================================================================== * ipdhcpc6_attr_server_unicast *=========================================================================== * Description: Returns the unicast address for a server * Parameters: srv - The server attributes * Returns: The unicast address if it exists. * */ IP_GLOBAL const struct Ip_in6_addr * ipdhcpc6_attr_server_unicast(Ipdhcpc6_attr_if_server_t *srv) { if (IP_IN6_ARE_ADDR_EQUAL(&srv->unicast, &ip_in6addr_any)) return IP_NULL; return &srv->unicast; } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * END OF FILE **************************************************************************** */