]> rtime.felk.cvut.cz Git - orte.git/blob - orte/liborte/sock.c
a5818e58c6f4fbe0b0e55ba704b04aa645261eb7
[orte.git] / orte / liborte / sock.c
1 /*
2  *  $Id: sock.c,v 0.0.0.1               2003/08/21 
3  *
4  *  DEBUG:  section 6                   Socket 
5  *
6  *  -------------------------------------------------------------------  
7  *                                ORTE                                 
8  *                      Open Real-Time Ethernet                       
9  *                                                                    
10  *                      Copyright (C) 2001-2006                       
11  *  Department of Control Engineering FEE CTU Prague, Czech Republic  
12  *                      http://dce.felk.cvut.cz                       
13  *                      http://www.ocera.org                          
14  *                                                                    
15  *  Author:              Petr Smolik    petr.smolik@wo.cz             
16  *  Advisor:             Pavel Pisa                                   
17  *  Project Responsible: Zdenek Hanzalek                              
18  *  --------------------------------------------------------------------
19  *
20  *  This program is free software; you can redistribute it and/or modify
21  *  it under the terms of the GNU General Public License as published by
22  *  the Free Software Foundation; either version 2 of the License, or
23  *  (at your option) any later version.
24  *  
25  *  This program is distributed in the hope that it will be useful,
26  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
27  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  *  GNU General Public License for more details.
29  *  
30  */ 
31
32 #include "orte_all.h"
33
34 /*********************************************************************/
35 int
36 sock_start(void) {
37 #if defined(SOCK_BSD) || defined (SOCK_RTLWIP)
38   return 0;
39 #elif defined (SOCK_WIN)
40   WORD wVersionRequested;
41   WSADATA wsaData;
42   #ifdef SOCK_WIN_PHARLAP
43     wVersionRequested = MAKEWORD(1, 1);
44   #else
45     wVersionRequested = MAKEWORD(2, 0);
46   #endif
47   return WSAStartup(wVersionRequested, &wsaData);
48 #endif
49 }
50
51 /*********************************************************************/
52 inline void
53 sock_finish(void) {
54 #if defined(SOCK_WIN)
55   WSACleanup();
56 #endif
57 }
58
59 /*********************************************************************/
60 int
61 sock_init_udp(sock_t *sock) {
62   sock->fd = socket(AF_INET, SOCK_DGRAM, 0);
63   if (sock->fd < 0) return -1;
64   return 0;
65 }
66
67 /*********************************************************************/
68 inline void
69 sock_cleanup(sock_t *sock) {
70 #if defined(SOCK_BSD)
71   close(sock->fd);
72 #elif defined(SOCK_RTLWIP)
73   close_socket_np(sock->fd);
74 #elif defined(SOCK_WIN)
75   closesocket(sock->fd);
76 #endif
77 }
78
79 /*********************************************************************/
80 inline int
81 sock_setsockopt(sock_t *sock,int level,int optname,const char *optval, int optlen) {
82   if (setsockopt(sock->fd, level, optname,(void *)optval, optlen)) {
83     sock_cleanup(sock);
84     return -1;
85   }
86   return 0;
87 }
88
89 /*********************************************************************/
90 inline int
91 sock_getsockopt(sock_t *sock,int level,int optname,char *optval, int *optlen) {
92   if (getsockopt(sock->fd, level, optname,(void *)optval, (socklen_t *)optlen)) {
93     sock_cleanup(sock);
94     return -1;
95   }
96   return 0;
97 }
98
99 /*********************************************************************/
100 int
101 sock_bind(sock_t *sock,uint16_t port, IPAddress listen) {
102   struct sockaddr_in name;
103   int size;
104
105   name.sin_family = AF_INET;
106   name.sin_port = htons(port);
107   name.sin_addr.s_addr = htonl(listen);
108   if (bind(sock->fd, 
109           #ifndef CONFIG_ORTE_RTL_ONETD 
110             (struct sockaddr *)
111           #endif
112           &name, sizeof(name)) < 0) {
113     sock_cleanup(sock);
114     return -1;
115   }
116   size = sizeof(name);
117   if (getsockname(sock->fd,
118          #ifndef CONFIG_ORTE_RTL_ONETD 
119            (struct sockaddr *)
120          #endif
121          &name, 
122          #ifndef CONFIG_ORTE_RTL_ONETD 
123            (socklen_t *)&size
124          #else
125            size 
126          #endif
127          ) < 0) {
128     sock_cleanup(sock);
129     return -1;
130   }
131   sock->port=ntohs(name.sin_port);
132   return 0;
133 }
134
135 /*********************************************************************/
136 inline int
137 sock_recvfrom(sock_t *sock, void *buf, int max_len,struct sockaddr_in *des,int des_len) {
138   return recvfrom(sock->fd, buf, max_len, 0,
139     #ifndef CONFIG_ORTE_RTL_ONETD 
140       (struct sockaddr*)
141     #endif
142     des,(socklen_t *)&des_len);
143 }
144
145 /*********************************************************************/
146 inline int
147 sock_sendto(sock_t *sock, void *buf, int len,struct sockaddr_in *des,int des_len) {
148   return sendto(sock->fd, buf, len, 0,
149     #ifndef CONFIG_ORTE_RTL_ONETD 
150       (struct sockaddr*)
151     #endif
152     des,des_len);
153 }
154
155 /*********************************************************************/
156 inline int
157 sock_ioctl(sock_t *sock, long cmd, unsigned long *arg) {
158   return ioctl(sock->fd, cmd, arg);
159 }
160
161 /*********************************************************************/
162
163 #if 0
164   #define SOCK_INTF_DEBUG(...) printf( __VA_ARGS__ )
165 #else
166   #define SOCK_INTF_DEBUG(...) do {;} while(0)
167 #endif
168
169 #ifdef HAVE_IFADDRS_H
170 #include <ifaddrs.h>
171 #endif /*HAVE_IFADDRS_H*/
172
173 int
174 sock_get_local_interfaces(sock_t *sock,ORTEIFProp *IFProp,char *IFCount) {
175 #if defined(HAVE_IFADDRS_H)
176   struct ifaddrs *ifa = NULL;
177   struct ifaddrs *ifa_it;
178
179   if (getifaddrs(&ifa)) {
180     SOCK_INTF_DEBUG("getifaddrs() failed\n");
181     return -1;
182   }
183
184   for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) {
185     if (ifa_it->ifa_addr == NULL) {
186       SOCK_INTF_DEBUG("interace %s without address ... skipping\n", ifa_it->ifa_name);
187       continue;
188     }
189     SOCK_INTF_DEBUG("interace %s SA_%d addr 0x%08lx flags 0x%08lx %s %s ... ",
190            ifa_it->ifa_name,
191            ifa_it->ifa_addr->sa_family,
192            (unsigned long)ntohl(((struct sockaddr_in*)(ifa_it->ifa_addr))->sin_addr.s_addr),
193            (unsigned long)ifa_it->ifa_flags,
194            ifa_it->ifa_flags & IFF_UP? "up":"down",
195            ifa_it->ifa_flags & IFF_LOOPBACK? "loopback":"");
196
197     if (!(ifa_it->ifa_flags & IFF_UP) || (ifa_it->ifa_flags & IFF_LOOPBACK) ||
198         (ifa_it->ifa_addr->sa_family != AF_INET)) {
199       SOCK_INTF_DEBUG("skipped\n");
200       continue;
201     }
202     SOCK_INTF_DEBUG("used\n");
203
204     (*IFCount)++;
205     IFProp->ifFlags=ifa_it->ifa_flags;
206     IFProp->ipAddress=ntohl(((struct sockaddr_in*)(ifa_it->ifa_addr))->sin_addr.s_addr);
207     IFProp++;
208     if(*IFCount >= MAX_INTERFACES)
209       break;
210   }
211
212   freeifaddrs(ifa);
213   return 0;
214 #elif defined(SOCK_BSD)
215   #define SOCK_SIOCGIFCONF_SA_LEN_UNCONDITIONAL 1 /* seems to be required for RTEMS*/
216
217   struct ifconf           ifc;
218   char                    *buf;
219   char                    *ptr;
220   int                     res;
221   int                     i;
222
223   ifc.ifc_len = MAX_INTERFACES*sizeof(struct ifreq);
224   if (ifc.ifc_len < 2 * 1024)
225     ifc.ifc_len = 2 * 1024;
226   ifc.ifc_buf = buf = malloc(ifc.ifc_len);
227
228   *IFCount=0;
229   res = ioctl(sock->fd, SIOCGIFCONF, &ifc);
230   if (res < 0) {
231      SOCK_INTF_DEBUG("ioctl(sock->fd, SIOCGIFCONF) failed\n");
232      free(buf);
233      return -1;
234   }
235   SOCK_INTF_DEBUG("ioctl(sock->fd, SIOCGIFCONF) returned %d\n", res);
236   for(i=0; i < ifc.ifc_len; i++)
237      SOCK_INTF_DEBUG(" %02x", buf[i]);
238   SOCK_INTF_DEBUG("\n");
239
240   SOCK_INTF_DEBUG("sizeof(struct sockaddr) %d, sizeof(struct ifreq) %d ifc.ifc_len %d\n",
241          (int)sizeof(struct sockaddr),
242          (int)sizeof(struct ifreq),
243          ifc.ifc_len);
244
245   for (ptr = buf; ptr < (buf + ifc.ifc_len);) {
246     struct ifreq*     ifr = (struct ifreq*) ptr;
247     struct sockaddr   addr;
248     size_t            addr_len = sizeof(addr);
249
250     if(buf + ifc.ifc_len - ptr < sizeof(struct ifreq)) {
251       SOCK_INTF_DEBUG("truncated ifreq entry\n");
252       break;
253     }
254
255     memcpy(&addr, &ifr->ifr_addr, sizeof(addr));
256
257    #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
258     addr_len = addr.sa_len;
259     if ((addr_len > sizeof(addr)) || SOCK_SIOCGIFCONF_SA_LEN_UNCONDITIONAL)
260       ptr = addr_len + (char*)&ifr->ifr_addr;
261     else
262    #endif /*HAVE_STRUCT_SOCKADDR_SA_LEN*/
263       ptr += sizeof(struct ifreq);
264
265     res = ioctl(sock->fd, SIOCGIFFLAGS, ifr);
266
267     SOCK_INTF_DEBUG("interace %s SA_%d addr 0x%08lx len %d flags 0x%08lx %s %s SIOCGIFFLAGS res %d\n",
268            ifr->ifr_name,
269            addr.sa_family,
270            (unsigned long)ntohl(((struct sockaddr_in*)&addr)->sin_addr.s_addr),
271            (int)addr_len,
272            (unsigned long)ifr->ifr_flags,
273            ifr->ifr_flags & IFF_UP? "up":"down",
274            ifr->ifr_flags & IFF_LOOPBACK? "loopback":"",
275            res);
276
277     if ((ifr->ifr_flags & IFF_UP) && !(ifr->ifr_flags & IFF_LOOPBACK) &&
278         (addr.sa_family == AF_INET)) {
279       (*IFCount)++;
280       IFProp->ifFlags=ifr->ifr_flags;
281       IFProp->ipAddress=ntohl(((struct sockaddr_in*)&addr)->sin_addr.s_addr);
282       IFProp++;
283       if(*IFCount >= MAX_INTERFACES)
284         break;
285     }
286   }
287   free(buf);
288   return 0;
289 #elif defined(SOCK_RTLWIP)
290   /* loopback iface is recognized if it has this address */
291   char ip_address [] = "127.0.0.1";
292   struct in_addr loopaddr;
293   int i;
294
295   *IFCount=0;
296   if (inet_aton(ip_address, &loopaddr) != 0) return -1;
297   
298   for (i = 0; i < NIC_TABLE_SIZE; i++) {
299     if (nic_table [i].nic_struct != NULL) {
300       if (nic_table[i].ipad.s_addr != loopaddr.s_addr) {
301         (*IFCount)++;
302         IFProp->ifFlags=0; //RT-Linux doesn't flags
303         IFProp->ipAddress=ntohl(nic_table[i].ipad.s_addr);
304         IFProp++;
305       }
306     }
307   }
308   return 0;
309 #elif defined(SOCK_WIN_PHARLAP)
310   DEVHANDLE hDev;
311   EK_TCPIPCFG *pCfg;
312   union {
313     EK_TCPETHSTATUS eth;
314     EK_TCPSLIPSTATUS slip;
315     EK_TCPPPPSTATUS ppp;
316   } status;
317   *IFCount = 0;
318   hDev = NULL;
319
320   while (hDev = EtsTCPIterateDeviceList(hDev)) {
321     pCfg = EtsTCPGetDeviceCfg(hDev);
322
323     if (pCfg->nwIPAddress == 0x0100007F) // 127.0.0.1 localhost
324       continue;
325
326     status.eth.length = sizeof(EK_TCPETHSTATUS);
327     EtsTCPGetDeviceStatus(hDev, &status);
328     if (status.eth.DevStatus.Flags & ETS_TCP_DEV_ONLINE) {
329       IFProp->ifFlags = IFF_UP;
330       IFProp->ipAddress = ntohl(pCfg->nwIPAddress);
331       (*IFCount)++;
332     }
333   }
334   return 0;
335 #elif defined(SOCK_WIN)
336   INTERFACE_INFO      InterfaceList[MAX_INTERFACES];
337   struct sockaddr_in* pAddress;
338   unsigned long       len,i;
339
340   *IFCount=0;
341   if (WSAIoctl(sock->fd,SIO_GET_INTERFACE_LIST,NULL,0,
342                InterfaceList, sizeof(InterfaceList),
343                &len, NULL, NULL)==SOCKET_ERROR) return -1;
344   len=len/sizeof(INTERFACE_INFO);
345   for(i=0;i<len;i++) {
346     long  nFlags;
347     pAddress = (struct sockaddr_in*)&(InterfaceList[i].iiAddress);
348     nFlags = InterfaceList[i].iiFlags;
349     if ((nFlags & IFF_UP) && !(nFlags & IFF_LOOPBACK)) {
350       IFProp->ifFlags=nFlags;
351       IFProp->ipAddress=ntohl(pAddress->sin_addr.s_addr);
352       IFProp++;
353       (*IFCount)++;
354     }
355   }
356   return 0;
357 #endif
358 }
359
360