Refresh existing patches.
[debian/iodine.git] / src / user.c
1 /*
2  * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
3  * 2006-2009 Bjorn Andersson <flex@kryo.se>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 #include <stdio.h>
19 #include <stdint.h>
20 #include <time.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <signal.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26
27 #ifdef WINDOWS32
28 #include <winsock2.h>
29 #else
30 #include <netdb.h>
31 #endif
32
33 #include "common.h"
34 #include "encoding.h"
35 #include "user.h"
36
37 struct tun_user *users;
38 unsigned usercount;
39
40 int
41 init_users(in_addr_t my_ip, int netbits)
42 {
43         int i;
44         int skip = 0;
45         char newip[16];
46
47         int maxusers;
48
49         in_addr_t netmask = 0;
50         struct in_addr net;
51         struct in_addr ipstart;
52
53         for (i = 0; i < netbits; i++) {
54                 netmask = (netmask << 1) | 1;
55         }
56         netmask <<= (32 - netbits);
57         net.s_addr = htonl(netmask);
58         ipstart.s_addr = my_ip & net.s_addr;
59
60         maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
61         usercount = MIN(maxusers, USERS);
62
63         users = calloc(usercount, sizeof(struct tun_user));
64         for (i = 0; i < usercount; i++) {
65                 in_addr_t ip;
66                 users[i].id = i;
67                 snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
68                 ip = ipstart.s_addr + inet_addr(newip);
69                 if (ip == my_ip && skip == 0) {
70                         /* This IP was taken by iodined */
71                         skip++;
72                         snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
73                         ip = ipstart.s_addr + inet_addr(newip);
74                 }
75                 users[i].tun_ip = ip;
76                 net.s_addr = ip;
77                 users[i].disabled = 0;
78                 users[i].authenticated = 0;
79                 users[i].authenticated_raw = 0;
80                 users[i].active = 0;
81                 /* Rest is reset on login ('V' packet) */
82         }
83
84         return usercount;
85 }
86
87 const char*
88 users_get_first_ip()
89 {
90         struct in_addr ip;
91         ip.s_addr = users[0].tun_ip;
92         return strdup(inet_ntoa(ip));
93 }
94
95 int
96 users_waiting_on_reply()
97 {
98         int ret;
99         int i;
100
101         ret = 0;
102         for (i = 0; i < usercount; i++) {
103                 if (users[i].active && !users[i].disabled &&
104                         users[i].last_pkt + 60 > time(NULL) &&
105                         users[i].q.id != 0 && users[i].conn == CONN_DNS_NULL) {
106                         ret++;
107                 }
108         }
109
110         return ret;
111 }
112
113 int
114 find_user_by_ip(uint32_t ip)
115 {
116         int ret;
117         int i;
118
119         ret = -1;
120         for (i = 0; i < usercount; i++) {
121                 if (users[i].active &&
122                         users[i].authenticated &&
123                         !users[i].disabled &&
124                         users[i].last_pkt + 60 > time(NULL) &&
125                         ip == users[i].tun_ip) {
126                         ret = i;
127                         break;
128                 }
129         }
130         return ret;
131 }
132
133 int
134 all_users_waiting_to_send()
135 /* If this returns true, then reading from tun device is blocked.
136    So only return true when all clients have at least one packet in
137    the outpacket-queue, so that sending back-to-back is possible
138    without going through another select loop.
139 */
140 {
141         time_t now;
142         int ret;
143         int i;
144
145         ret = 1;
146         now = time(NULL);
147         for (i = 0; i < usercount; i++) {
148                 if (users[i].active && !users[i].disabled &&
149                         users[i].last_pkt + 60 > now &&
150                         ((users[i].conn == CONN_RAW_UDP) ||
151                         ((users[i].conn == CONN_DNS_NULL)
152 #ifdef OUTPACKETQ_LEN
153                                 && users[i].outpacketq_filled < 1
154 #else
155                                 && users[i].outpacket.len == 0
156 #endif
157                         ))) {
158
159                         ret = 0;
160                         break;
161                 }
162         }
163         return ret;
164 }
165
166 int
167 find_available_user()
168 {
169         int ret = -1;
170         int i;
171         for (i = 0; i < usercount; i++) {
172                 /* Not used at all or not used in one minute */
173                 if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) {
174                         users[i].active = 1;
175                         users[i].authenticated = 0;
176                         users[i].authenticated_raw = 0;
177                         users[i].last_pkt = time(NULL);
178                         users[i].fragsize = 4096;
179                         users[i].conn = CONN_DNS_NULL;
180                         ret = i;
181                         break;
182                 }
183         }
184         return ret;
185 }
186
187 void
188 user_switch_codec(int userid, struct encoder *enc)
189 {
190         if (userid < 0 || userid >= usercount)
191                 return;
192
193         users[userid].encoder = enc;
194 }
195
196 void
197 user_set_conn_type(int userid, enum connection c)
198 {
199         if (userid < 0 || userid >= usercount)
200                 return;
201
202         if (c < 0 || c >= CONN_MAX)
203                 return;
204
205         users[userid].conn = c;
206 }
207