📄 device_info.c
字号:
/* $Id: device_info.c,v 1.12 2001/09/08 14:29:40 jm Exp $ * Device information daemon in a unix domain socket * * Dynamic hierarchial IP tunnel * Copyright (C) 1998-2001, Dynamics group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. *//* * Device info daemon can be used to query device priorities. It uses * configuration file by default in /etc/device_info.conf. The file * contains MAC addresses of devices and priorities to them. */#ifndef _GNU_SOURCE#define _GNU_SOURCE#endif#include <stdio.h>#include <stdarg.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <time.h>#include <getopt.h>#include <unistd.h>#include <signal.h>#include <arpa/inet.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <sys/param.h>#include <sys/ioctl.h>#include <linux/if.h>#include "util.h"#include "dyn_mnlib.h"#include "agentapi.h"#include "fixed_fd_zero.h"#include "device_info.h"#include "dyn_ip.h"#define PID_FILE "/var/run/device_info.pid"#define MAXLINE 100static char *default_socket_path = DEFAULT_DEVICE_INFO_PATH;static char *default_config_file_path = "/etc/device_info.conf";static char *config_file_path = NULL;static char *socket_path = NULL;static fd_set set;static int debug = 0;static struct device_info_config *config = NULL;struct device_info_config { unsigned char hw[ETH_ALEN]; int priority; int line; struct device_info_config *next;};void DEBUG(char *format, ...){ va_list ap; if (!debug) return; va_start(ap, format); vfprintf(stdout, format, ap); fflush(stdout); va_end(ap);}static int open_socket(char *path){ if (!path) { fprintf(stderr, "open_socket: path is NULL\n"); return -1; } return api_open_socket(path, NULL, NULL, (int)0666);}static void clean_up(int sig){ unlink(PID_FILE); exit(sig);}static struct device_info_config *find_entry(char *hw){ struct device_info_config *conf = config; if (hw == NULL) return NULL; while (conf != NULL) { if (!memcmp(hw, conf->hw, ETH_ALEN)) return conf; conf = conf->next; } return NULL;} static int send_reply(int sock, struct sockaddr_un *addr, struct device_info_query *query){ int r; if (addr == NULL || query == NULL) { fprintf(stderr, "send_reply: NULL argument\n"); return -1; } DEBUG("\tsending reply: index = %d, prio %d\n", query->device_index, query->priority); r = sendto(sock, query, sizeof(struct device_info_query), 0, (struct sockaddr *)addr, sizeof(struct sockaddr_un)); if (r != sizeof(struct device_info_query)) { fprintf(stderr, "send_reply: sendto %d/%d bytes: %s\n", r, sizeof(query), strerror(errno)); return -1; } return r;}static int handle_request(int sock){ struct sockaddr_un addr; struct device_info_query query; struct device_info_config *config; struct idxmap *idxmap, *idx; struct ifreq ifr; int n, len, found = 0, s; len = sizeof(addr); n = recvfrom(sock, &query, sizeof(query), 0, (struct sockaddr *) &addr, (unsigned int *)&len); if (n != sizeof(query)) { fprintf(stderr, "handle_request: couldn't receive whole " "message %d/%d\n", n, sizeof(query)); return -1; } DEBUG("received query\n\tquery.device_index = %d\n", query.device_index); memset(&ifr, 0, sizeof(ifr)); /* find interface name for the index */ idxmap = dyn_ip_get_interface_map(); idx = idxmap; while (idx != NULL) { if (idx->index == query.device_index) { memcpy(ifr.ifr_name, idx->name, sizeof(ifr.ifr_name)); DEBUG("\tdevice name: %s\n", ifr.ifr_name); found = 1; break; } idx = idx->next; } dyn_ip_free_interface_map(idxmap); if (!found) { fprintf(stderr, "handle_request: Couldn't find ifname\n"); return -1; } ifr.ifr_ifindex = query.device_index; s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (s < 0) { fprintf(stderr, "handle_request: socket failed: %s\n", strerror(errno)); return -1; } if (ioctl(s, SIOCGIFHWADDR, &ifr) != 0) { fprintf(stderr, "handle_request: SIOCGIFHWADDR ioctl: %s\n", strerror(errno)); return -1; } config = find_entry(ifr.ifr_hwaddr.sa_data); found = 1; if (!config) { DEBUG("handle_request: entry not found (%s)\n", ether_hwtoa((unsigned char *)&ifr.ifr_hwaddr.sa_data)); found = 0; query.priority = -2; /* entry not found */ } else { query.priority = config->priority; DEBUG("\tquery.priority = %d\n", query.priority); } /* reply */ n = send_reply(sock, &addr, &query); if (n < 0) { fprintf(stderr, "handle_request: Couldn't send reply\n"); return -1; } return 0;}static void parse_config(int sig){ FILE *file; char buffer[MAXLINE]; struct device_info_config *conf = config, *first = config; int line = 0, n; unsigned int hw[6]; if (debug && sig == SIGHUP) DEBUG("HUP signal received. Rereading config file\n"); if (config_file_path == NULL) { fprintf(stderr, "parse_config: path is NULL\n"); return; } file = fopen(config_file_path, "r"); if (file == NULL) { fprintf(stderr, "parse_config: Can't open file %s\n", strerror(errno)); return; } while (fgets(buffer, MAXLINE, file) != NULL) { buffer[strlen(buffer)-1]='\0'; ++line; if (buffer[0] == '#' || buffer[0] == '\n' || buffer[0] == '\t' || buffer[0] == ' ' || strlen(buffer) == 0) { continue; } if (conf == NULL) { DEBUG("Reading first time the configuration file\n"); conf = malloc(sizeof(struct device_info_config)); first = conf; } else { conf->next = malloc(sizeof(struct device_info_config)); conf = conf->next; } if (conf == NULL) { fprintf(stderr, "parse_config: Memory allocation " "failed\n"); fclose(file); return; } n = sscanf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x %d", &hw[0], &hw[1], &hw[2], &hw[3], &hw[4], &hw[5], &conf->priority); if (n != 7) { fprintf(stderr, "parse_config: Couldn't parse " "line %d '%s'\n", line, buffer); fclose(file); return; } conf->line = line; conf->hw[0] = (unsigned char)hw[0]; conf->hw[1] = (unsigned char)hw[1]; conf->hw[2] = (unsigned char)hw[2]; conf->hw[3] = (unsigned char)hw[3]; conf->hw[4] = (unsigned char)hw[4]; conf->hw[5] = (unsigned char)hw[5]; DEBUG("%s prio %d (line %d)\n", ether_hwtoa((unsigned char *)conf->hw), conf->priority, conf->line); } fclose(file); config = first; return;}int main(int argc, char *argv[]){ int s, foreground = 0, c, n; socket_path = default_socket_path; config_file_path = default_config_file_path; while (1) { int option_index = 0; static struct option long_options[] = { {"fg", no_argument, NULL, 'f'}, {"debug", no_argument, NULL, 'd'}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "fdc:s:", long_options, &option_index); if (c == -1) break; switch (c) { case 'f': switch (option_index) { case 0: fprintf(stderr,"Option: %s\n", long_options[option_index].name); foreground = 1; } break; case 'c': config_file_path = malloc(MAXPATHLEN); if (config_file_path == NULL) { fprintf(stderr, "malloc for config: %s\n", strerror(errno)); exit(1); } dynamics_strlcpy(config_file_path, optarg, MAXPATHLEN); break; case 's': socket_path = malloc(MAXPATHLEN); if (socket_path == NULL) { fprintf(stderr, "malloc for path: %s\n", strerror(errno)); exit(1); } dynamics_strlcpy(socket_path, optarg, MAXPATHLEN); break; case 'd': debug = 1; break; case '?': fprintf(stderr, "device_info -c <configuration file> " "[-s <API socket>] [--fg]\n"); exit(1); default: fprintf(stderr, "?? getopt returned character code " "0%o ??\n", c); } } parse_config(0); if (config == NULL) { fprintf(stderr, "Configuration file parsing failed\n"); exit(1); } s = open_socket(socket_path); if (s < 0) { fprintf(stderr, "Open socket failed\n"); exit(1); } DEBUG("Initializing mn admin socket path\n"); c = dynamics_mn_init(NULL); if (c == API_FAILED || c == API_ERROR) { fprintf(stderr, "MN admin socket path initialization " "failed\n"); exit(1); } DEBUG("Registering device info socket path\n"); if (dynamics_mn_register_dev_info_socket(socket_path, 3) != API_SUCCESS) { fprintf(stderr, "API device info socket initialization " "failed\n"); exit(1); } DEBUG("\tregistered\n"); if (!foreground && dynamics_fork_daemon() < 0) { fprintf(stderr, "fork failed\n"); exit(1); } dynamics_write_pid_file(PID_FILE); signal(SIGHUP, parse_config); signal(SIGTERM, clean_up); signal(SIGINT, clean_up); for (;;) { FD_ZERO(&set); FD_SET(s, &set); n = select(FD_SETSIZE, &set, NULL, NULL, NULL); if (n < 0 && errno != EINTR) fprintf(stderr, "select: %s\n", strerror(errno)); if (n == 1 && FD_ISSET(s, &set)) handle_request(s); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -