diff options
Diffstat (limited to 'src/inet.c')
-rw-r--r-- | src/inet.c | 117 |
1 files changed, 74 insertions, 43 deletions
@@ -165,61 +165,92 @@ static int inet_global_gethostname(lua_State *L) | |||
165 | /*-------------------------------------------------------------------------*\ | 165 | /*-------------------------------------------------------------------------*\ |
166 | * Retrieves socket peer name | 166 | * Retrieves socket peer name |
167 | \*-------------------------------------------------------------------------*/ | 167 | \*-------------------------------------------------------------------------*/ |
168 | int inet_meth_getpeername(lua_State *L, p_socket ps) | 168 | int inet_meth_getpeername(lua_State *L, p_socket ps, int family) |
169 | { | 169 | { |
170 | union { | 170 | switch (family) { |
171 | struct sockaddr_storage sas; | 171 | case PF_INET: { |
172 | struct sockaddr sa; | 172 | struct sockaddr_in peer; |
173 | struct sockaddr_in sa4; | 173 | socklen_t peer_len = sizeof(peer); |
174 | struct sockaddr_in6 sa6; | 174 | char name[INET_ADDRSTRLEN]; |
175 | } peer; | 175 | if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { |
176 | socklen_t peer_len = sizeof(peer); | 176 | lua_pushnil(L); |
177 | 177 | lua_pushstring(L, "getpeername failed"); | |
178 | if (getpeername(*ps, &peer.sa, &peer_len) < 0) { | 178 | return 2; |
179 | lua_pushnil(L); | 179 | } else { |
180 | lua_pushfstring(L, "getpeername failed (%d): %s", errno, | 180 | inet_ntop(family, &peer.sin_addr, name, sizeof(name)); |
181 | strerror(errno)); | 181 | lua_pushstring(L, name); |
182 | } else { | 182 | lua_pushnumber(L, ntohs(peer.sin_port)); |
183 | char ipaddr[INET6_ADDRSTRLEN] = ""; | 183 | lua_pushliteral(L, "inet"); |
184 | unsigned short port = 0; | 184 | return 3; |
185 | 185 | } | |
186 | switch (peer.sa.sa_family) { | 186 | } |
187 | case AF_INET: | 187 | case PF_INET6: { |
188 | inet_ntop(AF_INET, &peer.sa4.sin_addr, ipaddr, sizeof(ipaddr)); | 188 | struct sockaddr_in6 peer; |
189 | port = ntohs(peer.sa4.sin_port); | 189 | socklen_t peer_len = sizeof(peer); |
190 | break; | 190 | char name[INET6_ADDRSTRLEN]; |
191 | case AF_INET6: | 191 | if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { |
192 | inet_ntop(AF_INET6, &peer.sa6.sin6_addr, ipaddr, sizeof(ipaddr)); | 192 | lua_pushnil(L); |
193 | port = ntohs(peer.sa6.sin6_port); | 193 | lua_pushstring(L, "getpeername failed"); |
194 | break; | 194 | return 2; |
195 | } else { | ||
196 | inet_ntop(family, &peer.sin6_addr, name, sizeof(name)); | ||
197 | lua_pushstring(L, name); | ||
198 | lua_pushnumber(L, ntohs(peer.sin6_port)); | ||
199 | lua_pushliteral(L, "inet6"); | ||
200 | return 3; | ||
201 | } | ||
202 | return 2; | ||
203 | } | ||
195 | default: | 204 | default: |
196 | lua_pushnil(L); | 205 | lua_pushnil(L); |
197 | lua_pushfstring(L, "Unknown address family %d", peer.sa.sa_family); | 206 | lua_pushstring(L, "unknown family"); |
198 | return 2; | 207 | return 2; |
199 | break; | ||
200 | } | ||
201 | |||
202 | lua_pushstring(L, ipaddr); | ||
203 | lua_pushnumber(L, port); | ||
204 | } | 208 | } |
205 | return 2; | ||
206 | } | 209 | } |
207 | 210 | ||
208 | /*-------------------------------------------------------------------------*\ | 211 | /*-------------------------------------------------------------------------*\ |
209 | * Retrieves socket local name | 212 | * Retrieves socket local name |
210 | \*-------------------------------------------------------------------------*/ | 213 | \*-------------------------------------------------------------------------*/ |
211 | int inet_meth_getsockname(lua_State *L, p_socket ps) | 214 | int inet_meth_getsockname(lua_State *L, p_socket ps, int family) |
212 | { | 215 | { |
213 | struct sockaddr_in local; | 216 | switch (family) { |
214 | socklen_t local_len = sizeof(local); | 217 | case PF_INET: { |
215 | if (getsockname(*ps, (SA *) &local, &local_len) < 0) { | 218 | struct sockaddr_in local; |
216 | lua_pushnil(L); | 219 | socklen_t local_len = sizeof(local); |
217 | lua_pushstring(L, "getsockname failed"); | 220 | char name[INET_ADDRSTRLEN]; |
218 | } else { | 221 | if (getsockname(*ps, (SA *) &local, &local_len) < 0) { |
219 | lua_pushstring(L, inet_ntoa(local.sin_addr)); | 222 | lua_pushnil(L); |
220 | lua_pushnumber(L, ntohs(local.sin_port)); | 223 | lua_pushstring(L, "getsockname failed"); |
224 | return 2; | ||
225 | } else { | ||
226 | inet_ntop(family, &local.sin_addr, name, sizeof(name)); | ||
227 | lua_pushstring(L, name); | ||
228 | lua_pushnumber(L, ntohs(local.sin_port)); | ||
229 | lua_pushliteral(L, "inet"); | ||
230 | return 3; | ||
231 | } | ||
232 | } | ||
233 | case PF_INET6: { | ||
234 | struct sockaddr_in6 local; | ||
235 | socklen_t local_len = sizeof(local); | ||
236 | char name[INET6_ADDRSTRLEN]; | ||
237 | if (getsockname(*ps, (SA *) &local, &local_len) < 0) { | ||
238 | lua_pushnil(L); | ||
239 | lua_pushstring(L, "getsockname failed"); | ||
240 | return 2; | ||
241 | } else { | ||
242 | inet_ntop(family, &local.sin6_addr, name, sizeof(name)); | ||
243 | lua_pushstring(L, name); | ||
244 | lua_pushnumber(L, ntohs(local.sin6_port)); | ||
245 | lua_pushliteral(L, "inet6"); | ||
246 | return 3; | ||
247 | } | ||
248 | } | ||
249 | default: | ||
250 | lua_pushnil(L); | ||
251 | lua_pushstring(L, "unknown family"); | ||
252 | return 2; | ||
221 | } | 253 | } |
222 | return 2; | ||
223 | } | 254 | } |
224 | 255 | ||
225 | /*=========================================================================*\ | 256 | /*=========================================================================*\ |