1 /* Copyright 2008 Bernhard R. Fischer, Daniel Haslinger.
2 *
3 * This file is part of OnionCat.
4 *
5 * OnionCat is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License.
8 *
9 * OnionCat is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with OnionCat. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /*! ocatpeer.c
19 * This file contains function on managing the peer list, i.e.
20 * adding, removing peers and thread locking mechanism.
21 *
22 * @author Bernhard R. Fischer <rahra _at_ cypherpunk at>
23 * @version 2008/02/03-01
24 */
25
26
27 #include "ocat.h"
28
29
30 // array of active peers
31 static OcatPeer_t *peer_ = NULL;
32 // mutex for locking array of peers
33 static pthread_mutex_t peer_mutex_ = PTHREAD_MUTEX_INITIALIZER;
34
35
36 /*! Return pointer to first peer. */
get_first_peer(void)37 OcatPeer_t *get_first_peer(void)
38 {
39 return peer_;
40 }
41
42
43 /*! Return double pointer to first peer. */
get_first_peer_ptr(void)44 OcatPeer_t **get_first_peer_ptr(void)
45 {
46 return &peer_;
47 }
48
49
50 /*! Lock complete peer list. */
lock_peers(void)51 int lock_peers(void)
52 {
53 return pthread_mutex_lock(&peer_mutex_);
54 }
55
56
57 /*! Unlock peer list. */
unlock_peers(void)58 int unlock_peers(void)
59 {
60 return pthread_mutex_unlock(&peer_mutex_);
61 }
62
63
64 /*! Lock specific peer. Peer list MUST be locked before and
65 * maybe unlock directly after lock_peer(). */
lock_peer(OcatPeer_t * peer)66 int lock_peer(OcatPeer_t *peer)
67 {
68 return pthread_mutex_lock(&peer->mutex);
69 }
70
71
72 /*! Unlock secific peer. Lock must NOT be reclaimed without
73 * calling lock_peers() before! */
unlock_peer(OcatPeer_t * peer)74 int unlock_peer(OcatPeer_t *peer)
75 {
76 return pthread_mutex_unlock(&peer->mutex);
77 }
78
79
80 /*! Search a specific peer by IPv6 address.
81 * Peer list MUST be locked before. */
search_peer(const struct in6_addr * addr)82 OcatPeer_t *search_peer(const struct in6_addr *addr)
83 {
84 OcatPeer_t *peer;
85
86 for (peer = peer_; peer; peer = peer->next)
87 //if (!memcmp(addr, &peer->addr, sizeof(struct in6_addr)))
88 if (IN6_ARE_ADDR_EQUAL(addr, &peer->addr))
89 return peer;
90 return NULL;
91 }
92
93
94 /*! Create a new empty peer and add it to the peer list.
95 * Peer list MUST be locked befored. */
get_empty_peer(void)96 OcatPeer_t *get_empty_peer(void)
97 {
98 int rc;
99 OcatPeer_t *peer;
100
101 if (!(peer = calloc(1, sizeof(OcatPeer_t))))
102 {
103 log_msg(LOG_ERR, "cannot get memory for new peer: \"%s\"", strerror(errno));
104 return NULL;
105 }
106
107 peer->tunhdr = (uint32_t*) peer->_fragbuf;
108 peer->fragbuf = &peer->_fragbuf[CNF(fhd_key_len)];
109 if ((rc = pthread_mutex_init(&peer->mutex, NULL)))
110 {
111 log_msg(LOG_EMERG, "cannot init new peer mutex: \"%s\"", strerror(rc));
112 free(peer);
113 return NULL;
114 }
115 peer->rand = random();
116
117 peer->next = peer_;
118 peer_ = peer;
119
120 return peer;
121 }
122
123
124 /*! peer list MUST be locked with lock_peers() in advance!
125 * @param peer pointer to peer that shall be deleted.
126 */
delete_peer(OcatPeer_t * peer)127 void delete_peer(OcatPeer_t *peer)
128 {
129 int rc;
130 OcatPeer_t **p;
131
132 for (p = &peer_; *p; p = &(*p)->next)
133 if (*p == peer)
134 {
135 log_debug("going to delete peer at %p", peer);
136 // unlink peer from list
137 lock_peer(peer);
138 *p = peer->next;
139 unlock_peer(peer);
140
141 // effectively delete it
142 if ((rc = pthread_mutex_destroy(&peer->mutex)))
143 log_msg(LOG_EMERG, "cannot destroy mutex: \"%s\"", strerror(rc));
144 free(peer);
145 return;
146 }
147 }
148
149