]> rtime.felk.cvut.cz Git - orte.git/blob - orte/liborte/sock.c
Reformat the sources with orte/uncrustify script
[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@smoliku.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 {
38 #if defined(SOCK_BSD) || defined (SOCK_RTLWIP)
39   return 0;
40 #elif defined (SOCK_WIN)
41   WORD wVersionRequested;
42   WSADATA wsaData;
43   #ifdef SOCK_WIN_PHARLAP
44   wVersionRequested = MAKEWORD(1, 1);
45   #else
46   wVersionRequested = MAKEWORD(2, 0);
47   #endif
48   return WSAStartup(wVersionRequested, &wsaData);
49 #endif
50 }
51
52 /*********************************************************************/
53 inline void
54 sock_finish(void)
55 {
56 #if defined(SOCK_WIN)
57   WSACleanup();
58 #endif
59 }
60
61 /*********************************************************************/
62 int
63 sock_init_udp(sock_t *sock)
64 {
65   sock->fd = socket(AF_INET, SOCK_DGRAM, 0);
66   if (sock->fd < 0)
67     return -1;
68   return 0;
69 }
70
71 /*********************************************************************/
72 inline void
73 sock_cleanup(sock_t *sock)
74 {
75 #if defined(SOCK_BSD)
76   close(sock->fd);
77 #elif defined(SOCK_RTLWIP)
78   close_socket_np(sock->fd);
79 #elif defined(SOCK_WIN)
80   closesocket(sock->fd);
81 #endif
82 }
83
84 /*********************************************************************/
85 inline int
86 sock_setsockopt(sock_t *sock, int level, int optname, const char *optval, int optlen)
87 {
88   if (setsockopt(sock->fd, level, optname, (void *)optval, optlen)) {
89     sock_cleanup(sock);
90     return -1;
91   }
92   return 0;
93 }
94
95 /*********************************************************************/
96 inline int
97 sock_getsockopt(sock_t *sock, int level, int optname, char *optval, int *optlen)
98 {
99   if (getsockopt(sock->fd, level, optname, (void *)optval, (socklen_t *)optlen)) {
100     sock_cleanup(sock);
101     return -1;
102   }
103   return 0;
104 }
105
106 /*********************************************************************/
107 int
108 sock_bind(sock_t *sock, uint16_t port, IPAddress listen)
109 {
110   struct sockaddr_in name;
111   int size;
112
113   name.sin_family = AF_INET;
114   name.sin_port = htons(port);
115   name.sin_addr.s_addr = htonl(listen);
116   if (bind(sock->fd,
117           #ifndef CONFIG_ORTE_RTL_ONETD
118            (struct sockaddr *)
119           #endif
120            &name, sizeof(name)) < 0) {
121     sock_cleanup(sock);
122     return -1;
123   }
124   size = sizeof(name);
125   if (getsockname(sock->fd,
126          #ifndef CONFIG_ORTE_RTL_ONETD
127                   (struct sockaddr *)
128          #endif
129                   &name,
130          #ifndef CONFIG_ORTE_RTL_ONETD
131                   (socklen_t *)&size
132          #else
133                   size
134          #endif
135                   ) < 0) {
136     sock_cleanup(sock);
137     return -1;
138   }
139   sock->port = ntohs(name.sin_port);
140   return 0;
141 }
142
143 /*********************************************************************/
144 inline int
145 sock_recvfrom(sock_t *sock, void *buf, int max_len, struct sockaddr_in *des, int des_len)
146 {
147   return recvfrom(sock->fd, buf, max_len, 0,
148     #ifndef CONFIG_ORTE_RTL_ONETD
149                   (struct sockaddr *)
150     #endif
151                   des, (socklen_t *)&des_len);
152 }
153
154 /*********************************************************************/
155 inline int
156 sock_sendto(sock_t *sock, void *buf, int len, struct sockaddr_in *des, int des_len)
157 {
158   return sendto(sock->fd, buf, len, 0,
159     #ifndef CONFIG_ORTE_RTL_ONETD
160                 (struct sockaddr *)
161     #endif
162                 des, des_len);
163 }
164
165 /*********************************************************************/
166 inline int
167 sock_ioctl(sock_t *sock, long cmd, unsigned long *arg)
168 {
169   return ioctl(sock->fd, cmd, arg);
170 }
171
172 /*********************************************************************/
173
174 #if 0
175   #define SOCK_INTF_DEBUG(...) printf(__VA_ARGS__)
176 #else
177   #define SOCK_INTF_DEBUG(...) do {; } while (0)
178 #endif
179
180 #ifdef HAVE_IFADDRS_H
181 #include <ifaddrs.h>
182 #endif /*HAVE_IFADDRS_H*/
183
184 int
185 sock_get_local_interfaces(sock_t *sock, ORTEIFProp *IFProp, char *IFCount)
186 {
187 #if defined(HAVE_IFADDRS_H)
188   struct ifaddrs *ifa = NULL;
189   struct ifaddrs *ifa_it;
190
191   if (getifaddrs(&ifa)) {
192     SOCK_INTF_DEBUG("getifaddrs() failed\n");
193     return -1;
194   }
195
196   for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) {
197     if (ifa_it->ifa_addr == NULL) {
198       SOCK_INTF_DEBUG("interace %s without address ... skipping\n", ifa_it->ifa_name);
199       continue;
200     }
201     SOCK_INTF_DEBUG("interace %s SA_%d addr 0x%08lx flags 0x%08lx %s %s ... ",
202                     ifa_it->ifa_name,
203                     ifa_it->ifa_addr->sa_family,
204                     (unsigned long)ntohl(((struct sockaddr_in *)(ifa_it->ifa_addr))->sin_addr.s_addr),
205                     (unsigned long)ifa_it->ifa_flags,
206                     ifa_it->ifa_flags & IFF_UP ? "up" : "down",
207                     ifa_it->ifa_flags & IFF_LOOPBACK ? "loopback" : "");
208
209     if (!(ifa_it->ifa_flags & IFF_UP) || (ifa_it->ifa_flags & IFF_LOOPBACK) ||
210         (ifa_it->ifa_addr->sa_family != AF_INET)) {
211       SOCK_INTF_DEBUG("skipped\n");
212       continue;
213     }
214     SOCK_INTF_DEBUG("used\n");
215
216     (*IFCount)++;
217     IFProp->ifFlags = ifa_it->ifa_flags;
218     IFProp->ipAddress = ntohl(((struct sockaddr_in *)(ifa_it->ifa_addr))->sin_addr.s_addr);
219     IFProp++;
220     if (*IFCount >= MAX_INTERFACES)
221       break;
222   }
223
224   freeifaddrs(ifa);
225   return 0;
226 #elif defined(SOCK_BSD)
227   #define SOCK_SIOCGIFCONF_SA_LEN_UNCONDITIONAL 1 /* seems to be required for RTEMS*/
228
229   struct ifconf           ifc;
230   char                    *buf;
231   char                    *ptr;
232   int                     res;
233   int                     i;
234
235   ifc.ifc_len = MAX_INTERFACES*sizeof(struct ifreq);
236   if (ifc.ifc_len < 2 * 1024)
237     ifc.ifc_len = 2 * 1024;
238   ifc.ifc_buf = buf = malloc(ifc.ifc_len);
239
240   *IFCount = 0;
241   res = ioctl(sock->fd, SIOCGIFCONF, &ifc);
242   if (res < 0) {
243     SOCK_INTF_DEBUG("ioctl(sock->fd, SIOCGIFCONF) failed\n");
244     free(buf);
245     return -1;
246   }
247   SOCK_INTF_DEBUG("ioctl(sock->fd, SIOCGIFCONF) returned %d\n", res);
248   for (i = 0; i < ifc.ifc_len; i++)
249     SOCK_INTF_DEBUG(" %02x", buf[i]);
250   SOCK_INTF_DEBUG("\n");
251
252   SOCK_INTF_DEBUG("sizeof(struct sockaddr) %d, sizeof(struct ifreq) %d ifc.ifc_len %d\n",
253                   (int)sizeof(struct sockaddr),
254                   (int)sizeof(struct ifreq),
255                   ifc.ifc_len);
256
257   for (ptr = buf; ptr < (buf + ifc.ifc_len); ) {
258     struct ifreq *ifr = (struct ifreq *)ptr;
259     struct sockaddr   addr;
260     size_t            addr_len = sizeof(addr);
261
262     if (buf + ifc.ifc_len - ptr < sizeof(struct ifreq)) {
263       SOCK_INTF_DEBUG("truncated ifreq entry\n");
264       break;
265     }
266
267     memcpy(&addr, &ifr->ifr_addr, sizeof(addr));
268
269    #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
270     addr_len = addr.sa_len;
271     if ((addr_len > sizeof(addr)) || SOCK_SIOCGIFCONF_SA_LEN_UNCONDITIONAL)
272       ptr = addr_len + (char *)&ifr->ifr_addr;
273     else
274    #endif /*HAVE_STRUCT_SOCKADDR_SA_LEN*/
275     ptr += sizeof(struct ifreq);
276
277     res = ioctl(sock->fd, SIOCGIFFLAGS, ifr);
278
279     SOCK_INTF_DEBUG("interace %s SA_%d addr 0x%08lx len %d flags 0x%08lx %s %s SIOCGIFFLAGS res %d\n",
280                     ifr->ifr_name,
281                     addr.sa_family,
282                     (unsigned long)ntohl(((struct sockaddr_in *)&addr)->sin_addr.s_addr),
283                     (int)addr_len,
284                     (unsigned long)ifr->ifr_flags,
285                     ifr->ifr_flags & IFF_UP ? "up" : "down",
286                     ifr->ifr_flags & IFF_LOOPBACK ? "loopback" : "",
287                     res);
288
289     if ((ifr->ifr_flags & IFF_UP) && !(ifr->ifr_flags & IFF_LOOPBACK) &&
290         (addr.sa_family == AF_INET)) {
291       (*IFCount)++;
292       IFProp->ifFlags = ifr->ifr_flags;
293       IFProp->ipAddress = ntohl(((struct sockaddr_in *)&addr)->sin_addr.s_addr);
294       IFProp++;
295       if (*IFCount >= MAX_INTERFACES)
296         break;
297     }
298   }
299   free(buf);
300   return 0;
301 #elif defined(SOCK_RTLWIP)
302   /* loopback iface is recognized if it has this address */
303   char ip_address[] = "127.0.0.1";
304   struct in_addr loopaddr;
305   int i;
306
307   *IFCount = 0;
308   if (inet_aton(ip_address, &loopaddr) != 0)
309     return -1;
310
311   for (i = 0; i < NIC_TABLE_SIZE; i++) {
312     if (nic_table[i].nic_struct != NULL) {
313       if (nic_table[i].ipad.s_addr != loopaddr.s_addr) {
314         (*IFCount)++;
315         IFProp->ifFlags = 0; //RT-Linux doesn't flags
316         IFProp->ipAddress = ntohl(nic_table[i].ipad.s_addr);
317         IFProp++;
318       }
319     }
320   }
321   return 0;
322 #elif defined(SOCK_WIN_PHARLAP)
323   DEVHANDLE hDev;
324   EK_TCPIPCFG *pCfg;
325   union {
326     EK_TCPETHSTATUS eth;
327     EK_TCPSLIPSTATUS slip;
328     EK_TCPPPPSTATUS ppp;
329   } status;
330   *IFCount = 0;
331   hDev = NULL;
332
333   while (hDev = EtsTCPIterateDeviceList(hDev)) {
334     pCfg = EtsTCPGetDeviceCfg(hDev);
335
336     if (pCfg->nwIPAddress == 0x0100007F) // 127.0.0.1 localhost
337       continue;
338
339     status.eth.length = sizeof(EK_TCPETHSTATUS);
340     EtsTCPGetDeviceStatus(hDev, &status);
341     if (status.eth.DevStatus.Flags & ETS_TCP_DEV_ONLINE) {
342       IFProp->ifFlags = IFF_UP;
343       IFProp->ipAddress = ntohl(pCfg->nwIPAddress);
344       (*IFCount)++;
345     }
346   }
347   return 0;
348 #elif defined(SOCK_WIN)
349   INTERFACE_INFO      InterfaceList[MAX_INTERFACES];
350   struct sockaddr_in *pAddress;
351   unsigned long       len, i;
352
353   *IFCount = 0;
354   if (WSAIoctl(sock->fd, SIO_GET_INTERFACE_LIST, NULL, 0,
355                InterfaceList, sizeof(InterfaceList),
356                &len, NULL, NULL) == SOCKET_ERROR)
357     return -1;
358   len = len/sizeof(INTERFACE_INFO);
359   for (i = 0; i < len; i++) {
360     long  nFlags;
361     pAddress = (struct sockaddr_in *)&(InterfaceList[i].iiAddress);
362     nFlags = InterfaceList[i].iiFlags;
363     if ((nFlags & IFF_UP) && !(nFlags & IFF_LOOPBACK)) {
364       IFProp->ifFlags = nFlags;
365       IFProp->ipAddress = ntohl(pAddress->sin_addr.s_addr);
366       IFProp++;
367       (*IFCount)++;
368     }
369   }
370   return 0;
371 #endif /* if defined(HAVE_IFADDRS_H) */
372 }