xref: /libuv/src/unix/getnameinfo.c (revision 90891b42)
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 */
21 
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 
27 #include "uv.h"
28 #include "internal.h"
29 
30 
uv__getnameinfo_work(struct uv__work * w)31 static void uv__getnameinfo_work(struct uv__work* w) {
32   uv_getnameinfo_t* req;
33   int err;
34   socklen_t salen;
35 
36   req = container_of(w, uv_getnameinfo_t, work_req);
37 
38   if (req->storage.ss_family == AF_INET)
39     salen = sizeof(struct sockaddr_in);
40   else if (req->storage.ss_family == AF_INET6)
41     salen = sizeof(struct sockaddr_in6);
42   else
43     abort();
44 
45   err = getnameinfo((struct sockaddr*) &req->storage,
46                     salen,
47                     req->host,
48                     sizeof(req->host),
49                     req->service,
50                     sizeof(req->service),
51                     req->flags);
52   req->retcode = uv__getaddrinfo_translate_error(err);
53 }
54 
uv__getnameinfo_done(struct uv__work * w,int status)55 static void uv__getnameinfo_done(struct uv__work* w, int status) {
56   uv_getnameinfo_t* req;
57   char* host;
58   char* service;
59 
60   req = container_of(w, uv_getnameinfo_t, work_req);
61   uv__req_unregister(req->loop, req);
62   host = service = NULL;
63 
64   if (status == UV_ECANCELED) {
65     assert(req->retcode == 0);
66     req->retcode = UV_EAI_CANCELED;
67   } else if (req->retcode == 0) {
68     host = req->host;
69     service = req->service;
70   }
71 
72   if (req->getnameinfo_cb)
73     req->getnameinfo_cb(req, req->retcode, host, service);
74 }
75 
76 /*
77 * Entry point for getnameinfo
78 * return 0 if a callback will be made
79 * return error code if validation fails
80 */
uv_getnameinfo(uv_loop_t * loop,uv_getnameinfo_t * req,uv_getnameinfo_cb getnameinfo_cb,const struct sockaddr * addr,int flags)81 int uv_getnameinfo(uv_loop_t* loop,
82                    uv_getnameinfo_t* req,
83                    uv_getnameinfo_cb getnameinfo_cb,
84                    const struct sockaddr* addr,
85                    int flags) {
86   if (req == NULL || addr == NULL)
87     return UV_EINVAL;
88 
89   if (addr->sa_family == AF_INET) {
90     memcpy(&req->storage,
91            addr,
92            sizeof(struct sockaddr_in));
93   } else if (addr->sa_family == AF_INET6) {
94     memcpy(&req->storage,
95            addr,
96            sizeof(struct sockaddr_in6));
97   } else {
98     return UV_EINVAL;
99   }
100 
101   uv__req_init(loop, (uv_req_t*)req, UV_GETNAMEINFO);
102 
103   req->getnameinfo_cb = getnameinfo_cb;
104   req->flags = flags;
105   req->type = UV_GETNAMEINFO;
106   req->loop = loop;
107   req->retcode = 0;
108 
109   if (getnameinfo_cb) {
110     uv__work_submit(loop,
111                     &req->work_req,
112                     UV__WORK_SLOW_IO,
113                     uv__getnameinfo_work,
114                     uv__getnameinfo_done);
115     return 0;
116   } else {
117     uv__getnameinfo_work(&req->work_req);
118     uv__getnameinfo_done(&req->work_req, 0);
119     return req->retcode;
120   }
121 }
122