1 /*******************************************************************************
2 * netutils.c: various network functions
4 *******************************************************************************
6 *******************************************************************************
9 *******************************************************************************/
11 /*******************************************************************************
13 *******************************************************************************/
19 #include <sys/ioctl.h>
21 #include <arpa/inet.h>
22 #include <netinet/in.h>
23 #include <sys/socket.h>
34 /*******************************************************************************
35 * BuildInetAddr: build an Internet address descriptor
36 *******************************************************************************
37 * Build an internet socket descriptor from a host name, or an ip, and a port.
38 * If the address is NULL, then INADDR_ANY will be used, allowing to receive
39 * on any address for a local socket. Usually, in this case, 'port' is also null
40 * and the function always succeeds.
41 *******************************************************************************/
42 int BuildInetAddr( struct sockaddr_in *p_sa_in, char *psz_in_addr, int i_port )
44 struct hostent *p_hostent; /* host descriptor */
46 bzero( p_sa_in, sizeof( struct sockaddr_in ) );
47 p_sa_in->sin_family = AF_INET; /* family */
48 p_sa_in->sin_port = htons( i_port ); /* port */
50 /* Use INADDR_ANY if psz_in_addr is NULL */
51 if( psz_in_addr == NULL )
53 p_sa_in->sin_addr.s_addr = htonl(INADDR_ANY);
55 /* Try to convert address directly from in_addr - this will work if
56 * psz_in_addr is dotted decimal. */
57 else if( !inet_aton( psz_in_addr, &p_sa_in->sin_addr) )
59 /* The convertion failed: the address is an host name, which needs
61 intf_DbgMsg("debug: resolving internet address %s...\n", psz_in_addr);
62 if ( (p_hostent = gethostbyname(psz_in_addr)) == NULL)
64 intf_ErrMsg("error: unknown host %s\n", psz_in_addr);
68 /* Copy the first address of the host in the socket address */
69 bcopy( p_hostent->h_addr_list[0], &p_sa_in->sin_addr, p_hostent->h_length);
75 /*******************************************************************************
76 * ServerPort: extract port from a "server:port" adress
77 *******************************************************************************
78 * Returns the port number in a "server:port" address and replace the ":" by
79 * a NUL character, or returns -1.
80 *******************************************************************************/
81 int ServerPort( char *psz_addr )
85 /* Scan string for ':' */
86 for( psz_index = psz_addr; *psz_index && (*psz_index != ':'); psz_index++ )
91 /* If a port number has been found, convert it and return it */
92 if( *psz_index == ':' )
95 return( atoi( psz_index + 1 ) );
102 /*******************************************************************************
103 * ReadIfConf: Read the configuration of an interface
104 *******************************************************************************
105 * i_sockfd must reference a socket open as follow: AF_INET, DOCK_DGRAM, 0
106 *******************************************************************************/
107 int ReadIfConf(int i_sockfd, if_descr_t* p_ifdescr, char* psz_name)
109 struct ifreq ifr_config;
115 /* Which interface are we interested in ? */
116 strcpy(ifr_config.ifr_name, psz_name);
118 /* Read the flags for that interface */
119 i_rc = ioctl(i_sockfd, SIOCGIFFLAGS, (byte_t *)&ifr_config);
122 p_ifdescr->i_flags = ifr_config.ifr_flags;
123 intf_DbgMsg("%s flags: 0x%x\n", psz_name, p_ifdescr->i_flags);
127 intf_ErrMsg("Cannot read flags for interface %s: %s\n", psz_name,
132 /* Read physical address of the interface and store it in our description */
133 i_rc = ioctl(i_sockfd, SIOCGIFHWADDR, (byte_t *)&ifr_config);
136 memcpy(&p_ifdescr->sa_phys_addr, &ifr_config.ifr_addr, sizeof(struct sockaddr));
137 intf_DbgMsg("%s MAC address: %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", psz_name,
138 p_ifdescr->sa_phys_addr.sa_data[0]&0xff,
139 p_ifdescr->sa_phys_addr.sa_data[1]&0xff,
140 p_ifdescr->sa_phys_addr.sa_data[2]&0xff,
141 p_ifdescr->sa_phys_addr.sa_data[3]&0xff,
142 p_ifdescr->sa_phys_addr.sa_data[4]&0xff,
143 p_ifdescr->sa_phys_addr.sa_data[5]&0xff);
147 intf_ErrMsg("Cannot read hardware address for interface %s: %s\n",
148 psz_name, strerror(errno));
152 /* Read IP address of the interface and store it in our description */
153 i_rc = ioctl(i_sockfd, SIOCGIFADDR, (byte_t *)&ifr_config);
156 memcpy(&p_ifdescr->sa_net_addr, &ifr_config.ifr_addr, sizeof(struct sockaddr));
157 intf_DbgMsg("%s IP address: %s\n", psz_name,
158 inet_ntoa(p_ifdescr->sa_net_addr.sin_addr));
162 intf_ErrMsg("Cannot read network address for interface %s: %s\n",
163 psz_name, strerror(errno));
167 /* Read broadcast address of the interface and store it in our description */
168 if(p_ifdescr->i_flags & IFF_POINTOPOINT)
170 intf_DbgMsg("%s doen't not support broadcast\n", psz_name);
171 i_rc = ioctl(i_sockfd, SIOCGIFDSTADDR, (byte_t *)&ifr_config);
175 intf_DbgMsg("%s supports broadcast\n", psz_name);
176 i_rc = ioctl(i_sockfd, SIOCGIFBRDADDR, (byte_t *)&ifr_config);
180 memcpy(&p_ifdescr->sa_bcast_addr, &ifr_config.ifr_addr, sizeof(struct sockaddr));
181 intf_DbgMsg("%s broadcast address: %s\n", psz_name,
182 inet_ntoa(p_ifdescr->sa_bcast_addr.sin_addr));
186 intf_ErrMsg("Cannot read broadcast address for interface %s: %s\n",
187 psz_name, strerror(errno));
196 /*******************************************************************************
197 * ReadNetConf: Retrieve the network configuration of the host
198 *******************************************************************************
199 * Only IP interfaces are listed, and only if they are up
200 * i_sockfd must reference a socket open as follow: AF_INET, DOCK_DGRAM, 0
201 *******************************************************************************/
202 int ReadNetConf(int i_sockfd, net_descr_t* p_net_descr)
204 struct ifreq* a_ifr_ifconf = NULL;
205 struct ifreq* p_ifr_current_if;
206 struct ifconf ifc_netconf;
214 /* Start by assuming we have few than 3 interfaces (i_if_number will
215 be incremented by 1 when entering the loop) */
218 /* Retrieve network configuration for that host */
222 a_ifr_ifconf = realloc(a_ifr_ifconf, i_if_number*sizeof(struct ifreq));
223 ifc_netconf.ifc_len = i_if_number*sizeof(struct ifreq);
224 ifc_netconf.ifc_req = a_ifr_ifconf;
226 i_rc = ioctl(i_sockfd, SIOCGIFCONF, (byte_t*)&ifc_netconf);
229 intf_ErrMsg("Cannot read network configuration: %s\n",
234 /* If we detected ifc_len interfaces, this may mean that others have
235 been missed because the a_ifr_ifconf was to little, so increase
236 it's size and retry */
237 while( ifc_netconf.ifc_len >= i_if_number*sizeof(struct ifreq) );
239 /* No see what we detected */
242 /* Init the given net_descr_t struct */
243 p_net_descr->i_if_number = 0;
244 p_net_descr->a_if = NULL;
246 /* Iterate through the entries of the a_ifr_ifconf table */
247 p_ifr_current_if = ifc_netconf.ifc_req;
248 for( i_remaining = ifc_netconf.ifc_len / sizeof (struct ifreq);
249 i_remaining-- > 0; p_ifr_current_if++ )
251 intf_DbgMsg("Found interface %s\n", p_ifr_current_if->ifr_name);
253 /* Don't use an interface devoted to an address family other than IP */
254 if(p_ifr_current_if->ifr_addr.sa_family != AF_INET)
257 /* Read the status of this interface */
258 if( ioctl(i_sockfd, SIOCGIFFLAGS, (byte_t *)p_ifr_current_if) < 0 )
260 intf_ErrMsg("Cannot access interface %s: %s\n",
261 p_ifr_current_if->ifr_name, strerror(errno));
267 /* Skip this interface if it is not up or if this is a loopback one */
268 if( !p_ifr_current_if->ifr_flags & IFF_UP ||
269 p_ifr_current_if->ifr_flags & IFF_LOOPBACK )
272 /* Add an entry to the net_descr struct to store the description of
274 p_net_descr->i_if_number++;
275 p_net_descr->a_if = realloc(p_net_descr->a_if,
276 p_net_descr->i_if_number*sizeof(if_descr_t));
277 /* Read the info ??? */
278 i_rc = ReadIfConf(i_sockfd, &p_net_descr->a_if[p_net_descr->i_if_number-1],
279 p_ifr_current_if->ifr_name);
284 /* Don't need the a_ifr_ifconf anymore */
285 free( a_ifr_ifconf );