OLD | NEW |
1 #include <sys/socket.h> | 1 #include <sys/socket.h> |
2 #include <byteswap.h> | 2 #include <byteswap.h> |
3 #include <unistd.h> | 3 #include <unistd.h> |
4 #include <stdio.h> | 4 #include <stdio.h> |
5 #include <string.h> | 5 #include <string.h> |
6 #include <errno.h> | 6 #include <errno.h> |
7 #include <limits.h> | 7 #include <limits.h> |
8 #include "nscd.h" | 8 #include "nscd.h" |
9 | 9 |
10 static const struct { | 10 static const struct { |
11 » short sun_family; | 11 short sun_family; |
12 » char sun_path[21]; | 12 char sun_path[21]; |
13 } addr = { | 13 } addr = {AF_UNIX, "/var/run/nscd/socket"}; |
14 » AF_UNIX, | |
15 » "/var/run/nscd/socket" | |
16 }; | |
17 | 14 |
18 FILE *__nscd_query(int32_t req, const char *key, int32_t *buf, size_t len, int *
swap) | 15 FILE* __nscd_query(int32_t req, |
19 { | 16 const char* key, |
20 » size_t i; | 17 int32_t* buf, |
21 » int fd; | 18 size_t len, |
22 » FILE *f = 0; | 19 int* swap) { |
23 » int32_t req_buf[REQ_LEN] = { | 20 size_t i; |
24 » » NSCDVERSION, | 21 int fd; |
25 » » req, | 22 FILE* f = 0; |
26 » » strnlen(key,LOGIN_NAME_MAX)+1 | 23 int32_t req_buf[REQ_LEN] = {NSCDVERSION, req, |
27 » }; | 24 strnlen(key, LOGIN_NAME_MAX) + 1}; |
28 » struct msghdr msg = { | 25 struct msghdr msg = { |
29 » » .msg_iov = (struct iovec[]){ | 26 .msg_iov = (struct iovec[]){{&req_buf, sizeof(req_buf)}, |
30 » » » {&req_buf, sizeof(req_buf)}, | 27 {(char*)key, strlen(key) + 1}}, |
31 » » » {(char*)key, strlen(key)+1} | 28 .msg_iovlen = 2}; |
32 » » }, | 29 int errno_save = errno; |
33 » » .msg_iovlen = 2 | |
34 » }; | |
35 » int errno_save = errno; | |
36 | 30 |
37 » *swap = 0; | 31 *swap = 0; |
38 retry: | 32 retry: |
39 » memset(buf, 0, len); | 33 memset(buf, 0, len); |
40 » buf[0] = NSCDVERSION; | 34 buf[0] = NSCDVERSION; |
41 | 35 |
42 » fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); | 36 fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); |
43 » if (fd < 0) return NULL; | 37 if (fd < 0) |
| 38 return NULL; |
44 | 39 |
45 » if(!(f = fdopen(fd, "r"))) { | 40 if (!(f = fdopen(fd, "r"))) { |
46 » » close(fd); | 41 close(fd); |
47 » » return 0; | 42 return 0; |
48 » } | 43 } |
49 | 44 |
50 » if (req_buf[2] > LOGIN_NAME_MAX) | 45 if (req_buf[2] > LOGIN_NAME_MAX) |
51 » » return f; | 46 return f; |
52 | 47 |
53 » if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { | 48 if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { |
54 » » /* If there isn't a running nscd we simulate a "not found" | 49 /* If there isn't a running nscd we simulate a "not found" |
55 » » * result and the caller is responsible for calling | 50 * result and the caller is responsible for calling |
56 » » * fclose on the (unconnected) socket. The value of | 51 * fclose on the (unconnected) socket. The value of |
57 » » * errno must be left unchanged in this case. */ | 52 * errno must be left unchanged in this case. */ |
58 » » if (errno == EACCES || errno == ECONNREFUSED || errno == ENOENT)
{ | 53 if (errno == EACCES || errno == ECONNREFUSED || errno == ENOENT) { |
59 » » » errno = errno_save; | 54 errno = errno_save; |
60 » » » return f; | 55 return f; |
61 » » } | 56 } |
62 » » goto error; | 57 goto error; |
63 » } | 58 } |
64 | 59 |
65 » if (sendmsg(fd, &msg, MSG_NOSIGNAL) < 0) | 60 if (sendmsg(fd, &msg, MSG_NOSIGNAL) < 0) |
66 » » goto error; | 61 goto error; |
67 | 62 |
68 » if (!fread(buf, len, 1, f)) { | 63 if (!fread(buf, len, 1, f)) { |
69 » » /* If the VERSION entry mismatches nscd will disconnect. The | 64 /* If the VERSION entry mismatches nscd will disconnect. The |
70 » » * most likely cause is that the endianness mismatched. So, we | 65 * most likely cause is that the endianness mismatched. So, we |
71 » » * byteswap and try once more. (if we already swapped, just | 66 * byteswap and try once more. (if we already swapped, just |
72 » » * fail out) | 67 * fail out) |
73 » » */ | 68 */ |
74 » » if (ferror(f)) goto error; | 69 if (ferror(f)) |
75 » » if (!*swap) { | 70 goto error; |
76 » » » fclose(f); | 71 if (!*swap) { |
77 » » » for (i = 0; i < sizeof(req_buf)/sizeof(req_buf[0]); i++)
{ | 72 fclose(f); |
78 » » » » req_buf[i] = bswap_32(req_buf[i]); | 73 for (i = 0; i < sizeof(req_buf) / sizeof(req_buf[0]); i++) { |
79 » » » } | 74 req_buf[i] = bswap_32(req_buf[i]); |
80 » » » *swap = 1; | 75 } |
81 » » » goto retry; | 76 *swap = 1; |
82 » » } else { | 77 goto retry; |
83 » » » errno = EIO; | 78 } else { |
84 » » » goto error; | 79 errno = EIO; |
85 » » } | 80 goto error; |
86 » } | 81 } |
| 82 } |
87 | 83 |
88 » if (*swap) { | 84 if (*swap) { |
89 » » for (i = 0; i < len/sizeof(buf[0]); i++) { | 85 for (i = 0; i < len / sizeof(buf[0]); i++) { |
90 » » » buf[i] = bswap_32(buf[i]); | 86 buf[i] = bswap_32(buf[i]); |
91 » » } | 87 } |
92 » } | 88 } |
93 | 89 |
94 » /* The first entry in every nscd response is the version number. This | 90 /* The first entry in every nscd response is the version number. This |
95 » * really shouldn't happen, and is evidence of some form of malformed | 91 * really shouldn't happen, and is evidence of some form of malformed |
96 » * response. | 92 * response. |
97 » */ | 93 */ |
98 » if(buf[0] != NSCDVERSION) { | 94 if (buf[0] != NSCDVERSION) { |
99 » » errno = EIO; | 95 errno = EIO; |
100 » » goto error; | 96 goto error; |
101 » } | 97 } |
102 | 98 |
103 » return f; | 99 return f; |
104 error: | 100 error: |
105 » fclose(f); | 101 fclose(f); |
106 » return 0; | 102 return 0; |
107 } | 103 } |
OLD | NEW |