4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
23 * @desc Network interface callbacks entity
25 * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
30 #include "datausage-common.h"
31 #include "restriction-handler.h"
37 #include <linux/genetlink.h>
38 #include <linux/netlink.h>
39 #include <linux/rtnetlink.h>
41 #include <netinet/in.h>
42 #include <sys/socket.h> /*for netlink.h*/
43 #include <sys/types.h>
46 #define ADDR_EVENT_BUF_LEN 4096
49 static iface_callbacks *ifcallbacks;
50 static Ecore_Fd_Handler *iface_ecore_fd_handler;
52 static iface_callbacks *create_iface_callback(void)
54 iface_callbacks *callbacks = NULL;
55 gpointer callback_data = create_restriction_callback();
58 callbacks = g_list_prepend(callbacks, callback_data);
59 callback_data = create_iface_storage_callback();
61 callbacks = g_list_prepend(callbacks, callback_data);
62 callback_data = create_counter_callback();
64 callbacks = g_list_prepend(callbacks, callback_data);
69 static void _iface_up_iter(gpointer data, gpointer user_data)
71 iface_callback *arg = (iface_callback *)data;
72 uint32_t ifindex = *(uint32_t *) (user_data);
73 if (arg && arg->handle_iface_up)
74 arg->handle_iface_up(ifindex);
77 static void _iface_down_iter(gpointer data, gpointer user_data)
79 iface_callback *arg = (iface_callback *)data;
80 uint32_t ifindex = *(uint32_t *)(user_data);
81 if (arg && arg->handle_iface_down)
82 arg->handle_iface_down(ifindex);
85 static void process_nlh(int len, const struct nlmsghdr *nlh,
89 _D("Please provide valid argument!");
93 for (; (NLMSG_OK(nlh, len)) &&
94 (nlh->nlmsg_type != NLMSG_DONE);
95 nlh = NLMSG_NEXT(nlh, len)) {
96 if (nlh->nlmsg_type != RTM_NEWADDR
97 && nlh->nlmsg_type != RTM_DELADDR)
100 struct ifaddrmsg *ifa =
101 (struct ifaddrmsg *) NLMSG_DATA(nlh);
102 struct rtattr *rth = IFA_RTA(ifa);
103 int rtl = IFA_PAYLOAD(nlh);
105 for (; rtl && RTA_OK(rth, rtl);
106 rth = RTA_NEXT(rth, rtl)) {
107 if (rth->rta_type != IFA_LOCAL)
110 if (nlh->nlmsg_type == RTM_NEWADDR) {
112 return g_list_foreach(arg, _iface_up_iter,
115 } else if (nlh->nlmsg_type == RTM_DELADDR) {
116 g_list_foreach(arg, _iface_down_iter,
118 /* network delete hooks require old information,
119 * for example for get_iftype by ifindex */
127 static Eina_Bool iface_func_cb(void *user_data, Ecore_Fd_Handler *fd_handler)
129 char buff[ADDR_EVENT_BUF_LEN];
130 struct nlmsghdr *nlh;
131 iface_callbacks *localiarg = (iface_callbacks *)user_data;
135 if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) {
136 _E("ecore_main_fd_handler_active_get error , return\n");
137 return ECORE_CALLBACK_RENEW;
140 fd = ecore_main_fd_handler_fd_get(fd_handler);
142 _E("ecore_main_fd_handler_fd_get error");
143 return ECORE_CALLBACK_RENEW;
146 len = read(fd, buff, ADDR_EVENT_BUF_LEN);
148 _E("socket read error");
149 return ECORE_CALLBACK_RENEW;
152 nlh = (struct nlmsghdr *)buff;
153 process_nlh(len, nlh, localiarg);
155 return ECORE_CALLBACK_RENEW;
158 static int iface_func_init()
160 struct sockaddr_nl addr = {0};
161 int sock, error = 0, on;
163 sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
165 _E("Error creating NETLINK_ROUTE socket");
170 addr.nl_family = AF_NETLINK;
171 addr.nl_groups = RTMGRP_IPV4_IFADDR;
172 /* Enable address reuse */
174 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
175 _E("Error setsockopt");
180 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
181 _E("Error bind socket");
186 _D("Socket created successfully\n");
196 static void apply_iface_options(void)
198 resourced_options options = { 0 };
200 load_options(&options);
201 set_wifi_allowance(options.wifi);
202 set_datacall_allowance(options.datacall);
205 int resourced_iface_init(void)
207 ifcallbacks = create_iface_callback();
208 _D("Initialize network interface callbacks\n");
209 ret_value_msg_if(ifcallbacks == NULL, RESOURCED_ERROR_FAIL,
210 "Error create network interface callbacks");
211 iface_fd = iface_func_init();
212 ret_value_msg_if(iface_fd < 0, RESOURCED_ERROR_FAIL,
213 "Can not listen network interface changes %d",
215 iface_ecore_fd_handler = ecore_main_fd_handler_add(
216 iface_fd, ECORE_FD_READ, iface_func_cb,
217 (void *)ifcallbacks, NULL, NULL);
218 ret_value_msg_if(iface_ecore_fd_handler == NULL, RESOURCED_ERROR_FAIL,
219 "Failed to add iface callbacks\n");
220 apply_iface_options();
221 return RESOURCED_ERROR_NONE;
224 void resourced_iface_finalize(void)
226 _D("Finalize network interface callbacks\n");
227 ecore_main_fd_handler_del(iface_ecore_fd_handler);
228 shutdown(iface_fd, 2);
231 g_list_free_full(ifcallbacks, free);