diff --git a/include/constants.h b/include/constants.h new file mode 100644 index 0000000..73e46c2 --- /dev/null +++ b/include/constants.h @@ -0,0 +1,9 @@ +#ifndef __CONSTANTS_H__ +#define __CONSTANTS_H__ + +#define MAX_DUID_SIZE 128 + + +#endif /* __CONSTANTS_H__ */ + + diff --git a/include/public/netmgr.h b/include/public/netmgr.h index ae35bea..2f54345 100644 --- a/include/public/netmgr.h +++ b/include/public/netmgr.h @@ -34,13 +34,49 @@ free_interface( uint32_t ifup( - const char* pszInterfaceName + const char *pszInterfaceName ); uint32_t ifdown( - const char* pszInterfaceName + const char * pszInterfaceName ); +int +set_iaid( + const char *pszInterfaceName, + const uint32_t iaid +); + +int +get_iaid( + const char *pszInterfaceName, + uint32_t *iaid +); + +int +set_duid( + const char *pszInterfaceName, + const char *pszDuid +); + +int +get_duid( + const char *pszInterfaceName, + char *pszDuid +); + +int +set_dns_servers( + const char *pszInterfaceName, + const char *pszDnsServers +); + +int +get_dns_servers( + const char *pszInterfaceName, + char *pszDnsServers +); + #endif /* __NETMGR_H__ */ diff --git a/src/Makefile.am b/src/Makefile.am index e615bc7..cbd3bff 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,8 @@ AM_CFLAGS += $(GLIB_CFLAGS) libnetmgr_la_SOURCES = \ iniparser.c \ - netmgr.c + netmgr.c \ + utils.c libnetmgr_la_LIBADD = \ @top_builddir@/common/libcommon.la \ diff --git a/src/defines.h b/src/defines.h index fbabede..9e35c9c 100644 --- a/src/defines.h +++ b/src/defines.h @@ -14,7 +14,19 @@ #define IsNullOrEmptyString(str) (!(str) || !(*str)) +#ifndef __DEFINES_H__ +#define __DEFINES_H__ + + +#define MAX_LINE 128 + +#define SYSTEMD_PATH "/etc/systemd/" +#define SYSTEMD_NET_PATH "/etc/systemd/network/" + + #define bail_on_error(errcode) \ if (errcode) { \ goto error; \ } + +#endif /* __DEFINES_H__ */ diff --git a/src/includes.h b/src/includes.h index c859046..4b17e42 100644 --- a/src/includes.h +++ b/src/includes.h @@ -19,9 +19,9 @@ #include #include +#include #include - #include #include @@ -29,4 +29,5 @@ #include "defines.h" #include "structs.h" #include "prototypes.h" +#include "utils.h" diff --git a/src/iniparser.c b/src/iniparser.c index a17e2c1..fbfe4ef 100644 --- a/src/iniparser.c +++ b/src/iniparser.c @@ -81,6 +81,10 @@ ini_cfg_read( if (!fgets(buffer, sizeof(buffer), fp)) { + if (feof(fp)) + { + break; + } err = errno; bail_on_error(err); } @@ -292,6 +296,9 @@ ini_cfg_find_sections( bail_on_error(err); } + *pdwNumSections = 0; + *pppSections = NULL; + for (pCursor = pConfig->pSection; pCursor; pCursor = pCursor->pNext) { if (!strcmp(pCursor->pszName, pszName)) diff --git a/src/netmgr.c b/src/netmgr.c index 64a9dd8..66a88d4 100644 --- a/src/netmgr.c +++ b/src/netmgr.c @@ -110,7 +110,7 @@ free_interface( uint32_t ifup( - const char* pszInterfaceName + const char *pszInterfaceName ) { uint32_t err = 0; @@ -131,7 +131,7 @@ ifup( uint32_t ifdown( - const char* pszInterfaceName + const char *pszInterfaceName ) { uint32_t err = 0; @@ -148,3 +148,231 @@ ifdown( goto cleanup; } +int +set_iaid( + const char *pszInterfaceName, + const uint32_t iaid +) +{ + uint32_t err = 0; + char cfgFileName[MAX_LINE]; + const char szSectionName[] = "Link"; + const char szKey[] = "IAID"; + char szValue[MAX_LINE] = ""; + + if (!pszInterfaceName) + { + err = EINVAL; + bail_on_error(err); + } + + sprintf(cfgFileName, "%s10-%s.network", SYSTEMD_NET_PATH, pszInterfaceName); + sprintf(szValue, "%u", iaid); + + if (iaid > 0) + { + err = set_key_value(cfgFileName, szSectionName, szKey, szValue, 0); + } + else + { + err = set_key_value(cfgFileName, szSectionName, szKey, NULL, 0); + } + + bail_on_error(err); + +error: + return err; +} + +int +get_iaid( + const char *pszInterfaceName, + uint32_t *iaid +) +{ + uint32_t err = 0; + char cfgFileName[MAX_LINE]; + const char szSectionName[] = "Link"; + const char szKey[] = "IAID"; + char szIaid[MAX_LINE]; + + if (!pszInterfaceName) + { + err = EINVAL; + bail_on_error(err); + } + + sprintf(cfgFileName, "%s10-%s.network", SYSTEMD_NET_PATH, pszInterfaceName); + + err = get_key_value(cfgFileName, szSectionName, szKey, szIaid); + bail_on_error(err); + + sscanf(szIaid, "%u", iaid); + +error: + return err; +} + +int +set_duid( + const char *pszInterfaceName, + const char *pszDuid +) +{ + uint32_t err = 0; + char cfgFileName[MAX_LINE]; + const char szSectionName[] = "DUID"; + const char szKey[] = "RawData"; + + if (pszInterfaceName != NULL) + { + /* TODO: Add support */ + err = ENOTSUP; + bail_on_error(err); + } + else + { + sprintf(cfgFileName, "%snetworkd.conf", SYSTEMD_PATH); + } + + if (strlen(pszDuid) == 0) + { + err = set_key_value(cfgFileName, szSectionName, szKey, NULL, 0); + } + else + { + err = set_key_value(cfgFileName, szSectionName, szKey, pszDuid, 0); + } + bail_on_error(err); + +error: + return err; +} + +int +get_duid( + const char *pszInterfaceName, + char *pszDuid +) +{ + + uint32_t err = 0; + char cfgFileName[MAX_LINE]; + const char szSectionName[] = "DUID"; + const char szKey[] = "RawData"; + + if (pszInterfaceName != NULL) + { + /* TODO: Add support */ + err = ENOTSUP; + bail_on_error(err); + } + else + { + sprintf(cfgFileName, "%snetworkd.conf", SYSTEMD_PATH); + } + + err = get_key_value(cfgFileName, szSectionName, szKey, pszDuid); + bail_on_error(err); + +error: + return err; +} + +int +set_dns_servers( + const char *pszInterfaceName, + const char *pszDnsServers +) +{ + uint32_t err = 0; + char cfgFileName[MAX_LINE]; + char szSectionName[MAX_LINE]; + char szKey[MAX_LINE] = "DNS"; + char szValue[MAX_LINE]; + DIR *dirFile = NULL; + struct dirent *hFile; + + if (pszInterfaceName != NULL) + { + sprintf(cfgFileName, "%s10-%s.network", SYSTEMD_NET_PATH, pszInterfaceName); + sprintf(szSectionName, "Network"); + } + else + { + sprintf(cfgFileName, "%sresolved.conf", SYSTEMD_PATH); + sprintf(szSectionName, "Resolve"); + } + + if (strlen(pszDnsServers) == 0) + { + sprintf(szValue, "true"); + err = set_key_value(cfgFileName, szSectionName, szKey, NULL, 0); + } + else + { + sprintf(szValue, "false"); + err = set_key_value(cfgFileName, szSectionName, szKey, pszDnsServers, 0); + } + bail_on_error(err); + + /* For each .network file - set 'UseDNS=false' */ + if (pszInterfaceName == NULL) + { + dirFile = opendir(SYSTEMD_NET_PATH); + if (dirFile != NULL) + { + errno = 0; + sprintf(szSectionName, "DHCP"); + sprintf(szKey, "UseDNS"); + while ((hFile = readdir(dirFile)) != NULL) + { + if (!strcmp(hFile->d_name, ".")) continue; + if (!strcmp(hFile->d_name, "..")) continue; + if (hFile->d_name[0] == '.') continue; + if (strstr(hFile->d_name, ".network")) + { + sprintf(cfgFileName, "%s%s", SYSTEMD_NET_PATH, hFile->d_name); + err = set_key_value(cfgFileName, szSectionName, szKey, szValue, 0); + bail_on_error(err); + } + } + } + } + +error: + if (dirFile != NULL) + { + closedir(dirFile); + } + return err; +} + +int +get_dns_servers( + const char *pszInterfaceName, + char *pszDnsServers +) +{ + uint32_t err = 0; + char cfgFileName[MAX_LINE]; + char szSectionName[MAX_LINE]; + char szKey[MAX_LINE] = "DNS"; + + if (pszInterfaceName != NULL) + { + sprintf(cfgFileName, "%s10-%s.network", SYSTEMD_NET_PATH, pszInterfaceName); + sprintf(szSectionName, "Network"); + } + else + { + sprintf(cfgFileName, "%sresolved.conf", SYSTEMD_PATH); + sprintf(szSectionName, "Resolve"); + } + + err = get_key_value(cfgFileName, szSectionName, szKey, pszDnsServers); + bail_on_error(err); + +error: + return err; +} diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..4ca2fcf --- /dev/null +++ b/src/utils.c @@ -0,0 +1,169 @@ +/* + * Copyright © 2016 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the ?~@~\License?~@~]); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an ?~@~\AS IS?~@~] BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#include "includes.h" + +int +set_key_value( + const char *pszConfigFileName, + const char *pszSection, + const char *pszKey, + const char *pszValue, + uint32_t flags +) +{ + uint32_t err = 0, dwNumSections = 0; + PCONFIG_INI pConfig = NULL; + PSECTION_INI *ppSections = NULL, pSection = NULL; + PKEYVALUE_INI pKeyValue = NULL; + FILE *fp; + + if (!pszConfigFileName || !pszSection || !pszKey) + { + err = EINVAL; + bail_on_error(err); + } + + if ((flags & F_CREATE_CFG_FILE) && access(pszConfigFileName, R_OK|W_OK) < 0) + { + /* 'touch' the file */ + if ((fp = fopen(pszConfigFileName, "w")) != NULL) + { + fclose(fp); + } + else + { + /* TODO: Better error reporting */ + err = EINVAL; + bail_on_error(err); + } + } + + err = ini_cfg_read(pszConfigFileName, &pConfig); + bail_on_error(err); + + err = ini_cfg_find_sections(pConfig, pszSection, &ppSections, &dwNumSections); + bail_on_error(err); + + if (dwNumSections > 1) + { + /* TODO: Better error reporting */ + err = EINVAL; + bail_on_error(err); + } + else if ((dwNumSections == 0) && (pszValue != NULL)) + { + err = ini_cfg_add_section(pConfig, pszSection, &pSection); + bail_on_error(err); + } + else + { + pSection = ppSections[0]; + } + + pKeyValue = ini_cfg_find_key(pSection, pszKey); + if (pKeyValue == NULL) + { + if (pszValue != NULL) + { + err = ini_cfg_add_key(pSection, pszKey, pszValue); + } + } + else + { + if (pszValue != NULL) + { + err = ini_cfg_set_value(pSection, pszKey, pszValue); + } + else + { + err = ini_cfg_delete_key(pSection, pszKey); + } + } + bail_on_error(err); + + err = ini_cfg_save(pszConfigFileName, pConfig); + bail_on_error(err); + +error: + if (ppSections != NULL) + { + ini_cfg_free_sections(ppSections, dwNumSections); + } + if (pConfig != NULL) + { + ini_cfg_free_config(pConfig); + } + return err; +} + +int +get_key_value( + const char *pszConfigFileName, + const char *pszSection, + const char *pszKey, + char *pszValue +) +{ + uint32_t err = 0, dwNumSections = 0; + PCONFIG_INI pConfig = NULL; + PSECTION_INI *ppSections = NULL, pSection = NULL; + PKEYVALUE_INI pKeyValue = NULL; + + if (!pszConfigFileName || !pszSection || !pszKey || !pszValue) + { + err = EINVAL; + bail_on_error(err); + } + + err = ini_cfg_read(pszConfigFileName, &pConfig); + bail_on_error(err); + + err = ini_cfg_find_sections(pConfig, pszSection, &ppSections, &dwNumSections); + bail_on_error(err); + + if (dwNumSections > 1) + { + /* TODO: Log error */ + err = EINVAL; + bail_on_error(err); + } + else if (dwNumSections == 0) + { + err = ENOENT; + bail_on_error(err); + } + + pSection = ppSections[0]; + + pKeyValue = ini_cfg_find_key(pSection, pszKey); + if (pKeyValue == NULL) + { + err = ENOENT; + bail_on_error(err); + } + sscanf(pKeyValue->pszValue, "%s", pszValue); + +error: + if (ppSections != NULL) + { + ini_cfg_free_sections(ppSections, dwNumSections); + } + if (pConfig != NULL) + { + ini_cfg_free_config(pConfig); + } + return err; +} + diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..1a71e4d --- /dev/null +++ b/src/utils.h @@ -0,0 +1,37 @@ +/* + * Copyright © 2016 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the ?~@~\License?~@~]); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an ?~@~\AS IS?~@~] BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#ifndef __UTILS_H__ +#define __UTILS_H__ + +#define F_CREATE_CFG_FILE 0x00000001 + +int +set_key_value( + const char *pszConfigFileName, + const char *pszSection, + const char *pszKey, + const char *pszValue, + uint32_t flags +); + +int +get_key_value( + const char *pszConfigFileName, + const char *pszSection, + const char *pszKey, + char *pszValue +); + +#endif /* __UTILS_H__ */ diff --git a/tools/netmgr/main.c b/tools/netmgr/main.c index 6ae17a1..2d8f189 100644 --- a/tools/netmgr/main.c +++ b/tools/netmgr/main.c @@ -24,6 +24,12 @@ int main(int argc, char* argv[]) {"ifup", cmd_ifup}, {"ifdown", cmd_ifdown}, {"list", cmd_list}, + {"set_iaid", cmd_set_iaid}, + {"get_iaid", cmd_get_iaid}, + {"set_duid", cmd_set_duid}, + {"get_duid", cmd_get_duid}, + {"set_dns_servers", cmd_set_dns_servers}, + {"get_dns_servers", cmd_get_dns_servers}, }; int nCommandCount = sizeof(arCmdMap)/sizeof(NETMGR_CLI_CMD_MAP); @@ -209,3 +215,213 @@ cmd_list( error: goto cleanup; } + +uint32_t +cmd_set_iaid( + PNETMGR_CMD_ARGS pCmdArgs + ) +{ + uint32_t err = 0; + + if(!pCmdArgs) + { + err = EINVAL; + bail_on_error(err); + } + + if(pCmdArgs->nCmdCount < 3) + { + err = EDOM; + bail_on_error(err); + } + + err = set_iaid(pCmdArgs->ppszCmds[1], (uint32_t)atoi(pCmdArgs->ppszCmds[2])); + bail_on_error(err); + +cleanup: + return err; +error: + if(err == EDOM) + { + fprintf( + stderr, + "Usage: set_iaid \n"); + } + goto cleanup; +} + +uint32_t +cmd_get_iaid( + PNETMGR_CMD_ARGS pCmdArgs + ) +{ + uint32_t err = 0, iaid; + + if(!pCmdArgs) + { + err = EINVAL; + bail_on_error(err); + } + + if(pCmdArgs->nCmdCount < 2) + { + err = EDOM; + bail_on_error(err); + } + + err = get_iaid(pCmdArgs->ppszCmds[1], &iaid); + bail_on_error(err); + + fprintf(stdout, "IAID=%u\n", iaid); +cleanup: + return err; +error: + if(err == EDOM) + { + fprintf( + stderr, + "Usage: get_iaid \n"); + } + goto cleanup; +} + +uint32_t +cmd_set_duid( + PNETMGR_CMD_ARGS pCmdArgs + ) +{ + uint32_t err = 0; + + if(!pCmdArgs) + { + err = EINVAL; + bail_on_error(err); + } + + if(pCmdArgs->nCmdCount < 2) + { + err = EDOM; + bail_on_error(err); + } + + err = set_duid(NULL, pCmdArgs->ppszCmds[1]); + bail_on_error(err); + +cleanup: + return err; +error: + if(err == EDOM) + { + fprintf( + stderr, + "Usage: set_duid \n"); + } + goto cleanup; +} + +uint32_t +cmd_get_duid( + PNETMGR_CMD_ARGS pCmdArgs + ) +{ + uint32_t err = 0; + char duid[256]; + + if(!pCmdArgs) + { + err = EINVAL; + bail_on_error(err); + } + + if(pCmdArgs->nCmdCount < 1) + { + err = EDOM; + bail_on_error(err); + } + + err = get_duid(NULL, duid); + bail_on_error(err); + + fprintf(stdout, "DUID=%s\n", duid); +cleanup: + return err; +error: + if(err == EDOM) + { + fprintf( + stderr, + "Usage: get_duid\n"); + } + goto cleanup; +} + +uint32_t +cmd_set_dns_servers( + PNETMGR_CMD_ARGS pCmdArgs + ) +{ + uint32_t err = 0; + + if(!pCmdArgs) + { + err = EINVAL; + bail_on_error(err); + } + + if(pCmdArgs->nCmdCount < 2) + { + err = EDOM; + bail_on_error(err); + } + + err = set_dns_servers(NULL, pCmdArgs->ppszCmds[1]); + bail_on_error(err); + +cleanup: + return err; +error: + if(err == EDOM) + { + fprintf( + stderr, + "Usage: set_dns_servers \n"); + } + goto cleanup; +} + +uint32_t +cmd_get_dns_servers( + PNETMGR_CMD_ARGS pCmdArgs + ) +{ + uint32_t err = 0; + char dnsServers[1024]; + + if(!pCmdArgs) + { + err = EINVAL; + bail_on_error(err); + } + + if(pCmdArgs->nCmdCount < 1) + { + err = EDOM; + bail_on_error(err); + } + + err = get_dns_servers(NULL, dnsServers); + bail_on_error(err); + + fprintf(stdout, "DNS=%s\n", dnsServers); +cleanup: + return err; +error: + if(err == EDOM) + { + fprintf( + stderr, + "Usage: get_dns_servers\n"); + } + goto cleanup; +} + diff --git a/tools/netmgr/prototypes.h b/tools/netmgr/prototypes.h index a2f9370..e6ba33e 100644 --- a/tools/netmgr/prototypes.h +++ b/tools/netmgr/prototypes.h @@ -37,6 +37,37 @@ uint32_t cmd_list( PNETMGR_CMD_ARGS pCmdArgs ); + +uint32_t +cmd_set_iaid( + PNETMGR_CMD_ARGS pCmdArgs + ); + +uint32_t +cmd_get_iaid( + PNETMGR_CMD_ARGS pCmdArgs + ); + +uint32_t +cmd_set_duid( + PNETMGR_CMD_ARGS pCmdArgs + ); + +uint32_t +cmd_get_duid( + PNETMGR_CMD_ARGS pCmdArgs + ); + +uint32_t +cmd_set_dns_servers( + PNETMGR_CMD_ARGS pCmdArgs + ); + +uint32_t +cmd_get_dns_servers( + PNETMGR_CMD_ARGS pCmdArgs + ); + //parse_args.c uint32_t parse_args(