1 /*
2    Copyright (C) 2013 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU Lesser General Public License as published by
6    the Free Software Foundation; either version 2.1 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public License
15    along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <sys/socket.h>
24 #include <netdb.h>
25 #include "aros_compat.h"
26 #include <errno.h>
27 #include <bsdsocket/socketbasetags.h>
28 
29 #undef poll
30 
aros_getnameinfo(const struct sockaddr * sa,socklen_t salen,char * host,size_t hostlen,char * serv,size_t servlen,int flags)31 int aros_getnameinfo(const struct sockaddr *sa, socklen_t salen,
32 char *host, size_t hostlen,
33 char *serv, size_t servlen, int flags)
34 {
35   struct sockaddr_in *sin = (struct sockaddr_in *)sa;
36 
37   if (host) {
38     snprintf(host, hostlen, Inet_NtoA(sin->sin_addr.s_addr));
39   }
40 
41   return 0;
42 }
43 
aros_getaddrinfo(const char * node,const char * service,const struct addrinfo * hints,struct addrinfo ** res)44 int aros_getaddrinfo(const char *node, const char*service,
45 const struct addrinfo *hints,
46 struct addrinfo **res)
47 {
48   struct sockaddr_in *sin;
49 
50   sin = malloc(sizeof(struct sockaddr_in));
51   sin->sin_len = sizeof(struct sockaddr_in);
52   sin->sin_family=AF_INET;
53 
54   /* Some error checking would be nice */
55   sin->sin_addr.s_addr = inet_addr(node);
56 
57   sin->sin_port=0;
58   if (service) {
59     sin->sin_port=htons(atoi(service));
60   }
61 
62   *res = malloc(sizeof(struct addrinfo));
63 
64   (*res)->ai_family = AF_INET;
65   (*res)->ai_addrlen = sizeof(struct sockaddr_in);
66   (*res)->ai_addr = (struct sockaddr *)sin;
67 
68   return 0;
69 }
70 
aros_freeaddrinfo(struct addrinfo * res)71 void aros_freeaddrinfo(struct addrinfo *res)
72 {
73   free(res->ai_addr);
74   free(res);
75 }
76 
aros_inet_pton(int af,char * src,void * dst)77 int aros_inet_pton(int af, char *src, void *dst)
78 {
79   struct sockaddr_in sin;
80 
81   sin.sin_addr.s_addr = inet_addr(src);
82   memcpy(dst, &sin.sin_addr.s_addr, sizeof(sin.sin_addr.s_addr));
83   return 1;
84 }
85 
86 
87 /* unix device numbers dont really make much sense on aros ... */
major(int i)88 int major(int i)
89 {
90   return 1;
91 }
minor(int i)92 int minor(int i)
93 {
94   return 2;
95 }
96 
97 struct Library * SocketBase = NULL;
98 
99 extern int errno;
100 int h_errno = 0;
101 
102 
aros_init_socket(void)103 void aros_init_socket(void)
104 {
105   if (!(SocketBase = OpenLibrary("bsdsocket.library", 4))) {
106     printf("NoTCP/IP Stack available");
107     exit(10);
108   }
109   if (SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))),
110                      (IPTR)&errno,
111                      SBTM_SETVAL(SBTC_HERRNOLONGPTR),
112                      (IPTR)&h_errno, TAG_DONE)) {
113     printf("Failed to set ERRNO");
114     exit(10);
115   }
116 }
117 
aros_poll(struct pollfd * fds,unsigned int nfds,int timo)118 int aros_poll(struct pollfd *fds, unsigned int nfds, int timo)
119 {
120   struct timeval timeout, *toptr;
121   fd_set ifds, ofds, efds, *ip, *op;
122   unsigned int i, maxfd = 0;
123   int  rc;
124 
125   // Set up the file-descriptor sets in ifds, ofds and efds.
126   FD_ZERO(&ifds);
127   FD_ZERO(&ofds);
128   FD_ZERO(&efds);
129   for (i = 0, op = ip = 0; i < nfds; ++i)
130   {
131     fds[i].revents = 0;
132     if(fds[i].events & (POLLIN|POLLPRI))
133     {
134       ip = &ifds;
135       FD_SET(fds[i].fd, ip);
136     }
137     if(fds[i].events & POLLOUT)
138     {
139       op = &ofds;
140       FD_SET(fds[i].fd, op);
141     }
142     FD_SET(fds[i].fd, &efds);
143     if (fds[i].fd > maxfd) {
144       maxfd = fds[i].fd;
145     }
146   }
147 
148   // Set up the timeval structure for the timeout parameter
149   if(timo < 0)
150   {
151     toptr = 0;
152   }
153   else
154   {
155     toptr = &timeout;
156     timeout.tv_sec = timo / 1000;
157     timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000;
158   }
159 
160   rc = WaitSelect(maxfd + 1, ip, op, &efds, toptr, NULL);
161 
162   if(rc <= 0)
163     return rc;
164 
165   if(rc > 0)
166   {
167     for (i = 0; i < nfds; ++i)
168     {
169       int fd = fds[i].fd;
170       if(fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(fd, &ifds))
171         fds[i].revents |= POLLIN;
172       if(fds[i].events & POLLOUT && FD_ISSET(fd, &ofds))
173         fds[i].revents |= POLLOUT;
174       if(FD_ISSET(fd, &efds)) // Some error was detected ... should be some way to know.
175         fds[i].revents |= POLLHUP;
176     }
177   }
178   return rc;
179 }
180 
181