ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/services/piped/piped_nw.c b/marvell/services/piped/piped_nw.c
new file mode 100644
index 0000000..44b1a7d
--- /dev/null
+++ b/marvell/services/piped/piped_nw.c
@@ -0,0 +1,374 @@
+
+#include "piped.h"
+#include "piped_uci.h"
+#include "piped_util.h"
+#include "piped_nw.h"
+#include "piped_dhcp.h"
+#include "piped_dns.h"
+
+int pd_nw_add(struct pd_context *pdc, struct pd_iface *pdi)
+{
+	char lan_alias[MAX_IP_STR_LEN];
+	char *lan_ip = NULL;
+	char *network_lan_ip = NULL;
+	struct uci_context *c = pdc->c;
+	int i = 0;
+	int last_oct;
+	int third_oct;
+
+	lan_ip = pd_uci_get_opt(c, UCI_PKG_PIPE, UCI_SEC_LAN, UCI_OPT_IPADDR);
+	if (!lan_ip) {
+		PD_ERR(pd_nw_add, "pd_uci_get_opt failed %s\n", UCI_OPT_IPADDR);
+		return 1;
+	}
+	
+	ipv4_get_alias(pdi->ipaddr, lan_alias);
+	last_oct = ipv4_get_last_oct(pdi->ipaddr);
+	third_oct = ipv4_get_third_oct(pdi->ipaddr);
+	
+	PD_ERR(pd_nw_add_m0, "pd_nw_add: lan_ip=%s, lan_alias=%s\n", lan_ip, lan_alias);
+
+	network_lan_ip = pd_uci_get_opt(c, UCI_PKG_NW, UCI_SEC_LAN, UCI_OPT_IPADDR);
+	PD_ERR(pd_nw_add_m27, "pd_nw_add: network_lan_ip=%s\n", network_lan_ip);
+	
+	if (pd_uci_del(c, UCI_PKG_NW, UCI_SEC_LAN, UCI_OPT_IPADDR,
+		       lan_ip)) {
+		PD_ERR(pd_nw_add1, "pd_uci_del failed %s\n", lan_ip);
+//		return 1;
+	}
+	
+	PD_ERR(pd_nw_add_m0, "pd_nw_add: begin del ipaddr list, i=%d", i);
+	while(!pd_uci_del(c, UCI_PKG_NW, UCI_SEC_LAN, UCI_OPT_IPADDR, NULL)) {		
+		PD_ERR(pd_nw_add_m35, "pd_nw_add: del ipaddr, i=%d", i);
+		i++;
+	}
+
+
+	if (pd_uci_add_list(c, UCI_PKG_NW, UCI_SEC_LAN, UCI_OPT_IPADDR,
+			    lan_alias)) {
+		PD_ERR(pd_nw_add2, "pd_uci_add_listt failed %s\n", lan_alias);
+		return 1;
+	}
+/*	
+	if (pd_uci_add_list(c, UCI_PKG_NW, UCI_SEC_LAN, UCI_OPT_IPADDR,
+			    lan_ip)) {
+		PD_ERR(pd_nw_add3, "pd_uci_add_list failed %s\n", lan_ip);
+		return 1;
+	}
+*/
+	if (last_oct != 255 && last_oct != 0) {
+		if (pd_uci_set_opt(c, UCI_PKG_NW, UCI_SEC_LAN, UCI_OPT_NETMASK,
+				   UCI_DHCP_DFLT_SNMASK)) {
+			PD_ERR(pd_nw_add59, "pd_uci_set_opt failed %s\n", UCI_DHCP_DFLT_SNMASK);
+		}
+	} else {
+		if (third_oct != 255 && third_oct != 0) {
+			if (pd_uci_set_opt(c, UCI_PKG_NW, UCI_SEC_LAN, UCI_OPT_NETMASK,
+					   UCI_DHCP_DFLT_SNMASK1)) {
+				PD_ERR(pd_nw_add66, "pd_uci_set_opt failed %s\n", UCI_DHCP_DFLT_SNMASK1);
+			}
+		} else {
+			if (pd_uci_set_opt(c, UCI_PKG_NW, UCI_SEC_LAN, UCI_OPT_NETMASK,
+					   UCI_DHCP_DFLT_SNMASK2)) {
+				PD_ERR(pd_nw_add71, "pd_uci_set_opt failed %s\n", UCI_DHCP_DFLT_SNMASK2);	
+			}
+		}
+	}
+
+	pd_set(&pdc->status, PDC_NETWORK_CHANGED);
+
+	return 0;
+}
+
+int pd_nw_del(struct pd_context *pdc, struct pd_iface *pdi)
+{
+	char lan_alias[MAX_IP_STR_LEN];
+	struct uci_context *c = pdc->c;
+
+	ipv4_get_alias(pdi->ipaddr, lan_alias);
+	PD_ERR(pd_nw_del_m0, "pd_uci_del_from_list %s\n", lan_alias);
+	if (pd_uci_del_from_list(c, UCI_PKG_NW, UCI_SEC_LAN, UCI_OPT_IPADDR,
+				 lan_alias)) {
+		PD_ERR(pd_nw_del, "pd_uci_del_from_list failed %s\n", lan_alias);
+		return 1;
+	}
+
+	pd_set(&pdc->status, PDC_NETWORK_CHANGED);
+
+	return 0;
+}
+
+int pd_nw_change(struct pd_context *pdc, struct pd_iface *oldi,
+	       struct pd_iface *newi)
+{
+	int ret = 0;
+	if (pd_nw_del(pdc, oldi)) {
+		PD_ERR(pd_nw_change, "pd_nw_del failed for %s\n", oldi->sec);
+		return 1;
+	}
+	if (pd_nw_add(pdc, newi)) {
+		PD_ERR(pd_nw_change1, "pd_nw_add failed for %s\n", newi->sec);
+		return 1;
+	}
+
+#ifdef CONFIG_NETWORK_WAN_IN_PIPE
+	if (!strncasecmp(oldi->sec, "wan", 3)) {
+		ret = pd_nw_wan_config(oldi, false);
+		pd_set(&pdc->status, PDC_NETWORK_CHANGED);
+	}
+	if (!strncasecmp(newi->sec, "wan", 3)) {
+		ret |= pd_nw_wan_config(newi, true);
+		pd_set(&pdc->status, PDC_NETWORK_CHANGED);
+	}
+#endif
+	return ret;
+}
+
+void pd_nw_clean(struct pd_context *pdc)
+{
+	struct uci_context *c = pdc->c;
+
+	PD_INFO(pd_nw_clean, "cleaning network configuration\n");
+
+	if (pd_uci_set_opt(c, UCI_PKG_NW, UCI_SEC_LAN, UCI_OPT_IPADDR,
+			   UCI_NW_DFLT_IP)) {
+		PD_ERR(pd_nw_clean2, "pd_uci_set_opt failed %s\n", UCI_NW_DFLT_IP);
+		return;
+	}
+
+	if (pd_uci_set_opt(c, UCI_PKG_NW, UCI_SEC_LAN, UCI_OPT_NETMASK,
+				   UCI_DHCP_DFLT_SNMASK)) {
+		PD_ERR(pd_nw_clean133, "pd_uci_set_opt failed %s\n", UCI_DHCP_DFLT_SNMASK);
+	}
+	pd_set(&pdc->status, PDC_NETWORK_CHANGED);
+}
+
+#ifdef CONFIG_NETWORK_WAN_IN_PIPE
+int pd_nw_wan_add_del_addr(struct uci_context *c, struct pd_iface *pdi,
+				bool add)
+{
+	int ret = 0;
+	char ip6addr[MAX_IP6_STR_LEN];
+
+	if (add){
+		ret = pd_uci_set_opt(c, UCI_PKG_NW, pdi->sec, UCI_OPT_PROT, UCI_STATIC);
+		ret |= pd_uci_set_opt(c, UCI_PKG_NW, pdi->sec, UCI_OPT_MTU, UCI_DFLT_MTU);
+	}
+	else{
+		ret = pd_uci_set_opt(c, UCI_PKG_NW, pdi->sec, UCI_OPT_PROT, UCI_NONE);
+		ret |= pd_uci_del(c, UCI_PKG_NW, pdi->sec, UCI_OPT_MTU, UCI_DFLT_MTU);
+	}
+
+	if(ret)
+		goto err;
+
+	if (add && pdi->flags & PDI_AUTO)
+		ret = pd_uci_set_opt(c, UCI_PKG_NW, pdi->sec, UCI_OPT_AUTO, "1");
+	else if (pdi->flags & PDI_AUTO)
+		ret = pd_uci_del(c, UCI_PKG_NW, pdi->sec, UCI_OPT_AUTO, "1");
+
+	if (ret)
+		goto err;
+
+	if(pdi->flags & PDI_DEDICATEAPN) {
+		if (add)
+			ret = pd_uci_set_opt(c, UCI_PKG_NW, pdi->sec, UCI_OPT_DEDICATE_OPT, "1");
+		else if (pdi->flags & PDI_DEDICATEAPN)
+			ret = pd_uci_del(c, UCI_PKG_NW, pdi->sec, UCI_OPT_DEDICATE_OPT, "1");
+	} else {
+		if (add)
+			ret = pd_uci_set_opt(c, UCI_PKG_NW, pdi->sec, UCI_OPT_DEDICATE_OPT, "0");
+		else if (pdi->flags & PDI_DEDICATEAPN)
+			ret = pd_uci_del(c, UCI_PKG_NW, pdi->sec, UCI_OPT_DEDICATE_OPT, "0");
+	}
+
+	if (ret)
+		goto err;
+
+	if (add && pdi->flags & PDI_COMBINE_IF)
+		ret = pd_uci_set_opt(c, UCI_PKG_NW, pdi->sec, UCI_OPT_COMBINE_IF_OPT, pdi->combine_if);
+	else if (pdi->flags & PDI_COMBINE_IF)
+		ret = pd_uci_del(c, UCI_PKG_NW, pdi->sec, UCI_OPT_COMBINE_IF_OPT, pdi->combine_if);
+
+	if (ret)
+		goto err;
+
+	PD_INFO(pd_nw_wan_add_del_addr0, "pd_nw_wan_add_del_addr: ip=%s\n", pdi->ipaddr);
+	if (add && pdi->flags & PDI_IPADDR)
+		ret = pd_uci_set_opt(c, UCI_PKG_NW, pdi->sec, UCI_OPT_IPADDR, pdi->ipaddr);
+	else if (pdi->flags & PDI_IPADDR)
+		ret = pd_uci_del(c, UCI_PKG_NW, pdi->sec, UCI_OPT_IPADDR, pdi->ipaddr);
+
+	if (ret)
+		goto err;
+
+	sprintf(ip6addr, "%s/%d", pdi->ip6addr, UCI_IPV6_DFLT_PREF);
+	PD_INFO(pd_nw_wan_add_del_addr1, "pd_nw_wan_add_del_addr: ip6=%s\n", ip6addr);
+	if (add && pdi->flags & PDI_IP6ADDR) {
+		ret = pd_uci_set_opt(c, UCI_PKG_NW, pdi->sec, UCI_OPT_IP6ADDR, ip6addr);
+	} else if (pdi->flags & PDI_IP6ADDR) {
+		ret = pd_uci_del(c, UCI_PKG_NW, pdi->sec, UCI_OPT_IP6ADDR, ip6addr);
+	}
+
+	if(ret)
+		goto err;
+
+	return 0;
+err:
+	PD_ERR(pd_nw_wan_add_del_addr, "failed to [%s] ip address for [%s]\n", add ? "add" : "del", pdi->sec);
+	return ret;
+
+}
+
+int pd_nw_wan_add_del_dns(struct uci_context *c, struct pd_iface *pdi,
+				bool add)
+{
+	int ret = 0;
+	uint i = 0;
+	int flags[] = {pdi->flags & PDI_DNS4P, pdi->flags & PDI_DNS4S,
+		pdi->flags & PDI_DNS6P, pdi->flags & PDI_DNS6S};
+	char *addr[] = {pdi->dns4p, pdi->dns4s, pdi->dns6p, pdi->dns6s};
+
+	PD_INFO(pd_nw_wan_add_del_dns, "%s, %d, add: %d\n", __FUNCTION__, __LINE__, add);
+
+	for (i = 0; i < sizeof(flags)/sizeof(int); i++) {
+		if (flags[i] && add)
+			ret = pd_uci_add_list(c, UCI_PKG_NW, pdi->sec, UCI_OPT_DNS,
+				addr[i]);
+		else if (flags[i])
+			ret = pd_uci_del_from_list(c, UCI_PKG_NW, pdi->sec, UCI_OPT_DNS,
+				addr[i]);
+}
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	PD_ERR(pd_nw_wan_add_del_dns2, "failed to [%s] dns for [%s]\n", add ? "add" : "del", pdi->sec);
+	return ret;
+}
+
+int pd_nw_wan_add_del_mask(struct uci_context *c, struct pd_iface *pdi,
+				bool add)
+{
+	int ret = 0;
+	char netmask[MAX_IP_STR_LEN];
+	int last_oct;
+	int third_oct;
+
+	if (pdi->flags & PDI_IP6ADDR)
+	return 0;
+
+	last_oct = ipv4_get_last_oct(pdi->ipaddr);
+	third_oct = ipv4_get_third_oct(pdi->ipaddr);
+
+	if (last_oct != 255 && last_oct != 0)
+		memcpy(netmask, UCI_DHCP_DFLT_SNMASK, MAX_IP_STR_LEN);
+	else {
+		if (third_oct != 255 && third_oct != 0)
+			memcpy(netmask, UCI_DHCP_DFLT_SNMASK1, MAX_IP_STR_LEN);
+		else
+			memcpy(netmask, UCI_DHCP_DFLT_SNMASK2, MAX_IP_STR_LEN);
+	}
+
+	if (add)
+		ret = pd_uci_set_opt(c, UCI_PKG_NW, pdi->sec, UCI_OPT_NETMASK,
+				netmask);
+	else
+		ret = pd_uci_del(c, UCI_PKG_NW, pdi->sec, UCI_OPT_NETMASK,
+				netmask);
+
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	PD_ERR(pd_nw_wan_add_del_mask, "failed to [%s] netmask for [%s]\n", add ? "add" : "del", pdi->sec);
+	return ret;
+}
+
+int pd_nw_wan_add_del_gw(struct uci_context *c, struct pd_iface *pdi,
+				bool add)
+{
+	int ret = 0;
+
+	if (add)
+		ret = pd_uci_set_opt(c, UCI_PKG_NW, pdi->sec, UCI_OPT_GW, pdi->ipaddr);
+	else
+		ret = pd_uci_del(c, UCI_PKG_NW, pdi->sec, UCI_OPT_GW, pdi->ipaddr);
+
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	PD_ERR(pd_nw_wan_add_del_gw, "failed to [%s] gw for [%s]\n", add ? "add" : "del", pdi->sec);
+	return ret;
+}
+
+int pd_nw_wan_uci_init(struct uci_context **c)
+{
+	struct uci_package *p = NULL;
+
+	*c = uci_alloc_context();
+	if (!*c) {
+		PD_ERR(pd_nw_wan_uci_init, "failed to allocate context\n");
+		return 1;
+	}
+
+	uci_load(*c, UCI_PKG_NW, &p);
+	if (!p) {
+		uci_free_context(*c);
+		PD_ERR(pd_nw_wan_uci_init337, "failed to load network package\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+void pd_nw_wan_uci_done(struct uci_context *c, bool commit)
+{
+	struct uci_package *p;
+
+	if (!c)
+		return;
+
+	if (commit) {
+		if((p = uci_lookup_package(c, UCI_PKG_NW)))
+			uci_commit(c, &p, false);
+	}
+	uci_free_context(c);
+}
+
+int pd_nw_wan_config(struct pd_iface *pdi, bool add)
+{
+	struct uci_context *c = NULL;
+
+	PD_INFO(pd_nw_wan_config, "Enter pd_nw_wan_config, add: %d\n", add);
+
+	if (pd_nw_wan_uci_init(&c))
+		goto err;
+
+	if (pd_nw_wan_add_del_addr(c, pdi, add))
+		goto err;
+
+	if (pd_nw_wan_add_del_gw(c, pdi, add))
+		goto err;
+
+	if (pd_nw_wan_add_del_mask(c, pdi, add))
+		goto err;
+
+	if (pd_nw_wan_add_del_dns(c, pdi, add))
+			goto err;
+
+	pd_nw_wan_uci_done(c, true);
+
+	return 0;
+err:
+	PD_ERR(pd_nw_wan_config414, "pd_nw_wan_config failed\n");
+	pd_nw_wan_uci_done(c, false);
+	return -1;
+
+}
+#endif
+