/
githubmirror
/
rsyslog
Обзор
Документация
Войти
/
githubmirror
/
rsyslog
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
runtime/netns_socket.c
167 строк
5 KB
Rainer Gerhards
ci: enforce compile warnings configure option
29 май 2026, 14:38
Не верифицирован
29 май 2026, 14:38
cf64962
Код
Авторство
О чём код?
/* Implementation for netns_socket API * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include <stdio.h> #include <errno.h> #include <fcntl.h> #include <sched.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include "rsyslog.h" #include "debug.h" #include "errmsg.h" #include "netns_socket.h" /* Change to the given network namespace. * This function based on previous implementation * of tools/omfwd.c function changeToNs. */ rsRetVal netns_switch(const char *ns) { DEFiRet; #ifdef HAVE_SETNS int ns_fd = -1; char *nsPath = NULL; if (ns && *ns) { /* Build network namespace path */ if (asprintf(&nsPath, "/var/run/netns/%s", ns) == -1) { // Some implementations say nsPath would be undefined on failure nsPath = NULL; LogError(0, RS_RET_OUT_OF_MEMORY, "%s: asprintf failed", __func__); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* Open file descriptor of destination network namespace */ ns_fd = open(nsPath, O_RDONLY); if (ns_fd < 0) { LogError(errno, RS_RET_IO_ERROR, "%s: could not open namespace '%s'", __func__, ns); ABORT_FINALIZE(RS_RET_IO_ERROR); } /* Change to the destination network namespace */ if (setns(ns_fd, CLONE_NEWNET) != 0) { LogError(errno, RS_RET_IO_ERROR, "%s: could not change to namespace '%s'", __func__, ns); ABORT_FINALIZE(RS_RET_IO_ERROR); } dbgprintf("%s: changed to network namespace '%s'\n", __func__, ns); } finalize_it: free(nsPath); if ((ns_fd >= 0) && (close(ns_fd) != 0)) { LogError(errno, RS_RET_IO_ERROR, "%s: failed to close namespace '%s'", __func__, ns); } #else // ndef HAVE_SETNS if (ns && *ns) { LogError(ENOSYS, RS_RET_VALUE_NOT_SUPPORTED, "%s: could not change to namespace '%s'", __func__, ns); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: #endif // ndef HAVE_SETNS RETiRet; } /* Return to the startup network namespace. * This function based on code in tools/omfwd.c */ rsRetVal ATTR_NONNULL() netns_restore(int *fd) { DEFiRet; #ifdef HAVE_SETNS if (*fd >= 0) { if (setns(*fd, CLONE_NEWNET) != 0) { LogError(errno, RS_RET_IO_ERROR, "%s: could not return to startup namespace", __func__); ABORT_FINALIZE(RS_RET_IO_ERROR); } dbgprintf("%s: returned to startup network namespace\n", __func__); } finalize_it: #endif // def HAVE_SETNS if (*fd >= 0 && close(*fd) != 0) { LogError(errno, RS_RET_IO_ERROR, "%s: could not close startup namespace fd", __func__); } *fd = -1; RETiRet; } /* Save the current network namespace fd */ rsRetVal ATTR_NONNULL() netns_save(int *fd) { DEFiRet; /* * The fd must always point to either a valid fd * or to -1. We expect it to be -1 on entry here. * To avoid bugs, or possible descriptor leaks, * check that it is always -1 on entry. */ if (*fd != -1) { LogError(0, RS_RET_CODE_ERR, "%s: called with uninitialized descriptor", __func__); ABORT_FINALIZE(RS_RET_CODE_ERR); } #ifdef HAVE_SETNS *fd = open("/proc/self/ns/net", O_RDONLY); if (*fd == -1) { LogError(errno, RS_RET_IO_ERROR, "%s: could not access startup namespace", __func__); ABORT_FINALIZE(RS_RET_IO_ERROR); } dbgprintf("%s: saved startup network namespace\n", __func__); #endif finalize_it: RETiRet; } rsRetVal netns_socket(int *fdp, int domain, int type, int protocol, const char *ns) { DEFiRet; int fd = -1; #ifndef HAVE_SETNS if (ns && *ns) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "Network namespaces are not supported"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } #else /* def HAVE_SETNS */ rsRetVal iRet_restore; int ns_fd = -1; if (ns && *ns) { CHKiRet(netns_save(&ns_fd)); CHKiRet(netns_switch(ns)); } #endif /* def HAVE_SETNS */ *fdp = fd = socket(domain, type, protocol); if (fd == -1) { LogError(errno, RS_RET_NO_SOCKET, "%s: socket(%d, %d, %d) failed", __func__, domain, type, protocol); ABORT_FINALIZE(RS_RET_NO_SOCKET); } finalize_it: #ifdef HAVE_SETNS iRet_restore = netns_restore(&ns_fd); if (iRet == RS_RET_OK) iRet = iRet_restore; #endif /* def HAVE_SETNS */ if (iRet != RS_RET_OK && fd != -1) { (void)close(fd); *fdp = -1; } RETiRet; }