Configuration daemon for simple-netaid.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

331 lines
9.1 KiB

/*
* util.c
* Copyright (C) Aitor Cuadrado Zubizarreta <aitor_czr@gnuinos.org>
*
* simple-netaid is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* simple-netaid is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
* See the COPYING file.
*/
#include <stdio.h>
#include <stdlib.h>
#include <simple-netaid/sbuf.h>
#include <simple-netaid/interfaces.h>
#include <simple-netaid/helpers.h>
#include <simple-netaid/wireless.h>
#include <simple-netaid/ipaddr.h>
#include <simple-netaid/ethlink.h>
#include "util.h"
#include "config.h"
#include "def.h"
#define MAX_SIZE 256
/**
* \brief Get the PID of the process.
*/
pid_t get_pid_t(void)
{
static char txt[MAX_SIZE];
int fd = -1, locked = -1;
pid_t ret = (pid_t) -1, pid;
ssize_t l;
long lpid;
char *e = NULL;
if ((fd = open(m_config->pidfile_path, O_RDWR, 0644)) < 0) {
if ((fd = open(m_config->pidfile_path, O_RDONLY, 0644)) < 0) {
if (errno != ENOENT) {
log_error("Failed to open pidfile '%s': %s , errno=%d\n", m_config->pidfile_path, strerror(errno), errno);
}
goto finish;
}
}
if ((l = read(fd, txt, MAX_SIZE-1)) < 0) {
int saved_errno = errno;
log_error("read(): %s , errno=%d", strerror(errno), errno);
unlink(m_config->pidfile_path);
errno = saved_errno;
goto finish;
}
txt[l] = 0;
txt[strcspn(txt, "\r\n")] = 0;
errno = 0;
lpid = strtol(txt, &e, 10);
pid = (pid_t) lpid;
if (errno != 0 || !e || *e || (long) pid != lpid) {
unlink(m_config->pidfile_path);
errno = EINVAL;
log_warn("PID file corrupt, removing. (%s) , errno=%d", m_config->pidfile_path, errno);
goto finish;
}
if (kill(pid, 0) != 0 && errno != EPERM) {
int saved_errno = errno;
log_warn("Process %lu died: %s; trying to remove PID file. (%s)", (unsigned long) pid, strerror(errno), m_config->pidfile_path);
unlink(m_config->pidfile_path);
errno = saved_errno;
goto finish;
}
ret = pid;
finish:
if (fd >= 0) {
int saved_errno = errno;
if (locked >= 0)
lock_file(fd, 0);
close(fd);
errno = saved_errno;
}
return ret;
}
/**
* \brief Kill the daemon process.
*/
int wait_on_kill(int s, int m)
{
pid_t pid;
time_t t;
if ((pid = get_pid_t()) < 0)
return -1;
if (kill(pid, s) < 0)
return -1;
t = time(NULL) + m;
for (;;) {
int r;
struct timeval tv = { 0, 100000 };
if (time(NULL) > t) {
errno = ETIME;
return -1;
}
if ((r = kill(pid, 0)) < 0 && errno != ESRCH)
return -1;
if (r)
return 0;
if (select(0, NULL, NULL, NULL, &tv) < 0)
return -1;
}
}
/**
* \brief This function will daemonize this app
*/
void daemonize()
{
pid_t pid = 0;
int fd;
/* Fork off the parent process.
* The first fork will change our pid
* but the sid and pgid will be the
* calling process
*/
pid = fork();
/* An error occurred */
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* Fork off for the second time.
* The magical double fork. We're the session
* leader from the code above. Since only the
* session leader can take control of a tty
* we will fork and exit the session leader.
* Once the fork is done below and we use
* the child process we will ensure we're
* not the session leader, thus, we cannot
* take control of a tty.
*/
if (pid > 0) {
exit(EXIT_SUCCESS);
}
/* On success: The child process becomes session leader */
if (setsid() < 0) {
exit(EXIT_FAILURE);
}
/* Ignore signal sent from child to parent process */
signal(SIGCHLD, SIG_IGN);
/* Fork off for the second time*/
pid = fork();
/* An error occurred */
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* Success: Let the parent terminate */
if (pid > 0) {
exit(EXIT_SUCCESS);
}
/* Set new file permissions */
umask(0);
/* Change the working directory to /tmp */
/* or another appropriated directory */
chdir("/tmp");
/* Close all open file descriptors */
for (fd = sysconf(_SC_OPEN_MAX); fd > 0; fd--) {
close(fd);
}
/* Reopen stdin (fd = 0), stdout (fd = 1), stderr (fd = 2) */
stdin = fopen("/dev/null", "r");
stdout = fopen("/dev/null", "w+");
stderr = fopen("/dev/null", "w+");
/* Try to write PID of daemon to lockfile */
if (m_config->pidfile_path)
{
char str[MAX_SIZE];
pid_fd = open(m_config->pidfile_path, O_RDWR|O_CREAT, 0640);
if (pid_fd < 0) {
/* Can't open lockfile */
exit(EXIT_FAILURE);
}
if (lockf(pid_fd, F_TLOCK, 0) < 0) {
/* Can't lock file */
exit(EXIT_FAILURE);
}
/* Get current PID */
sprintf(str, "%d\n", getpid());
/* Write PID to lockfile */
write(pid_fd, str, strlen(str));
}
}
/**
* \brief Connection attempt
*/
void work(const char *wired_device, const char *wireless_device)
{
if(ifquery(wired_device) && get_interface_status(wired_device) && ethlink(wired_device)==1) {
wired_connection(wired_device);
}
else {
struct sbuf buffer;
sbuf_init(&buffer);
int n=0;
if(ifquery(wireless_device) && get_interface_status(wireless_device)) {
n=scan_active_wifis(wireless_device, &buffer);
}
if(n) {
const char delimiters[] = "\n";
char *token=NULL;
int i=0;
while ((token = strsep(&buffer.buf, delimiters))) {
if(i==1) {
DIR *dir = opendir(WIFI_DIR);
if(!dir) {
log_warn("Enable to open %s\n", WIFI_DIR);
free(buffer.buf);
return;
}
struct dirent *ent;
while ((ent=readdir(dir))) {
if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
if (ent->d_type != DT_DIR) {
FILE *fp;
struct sbuf path;
sbuf_init(&path);
sbuf_concat(&path, 2, WIFI_DIR, ent->d_name);
fp = fopen(path.buf, "r");
if(!fp) {
log_error("fopen(%s) , errno = %d\n", ent->d_name, errno);
}
char line[MAX_SIZE];
while(fgets(line, MAX_SIZE, fp)) {
line[strlen(line)-1]=0;
char *tmp = malloc (strlen (line) + 1);
if(!tmp) {
log_error("Memory failure , errno=%d\n", -ENOMEM);
exit(-1);
}
strcpy(tmp, line);
char *node = strtok(line, "\"");
if(strcmp(node, tmp)) {
node = strtok(NULL, "\"");
if(!strcmp(node, token)) {
struct sbuf cmd;
sbuf_init(&cmd);
kill_all_processes();
ipaddr_flush(wireless_device);
interface_down(wireless_device);
ifdown(wireless_device);
interface_up(wireless_device);
sbuf_concat
(
&cmd, 5,
"/sbin/wpa_supplicant -B -i",
wireless_device,
" -c\"",
path.buf,
"\" > /dev/null"
);
log_info("Executing %s\n", cmd.buf);
system(cmd.buf);
sleep(1);
ifup(wireless_device);
free(cmd.buf);
}
}
free(tmp);
}
free(path.buf);
fclose(fp);
}
}
}
closedir(dir);
}
i++;
if(i>3) i=1;
}
}
free(buffer.buf);
}
}