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