]> git.sesse.net Git - vlc/blob - src/misc/netutils.c
D�but du portage BeOS. Beaucoup de fuchiers ont �t� modifi� car il a fallu
[vlc] / src / misc / netutils.c
1 /*****************************************************************************
2  * netutils.c: various network functions
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  *
6  * Authors:
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public
19  * License along with this program; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <netdb.h>                                        /* gethostbyname() */
28 #include <stdlib.h>                             /* free(), realloc(), atoi() */
29 #include <errno.h>                                                /* errno() */
30 #include <string.h>                                      /* bzero(), bcopy() */
31
32 #ifdef SYS_BSD
33 #include <netinet/in.h>                                    /* struct in_addr */
34 #include <sys/socket.h>                                   /* struct sockaddr */
35 #endif
36
37 #if defined(SYS_LINUX) || defined(SYS_BSD) || defined(SYS_GNU)
38 #include <arpa/inet.h>                           /* inet_ntoa(), inet_aton() */
39 #endif
40
41
42 #ifdef SYS_LINUX
43 #include <sys/ioctl.h>                                            /* ioctl() */
44 #include <net/if.h>                            /* interface (arch-dependent) */
45 #endif
46
47 #include "config.h"
48 #include "common.h"
49 #include "mtime.h"
50
51 #include "intf_msg.h"
52 #include "debug.h"
53
54 #include "netutils.h"
55
56 /*****************************************************************************
57  * BuildInetAddr: build an Internet address descriptor
58  *****************************************************************************
59  * Build an internet socket descriptor from a host name, or an ip, and a port.
60  * If the address is NULL, then INADDR_ANY will be used, allowing to receive
61  * on any address for a local socket. Usually, in this case, 'port' is also null
62  * and the function always succeeds.
63  *****************************************************************************/
64 int BuildInetAddr( struct sockaddr_in *p_sa_in, char *psz_in_addr, int i_port )
65 {
66     struct hostent *p_hostent;                            /* host descriptor */
67
68     memset( p_sa_in, 0, sizeof( struct sockaddr_in ) );
69     p_sa_in->sin_family = AF_INET;                                 /* family */
70     p_sa_in->sin_port = htons( i_port );                             /* port */
71
72     /* Use INADDR_ANY if psz_in_addr is NULL */
73     if( psz_in_addr == NULL )
74     {
75         p_sa_in->sin_addr.s_addr = htonl(INADDR_ANY);
76     }
77     /* Try to convert address directly from in_addr - this will work if
78      * psz_in_addr is dotted decimal. */
79 #ifdef SYS_BEOS
80     else if( (p_sa_in->sin_addr.s_addr = inet_addr( psz_in_addr )) == -1 )
81 #else
82     else if( !inet_aton( psz_in_addr, &p_sa_in->sin_addr) )
83 #endif
84     {
85         /* The convertion failed: the address is an host name, which needs
86          * to be resolved */
87         intf_DbgMsg("debug: resolving internet address %s...\n", psz_in_addr);
88         if ( (p_hostent = gethostbyname(psz_in_addr)) == NULL)
89         {
90             intf_ErrMsg("error: unknown host %s\n", psz_in_addr);
91             return( -1 );
92         }
93
94         /* Copy the first address of the host in the socket address */
95         memmove( &p_sa_in->sin_addr, p_hostent->h_addr_list[0], p_hostent->h_length );
96     }
97     return( 0 );
98 }
99
100
101 /*****************************************************************************
102  * ServerPort: extract port from a "server:port" adress
103  *****************************************************************************
104  * Returns the port number in a "server:port" address and replace the ":" by
105  * a NUL character, or returns -1.
106  *****************************************************************************/
107 int ServerPort( char *psz_addr )
108 {
109     char *psz_index;
110
111     /* Scan string for ':' */
112     for( psz_index = psz_addr; *psz_index && (*psz_index != ':'); psz_index++ )
113     {
114         ;
115     }
116
117     /* If a port number has been found, convert it and return it */
118     if( *psz_index == ':' )
119     {
120         *psz_index = '\0';
121         return( atoi( psz_index + 1 ) );
122     }
123
124     return( - 1 );
125 }
126
127
128 /*****************************************************************************
129  * ReadIfConf: Read the configuration of an interface
130  *****************************************************************************
131  * i_sockfd must reference a socket open as follow: AF_INET, DOCK_DGRAM, 0
132  *****************************************************************************/
133 int ReadIfConf(int i_sockfd, if_descr_t* p_ifdescr, char* psz_name)
134 {
135     int i_rc = 0;
136 #ifdef SYS_LINUX
137     struct ifreq ifr_config;
138
139     ASSERT(p_ifdescr);
140     ASSERT(psz_name);
141
142     /* Which interface are we interested in ? */
143     strcpy(ifr_config.ifr_name, psz_name);
144
145     /* Read the flags for that interface */
146     i_rc = ioctl(i_sockfd, SIOCGIFFLAGS, (byte_t *)&ifr_config);
147     if( !i_rc )
148     {
149         p_ifdescr->i_flags = ifr_config.ifr_flags;
150         intf_DbgMsg("%s flags: 0x%x\n", psz_name, p_ifdescr->i_flags);
151     }
152     else
153     {
154         intf_ErrMsg("Cannot read flags for interface %s: %s\n", psz_name,
155                     strerror(errno));
156         return -1;
157     }
158
159    /* Read physical address of the interface and store it in our description */
160     i_rc = ioctl(i_sockfd, SIOCGIFHWADDR, (byte_t *)&ifr_config);
161     if( !i_rc )
162     {
163         memcpy(&p_ifdescr->sa_phys_addr, &ifr_config.ifr_addr, sizeof(struct sockaddr));
164         intf_DbgMsg("%s MAC address: %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", psz_name,
165                     p_ifdescr->sa_phys_addr.sa_data[0]&0xff,
166                     p_ifdescr->sa_phys_addr.sa_data[1]&0xff,
167                     p_ifdescr->sa_phys_addr.sa_data[2]&0xff,
168                     p_ifdescr->sa_phys_addr.sa_data[3]&0xff,
169                     p_ifdescr->sa_phys_addr.sa_data[4]&0xff,
170                     p_ifdescr->sa_phys_addr.sa_data[5]&0xff);
171     }
172     else
173     {
174         intf_ErrMsg("Cannot read hardware address for interface %s: %s\n",
175                     psz_name, strerror(errno));
176         return -1;
177     }
178
179     /* Read IP address of the interface and store it in our description */
180     i_rc = ioctl(i_sockfd, SIOCGIFADDR, (byte_t *)&ifr_config);
181     if( !i_rc )
182     {
183         memcpy(&p_ifdescr->sa_net_addr, &ifr_config.ifr_addr, sizeof(struct sockaddr));
184         intf_DbgMsg("%s IP address: %s\n", psz_name,
185                     inet_ntoa(p_ifdescr->sa_net_addr.sin_addr));
186     }
187     else
188     {
189         intf_ErrMsg("Cannot read network address for interface %s: %s\n",
190                     psz_name, strerror(errno));
191         return -1;
192     }
193
194   /* Read broadcast address of the interface and store it in our description */
195     if(p_ifdescr->i_flags & IFF_POINTOPOINT)
196     {
197         intf_DbgMsg("%s doen't not support broadcast\n", psz_name);
198         i_rc = ioctl(i_sockfd, SIOCGIFDSTADDR, (byte_t *)&ifr_config);
199     }
200     else
201     {
202         intf_DbgMsg("%s supports broadcast\n", psz_name);
203         i_rc = ioctl(i_sockfd, SIOCGIFBRDADDR, (byte_t *)&ifr_config);
204     }
205     if( !i_rc )
206     {
207         memcpy(&p_ifdescr->sa_bcast_addr, &ifr_config.ifr_addr, sizeof(struct sockaddr));
208         intf_DbgMsg("%s broadcast address: %s\n", psz_name,
209                     inet_ntoa(p_ifdescr->sa_bcast_addr.sin_addr));
210     }
211     else
212     {
213         intf_ErrMsg("Cannot read broadcast address for interface %s: %s\n",
214                     psz_name, strerror(errno));
215         return -1;
216     }
217 #endif /* SYS_LINUX */
218
219     return i_rc;
220 }
221
222
223
224 /*****************************************************************************
225  * ReadNetConf: Retrieve the network configuration of the host
226  *****************************************************************************
227  * Only IP interfaces are listed, and only if they are up
228  * i_sockfd must reference a socket open as follow: AF_INET, DOCK_DGRAM, 0
229  *****************************************************************************/
230 int ReadNetConf(int i_sockfd, net_descr_t* p_net_descr)
231 {
232 #ifdef SYS_LINUX
233     struct ifreq* a_ifr_ifconf = NULL;
234     struct ifreq* p_ifr_current_if;
235     struct ifconf ifc_netconf;
236
237     int i_if_number;
238     int i_remaining;
239 #endif /* SYS_LINUX */
240     int i_rc = 0;
241
242 #ifdef SYS_LINUX
243     ASSERT(p_net_descr);
244
245     /* Start by assuming we have few than 3 interfaces (i_if_number will
246        be incremented by 1 when entering the loop) */
247     i_if_number = 2;
248
249     /* Retrieve network configuration for that host */
250     do
251     {
252         i_if_number++;
253         a_ifr_ifconf = realloc(a_ifr_ifconf, i_if_number*sizeof(struct ifreq));
254         ifc_netconf.ifc_len = i_if_number*sizeof(struct ifreq);
255         ifc_netconf.ifc_req = a_ifr_ifconf;
256
257         i_rc = ioctl(i_sockfd, SIOCGIFCONF, (byte_t*)&ifc_netconf);
258         if( i_rc )
259         {
260             intf_ErrMsg("Cannot read network configuration: %s\n",
261                         strerror(errno));
262             break;
263         }
264     }
265     /* If we detected ifc_len interfaces, this may mean that others have
266        been missed because the a_ifr_ifconf was to little, so increase
267        it's size and retry */
268     while( ifc_netconf.ifc_len >= i_if_number*sizeof(struct ifreq) );
269
270     /* No see what we detected */
271     if( !i_rc )
272     {
273         /* Init the given net_descr_t struct */
274         p_net_descr->i_if_number = 0;
275         p_net_descr->a_if = NULL;
276
277         /* Iterate through the entries of the a_ifr_ifconf table */
278         p_ifr_current_if = ifc_netconf.ifc_req;
279         for( i_remaining = ifc_netconf.ifc_len / sizeof (struct ifreq);
280              i_remaining-- > 0; p_ifr_current_if++ )
281         {
282             intf_DbgMsg("Found interface %s\n", p_ifr_current_if->ifr_name);
283
284             /* Don't use an interface devoted to an address family other than IP */
285             if(p_ifr_current_if->ifr_addr.sa_family != AF_INET)
286                 continue;
287
288             /* Read the status of this interface */
289             if( ioctl(i_sockfd, SIOCGIFFLAGS, (byte_t *)p_ifr_current_if) < 0 )
290             {
291                 intf_ErrMsg("Cannot access interface %s: %s\n",
292                             p_ifr_current_if->ifr_name, strerror(errno));
293                 i_rc = -1;
294                 break;
295             }
296             else
297             {
298                 /* Skip this interface if it is not up or if this is a loopback one */
299                 if( !p_ifr_current_if->ifr_flags & IFF_UP ||
300                     p_ifr_current_if->ifr_flags & IFF_LOOPBACK )
301                   continue;
302
303                 /* Add an entry to the net_descr struct to store the description of
304                    that interface */
305                 p_net_descr->i_if_number++;
306                 p_net_descr->a_if = realloc(p_net_descr->a_if,
307                                             p_net_descr->i_if_number*sizeof(if_descr_t));
308                 /* FIXME: Read the info ?? */
309                 i_rc = ReadIfConf(i_sockfd, &p_net_descr->a_if[p_net_descr->i_if_number-1],
310                                   p_ifr_current_if->ifr_name);
311             }
312         }
313     }
314
315     /* Don't need the a_ifr_ifconf anymore */
316     free( a_ifr_ifconf );
317 #endif /* SYS_LINUX */
318
319     return i_rc;
320 }
321
322