From 192160f19d388901b44ef62e9265a59282a06ad9 Mon Sep 17 00:00:00 2001 From: darkcoven Date: Sat, 19 Oct 2013 21:55:23 +0200 Subject: [PATCH] Fix network configuration modification --- cli/src/com_netconf.c | 4 ++-- lib/src/netconf.c | 48 +++++++++++++++++++++++++------------------ lib/src/network.c | 5 ++++- raw/src/attr.c | 10 ++++++++- spy/src/spy.c | 2 +- 5 files changed, 44 insertions(+), 25 deletions(-) diff --git a/cli/src/com_netconf.c b/cli/src/com_netconf.c index 31b09ef..277d750 100644 --- a/cli/src/com_netconf.c +++ b/cli/src/com_netconf.c @@ -48,9 +48,9 @@ int do_netconf_set (int argc, const char **argv, struct ngadmin *nga) return 1; } - memset(&nc, 0, sizeof(struct net_conf)); + memcpy(&nc, &sa->nc, sizeof(struct net_conf)); - for (k = 0; k < argc; k += 2) { + for (k = 0; k < argc - 1; k += 2) { if (strcasecmp(argv[k], "dhcp") == 0) { if (strcasecmp(argv[k + 1], "yes") == 0) { nc.dhcp = true; diff --git a/lib/src/netconf.c b/lib/src/netconf.c index 15d0c90..70498c3 100644 --- a/lib/src/netconf.c +++ b/lib/src/netconf.c @@ -122,6 +122,7 @@ int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc) List *attr; int ret = ERR_OK; struct swi_attr *sa; + struct net_conf nc_new; if (nga == NULL || nc == NULL) @@ -131,20 +132,36 @@ int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc) if (sa == NULL) return ERR_NOTLOG; + memcpy(&nc_new, &sa->nc, sizeof(struct net_conf)); + if (nc->ip.s_addr != 0) + nc_new.ip = nc->ip; + if (nc->netmask.s_addr != 0) + nc_new.netmask = nc->netmask; + if (nc->gw.s_addr != 0) + nc_new.gw = nc->gw; + nc_new.dhcp = nc->dhcp; + + /* gateway must be in the network range */ + if ((nc_new.ip.s_addr & nc_new.netmask.s_addr) != (nc_new.gw.s_addr & nc_new.netmask.s_addr)) + return ERR_INVARG; + + /* no need to send anything if old and new configurations are the same */ + if (memcmp(&nc_new, &sa->nc, sizeof(struct net_conf)) == 0) + return ERR_OK; + attr = createEmptyList(); - if (nc->dhcp) { - pushBackList(attr, newShortAttr(ATTR_DHCP, 1)); + /* Note: DHCP attribute is special, it is 2 two bytes long when sent + * by the switch but only 1 byte long when sent by the client + */ + if (nc_new.dhcp) { + pushBackList(attr, newByteAttr(ATTR_DHCP, 1)); } else { - pushBackList(attr, newShortAttr(ATTR_DHCP, 0)); - /* only add non-null values */ - if (nc->ip.s_addr != 0) - pushBackList(attr, newAddrAttr(ATTR_IP, nc->ip)); - if (nc->netmask.s_addr != 0) - pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc->netmask)); - if (nc->gw.s_addr != 0) - pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc->gw)); + pushBackList(attr, newAddrAttr(ATTR_IP, nc_new.ip)); + pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc_new.netmask)); + pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc_new.gw)); + pushBackList(attr, newByteAttr(ATTR_DHCP, 0)); } ret = writeRequest(nga, attr); @@ -153,16 +170,7 @@ int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc) /* update local values */ - sa->nc.dhcp = nc->dhcp; - if (!nc->dhcp) { - if (nc->ip.s_addr !=0) - sa->nc.ip = nc->ip; - if (nc->netmask.s_addr != 0) - sa->nc.netmask = nc->netmask; - if (nc->gw.s_addr != 0) - sa->nc.gw = nc->gw; - } - + memcpy(&sa->nc, &nc_new, sizeof(struct net_conf)); end: diff --git a/lib/src/network.c b/lib/src/network.c index b48461c..8f26fc9 100644 --- a/lib/src/network.c +++ b/lib/src/network.c @@ -357,7 +357,10 @@ void extractSwitchAttributes (struct swi_attr *sa, const List *l) break; case ATTR_DHCP: - sa->nc.dhcp = (ntohs(*(unsigned short*)at->data) == 1); + /* Note: DHCP attribute is special, it is 2 two bytes long when sent + * by the switch but only 1 byte long when sent by the client + */ + sa->nc.dhcp = (at->size == 2) && ((*(unsigned short*)at->data) == 1); break; case ATTR_FIRM_VER: diff --git a/raw/src/attr.c b/raw/src/attr.c index 70f3a18..aec7584 100644 --- a/raw/src/attr.c +++ b/raw/src/attr.c @@ -556,8 +556,16 @@ static int processAttr (struct attr *at, bool encode) return 0; case ATTR_DHCP: - if (at->size != 2) + /* Note: DHCP attribute is special, it is 2 two bytes long + * when sent by the switch but only 1 byte long when sent + * by the client + */ + if (at->size == 1) { + *byte = (*byte != 0); + return 0; + } else if (at->size > 2) { return -EMSGSIZE; + } if (!encode) *word = ntohs(*word); diff --git a/spy/src/spy.c b/spy/src/spy.c index ead684d..2006890 100644 --- a/spy/src/spy.c +++ b/spy/src/spy.c @@ -276,7 +276,7 @@ static void print_attr (const struct attr *at) break; case ATTR_DHCP: - printf("\tDHCP = %s\n", *byte ? "yes" : "no"); + printf("\tDHCP = %s\n", (at->size == 1 ? *byte : *word) ? "yes" : "no"); break; case ATTR_FIRM_VER: -- 2.39.2