1 /*
2  * Copyright (c) 2002-2010 Balabit
3  * Copyright (c) 1998-2010 Balázs Scheidler
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  * As an additional exemption you are allowed to compile & link against the
20  * OpenSSL libraries as published by the OpenSSL project. See the file
21  * COPYING for details.
22  *
23  */
24 
25 #include "gsocket.h"
26 
27 #include <errno.h>
28 #include <arpa/inet.h>
29 
30 /**
31  * g_inet_ntoa:
32  * @buf:        store result in this buffer
33  * @bufsize:    the available space in buf
34  * @a:          address to convert.
35  *
36  * Thread friendly version of inet_ntoa(), converts an IP address to
37  * human readable form. Returns: the address of buf
38  **/
39 gchar *
g_inet_ntoa(char * buf,size_t bufsize,struct in_addr a)40 g_inet_ntoa(char *buf, size_t bufsize, struct in_addr a)
41 {
42   unsigned int ip = ntohl(a.s_addr);
43 
44   g_snprintf(buf, bufsize, "%d.%d.%d.%d",
45              (ip & 0xff000000) >> 24,
46              (ip & 0x00ff0000) >> 16,
47              (ip & 0x0000ff00) >> 8,
48              (ip & 0x000000ff));
49   return buf;
50 }
51 
52 gint
g_inet_aton(const char * buf,struct in_addr * a)53 g_inet_aton(const char *buf, struct in_addr *a)
54 {
55   return inet_aton(buf, a);
56 }
57 
58 /**
59  * g_bind:
60  * @fd:         fd to bind
61  * @addr:       address to bind to
62  *
63  * A thin interface around bind() using a GSockAddr structure for
64  * socket address. It enables the NET_BIND_SERVICE capability (should be
65  * in the permitted set.
66  **/
67 GIOStatus
g_bind(int fd,GSockAddr * addr)68 g_bind(int fd, GSockAddr *addr)
69 {
70   GIOStatus rc;
71 
72   if (addr->sa_funcs && addr->sa_funcs->bind_prepare)
73     addr->sa_funcs->bind_prepare(fd, addr);
74 
75   if (addr->sa_funcs && addr->sa_funcs->bind)
76     rc = addr->sa_funcs->bind(fd, addr);
77   else
78     {
79       if (addr && bind(fd, &addr->sa, addr->salen) < 0)
80         {
81           return G_IO_STATUS_ERROR;
82         }
83       rc = G_IO_STATUS_NORMAL;
84     }
85   return rc;
86 }
87 
88 /**
89  * g_accept:
90  * @fd:         accept connection on this socket
91  * @newfd:      fd of the accepted connection
92  * @addr:       store the address of the client here
93  *
94  * Accept a connection on the given fd, returning the newfd and the
95  * address of the client in a Zorp SockAddr structure.
96  *
97  *  Returns: glib style I/O error
98  **/
99 GIOStatus
g_accept(int fd,int * newfd,GSockAddr ** addr)100 g_accept(int fd, int *newfd, GSockAddr **addr)
101 {
102   char sabuf[1024];
103   socklen_t salen = sizeof(sabuf);
104 
105   do
106     {
107       *newfd = accept(fd, (struct sockaddr *) sabuf, &salen);
108     }
109   while (*newfd == -1 && errno == EINTR);
110   if (*newfd != -1)
111     {
112       *addr = g_sockaddr_new((struct sockaddr *) sabuf, salen);
113     }
114   else if (errno == EAGAIN)
115     {
116       return G_IO_STATUS_AGAIN;
117     }
118   else
119     {
120       return G_IO_STATUS_ERROR;
121     }
122   return G_IO_STATUS_NORMAL;
123 }
124 
125 /**
126  * g_connect:
127  * @fd: socket to connect
128  * @remote:  remote address
129  *
130  * Connect a socket using Zorp style GSockAddr structure.
131  *
132  * Returns: glib style I/O error
133  **/
134 GIOStatus
g_connect(int fd,GSockAddr * remote)135 g_connect(int fd, GSockAddr *remote)
136 {
137   int rc;
138 
139   do
140     {
141       rc = connect(fd, &remote->sa, remote->salen);
142     }
143   while (rc == -1 && errno == EINTR);
144   if (rc == -1)
145     {
146       if (errno == EAGAIN)
147         return G_IO_STATUS_AGAIN;
148       else
149         return G_IO_STATUS_ERROR;
150     }
151   else
152     {
153       return G_IO_STATUS_NORMAL;
154     }
155 }
156 
157 GSockAddr *
g_socket_get_peer_name(gint fd)158 g_socket_get_peer_name(gint fd)
159 {
160   GSockAddr *result = NULL;
161   struct sockaddr_storage addr;
162   socklen_t len =  sizeof(addr);
163 
164   if (getpeername(fd, (struct sockaddr *)&addr, &len) == 0)
165     {
166       result = g_sockaddr_new((struct sockaddr *)&addr, len);
167     }
168   return result;
169 }
170 
171 GSockAddr *
g_socket_get_local_name(gint fd)172 g_socket_get_local_name(gint fd)
173 {
174   GSockAddr *result = NULL;
175   struct sockaddr_storage addr;
176   socklen_t len =  sizeof(addr);
177 
178   if (getsockname(fd, (struct sockaddr *)&addr, &len) == 0)
179     {
180       result = g_sockaddr_new((struct sockaddr *)&addr, len);
181     }
182   return result;
183 }
184