bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/*
a81d5c3f5a4ad5d100b258d10d4c75f4a02ab1f6Stephan Bosch Authors:
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi Sumit Bose <sbose@redhat.com>
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi Copyright (C) 2017 Red Hat
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi SSSD's enhanced NSS API
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi This program is free software; you can redistribute it and/or modify
3f6149c3fd34f54ab33415bf7141e33fc9822e23Aki Tuomi it under the terms of the GNU General Public License as published by
3f6149c3fd34f54ab33415bf7141e33fc9822e23Aki Tuomi the Free Software Foundation; either version 3 of the License, or
3f6149c3fd34f54ab33415bf7141e33fc9822e23Aki Tuomi (at your option) any later version.
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
a62dad9ec88bb112079dd95be456d258c6c86369Timo Sirainen This program is distributed in the hope that it will be useful,
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi but WITHOUT ANY WARRANTY; without even the implied warranty of
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
a7ad754fca008f60d348f4296e5831e31ce8cc71Timo Sirainen GNU General Public License for more details.
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
f86bd28cf4dadc4de794eebf34b28aefc8a3fc3aAki Tuomi You should have received a copy of the GNU General Public License
f86bd28cf4dadc4de794eebf34b28aefc8a3fc3aAki Tuomi along with this program. If not, see <http://www.gnu.org/licenses/>.
f86bd28cf4dadc4de794eebf34b28aefc8a3fc3aAki Tuomi*/
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
a62dad9ec88bb112079dd95be456d258c6c86369Timo Sirainen#include <time.h>
a62dad9ec88bb112079dd95be456d258c6c86369Timo Sirainen#include <errno.h>
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi#include "sss_cli.h"
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi#include "common_private.h"
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomiextern struct sss_mutex sss_nss_mtx;
a7ad754fca008f60d348f4296e5831e31ce8cc71Timo Sirainen
3f6149c3fd34f54ab33415bf7141e33fc9822e23Aki Tuomi#define SEC_FROM_MSEC(ms) ((ms) / 1000)
a7ad754fca008f60d348f4296e5831e31ce8cc71Timo Sirainen#define NSEC_FROM_MSEC(ms) (((ms) % 1000) * 1000 * 1000)
d86910a95633a25cf7577ea2dff0472b5a489bc3Teemu Huovila
a7ad754fca008f60d348f4296e5831e31ce8cc71Timo Sirainen/* adopted from timersub() defined in /usr/include/sys/time.h */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi#define TIMESPECSUB(a, b, result) \
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi do { \
a7ad754fca008f60d348f4296e5831e31ce8cc71Timo Sirainen (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi (result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec; \
a62dad9ec88bb112079dd95be456d258c6c86369Timo Sirainen if ((result)->tv_nsec < 0) { \
a62dad9ec88bb112079dd95be456d258c6c86369Timo Sirainen --(result)->tv_sec; \
a62dad9ec88bb112079dd95be456d258c6c86369Timo Sirainen (result)->tv_nsec += 1000000000; \
a62dad9ec88bb112079dd95be456d258c6c86369Timo Sirainen } \
a62dad9ec88bb112079dd95be456d258c6c86369Timo Sirainen } while (0)
a62dad9ec88bb112079dd95be456d258c6c86369Timo Sirainen
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi#define TIMESPEC_TO_MS(ts) ( ((ts)->tv_sec * 1000) \
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi + ((ts)->tv_nsec) / (1000 * 1000) )
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
f86bd28cf4dadc4de794eebf34b28aefc8a3fc3aAki Tuomistatic int sss_mt_timedlock(struct sss_mutex *m, struct timespec *endtime)
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi{
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi int ret;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi ret = pthread_mutex_timedlock(&m->mtx, endtime);
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi if (ret != 0) {
a7ad754fca008f60d348f4296e5831e31ce8cc71Timo Sirainen return ret;
a62dad9ec88bb112079dd95be456d258c6c86369Timo Sirainen }
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &m->old_cancel_state);
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi return 0;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi}
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomiint sss_nss_timedlock(unsigned int timeout_ms, int *time_left_ms)
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi{
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi int ret;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi int left;
3c503fa10d3d0fe2abb1767caf217b0a770dc6aaAki Tuomi struct timespec starttime;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi struct timespec endtime;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi struct timespec diff;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* make sure there is no overrun when calculating the time left */
3c503fa10d3d0fe2abb1767caf217b0a770dc6aaAki Tuomi if (timeout_ms > INT_MAX) {
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi timeout_ms = INT_MAX;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi }
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi ret = clock_gettime(CLOCK_REALTIME, &starttime);
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi if (ret != 0) {
3c503fa10d3d0fe2abb1767caf217b0a770dc6aaAki Tuomi return ret;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi }
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi endtime.tv_sec = starttime.tv_sec + SEC_FROM_MSEC(timeout_ms);
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi endtime.tv_nsec = starttime.tv_nsec + NSEC_FROM_MSEC(timeout_ms);
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
3c503fa10d3d0fe2abb1767caf217b0a770dc6aaAki Tuomi ret = sss_mt_timedlock(&sss_nss_mtx, &endtime);
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi if (ret == 0) {
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi ret = clock_gettime(CLOCK_REALTIME, &endtime);
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi if (ret != 0) {
3c503fa10d3d0fe2abb1767caf217b0a770dc6aaAki Tuomi sss_nss_unlock();
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi return ret;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi }
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi if (timeout_ms == 0) {
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi *time_left_ms = 0;
3c503fa10d3d0fe2abb1767caf217b0a770dc6aaAki Tuomi } else {
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi TIMESPECSUB(&endtime, &starttime, &diff);
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi left = timeout_ms - TIMESPEC_TO_MS(&diff);
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi if (left <= 0) {
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi sss_nss_unlock();
3c503fa10d3d0fe2abb1767caf217b0a770dc6aaAki Tuomi return EIO;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi } else if (left > SSS_CLI_SOCKET_TIMEOUT) {
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi *time_left_ms = SSS_CLI_SOCKET_TIMEOUT;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi } else {
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi *time_left_ms = left;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi }
3c503fa10d3d0fe2abb1767caf217b0a770dc6aaAki Tuomi }
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi }
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi return ret;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi}
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi