| 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 |