Integrate RTNL deeper into IP configuration tracking
[platform/upstream/connman.git] / plugins / ethernet.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <net/if.h>
28
29 #ifndef IFF_LOWER_UP
30 #define IFF_LOWER_UP    0x10000
31 #endif
32
33 #include <glib.h>
34
35 #define CONNMAN_API_SUBJECT_TO_CHANGE
36 #include <connman/plugin.h>
37 #include <connman/device.h>
38 #include <connman/inet.h>
39 #include <connman/rtnl.h>
40 #include <connman/log.h>
41
42 struct ethernet_data {
43         int index;
44         unsigned flags;
45         unsigned int watch;
46 };
47
48 static void ethernet_newlink(unsigned flags, unsigned change, void *user_data)
49 {
50         struct connman_device *device = user_data;
51         struct ethernet_data *ethernet = connman_device_get_data(device);
52
53         DBG("index %d flags %d change %d", ethernet->index, flags, change);
54
55         if ((ethernet->flags & IFF_UP) != (flags & IFF_UP)) {
56                 if (flags & IFF_UP) {
57                         DBG("power on");
58                         connman_device_set_powered(device, TRUE);
59                 } else {
60                         DBG("power off");
61                         connman_device_set_powered(device, FALSE);
62                 }
63         }
64
65         if ((ethernet->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
66                 if (flags & IFF_LOWER_UP) {
67                         DBG("carrier on");
68                         connman_device_set_carrier(device, TRUE);
69                 } else {
70                         DBG("carrier off");
71                         connman_device_set_carrier(device, FALSE);
72                 }
73         }
74
75         ethernet->flags = flags;
76 }
77
78 static int ethernet_probe(struct connman_device *device)
79 {
80         struct ethernet_data *ethernet;
81
82         DBG("device %p", device);
83
84         ethernet = g_try_new0(struct ethernet_data, 1);
85         if (ethernet == NULL)
86                 return -ENOMEM;
87
88         connman_device_set_data(device, ethernet);
89
90         ethernet->index = connman_device_get_index(device);
91         ethernet->flags = 0;
92
93         ethernet->watch = connman_rtnl_add_newlink_watch(ethernet->index,
94                                                 ethernet_newlink, device);
95
96         return 0;
97 }
98
99 static void ethernet_remove(struct connman_device *device)
100 {
101         struct ethernet_data *ethernet = connman_device_get_data(device);
102
103         DBG("device %p", device);
104
105         connman_device_set_data(device, NULL);
106
107         connman_rtnl_remove_watch(ethernet->watch);
108
109         g_free(ethernet);
110 }
111
112 static int ethernet_enable(struct connman_device *device)
113 {
114         struct ethernet_data *ethernet = connman_device_get_data(device);
115
116         DBG("device %p", device);
117
118         return connman_inet_ifup(ethernet->index);
119 }
120
121 static int ethernet_disable(struct connman_device *device)
122 {
123         struct ethernet_data *ethernet = connman_device_get_data(device);
124
125         DBG("device %p", device);
126
127         return connman_inet_ifdown(ethernet->index);
128 }
129
130 static int ethernet_connect(struct connman_device *device)
131 {
132         struct ethernet_data *ethernet = connman_device_get_data(device);
133
134         DBG("device %p", device);
135
136         if (!(ethernet->flags & IFF_LOWER_UP))
137                 return -ENOTCONN;
138
139         return connman_device_set_connected(device, TRUE);
140 }
141
142 static int ethernet_disconnect(struct connman_device *device)
143 {
144         struct ethernet_data *ethernet = connman_device_get_data(device);
145
146         DBG("device %p", device);
147
148         if (!(ethernet->flags & IFF_LOWER_UP))
149                 return -ENOTCONN;
150
151         return connman_device_set_connected(device, FALSE);
152 }
153
154 static struct connman_device_driver ethernet_driver = {
155         .name           = "ethernet",
156         .type           = CONNMAN_DEVICE_TYPE_ETHERNET,
157         .probe          = ethernet_probe,
158         .remove         = ethernet_remove,
159         .enable         = ethernet_enable,
160         .disable        = ethernet_disable,
161         .connect        = ethernet_connect,
162         .disconnect     = ethernet_disconnect,
163 };
164
165 static int ethernet_init(void)
166 {
167         return connman_device_driver_register(&ethernet_driver);
168 }
169
170 static void ethernet_exit(void)
171 {
172         connman_device_driver_unregister(&ethernet_driver);
173 }
174
175 CONNMAN_PLUGIN_DEFINE(ethernet, "Ethernet interface plugin", VERSION,
176                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ethernet_init, ethernet_exit)