2
* (c) Copyright 1992 by Panagiotis Tsirigotis
3
* (c) Sections Copyright 1998-2001 by Rob Braun
4
* All rights reserved. The file named COPYRIGHT specifies the terms
5
* and conditions for redistribution.
10
#include <sys/socket.h>
11
#include <netinet/in.h>
12
#include <arpa/inet.h>
18
#ifdef HAVE_SYS_SELECT_H
19
#include <sys/select.h>
23
#include "intcommon.h"
25
#include "connection.h"
32
* Datagrams greater than this will be truncated
34
#define MAX_DATAGRAM_SIZE ( 32 * 1024 )
38
union xsockaddr from ;
43
typedef struct packet packet_s ;
48
unsigned received_packets ;
51
#define IDP( p ) ((struct idgram_private *)(p))
54
static struct idgram_private idgram ;
56
static void di_mux(void) ;
57
static void udp_remote_to_local( struct intercept_s *ip, channel_s **chpp );
58
static status_e udp_local_to_remote( channel_s *chp );
59
static void send_data( int sd, char *buf, int len, union xsockaddr *addr );
60
static status_e get_incoming_packet( struct intercept_s *ip, packet_s *pp );
62
static const struct intercept_ops idgram_ops =
69
static struct intercept_s dgram_intercept_state ;
72
struct intercept_s *di_init( struct server *serp )
74
struct intercept_s *ip = &dgram_intercept_state ;
76
ip->int_socket_type = SOCK_DGRAM ;
77
ip->int_priv = (void *) &idgram ;
78
ip->int_ops = &idgram_ops ;
79
int_init( ip, serp ) ;
86
struct intercept_s *ip = &dgram_intercept_state ;
88
if ( IDP( ip->int_priv )->received_packets == 0 )
89
drain( INT_REMOTE( ip ) ) ;
95
* Returns only if there is an I/O error while communicating with the server
97
static void di_mux(void)
99
struct intercept_s *ip = &dgram_intercept_state ;
103
FD_ZERO( &socket_mask ) ;
104
FD_SET( INT_REMOTE( ip ), &socket_mask ) ;
105
mask_max = INT_REMOTE( ip ) ;
114
read_mask = socket_mask ;
115
n_ready = int_select( mask_max+1, &read_mask ) ;
120
if ( FD_ISSET( INT_REMOTE( ip ), &read_mask ) )
122
udp_remote_to_local( ip, &chp ) ;
125
FD_SET( chp->ch_local_socket, &socket_mask ) ;
126
if ( chp->ch_local_socket > mask_max )
127
mask_max = chp->ch_local_socket ;
129
if ( --n_ready == 0 )
133
for ( u = 0 ; u < pset_count( INT_CONNECTIONS( ip ) ) ; u++ )
135
chp = CHP( pset_pointer( INT_CONNECTIONS( ip ), u ) ) ;
137
if ( FD_ISSET( chp->ch_local_socket, &read_mask ) )
139
if ( udp_local_to_remote( chp ) == FAILED )
141
if ( --n_ready == 0 )
150
* Read data from the remote socket and send it to the appropriate local
152
* If this is a new connection, insert it in the connection table and
153
* place its handle in *chpp.
155
static void udp_remote_to_local( struct intercept_s *ip, channel_s **chpp )
157
char buf[ MAX_DATAGRAM_SIZE ] ;
160
bool_int addr_checked ;
162
*chpp = CHANNEL_NULL ;
165
packet.size = sizeof( buf ) ;
166
if ( get_incoming_packet( ip, &packet ) == FAILED )
169
chp = int_lookupconn( ip, &packet.from, &addr_checked ) ;
170
if ( chp == CHANNEL_NULL )
172
struct server *serp = INT_SERVER( ip ) ;
173
struct service *sp = SERVER_SERVICE( serp ) ;
174
connection_s *cop = SERVER_CONNECTION( serp ) ;
176
if ( ( chp = int_newconn( ip, &packet.from, INT_REMOTE( ip ) ) ) == NULL )
179
CONN_SETADDR( cop, &packet.from ) ; /* for logging */
181
if ( INTERCEPT( ip ) )
186
M_OR( check_mask, XMASK( CF_ADDRESS ), XMASK( CF_TIME ) ) ;
187
result = access_control( sp, cop, &check_mask ) ;
189
if ( result != AC_OK )
191
svc_log_failure( sp, cop, result ) ;
192
chp->ch_state = BAD_CHANNEL ;
198
* Since we don't distinguish ports, there is no point to log
199
* another successful attempt from the same address
201
if ( ! addr_checked )
202
svc_log_success( sp, cop, SERVER_PID( serp ) ) ;
206
else if ( chp->ch_state == BAD_CHANNEL )
211
msg( LOG_DEBUG, "udp_remote_to_local",
212
"sending %d bytes to server on port %d",
213
packet.size, ntohs( INT_LOCALADDR( ip )->sin_port ) ) ;
216
send_data( chp->ch_local_socket,
217
packet.data, packet.size, NULL ) ;
222
* Send the data in buf to destination addr using the socket sd.
223
* If addr is NULL, use the default socket destination
225
static void send_data( int sd, char *buf, int len, union xsockaddr *addr )
230
const char *func = "send_data" ;
232
for ( p = buf, left = len ; left > 0 ; left -= cc, p+= cc )
235
cc = send( sd, p, left, 0 ) ;
237
cc = sendto( sd, p, left, 0, SA( addr ), sizeof( *addr ) ) ;
240
if ( errno == EINTR )
247
msg( LOG_ERR, func, "%s: %m", addr ? "sendto" : "send" ) ;
255
static status_e get_incoming_packet( struct intercept_s *ip, packet_s *pp )
258
const char *func = "get_incoming_packet" ;
260
if( SC_IPV4( SVC_CONF( SERVER_SERVICE( INT_SERVER( ip ) ) ) ) )
261
from_len = sizeof( struct sockaddr_in );
262
if( SC_IPV6( SVC_CONF( SERVER_SERVICE( INT_SERVER( ip ) ) ) ) )
263
from_len = sizeof( struct sockaddr_in6 );
269
from_len = sizeof( pp->from ) ;
270
cc = recvfrom( INT_REMOTE( ip ), pp->data, pp->size,
271
0, SA( &pp->from ), &from_len ) ;
274
if ( errno != EINTR )
276
msg( LOG_ERR, func, "recvfrom error: %m" ) ;
285
IDP( ip->int_priv )->received_packets++ ;
292
msg( LOG_ERR, func, "incoming packet had 0 length address" ) ;
298
msg( LOG_DEBUG, func, "Received %d bytes from address: %s,%d",
299
pp->size, xaddrname( &pp->from ), ntohs( xaddrport(&pp->from) ) );
306
static status_e udp_local_to_remote( channel_s *chp )
308
char buf[ MAX_DATAGRAM_SIZE ] ;
310
const char *func = "udp_local_to_remote" ;
314
cc = recv( chp->ch_local_socket, buf, sizeof( buf ), 0 ) ;
318
if ( errno != EINTR )
320
msg( LOG_ERR, func, "recv from daemon: %m" ) ;
332
msg( LOG_DEBUG, func, "sending %d bytes to address %s,%d",
333
cc, xaddrname( &chp->ch_from ), ntohs( xaddrport(&chp->ch_from) ) ) ;
336
send_data( chp->ch_remote_socket, buf, cc, &chp->ch_from ) ;