completed pkcs7 parsing methods
[strongswan.git] / src / dumm / bridge.c
1 /*
2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <sys/types.h>
17 #include <libbridge.h>
18
19 #include <debug.h>
20 #include <utils/linked_list.h>
21
22 #include "bridge.h"
23
24 typedef struct private_bridge_t private_bridge_t;
25
26 struct private_bridge_t {
27 /** public interface */
28 bridge_t public;
29 /** device name */
30 char *name;
31 /** list of attached interfaces */
32 linked_list_t *ifaces;
33 };
34
35 /**
36 * Implementation of bridge_t.get_name.
37 */
38 static char* get_name(private_bridge_t *this)
39 {
40 return this->name;
41 }
42
43 /**
44 * Implementation of bridge_t.create_iface_iterator.
45 */
46 static iterator_t* create_iface_iterator(private_bridge_t *this)
47 {
48 return this->ifaces->create_iterator(this->ifaces, TRUE);
49 }
50
51 /**
52 * Implementation of bridge_t.disconnect_iface.
53 */
54 static bool disconnect_iface(private_bridge_t *this, iface_t *iface)
55 {
56 iterator_t *iterator;
57 iface_t *current;
58 bool good = FALSE;
59
60 iterator = this->ifaces->create_iterator(this->ifaces, TRUE);
61 while (iterator->iterate(iterator, (void**)&current))
62 {
63 if (current == iface)
64 {
65 if (br_del_interface(this->name, iface->get_hostif(iface)) != 0)
66 {
67 DBG1("removing iface '%s' from bridge '%s' in kernel failed: %m",
68 iface->get_hostif(iface), this->name);
69 }
70 else
71 {
72 iface->set_bridge(iface, NULL);
73 good = TRUE;
74 }
75 break;
76 }
77 }
78 if (iface != current)
79 {
80 DBG1("iface '%s' not found on bridge '%s'", iface->get_hostif(iface),
81 this->name);
82 }
83 iterator->destroy(iterator);
84 return good;
85 }
86
87 /**
88 * Implementation of bridge_t.connect_iface.
89 */
90 static bool connect_iface(private_bridge_t *this, iface_t *iface)
91 {
92 if (br_add_interface(this->name, iface->get_hostif(iface)) != 0)
93 {
94 DBG1("adding iface '%s' to bridge '%s' failed: %m",
95 iface->get_hostif(iface), this->name);
96 return FALSE;
97 }
98 iface->set_bridge(iface, &this->public);
99 this->ifaces->insert_last(this->ifaces, iface);
100 return TRUE;
101 }
102
103 /**
104 * instance counter to (de-)initialize libbridge
105 */
106 static int instances = 0;
107
108 /**
109 * unregister an interface from bridge
110 */
111 static void unregister(iface_t *iface)
112 {
113 iface->set_bridge(iface, NULL);
114 }
115
116 /**
117 * Implementation of bridge_t.destroy.
118 */
119 static void destroy(private_bridge_t *this)
120 {
121 this->ifaces->invoke_function(this->ifaces, (void(*)(void*))unregister);
122 this->ifaces->destroy(this->ifaces);
123 if (br_del_bridge(this->name) != 0)
124 {
125 DBG1("deleting bridge '%s' from kernel failed: %m", this->name);
126 }
127 free(this->name);
128 free(this);
129 if (--instances == 0)
130 {
131 br_shutdown();
132 }
133 }
134
135 /**
136 * create the bridge instance
137 */
138 bridge_t *bridge_create(char *name)
139 {
140 private_bridge_t *this;
141
142 if (instances == 0)
143 {
144 if (br_init() != 0)
145 {
146 DBG1("libbridge initialization failed: %m");
147 return NULL;
148 }
149 }
150
151 this = malloc_thing(private_bridge_t);
152 this->public.get_name = (char*(*)(bridge_t*))get_name;
153 this->public.create_iface_iterator = (iterator_t*(*)(bridge_t*))create_iface_iterator;
154 this->public.disconnect_iface = (bool(*)(bridge_t*, iface_t *iface))disconnect_iface;
155 this->public.connect_iface = (bool(*)(bridge_t*, iface_t *iface))connect_iface;
156 this->public.destroy = (void*)destroy;
157
158 if (br_add_bridge(name) != 0)
159 {
160 DBG1("creating bridge '%s' failed: %m", name);
161 free(this);
162 return NULL;
163 }
164
165 this->name = strdup(name);
166 this->ifaces = linked_list_create();
167
168 instances++;
169 return &this->public;
170 }
171