summaryrefslogtreecommitdiff
path: root/ot_udp.c
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2024-04-15 00:39:02 +0200
committerDirk Engling <erdgeist@erdgeist.org>2024-04-15 00:39:02 +0200
commit7c633c259ebc4a863c5076462c5792ecb8b9f617 (patch)
tree550a272a82325c554923c7498811cb8971aa49c2 /ot_udp.c
parent4c5935c0574481dc4b0e0bf57528dc3069e34742 (diff)
clang-format
Diffstat (limited to 'ot_udp.c')
-rw-r--r--ot_udp.c263
1 files changed, 136 insertions, 127 deletions
diff --git a/ot_udp.c b/ot_udp.c
index c32a7e2..912c7e4 100644
--- a/ot_udp.c
+++ b/ot_udp.c
@@ -4,31 +4,31 @@
4 $id$ */ 4 $id$ */
5 5
6/* System */ 6/* System */
7#include <stdlib.h>
8#include <pthread.h>
9#include <string.h>
10#include <arpa/inet.h> 7#include <arpa/inet.h>
8#include <pthread.h>
11#include <stdio.h> 9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12 12
13/* Libowfat */ 13/* Libowfat */
14#include "socket.h"
15#include "io.h" 14#include "io.h"
16#include "ip6.h" 15#include "ip6.h"
16#include "socket.h"
17 17
18/* Opentracker */ 18/* Opentracker */
19#include "trackerlogic.h"
20#include "ot_udp.h"
21#include "ot_stats.h"
22#include "ot_rijndael.h" 19#include "ot_rijndael.h"
20#include "ot_stats.h"
21#include "ot_udp.h"
22#include "trackerlogic.h"
23 23
24#if 0 24#if 0
25static const uint8_t g_static_connid[8] = { 0x23, 0x42, 0x05, 0x17, 0xde, 0x41, 0x50, 0xff }; 25static const uint8_t g_static_connid[8] = { 0x23, 0x42, 0x05, 0x17, 0xde, 0x41, 0x50, 0xff };
26#endif 26#endif
27static uint32_t g_rijndael_round_key[44] = {0}; 27static uint32_t g_rijndael_round_key[44] = {0};
28static uint32_t g_key_of_the_hour[2] = {0}; 28static uint32_t g_key_of_the_hour[2] = {0};
29static ot_time g_hour_of_the_key; 29static ot_time g_hour_of_the_key;
30 30
31static void udp_generate_rijndael_round_key() { 31static void udp_generate_rijndael_round_key() {
32 uint32_t key[16]; 32 uint32_t key[16];
33#ifdef WANT_ARC4RANDOM 33#ifdef WANT_ARC4RANDOM
34 arc4random_buf(&key[0], sizeof(key)); 34 arc4random_buf(&key[0], sizeof(key));
@@ -38,7 +38,7 @@ static void udp_generate_rijndael_round_key() {
38 key[2] = random(); 38 key[2] = random();
39 key[3] = random(); 39 key[3] = random();
40#endif 40#endif
41 rijndaelKeySetupEnc128( g_rijndael_round_key, (uint8_t*)key ); 41 rijndaelKeySetupEnc128(g_rijndael_round_key, (uint8_t *)key);
42 42
43#ifdef WANT_ARC4RANDOM 43#ifdef WANT_ARC4RANDOM
44 g_key_of_the_hour[0] = arc4random(); 44 g_key_of_the_hour[0] = arc4random();
@@ -49,181 +49,190 @@ static void udp_generate_rijndael_round_key() {
49} 49}
50 50
51/* Generate current and previous connection id for ip */ 51/* Generate current and previous connection id for ip */
52static void udp_make_connectionid( uint32_t connid[2], const ot_ip6 remoteip, int age ) { 52static void udp_make_connectionid(uint32_t connid[2], const ot_ip6 remoteip, int age) {
53 uint32_t plain[4], crypt[4]; 53 uint32_t plain[4], crypt[4];
54 int i; 54 int i;
55 if( g_now_minutes + 60 > g_hour_of_the_key ) { 55 if (g_now_minutes + 60 > g_hour_of_the_key) {
56 g_hour_of_the_key = g_now_minutes; 56 g_hour_of_the_key = g_now_minutes;
57 g_key_of_the_hour[1] = g_key_of_the_hour[0]; 57 g_key_of_the_hour[1] = g_key_of_the_hour[0];
58#ifdef WANT_ARC4RANDOM 58#ifdef WANT_ARC4RANDOM
59 g_key_of_the_hour[0] = arc4random(); 59 g_key_of_the_hour[0] = arc4random();
60#else 60#else
61 g_key_of_the_hour[0] = random(); 61 g_key_of_the_hour[0] = random();
62#endif 62#endif
63 } 63 }
64 64
65 memcpy( plain, remoteip, sizeof( plain ) ); 65 memcpy(plain, remoteip, sizeof(plain));
66 for( i=0; i<4; ++i ) plain[i] ^= g_key_of_the_hour[age]; 66 for (i = 0; i < 4; ++i)
67 rijndaelEncrypt128( g_rijndael_round_key, (uint8_t*)remoteip, (uint8_t*)crypt ); 67 plain[i] ^= g_key_of_the_hour[age];
68 rijndaelEncrypt128(g_rijndael_round_key, (uint8_t *)remoteip, (uint8_t *)crypt);
68 connid[0] = crypt[0] ^ crypt[1]; 69 connid[0] = crypt[0] ^ crypt[1];
69 connid[1] = crypt[2] ^ crypt[3]; 70 connid[1] = crypt[2] ^ crypt[3];
70} 71}
71 72
72/* UDP implementation according to http://xbtt.sourceforge.net/udp_tracker_protocol.html */ 73/* UDP implementation according to http://xbtt.sourceforge.net/udp_tracker_protocol.html */
73int handle_udp6( int64 serversocket, struct ot_workstruct *ws ) { 74int handle_udp6(int64 serversocket, struct ot_workstruct *ws) {
74 ot_ip6 remoteip; 75 ot_ip6 remoteip;
75 uint32_t *inpacket = (uint32_t*)ws->inbuf; 76 uint32_t *inpacket = (uint32_t *)ws->inbuf;
76 uint32_t *outpacket = (uint32_t*)ws->outbuf; 77 uint32_t *outpacket = (uint32_t *)ws->outbuf;
77 uint32_t left, event, scopeid; 78 uint32_t left, event, scopeid;
78 uint32_t connid[2]; 79 uint32_t connid[2];
79 uint32_t action; 80 uint32_t action;
80 uint16_t port, remoteport; 81 uint16_t port, remoteport;
81 size_t byte_count, scrape_count; 82 size_t byte_count, scrape_count;
82 83
83 byte_count = socket_recv6( serversocket, ws->inbuf, G_INBUF_SIZE, remoteip, &remoteport, &scopeid ); 84 byte_count = socket_recv6(serversocket, ws->inbuf, G_INBUF_SIZE, remoteip, &remoteport, &scopeid);
84 if( !byte_count ) return 0; 85 if (!byte_count)
85 86 return 0;
86 stats_issue_event( EVENT_ACCEPT, FLAG_UDP, (uintptr_t)remoteip ); 87
87 stats_issue_event( EVENT_READ, FLAG_UDP, byte_count ); 88 stats_issue_event(EVENT_ACCEPT, FLAG_UDP, (uintptr_t)remoteip);
89 stats_issue_event(EVENT_READ, FLAG_UDP, byte_count);
88 90
89 /* Minimum udp tracker packet size, also catches error */ 91 /* Minimum udp tracker packet size, also catches error */
90 if( byte_count < 16 ) 92 if (byte_count < 16)
91 return 1; 93 return 1;
92 94
93 /* Get action to take. Ignore error messages and broken packets */ 95 /* Get action to take. Ignore error messages and broken packets */
94 action = ntohl( inpacket[2] ); 96 action = ntohl(inpacket[2]);
95 if( action > 2 ) 97 if (action > 2)
96 return 1; 98 return 1;
97 99
98 /* Generate the connection id we give out and expect to and from 100 /* Generate the connection id we give out and expect to and from
99 the requesting ip address, this prevents udp spoofing */ 101 the requesting ip address, this prevents udp spoofing */
100 udp_make_connectionid( connid, remoteip, 0 ); 102 udp_make_connectionid(connid, remoteip, 0);
101 103
102 /* Initialise hash pointer */ 104 /* Initialise hash pointer */
103 ws->hash = NULL; 105 ws->hash = NULL;
104 ws->peer_id = NULL; 106 ws->peer_id = NULL;
105 107
106 /* If action is not 0 (connect), then we expect the derived 108 /* If action is not 0 (connect), then we expect the derived
107 connection id in first 64 bit */ 109 connection id in first 64 bit */
108 if( ( action > 0 ) && ( inpacket[0] != connid[0] || inpacket[1] != connid[1] ) ) { 110 if ((action > 0) && (inpacket[0] != connid[0] || inpacket[1] != connid[1])) {
109 /* If connection id does not match, try the one that was 111 /* If connection id does not match, try the one that was
110 valid in the previous hour. Only if this also does not 112 valid in the previous hour. Only if this also does not
111 match, return an error packet */ 113 match, return an error packet */
112 udp_make_connectionid( connid, remoteip, 1 ); 114 udp_make_connectionid(connid, remoteip, 1);
113 if( inpacket[0] != connid[0] || inpacket[1] != connid[1] ) { 115 if (inpacket[0] != connid[0] || inpacket[1] != connid[1]) {
114 const size_t s = sizeof( "Connection ID missmatch." ); 116 const size_t s = sizeof("Connection ID missmatch.");
115 outpacket[0] = htonl( 3 ); outpacket[1] = inpacket[3]; 117 outpacket[0] = htonl(3);
116 memcpy( &outpacket[2], "Connection ID missmatch.", s ); 118 outpacket[1] = inpacket[3];
117 socket_send6( serversocket, ws->outbuf, 8 + s, remoteip, remoteport, 0 ); 119 memcpy(&outpacket[2], "Connection ID missmatch.", s);
118 stats_issue_event( EVENT_CONNID_MISSMATCH, FLAG_UDP, 8 + s ); 120 socket_send6(serversocket, ws->outbuf, 8 + s, remoteip, remoteport, 0);
121 stats_issue_event(EVENT_CONNID_MISSMATCH, FLAG_UDP, 8 + s);
119 return 1; 122 return 1;
120 } 123 }
121 } 124 }
122 125
123 switch( action ) { 126 switch (action) {
124 case 0: /* This is a connect action */ 127 case 0: /* This is a connect action */
125 /* look for udp bittorrent magic id */ 128 /* look for udp bittorrent magic id */
126 if( (ntohl(inpacket[0]) != 0x00000417) || (ntohl(inpacket[1]) != 0x27101980) ) 129 if ((ntohl(inpacket[0]) != 0x00000417) || (ntohl(inpacket[1]) != 0x27101980))
127 return 1; 130 return 1;
131
132 outpacket[0] = 0;
133 outpacket[1] = inpacket[3];
134 outpacket[2] = connid[0];
135 outpacket[3] = connid[1];
136
137 socket_send6(serversocket, ws->outbuf, 16, remoteip, remoteport, 0);
138 stats_issue_event(EVENT_CONNECT, FLAG_UDP, 16);
139 break;
140 case 1: /* This is an announce action */
141 /* Minimum udp announce packet size */
142 if (byte_count < 98)
143 return 1;
144
145 /* We do only want to know, if it is zero */
146 left = inpacket[64 / 4] | inpacket[68 / 4];
147
148 event = ntohl(inpacket[80 / 4]);
149 port = *(uint16_t *)(((char *)inpacket) + 96);
150 ws->hash = (ot_hash *)(((char *)inpacket) + 16);
128 151
129 outpacket[0] = 0; 152 OT_SETIP(ws->peer, remoteip);
130 outpacket[1] = inpacket[3]; 153 OT_SETPORT(ws->peer, &port);
131 outpacket[2] = connid[0]; 154 OT_PEERFLAG(ws->peer) = 0;
132 outpacket[3] = connid[1];
133 155
134 socket_send6( serversocket, ws->outbuf, 16, remoteip, remoteport, 0 ); 156 switch (event) {
135 stats_issue_event( EVENT_CONNECT, FLAG_UDP, 16 ); 157 case 1:
158 OT_PEERFLAG(ws->peer) |= PEER_FLAG_COMPLETED;
136 break; 159 break;
137 case 1: /* This is an announce action */ 160 case 3:
138 /* Minimum udp announce packet size */ 161 OT_PEERFLAG(ws->peer) |= PEER_FLAG_STOPPED;
139 if( byte_count < 98 )
140 return 1;
141
142 /* We do only want to know, if it is zero */
143 left = inpacket[64/4] | inpacket[68/4];
144
145 event = ntohl( inpacket[80/4] );
146 port = *(uint16_t*)( ((char*)inpacket) + 96 );
147 ws->hash = (ot_hash*)( ((char*)inpacket) + 16 );
148
149 OT_SETIP( ws->peer, remoteip );
150 OT_SETPORT( ws->peer, &port );
151 OT_PEERFLAG( ws->peer ) = 0;
152
153 switch( event ) {
154 case 1: OT_PEERFLAG( ws->peer ) |= PEER_FLAG_COMPLETED; break;
155 case 3: OT_PEERFLAG( ws->peer ) |= PEER_FLAG_STOPPED; break;
156 default: break;
157 }
158
159 if( !left )
160 OT_PEERFLAG( ws->peer ) |= PEER_FLAG_SEEDING;
161
162 outpacket[0] = htonl( 1 ); /* announce action */
163 outpacket[1] = inpacket[12/4];
164
165 if( OT_PEERFLAG( ws->peer ) & PEER_FLAG_STOPPED ) { /* Peer is gone. */
166 ws->reply = ws->outbuf;
167 ws->reply_size = remove_peer_from_torrent( FLAG_UDP, ws );
168 } else {
169 /* Limit amount of peers to OT_MAX_PEERS_UDP */
170 uint32_t numwant = ntohl( inpacket[92/4] );
171 size_t max_peers = ip6_isv4mapped(remoteip) ? OT_MAX_PEERS_UDP4 : OT_MAX_PEERS_UDP6;
172 if (numwant > max_peers) numwant = max_peers;
173
174 ws->reply = ws->outbuf + 8;
175 ws->reply_size = 8 + add_peer_to_torrent_and_return_peers( FLAG_UDP, ws, numwant );
176 }
177
178 socket_send6( serversocket, ws->outbuf, ws->reply_size, remoteip, remoteport, 0 );
179 stats_issue_event( EVENT_ANNOUNCE, FLAG_UDP, ws->reply_size );
180 break; 162 break;
163 default:
164 break;
165 }
181 166
182 case 2: /* This is a scrape action */ 167 if (!left)
183 outpacket[0] = htonl( 2 ); /* scrape action */ 168 OT_PEERFLAG(ws->peer) |= PEER_FLAG_SEEDING;
184 outpacket[1] = inpacket[12/4];
185 169
186 for( scrape_count = 0; ( scrape_count * 20 < byte_count - 16) && ( scrape_count <= 74 ); scrape_count++ ) 170 outpacket[0] = htonl(1); /* announce action */
187 return_udp_scrape_for_torrent( *(ot_hash*)( ((char*)inpacket) + 16 + 20 * scrape_count ), ((char*)outpacket) + 8 + 12 * scrape_count ); 171 outpacket[1] = inpacket[12 / 4];
188 172
189 socket_send6( serversocket, ws->outbuf, 8 + 12 * scrape_count, remoteip, remoteport, 0 ); 173 if (OT_PEERFLAG(ws->peer) & PEER_FLAG_STOPPED) { /* Peer is gone. */
190 stats_issue_event( EVENT_SCRAPE, FLAG_UDP, scrape_count ); 174 ws->reply = ws->outbuf;
191 break; 175 ws->reply_size = remove_peer_from_torrent(FLAG_UDP, ws);
176 } else {
177 /* Limit amount of peers to OT_MAX_PEERS_UDP */
178 uint32_t numwant = ntohl(inpacket[92 / 4]);
179 size_t max_peers = ip6_isv4mapped(remoteip) ? OT_MAX_PEERS_UDP4 : OT_MAX_PEERS_UDP6;
180 if (numwant > max_peers)
181 numwant = max_peers;
182
183 ws->reply = ws->outbuf + 8;
184 ws->reply_size = 8 + add_peer_to_torrent_and_return_peers(FLAG_UDP, ws, numwant);
185 }
186
187 socket_send6(serversocket, ws->outbuf, ws->reply_size, remoteip, remoteport, 0);
188 stats_issue_event(EVENT_ANNOUNCE, FLAG_UDP, ws->reply_size);
189 break;
190
191 case 2: /* This is a scrape action */
192 outpacket[0] = htonl(2); /* scrape action */
193 outpacket[1] = inpacket[12 / 4];
194
195 for (scrape_count = 0; (scrape_count * 20 < byte_count - 16) && (scrape_count <= 74); scrape_count++)
196 return_udp_scrape_for_torrent(*(ot_hash *)(((char *)inpacket) + 16 + 20 * scrape_count), ((char *)outpacket) + 8 + 12 * scrape_count);
197
198 socket_send6(serversocket, ws->outbuf, 8 + 12 * scrape_count, remoteip, remoteport, 0);
199 stats_issue_event(EVENT_SCRAPE, FLAG_UDP, scrape_count);
200 break;
192 } 201 }
193 return 1; 202 return 1;
194} 203}
195 204
196static void* udp_worker( void * args ) { 205static void *udp_worker(void *args) {
197 int64 sock = (int64)args; 206 int64 sock = (int64)args;
198 struct ot_workstruct ws; 207 struct ot_workstruct ws;
199 memset( &ws, 0, sizeof(ws) ); 208 memset(&ws, 0, sizeof(ws));
200 209
201 ws.inbuf=malloc(G_INBUF_SIZE); 210 ws.inbuf = malloc(G_INBUF_SIZE);
202 ws.outbuf=malloc(G_OUTBUF_SIZE); 211 ws.outbuf = malloc(G_OUTBUF_SIZE);
203#ifdef _DEBUG_HTTPERROR 212#ifdef _DEBUG_HTTPERROR
204 ws.debugbuf=malloc(G_DEBUGBUF_SIZE); 213 ws.debugbuf = malloc(G_DEBUGBUF_SIZE);
205#endif 214#endif
206 215
207 while( g_opentracker_running ) 216 while (g_opentracker_running)
208 handle_udp6( sock, &ws ); 217 handle_udp6(sock, &ws);
209 218
210 free( ws.inbuf ); 219 free(ws.inbuf);
211 free( ws.outbuf ); 220 free(ws.outbuf);
212#ifdef _DEBUG_HTTPERROR 221#ifdef _DEBUG_HTTPERROR
213 free( ws.debugbuf ); 222 free(ws.debugbuf);
214#endif 223#endif
215 return NULL; 224 return NULL;
216} 225}
217 226
218void udp_init( int64 sock, unsigned int worker_count ) { 227void udp_init(int64 sock, unsigned int worker_count) {
219 pthread_t thread_id; 228 pthread_t thread_id;
220 if( !g_rijndael_round_key[0] ) 229 if (!g_rijndael_round_key[0])
221 udp_generate_rijndael_round_key(); 230 udp_generate_rijndael_round_key();
222#ifdef _DEBUG 231#ifdef _DEBUG
223 fprintf( stderr, " installing %d workers on udp socket %ld\n", worker_count, (unsigned long)sock ); 232 fprintf(stderr, " installing %d workers on udp socket %ld\n", worker_count, (unsigned long)sock);
224#endif 233#endif
225 while( worker_count-- ) 234 while (worker_count--)
226 pthread_create( &thread_id, NULL, udp_worker, (void *)sock ); 235 pthread_create(&thread_id, NULL, udp_worker, (void *)sock);
227} 236}
228 237
229const char *g_version_udp_c = "$Source$: $Revision$\n"; 238const char *g_version_udp_c = "$Source$: $Revision$\n";