Ticket refs #10128 : ipv6 Support

This commit is contained in:
imen.bhiri 2016-09-26 15:09:36 +01:00
parent 0537fff722
commit cd55e17e49
12 changed files with 193 additions and 21 deletions

View file

@ -2013,6 +2013,14 @@ int cwmp_load_saved_session(struct cwmp *cwmp, char **ret, enum backup_loading l
break;
}
}
if(load == CR_IPv6)
{
if(b->type == MXML_ELEMENT && strcmp(b->value.element.name, "connection_request") == 0)
{
*ret = load_child_value(b, "ipv6");
break;
}
}
if(load == CR_PORT)
{
if(b->type == MXML_ELEMENT && strcmp(b->value.element.name, "connection_request") == 0)

7
cwmp.c
View file

@ -32,6 +32,7 @@
struct cwmp cwmp_main = {0};
int ip_version = 4;
LIST_HEAD(list_execute_end_session);
int dm_add_end_session(void(*function)(int a, void *d), int action, void *data)
@ -533,7 +534,7 @@ int run_session_end_func (struct session *session)
{
CWMP_LOG (INFO,"Executing external commands: end session request");
external_init();
external_simple("end_session", NULL);
external_simple("end_session", NULL, 0);
external_exit();
}
@ -541,7 +542,7 @@ int run_session_end_func (struct session *session)
{
CWMP_LOG (INFO,"Executing factory reset: end session request");
external_init();
external_simple("factory_reset", NULL);
external_simple("factory_reset", NULL, 0);
external_exit();
exit(EXIT_SUCCESS);
}
@ -556,7 +557,7 @@ int run_session_end_func (struct session *session)
{
CWMP_LOG (INFO,"Executing Reboot: end session request");
external_init();
external_simple("reboot", NULL);
external_simple("reboot", NULL, 0);
external_exit();
exit(EXIT_SUCCESS);
}

View file

@ -21,6 +21,7 @@
#include <sys/stat.h>
#include <sys/wait.h>
#include <uci.h>
#include <cwmp.h>
#include "dmcwmp.h"
#include "dmuci.h"
#include "dmubus.h"
@ -378,10 +379,21 @@ int ipcalc_rev_end(char *ip_str, char *mask_str, char *start_str, char *ipend_st
int network_get_ipaddr(char **value, char *iface)
{
json_object *res;
char *ipv6_value = "";
dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", iface}}, 1, &res);
DM_ASSERT(res, *value = "");
json_select(res, "ipv4-address", 0, "address", value, NULL);
json_select(res, "ipv6-address", 0, "address", &ipv6_value, NULL);
if((*value)[0] == '\0' || ipv6_value[0] == '\0') {
if ((*value)[0] == '\0')
*value = ipv6_value;
}
else if (ip_version == 6) {
*value = ipv6_value;
return 0;
}
return 0;
}

18
event.c
View file

@ -734,21 +734,25 @@ void sotfware_version_value_change(struct cwmp *cwmp, struct transfer_complete *
}
void connection_request_ip_value_change(struct cwmp *cwmp)
void connection_request_ip_value_change(struct cwmp *cwmp, int version)
{
char *bip = NULL;
struct event_container *event_container;
int error;
char *ip_version = (version == IPv6) ? strdup("ipv6") : strdup("ip");
char *ip_value = (version == IPv6) ? strdup(cwmp->conf.ipv6) : strdup(cwmp->conf.ip);
error = cwmp_load_saved_session(cwmp, &bip, CR_IP);
error = (version == IPv6) ? cwmp_load_saved_session(cwmp, &bip, CR_IPv6): cwmp_load_saved_session(cwmp, &bip, CR_IP);
if(bip == NULL)
{
bkp_session_simple_insert_in_parent("connection_request", "ip", cwmp->conf.ip);
bkp_session_simple_insert_in_parent("connection_request", ip_version, ip_value);
bkp_session_save();
FREE(ip_version);
FREE(ip_value);
return;
}
if (strcmp(bip, cwmp->conf.ip)!=0)
if (strcmp(bip, ip_value)!=0)
{
pthread_mutex_lock (&(cwmp->mutex_session_queue));
event_container = cwmp_add_event_container (cwmp, EVENT_IDX_4VALUE_CHANGE, "");
@ -756,15 +760,19 @@ void connection_request_ip_value_change(struct cwmp *cwmp)
{
FREE(bip);
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
FREE(ip_version);
FREE(ip_value);
return;
}
cwmp_save_event_container (cwmp,event_container);
bkp_session_simple_insert_in_parent("connection_request", "ip", cwmp->conf.ip);
bkp_session_simple_insert_in_parent("connection_request", ip_version, ip_value);
bkp_session_save();
pthread_mutex_unlock (&(cwmp->mutex_session_queue));
pthread_cond_signal(&(cwmp->threshold_session_send));
}
FREE(bip);
FREE(ip_version);
FREE(ip_value);
}
void connection_request_port_value_change(struct cwmp *cwmp, int port)

View file

@ -231,7 +231,7 @@ int external_handle_action(int (*external_handler)(char *msg))
return 0;
}
int external_simple(char *command, char *arg)
int external_simple(char *command, char *arg, int c)
{
DD(INFO,"executing %s request", command);
@ -243,6 +243,7 @@ int external_simple(char *command, char *arg)
json_obj_out_add(json_obj_out, "command", command);
if (arg) json_obj_out_add(json_obj_out, "arg", arg);
if (c) json_obj_out_add(json_obj_out, "ipv6", "1");
external_write_pipe_output(json_object_to_json_string(json_obj_out));
json_object_put(json_obj_out);

30
http.c
View file

@ -53,6 +53,7 @@ http_client_init(struct cwmp *cwmp)
{
char *dhcp_dis;
char *acs_var_stat;
unsigned char buf[sizeof(struct in6_addr)];
uci_get_value(UCI_DHCP_DISCOVERY_PATH, &dhcp_dis);
#ifdef HTTP_CURL
if (dhcp_dis && cwmp->retry_count_session > 0 && strcmp(dhcp_dis, "enable") == 0) {
@ -108,6 +109,14 @@ http_client_init(struct cwmp *cwmp)
return -1;
#endif /* HTTP_ZSTREAM */
char *ip = NULL;
curl_easy_setopt(curl, CURLOPT_URL, http_c.url);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, HTTP_TIMEOUT);
curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
curl_easy_getinfo(curl, CURLINFO_PRIMARY_IP, &ip);
curl_easy_perform(curl);
int tmp = inet_pton(AF_INET, ip, buf);
ip_version = (tmp == 1) ? 4 : 6;
return 0;
}
@ -157,6 +166,7 @@ http_get_response(void *buffer, size_t size, size_t rxed, char **msg_in)
int
http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len,char **msg_in)
{
unsigned char buf[sizeof(struct in6_addr)];
#ifdef HTTP_CURL
CURLcode res;
long http_code = 0;
@ -181,6 +191,7 @@ http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len,char **msg_i
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, HTTP_TIMEOUT);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
switch (cwmp->conf.compression) {
case COMP_NONE:
break;
@ -240,8 +251,13 @@ http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len,char **msg_i
if (!ip_acs || strcmp(ip_acs, ip) != 0) {
FREE(ip_acs);
ip_acs = strdup(ip);
int tmp = inet_pton(AF_INET, ip, buf);
if (tmp == 1)
tmp = 0;
else
tmp = inet_pton(AF_INET6, ip, buf);
external_init();
external_simple("allow_cr_ip", ip_acs);
external_simple("allow_cr_ip", ip_acs, tmp);
external_exit();
}
}
@ -390,14 +406,14 @@ http_done:
void http_server_init(void)
{
struct sockaddr_in server = {0};
struct sockaddr_in6 server = {0};
unsigned short cr_port;
for(;;) {
cr_port = (unsigned short) (cwmp_main.conf.connection_request_port);
unsigned short i = (DEFAULT_CONNECTION_REQUEST_PORT == cr_port)? 1 : 0;
//Create socket
cwmp_main.cr_socket_desc = socket(AF_INET , SOCK_STREAM , 0);
cwmp_main.cr_socket_desc = socket(AF_INET6 , SOCK_STREAM , 0);
if (cwmp_main.cr_socket_desc == -1)
{
CWMP_LOG (ERROR,"Could not open server socket for Connection Requests, Error no is : %d, Error description is : %s", errno, strerror(errno));
@ -414,11 +430,11 @@ void http_server_init(void)
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin6_family = AF_INET6;
server.sin6_addr=in6addr_any;
for(;;i++) {
server.sin_port = htons(cr_port);
server.sin6_port = htons(cr_port);
//Bind
if( bind(cwmp_main.cr_socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
@ -446,7 +462,7 @@ void http_server_listen(void)
static time_t restrict_start_time = 0;
time_t current_time;
bool service_available;
struct sockaddr_in client;
struct sockaddr_in6 client;
//Listen
listen(cwmp_main.cr_socket_desc , 3);

View file

@ -31,6 +31,7 @@ typedef enum backup_loading {
ALL,
ACS,
CR_IP,
CR_IPv6,
CR_PORT
} backup_loading;

View file

@ -180,6 +180,7 @@ typedef struct config {
char *cpe_passwd;
char *dhcp_url_path;
char *ip;
char *ipv6;
char *interface;
char *ubus_socket;
int connection_request_port;
@ -230,6 +231,11 @@ enum enum_session_status {
SESSION_SUCCESS
};
enum enum_ip_version {
IPv4 = 4,
IPv6 = 6
};
struct deviceid {
char *manufacturer;
char *oui;
@ -310,6 +316,7 @@ typedef struct execute_end_session {
void (*function)(int, void*);
} execute_end_session;
extern int ip_version;
#define ARRAYSIZEOF(a) (sizeof(a) / sizeof((a)[0]))
#define FREE(x) do { free(x); x = NULL; } while (0)
@ -335,7 +342,7 @@ int netlink_init(void);
char * mix_get_time(void);
char * mix_get_time_of(time_t t_time);
void *thread_exit_program (void *v);
void connection_request_ip_value_change(struct cwmp *cwmp);
void connection_request_ip_value_change(struct cwmp *cwmp, int version);
void connection_request_port_value_change(struct cwmp *cwmp, int port);
void add_dm_parameter_tolist(struct list_head *head, char *param_name, char *param_data, char *param_type);
void cwmp_set_end_session (unsigned int end_session_flag);

View file

@ -27,7 +27,7 @@ void external_uploadFaultResp (char *fault_code);
void external_fetch_uploadFaultResp (char **fault_code);
void external_uninstallFaultResp (char *fault_code);
void external_fetch_uninstallFaultResp (char **fault);
int external_simple(char *command, char *arg);
int external_simple(char *command, char *arg, int c);
int external_download(char *url, char *size, char *type, char *user, char *pass,time_t c);
int external_upload(char *url, char *type, char *user, char *pass, char *name);
int external_apply(char *action, char *arg,time_t c);

113
netlink.c
View file

@ -34,7 +34,9 @@
#include "log.h"
static void netlink_new_msg(struct uloop_fd *ufd, unsigned events);
static void netlink_new_msg_v6(struct uloop_fd *ufd, unsigned events);
static struct uloop_fd netlink_event = { .cb = netlink_new_msg };
static struct uloop_fd netlink_event_v6 = { .cb = netlink_new_msg };
static void freecwmp_netlink_interface(struct nlmsghdr *nlh)
{
@ -47,6 +49,8 @@ static void freecwmp_netlink_interface(struct nlmsghdr *nlh)
memset(&if_name, 0, sizeof(if_name));
memset(&if_addr, 0, sizeof(if_addr));
char pradd_v6[128];
if(ifa->ifa_family == AF_INET) { //CASE IPv4
while (rtl && RTA_OK(rth, rtl)) {
if (rth->rta_type != IFA_LOCAL) {
rth = RTA_NEXT(rth, rtl);
@ -76,11 +80,33 @@ static void freecwmp_netlink_interface(struct nlmsghdr *nlh)
uci_set_state_value(c);
free(c);
}
connection_request_ip_value_change(&cwmp_main);
connection_request_ip_value_change(&cwmp_main, IPv4);
break;
}
if (strlen(if_addr) == 0) return;
} else { //CASE IPv6
while (rtl && RTA_OK(rth, rtl)) {
if (rth->rta_type != IFA_ADDRESS || ifa->ifa_scope == RT_SCOPE_LINK) {
rth = RTA_NEXT(rth, rtl);
continue;
}
inet_ntop(AF_INET6, RTA_DATA(rth), pradd_v6, sizeof(pradd_v6));
if_indextoname(ifa->ifa_index, if_name);
if (strncmp(cwmp_main.conf.interface, if_name, IFNAMSIZ)) {
rth = RTA_NEXT(rth, rtl);
continue;
}
if (cwmp_main.conf.ipv6) FREE(cwmp_main.conf.ipv6);
cwmp_main.conf.ipv6 = strdup(pradd_v6);
if (asprintf(&c,"cwmp.cpe.ipv6=%s",cwmp_main.conf.ipv6) != -1)
{
uci_set_state_value(c);
free(c);
}
connection_request_ip_value_change(&cwmp_main, IPv6);
break;
}
}
}
static void netlink_new_msg(struct uloop_fd *ufd, unsigned events)
@ -119,6 +145,89 @@ static void netlink_new_msg(struct uloop_fd *ufd, unsigned events)
}
}
static void netlink_new_msg_v6(struct uloop_fd *ufd, unsigned events)
{
struct nlmsghdr *nlh;
char buffer[BUFSIZ];
int msg_size;
memset(&buffer, 0, sizeof(buffer));
nlh = (struct nlmsghdr *)buffer;
if ((msg_size = recv(ufd->fd, nlh, BUFSIZ, 0)) == -1) {
CWMP_LOG(ERROR,"error receiving netlink message");
return;
}
while (msg_size > sizeof(*nlh)) {
int len = nlh->nlmsg_len;
int req_len = len - sizeof(*nlh);
if (req_len < 0 || len > msg_size) {
CWMP_LOG(ERROR,"error reading netlink message");
return;
}
if (!NLMSG_OK(nlh, msg_size)) {
CWMP_LOG(ERROR,"netlink message is not NLMSG_OK");
return;
}
if (nlh->nlmsg_type == RTM_NEWADDR) {
freecwmp_netlink_interface(nlh);
}
msg_size -= NLMSG_ALIGN(len);
nlh = (struct nlmsghdr*)((char*)nlh + NLMSG_ALIGN(len));
}
}
int netlink_init_v6(void)
{
struct {
struct nlmsghdr hdr;
struct ifaddrmsg msg;
} req;
struct sockaddr_nl addr;
int sock[2];
memset(&addr, 0, sizeof(addr));
memset(&req, 0, sizeof(req));
if ((sock[0] = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) {
CWMP_LOG(ERROR,"couldn't open NETLINK_ROUTE socket");
return -1;
}
addr.nl_family = AF_NETLINK;
addr.nl_groups = RTMGRP_IPV6_IFADDR;
if ((bind(sock[0], (struct sockaddr_in6 *)&addr, sizeof(addr))) == -1) {
CWMP_LOG(ERROR,"couldn't bind netlink socket");
return -1;
}
netlink_event_v6.fd = sock[0];
uloop_fd_add(&netlink_event_v6, ULOOP_READ | ULOOP_EDGE_TRIGGER);
if ((sock[1] = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) == -1) {
CWMP_LOG(ERROR,"couldn't open NETLINK_ROUTE socket");
return -1;
}
req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
req.hdr.nlmsg_type = RTM_GETADDR;
req.msg.ifa_family = AF_INET6;
if ((send(sock[1], &req, req.hdr.nlmsg_len, 0)) == -1) {
CWMP_LOG(ERROR,"couldn't send netlink socket");
return -1;
}
struct uloop_fd dummy_event = { .fd = sock[1] };
netlink_new_msg(&dummy_event, 0);
return 0;
}
int netlink_init(void)
{
struct {

View file

@ -120,6 +120,7 @@ case "$1" in
allow_cr_ip)
action="allow_cr_ip"
__arg1="$2"
__arg2="$3"
;;
json_continuous_input)
action="json_continuous_input"
@ -361,7 +362,11 @@ handle_action() {
local zone_name=`$UCI_GET firewall.$zone.name`
[ "$zone_name" = "" ] && return
# update iptables rule
sed -i "s,^.*Open ACS port.*,iptables -I zone_${zone_name}_input -p tcp -s $__arg1 --dport $port -j ACCEPT -m comment --comment=\"Open ACS port\",g" /etc/firewall.cwmp
if [ "$__arg2" != "1" ]; then
sed -i "s,^.*iptables.*Open ACS port.*,iptables -I zone_${zone_name}_input -p tcp -s $__arg1 --dport $port -j ACCEPT -m comment --comment=\"Open ACS port\",g" /etc/firewall.cwmp
else
sed -i "s,^.*iptables.*Open ACS port.*,ip6tables -I zone_${zone_name}_input -p tcp -s $__arg1 --dport $port -j ACCEPT -m comment --comment=\"Open ACS port\",g" /etc/firewall.cwmp
fi
fw3 reload
fi
@ -470,6 +475,7 @@ handle_action() {
allow_cr_ip)
action="allow_cr_ip"
json_get_var __arg1 arg
json_get_var __arg2 ipv6
;;
end)
echo "$CWMP_PROMPT"

3
ubus.c
View file

@ -329,6 +329,9 @@ ubus_init(struct cwmp *cwmp)
CWMP_LOG(ERROR,"netlink initialization failed");
}
if (netlink_init_v6()) {
CWMP_LOG(ERROR,"netlink initialization failed");
}
ctx = ubus_connect(cwmp->conf.ubus_socket);
if (!ctx) return -1;