netutils.c 18.2 KB
Newer Older
1
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
2
 * netutils.c: various network functions
3
 *****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
4
 * Copyright (C) 1999, 2000, 2001 VideoLAN
Tony Castley's avatar
Tony Castley committed
5
 * $Id: netutils.c,v 1.38 2001/10/03 02:20:39 tcastley Exp $
6
 *
7
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
Benoit Steiner's avatar
   
Benoit Steiner committed
8
 *          Benoit Steiner <benny@via.ecp.fr>
Henri Fallon's avatar
   
Henri Fallon committed
9
 *          Henri Fallon <henri@videolan.org>
Xavier Marchesini's avatar
Xavier Marchesini committed
10
 *          Xavier Marchesini <xav@via.ecp.fr>
11
12
13
14
15
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
Sam Hocevar's avatar
   
Sam Hocevar committed
16
 *
17
18
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
21
 *
22
23
24
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
25
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
26

27
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
28
 * Preamble
29
 *****************************************************************************/
30
31
#include "defs.h"

32
33
#include <stdlib.h>                             /* free(), realloc(), atoi() */
#include <errno.h>                                                /* errno() */
Sam Hocevar's avatar
   
Sam Hocevar committed
34
#include <string.h>                                              /* memset() */
Sam Hocevar's avatar
   
Sam Hocevar committed
35
36

#ifdef HAVE_UNISTD_H
Sam Hocevar's avatar
   
Sam Hocevar committed
37
#include <unistd.h>                                         /* gethostname() */
Sam Hocevar's avatar
   
Sam Hocevar committed
38
39
40
41
42
#elif defined( _MSC_VER ) && defined( _WIN32 )
#include <io.h>
#endif

#if !defined( _MSC_VER )
Henri Fallon's avatar
   
Henri Fallon committed
43
#include <sys/time.h>                                        /* gettimeofday */
Sam Hocevar's avatar
   
Sam Hocevar committed
44
#endif
45

Sam Hocevar's avatar
   
Sam Hocevar committed
46
#if !defined( WIN32 )
Sam Hocevar's avatar
   
Sam Hocevar committed
47
#include <netdb.h>                                        /* gethostbyname() */
48
49
#include <netinet/in.h>                               /* BSD: struct in_addr */
#include <sys/socket.h>                              /* BSD: struct sockaddr */
Sam Hocevar's avatar
   
Sam Hocevar committed
50
51
#endif

52
#ifdef HAVE_ARPA_INET_H
53
54
55
#include <arpa/inet.h>                           /* inet_ntoa(), inet_aton() */
#endif

Henri Fallon's avatar
   
Henri Fallon committed
56
57
58
59
#ifdef SYS_LINUX
#include <sys/ioctl.h>                                            /* ioctl() */
#endif

Sam Hocevar's avatar
   
Sam Hocevar committed
60
#if defined( WIN32 )                    /* tools to get the MAC adress from  */
Xavier Marchesini's avatar
Xavier Marchesini committed
61
62
63
64
#include <windows.h>                    /* the interface under Windows	     */
#include <stdio.h>
#endif

Sam Hocevar's avatar
   
Sam Hocevar committed
65
#ifdef HAVE_NET_IF_H
66
67
#include <net/if.h>                            /* interface (arch-dependent) */
#endif
Henri Fallon's avatar
   
Henri Fallon committed
68

Benoit Steiner's avatar
   
Benoit Steiner committed
69
#ifdef HAVE_SYS_SOCKIO_H
Benoit Steiner's avatar
Benoit Steiner committed
70
#include <sys/sockio.h>
Benoit Steiner's avatar
   
Benoit Steiner committed
71
#endif
Michel Kaempf's avatar
Michel Kaempf committed
72
73
74
75

#include "config.h"
#include "common.h"
#include "mtime.h"
Henri Fallon's avatar
   
Henri Fallon committed
76
#include "threads.h"
Henri Fallon's avatar
   
Henri Fallon committed
77
#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
78
79
80

#include "intf_msg.h"

Sam Hocevar's avatar
   
Sam Hocevar committed
81
#include "netutils.h"
Henri Fallon's avatar
   
Henri Fallon committed
82

83
/*****************************************************************************
Henri Fallon's avatar
   
Henri Fallon committed
84
85
86
87
88
89
90
91
92
 * input_channel_t: channel library data
 *****************************************************************************
 * Store global channel library data.
 * The part of the code concerning the channel changing process is unstable
 * as it depends on the VideoLAN channel server, which isn't frozen for
 * the time being.
 *****************************************************************************/
typedef struct input_channel_s
{
Sam Hocevar's avatar
   
Sam Hocevar committed
93
    int         i_channel;                         /* current channel number */
Henri Fallon's avatar
   
Henri Fallon committed
94
95
96
    mtime_t     last_change;                             /* last change date */
} input_channel_t;

Xavier Marchesini's avatar
Xavier Marchesini committed
97
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
98
99
100
101
102
 * Local prototypes
 *****************************************************************************/
static int GetMacAddress   ( int i_socket, char *psz_mac );
#ifdef WIN32
static int GetAdapterInfo  ( int i_adapter, char *psz_string );
Xavier Marchesini's avatar
Xavier Marchesini committed
103
104
#endif

Henri Fallon's avatar
   
Henri Fallon committed
105
106
/*****************************************************************************
 * network_BuildLocalAddr : fill a sockaddr_in structure for local binding
107
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
108
int network_BuildLocalAddr( struct sockaddr_in * p_socket, int i_port,
Henri Fallon's avatar
   
Henri Fallon committed
109
                            char * psz_broadcast )
Michel Kaempf's avatar
Michel Kaempf committed
110
{
Tony Castley's avatar
Tony Castley committed
111

Henri Fallon's avatar
   
Henri Fallon committed
112
113
    char                psz_hostname[INPUT_MAX_SOURCE_LENGTH];
    struct hostent    * p_hostent;
Sam Hocevar's avatar
   
Sam Hocevar committed
114

Tony Castley's avatar
Tony Castley committed
115
116
117
118
119
#if defined( SYS_BEOS )
    intf_ErrMsg( "error: channel changing is not yet supported under BeOS" );
    return( 1 );
#endif

Henri Fallon's avatar
   
Henri Fallon committed
120
121
    /* Reset struct */
    memset( p_socket, 0, sizeof( struct sockaddr_in ) );
Sam Hocevar's avatar
   
Sam Hocevar committed
122
    p_socket->sin_family = AF_INET;                                /* family */
Henri Fallon's avatar
   
Henri Fallon committed
123
    p_socket->sin_port = htons( i_port );
Henri Fallon's avatar
   
Henri Fallon committed
124
    if( psz_broadcast == NULL )
Henri Fallon's avatar
   
Henri Fallon committed
125
126
127
128
129
130
131
132
    {
        /* Try to get our own IP */
        if( gethostname( psz_hostname, sizeof(psz_hostname) ) )
        {
            intf_ErrMsg( "BuildLocalAddr : unable to resolve local name : %s",
                         strerror( errno ) );
            return( -1 );
        }
Michel Kaempf's avatar
Michel Kaempf committed
133

Henri Fallon's avatar
   
Henri Fallon committed
134
135
    }
    else
Sam Hocevar's avatar
   
Sam Hocevar committed
136
137
    {
        /* I didn't manage to make INADDR_ANYT work, even with setsockopt
Henri Fallon's avatar
   
Henri Fallon committed
138
139
140
         * so, as it's kludgy to try and determine the broadcast addr
         * it is passed as an argument in the command line */
        strncpy( psz_hostname, psz_broadcast, INPUT_MAX_SOURCE_LENGTH );
141
    }
Henri Fallon's avatar
   
Henri Fallon committed
142

143
144
    /* Try to convert address directly from in_addr - this will work if
     * psz_in_addr is dotted decimal. */
Henri Fallon's avatar
   
Henri Fallon committed
145
146
#ifdef HAVE_ARPA_INET_H
    if( !inet_aton( psz_hostname, &p_socket->sin_addr) )
147
#else
Henri Fallon's avatar
   
Henri Fallon committed
148
    if( (p_socket->sin_addr.s_addr = inet_addr( psz_hostname )) == -1 )
149
#endif
Michel Kaempf's avatar
Michel Kaempf committed
150
    {
Henri Fallon's avatar
   
Henri Fallon committed
151
152
        /* We have a fqdn, try to find its address */
        if ( (p_hostent = gethostbyname( psz_hostname )) == NULL )
Michel Kaempf's avatar
Michel Kaempf committed
153
        {
Henri Fallon's avatar
   
Henri Fallon committed
154
            intf_ErrMsg( "BuildLocalAddr: unknown host %s", psz_hostname );
155
            return( -1 );
Michel Kaempf's avatar
Michel Kaempf committed
156
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
157

Michel Kaempf's avatar
Michel Kaempf committed
158
        /* Copy the first address of the host in the socket address */
Sam Hocevar's avatar
   
Sam Hocevar committed
159
        memcpy( &p_socket->sin_addr, p_hostent->h_addr_list[0],
Henri Fallon's avatar
   
Henri Fallon committed
160
                 p_hostent->h_length );
Michel Kaempf's avatar
Michel Kaempf committed
161
    }
162
    return( 0 );
Michel Kaempf's avatar
Michel Kaempf committed
163
164
}

165
/*****************************************************************************
Henri Fallon's avatar
   
Henri Fallon committed
166
 * network_BuildRemoteAddr : fill a sockaddr_in structure for remote host
167
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
168
int network_BuildRemoteAddr( struct sockaddr_in * p_socket, char * psz_server )
Michel Kaempf's avatar
Michel Kaempf committed
169
{
Tony Castley's avatar
Tony Castley committed
170

Henri Fallon's avatar
   
Henri Fallon committed
171
    struct hostent            * p_hostent;
Sam Hocevar's avatar
   
Sam Hocevar committed
172

Tony Castley's avatar
Tony Castley committed
173
174
175
176
177
#if defined( SYS_BEOS )
    intf_ErrMsg( "error: channel changing is not yet supported under BeOS" );
    return( 1 );
#endif

Henri Fallon's avatar
   
Henri Fallon committed
178
179
    /* Reset structure */
    memset( p_socket, 0, sizeof( struct sockaddr_in ) );
Sam Hocevar's avatar
   
Sam Hocevar committed
180
181
    p_socket->sin_family = AF_INET;                                /* family */
    p_socket->sin_port = htons( 0 );               /* This is for remote end */
Sam Hocevar's avatar
   
Sam Hocevar committed
182

Henri Fallon's avatar
   
Henri Fallon committed
183
184
     /* Try to convert address directly from in_addr - this will work if
      * psz_in_addr is dotted decimal. */
Michel Kaempf's avatar
Michel Kaempf committed
185

Henri Fallon's avatar
   
Henri Fallon committed
186
187
#ifdef HAVE_ARPA_INET_H
    if( !inet_aton( psz_server, &p_socket->sin_addr) )
Benoit Steiner's avatar
Benoit Steiner committed
188
#else
Henri Fallon's avatar
   
Henri Fallon committed
189
    if( (p_socket->sin_addr.s_addr = inet_addr( psz_server )) == -1 )
190
#endif
Michel Kaempf's avatar
Michel Kaempf committed
191
    {
Henri Fallon's avatar
   
Henri Fallon committed
192
193
        /* We have a fqdn, try to find its address */
        if ( (p_hostent = gethostbyname(psz_server)) == NULL )
Michel Kaempf's avatar
Michel Kaempf committed
194
        {
Sam Hocevar's avatar
   
Sam Hocevar committed
195
            intf_ErrMsg( "BuildRemoteAddr: unknown host %s",
Henri Fallon's avatar
   
Henri Fallon committed
196
197
                         psz_server );
            return( -1 );
Michel Kaempf's avatar
Michel Kaempf committed
198
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
199

Henri Fallon's avatar
   
Henri Fallon committed
200
        /* Copy the first address of the host in the socket address */
Sam Hocevar's avatar
   
Sam Hocevar committed
201
        memcpy( &p_socket->sin_addr, p_hostent->h_addr_list[0],
Henri Fallon's avatar
   
Henri Fallon committed
202
                 p_hostent->h_length );
Michel Kaempf's avatar
Michel Kaempf committed
203
    }
Henri Fallon's avatar
   
Henri Fallon committed
204
    return( 0 );
Michel Kaempf's avatar
Michel Kaempf committed
205
}
Sam Hocevar's avatar
   
Sam Hocevar committed
206

Henri Fallon's avatar
   
Henri Fallon committed
207
208
209
210
/*****************************************************************************
 * network_ChannelCreate: initialize global channel method data
 *****************************************************************************
 * Initialize channel input method global data. This function should be called
Sam Hocevar's avatar
   
Sam Hocevar committed
211
 * once before any input thread is created or any call to other
Henri Fallon's avatar
   
Henri Fallon committed
212
213
214
215
 * input_Channel*() function is attempted.
 *****************************************************************************/
int network_ChannelCreate( void )
{
Sam Hocevar's avatar
   
Sam Hocevar committed
216
217
/* Even when BSD are supported, BeOS is not likely to be supported, so
 * I prefer to put it apart */
Sam Hocevar's avatar
   
Sam Hocevar committed
218
#if defined( SYS_BEOS )
Henri Fallon's avatar
   
Henri Fallon committed
219
220
    intf_ErrMsg( "error: channel changing is not yet supported under BeOS" );
    return( 1 );
Sam Hocevar's avatar
   
Sam Hocevar committed
221

Sam Hocevar's avatar
   
Sam Hocevar committed
222
#elif defined( SYS_LINUX ) || defined( WIN32 )
Henri Fallon's avatar
   
Henri Fallon committed
223
224
225
226
227
/* FIXME : channels handling only work for linux */
    /* Allocate structure */
    p_main->p_channel = malloc( sizeof( input_channel_t ) );
    if( p_main->p_channel == NULL )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
228
        intf_ErrMsg( "network error: could not create channel bank" );
Henri Fallon's avatar
   
Henri Fallon committed
229
230
231
232
        return( -1 );
    }

    /* Initialize structure */
Sam Hocevar's avatar
   
Sam Hocevar committed
233
    p_main->p_channel->i_channel   = 0;
Henri Fallon's avatar
   
Henri Fallon committed
234
235
    p_main->p_channel->last_change = 0;

Sam Hocevar's avatar
   
Sam Hocevar committed
236
    intf_Msg( "network: channels initialized" );
Henri Fallon's avatar
   
Henri Fallon committed
237
    return( 0 );
Sam Hocevar's avatar
   
Sam Hocevar committed
238

Henri Fallon's avatar
   
Henri Fallon committed
239
#else
Sam Hocevar's avatar
   
Sam Hocevar committed
240
    intf_ErrMsg( "network error : channels not supported" );
Sam Hocevar's avatar
   
Sam Hocevar committed
241
    return( 1 );
Sam Hocevar's avatar
   
Sam Hocevar committed
242
243

#endif
Henri Fallon's avatar
   
Henri Fallon committed
244
245
246
247
248
}

/*****************************************************************************
 * network_ChannelJoin: join a channel
 *****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
249
250
251
252
253
 * This function will try to join a channel. If the relevant interface is
 * already on the good channel, nothing will be done. Else, and if possible
 * (if the interface is not locked), the channel server will be contacted
 * and a change will be requested. The function will block until the change
 * is effective. Note that once a channel is no more used, it's interface
Henri Fallon's avatar
   
Henri Fallon committed
254
255
256
 * should be unlocked using input_ChannelLeave().
 * Non 0 will be returned in case of error.
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
257
int network_ChannelJoin( int i_channel )
Henri Fallon's avatar
   
Henri Fallon committed
258
{
Sam Hocevar's avatar
   
Sam Hocevar committed
259
/* I still prefer to put BeOS a bit apart */
Sam Hocevar's avatar
   
Sam Hocevar committed
260
#if defined( SYS_BEOS )
Sam Hocevar's avatar
   
Sam Hocevar committed
261
    intf_ErrMsg( "network error: channels are not yet supported under BeOS" );
Henri Fallon's avatar
   
Henri Fallon committed
262
    return( -1 );
Sam Hocevar's avatar
   
Sam Hocevar committed
263

Sam Hocevar's avatar
   
Sam Hocevar committed
264
#elif defined( SYS_LINUX ) || defined( WIN32 )
Sam Hocevar's avatar
   
Sam Hocevar committed
265
    int                 i_socket;
Marc Ariberti's avatar
Marc Ariberti committed
266
    int                 i_fromlen;
Henri Fallon's avatar
   
Henri Fallon committed
267
268
    struct sockaddr_in  sa_server;
    struct sockaddr_in  sa_client;
Marc Ariberti's avatar
Marc Ariberti committed
269
    unsigned int        i_version = 12;
Sam Hocevar's avatar
   
Sam Hocevar committed
270
271
    char                psz_mess[ 80 ];
    char                psz_mac[ 40 ];
Marc Ariberti's avatar
Marc Ariberti committed
272
    char                i_mess_length = 80;
Sam Hocevar's avatar
   
Sam Hocevar committed
273
274
    unsigned long int   i_date;
    struct timeval      answer_delay;
Marc Ariberti's avatar
Marc Ariberti committed
275
276
    int                 i_nbanswer;
    char                i_answer;
Sam Hocevar's avatar
   
Sam Hocevar committed
277
    fd_set              fds;
Sam Hocevar's avatar
   
Sam Hocevar committed
278
    unsigned int        i_rc;
279
    char *              psz_channel_server;
Sam Hocevar's avatar
   
Sam Hocevar committed
280

281
282
    if( !main_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR,
                              INPUT_NETWORK_CHANNEL_DEFAULT  ) )
Henri Fallon's avatar
   
Henri Fallon committed
283
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
284
285
        intf_ErrMsg( "network: channels disabled, to enable them, use the"
                     "--channels option" );
Henri Fallon's avatar
   
Henri Fallon committed
286
287
        return( -1 );
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
288
289
290

    /* debug */
    intf_DbgMsg( "network: ChannelJoin : %d", i_channel );
Henri Fallon's avatar
   
Henri Fallon committed
291
292
293
    /* If last change is too recent, wait a while */
    if( mdate() - p_main->p_channel->last_change < INPUT_CHANNEL_CHANGE_DELAY )
    {
294
        intf_WarnMsg( 2, "network: waiting before changing channel" );
Henri Fallon's avatar
   
Henri Fallon committed
295
296
        mwait( p_main->p_channel->last_change + INPUT_CHANNEL_CHANGE_DELAY );
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
297

Henri Fallon's avatar
   
Henri Fallon committed
298
    p_main->p_channel->last_change = mdate();
Sam Hocevar's avatar
   
Sam Hocevar committed
299
    p_main->p_channel->i_channel   = i_channel;
Henri Fallon's avatar
   
Henri Fallon committed
300

301
    intf_WarnMsg( 2, "network: joining channel %d", i_channel );
Henri Fallon's avatar
   
Henri Fallon committed
302
303

    /*
Sam Hocevar's avatar
   
Sam Hocevar committed
304
     * Initializing the socket
Henri Fallon's avatar
   
Henri Fallon committed
305
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
306
    i_socket = socket( AF_INET, SOCK_DGRAM, 0 );
Henri Fallon's avatar
   
Henri Fallon committed
307

Sam Hocevar's avatar
   
Sam Hocevar committed
308
309
    /*
     * Getting the server's information
Henri Fallon's avatar
   
Henri Fallon committed
310
     */
311
312
313
314
315
316
    intf_WarnMsg( 6, "Channel server: %s port: %d",
            main_GetPszVariable( INPUT_CHANNEL_SERVER_VAR,
                                 INPUT_CHANNEL_SERVER_DEFAULT ),
            main_GetIntVariable( INPUT_CHANNEL_PORT_VAR,
                                 INPUT_CHANNEL_PORT_DEFAULT ) );

Sam Hocevar's avatar
   
Sam Hocevar committed
317
    memset( &sa_server, 0x00, sizeof(struct sockaddr_in) );
Marc Ariberti's avatar
Marc Ariberti committed
318
    sa_server.sin_family = AF_INET;
319
320
321
322
323
    sa_server.sin_port   = htons( main_GetIntVariable( INPUT_CHANNEL_PORT_VAR,
                                  INPUT_CHANNEL_PORT_DEFAULT ) );

    psz_channel_server = strdup( main_GetPszVariable( INPUT_CHANNEL_SERVER_VAR,
                                 INPUT_CHANNEL_SERVER_DEFAULT ) );
Sam Hocevar's avatar
   
Sam Hocevar committed
324
#ifdef HAVE_ARPA_INET_H
325
    inet_aton( psz_channel_server, &sa_server.sin_addr );
Sam Hocevar's avatar
   
Sam Hocevar committed
326
#else
327
    sa_server.sin_addr.s_addr = inet_addr( psz_channel_server );
Sam Hocevar's avatar
   
Sam Hocevar committed
328
#endif
329
    free( psz_channel_server );
Marc Ariberti's avatar
Marc Ariberti committed
330

Henri Fallon's avatar
   
Henri Fallon committed
331
332
333
    /*
     * Looking for the interface MAC address
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
334
    if( GetMacAddress( i_socket, psz_mac ) )
Henri Fallon's avatar
   
Henri Fallon committed
335
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
336
337
        intf_ErrMsg( "network error: failed getting MAC address" );
        return( -1 );
Marc Ariberti's avatar
Marc Ariberti committed
338
    }
Henri Fallon's avatar
   
Henri Fallon committed
339

Sam Hocevar's avatar
   
Sam Hocevar committed
340
341
342
343
344
    /*
     * Getting date of the client in seconds
     */
    i_date = mdate() / 1000000;
    intf_DbgMsg( "vlcs: date %lu", i_date );
Henri Fallon's avatar
   
Henri Fallon committed
345

Sam Hocevar's avatar
   
Sam Hocevar committed
346
    /*
Henri Fallon's avatar
   
Henri Fallon committed
347
348
     * Build of the message
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
349
350
351
352
    sprintf( psz_mess, "%d %u %lu %s \n",
             i_channel, i_version, i_date, psz_mac );

    intf_DbgMsg( "vlcs: The message is %s", psz_mess );
Henri Fallon's avatar
   
Henri Fallon committed
353
354
355
356

    /*
     * Open the socket 2
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
357
    memset( &sa_client, 0x00, sizeof(struct sockaddr_in) );
Marc Ariberti's avatar
Marc Ariberti committed
358
359
360
361
    sa_client.sin_family = AF_INET;
    sa_client.sin_port   = htons(4312);
    sa_client.sin_addr.s_addr = INADDR_ANY;
    i_fromlen = sizeof( struct sockaddr );
Sam Hocevar's avatar
   
Sam Hocevar committed
362
    i_rc = bind( i_socket, (struct sockaddr *)(&sa_client),\
Marc Ariberti's avatar
Marc Ariberti committed
363
364
                 sizeof(struct sockaddr) );
    if ( i_rc )
Henri Fallon's avatar
   
Henri Fallon committed
365
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
366
        intf_ErrMsg( "vlcs: Unable to bind socket:%u ", i_rc );
Henri Fallon's avatar
   
Henri Fallon committed
367
368
369
370
371
372
373
374
    /* TODO put CS_R_BIND in types.h*/
    /*    return CS_R_SOCKET;*/
        return -1;
    }

    /*
     * Send the message
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
375
    sendto( i_socket, psz_mess, i_mess_length, 0, \
Marc Ariberti's avatar
Marc Ariberti committed
376
377
            (struct sockaddr *)(&sa_server),   \
            sizeof(struct sockaddr) );
Sam Hocevar's avatar
   
Sam Hocevar committed
378

Henri Fallon's avatar
   
Henri Fallon committed
379
380
381
     /*
     * Waiting 5 sec for one answer from the server
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
382
383
    answer_delay.tv_sec  = 5;
    answer_delay.tv_usec = 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
384
385
386
    FD_ZERO( &fds );
    FD_SET( i_socket, &fds );
    i_nbanswer = select( i_socket + 1, &fds, NULL, NULL, &answer_delay );
Sam Hocevar's avatar
   
Sam Hocevar committed
387
388

    switch( i_nbanswer )
Henri Fallon's avatar
   
Henri Fallon committed
389
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
390
391
392
393
394
395
396
397
398
399
    case 0:
        intf_DbgMsg( "vlcs: no answer" );
        break;

    case -1:
        intf_DbgMsg( "vlcs: unable to receive the answer ");
        break;

    default:
        recvfrom( i_socket, &i_answer, sizeof(char), 0,\
Marc Ariberti's avatar
Marc Ariberti committed
400
                  (struct sockaddr *)(&sa_client), &i_fromlen);
Sam Hocevar's avatar
   
Sam Hocevar committed
401
402
403
404

        intf_DbgMsg( "vlcs: the answer : %i", i_answer );

        switch( i_answer )
Marc Ariberti's avatar
Marc Ariberti committed
405
        {
Sam Hocevar's avatar
   
Sam Hocevar committed
406
407
408
409
410
411
412
413
414
            case -1:
                intf_DbgMsg( "vlcs: the server failed to create the thread" );
                break;
            case 0:
                intf_DbgMsg( "vlcs: the server tries to change the channel" );
                break;
            default:
                intf_DbgMsg( "vlcs: unknown answer !" );
                break;
Marc Ariberti's avatar
Marc Ariberti committed
415
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
416
        break;
Henri Fallon's avatar
   
Henri Fallon committed
417
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
418

Henri Fallon's avatar
   
Henri Fallon committed
419
420
421
    /*
     * Close the socket
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
422
    close( i_socket );
Henri Fallon's avatar
   
Henri Fallon committed
423

Marc Ariberti's avatar
Marc Ariberti committed
424
425
    return( 0 );

Sam Hocevar's avatar
   
Sam Hocevar committed
426
#else
Sam Hocevar's avatar
   
Sam Hocevar committed
427
    intf_ErrMsg( "network error: channels not supported" );
Sam Hocevar's avatar
   
Sam Hocevar committed
428
429
430
    return( -1 );

#endif
Henri Fallon's avatar
   
Henri Fallon committed
431
}
Sam Hocevar's avatar
   
Sam Hocevar committed
432

Sam Hocevar's avatar
   
Sam Hocevar committed
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
/* Following functions are local */

/*****************************************************************************
 * GetMacAddress: extract the MAC Address
 *****************************************************************************/
static int GetMacAddress( int i_socket, char *psz_mac )
{
#if defined( SYS_LINUX )
    struct ifreq interface;
    int i_ret;

    /*
     * Looking for information about the eth0 interface
     */
    interface.ifr_addr.sa_family = AF_INET;
    strcpy( interface.ifr_name, INPUT_IFACE_DEFAULT );

    i_ret = ioctl( i_socket, SIOCGIFHWADDR, &interface );

    if( i_ret )
    {
        intf_ErrMsg( "network error: ioctl SIOCGIFHWADDR failed" );
        return( i_ret );
    }

    sprintf( psz_mac, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
                      interface.ifr_hwaddr.sa_data[0] & 0xff,
                      interface.ifr_hwaddr.sa_data[1] & 0xff,
                      interface.ifr_hwaddr.sa_data[2] & 0xff,
                      interface.ifr_hwaddr.sa_data[3] & 0xff,
                      interface.ifr_hwaddr.sa_data[4] & 0xff,
                      interface.ifr_hwaddr.sa_data[5] & 0xff );

    return( 0 );

#elif defined( WIN32 )
    int i, i_ret = -1;

    /* Get adapter list - support for more than one adapter */
    LANA_ENUM AdapterList;
    NCB       Ncb;

    intf_WarnMsg( 2, "network: looking for MAC address" );

    memset( &Ncb, 0, sizeof( NCB ) );
    Ncb.ncb_command = NCBENUM;
    Ncb.ncb_buffer = (unsigned char *)&AdapterList;
    Ncb.ncb_length = sizeof( AdapterList );
    Netbios( &Ncb );

    /* Get all of the local ethernet addresses */
    for ( i = 0; i < AdapterList.length ; ++i )
    {
        if ( GetAdapterInfo ( AdapterList.lana[ i ], psz_mac ) == 0 )
        {
	    i_ret = 0;
        }
    }

    return( i_ret );

Sam Hocevar's avatar
   
Sam Hocevar committed
494
#else
Sam Hocevar's avatar
   
Sam Hocevar committed
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
    return( -1);

#endif
}

#ifdef WIN32
/*****************************************************************************
 * GetAdapterInfo : gets some informations about the interface using NETBIOS
 *****************************************************************************/
static int GetAdapterInfo( int i_adapter, char *psz_string )
{
    struct ASTAT
    {
        ADAPTER_STATUS adapt;
        NAME_BUFFER    psz_name[30];
    } Adapter;

    /* Reset the LAN adapter so that we can begin querying it */
    NCB Ncb;
    memset( &Ncb, 0, sizeof ( Ncb ) );
    Ncb.ncb_command  = NCBRESET;
    Ncb.ncb_lana_num = i_adapter;

    if( Netbios( &Ncb ) != NRC_GOODRET )
    {
        intf_ErrMsg( "network error: reset returned %i", Ncb.ncb_retcode );
        return -1;
    }

    /* Prepare to get the adapter status block */
    memset( &Ncb, 0, sizeof( Ncb ) ) ;     /* Initialization */
    Ncb.ncb_command = NCBASTAT;
    Ncb.ncb_lana_num = i_adapter;

    strcpy( (char *)Ncb.ncb_callname, "*" );

    memset( &Adapter, 0, sizeof ( Adapter ) );
    Ncb.ncb_buffer = ( unsigned char * ) &Adapter;
    Ncb.ncb_length = sizeof ( Adapter );

    /* Get the adapter's info and, if this works, return it in standard,
     * colon-delimited form. */
    if ( Netbios( &Ncb ) == 0 )
    {
        sprintf ( psz_string, "%02X:%02X:%02X:%02X:%02X:%02X",
                (int) ( Adapter.adapt.adapter_address[0] ),
                (int) ( Adapter.adapt.adapter_address[1] ),
                (int) ( Adapter.adapt.adapter_address[2] ),
                (int) ( Adapter.adapt.adapter_address[3] ),
                (int) ( Adapter.adapt.adapter_address[4] ),
                (int) ( Adapter.adapt.adapter_address[5] ) );

	intf_WarnMsg( 2, "network: found MAC address %s", psz_string );

        return 0;
    }
    else
    {
        intf_ErrMsg( "network error: ASTAT returned %i", Ncb.ncb_retcode );
        return -1;
    }
}
#endif /* WIN32 */