From ea88a565c376e85c7d4176f9245bc16c746aeaef Mon Sep 17 00:00:00 2001 From: dlyao Date: Sat, 27 Apr 2013 08:47:26 +0000 Subject: [PATCH] =?UTF-8?q?=E9=92=88=E5=AF=B91.6=E7=89=88=E6=9C=AC?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E4=BA=86=E5=85=B1=E4=BA=AB=E5=86=85?= =?UTF-8?q?=E5=AD=98=E5=92=8C=E4=BF=A1=E5=8F=B7=E9=87=8F=E7=9A=84=E7=94=9F?= =?UTF-8?q?=E6=88=90=E4=BD=8D=E7=BD=AE=EF=BC=8C=E4=BB=8E~d5000/tmp/?= =?UTF-8?q?=E6=94=B9=E4=B8=BA~d5000/share=20=E5=A2=9E=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E6=89=80=E9=9C=80=E7=9A=84=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E5=BA=93libman.so=EF=BC=8C=E5=A2=9E=E5=8A=A0=E4=BA=86=E5=8F=AF?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E5=AE=89=E8=A3=85=E7=9A=84pkg=E5=8C=85?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://172.17.0.253/svn/soft_pkgs/sys_nicmonitor@1382 09c3743a-b0dd-45d3-b506-aa74c7a2a6ef --- code/tags/README1.7 | 15 + code/tags/libman.so | Bin 0 -> 102404 bytes code/tags/sys_nicmonitor-1.7/Makefile | 28 + code/tags/sys_nicmonitor-1.7/Makefile.config | 16 + code/tags/sys_nicmonitor-1.7/const.h | 51 + code/tags/sys_nicmonitor-1.7/mnic.c | 1552 +++++++++++++++++ code/tags/sys_nicmonitor-1.7/mnic.h | 44 + code/tags/sys_nicmonitor-1.7/nicinfo_shm.c | 209 +++ code/tags/sys_nicmonitor-1.7/nicinfo_shm.h | 52 + code/tags/sys_nicmonitor-1.7/proc_inv.h | 198 +++ code/tags/sys_nicmonitor-1.7/read_netcard.c | 133 ++ code/tags/sys_nicmonitor-1.7/send_alarm.c | 37 + code/tags/sys_nicmonitor-1.7/sys_netcard.h | 88 + ...onitor#1.7-x86_64-linx-Rocky4.2.pkg.tar.gz | Bin 0 -> 18551 bytes 14 files changed, 2423 insertions(+) create mode 100644 code/tags/README1.7 create mode 100644 code/tags/libman.so create mode 100644 code/tags/sys_nicmonitor-1.7/Makefile create mode 100644 code/tags/sys_nicmonitor-1.7/Makefile.config create mode 100644 code/tags/sys_nicmonitor-1.7/const.h create mode 100644 code/tags/sys_nicmonitor-1.7/mnic.c create mode 100644 code/tags/sys_nicmonitor-1.7/mnic.h create mode 100644 code/tags/sys_nicmonitor-1.7/nicinfo_shm.c create mode 100644 code/tags/sys_nicmonitor-1.7/nicinfo_shm.h create mode 100644 code/tags/sys_nicmonitor-1.7/proc_inv.h create mode 100644 code/tags/sys_nicmonitor-1.7/read_netcard.c create mode 100644 code/tags/sys_nicmonitor-1.7/send_alarm.c create mode 100644 code/tags/sys_nicmonitor-1.7/sys_netcard.h create mode 100644 packages/sys_nicmonitor#1.7-x86_64-linx-Rocky4.2.pkg.tar.gz diff --git a/code/tags/README1.7 b/code/tags/README1.7 new file mode 100644 index 0000000..b2afb8c --- /dev/null +++ b/code/tags/README1.7 @@ -0,0 +1,15 @@ +V1.6与V1.7差异 +共享内存路径修改: +由/home/d5000/someone/tmp/sys_netcard_shm_path 改为 /home/d5000/someone/share/sys_netcard_shm_path +信号量路径修改: +由/home/d5000/someone/tmp/sys_netcard_sem_path 改为 /home/d5000/someone/share/sys_netcard_sem_path + +注意:在编译过程中,需要动态看libman.so,它存放在目录 tags/下面 ,在进行编译的时候需要将其拷贝到 +/lib64/目录下,编译的基础环境是 Rocky 4.2 系统。 + +pkgmk命令的使用: +将源代码打包成name-version.tar.gz样式,编写Pkgfile文件。 +使用命令: + pkgmk -um #更新软件包的md5值 + pkgmk -kw #制作pkg安装包 + diff --git a/code/tags/libman.so b/code/tags/libman.so new file mode 100644 index 0000000000000000000000000000000000000000..c78c12ae1a54433fa7ad5676285f1fbe831ccba6 GIT binary patch literal 102404 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 C)9E(= literal 0 HcmV?d00001 diff --git a/code/tags/sys_nicmonitor-1.7/Makefile b/code/tags/sys_nicmonitor-1.7/Makefile new file mode 100644 index 0000000..5cccc77 --- /dev/null +++ b/code/tags/sys_nicmonitor-1.7/Makefile @@ -0,0 +1,28 @@ +#! /usr/bin/make -f + +DEFAULTS = Makefile.config + +include $(DEFAULTS) + +all:sys_nicmonitor libnic_shm.so + +CFLAGS += -Wall -Wformat=2 -Wno-format-extra-args -Wformat-security -Wformat-nonliteral #-g + +sys_nicmonitor:mnic.o read_netcard.o send_alarm.o + $(CC) -lman -ldotconf -lpthread -o $@ $^ +libnic_shm.so:nicinfo_shm.c + $(CC) -fpic -shared -o $@ $^ +clean: + $(RM) *.o + $(RM) libnic_shm.so sys_nicmonitor +install: + $(MKDIR) -p $(LIBDIR) + $(MKDIR) -p $(BINDIR) + $(MKDIR) -p $(INCDIR) + $(CP) libnic_shm.so $(LIBDIR) + $(CP) sys_nicmonitor $(BINDIR) + $(CP) nicinfo_shm.h $(INCDIR) +uninstall: + $(RM) -f $(LIBDIR)/libnic_shm.so + $(RM) -f $(BINDIR)/sys_nicmonitor + $(RM) -f $(INCDIR)/nicinfo_shm.h diff --git a/code/tags/sys_nicmonitor-1.7/Makefile.config b/code/tags/sys_nicmonitor-1.7/Makefile.config new file mode 100644 index 0000000..7a2d8e6 --- /dev/null +++ b/code/tags/sys_nicmonitor-1.7/Makefile.config @@ -0,0 +1,16 @@ + +PREFIX = $(DESTDIR) + +BINDIR = $(PREFIX)/usr/bin + +LIBDIR = $(PREFIX)/usr/lib64 + +INCDIR = $(PREFIX)/usr/include + +INSTALL_SH = ./install.sh + +CP = cp +RM = rm +#CC = gcc +CC = g++ +MKDIR = mkdir diff --git a/code/tags/sys_nicmonitor-1.7/const.h b/code/tags/sys_nicmonitor-1.7/const.h new file mode 100644 index 0000000..e2ebfa5 --- /dev/null +++ b/code/tags/sys_nicmonitor-1.7/const.h @@ -0,0 +1,51 @@ +#ifndef _RTE_CONST_H +#define _RTE_CONST_H + +#include + + +#define MAX_STRING_LEN 24 +#define MAX_EXECMD_LEN 200 +#define MAX_FILENAME_LEN 200 + +#define MAX_CONTEXT 8 +#define MAX_HOSTNAME_LEN 24 +#define MAX_LOCAL_MESPROC 512 +#define MAX_LOCAL_PROCESS MAX_LOCAL_MESPROC +#define MAX_LOCAL_APP 32 +#define MAX_LOCAL_NODE 256 + +#define MAX_SET 256 //max num of event set +#define MAX_EVENT 1300 +#define MAX_REG_PROC 20 + +#define LEN_SHMBLK_BIG 4096 +#define MAX_MSGBUF_LEN 32767 +#define FREE_PAGE_SIZE 65536 +#define MAX_PAGE_NUM 1024 + +#define MAX_QUE MAX_LOCAL_MESPROC +#define MAX_SEMPHORE_SET MAX_LOCAL_MESPROC*2 +#define RTE_HAN 0 // queue number for event handeler0(RTE) +#define EX_EVENT_HAN RTE_HAN // queue number for extrnal event handeler + +#define DOMAIN_I 1 +#define DOMAIN_II 2 +#define DOMAIN_III 3 + +//Add 20090225 +const int PROC_TYPE_RPT =1; +const int PROC_TYPE_UNRPT =0; +//add end + + +//status for proc and app +const int NON_ACTIVE = 0; +const int ACTIVE = 1; +const int HANGUP = 2; +const int FAILURE = 5; +const int START = 6; +const int STOP = 7; + +#endif + diff --git a/code/tags/sys_nicmonitor-1.7/mnic.c b/code/tags/sys_nicmonitor-1.7/mnic.c new file mode 100644 index 0000000..a538209 --- /dev/null +++ b/code/tags/sys_nicmonitor-1.7/mnic.c @@ -0,0 +1,1552 @@ +#include "mnic.h" +#include "dotconf.h" +#include +#include +#include "proc_inv.h" + +#define THRNR 10 +#define DAYS 25 +#define LINE_SIZE 2048 +#define HOST_NAME_SIZE 40 +#define BOND_PATH "/proc/net/bonding/*" +#define LOG_PATH "/var/log/netcard/" +#define SHM_PATH "/share/sys_netcard_shm_path" +#define SEM_PATH "/share/sys_netcard_sem_path" +#define MAX_GW 32 +#define DEV_MAXLEN 32 +#define IPLEN 16 +#define CONF_FILE "/conf/nic/sys_netcard_conf.txt" + +#define MNIC_VERSION "1.7" + +#define NIC_UNKNOWN 0 +#define NIC_DOWN 1 +#define NIC_UNRUNNING 2 +#define NIC_UNLINKABLE 3 +#define NIC_NORMAL 4 + +//网卡设备描述结构 +typedef struct __nic_dev{ + char dev_name[DEV_MAXLEN]; //网卡名称 + char ping_ip[MAX_GW][IPLEN]; //ping地址列表,最多32个 + int gw_num; //地址列表的长度 +}NIC_DEV; + +typedef struct __config_file_st{ + unsigned char domain; + short serv; + short event; + int udpport; + int monitor_interval; + int write_interval; + int flow_interval; + int flow_limit; + int flow_peak; + char udp[NIC_NAME_LEN]; + NIC_DEV nic[MAXNICNUM]; //被监视网卡的列表 + char ip[IPSIZE]; + int pingnum; //OPTIONAL!! How many times for once ping check? Default is 2. + int pinglap; //OPTIONAL!! How many seconds does ping wait for reply package? Default is 1. +}CONFIG_FILE_ST; + +typedef struct inc_name_node{ + char name[NIC_NAME_LEN]; + struct inc_name_node *next; +}NET_NAME_ST; + +typedef struct inc_info_node{ + NETCARD_INFO info; + int status; + struct inc_info_node *next; +}NETCARD_INFO_ST; + +typedef struct net_info{ + NETCARD_INFO info[MAXNICNUM]; +}SHM; + +typedef struct __thread_env_st{ + D5000_NIC_ALARM Malarm; + char bond_file_path[64]; + char host_name[HOST_NAME_SIZE]; + int host_name_size; + CONFIG_FILE_ST *conf; +}THENV; + +typedef struct __thread_mem_st{ + int semid; + SHM *shm_ptr; + NETCARD_INFO_ST *listp; + CONFIG_FILE_ST *conf; +}THMEM; + +typedef struct __thread_flow_st{ + THENV env; + THMEM mem; +}THFLOW; + +int find_nic_config(char *); + +static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; +static short seqno = 1; +static char log_flag = 1; +static int sem_id = 0; +static char process_name[64]; +char log_path[1024]; +char shm_path[1024]; +char sem_path[1024]; +char conf_path[1024]; + +int host_name_size = 0; +char host_name[HOST_NAME_SIZE]; +int semid = -1; +SHM *shm_ptr; + +//20100510 +int total_ping_time, elapsed_ping_time; +int get_netcard_status(NETCARD_INFO_ST *); + +/****dotconf****/ +static DOTCONF_CB(cb_str); +static DOTCONF_CB(cb_int); +int nicnum = 0; +CONFIG_FILE_ST conf; + +char myconf[][64] = { + "domain", // 0 + "serv", // 1 + "event", // 2 + "udpport", // 3 + "sys_netcard_shm_path", // 4 + "sys_netcard_sem_path", // 5 + "monitor_interval", // 6 + "write_interval", // 7 + "flow_interval", // 8 + "flow_limit", // 9 + "flow_peak", // 10 + "udp", // 11 + "nic", // 12 + "ping", // 13 + "pingnum", // 14 + "pinglap", // 15 + "" +}; + +static const configoption_t options[] = { + {myconf[0], ARG_INT, cb_int, NULL, CTX_ALL}, + {myconf[1], ARG_INT, cb_int, NULL, CTX_ALL}, + {myconf[2], ARG_INT, cb_int, NULL, CTX_ALL}, + {myconf[3], ARG_INT, cb_int, NULL, CTX_ALL}, + {myconf[4], ARG_STR, cb_str, NULL, CTX_ALL}, + {myconf[5], ARG_STR, cb_str, NULL, CTX_ALL}, + {myconf[6], ARG_INT, cb_int, NULL, CTX_ALL}, + {myconf[7], ARG_INT, cb_int, NULL, CTX_ALL}, + {myconf[8], ARG_INT, cb_int, NULL, CTX_ALL}, + {myconf[9], ARG_INT, cb_int, NULL, CTX_ALL}, + {myconf[10], ARG_INT, cb_int, NULL, CTX_ALL}, + {myconf[11], ARG_STR, cb_str, NULL, CTX_ALL}, + {myconf[12], ARG_STR, cb_str, NULL, CTX_ALL}, + {myconf[13], ARG_STR, cb_str, NULL, CTX_ALL}, + {myconf[14], ARG_INT, cb_int, NULL, CTX_ALL}, + {myconf[15], ARG_INT, cb_int, NULL, CTX_ALL}, + LAST_OPTION +}; +/****dotconf****/ + +/* write error in logfile */ +void record_log(char *str) +{ + time_t tamp; + char str_tm[4]; + char log_str[512]; + FILE *log_fp = NULL; + struct tm tmptr; + struct timeval tv; + struct timezone tz; + + if((log_fp = fopen(log_path, "a")) != NULL){ + tamp = time(NULL); + memset(str_tm, 0, sizeof(str_tm)); + memset(log_str, 0, sizeof(log_str)); + localtime_r(&tamp, &tmptr); + gettimeofday(&tv, &tz); + snprintf(str_tm, sizeof(str_tm), "%d", (int)tv.tv_usec/1000); + if(str_tm[1] == '\0')str_tm[1] = '0'; + if(str_tm[2] == '\0')str_tm[2] = '0'; + strftime(log_str, sizeof(log_str), "%F %T.", &tmptr); + strcat(log_str, str_tm); + strcat(log_str, " "); + strcat(log_str, process_name); + strcat(log_str, " "); + strcat(log_str, str); + if(fwrite(log_str, 1, strlen(log_str), log_fp) < 1){ + } + fclose(log_fp); + } +} + +static void init_sem(int *semid, CONFIG_FILE_ST *ptr) +{ + key_t key; + char error_str[200]; + + /* write error in logfile */ + memset(error_str, 0, sizeof(error_str)); + if ((key = ftok(sem_path, SEM_PROJ_ID)) == -1) { + snprintf(error_str, sizeof(error_str), "EMERG: ftok():%s\n", strerror(errno)); + record_log(error_str); + return; + } + if((*semid = semget(key, 1, IPC_CREAT|0666)) == -1){ + snprintf(error_str, sizeof(error_str), "EMERG: semget():%s\n", strerror(errno)); + record_log(error_str); + return; + } + if(semctl(*semid, 0, SETVAL, 0) == -1){ + snprintf(error_str, sizeof(error_str), "EMERG: semctl: %s !\n", strerror(errno)); + record_log(error_str); + semctl(*semid, 0, IPC_RMID); + return; + } +} + +static void init_shm(SHM **ptr, CONFIG_FILE_ST *p) +{ + int fd = -1; + char error_str[200]; + + mode_t mask_tmp; + mask_tmp = umask(0000); + if((fd = open(shm_path, O_RDWR|O_CREAT|O_TRUNC, 0666)) == -1){ + printf("could not create %s\n", shm_path); + return; + } + umask(mask_tmp); + lseek(fd, sizeof(SHM), SEEK_SET); + write(fd, "\0", 1); + *ptr = (SHM *)mmap(NULL, sizeof(SHM), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if(*ptr == MAP_FAILED){ + snprintf(error_str, sizeof(error_str), "EMERG: mmap():%s\n", strerror(errno)); + record_log(error_str); + return; + } + close(fd); + +} + +static void get_sem(int semid) +{ + struct sembuf lock[2]; + char error_str[200]; + + lock[0].sem_num = 0; + lock[0].sem_op = 0; + lock[0].sem_flg = SEM_UNDO; + + lock[1].sem_num = 0; + lock[1].sem_op = 1; + lock[1].sem_flg = SEM_UNDO; + + while(semop(semid, lock, 2)){ + if(errno == EINTR)continue; + snprintf(error_str, sizeof(error_str), "EMERG: get_sem semop():%s\n", strerror(errno)); + record_log(error_str); + return; + } +} + +static void release_sem(int semid) +{ + int ret; + char error_str[200]; + struct sembuf unlock; + + unlock.sem_num = 0; + unlock.sem_op = -1; + unlock.sem_flg = SEM_UNDO; + + if((ret = semop(semid, &unlock, 1)) == -1){ + snprintf(error_str, sizeof(error_str), "EMERG: rel_sem semop():%s\n", strerror(errno)); + record_log(error_str); + return; + } +} + +static void proc_get_name(NET_NAME_ST *nodep) +{ + char linebuf[LINE_SIZE]; + char error_str[200]; + char *retp = NULL; + int err_val=0; + NET_NAME_ST *node = NULL; + FILE *dev_fp; + + if((dev_fp = fopen("/proc/net/dev", "rb")) == NULL){ + snprintf(error_str, sizeof(error_str), "EMERG: Can't open dev file:%s\n", strerror(errno)); + record_log(error_str); + return; + } + memset(linebuf, 0, sizeof(linebuf)); + fgets(linebuf, sizeof(linebuf), dev_fp); + fgets(linebuf, sizeof(linebuf), dev_fp); + while((retp = fgets(linebuf, sizeof(linebuf), dev_fp)) != NULL){ + if((node = (NET_NAME_ST *)malloc(sizeof(NET_NAME_ST))) == NULL){ + err_val = 1; + break; + } + memset(node->name, 0, NIC_NAME_LEN); + get_name(node->name, retp); + node->next = nodep->next; + nodep->next = node; + } + if(err_val){ + NET_NAME_ST *curr = nodep->next; + while(curr != NULL){ + node = curr->next; + free(curr); + curr = node; + } + } + fclose(dev_fp); +} + +static void ioctl_get_name(NET_NAME_ST *nodep) +{ + int count = 0; + int inuse = 0; + int err_val = 0; + NETCARD_INFO net_name[MAXNICNUM]; + NET_NAME_ST *node = NULL, *curr = NULL; + + memset(net_name, 0, sizeof(net_name)); + if((count = ioc_get_name(net_name)) == 0)return; + if(nodep->next == NULL) + inuse = 1; + while(count > 0){ + curr = nodep->next; + while(curr != NULL){ + if(!strncmp(net_name[count - 1].charname, curr->name, NIC_NAME_LEN)){ + inuse = 0; + break; + } + inuse = 1; + curr = curr->next; + } + if(inuse){ + if((node = (NET_NAME_ST *)malloc(sizeof(NET_NAME_ST))) == NULL){ + err_val = 1; + break; + } + memset(node->name, 0, NIC_NAME_LEN); + strncpy(node->name, net_name[count - 1].charname, NIC_NAME_LEN); + node->next = nodep->next; + nodep->next = node; + } + count--; + } + if(err_val){ + curr = nodep->next; + while(curr != NULL){ + node = curr->next; + free(curr); + curr = node; + } + } +} + +static void get_all_name(NET_NAME_ST *nodep) +{ + proc_get_name(nodep); + ioctl_get_name(nodep); +} + +static void create_monit_list(NET_NAME_ST *nodep, NETCARD_INFO_ST *info_list, char *bond) +{ + int err_val = 0; + NETCARD_INFO_ST *info_node = NULL; + NET_NAME_ST *curr, *node; + + curr = nodep->next; + while(curr != NULL){ + if((info_node = (NETCARD_INFO_ST *)malloc(sizeof(NETCARD_INFO_ST))) == NULL){ + err_val = 1; + break; + } + memset(info_node, 0, sizeof(NETCARD_INFO_ST)); + strncpy(info_node->info.charname, curr->name, NIC_NAME_LEN); + strncpy(info_node->info.descr, bond, strlen(bond)); + info_node->next = info_list->next; + info_list->next = info_node; + curr = curr->next; + } + if(err_val){ + NETCARD_INFO_ST *info_curr = info_list->next; + while(info_curr != NULL){ + info_node = info_curr->next; + free(info_curr); + info_curr = info_node; + } + curr = nodep->next; + while(curr != NULL){ + node = curr->next; + free(curr); + curr = node; + } + } +} + +static int get_inc_info(NETCARD_INFO *net) +{ + return if_fetch(net); +} + +static void get_inc_stats(NETCARD_INFO *net) +{ + char linebuf[LINE_SIZE]; + char *retp = NULL; + char *str = NULL; + FILE *dev_fp; + + if((dev_fp = fopen("/proc/net/dev", "r")) == NULL)return; + memset(linebuf, 0, sizeof(linebuf)); + while((retp = fgets(linebuf, sizeof(linebuf), dev_fp)) != NULL){ + if((str = strstr(linebuf, net->charname)) != NULL){ + str +=strlen(net->charname) + 2; + get_dev_fields(str, net); + break; + } + } + fclose(dev_fp); +} + +static void send_inc_info_one(NETCARD_INFO *net, int semid, SHM *ptr) +{ + int i; + for(i = 0; ptr->info[i].charname[0] != 0; i++){ + if(!strncmp(ptr->info[i].charname, net->charname, NIC_NAME_LEN)){ + get_sem(semid); + memcpy(&ptr->info[i], net, sizeof(NETCARD_INFO)); + release_sem(semid); + } + } +} + +static void *send_inc_info(void *p) +{ + int i = 0; + int flags = 1; + char error_str[200]; + unsigned long long bytes[MAXNICNUM]; + THMEM *ptr = (THMEM *)p; + NETCARD_INFO_ST *curr; + struct timespec s_time, os_time; + + if((curr = ptr->listp->next) == NULL){ + pthread_mutex_lock(&mut); + snprintf(error_str, sizeof(error_str), "EMERG: Empty Netcard list!\n"); + record_log(error_str); + pthread_mutex_unlock(&mut); + return NULL; + } + s_time.tv_sec = ptr->conf->write_interval; + s_time.tv_nsec = 0; + + /* copy all net_info*/ + while(1){ + i = 0; + get_sem(ptr->semid); + //memset(ptr->shm_ptr, 0, sizeof(SHM)); + curr = ptr->listp->next; + while(curr != NULL){ + get_inc_info(&curr->info); + if(curr->status == NIC_UNLINKABLE){ + curr->info.flags &= (~IFF_UP); + curr->info.flags &= (~IFF_RUNNING); + } + get_inc_stats(&curr->info); + if(flags){ + bytes[i] = curr->info.rx_bytes + curr->info.tx_bytes; + } + curr->info.average_flow =(unsigned long long)((curr->info.rx_bytes + curr->info.tx_bytes - bytes[i])/(ptr->conf->write_interval)); + memcpy(&ptr->shm_ptr->info[i], &curr->info, sizeof(NETCARD_INFO)); + bytes[i] = curr->info.rx_bytes + curr->info.tx_bytes; + i++; + curr = curr->next; + } + release_sem(ptr->semid); + flags = 0; + nanosleep(&s_time, &os_time); + } +} + +static int get_netcard_count(char *name) +{ + int count = 0; + FILE *fp = NULL; + char path[64] = "/proc/net/bonding/"; + char buf[LINE_SIZE]; + char *retp = NULL; + char *str = NULL; + + strncat(path, name, strlen(name)); + if((fp = fopen(path, "r")) == NULL)return 1; + + memset(buf, 0, sizeof(buf)); + fseek(fp, 65, SEEK_SET); + while((retp = fgets(buf, sizeof(buf), fp)) != NULL){ + if((str = strstr(buf, "active-backup")) != NULL){ + fclose(fp); + return 1; + } + if(!strncmp(buf, "Slave Interface:", 16))count++; + } + fclose(fp); + return count; +} + +static void *cacu_flow(void *p) +{ + int i = 0, count_t = 1; + int summit = 0; + int flags = 1; + int count_ok[MAXNICNUM]; + int count_no[MAXNICNUM]; + char error_str[200]; + unsigned long long bytes[MAXNICNUM]; + THFLOW *ptr = (THFLOW *)p; + NETCARD_INFO_ST *curr; + struct timespec s_time, os_time; + + if((curr = ptr->mem.listp->next) == NULL){ + pthread_mutex_lock(&mut); + snprintf(error_str, sizeof(error_str), "EMERG: Empty Netcard list!\n"); + record_log(error_str); + pthread_mutex_unlock(&mut); + return NULL; + } + s_time.tv_sec = ptr->mem.conf->flow_interval; + s_time.tv_nsec = 0; + + for(i = 0; i < MAXNICNUM ; i++){ + count_ok[i] = 0; + count_no[i] = 0; + } + while(1){ + i = 0; + curr = ptr->mem.listp->next; + while(curr != NULL){ + get_inc_info(&curr->info); + get_inc_stats(&curr->info); + if(flags){ + bytes[i] = curr->info.rx_bytes + curr->info.tx_bytes; + } + curr->info.average_flow =(unsigned long long)((curr->info.rx_bytes + curr->info.tx_bytes - bytes[i])/ptr->mem.conf->flow_interval); + if(!strncmp(curr->info.charname, "bond", 4)){ + count_t = get_netcard_count(curr->info.charname); + }else { + count_t = 1; + } + summit = (unsigned int)(curr->info.average_flow*8*100/1024/1024/ptr->mem.conf->flow_peak/count_t); +#if 0 + printf("%s:\tcount=%d\tsummit=%d\tflow_limit:%d\taverage_flow:%d\n", curr->info.charname, count_t, summit, conf.flow_limit, curr->info.average_flow); +#endif + if(summit >= ptr->mem.conf->flow_limit){ + memset(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, 0, NIC_NAME_LEN); + strncpy(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, ptr->env.host_name, ptr->env.host_name_size); + strncat(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, "-", 1); + strncat(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, curr->info.charname, (NIC_NAME_LEN - ptr->env.host_name_size - 1)); + ptr->env.Malarm.tSysNetcardAlarm.flags = NETCARD_ALARM_ABNORMAL; + ptr->env.Malarm.tSysNetcardAlarm.retrytimes = 0; + ptr->env.Malarm.tMsgFrame.len = sizeof(ptr->env.Malarm); + ptr->env.Malarm.tMsgFrame.seqno = seqno; + pthread_mutex_lock(&mut); + while(count_no[i] > 0){ + send_alarm(&ptr->env.Malarm, ptr->mem.conf->udpport, ptr->mem.conf->ip); + seqno++; + ptr->env.Malarm.tMsgFrame.seqno = seqno; + ptr->env.Malarm.tSysNetcardAlarm.retrytimes++; + count_no[i]--; + if(count_no[i] == 0){ + send_inc_info_one(&curr->info, ptr->mem.semid, ptr->mem.shm_ptr); + //snprintf(error_str, sizeof(error_str), "NOTICE: %s flow is abnormal, summit is %d, average flow is %lld !\n", curr->info.charname, summit, curr->info.average_flow); + snprintf(error_str, sizeof(error_str), "NOTICE: %s flow is abnormal !\n", curr->info.charname); + record_log(error_str); + } + } + pthread_mutex_unlock(&mut); + count_ok[i] = 3; + }else{ + memset(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, 0, NIC_NAME_LEN); + strncpy(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, ptr->env.host_name, ptr->env.host_name_size); + strncat(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, "-", 1); + strncat(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, curr->info.charname, (NIC_NAME_LEN - ptr->env.host_name_size - 1)); + ptr->env.Malarm.tSysNetcardAlarm.flags = NETCARD_ALARM_NORMAL; + ptr->env.Malarm.tSysNetcardAlarm.retrytimes = 0; + ptr->env.Malarm.tMsgFrame.len = sizeof(ptr->env.Malarm); + ptr->env.Malarm.tMsgFrame.seqno = seqno; + pthread_mutex_lock(&mut); + while(count_ok[i] > 0){ + send_alarm(&ptr->env.Malarm, ptr->mem.conf->udpport, ptr->mem.conf->ip); + seqno++; + ptr->env.Malarm.tMsgFrame.seqno = seqno; + ptr->env.Malarm.tSysNetcardAlarm.retrytimes++; + count_ok[i]--; + if(count_ok[i] == 0){ + send_inc_info_one(&curr->info, ptr->mem.semid, ptr->mem.shm_ptr); + snprintf(error_str, sizeof(error_str), "NOTICE: %s flow is normal now !\n", curr->info.charname); + record_log(error_str); + } + } + pthread_mutex_unlock(&mut); + count_no[i] = 3; + }/* end if(summit... */ + bytes[i] = curr->info.rx_bytes + curr->info.tx_bytes; + i++; + curr = curr->next; + }/* end while(curr...) */ + flags = 0; + nanosleep(&s_time, &os_time); + }/* end while(1) */ +} +static char *parse_str(char **s) +{ + char *retp = NULL; + char *p = *s; + + while(isspace(*p))p++; + retp = p; + while(!isspace(*p))p++; + *p = '\0'; + + return retp; +} + +int ping_gw(char *devname) +{ + FILE *fp; + int i, j, k; + char buf[128]; + char getbuf[64]; + + i = find_nic_config(devname); + if( i == -1 ) + return 0; + + if(conf.nic[i].gw_num == 0) + return 0; + + for(k=0; kbond_file_path, "r")) == NULL){ + snprintf(error_str, sizeof(error_str), "EMERG: fopen():%s\n", strerror(errno)); + record_log(error_str); + free(ptr); + return NULL; + } + fseek(fp, 65, SEEK_SET); + memset(name, 0, sizeof(name)); + memset(linebuf, 0, sizeof(linebuf)); + if((retp = fgets(linebuf, sizeof(linebuf), fp)) != NULL){ + if((retp = strstr(linebuf, "active-backup")) == NULL){ + free(ptr); + fclose(fp); + return NULL; + } + } + + s_time.tv_sec = 0; + s_time.tv_nsec = 100000000; + + while(1){ + while((str = fgets(linebuf, sizeof(linebuf), fp)) != NULL){ + if(!strncmp(linebuf, "Currently Active Slave:", 23)){ + str += 23; + retp = parse_str(&str); + break; + } + } + if(name[0] == 0){ + strncpy(name, retp, strlen(retp)); + }else if(strncmp(name, retp, strlen(retp)) != 0){ + memset(arg->Malarm.tSysNetcardAlarm.switch_devname, 0, NIC_NAME_LEN); + strncpy(arg->Malarm.tSysNetcardAlarm.switch_devname, arg->host_name, arg->host_name_size); + strncat(arg->Malarm.tSysNetcardAlarm.switch_devname, "-", 1); + strncat(arg->Malarm.tSysNetcardAlarm.switch_devname, retp, (NIC_NAME_LEN - arg->host_name_size - 1)); + arg->Malarm.tSysNetcardAlarm.flags = NETCARD_ALARM_SWITCH; + arg->Malarm.tSysNetcardAlarm.retrytimes = 0; + arg->Malarm.tMsgFrame.len = sizeof(arg->Malarm); + arg->Malarm.tMsgFrame.seqno = seqno; + count = 3; + pthread_mutex_lock(&mut); + snprintf(error_str, sizeof(error_str), "NOTICE: Net card checking to %s!\n", retp); + record_log(error_str); + while(count > 0){ + send_alarm(&arg->Malarm, arg->conf->udpport, arg->conf->ip); + seqno++; + arg->Malarm.tMsgFrame.seqno = seqno; + arg->Malarm.tSysNetcardAlarm.retrytimes++; + count--; + } + pthread_mutex_unlock(&mut); + memset(name, 0, NIC_NAME_LEN); + strncpy(name, retp, strlen(retp)); + } + fclose(fp); + nanosleep(&s_time, &os_time); + if((fp = fopen(arg->bond_file_path, "r")) == NULL){ + free(ptr); + return NULL; + } + fseek(fp, 65, SEEK_SET); + } + free(ptr); + fclose(fp); + return NULL; +} + +static void *create_logfile(void *ptr) +{ + char buf[128]; + char del_file[DAYS][1024]; + char *s; + int head, tail, fd; + int flag = 0, del_flag = 0; + int old_mon = 0; + int old_day = 0; + time_t tamp; + struct tm tmptr; + struct timespec s_time, os_time; + + s_time.tv_sec = 1; + s_time.tv_nsec = 0; + head = tail = 0; + while(1){ + tamp = time(NULL); + localtime_r(&tamp, &tmptr); + if(old_mon != (tmptr.tm_mon + 1))flag = 1; + else if(old_day != tmptr.tm_mday)flag = 1; + else flag = 0; + if(flag){ + s = strrchr(log_path, '/'); + s++; + *s = '\0'; + memset(buf, 0, sizeof(buf)); + strftime(buf, sizeof(buf), "%Y%m%d_", &tmptr); + strcat(buf, process_name); + strcat(buf, ".log"); + strcat(log_path, buf); + mode_t mask_tmp; + mask_tmp = umask(0000); + if((fd = open(log_path, O_RDWR|O_CREAT, 0666)) != -1){ + log_flag = 0; + close(fd); + } + umask(mask_tmp); + old_mon = tmptr.tm_mon+1; + old_day = tmptr.tm_mday; + strcpy(del_file[head++], log_path); + if(head == DAYS){ + head = 0; + del_flag = 1; + } + if(del_flag){ + unlink(del_file[tail]); + tail++; + if(tail == DAYS)tail = 0; + } + } + nanosleep(&s_time, &os_time); + } +} + +void write_time(int semid, SHM *ptr) +{ + int i = 0; + int flag_time_stamp; + + flag_time_stamp = time(NULL); + + while(ptr->info[i].charname[0] != 0){ + ptr->info[i].time_stamp = flag_time_stamp; + i++; + } +} +#if 0 +char *parse(char *line) +{ + char *begin = NULL; + char *end = NULL; + + if((begin = strchr(line, '/')) != NULL){ + if((end = strstr(line, "bin")) != NULL){ + *end='\0'; + return begin; + } + } + return NULL; +} +#endif +void release_name_list(NET_NAME_ST *head) +{ + NET_NAME_ST *curr, *save; + + curr = head->next; + while(curr != NULL){ + save = curr->next; + free(curr); + curr = save; + } +} +int get_netcard(char *line, char *nic) +{ + char *begin, *retp; + + while(isspace(*line))line++; + begin = line; + while(!isspace(*line))line++; + *line++ = '\0'; + if(!strncmp(begin, "nic", 4)){ + if((retp = parse_str(&line)) != NULL){ + strncpy(nic, retp, MAXNICNUM); + return 1; + } + } + return 0; +} + +void sig_handler(int sig) +{ + // char err_str[200]; + +#if 0 + if(unlink(SHM_PATH) == -1){ + snprintf(err_str, sizeof(err_str), "NOTICE: error delete %s\n", strerror(errno)); + record_log(err_str); + } + if(unlink(SEM_PATH) == -1){ + snprintf(err_str, sizeof(err_str), "NOTICE: error delete %s\n", strerror(errno)); + record_log(err_str); + } +#endif + // semctl(sem_id, 0, IPC_RMID); + + // snprintf(err_str, sizeof(err_str), "NOTICE: process exit by signal %d\n", sig); + // record_log(err_str); + exit(0); +} + +/* + * 查看数据结构中是否有给定的网卡 + * 输入:网卡名称 + * 返回值:-1 表示没有 + * 非0值表示设备列表中的索引 + * + */ +int find_nic_config(char *dev_name){ + int i, index=-1; + + for(i=0; iname, myconf[13]) == 0) && (nicnum <= MAXNICNUM)){ + i = 1; + if(cmd->data.list[0] && cmd->data.list[1]){ + //查找设备列表中是否已有该网卡 + //如果没有则创建一项 + //如果已有则只要增加ping的地址和地址数量 + //一般都能找到,因为配置文件中一般总是先定义"nic",后定义"ping" + //如果没找到,则表明先定义了"ping",未定义"nic"或后定义"nic",而未定义"nic"应该是错误的 + index = find_nic_config(cmd->data.list[0]); + if(index == -1){ + strncpy(conf.nic[nicnum].dev_name, cmd->data.list[0], strlen(cmd->data.list[0]) >= IPLEN ? IPLEN-1 : strlen(cmd->data.list[0])); + card_info_index = nicnum; + nicnum++; + } + else + card_info_index = index; + + while(cmd->data.list[i]){ + if((int)(inet_addr(cmd->data.list[i])) == -1){ + sprintf(wrong_ip,"The wrong IP address:'%s'",cmd->data.list[i]); + strcat(wrong_ip,"\n"); + record_log(wrong_ip); + } else{ + strncpy(conf.nic[card_info_index].ping_ip[conf.nic[card_info_index].gw_num++], cmd->data.list[i], strlen(cmd->data.list[i]) >= IPLEN ? IPLEN-1 : strlen(cmd->data.list[i])); + } + i++; + } + } + } + + //"nic"选项的处理 + if((strcmp(cmd ->name, myconf[12]) == 0) && (nicnum <= MAXNICNUM)){ + //设备列表中没有给定的网卡设备,则添加一项 + //否则不必添加 + //对应配置文件中先指定"ping"后指定"nic"的情况 + index = find_nic_config(cmd->data.str); + if(index == -1){ + strncpy(conf.nic[nicnum].dev_name, cmd->data.str, strlen(cmd->data.str) >= NIC_NAME_LEN ? NIC_NAME_LEN-1 : strlen(cmd->data.str)); + nicnum++; + } + } + + if((strcmp(cmd ->name, myconf[11]) == 0)){ + strncpy(conf.udp, cmd->data.str, strlen(cmd->data.str)); + } + + return NULL; +} + +DOTCONF_CB(cb_int) +{ + if(strcmp(cmd ->name, myconf[0]) == 0){ + conf.domain = cmd->data.value; + } + if(strcmp(cmd ->name, myconf[1]) == 0){ + conf.serv = cmd->data.value; + } + if(strcmp(cmd ->name, myconf[2]) == 0){ + conf.event = cmd->data.value; + } + if(strcmp(cmd ->name, myconf[3]) == 0){ + conf.udpport = cmd->data.value; + } + if(strcmp(cmd ->name, myconf[6]) == 0){ + conf.monitor_interval = cmd->data.value; + } + if(strcmp(cmd ->name, myconf[7]) == 0){ + conf.write_interval = cmd->data.value; + } + if(strcmp(cmd ->name, myconf[8]) == 0){ + conf.flow_interval = cmd->data.value; + } + if(strcmp(cmd ->name, myconf[9]) == 0){ + conf.flow_limit = cmd->data.value; + } + if(strcmp(cmd ->name, myconf[10]) == 0){ + conf.flow_peak = cmd->data.value; + } + if(strcmp(cmd ->name, myconf[14]) == 0){ + conf.pingnum = cmd->data.value; + } + if(strcmp(cmd ->name, myconf[15]) == 0){ + conf.pinglap = cmd->data.value; + } + + return NULL; +} + +DOTCONF_CB(cb_list) +{ + return NULL; +} + +int get_conf() +{ + // int uid; + // char buf[1024]; + // int i; + // struct passwd *user; + configfile_t *configfile; + + // memset(buf, 0, sizeof(buf)); + // uid=getuid(); + // user = getpwnam("d5000"); + // user = getpwuid(uid); + + // sprintf(buf,"%s", user->pw_dir); + // strcat(buf,conf_path); + + configfile = dotconf_create(conf_path, options, NULL, CASE_INSENSITIVE); + if (!configfile) + { + record_log("Warning can't reading config file\n"); + return -1; + } + + if (dotconf_command_loop(configfile) == 0){ + record_log("Warning can't reading config file\n"); + return -1; + } + dotconf_cleanup(configfile); + + if(conf.domain == 0) + conf.domain = 10; + if(conf.serv == 0) + conf.serv = 1; + if(conf.event == 0) + conf.event = 2; + if(conf.udpport == 0) + conf.udpport = 15000; + if(conf.monitor_interval == 0) + conf.monitor_interval = 100; + if(conf.write_interval == 0) + conf.write_interval = 300; + if(conf.flow_interval == 0) + conf.flow_interval = 60; + if(conf.flow_limit == 0) + conf.flow_limit = 30; + if(conf.flow_peak == 0) + conf.flow_peak = 1000; + if(conf.udp[0] == 0) + strcpy(conf.udp, "bond0"); + if(conf.nic[0].dev_name[0] == 0) + strcpy(conf.nic[0].dev_name, "bond0"); + if(conf.pingnum == 0) + conf.pingnum = 2; + if(conf.pinglap == 0) + conf.pinglap = 1; + + return 0; +} + +int isrun(char *p) +{ + char buf[16]; + char cmdbuf[1024]; + FILE *fp; + + memset(buf, 0, sizeof(buf)); + memset(cmdbuf, 0, sizeof(cmdbuf)); + + snprintf(cmdbuf, sizeof(cmdbuf), "pidof %s", p); + fp=popen(cmdbuf, "r"); + fread(buf, sizeof(char), sizeof(buf), fp); + pclose(fp); + if(strchr(buf, ' ') != NULL) + return 1; + else + return 0; +} + +int get_broad_ip(void) +{ + char ip_p[4][4]; + char error_str[200]; + int skfd; + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + memset(ip_p, 0, sizeof(ip_p)); + + if((skfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)return -1; + strcpy(ifr.ifr_name, conf.udp); + if (!ioctl(skfd, SIOCGIFBRDADDR, &ifr)){ + sprintf(ip_p[0], "%d", (unsigned char)ifr.ifr_broadaddr.sa_data[2]); + sprintf(ip_p[1], "%d", (unsigned char)ifr.ifr_broadaddr.sa_data[3]); + sprintf(ip_p[2], "%d", (unsigned char)ifr.ifr_broadaddr.sa_data[4]); + sprintf(ip_p[3], "%d", (unsigned char)ifr.ifr_broadaddr.sa_data[5]); + }else{ + snprintf(error_str, sizeof(error_str), "EMERG: Invalid broadcast device -- %s\n", conf.udp); + record_log(error_str); + close(skfd); + return -1; + } + close(skfd); + strcat(conf.ip, ip_p[0]); + strcat(conf.ip, "."); + strcat(conf.ip, ip_p[1]); + strcat(conf.ip, "."); + strcat(conf.ip, ip_p[2]); + strcat(conf.ip, "."); + strcat(conf.ip, ip_p[3]); + + return 0; +} + +void create_dir(char *create_path) +{ + int i,len = strlen(create_path); + + len = strlen(create_path); + + for(i=1; inext; + while(curr != NULL){ + if(!strncmp(curr->name, conf.nic[i].dev_name, NIC_NAME_LEN)){ + if((node = (NET_NAME_ST *)malloc(sizeof(NET_NAME_ST))) == NULL){ + err_val = 1; + break; + } + memset(node->name, 0, NIC_NAME_LEN); + strncpy(node->name, conf.nic[i].dev_name, NIC_NAME_LEN); + node->next = opt_name_list->next; + opt_name_list->next = node; + count_t ++; + break; + } + curr = curr->next; + } + if(err_val)break; + } + if(count_t != i || err_val){ + for(curr = opt_name_list->next; curr != NULL; curr = curr->next)free(curr); + snprintf(error_str, sizeof(error_str), "EMERG: Invalid netcard name --\n"); + record_log(error_str); + return -1; + } + err_val = 0; + + return 0; +} + +int get_netcard_status(NETCARD_INFO_ST *listp) +{ + if((listp->info.flags & IFF_UP) != IFF_UP) + return NIC_DOWN; + + if((listp->info.flags & IFF_RUNNING) != IFF_RUNNING) + return NIC_UNRUNNING; + + //20100510 + if(elapsed_ping_time == total_ping_time){ + if(ping_gw(listp->info.charname) != 0) + return NIC_UNLINKABLE; + } + else{ + if(listp->status == NIC_UNLINKABLE) + return NIC_UNLINKABLE; + } + + return NIC_NORMAL; +} + +int do_alarm(NETCARD_INFO_ST *listp, int nic_status, D5000_NIC_ALARM *Malarm) +{ + int i; + char error_str[200]; + + memset(Malarm->tSysNetcardAlarm.fault_devname, 0, NIC_NAME_LEN); + strncpy(Malarm->tSysNetcardAlarm.fault_devname, host_name, host_name_size); + strncat(Malarm->tSysNetcardAlarm.fault_devname, "-", 1); + strncat(Malarm->tSysNetcardAlarm.fault_devname, listp->info.charname, NIC_NAME_LEN - host_name_size - 1); + Malarm->tSysNetcardAlarm.retrytimes = 0; + Malarm->tMsgFrame.len = sizeof(Malarm); + Malarm->tMsgFrame.seqno = seqno; + + switch(nic_status){ + case NIC_DOWN: + Malarm->tSysNetcardAlarm.flags = NETCARD_ALARM_FAULT; + snprintf(error_str, sizeof(error_str), "NOTICE: %s is DOWN!\n", listp->info.charname); + break; + case NIC_UNRUNNING: + Malarm->tSysNetcardAlarm.flags = NETCARD_ALARM_FAULT; + snprintf(error_str, sizeof(error_str), "NOTICE: %s is UP but UNRUNNING!\n", listp->info.charname); + break; + case NIC_UNLINKABLE: + Malarm->tSysNetcardAlarm.flags = NETCARD_ALARM_FAULT; + listp->info.flags &= (~IFF_UP); + listp->info.flags &= (~IFF_RUNNING); + snprintf(error_str, sizeof(error_str), "NOTICE: %s is RUNNING but UNLINKABLE!\n", listp->info.charname); + break; + case NIC_NORMAL: + Malarm->tSysNetcardAlarm.flags = NETCARD_ALARM_RESUME; + snprintf(error_str, sizeof(error_str), "NOTICE: %s is NORMAL!\n", listp->info.charname); + break; + } + pthread_mutex_lock(&mut); + for(i = 0; i < 3; i++){ + send_alarm(Malarm, conf.udpport, conf.ip); + seqno++; + Malarm->tMsgFrame.seqno = seqno; + Malarm->tSysNetcardAlarm.retrytimes++; + } + send_inc_info_one(&listp->info, semid, shm_ptr); + pthread_mutex_unlock(&mut); + record_log(error_str); + + return 0; +} + +int main(int argc, char ** argv) +{ + int ret = 0, proc_stat = 0; + unsigned int i = 0; + int nic_status; + int sys_time_stamp = 0; + char *retp = NULL; + char *str = NULL; + char bond[128]; + char error_str[200]; + char linebuf[LINE_SIZE]; + THENV *arg; + glob_t res; + FILE *bond_fp = NULL; + pthread_t tid[THRNR]; + pthread_t tid_mem; + pthread_t tid_flow; + pthread_t tid_time; + THMEM mem; + THFLOW flow; + struct timespec s_time, os_time, log_time; + NET_NAME_ST all_name_list, opt_name_list; + NETCARD_INFO_ST inc_info_list, *listp = NULL; + D5000_NIC_ALARM Malarm; + struct sigaction sig; + struct passwd *user; + proc_invocation prcm; + + char log_record[125]={0}; + + memset(&conf, 0, sizeof(CONFIG_FILE_ST)); + if(isrun(argv[0]) == 1){ + printf("the program is already started!\n"); + exit(0); + } + //process register +#if 1 + if((proc_stat=prcm.proc_init("sys","base_srv","sys_nicmonitor"))==-1){ + perror("proc_init()"); + exit(-1); + } +#endif + + sig.sa_handler = sig_handler; + sigemptyset(&sig.sa_mask); + sigaddset(&sig.sa_mask, SIGINT); + sigaddset(&sig.sa_mask, SIGTERM); + sig.sa_flags = 0; + sigaction(SIGTERM, &sig, NULL); + sigaction(SIGINT, &sig, NULL); + sigaction(SIGSEGV, &sig, NULL); + + /* create dir file path */ + if((user = getpwnam("d5000")) != NULL){ + sprintf(log_path,"%s",user->pw_dir); + sprintf(shm_path,"%s",user->pw_dir); + sprintf(sem_path,"%s",user->pw_dir); + sprintf(conf_path,"%s",user->pw_dir); + } + + strcat(log_path,LOG_PATH); + strcat(shm_path,SHM_PATH); + strcat(sem_path,SEM_PATH); + strcat(conf_path,CONF_FILE); + + create_semdir(); + create_shmdir(); + create_logdir(); + create_confdir(); + + /* get process name */ + memset(process_name, 0, sizeof(process_name)); + if((retp = strrchr(argv[0], '/')) != NULL){ + retp++; + strcpy(process_name, retp); + }else{ + strcpy(process_name, argv[0]); + } + /*create logfile thread */ + pthread_create(&tid_time, NULL, create_logfile, NULL); + + /* initialize some....*/ + memset(&all_name_list, 0, sizeof(NET_NAME_ST)); + all_name_list.next = NULL; + memset(&opt_name_list, 0, sizeof(NET_NAME_ST)); + opt_name_list.next = NULL; + + memset(&inc_info_list, 0, sizeof(NETCARD_INFO_ST)); + inc_info_list.next = NULL; + + + /* get all netcard by proc/net/dev and ioctl */ + get_all_name(&all_name_list); + + /* wait for create log thread */ + log_time.tv_sec = 0; + log_time.tv_nsec = 1000000; + while(log_flag)nanosleep(&log_time, NULL); + + /* sure the process is started */ + snprintf(error_str, sizeof(error_str), "NOTICE: %s V%s is started !\n", process_name, MNIC_VERSION); + record_log(error_str); + + get_conf(); + + if(shm_path){ + printf("shm_path:%s\n",shm_path); + sprintf(log_record,"shm_path:%s\n",shm_path); + record_log(log_record); + } + + if(log_path){ + printf("log_path:%s\n",log_path); + sprintf(log_record,"log_path:%s\n",log_path); + record_log(log_record); + } + + + if(conf.udp){ + printf("udp %s\n",conf.udp); + sprintf(log_record,"udp %s\n",conf.udp); + record_log(log_record); + } + + for(i=0;conf.nic[i].dev_name[0]!=0;i++){ + printf("nic %s\n",conf.nic[i].dev_name); + sprintf(log_record,"nic %s\n",conf.nic[i].dev_name); + record_log(log_record); + } + + /* get broadcast address*/ + if((ret = get_broad_ip()) != 0) + return -1; + if((ret = create_name_list(&all_name_list, &opt_name_list)) != 0) + return -1; + /* get hostname */ + if((ret = gethostname(host_name, sizeof(host_name))) != -1){ + host_name_size = strlen(host_name); + }else host_name_size = HOST_NAME_SIZE; + /* initialize Malarm */ + Malarm.tMsgFrame.serv = conf.serv; + Malarm.tMsgFrame.event = conf.event; + Malarm.tMsgFrame.domain = conf.domain; + + /* get bonding file */ + memset(bond, 0, sizeof(bond)); + memset(linebuf, 0, sizeof(linebuf)); + if((ret = glob(BOND_PATH, 0, NULL, &res)) != 0){ + snprintf(error_str, sizeof(error_str), "NOTICE: No bonding netcard !\n"); + record_log(error_str); + strcpy(bond, "No bonding netcard!"); + } + for (i = 0; i < res.gl_pathc; ++i) { + if((arg = (THENV *)malloc(sizeof(THENV))) != NULL){ + memset(arg, 0, sizeof(THENV)); + strncpy(arg->bond_file_path, res.gl_pathv[i], strlen(res.gl_pathv[i])); + arg->Malarm = Malarm; + strncpy(arg->host_name, host_name, host_name_size); + arg->host_name_size = host_name_size; + arg->conf = &conf; + if(pthread_create(tid+i, NULL, check_inc_switch, (void*)arg)){ + snprintf(error_str, sizeof(error_str), "EMERG: pthread_create(): %s\n", strerror(errno)); + record_log(error_str); + } + } + } + for(i = 0; i < res.gl_pathc; ++i){ + if((bond_fp = fopen(res.gl_pathv[i], "r")) == NULL){ + snprintf(error_str, sizeof(error_str), "EMERG: fopen(): %s\n", strerror(errno)); + record_log(error_str); + }else{ + retp = strrchr(res.gl_pathv[i], '/'); + retp++; + strcat(bond, retp); + strcat(bond, ":"); + while((str = fgets(linebuf, sizeof(linebuf), bond_fp)) != NULL){ + if(!strncmp(linebuf, "Slave Interface:", 16)){ + str += 16; + retp = parse_str(&str); + strcat(bond, retp); + strcat(bond, " "); + } + } + fclose(bond_fp); + } + } + + /* initialize time*/ + s_time.tv_sec = 0; + s_time.tv_nsec = conf.monitor_interval*1000*1000; + + /* initialize sem*/ + init_sem(&semid, &conf); + init_shm(&shm_ptr, &conf); + /* for IPC_RMID */ + sem_id = semid; + + /* create monitor netcard list */ + create_monit_list(&opt_name_list, &inc_info_list, bond); + release_name_list(&all_name_list); + release_name_list(&opt_name_list); + + mem.semid = semid; + mem.shm_ptr = shm_ptr; + mem.listp = &inc_info_list; + mem.conf = &conf; + if(pthread_create(&tid_mem, NULL, send_inc_info, (void *)&mem)){ + snprintf(error_str, sizeof(error_str), "EMERG: pthread_create(): %s\n", strerror(errno)); + record_log(error_str); + } + + /* create caculate flow thread*/ + flow.env.Malarm = Malarm; + strncpy(flow.env.host_name, host_name, host_name_size); + flow.env.host_name_size = host_name_size; + flow.mem.semid = semid; + flow.mem.shm_ptr = shm_ptr; + flow.mem.listp = &inc_info_list; + flow.mem.conf = &conf; + if(pthread_create(&tid_flow, NULL, cacu_flow, (void *)&flow)){ + snprintf(error_str, sizeof(error_str), "EMERG: pthread_create(): %s\n", strerror(errno)); + record_log(error_str); + } + + total_ping_time = 1000 / conf.monitor_interval; + if(total_ping_time == 0) + total_ping_time = 1; + elapsed_ping_time = 1; + + while(1){ + i = 0; + listp = inc_info_list.next; + for(i = 0; listp != NULL; i++){ + get_inc_info(&listp->info); + get_inc_stats(&listp->info); + nic_status = get_netcard_status(listp); + if(nic_status != listp->status){ + do_alarm(listp, nic_status, &Malarm); + listp->status = nic_status; + } + listp = listp->next; + } + + if(seqno > 32765)seqno = 0; + nanosleep(&s_time, &os_time); + + + //20100510 + ++elapsed_ping_time; + if(elapsed_ping_time > total_ping_time) + elapsed_ping_time = 1; + + sys_time_stamp += conf.monitor_interval; + if(sys_time_stamp >= 1000){ + sys_time_stamp = 0; + write_time(semid, shm_ptr); + } + } + for (i = 0; i < res.gl_pathc; i++) { + pthread_join(tid[i], NULL); + } + pthread_join(tid_mem, NULL); + pthread_join(tid_flow, NULL); + pthread_join(tid_time, NULL); + pthread_mutex_destroy(&mut); + globfree(&res); + munmap(shm_ptr, sizeof(SHM)); + return 0; +} diff --git a/code/tags/sys_nicmonitor-1.7/mnic.h b/code/tags/sys_nicmonitor-1.7/mnic.h new file mode 100644 index 0000000..d7a6390 --- /dev/null +++ b/code/tags/sys_nicmonitor-1.7/mnic.h @@ -0,0 +1,44 @@ +#ifndef __MNIC_H +#define __MNIC_H + +//#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys_netcard.h" +#include +#include +#define IPSIZE 16 + +char *get_name(char *, char *); +int if_fetch(NETCARD_INFO *); +int ioc_get_name(NETCARD_INFO *); +int get_dev_fields(char *p, NETCARD_INFO *); +int get_user_home(int , char *); +void send_alarm(D5000_NIC_ALARM *, int , char *); +void record_log(char *); + +#endif diff --git a/code/tags/sys_nicmonitor-1.7/nicinfo_shm.c b/code/tags/sys_nicmonitor-1.7/nicinfo_shm.c new file mode 100644 index 0000000..7363568 --- /dev/null +++ b/code/tags/sys_nicmonitor-1.7/nicinfo_shm.c @@ -0,0 +1,209 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nicinfo_shm.h" + +#define SHM_PATH "/share/sys_netcard_shm_path" +#define SEM_PATH "/share/sys_netcard_sem_path" +#define LOG_PATH "/var/log/netcard/" + +typedef struct net_info{ + NETCARD_INFO info[MAXNICNUM]; +}SHM; + +static int semid = 0; +static char log_path[1024]; +static char shm_path[1024]; +static char sem_path[1024]; +SHM *ptr = NULL; + +/* write error in logfile */ +void record_log(char *str) +{ + time_t tamp; + char str_tm[4]; + char log_str[512]; + FILE *log_fp = NULL; + struct tm tmptr; + struct timeval tv; + struct timezone tz; + + if((log_fp = fopen(log_path, "a")) != NULL){ + tamp = time(NULL); + memset(str_tm, 0, sizeof(str_tm)); + memset(log_str, 0, sizeof(log_str)); + localtime_r(&tamp, &tmptr); + gettimeofday(&tv, &tz); + snprintf(str_tm, sizeof(str_tm), "%d", (int)tv.tv_usec/1000); + if(str_tm[1] == '\0')str_tm[1] = '0'; + if(str_tm[2] == '\0')str_tm[2] = '0'; + strftime(log_str, sizeof(log_str), "%F %T.", &tmptr); + strcat(log_str, str_tm); + strcat(log_str, " "); + strcat(log_str, "get_nic_info"); + strcat(log_str, " "); + strcat(log_str, str); + if(fwrite(log_str, 1, strlen(log_str), log_fp) < 1){ + } + fclose(log_fp); + } +} + +void get_sem(int semid) +{ + char err_str[200]; + struct sembuf lock[2]; + + lock[0].sem_num = 0; + lock[0].sem_op = 0; + lock[0].sem_flg = SEM_UNDO; + + lock[1].sem_num = 0; + lock[1].sem_op = 1; + lock[1].sem_flg = SEM_UNDO; + + while(semop(semid, lock, 2)){ + if (errno == EINTR) { + continue; + } + snprintf(err_str, sizeof(err_str), "EMERG: semop():\n", strerror(errno)); + record_log(err_str); + return; + } +} + +void release_sem(int semid) +{ + int ret; + char err_str[200]; + struct sembuf unlock; + + unlock.sem_num = 0; + unlock.sem_op = -1; + unlock.sem_flg = SEM_UNDO; + + if((ret = semop(semid, &unlock, 1)) == -1){ + snprintf(err_str, sizeof(err_str), "EMERG: semop():\n", strerror(errno)); + record_log(err_str); + return; + } +} + + +int init_nic_info(void) +{ + int fd = -1; + int sem_val; + char err_str[200]; + key_t key; + + + if ((key=ftok(sem_path, SEM_PROJ_ID)) == -1) { + snprintf(err_str, sizeof(err_str), "EMERG: ftok():%s\n", strerror(errno)); + record_log(err_str); + return -1; + } + if((semid = semget(key, 1, IPC_CREAT|0666)) == -1){ + snprintf(err_str, sizeof(err_str), "EMERG: Create semaphore error: %s\n", strerror(errno)); + record_log(err_str); + return -1; + } + /* + if((sem_val = semctl(semid, 0, GETVAL, 0)) == -1){ + snprintf(err_str, sizeof(err_str), "EMERG: semctl: %s !\n", strerror(errno)); + record_log(err_str); + semctl(semid, 0, IPC_RMID); + return -1; + } + if(!sem_val){ + if(semctl(semid, 0, SETVAL, 1) == -1){ + snprintf(err_str, sizeof(err_str), "EMERG: semctl: %s !\n", strerror(errno)); + record_log(err_str); + semctl(semid, 0, IPC_RMID); + return -1; + } + } + */ + if((fd = open(shm_path, O_RDONLY)) == -1){ + snprintf(err_str, sizeof(err_str), "EMERG: Error open %s: %s!\n",shm_path, strerror(errno)); + record_log(err_str); + return -1; + } + ptr = (SHM*)mmap(NULL, sizeof(SHM), PROT_READ, MAP_SHARED, fd, 0); + if(ptr == MAP_FAILED){ + snprintf(err_str, sizeof(err_str), "EMERG: mmap():%s\n", strerror(errno)); + record_log(err_str); + return -1; + } + close(fd); + + return 0; +} +int get_nic_info(char *nic_name, NETCARD_INFO *net_info) +{ + int i,ret; + time_t tamp; + struct tm tmptr; + DIR *dir; + char *s; + char buf[128]; + char err_str[200]; + struct passwd *user; + + tamp = time(NULL); + localtime_r(&tamp, &tmptr); + + if((user = getpwnam("d5000"))!= NULL){ + sprintf(log_path,"%s",user->pw_dir); + sprintf(shm_path,"%s",user->pw_dir); + sprintf(sem_path,"%s",user->pw_dir); + } + strcat(log_path,LOG_PATH); + strcat(shm_path,SHM_PATH); + strcat(sem_path,SEM_PATH); + + if((dir = opendir(log_path)) == NULL){ + if(errno == ENOENT){ + strcpy(log_path, "/tmp/"); + } + } + closedir(dir); + s = strrchr(log_path, '/'); + s++; + *s = '\0'; + memset(buf, 0, sizeof(buf)); + strftime(buf, sizeof(buf), "%Y%m%d_", &tmptr); + strcat(buf, "sys_nicmonitor"); + strcat(buf, ".log"); + strcat(log_path, buf); + if((ret = init_nic_info()) == -1){ + return -1; + } + get_sem(semid); + for(i = 0; ptr->info[i].charname[0] != 0; i++){ + if(!strcmp(ptr->info[i].charname, nic_name)){ + // get_sem(semid); + memcpy(net_info, &ptr->info[i], sizeof(NETCARD_INFO)); + release_sem(semid); + munmap(ptr, sizeof(SHM)); + return 0; + } + } + release_sem(semid); + snprintf(err_str, sizeof(err_str), "NOTICE: No information of %s !\n", nic_name); + record_log(err_str); + munmap(ptr, sizeof(SHM)); + return -1; +} diff --git a/code/tags/sys_nicmonitor-1.7/nicinfo_shm.h b/code/tags/sys_nicmonitor-1.7/nicinfo_shm.h new file mode 100644 index 0000000..cd74135 --- /dev/null +++ b/code/tags/sys_nicmonitor-1.7/nicinfo_shm.h @@ -0,0 +1,52 @@ +#ifndef NIC_SHM_H +#define NIC_SHM_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NIC_NAME_LEN +#define NIC_NAME_LEN 64 +#endif +#define SEM_PROJ_ID 's' +#define MAXNICNUM 32 + +typedef long KEYID; +typedef struct _net_info +{ + KEYID ID; + char charname[NIC_NAME_LEN]; + char descr[128]; + struct sockaddr addr; + struct sockaddr broadaddr; + struct sockaddr netmask; + struct sockaddr hwaddr; + int time_stamp; + short flags; + int mtu; + int tx_queue_len; + unsigned long long average_flow; + unsigned long long rx_packets; + unsigned long long tx_packets; + unsigned long long rx_bytes; + unsigned long long tx_bytes; + unsigned long rx_errors; + unsigned long tx_errors; + unsigned long rx_dropped; + unsigned long tx_dropped; + unsigned long rx_multicast; + unsigned long collisions; + unsigned long rx_fifo_errors; + unsigned long tx_carrier_errors; + unsigned long tx_fifo_errors; +}NETCARD_INFO; + +int get_nic_info(char *nic_name, NETCARD_INFO *net_info); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/code/tags/sys_nicmonitor-1.7/proc_inv.h b/code/tags/sys_nicmonitor-1.7/proc_inv.h new file mode 100644 index 0000000..945622c --- /dev/null +++ b/code/tags/sys_nicmonitor-1.7/proc_inv.h @@ -0,0 +1,198 @@ +//////////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) Comets' Grp. of Kedong Corp 2008. All Rights Reserved. +// +// FileName : procconf.h +// +// Function : this class realize some basic functions for process managerment, +// such as initiate process, report status of process, check status of process, +// update status of process, get information of process +// +// Author : +// +// Date : +// +// Modify by : +// +// Mod Date : +// +//////////////////////////////////////////////////////////////////////////////////// + +#ifndef _PROCCONF_H +#define _PROCCONF_H + +#include +#include +#include +#include +#include +#include +#include +//#include +#include + +#include "const.h" + +//for alarm ................................ +typedef struct MESS_BH +{ + unsigned char mtype; + int length; +}; +typedef struct PROCESS_ALM +{ + char context_name[MAX_STRING_LEN]; + char app_name[MAX_STRING_LEN]; + char proc_name[MAX_STRING_LEN]; + unsigned char status; +}; +//for alarm end ............................. + +//for mmi.................................... +const int MAX_BUFFER_LEN = 500; +typedef struct MESS_BLOCK +{ + unsigned char num; + char buffer[MAX_BUFFER_LEN]; +}; +typedef struct MESS_PROC +{ + char context_name[MAX_STRING_LEN]; + char app_name[MAX_STRING_LEN]; + char proc_name[MAX_STRING_LEN]; + char status; +}; +//for mmi end ................................ + +const int DEFAULT_PERIOD = 3; +const int COUNT_LIMIT = 2; +const int START_DEFAULT_PERIOD = 60; +const int START_COUNT_LIMIT = 5; +const int APP_COUNT_LIMIT = 1; + +//process critical level +//const int WST_CRITICAL = 1; // Shutdown and reboot workstation when failed +//const int SYS_CRITICAL = 2; // Shutdown and reboot the system on the wst when failed +//const int USER_CRITICAL = 3; // Shutdown and reboot the subsystem when failed +//const int GENERAL = 4; // reboot the process +const int CRUCIAL = 1; // crucial process +const int GENERAL = 0; // general process + + +extern int srv_init(char *service,int port); +extern int Tcp_close(int sockfd); +extern int Tcp_read(int fd,char *ptr,int nbytes); +extern int Tcp_write(int fd,char *ptr,int nbytes); +extern int srv_accept(int fd,struct sockaddr *cli_addr,int *clilen); +extern int client_tcp_open(char *host,char *service,int port); + +typedef struct +{ + char context_name[MAX_STRING_LEN]; + char app_name[MAX_STRING_LEN]; + char proc_name[MAX_STRING_LEN]; + pid_t proc_pid; +}PROC_ADM_INFO; + +//*************************************************************** +// structure name : PROC_INFO +// function : store process informatin +// author : +// date : +// modify by : +// modification : +// mod date : +//*************************************************************** +typedef struct +{ + int position; + char node_name[MAX_STRING_LEN]; + char context_name[MAX_STRING_LEN]; + char app_name[MAX_STRING_LEN]; + char proc_name[MAX_STRING_LEN]; + + unsigned char active_flag; + unsigned char master_flag; + + time_t startup_time; + time_t refresh_time; + short refresh_peri; + unsigned char monitor_type; + + pid_t proc_pid; + unsigned char auto_start; + unsigned char act_timer; + unsigned char start_timer; + unsigned char critical_level; + + char exefile_path[MAX_EXECMD_LEN]; + +}PROC_INFO; + +//*************************************************************** +// structure name : APP_INFO +// function : store application informatin +// author : +// date : +// modify by : +// modification : +// mod date : +//*************************************************************** +typedef struct +{ + int position; + char context_name[MAX_STRING_LEN]; + int context_id; + char app_name[MAX_STRING_LEN]; + int app_id; + unsigned char act_timer; + unsigned char active_flag; +}APP_INFO; + + +typedef struct +{ + int no_proc; + int semdes_cfg; + PROC_INFO proc[MAX_LOCAL_PROCESS]; + APP_INFO app[MAX_LOCAL_APP]; +}PROCCFG; + +class proc_invocation +{ + public: + int m_init; + PROCCFG *proccfg_p; + + public: + proc_invocation(); + ~proc_invocation(); + + int conf_create(); + //int check_proc_status(); + //int update_rtdb(); + //int kill_proc(pid_t pid); + //int start_proc(char *cmdline); + //int send_alarm(char *context_name, char *app_name, char *proc_name, unsigned char status); + //int update_proc_status(char *context_name, char *app_name, char *proc_name, char status); + + //int proc_init(char *context_name, char *app_name, char *proc_name, int critical_level);//exefile_path,auto_start + int proc_init(char *context_name, char *app_name, char *proc_name); + int proc_report(int pos, char status, int intertime=3); + int proc_exit(int proc_pos); + + int get_pos(char *context_name, char *app_name, char *proc_name); + int is_proc_exist(char *context_name, char *app_name, char *proc_name); + int conf_map(); + + int get_procinfo(int position, PROC_ADM_INFO *p_info); + int get_active_pid(int &num, int *p_pidlist); + int is_proc_run(pid_t pid); + int is_proc_run(char *context_name, char *app_name, char *proc_name); + +}; + +#endif + + + diff --git a/code/tags/sys_nicmonitor-1.7/read_netcard.c b/code/tags/sys_nicmonitor-1.7/read_netcard.c new file mode 100644 index 0000000..c745f48 --- /dev/null +++ b/code/tags/sys_nicmonitor-1.7/read_netcard.c @@ -0,0 +1,133 @@ +#include "mnic.h" + +static char *prase_digit(char **s) +{ + char *retp = NULL; + char *p = *s; + + if(!p)return NULL; + while(!isdigit(*p)){ + p++; + if(*p == '\0')return NULL; + } + retp = p; + while(isdigit(*p)){ + p++; + if(*p == '\0'){ + *s = NULL; + return retp; + } + } + *p = '\0'; + p++; + *s = p; + return retp; +} + + +char *get_name(char *name, char *p) +{ + while (isspace(*p)) + p++; + while (*p) { + if (isspace(*p)) + break; + if (*p == ':') { /* could be an alias */ + char *dot = p, *dotname = name; + *name++ = *p++; + while (isdigit(*p)) + *name++ = *p++; + if (*p != ':') { /* it wasn't, backup */ + p = dot; + name = dotname; + } + if (*p == '\0') + return NULL; + p++; + break; + } + *name++ = *p++; + } + *name++ = '\0'; + return p; +} + +int get_dev_fields(char *str, NETCARD_INFO *ife) +{ + int i = 0; + char *retp[16]; + + while((retp[i] = prase_digit(&str)) != NULL){i++;if(i > 15)break;} + ife->rx_bytes = atoll(retp[0]); + ife->rx_packets = atoll(retp[1]); + ife->rx_errors = atol(retp[2]); + ife->rx_dropped = atol(retp[3]); + ife->rx_fifo_errors = atol(retp[4]); + ife->rx_multicast = atol(retp[7]); + ife->tx_bytes = atoll(retp[8]); + ife->tx_packets = atoll(retp[9]); + ife->tx_errors = atol(retp[10]); + ife->tx_dropped = atol(retp[11]); + ife->tx_fifo_errors = atol(retp[12]); + ife->collisions = atol(retp[13]); + ife->tx_carrier_errors = atol(retp[14]); + return 0; +} + +int if_fetch(NETCARD_INFO *ife) +{ + int skfd; + struct ifreq ifr; + + if((skfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)return -1; + + strcpy(ifr.ifr_name, ife->charname); + if (!ioctl(skfd, SIOCGIFFLAGS, &ifr)) + ife->flags = ifr.ifr_flags; + + if (!ioctl(skfd, SIOCGIFHWADDR, &ifr)) + ife->hwaddr = ifr.ifr_hwaddr; + + if (!ioctl(skfd, SIOCGIFMTU, &ifr)) + ife->mtu = ifr.ifr_mtu; + + if (!ioctl(skfd, SIOCGIFTXQLEN, &ifr)) + ife->tx_queue_len = ifr.ifr_qlen; + + if (!ioctl(skfd, SIOCGIFADDR, &ifr)) + ife->addr = ifr.ifr_addr; + + if (!ioctl(skfd, SIOCGIFBRDADDR, &ifr)) + ife->broadaddr = ifr.ifr_broadaddr; + + if (!ioctl(skfd, SIOCGIFNETMASK, &ifr)) + ife->netmask = ifr.ifr_netmask; + + ife->time_stamp = time(NULL); + close(skfd); + return 0; +} + + +int ioc_get_name(NETCARD_INFO *name) +{ + int skfd; + int ifrnum; + int i = 0; + struct ifconf ifc; + struct ifreq buf[MAXNICNUM]; + + if((skfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)return -1; + memset(buf, 0, sizeof(buf)); + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = (caddr_t) buf; + ioctl(skfd, SIOCGIFCONF, &ifc); + ifrnum = ifc.ifc_len / sizeof(struct ifreq); + while(ifrnum-- > 0){ + strcpy(name[i].charname, buf[ifrnum].ifr_name); + i++; + } + close(skfd); + return i; +} + diff --git a/code/tags/sys_nicmonitor-1.7/send_alarm.c b/code/tags/sys_nicmonitor-1.7/send_alarm.c new file mode 100644 index 0000000..e88635f --- /dev/null +++ b/code/tags/sys_nicmonitor-1.7/send_alarm.c @@ -0,0 +1,37 @@ +#include "mnic.h" + +void send_alarm(D5000_NIC_ALARM *mesg, int socket_port, char *ipv4) +{ + int bytes; + int sock_sd; + int val; + char error_str[200]; + struct sockaddr_in recever; + socklen_t sock_len; + + if((sock_sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){ + snprintf(error_str, sizeof(error_str), "EMERG: socket(): %s\n", strerror(errno)); + record_log(error_str); + return; + } + val=1; + if ((setsockopt(sock_sd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val))) == -1) { + snprintf(error_str, sizeof(error_str), "EMERG: setsockopt(): %s\n", strerror(errno)); + record_log(error_str); + return; + } + /* init socket*/ + recever.sin_family = AF_INET; + recever.sin_port = htons(socket_port); + inet_pton(AF_INET, ipv4, &recever.sin_addr); + sock_len = sizeof(recever); + /* send alarm*/ + if((bytes = sendto(sock_sd, mesg, sizeof(D5000_NIC_ALARM), 0, (const struct sockaddr *)&recever, sock_len)) < 1){ + snprintf(error_str, sizeof(error_str), "EMERG: sendto(): %s\n", strerror(errno)); + record_log(error_str); + return; + } + //snprintf(error_str, sizeof(error_str), "NOTICE: Alarm information has already send!\n"); + //record_log(error_str); + close(sock_sd); +} diff --git a/code/tags/sys_nicmonitor-1.7/sys_netcard.h b/code/tags/sys_nicmonitor-1.7/sys_netcard.h new file mode 100644 index 0000000..0d7746c --- /dev/null +++ b/code/tags/sys_nicmonitor-1.7/sys_netcard.h @@ -0,0 +1,88 @@ +#ifndef _SYS_NETCARD_H +#define _SYS_NETCARD_H + +#include + +#ifndef NIC_NAME_LEN +#define NIC_NAME_LEN 64 +#endif + +#define SEM_PROJ_ID 's' +#define MAXNICNUM 32 + +#ifdef __cplusplus +extern "C"{ +#endif + +typedef long KEYID; + +typedef struct _msg_frame // message frame +{ + short len; // message length + short seqno; // send sequence + short serv; // services ID + short event; // event ID + unsigned char domain; // domain ID + unsigned char ctxt; // Context ID + short stid; // SOURCE task id + short dtid; // DESTINATION task ID + unsigned char ver_coding; // 版本号 + 编码 + unsigned char mes_type; // 帧类型 +}MSG_FRAME, *LPMSG_FRAME; + +typedef struct _net_info +{ + KEYID ID; + char charname[NIC_NAME_LEN]; + char descr[128]; + struct sockaddr addr; + struct sockaddr broadaddr; + struct sockaddr netmask; + struct sockaddr hwaddr; + int time_stamp; + short flags; + int mtu; + int tx_queue_len; + unsigned long long average_flow; + unsigned long long rx_packets; + unsigned long long tx_packets; + unsigned long long rx_bytes; + unsigned long long tx_bytes; + unsigned long rx_errors; + unsigned long tx_errors; + unsigned long rx_dropped; + unsigned long tx_dropped; + unsigned long rx_multicast; + unsigned long collisions; + unsigned long rx_fifo_errors; + unsigned long tx_carrier_errors; + unsigned long tx_fifo_errors; +}NETCARD_INFO, *LPNETCARD_INFO; + +#define NETCARD_ALARM_FAULT 1 +#define NETCARD_ALARM_RESUME 2 +#define NETCARD_ALARM_SWITCH 3 +#define NETCARD_ALARM_ABNORMAL 4 +#define NETCARD_ALARM_NORMAL 5 +typedef struct _sys_netcard_alarm +{ + char fault_devname[NIC_NAME_LEN]; /*故障设备名称 */ + char switch_devname[NIC_NAME_LEN]; /*切换设备名称 */ + short flags; /* 状态标记 : 1:网卡故障。2:网卡恢复。3:网卡切换。4:流量异常。*/ + short retrytimes; //0,1,2 重发次数 +}SYS_NETCARD_ALARM, *LPSYS_NETCARD_ALARM; + + +typedef struct _d5000_nic_alarm +{ + MSG_FRAME tMsgFrame ; + SYS_NETCARD_ALARM tSysNetcardAlarm ; +}D5000_NIC_ALARM, *LPD5000_NIC_ALARM; + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/packages/sys_nicmonitor#1.7-x86_64-linx-Rocky4.2.pkg.tar.gz b/packages/sys_nicmonitor#1.7-x86_64-linx-Rocky4.2.pkg.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..8dcc222b3b0c8952e1dc0eee15b0fb8a1e88ff9f GIT binary patch literal 18551 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 literal 0 HcmV?d00001