dnsproxy: Only one copy of the relevant buffers will be made to a TCP request
[framework/connectivity/connman.git] / src / bridge.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
6  *  Copyright (C) 2012  BMW Car IT GmbH. All rights reserved.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License version 2 as
10  *  published by the Free Software Foundation.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <sys/ioctl.h>
33 #include <net/if.h>
34 #include <linux/sockios.h>
35 #include <string.h>
36 #include <fcntl.h>
37 #include <linux/if_tun.h>
38
39 #include "connman.h"
40
41 static int set_forward_delay(const char *name, unsigned int delay)
42 {
43         FILE *f;
44         char *forward_delay_path;
45
46         forward_delay_path =
47                 g_strdup_printf("/sys/class/net/%s/bridge/forward_delay", name);
48
49         if (forward_delay_path == NULL)
50                 return -ENOMEM;
51
52         f = fopen(forward_delay_path, "r+");
53
54         g_free(forward_delay_path);
55
56         if (f == NULL)
57                 return -errno;
58
59         fprintf(f, "%d", delay);
60
61         fclose(f);
62
63         return 0;
64 }
65
66 int __connman_bridge_create(const char *name)
67 {
68         int sk, err;
69
70         DBG("name %s", name);
71
72         sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
73         if (sk < 0)
74                 return -EOPNOTSUPP;
75
76         if (ioctl(sk, SIOCBRADDBR, name) == -1) {
77                 err = -errno;
78                 if (err != -EEXIST)
79                         return -EOPNOTSUPP;
80         }
81
82         err = set_forward_delay(name, 0);
83
84         if (err < 0)
85                 ioctl(sk, SIOCBRDELBR, name);
86
87         close(sk);
88
89         return err;
90 }
91
92 int __connman_bridge_remove(const char *name)
93 {
94         int sk, err;
95
96         DBG("name %s", name);
97
98         sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
99         if (sk < 0)
100                 return -EOPNOTSUPP;
101
102         err = ioctl(sk, SIOCBRDELBR, name);
103
104         close(sk);
105
106         if (err < 0)
107                 return -EOPNOTSUPP;
108
109         return 0;
110 }
111
112 int __connman_bridge_enable(const char *name, const char *gateway,
113                                 const char *broadcast)
114 {
115         int err, index;
116
117         index = connman_inet_ifindex(name);
118         if (index < 0)
119                 return index;
120
121         err = __connman_inet_modify_address(RTM_NEWADDR,
122                         NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
123                                         gateway, NULL, 24, broadcast);
124         if (err < 0)
125                 return err;
126
127         return connman_inet_ifup(index);
128 }
129
130 int __connman_bridge_disable(const char *name)
131 {
132         int index;
133
134         index = connman_inet_ifindex(name);
135         if (index < 0)
136                 return index;
137
138         return connman_inet_ifdown(index);
139 }