netutils.c 17.1 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
Sam Hocevar's avatar
   
Sam Hocevar committed
5
 * $Id: netutils.c,v 1.34 2001/05/30 17:03:12 sam 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
#include <unistd.h>                                         /* gethostname() */
Henri Fallon's avatar
   
Henri Fallon committed
36
#include <sys/time.h>                                        /* gettimeofday */
37

Sam Hocevar's avatar
   
Sam Hocevar committed
38
39
#ifndef WIN32
#include <netdb.h>                                        /* gethostbyname() */
40
41
#include <netinet/in.h>                               /* BSD: struct in_addr */
#include <sys/socket.h>                              /* BSD: struct sockaddr */
Sam Hocevar's avatar
   
Sam Hocevar committed
42
43
#endif

44
#ifdef HAVE_ARPA_INET_H
45
46
47
#include <arpa/inet.h>                           /* inet_ntoa(), inet_aton() */
#endif

Henri Fallon's avatar
   
Henri Fallon committed
48
49
50
51
#ifdef SYS_LINUX
#include <sys/ioctl.h>                                            /* ioctl() */
#endif

Xavier Marchesini's avatar
Xavier Marchesini committed
52
53
54
55
56
#ifdef WIN32                            /* tools to get the MAC adress from  */
#include <windows.h>                    /* the interface under Windows	     */
#include <stdio.h>
#endif

Sam Hocevar's avatar
   
Sam Hocevar committed
57
#ifdef HAVE_NET_IF_H
58
59
#include <net/if.h>                            /* interface (arch-dependent) */
#endif
Henri Fallon's avatar
   
Henri Fallon committed
60

Benoit Steiner's avatar
   
Benoit Steiner committed
61
#ifdef HAVE_SYS_SOCKIO_H
Benoit Steiner's avatar
Benoit Steiner committed
62
#include <sys/sockio.h>
Benoit Steiner's avatar
   
Benoit Steiner committed
63
#endif
Michel Kaempf's avatar
Michel Kaempf committed
64
65
66
67

#include "config.h"
#include "common.h"
#include "mtime.h"
Henri Fallon's avatar
   
Henri Fallon committed
68
#include "threads.h"
Henri Fallon's avatar
   
Henri Fallon committed
69
#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
70
71
72

#include "intf_msg.h"

Sam Hocevar's avatar
   
Sam Hocevar committed
73
#include "netutils.h"
Henri Fallon's avatar
   
Henri Fallon committed
74

75
/*****************************************************************************
Henri Fallon's avatar
   
Henri Fallon committed
76
77
78
79
80
81
82
83
84
 * 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
85
    int         i_channel;                         /* current channel number */
Henri Fallon's avatar
   
Henri Fallon committed
86
87
88
    mtime_t     last_change;                             /* last change date */
} input_channel_t;

Xavier Marchesini's avatar
Xavier Marchesini committed
89
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
90
91
92
93
94
 * 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
95
96
#endif

Henri Fallon's avatar
   
Henri Fallon committed
97
98
/*****************************************************************************
 * network_BuildLocalAddr : fill a sockaddr_in structure for local binding
99
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
100
int network_BuildLocalAddr( struct sockaddr_in * p_socket, int i_port,
Henri Fallon's avatar
   
Henri Fallon committed
101
                            char * psz_broadcast )
Michel Kaempf's avatar
Michel Kaempf committed
102
{
Henri Fallon's avatar
   
Henri Fallon committed
103
104
    char                psz_hostname[INPUT_MAX_SOURCE_LENGTH];
    struct hostent    * p_hostent;
Sam Hocevar's avatar
   
Sam Hocevar committed
105

Henri Fallon's avatar
   
Henri Fallon committed
106
107
    /* Reset struct */
    memset( p_socket, 0, sizeof( struct sockaddr_in ) );
Sam Hocevar's avatar
   
Sam Hocevar committed
108
    p_socket->sin_family = AF_INET;                                /* family */
Henri Fallon's avatar
   
Henri Fallon committed
109
    p_socket->sin_port = htons( i_port );
Henri Fallon's avatar
   
Henri Fallon committed
110
    if( psz_broadcast == NULL )
Henri Fallon's avatar
   
Henri Fallon committed
111
112
113
114
115
116
117
118
    {
        /* 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
119

Henri Fallon's avatar
   
Henri Fallon committed
120
121
    }
    else
Sam Hocevar's avatar
   
Sam Hocevar committed
122
123
    {
        /* I didn't manage to make INADDR_ANYT work, even with setsockopt
Henri Fallon's avatar
   
Henri Fallon committed
124
125
126
         * 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 );
127
    }
Henri Fallon's avatar
   
Henri Fallon committed
128

129
130
    /* 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
131
132
#ifdef HAVE_ARPA_INET_H
    if( !inet_aton( psz_hostname, &p_socket->sin_addr) )
133
#else
Henri Fallon's avatar
   
Henri Fallon committed
134
    if( (p_socket->sin_addr.s_addr = inet_addr( psz_hostname )) == -1 )
135
#endif
Michel Kaempf's avatar
Michel Kaempf committed
136
    {
Henri Fallon's avatar
   
Henri Fallon committed
137
138
        /* We have a fqdn, try to find its address */
        if ( (p_hostent = gethostbyname( psz_hostname )) == NULL )
Michel Kaempf's avatar
Michel Kaempf committed
139
        {
Henri Fallon's avatar
   
Henri Fallon committed
140
            intf_ErrMsg( "BuildLocalAddr: unknown host %s", psz_hostname );
141
            return( -1 );
Michel Kaempf's avatar
Michel Kaempf committed
142
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
143

Michel Kaempf's avatar
Michel Kaempf committed
144
        /* Copy the first address of the host in the socket address */
Sam Hocevar's avatar
   
Sam Hocevar committed
145
        memcpy( &p_socket->sin_addr, p_hostent->h_addr_list[0],
Henri Fallon's avatar
   
Henri Fallon committed
146
                 p_hostent->h_length );
Michel Kaempf's avatar
Michel Kaempf committed
147
    }
148
    return( 0 );
Michel Kaempf's avatar
Michel Kaempf committed
149
150
}

151
/*****************************************************************************
Henri Fallon's avatar
   
Henri Fallon committed
152
 * network_BuildRemoteAddr : fill a sockaddr_in structure for remote host
153
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
154
int network_BuildRemoteAddr( struct sockaddr_in * p_socket, char * psz_server )
Michel Kaempf's avatar
Michel Kaempf committed
155
{
Henri Fallon's avatar
   
Henri Fallon committed
156
    struct hostent            * p_hostent;
Sam Hocevar's avatar
   
Sam Hocevar committed
157

Henri Fallon's avatar
   
Henri Fallon committed
158
159
    /* Reset structure */
    memset( p_socket, 0, sizeof( struct sockaddr_in ) );
Sam Hocevar's avatar
   
Sam Hocevar committed
160
161
    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
162

Henri Fallon's avatar
   
Henri Fallon committed
163
164
     /* 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
165

Henri Fallon's avatar
   
Henri Fallon committed
166
167
#ifdef HAVE_ARPA_INET_H
    if( !inet_aton( psz_server, &p_socket->sin_addr) )
Benoit Steiner's avatar
Benoit Steiner committed
168
#else
Henri Fallon's avatar
   
Henri Fallon committed
169
    if( (p_socket->sin_addr.s_addr = inet_addr( psz_server )) == -1 )
170
#endif
Michel Kaempf's avatar
Michel Kaempf committed
171
    {
Henri Fallon's avatar
   
Henri Fallon committed
172
173
        /* We have a fqdn, try to find its address */
        if ( (p_hostent = gethostbyname(psz_server)) == NULL )
Michel Kaempf's avatar
Michel Kaempf committed
174
        {
Sam Hocevar's avatar
   
Sam Hocevar committed
175
            intf_ErrMsg( "BuildRemoteAddr: unknown host %s",
Henri Fallon's avatar
   
Henri Fallon committed
176
177
                         psz_server );
            return( -1 );
Michel Kaempf's avatar
Michel Kaempf committed
178
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
179

Henri Fallon's avatar
   
Henri Fallon committed
180
        /* Copy the first address of the host in the socket address */
Sam Hocevar's avatar
   
Sam Hocevar committed
181
        memcpy( &p_socket->sin_addr, p_hostent->h_addr_list[0],
Henri Fallon's avatar
   
Henri Fallon committed
182
                 p_hostent->h_length );
Michel Kaempf's avatar
Michel Kaempf committed
183
    }
Henri Fallon's avatar
   
Henri Fallon committed
184
    return( 0 );
Michel Kaempf's avatar
Michel Kaempf committed
185
}
Sam Hocevar's avatar
   
Sam Hocevar committed
186

Henri Fallon's avatar
   
Henri Fallon committed
187
188
189
190
/*****************************************************************************
 * 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
191
 * once before any input thread is created or any call to other
Henri Fallon's avatar
   
Henri Fallon committed
192
193
194
195
 * input_Channel*() function is attempted.
 *****************************************************************************/
int network_ChannelCreate( void )
{
Sam Hocevar's avatar
   
Sam Hocevar committed
196
197
/* 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
198
#if defined( SYS_BEOS )
Henri Fallon's avatar
   
Henri Fallon committed
199
200
    intf_ErrMsg( "error: channel changing is not yet supported under BeOS" );
    return( 1 );
Sam Hocevar's avatar
   
Sam Hocevar committed
201

Sam Hocevar's avatar
   
Sam Hocevar committed
202
#elif defined( SYS_LINUX ) || defined( WIN32 )
Henri Fallon's avatar
   
Henri Fallon committed
203
204
205
206
207
/* 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
208
        intf_ErrMsg( "network error: could not create channel bank" );
Henri Fallon's avatar
   
Henri Fallon committed
209
210
211
212
        return( -1 );
    }

    /* Initialize structure */
Sam Hocevar's avatar
   
Sam Hocevar committed
213
    p_main->p_channel->i_channel   = 0;
Henri Fallon's avatar
   
Henri Fallon committed
214
215
    p_main->p_channel->last_change = 0;

Sam Hocevar's avatar
   
Sam Hocevar committed
216
    intf_Msg( "network: channels initialized" );
Henri Fallon's avatar
   
Henri Fallon committed
217
    return( 0 );
Sam Hocevar's avatar
   
Sam Hocevar committed
218

Henri Fallon's avatar
   
Henri Fallon committed
219
#else
Sam Hocevar's avatar
   
Sam Hocevar committed
220
    intf_ErrMsg( "network error : channels not supported" );
Sam Hocevar's avatar
   
Sam Hocevar committed
221
    return( 1 );
Sam Hocevar's avatar
   
Sam Hocevar committed
222
223

#endif
Henri Fallon's avatar
   
Henri Fallon committed
224
225
226
227
228
}

/*****************************************************************************
 * network_ChannelJoin: join a channel
 *****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
229
230
231
232
233
 * 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
234
235
236
 * should be unlocked using input_ChannelLeave().
 * Non 0 will be returned in case of error.
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
237
int network_ChannelJoin( int i_channel )
Henri Fallon's avatar
   
Henri Fallon committed
238
{
Sam Hocevar's avatar
   
Sam Hocevar committed
239
/* I still prefer to put BeOS a bit apart */
Sam Hocevar's avatar
   
Sam Hocevar committed
240
#if defined( SYS_BEOS )
Sam Hocevar's avatar
   
Sam Hocevar committed
241
    intf_ErrMsg( "network error: channels are not yet supported under BeOS" );
Henri Fallon's avatar
   
Henri Fallon committed
242
    return( -1 );
Sam Hocevar's avatar
   
Sam Hocevar committed
243

Sam Hocevar's avatar
   
Sam Hocevar committed
244
#elif defined( SYS_LINUX ) || defined( WIN32 )
Sam Hocevar's avatar
   
Sam Hocevar committed
245
    int                 i_socket;
Marc Ariberti's avatar
Marc Ariberti committed
246
    int                 i_fromlen;
Henri Fallon's avatar
   
Henri Fallon committed
247
248
    struct sockaddr_in  sa_server;
    struct sockaddr_in  sa_client;
Marc Ariberti's avatar
Marc Ariberti committed
249
    unsigned int        i_version = 12;
Sam Hocevar's avatar
   
Sam Hocevar committed
250
251
    char                psz_mess[ 80 ];
    char                psz_mac[ 40 ];
Marc Ariberti's avatar
Marc Ariberti committed
252
    char                i_mess_length = 80;
Sam Hocevar's avatar
   
Sam Hocevar committed
253
254
    unsigned long int   i_date;
    struct timeval      answer_delay;
Marc Ariberti's avatar
Marc Ariberti committed
255
256
    int                 i_nbanswer;
    char                i_answer;
Sam Hocevar's avatar
   
Sam Hocevar committed
257
    fd_set              fd;
Sam Hocevar's avatar
   
Sam Hocevar committed
258
    unsigned int        i_rc;
Sam Hocevar's avatar
   
Sam Hocevar committed
259

Henri Fallon's avatar
   
Henri Fallon committed
260
261
    if( ! p_main->b_channels )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
262
263
        intf_ErrMsg( "network: channels disabled, to enable them, use the"
                     "--channels option" );
Henri Fallon's avatar
   
Henri Fallon committed
264
265
        return( -1 );
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
266
267
268

    /* debug */
    intf_DbgMsg( "network: ChannelJoin : %d", i_channel );
Henri Fallon's avatar
   
Henri Fallon committed
269
270
271
    /* If last change is too recent, wait a while */
    if( mdate() - p_main->p_channel->last_change < INPUT_CHANNEL_CHANGE_DELAY )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
272
        intf_Msg( "network: waiting before changing channel" );
Henri Fallon's avatar
   
Henri Fallon committed
273
274
        mwait( p_main->p_channel->last_change + INPUT_CHANNEL_CHANGE_DELAY );
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
275

Henri Fallon's avatar
   
Henri Fallon committed
276
    p_main->p_channel->last_change = mdate();
Sam Hocevar's avatar
   
Sam Hocevar committed
277
    p_main->p_channel->i_channel   = i_channel;
Henri Fallon's avatar
   
Henri Fallon committed
278

Sam Hocevar's avatar
   
Sam Hocevar committed
279
    intf_Msg( "network: joining channel %d", i_channel );
Henri Fallon's avatar
   
Henri Fallon committed
280
281

    /*
Sam Hocevar's avatar
   
Sam Hocevar committed
282
     * Initializing the socket
Henri Fallon's avatar
   
Henri Fallon committed
283
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
284
    i_socket = socket( AF_INET, SOCK_DGRAM, 0 );
Henri Fallon's avatar
   
Henri Fallon committed
285

Sam Hocevar's avatar
   
Sam Hocevar committed
286
287
    /*
     * Getting the server's information
Henri Fallon's avatar
   
Henri Fallon committed
288
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
289
    memset( &sa_server, 0x00, sizeof(struct sockaddr_in) );
Marc Ariberti's avatar
Marc Ariberti committed
290
291
    sa_server.sin_family = AF_INET;
    sa_server.sin_port   = htons( INPUT_CHANNEL_PORT_DEFAULT );
Sam Hocevar's avatar
   
Sam Hocevar committed
292
#ifdef HAVE_ARPA_INET_H
Sam Hocevar's avatar
   
Sam Hocevar committed
293
    inet_aton( INPUT_CHANNEL_SERVER_DEFAULT, &sa_server.sin_addr );
Sam Hocevar's avatar
   
Sam Hocevar committed
294
#else
Sam Hocevar's avatar
   
Sam Hocevar committed
295
    sa_server.sin_addr.s_addr = inet_addr( INPUT_CHANNEL_SERVER_DEFAULT );
Sam Hocevar's avatar
   
Sam Hocevar committed
296
#endif
Marc Ariberti's avatar
Marc Ariberti committed
297

Henri Fallon's avatar
   
Henri Fallon committed
298
299
300
    /*
     * Looking for the interface MAC address
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
301
    if( GetMacAddress( i_socket, psz_mac ) )
Henri Fallon's avatar
   
Henri Fallon committed
302
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
303
304
        intf_ErrMsg( "network error: failed getting MAC address" );
        return( -1 );
Marc Ariberti's avatar
Marc Ariberti committed
305
    }
Henri Fallon's avatar
   
Henri Fallon committed
306

Sam Hocevar's avatar
   
Sam Hocevar committed
307
308
309
310
311
    /*
     * 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
312

Sam Hocevar's avatar
   
Sam Hocevar committed
313
    /*
Henri Fallon's avatar
   
Henri Fallon committed
314
315
     * Build of the message
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
316
317
318
319
    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
320
321
322
323

    /*
     * Open the socket 2
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
324
    memset( &sa_client, 0x00, sizeof(struct sockaddr_in) );
Marc Ariberti's avatar
Marc Ariberti committed
325
326
327
328
    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
329
    i_rc = bind( i_socket, (struct sockaddr *)(&sa_client),\
Marc Ariberti's avatar
Marc Ariberti committed
330
331
                 sizeof(struct sockaddr) );
    if ( i_rc )
Henri Fallon's avatar
   
Henri Fallon committed
332
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
333
        intf_ErrMsg( "vlcs: Unable to bind socket:%u ", i_rc );
Henri Fallon's avatar
   
Henri Fallon committed
334
335
336
337
338
339
340
341
    /* TODO put CS_R_BIND in types.h*/
    /*    return CS_R_SOCKET;*/
        return -1;
    }

    /*
     * Send the message
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
342
    sendto( i_socket, psz_mess, i_mess_length, 0, \
Marc Ariberti's avatar
Marc Ariberti committed
343
344
            (struct sockaddr *)(&sa_server),   \
            sizeof(struct sockaddr) );
Sam Hocevar's avatar
   
Sam Hocevar committed
345

Henri Fallon's avatar
   
Henri Fallon committed
346
347
348
     /*
     * Waiting 5 sec for one answer from the server
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
349
350
351
352
353
354
355
    answer_delay.tv_sec  = 5;
    answer_delay.tv_usec = 0;
    FD_ZERO( &fd );
    FD_SET( i_socket, &fd );
    i_nbanswer = select( i_socket + 1, &fd, NULL, NULL, &answer_delay );

    switch( i_nbanswer )
Henri Fallon's avatar
   
Henri Fallon committed
356
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
357
358
359
360
361
362
363
364
365
366
    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
367
                  (struct sockaddr *)(&sa_client), &i_fromlen);
Sam Hocevar's avatar
   
Sam Hocevar committed
368
369
370
371

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

        switch( i_answer )
Marc Ariberti's avatar
Marc Ariberti committed
372
        {
Sam Hocevar's avatar
   
Sam Hocevar committed
373
374
375
376
377
378
379
380
381
            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
382
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
383
        break;
Henri Fallon's avatar
   
Henri Fallon committed
384
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
385

Henri Fallon's avatar
   
Henri Fallon committed
386
387
388
    /*
     * Close the socket
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
389
    close( i_socket );
Henri Fallon's avatar
   
Henri Fallon committed
390

Marc Ariberti's avatar
Marc Ariberti committed
391
392
    return( 0 );

Sam Hocevar's avatar
   
Sam Hocevar committed
393
#else
Sam Hocevar's avatar
   
Sam Hocevar committed
394
    intf_ErrMsg( "network error: channels not supported" );
Sam Hocevar's avatar
   
Sam Hocevar committed
395
396
397
    return( -1 );

#endif
Henri Fallon's avatar
   
Henri Fallon committed
398
}
Sam Hocevar's avatar
   
Sam Hocevar committed
399

Sam Hocevar's avatar
   
Sam Hocevar committed
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
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
/* 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
461
#else
Sam Hocevar's avatar
   
Sam Hocevar committed
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
494
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
    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 */