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