├── Makefile ├── README.md ├── ac ├── Makefile ├── aphash.c ├── aphash.h ├── main.c ├── net.c ├── net.h ├── process.c ├── process.h ├── resource.c ├── resource.h ├── sql.c └── sql.h ├── ap ├── Makefile ├── apstatus.c ├── main.c ├── message.c ├── message.h ├── net.c ├── net.h ├── process.c └── process.h ├── include ├── apstatus.h ├── arg.h ├── chap.h ├── dllayer.h ├── link.h ├── list.h ├── log.h ├── md5.h ├── mjson.h ├── msg.h ├── netlayer.h └── thread.h ├── lib ├── Makefile ├── arg.c ├── cfgarg.c ├── chap.c ├── cmdarg.c ├── dllayer.c ├── link.c ├── md5.c ├── mjson.c ├── netlayer.c └── thread.c ├── scripts ├── Kbuild.include └── ac.sql └── test ├── Makefile ├── dllcli.c └── dllser.c /Makefile: -------------------------------------------------------------------------------- 1 | TOPDIR = $(CURDIR) 2 | SCRIPT_DIR = $(TOPDIR)/scripts 3 | export TOPDIR 4 | 5 | ifeq ("$(origin V)", "command line") 6 | BUILD_VERBOSE = $(V) 7 | endif 8 | ifndef BUILD_VERBOSE 9 | BUILD_VERBOSE = 0 10 | endif 11 | ifeq ($(BUILD_VERBOSE),1) 12 | quiet = 13 | Q = 14 | else 15 | quiet=quiet_ 16 | Q = @ 17 | MAKEFLAGS += --no-print-directory 18 | endif 19 | 20 | ifneq ($(findstring s,$(MAKEFLAGS)),) 21 | quiet=silent_ 22 | endif 23 | export quiet Q BUILD_VERBOSE 24 | 25 | echo := : 26 | quiet_echo := echo 27 | silent_echo := : 28 | echo := $($(quiet)echo) 29 | include $(SCRIPT_DIR)/Kbuild.include 30 | 31 | 32 | # gnu utils 33 | CC = gcc 34 | LD = ld 35 | AR = ar 36 | INSTALL = install 37 | 38 | # cross utils 39 | TARGET= 40 | 41 | export CC LD AR INSTALL TARGET 42 | 43 | INC = -I$(TOPDIR)/include 44 | CFLAGS = -Wall -Wno-unused-function -O0 $(INC) 45 | CFLAGS += -g -DDEBUG 46 | LDFLAGS = -lpthread 47 | CFLAGS+=$(shell mysql_config --cflags) 48 | LDFLAGS+=$(shell mysql_config --libs) 49 | export CFLAGS LDFLAGS 50 | 51 | all:acser apcli test 52 | 53 | 54 | LIB = libapctl.o 55 | LIBDIR = $(TOPDIR)/lib 56 | export LIB LIBDIR 57 | 58 | ACDIR = $(TOPDIR)/ac 59 | acser: 60 | @$(MAKE) -C $(ACDIR) 61 | 62 | APDIR = $(TOPDIR)/ap 63 | apcli: 64 | @$(MAKE) -C $(APDIR) 65 | 66 | TESTDIR = $(TOPDIR)/test 67 | test: FORCE 68 | @$(MAKE) -C $(TESTDIR) 69 | 70 | tags: FORCE 71 | @find . -name "*.h" -o -name "*.c" -o -name "*.s" > cscope.files 72 | @cscope -bkq -i cscope.files 73 | @ctags -L cscope.files 74 | 75 | clean: 76 | @rm -rf `find . -name "*.o"` $(ACDIR)/acser $(APDIR)/apctl 77 | @rm -rf `find . -name "*.so"` 78 | @rm -rf $(TESTDIR)/dllser $(TESTDIR)/dllcli 79 | @rm -rf cscope* tags 80 | FORCE: 81 | 82 | PHONY += deps clean FORCE 83 | .PHONY: $(PHONY) 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 简介 2 | ======= 3 | 4 | Openwrt ac 控制器(acctl), 包含服务端和客户端两大块。支持以下特性: 5 | 6 | * 同一网段,二层发现,自动配置ip 7 | * 自动二层/三层发送控制信息 8 | * 二层主动探测网络中ap,可接管其他ac控制ap 9 | * 客户端主动链接,并保持长链接 10 | 11 | 12 | 目录 13 | ======= 14 | 15 | ac: 服务器代码 16 | ap: 客户端代码 17 | lib: 共用代码 18 | include: 共用头文件 19 | scripts: 编译等辅助脚本 20 | 21 | 22 | ac 23 | ================ 24 | 25 | ac 为多线程,包含以下线程: 26 | 27 | * net_recv: 接收二层或者三层数据包 28 | * net_netlisten: 监听tcp链接 29 | * net_dllbrd: 二层广播 30 | * message_travel: 定时处理收到的报文 31 | * 主线程: 用于命令行查看系统状态 32 | 33 | - net_dllbrd 线程广播探测报文, 报文中携带ac的地址和监听端口 34 | - ap接收到探测报文后,发起tcp链接 35 | - ac 将ap信息插入aphash 36 | - ap 定时汇报状态 37 | - ac 从数据库中提出配置,与状态比较,并发出命令 38 | - 当tcp链接断开时,认为ap掉线 39 | - 删除aphash记录 40 | 41 | 启动过程: 42 | 43 | * 初始化ac控制器uuid 44 | * 初始化epoll 45 | * 初始化二层socket, 加入epoll 46 | * 启动net_recv线程,收包(此时只接收二层数据包) 47 | * 初始化三层tcp listen线程, 等待tcp 链接 48 | * 初始化二层广播,汇报服务器地址,端口,ac uuid 49 | 50 | ap 51 | ================ 52 | 53 | ap 为多线程,包含以下线程: 54 | 55 | * net_recv: 接收二层或者三层数据包 56 | * message_travel: 定时处理收到的报文 57 | * 主线程: 状态查询 58 | 59 | 60 | chap 二层保护 61 | ================= 62 | 63 | 编译时makefile会要求输入password, 客户端和服务端必须密码一致,用于报文确认。random 用于防止重放攻击。 64 | 65 | 1、发送broadcast报文, 生成broadcast `random0` 66 | 2、ap接收到broadcast报文, 生成`random1`, 对`数据+ random0 + password`计算`md5sum1`, 发送ap reg 报文。 67 | 3、ac收到ap reg报文,提取`md5sum1`并置原报文位置为0, 对`报文 + random0 + password`计算`md5sum2`, 如果md5sum1 与 md5sum2 不一致,则丢弃。ac 生成reg response 报文,生成`random2`, 对`数据 + random1 + password`计算`md5sum3` 68 | 4、ap 收到reg response 报文,提取`md5sum3`并置原报文位置为0, 对`报文 + random1 + password`计算`md5sum3`, 如果md5sum3 与 md5sum4 不一致,则丢弃 69 | 70 | -------------------------------------------------------------------------------- /ac/Makefile: -------------------------------------------------------------------------------- 1 | all:acser 2 | LIB:= $(LIBDIR)/$(LIB) 3 | 4 | CFLAGS+=-DSERVER 5 | 6 | FILE = $(shell find . -name "*.c") 7 | OBJ = $(FILE:.c=.o) 8 | acser:$(OBJ) $(LIB) 9 | $(CC) $^ $(CFLAGS) $(LDFLAGS) -o $@ 10 | 11 | %.o:%.c 12 | $(CC) $(CFLAGS) -c $^ -o $@ 13 | 14 | export LIB LIBDIR CFLAGS 15 | $(LIB): FORCE 16 | @$(MAKE) -C $(LIBDIR) 17 | 18 | FORCE: 19 | PHONY += FORCE 20 | .PHONY: $(PHONY) 21 | -------------------------------------------------------------------------------- /ac/aphash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: aphash.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月20日 17时09分49秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "aphash.h" 25 | #include "thread.h" 26 | #include "arg.h" 27 | #include "msg.h" 28 | #include "process.h" 29 | 30 | struct ap_hash_head_t *aphead = NULL; 31 | unsigned int conflict_count = 0; 32 | 33 | /* all ap in net, not reg counter */ 34 | unsigned int ap_innet_cnt = 0; 35 | /* all ap in reg */ 36 | unsigned int ap_reg_cnt = 0; 37 | 38 | static unsigned int 39 | __elfhash(char* str, unsigned int len) 40 | { 41 | unsigned int hash = 0; 42 | unsigned int x = 0; 43 | unsigned int i = 0; 44 | for(i = 0; i < len; str++, i++) 45 | { 46 | hash = (hash << 4) + (*str); 47 | if((x = hash & 0xF0000000L) != 0) 48 | { 49 | hash ^= (x >> 24); 50 | } 51 | hash &= ~x; 52 | } 53 | return hash; 54 | } 55 | 56 | static unsigned int 57 | __hash_key(char *data, unsigned int len) 58 | { 59 | assert(data != NULL && len > 0); 60 | return __elfhash(data, len) % MAX_BUCKET; 61 | } 62 | 63 | struct ap_hash_t *hash_ap(char *mac) 64 | { 65 | assert(mac != NULL); 66 | 67 | char *dest; 68 | int key, len = 6; 69 | 70 | struct ap_hash_head_t *head = NULL; 71 | struct ap_hash_t **pprev, *aphash = NULL; 72 | pprev = &aphash; 73 | 74 | key = __hash_key(mac, len); 75 | 76 | head = aphead + key; 77 | pthread_mutex_lock(&head->lock); 78 | aphash = &head->aphash; 79 | dest = aphash->ap.mac; 80 | 81 | /* aphash head is null */ 82 | if(aphash->key == IDLE_AP) 83 | goto new; 84 | 85 | /* travel list */ 86 | while(aphash) { 87 | pprev = &aphash; 88 | if(!strncmp(aphash->ap.mac, mac, ETH_ALEN)) 89 | goto ret; 90 | aphash = aphash->apnext; 91 | conflict_count++; 92 | } 93 | 94 | /* calloc new */ 95 | aphash = calloc(1, sizeof(struct ap_hash_t)); 96 | if(aphash == NULL) { 97 | sys_err("Calloc failed: %s\n", 98 | strerror(errno)); 99 | return NULL; 100 | } 101 | (*pprev)->apnext = aphash; 102 | goto new; 103 | 104 | new: 105 | pthread_mutex_init(&aphash->lock, 0); 106 | aphash->key = key; 107 | aphash->ptail = &aphash->next; 108 | memcpy(dest, mac, len); 109 | ap_innet_cnt++; 110 | ret: 111 | pthread_mutex_unlock(&head->lock); 112 | pr_hash(key, aphash, mac); 113 | return aphash; 114 | } 115 | 116 | void hash_init() 117 | { 118 | assert(aphead == NULL); 119 | _Static_assert(MAX_BUCKET < (1ull << 32), "ap num too large\n"); 120 | 121 | aphead = calloc(1, sizeof(struct ap_hash_head_t) * MAX_BUCKET); 122 | if(aphead == NULL) { 123 | sys_err("Malloc hash bucket failed: %s\n", 124 | strerror(errno)); 125 | exit(-1); 126 | } 127 | sys_debug("Max support ap: %lu\n", MAX_BUCKET); 128 | 129 | int i; 130 | for(i = 0; i < MAX_BUCKET; i++) { 131 | aphead[i].aphash.key = IDLE_AP; 132 | aphead[i].aphash.ptail = &aphead[i].aphash.next; 133 | pthread_mutex_init(&aphead[i].lock, 0); 134 | } 135 | 136 | return; 137 | } 138 | 139 | void message_insert(struct ap_hash_t *aphash, struct message_t *msg) 140 | { 141 | assert(aphash != NULL); 142 | 143 | msg->next = NULL; 144 | 145 | sys_debug("message insert aphash: %p, msg: %p\n", aphash, msg); 146 | pthread_mutex_lock(&aphash->lock); 147 | *(aphash->ptail) = msg; 148 | aphash->ptail = &msg->next; 149 | aphash->count++; 150 | pthread_mutex_unlock(&aphash->lock); 151 | } 152 | 153 | static struct message_t *message_delete(struct ap_hash_t *aphash) 154 | { 155 | if(aphash->next == NULL) 156 | return NULL; 157 | 158 | struct message_t *msg; 159 | 160 | pthread_mutex_lock(&aphash->lock); 161 | msg = aphash->next; 162 | aphash->next = msg->next; 163 | aphash->count--; 164 | 165 | if(&msg->next == aphash->ptail) 166 | aphash->ptail = &aphash->next; 167 | pthread_mutex_unlock(&aphash->lock); 168 | 169 | sys_debug("message delete aphash: %p, msg: %p\n", aphash, msg); 170 | 171 | return msg; 172 | } 173 | 174 | static void message_free(struct message_t *msg) 175 | { 176 | free(msg); 177 | } 178 | 179 | static void *message_travel(void *arg) 180 | { 181 | assert(aphead != NULL); 182 | 183 | struct ap_hash_t *aphash; 184 | struct message_t *msg; 185 | int i; 186 | while(1) { 187 | sleep(argument.msgitv); 188 | 189 | /* travel hash bucket */ 190 | for(i = 0; i < MAX_BUCKET; i++) { 191 | aphash = &(aphead[i].aphash); 192 | /* travel hash list */ 193 | while(aphash) { 194 | /* travel message */ 195 | while((msg = message_delete(aphash))) { 196 | msg_proc(aphash, 197 | (void *)&msg->data[0], 198 | msg->len, 199 | msg->proto); 200 | message_free(msg); 201 | } 202 | aphash = aphash->apnext; 203 | } 204 | } 205 | } 206 | } 207 | 208 | void message_travel_init() 209 | { 210 | /* create thread process all message */ 211 | create_pthread(message_travel, NULL); 212 | } 213 | 214 | -------------------------------------------------------------------------------- /ac/aphash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: aphash.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月20日 14时26分57秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __APHASH_H__ 19 | #define __APHASH_H__ 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "dllayer.h" 28 | #include "log.h" 29 | #include "msg.h" 30 | 31 | /* 32 | * statistical information 33 | */ 34 | /* all ap in net, not reg counter */ 35 | extern unsigned int ap_innet_cnt; 36 | /* all ap in reg */ 37 | extern unsigned int ap_reg_cnt; 38 | 39 | 40 | extern struct ap_hash_head_t *aphead; 41 | extern unsigned int conflict_count; 42 | #ifndef MAX_BUCKET 43 | #define MAX_BUCKET (1ul << 14) 44 | #endif 45 | #define IDLE_AP (MAX_BUCKET + 1) 46 | 47 | /* message */ 48 | struct message_t { 49 | /* dllayer or tcp */ 50 | int proto; 51 | struct message_t *next; 52 | int len; 53 | char data[0]; 54 | }; 55 | 56 | struct ap_status_t { 57 | int isreg; 58 | /* set when ap reg in other ac */ 59 | char reguuid[UUID_LEN]; 60 | 61 | int level; 62 | }; 63 | 64 | struct ap_t { 65 | /* key and dllayer mac */ 66 | char mac[ETH_ALEN]; 67 | 68 | /* tcp sock */ 69 | int sock; 70 | struct ap_status_t ap_status; 71 | 72 | /* last random */ 73 | uint32_t random; 74 | }; 75 | 76 | struct ap_hash_t { 77 | int key; 78 | struct ap_t ap; 79 | 80 | pthread_mutex_t lock; 81 | 82 | struct message_t *next; 83 | struct message_t **ptail; 84 | time_t timestamp; 85 | int count; 86 | 87 | struct ap_hash_t *apnext; 88 | }; 89 | 90 | /* ap hash table */ 91 | struct ap_hash_head_t { 92 | pthread_mutex_t lock; 93 | struct ap_hash_t aphash; 94 | }; 95 | 96 | void hash_init(); 97 | struct ap_hash_t *hash_ap(char *mac); 98 | 99 | void message_travel_init(); 100 | void message_insert(struct ap_hash_t *aphash, struct message_t *msg); 101 | #endif /* __APHASH_H__ */ 102 | -------------------------------------------------------------------------------- /ac/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: main.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月18日 17时30分36秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "arg.h" 24 | #include "net.h" 25 | #include "msg.h" 26 | #include "aphash.h" 27 | #include "process.h" 28 | #include "netlayer.h" 29 | #include "resource.h" 30 | #include "sql.h" 31 | 32 | void ui() 33 | { 34 | printf("1 system status\n"); 35 | 36 | int num; 37 | while(1) { 38 | printf("Input num: "); 39 | scanf("%d", &num); 40 | 41 | switch(num) { 42 | case 1: { 43 | } 44 | } 45 | } 46 | } 47 | 48 | int main(int argc, char *argv[]) 49 | { 50 | sql_init(&sql); 51 | 52 | proc_arg(argc, argv); 53 | /* resource init */ 54 | resource_init(); 55 | /* set ac uuid, random, md5sum */ 56 | ac_init(); 57 | /* init ap hash table */ 58 | hash_init(); 59 | /* start message travel thread */ 60 | message_travel_init(); 61 | /* start recv message */ 62 | net_init(); 63 | 64 | ui(); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /ac/net.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: net.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月20日 14时25分36秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "dllayer.h" 29 | #include "aphash.h" 30 | #include "net.h" 31 | #include "log.h" 32 | #include "msg.h" 33 | #include "arg.h" 34 | #include "thread.h" 35 | #include "process.h" 36 | #include "link.h" 37 | #include "chap.h" 38 | 39 | static void *__net_dllrecv(void *arg) 40 | { 41 | struct message_t *msg; 42 | msg = malloc(sizeof(struct message_t) + DLL_PKT_DATALEN); 43 | if(msg == NULL) { 44 | sys_warn("malloc memory for dllayer failed: %s\n", 45 | strerror(errno)); 46 | goto err; 47 | } 48 | 49 | int rcvlen; 50 | rcvlen = dll_rcv(msg->data, DLL_PKT_DATALEN); 51 | if(rcvlen < (int)sizeof(struct ethhdr)) { 52 | free(msg); 53 | goto err; 54 | } 55 | msg->len = rcvlen; 56 | 57 | sys_debug("datalink layer recive a packet\n"); 58 | char *mac; 59 | struct msg_head_t *head; 60 | head = (struct msg_head_t *)(msg->data); 61 | mac = &head->mac[0]; 62 | 63 | struct ap_hash_t *aphash; 64 | aphash = hash_ap(mac); 65 | if(aphash == NULL) { 66 | free(msg); 67 | goto err; 68 | } 69 | 70 | memcpy(aphash->ap.mac, mac, ETH_ALEN); 71 | msg->proto = MSG_PROTO_ETH; 72 | message_insert(aphash, msg); 73 | err: 74 | return NULL; 75 | } 76 | 77 | /* pthread recv netlayer */ 78 | static void *__net_netrcv(void *arg) 79 | { 80 | struct sockarr_t *sockarr = arg; 81 | unsigned int events = sockarr->retevents; 82 | int clisock = sockarr->sock; 83 | 84 | if(events & EPOLLRDHUP || 85 | events & EPOLLERR || 86 | events & EPOLLHUP) { 87 | sys_debug("Epool get err: %s(%d)\n", strerror(errno), errno); 88 | ap_lost(clisock); 89 | return NULL; 90 | } 91 | 92 | if(!(events & EPOLLIN)) { 93 | sys_warn("Epoll unknow events: %u\n", events); 94 | return NULL; 95 | } 96 | 97 | struct message_t *msg; 98 | msg = malloc(sizeof(struct message_t) + NET_PKT_DATALEN); 99 | if(msg == NULL) { 100 | sys_warn("Malloc memory for message failed: %s(%d)\n", 101 | strerror(errno), errno); 102 | goto err; 103 | } 104 | 105 | sys_debug("net layer recive a packet\n"); 106 | struct nettcp_t tcp; 107 | tcp.sock = clisock; 108 | int rcvlen; 109 | rcvlen = tcp_rcv(&tcp, msg->data, NET_PKT_DATALEN); 110 | if(rcvlen <= 0) { 111 | ap_lost(clisock); 112 | free(msg); 113 | goto err; 114 | } 115 | msg->len = rcvlen; 116 | 117 | char *mac; 118 | struct msg_head_t *head; 119 | head = (struct msg_head_t *)(msg->data); 120 | mac = &head->mac[0]; 121 | 122 | struct ap_hash_t *aphash; 123 | aphash = hash_ap(mac); 124 | if(aphash == NULL) { 125 | free(msg); 126 | goto err; 127 | } 128 | 129 | aphash->ap.sock = clisock; 130 | msg->proto = MSG_PROTO_TCP; 131 | message_insert(aphash, msg); 132 | err: 133 | return NULL; 134 | } 135 | 136 | /* pthread broadcast */ 137 | static void *net_dllbrd(void *arg) 138 | { 139 | struct msg_ac_brd_t *reqbuf = 140 | malloc(sizeof(struct msg_ac_brd_t)); 141 | if(reqbuf == NULL) { 142 | sys_err("Malloc broadcast message failed: %s(%d)\n", 143 | strerror(errno), errno); 144 | return NULL; 145 | } 146 | 147 | while(1) { 148 | ac.random = chap_get_random(); 149 | sys_debug("Send a broadcast probe msg, random: %u (next %d second later)\n", 150 | ac.random, argument.brditv); 151 | 152 | /* generate random0 */ 153 | fill_msg_header(&reqbuf->header, MSG_AC_BRD, 154 | &ac.acuuid[0], ac.random); 155 | 156 | /* first broad cast packet, there is no need calculate chap */ 157 | dll_brdcast((char *)reqbuf, sizeof(struct msg_ac_brd_t)); 158 | sleep(argument.brditv); 159 | } 160 | return NULL; 161 | } 162 | 163 | static void *net_netlisten(void *arg) 164 | { 165 | int ret; 166 | struct nettcp_t tcplisten; 167 | tcplisten.addr.sin_family = AF_INET; 168 | tcplisten.addr.sin_addr.s_addr = htonl(INADDR_ANY); 169 | tcplisten.addr.sin_port = htons(argument.port); 170 | ret = tcp_listen(&tcplisten); 171 | if(ret < 0) { 172 | sys_err("Create listen tcp failed\n"); 173 | exit(-1); 174 | } 175 | 176 | while(1) 177 | tcp_accept(&tcplisten, __net_netrcv); 178 | } 179 | 180 | void net_init() 181 | { 182 | int sock; 183 | 184 | /* init epoll */ 185 | net_epoll_init(); 186 | 187 | /* init datalink layer */ 188 | dll_init(&argument.nic[0], &sock, NULL, NULL); 189 | insert_sockarr(sock, __net_dllrecv, NULL); 190 | 191 | /* create pthread recv msg */ 192 | create_pthread(net_recv, NULL); 193 | sys_debug("Create pthread net_recv msg\n"); 194 | 195 | /* create pthread tcp listen */ 196 | create_pthread(net_netlisten, NULL); 197 | sys_debug("Create pthread tcp listen\n"); 198 | 199 | /* create pthread broadcast ac probe packet */ 200 | create_pthread(net_dllbrd, NULL); 201 | sys_debug("Create pthread broadcast dllayer msg\n"); 202 | } 203 | 204 | -------------------------------------------------------------------------------- /ac/net.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: net.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月20日 14时25分43秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __NET_H__ 19 | #define __NET_H__ 20 | #include "netlayer.h" 21 | 22 | void net_init(); 23 | #endif /*__NET_H__*/ 24 | -------------------------------------------------------------------------------- /ac/process.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: process.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月25日 14时31分55秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "net.h" 29 | #include "log.h" 30 | #include "msg.h" 31 | #include "aphash.h" 32 | #include "arg.h" 33 | #include "netlayer.h" 34 | #include "apstatus.h" 35 | #include "link.h" 36 | #include "process.h" 37 | #include "resource.h" 38 | 39 | static void __get_cmd_stdout(char *cmd, char *buf, int len) 40 | { 41 | FILE *fp; 42 | int size; 43 | fp = popen(cmd, "r"); 44 | if(fp != NULL) { 45 | size = fread(buf, 1, len, fp); 46 | if(size <= 0) 47 | goto err; 48 | /* skip \n */ 49 | buf[size - 1] = 0; 50 | pclose(fp); 51 | return; 52 | } 53 | err: 54 | buf[0] = 0; 55 | sys_err("Exec %s failed: %s\n", cmd, strerror(errno)); 56 | exit(0); 57 | } 58 | 59 | static int __uuid_equ(char *src, char *dest) 60 | { 61 | return !strncmp(src, dest, UUID_LEN - 1); 62 | } 63 | 64 | static char *__buildcmd() 65 | { 66 | char *cmd; 67 | cmd = malloc(100); 68 | strcpy(cmd, "cmdtest;"); 69 | return cmd; 70 | } 71 | 72 | static void __ap_status(struct ap_t *ap, struct msg_ap_reg_t *msg) 73 | { 74 | sys_debug("recive ap report status packet\n"); 75 | 76 | int ret; 77 | struct apstatus_t *status = (void *)((char *)msg + 78 | sizeof(struct msg_ap_status_t)); 79 | printf("ssidnum:%d, ssid:%s \n", status->ssidnum, status->ssid0.ssid); 80 | 81 | char *cmd = __buildcmd(); 82 | if(cmd == NULL) return; 83 | int cmdlen = strlen(cmd); 84 | int totallen = sizeof(struct msg_ac_cmd_t) + cmdlen; 85 | assert(totallen <= NET_PKT_DATALEN); 86 | 87 | struct msg_ac_cmd_t *data = malloc(totallen); 88 | if(data == NULL) { 89 | sys_warn("malloc msg for cmd failed: %s\n", 90 | strerror(errno)); 91 | return; 92 | } 93 | fill_msg_header(&data->header, MSG_AC_CMD, 94 | &ac.acuuid[0], msg->header.random); 95 | strncpy((char *)data + sizeof(struct msg_ac_cmd_t), cmd, cmdlen); 96 | 97 | struct nettcp_t tcp; 98 | tcp.sock = ap->sock; 99 | ret = tcp_sendpkt(&tcp, (char *)data, totallen); 100 | if(ret <= 0) 101 | ap_lost(ap->sock); 102 | free(data); 103 | free(cmd); 104 | } 105 | 106 | 107 | static void __ap_reg(struct ap_t *ap, 108 | struct msg_ap_reg_t *msg, int len, int proto) 109 | { 110 | sys_debug("recive ap reg packet\n"); 111 | if(len < sizeof(*msg)) { 112 | sys_err("receive wrong ap reg packet\n"); 113 | return; 114 | } 115 | 116 | /* XXX:first random is broadcast random, 117 | * ac broadcast random will change every argument.brditv 118 | * so ap reg packet must be recive in argument.brditv */ 119 | /* calculate: md5sum2 = packet + random0 + password 120 | * compare md5sum1 with md5sum2*/ 121 | if(chap_msg_cmp_md5((void *)msg, sizeof(*msg), ac.random)) { 122 | sys_err("receive packet chap check failed\n"); 123 | return; 124 | } 125 | 126 | struct _ip_t *ip; 127 | struct sockaddr_in *addr; 128 | if(res_ip_conflict(&(msg->ipv4), msg->header.mac)) 129 | addr = NULL; 130 | else 131 | addr = &(msg->ipv4); 132 | 133 | pr_ipv4(addr); 134 | ip = res_ip_alloc(addr, msg->header.mac); 135 | pr_ipv4(&ip->ipv4); 136 | 137 | struct msg_ac_reg_resp_t *resp = 138 | calloc(1, sizeof(struct msg_ac_reg_resp_t)); 139 | if(resp == NULL) { 140 | sys_err("Calloc memory failed: %s(%d)\n", 141 | strerror(errno), errno); 142 | return; 143 | } 144 | 145 | /* generate random2 */ 146 | ap->random = chap_get_random(); 147 | fill_msg_header((void *)resp, MSG_AC_REG_RESP, 148 | &ac.acuuid[0], ap->random); 149 | 150 | resp->acaddr = argument.addr; 151 | if(ip != NULL) 152 | resp->apaddr = ip->ipv4; 153 | 154 | /* calculate chap: md5sum3 = packet + random1 + password */ 155 | chap_fill_msg_md5((void *)resp, sizeof(*resp), msg->header.random); 156 | net_send(proto, ap->sock, msg->header.mac, 157 | (void *)resp, sizeof(struct msg_ac_reg_resp_t)); 158 | free(resp); 159 | ap_reg_cnt++; 160 | } 161 | 162 | struct ac_t ac; 163 | #define X86_UUID "cat /sys/class/dmi/id/product_uuid" 164 | void ac_init() 165 | { 166 | memset(ac.acuuid, 0, UUID_LEN); 167 | __get_cmd_stdout(X86_UUID, ac.acuuid, UUID_LEN-1); 168 | } 169 | 170 | void ap_lost(int sock) 171 | { 172 | sys_debug("ap lost sock: %d\n", sock); 173 | delete_sockarr(sock); 174 | } 175 | 176 | int is_mine(struct msg_head_t *msg, int len) 177 | { 178 | /* check packet len */ 179 | if(len < sizeof(*msg)) { 180 | sys_err("receive ultrashort packet\n"); 181 | return 0; 182 | } 183 | 184 | /* ap have reg in other ac */ 185 | char *ap = msg->mac; 186 | if(!__uuid_equ(msg->acuuid, ac.acuuid) 187 | && (msg->msg_type == MSG_AP_RESP)) { 188 | pr_ap(ap, msg->acuuid); 189 | return 0; 190 | } 191 | 192 | return 1; 193 | } 194 | 195 | void msg_proc(struct ap_hash_t *aphash, 196 | struct msg_head_t *msg, int len, int proto) 197 | { 198 | if(!is_mine(msg, len)) return; 199 | 200 | switch(msg->msg_type) { 201 | case MSG_AP_REG: 202 | __ap_reg(&aphash->ap, (void *)msg, len, proto); 203 | break; 204 | case MSG_AP_STATUS: 205 | /* only received by tcp */ 206 | __ap_status(&aphash->ap, (void *)msg); 207 | break; 208 | default: 209 | sys_err("Invaild msg type\n"); 210 | break; 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /ac/process.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: process.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月25日 18时28分04秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __PROCESS_H__ 19 | #define __PROCESS_H__ 20 | #include 21 | struct ac_t { 22 | uint32_t random; 23 | char acuuid[UUID_LEN]; 24 | }; 25 | 26 | extern struct ac_t ac; 27 | 28 | void ac_init(); 29 | void ap_lost(int sock); 30 | void msg_proc(struct ap_hash_t *aphash, 31 | struct msg_head_t *msg, int len, int proto); 32 | #endif /* __PROCESS_H__ */ 33 | -------------------------------------------------------------------------------- /ac/resource.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: resource.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年10月24日 15时10分07秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "log.h" 31 | #include "resource.h" 32 | #include "sql.h" 33 | 34 | struct _ippool_t *ippool = NULL; 35 | 36 | struct _ip_t *res_ip_alloc(struct sockaddr_in *addr, char *mac) 37 | { 38 | assert(ippool != NULL); 39 | 40 | if(!ippool->left && !list_empty(&ippool->pool)) { 41 | sys_warn("No ip in pool\n"); 42 | return NULL; 43 | } 44 | 45 | struct _ip_t *new; 46 | alloc_new: 47 | if(addr == NULL || addr->sin_addr.s_addr == 0) { 48 | LOCK(&ippool->lock); 49 | new = list_first_entry(&ippool->pool, 50 | struct _ip_t, list); 51 | memcpy(new->apmac, mac, ETH_ALEN); 52 | list_move(&new->list, &ippool->alloc); 53 | ippool->left--; 54 | UNLOCK(&ippool->lock); 55 | return new; 56 | } else { 57 | /* if specify addr will alloc addr first */ 58 | LOCK(&ippool->lock); 59 | list_for_each_entry(new, &ippool->pool, list) { 60 | if((addr->sin_addr.s_addr == 61 | new->ipv4.sin_addr.s_addr)) { 62 | list_move(&new->list, &ippool->alloc); 63 | memcpy(new->apmac, mac, ETH_ALEN); 64 | ippool->left--; 65 | UNLOCK(&ippool->lock); 66 | return new; 67 | } 68 | } 69 | UNLOCK(&ippool->lock); 70 | 71 | /* have no addr */ 72 | addr = NULL; 73 | goto alloc_new; 74 | } 75 | 76 | return NULL; 77 | } 78 | 79 | static int 80 | addrequ(struct sockaddr_in *src, struct sockaddr_in *dest) 81 | { 82 | if(src->sin_addr.s_addr == dest->sin_addr.s_addr) 83 | return 1; 84 | return 0; 85 | } 86 | 87 | int res_ip_conflict(struct sockaddr_in *addr, char *mac) 88 | { 89 | assert(ippool != NULL); 90 | 91 | if(addr->sin_addr.s_addr == 0) 92 | return 0; 93 | 94 | int ret = 0; 95 | struct _ip_t *ip; 96 | LOCK(&ippool->lock); 97 | list_for_each_entry(ip, &ippool->alloc, list) { 98 | if(addrequ(&ip->ipv4, addr)) { 99 | if(memcmp(mac, ip->apmac, ETH_ALEN)) 100 | ret = 1; 101 | else 102 | ret = 0; 103 | goto end; 104 | } 105 | } 106 | end: 107 | UNLOCK(&ippool->lock); 108 | return ret; 109 | } 110 | 111 | static int res_ip_repeat(struct sockaddr_in *addr) 112 | { 113 | assert(ippool != NULL); 114 | 115 | struct _ip_t *pos; 116 | 117 | list_for_each_entry(pos, &ippool->pool, list) { 118 | if(addrequ(&pos->ipv4, addr)) 119 | return 1; 120 | } 121 | 122 | list_for_each_entry(pos, &ippool->alloc, list) { 123 | if(addrequ(&pos->ipv4, addr)) 124 | return 1; 125 | } 126 | return 0; 127 | } 128 | 129 | int res_ip_add(struct sockaddr_in *addr) 130 | { 131 | assert(ippool != NULL); 132 | 133 | LOCK(&ippool->lock); 134 | if(res_ip_repeat(addr)) 135 | goto err; 136 | 137 | struct _ip_t *ip = 138 | calloc(1, sizeof(struct _ip_t)); 139 | if(!ip) { 140 | sys_err("Calloc ip_t failed: %s(%d)\n", 141 | strerror(errno), errno); 142 | goto err; 143 | } 144 | 145 | ip->ipv4 = *addr; 146 | list_add_tail(&ip->list, &ippool->pool); 147 | ippool->total++; 148 | ippool->left++; 149 | UNLOCK(&ippool->lock); 150 | return 0; 151 | err: 152 | UNLOCK(&ippool->lock); 153 | return -1; 154 | } 155 | 156 | void res_ip_clear() 157 | { 158 | assert(ippool != NULL); 159 | 160 | struct _ip_t *pos, *tmp; 161 | 162 | LOCK(&ippool->lock); 163 | 164 | list_for_each_entry_safe(pos, tmp, &ippool->pool, list) 165 | free(pos); 166 | 167 | list_for_each_entry_safe(pos, tmp, &ippool->alloc, list) 168 | free(pos); 169 | 170 | ippool->total = 0; 171 | ippool->left = 0; 172 | 173 | UNLOCK(&ippool->lock); 174 | } 175 | 176 | static void res_ip_init() 177 | { 178 | assert(ippool == NULL); 179 | ippool = calloc(1, sizeof(struct _ippool_t)); 180 | if(ippool == NULL) { 181 | sys_err("Calloc memory for ip pool failed: %s(%d)\n", 182 | strerror(errno), errno); 183 | exit(-1); 184 | } 185 | 186 | LOCK_INIT(&ippool->lock); 187 | INIT_LIST_HEAD(&ippool->pool); 188 | INIT_LIST_HEAD(&ippool->alloc); 189 | return; 190 | } 191 | 192 | static int res_ip_equ_bak() 193 | { 194 | if(strcmp(resource.ip_start, resource.bak_start) || 195 | strcmp(resource.ip_end, resource.bak_end) || 196 | strcmp(resource.ip_mask, resource.bak_mask)) { 197 | strcpy(resource.bak_start, resource.ip_start); 198 | strcpy(resource.bak_end, resource.ip_end); 199 | strcpy(resource.bak_mask, resource.ip_mask); 200 | return 0; 201 | } 202 | return 1; 203 | } 204 | 205 | #define HTONL(s, d) (d = htonl(s)) 206 | #define NTOHL(s, d) (d = ntohl(s)) 207 | void res_ip_reload() 208 | { 209 | if(!strcmp(resource.ip_start, SQL_NULL) || 210 | !strcmp(resource.ip_end, SQL_NULL) || 211 | !strcmp(resource.ip_mask, SQL_NULL)) { 212 | sys_err("Resource ip error\n"); 213 | return; 214 | } 215 | 216 | struct in_addr ipstart, ipend, ipmask; 217 | if(!inet_aton(resource.ip_start, &ipstart) || 218 | !inet_aton(resource.ip_end, &ipend) || 219 | !inet_aton(resource.ip_mask, &ipmask)) { 220 | sys_err("Resource ip error\n"); 221 | return; 222 | } 223 | if(res_ip_equ_bak()) return; 224 | 225 | sys_debug("start: %s, end: %s, mask: %s\n", 226 | resource.ip_start, resource.ip_end, resource.ip_mask); 227 | 228 | NTOHL(ipstart.s_addr, ipstart.s_addr); 229 | NTOHL(ipend.s_addr, ipend.s_addr); 230 | NTOHL(ipmask.s_addr, ipmask.s_addr); 231 | 232 | int num = (ipend.s_addr & ~ipmask.s_addr) - 233 | (ipstart.s_addr & ~ipmask.s_addr) + 1; 234 | if(num <= 0) { 235 | sys_warn("Resource ip error\n"); 236 | return; 237 | } 238 | 239 | int i; 240 | struct sockaddr_in addr, tmp; 241 | /* skip net addr */ 242 | if(!(ipstart.s_addr & (~ipmask.s_addr))) { 243 | ipstart.s_addr++; 244 | num--; 245 | } 246 | 247 | /* skip broadcast addr */ 248 | if((ipend.s_addr & (~ipmask.s_addr)) == (~ipmask.s_addr)) 249 | num--; 250 | 251 | addr.sin_addr.s_addr = ipstart.s_addr; 252 | 253 | res_ip_clear(); 254 | for(i = 0; i < num; i++, addr.sin_addr.s_addr++) { 255 | HTONL(addr.sin_addr.s_addr, tmp.sin_addr.s_addr); 256 | sys_debug("add %s\n", inet_ntoa(tmp.sin_addr)); 257 | res_ip_add(&tmp); 258 | } 259 | } 260 | 261 | static void *res_check(void *arg) 262 | { 263 | static char buffer[1024]; 264 | int status; 265 | while(1) { 266 | sys_debug("load resource from mysql(next: %d)\n", 267 | argument.reschkitv); 268 | 269 | sql_query_res(&sql, buffer, 1024); 270 | 271 | status = json_read_object(buffer, json_attrs, NULL); 272 | if (status != 0) { 273 | sys_err("%s\n", json_error_string(status)); 274 | exit(-1); 275 | } 276 | res_ip_reload(); 277 | 278 | sleep(argument.reschkitv); 279 | } 280 | return NULL; 281 | } 282 | 283 | void resource_init() 284 | { 285 | res_ip_init(); 286 | create_pthread(res_check, NULL); 287 | } 288 | -------------------------------------------------------------------------------- /ac/resource.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: resource.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年10月24日 15时10分10秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __RESOURCE_H__ 19 | #define __RESOURCE_H__ 20 | 21 | #include "thread.h" 22 | #include "list.h" 23 | #include "mjson.h" 24 | 25 | #define IPLEN (20) 26 | struct res_t { 27 | char ip_start[IPLEN]; 28 | char ip_end[IPLEN]; 29 | char ip_mask[IPLEN]; 30 | char bak_start[IPLEN]; 31 | char bak_end[IPLEN]; 32 | char bak_mask[IPLEN]; 33 | } resource; 34 | 35 | static const struct json_attr_t json_attrs[] = { 36 | {"ip_start", t_string, .addr.string = resource.ip_start, .len = IPLEN}, 37 | {"ip_end", t_string, .addr.string = resource.ip_end, .len = IPLEN}, 38 | {"ip_mask", t_string, .addr.string = resource.ip_mask, .len = IPLEN}, 39 | {NULL}, 40 | }; 41 | 42 | struct _ip_t { 43 | char apmac[ETH_ALEN]; 44 | struct sockaddr_in ipv4; 45 | struct list_head list; 46 | }; 47 | 48 | struct _ippool_t { 49 | THREAD lock; 50 | struct list_head pool; 51 | struct list_head alloc; 52 | int total; 53 | int left; 54 | }; 55 | 56 | extern struct _ippool_t *ippool; 57 | 58 | void resource_init(); 59 | struct _ip_t *res_ip_alloc(struct sockaddr_in *addr, char *mac); 60 | int res_ip_conflict(struct sockaddr_in *addr, char *mac); 61 | int res_ip_add(struct sockaddr_in *addr); 62 | void res_ip_clear(); 63 | #endif /* __RESOURCE_H__ */ 64 | -------------------------------------------------------------------------------- /ac/sql.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: sql.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年11月12日 15时49分05秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include "sql.h" 22 | #include "mjson.h" 23 | #include "log.h" 24 | 25 | MYSQL sql; 26 | struct tbl_col_t tables; 27 | 28 | int sql_query(SQL *sql, char *cmd, MYSQL_RES **res, my_ulonglong *rows) 29 | { 30 | int ret; 31 | ret = mysql_query(sql, cmd); 32 | if(ret) { 33 | pr_sqlerr(); 34 | return -1; 35 | } 36 | 37 | *res = mysql_store_result(sql); 38 | if(!res) { 39 | pr_sqlerr(); 40 | return -1; 41 | } 42 | 43 | my_ulonglong row = mysql_num_rows(*res); 44 | if(row <= 0) { 45 | sys_warn("Have no resource in database\n"); 46 | mysql_free_result(*res); 47 | return -1; 48 | } 49 | if(rows) *rows = row; 50 | 51 | return 0; 52 | } 53 | 54 | int sql_query_res(SQL *sql, char *buffer, int len) 55 | { 56 | MYSQL_RES *res; 57 | if(sql_query(sql, GETRES, &res, NULL) < 0) 58 | return -1; 59 | 60 | int i; 61 | MYSQL_ROW row; 62 | struct col_name_t *col = tables.res.head; 63 | 64 | while((row = mysql_fetch_row(res))) { 65 | JSON_ENCODE_START(buffer, len); 66 | 67 | for(i = 0; i < tables.res.col_num && len > 2; i++) 68 | JSON_ENCODE(buffer, len, col[i].name, row[i]); 69 | 70 | JSON_ENCODE_END(buffer, len); 71 | } 72 | 73 | return 0; 74 | } 75 | 76 | void sql_close(SQL *sql) 77 | { 78 | mysql_close(sql); 79 | } 80 | 81 | void _sql_tbl_col(SQL *sql, char *table, struct tbl_dsc_t *dsc) 82 | { 83 | MYSQL_RES *res; 84 | res = mysql_list_fields(sql, table, NULL); 85 | if(!res) { 86 | pr_sqlerr(); 87 | exit(-1); 88 | } 89 | dsc->col_num = mysql_num_fields(res); 90 | dsc->head = 91 | malloc(sizeof(struct col_name_t) * dsc->col_num); 92 | if(!dsc->head) { 93 | sys_err("Malloc failed: %s(%d)\n", 94 | strerror(errno), errno); 95 | exit(-1); 96 | } 97 | 98 | int i; 99 | MYSQL_FIELD *col; 100 | for(i = 0; i < dsc->col_num; i++) { 101 | col = mysql_fetch_field_direct(res, i); 102 | assert(strlen(col->name) < (COLMAX - 1)); 103 | strcpy(dsc->head[i].name, col->name); 104 | } 105 | 106 | mysql_free_result(res); 107 | } 108 | 109 | void sql_tbl_col(SQL *sql) 110 | { 111 | _sql_tbl_col(sql, RESOURCE, &tables.res); 112 | } 113 | 114 | int sql_init(SQL *sql) 115 | { 116 | int ret; 117 | void *state; 118 | 119 | printf("Mysql version:%s\n", mysql_get_client_info()); 120 | 121 | sql = mysql_init(sql); 122 | if(sql == NULL) { 123 | pr_sqlerr(); 124 | exit(-1); 125 | } 126 | 127 | mysql_options(sql, MYSQL_READ_DEFAULT_GROUP, "acctl"); 128 | state = mysql_real_connect(sql, NULL, NULL, 129 | NULL, NULL, 0, NULL, 0); 130 | if(state == NULL) { 131 | pr_sqlerr(); 132 | exit(-1); 133 | } 134 | 135 | ret = mysql_select_db(sql, DBNAME); 136 | if(ret) { 137 | pr_sqlerr(); 138 | exit(-1); 139 | } 140 | 141 | sql_tbl_col(sql); 142 | return 0; 143 | } 144 | 145 | -------------------------------------------------------------------------------- /ac/sql.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: sql.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年11月12日 15时49分08秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __SQL_H__ 19 | #define __SQL_H__ 20 | #include 21 | #include 22 | 23 | #define SQL MYSQL 24 | #define SQL_NULL "(null)" 25 | 26 | 27 | #define DBNAME "ac" 28 | #define RESOURCE "resource" 29 | 30 | #define GETRES "SELECT * FROM resource LIMIT 1" 31 | #define pr_sqlerr() \ 32 | sys_err("Error %u: %s\n", mysql_errno(sql), mysql_error(sql)); 33 | 34 | extern MYSQL sql; 35 | 36 | #define COLMAX (128) 37 | struct col_name_t { 38 | char name[128]; 39 | }; 40 | 41 | struct tbl_dsc_t { 42 | unsigned int col_num; 43 | struct col_name_t *head; 44 | }; 45 | 46 | struct tbl_col_t { 47 | struct tbl_dsc_t res; 48 | }; 49 | 50 | int sql_init(SQL *sql); 51 | int sql_query_res(SQL *sql, char *buffer, int len); 52 | #endif /* __SQL_H__ */ 53 | -------------------------------------------------------------------------------- /ap/Makefile: -------------------------------------------------------------------------------- 1 | all:apctl 2 | 3 | LIB:= $(LIBDIR)/$(LIB) 4 | 5 | CFLAGS+=-DCLIENT 6 | 7 | FILE = $(shell find . -name "*.c") 8 | OBJ = $(FILE:.c=.o) 9 | apctl:$(OBJ) $(LIB) 10 | $(CC) $^ $(LDFLAGS) -o $@ 11 | 12 | %.o:%.c 13 | $(CC) $(CFLAGS) -c $^ -o $@ 14 | 15 | export LIB LIBDIR CFLAGS 16 | $(LIB): FORCE 17 | @$(MAKE) -C $(LIBDIR) 18 | 19 | FORCE: 20 | PHONY += FORCE 21 | .PHONY: $(PHONY) 22 | -------------------------------------------------------------------------------- /ap/apstatus.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: apstatus.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年09月01日 15时27分34秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | 22 | #include "apstatus.h" 23 | 24 | struct apstatus_t ap = {0}; 25 | 26 | struct apstatus_t *get_apstatus() 27 | { 28 | ap.ssidnum = 1; 29 | strcpy(&ap.ssid0.ssid[0], "jianxi-pri"); 30 | 31 | return ≈ 32 | } 33 | -------------------------------------------------------------------------------- /ap/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: main.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月26日 09时05分59秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "arg.h" 24 | #include "message.h" 25 | #include "process.h" 26 | #include "msg.h" 27 | #include "net.h" 28 | #include "netlayer.h" 29 | #include "log.h" 30 | #include "link.h" 31 | #include "thread.h" 32 | 33 | void ui(); 34 | 35 | int main(int argc, char *argv[]) 36 | { 37 | proc_arg(argc, argv); 38 | 39 | /* create recv pthread */ 40 | net_init(); 41 | /* create message loop travel pthread */ 42 | message_init(); 43 | /* create report pthread */ 44 | init_report(); 45 | 46 | pause(); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /ap/message.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: message.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月26日 09时16分29秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "log.h" 26 | #include "arg.h" 27 | #include "msg.h" 28 | #include "thread.h" 29 | #include "message.h" 30 | #include "process.h" 31 | 32 | struct message_t *head = NULL; 33 | struct message_t **tail = &head; 34 | pthread_mutex_t message_lock = PTHREAD_MUTEX_INITIALIZER; 35 | #define MUTEX_LOCK(lock) pthread_mutex_lock(&lock) 36 | #define MUTEX_UNLOCK(lock) pthread_mutex_unlock(&lock) 37 | 38 | static int message_num = 0; 39 | void message_insert(struct message_t *msg) 40 | { 41 | sys_debug("message insert msg: %p\n", msg); 42 | msg->next = NULL; 43 | 44 | MUTEX_LOCK(message_lock); 45 | message_num++; 46 | *tail = msg; 47 | tail = &msg->next; 48 | MUTEX_UNLOCK(message_lock); 49 | } 50 | 51 | struct message_t * message_delete() 52 | { 53 | MUTEX_LOCK(message_lock); 54 | if(message_num == 0) { 55 | assert(*tail == head); 56 | MUTEX_UNLOCK(message_lock); 57 | return NULL; 58 | } 59 | 60 | struct message_t *tmp = head; 61 | message_num--; 62 | 63 | head = head->next; 64 | if(tail == &tmp->next) 65 | tail = &head; 66 | 67 | MUTEX_UNLOCK(message_lock); 68 | sys_debug("message delete: %p\n", tmp); 69 | return tmp; 70 | } 71 | 72 | void message_free(struct message_t *msg) 73 | { 74 | free(msg); 75 | } 76 | 77 | void *message_travel(void *arg) 78 | { 79 | struct message_t *msg; 80 | while(1) { 81 | sleep(argument.msgitv); 82 | if(head == NULL) continue; 83 | while((msg = message_delete())) { 84 | msg_proc((void *)msg->data, msg->len, msg->proto); 85 | message_free(msg); 86 | } 87 | sys_debug("Message travel pthreads (next %d second later)\n", 88 | argument.msgitv); 89 | } 90 | return NULL; 91 | } 92 | 93 | void message_init() 94 | { 95 | /* create thread to travel all message */ 96 | create_pthread(message_travel, NULL); 97 | } 98 | -------------------------------------------------------------------------------- /ap/message.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: message.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月26日 09时16分35秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __MESSAGE_H__ 19 | #define __MESSAGE_H__ 20 | #include "dllayer.h" 21 | 22 | enum { 23 | ETH, 24 | TCP, 25 | }; 26 | 27 | /* message */ 28 | struct message_t { 29 | /* dllayer or tcp */ 30 | int proto; 31 | struct message_t *next; 32 | int len; 33 | char data[0]; 34 | }; 35 | 36 | extern struct message_t *head, **tail; 37 | 38 | void message_init(); 39 | void message_insert(struct message_t *msg); 40 | #endif /* __MESSAGE_H__ */ 41 | -------------------------------------------------------------------------------- /ap/net.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: net.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 08/26/14 14:18:52 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "message.h" 28 | #include "dllayer.h" 29 | #include "netlayer.h" 30 | #include "log.h" 31 | #include "thread.h" 32 | #include "arg.h" 33 | #include "link.h" 34 | #include "process.h" 35 | 36 | /* recv dllayer */ 37 | static void *net_dllrecv(void *arg) 38 | { 39 | struct message_t *msg; 40 | int rcvlen; 41 | 42 | msg = malloc(sizeof(struct message_t) + 43 | DLL_PKT_DATALEN); 44 | if(msg == NULL) { 45 | sys_warn("malloc memory for dllayer failed: %s\n", 46 | strerror(errno)); 47 | goto err; 48 | } 49 | 50 | rcvlen = dll_rcv(msg->data, DLL_PKT_DATALEN); 51 | if(rcvlen < (int)sizeof(struct ethhdr)) { 52 | free(msg); 53 | goto err; 54 | } 55 | msg->len = rcvlen; 56 | msg->proto = MSG_PROTO_ETH; 57 | message_insert(msg); 58 | err: 59 | return NULL; 60 | } 61 | 62 | /* recv netlayer */ 63 | void *__net_netrcv(void *arg) 64 | { 65 | struct sockarr_t *sockarr = arg; 66 | unsigned int events = sockarr->retevents; 67 | int clisock = sockarr->sock; 68 | 69 | if(events & EPOLLRDHUP || 70 | events & EPOLLERR || 71 | events & EPOLLHUP) { 72 | sys_debug("Epool get err: %s(%d)\n", strerror(errno), errno); 73 | ac_lost(); 74 | return NULL; 75 | } 76 | 77 | struct message_t *msg; 78 | msg = malloc(sizeof(struct message_t) + NET_PKT_DATALEN); 79 | if(msg == NULL) { 80 | sys_warn("malloc memory for dllayer failed: %s\n", 81 | strerror(errno)); 82 | goto err; 83 | } 84 | 85 | int rcvlen; 86 | struct nettcp_t tcp; 87 | tcp.sock = clisock; 88 | rcvlen = tcp_rcv(&tcp, msg->data, NET_PKT_DATALEN); 89 | if(rcvlen <= 0) { 90 | ac_lost(); 91 | free(msg); 92 | goto err; 93 | } 94 | msg->len = rcvlen; 95 | msg->proto = MSG_PROTO_TCP; 96 | message_insert(msg); 97 | err: 98 | return NULL; 99 | } 100 | 101 | void net_init() 102 | { 103 | int sock; 104 | /* init epoll */ 105 | net_epoll_init(); 106 | 107 | dll_init(&argument.nic[0], &sock, NULL, NULL); 108 | insert_sockarr(sock, net_dllrecv, NULL); 109 | 110 | /* create pthread recv msg */ 111 | create_pthread(net_recv, head); 112 | sys_debug("Create pthread recv dllayer msg\n"); 113 | } 114 | 115 | -------------------------------------------------------------------------------- /ap/net.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: net.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 08/26/14 14:26:10 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __NET_H__ 19 | #define __NET_H__ 20 | 21 | extern struct nettcp_t tcp; 22 | void net_init(); 23 | void *__net_netrcv(void *arg); 24 | #endif /* __NET_H__ */ 25 | -------------------------------------------------------------------------------- /ap/process.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: process.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月26日 10时04分23秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "msg.h" 27 | #include "log.h" 28 | #include "dllayer.h" 29 | #include "netlayer.h" 30 | #include "link.h" 31 | #include "net.h" 32 | #include "arg.h" 33 | #include "thread.h" 34 | #include "process.h" 35 | #include "apstatus.h" 36 | 37 | #define SYSSTAT_LOCK() (pthread_mutex_lock(&sysstat.lock)) 38 | #define SYSSTAT_UNLOCK() (pthread_mutex_unlock(&sysstat.lock)) 39 | 40 | struct sysstat_t sysstat = { 41 | .acuuid = {0}, 42 | .isreg = 0, 43 | .sock = -1, 44 | .dmac = {0}, 45 | .lock = PTHREAD_MUTEX_INITIALIZER, 46 | }; 47 | 48 | static void ac_reconnect() 49 | { 50 | if(!sysstat.server.sin_addr.s_addr) 51 | return; 52 | 53 | int ret; 54 | struct nettcp_t tcp; 55 | SYSSTAT_LOCK(); 56 | /* other process have reconnect */ 57 | if(sysstat.sock >= 0) 58 | goto unlock; 59 | 60 | tcp.addr = sysstat.server; 61 | ret = tcp_connect(&tcp); 62 | if(ret < 0) 63 | goto unlock; 64 | 65 | pr_ipv4(&tcp.addr); 66 | sysstat.sock = ret; 67 | SYSSTAT_UNLOCK(); 68 | sys_debug("connect success: %d\n", sysstat.sock); 69 | insert_sockarr(tcp.sock, __net_netrcv, NULL); 70 | return; 71 | 72 | unlock: 73 | SYSSTAT_UNLOCK(); 74 | return; 75 | } 76 | 77 | static void *report_apstatus(void *arg) 78 | { 79 | int ret; 80 | struct apstatus_t *ap; 81 | 82 | int bufsize = sizeof(struct msg_ap_status_t) + 83 | sizeof(struct apstatus_t); 84 | char *buf = calloc(1, bufsize); 85 | if(buf == 0) { 86 | sys_err("Malloc for report apstatus failed:%s ", 87 | strerror(errno)); 88 | exit(-1); 89 | } 90 | 91 | int proto; 92 | /* tcp do not use chap to protect */ 93 | fill_msg_header((void *)buf, MSG_AP_STATUS, NULL, 0); 94 | 95 | /* ap will first connect remote ac, but if 96 | * find local ac, ap will connect to local ac */ 97 | while(1) { 98 | proto = (sysstat.sock >= 0) ? MSG_PROTO_TCP : MSG_PROTO_ETH; 99 | if(proto == MSG_PROTO_ETH) { 100 | ac_reconnect(); 101 | goto wait; 102 | } 103 | 104 | ap = get_apstatus(); 105 | memcpy(buf + sizeof(struct msg_ap_status_t), 106 | ap, sizeof(struct apstatus_t)); 107 | 108 | ret = net_send(proto, sysstat.sock, 109 | sysstat.dmac, buf, bufsize); 110 | if(ret <= 0 && proto == MSG_PROTO_TCP) { 111 | ac_lost(); 112 | ac_reconnect(); 113 | } 114 | wait: 115 | sys_debug("report ap status (next %d seconds later)\n", 116 | argument.reportitv); 117 | sleep(argument.reportitv); 118 | } 119 | return NULL; 120 | } 121 | 122 | static int __uuid_equ(char *src, char *dest) 123 | { 124 | return !strncmp(src, dest, UUID_LEN - 1); 125 | } 126 | 127 | /* XXX: only use in !reg stat, 128 | * there is impossible have 10 ac in local */ 129 | #define LOCAL_AC_MAX (10) 130 | struct mac_random_map_t { 131 | uint32_t random; 132 | char mac[ETH_ALEN]; 133 | }; 134 | static struct mac_random_map_t random_map[LOCAL_AC_MAX] = {{0}}; 135 | 136 | static int offset = 0; 137 | static uint32_t new_random(char *mac) 138 | { 139 | uint32_t random; 140 | random_map[offset].random = chap_get_random(); 141 | memcpy(random_map[offset].mac, mac, ETH_ALEN); 142 | random = random_map[offset].random; 143 | offset = (offset + 1) % LOCAL_AC_MAX; 144 | return random; 145 | } 146 | 147 | static uint32_t get_random(char *mac) 148 | { 149 | int i, j; 150 | /* offset should be check first */ 151 | for(i = offset - 1, j = 0; j < LOCAL_AC_MAX; i++, j++) { 152 | if(!memcmp(mac, random_map[i % LOCAL_AC_MAX].mac, ETH_ALEN)) 153 | return random_map[i % LOCAL_AC_MAX].random; 154 | } 155 | return 0; 156 | } 157 | 158 | static void _proc_brd(struct msg_ac_brd_t *msg, int len, int proto) 159 | { 160 | /* send current ipv4 */ 161 | struct msg_ap_reg_t *resp = 162 | malloc(sizeof(struct msg_ap_reg_t)); 163 | if(resp == NULL) { 164 | sys_warn("Malloc for response failed:%s\n", 165 | strerror(errno)); 166 | return; 167 | } 168 | 169 | /* generate random1 */ 170 | fill_msg_header((void *)resp, MSG_AP_REG, 171 | msg->header.acuuid, new_random(msg->header.mac)); 172 | resp->ipv4 = argument.addr; 173 | 174 | /* calculate chap: md5sum1 = packet + random0 + password */ 175 | chap_fill_msg_md5((void *)resp, sizeof(*resp), msg->header.random); 176 | net_send(proto, -1, &msg->header.mac[0], 177 | (void *)resp, sizeof(struct msg_ap_reg_t)); 178 | free(resp); 179 | } 180 | 181 | static void 182 | _proc_brd_isreg(struct msg_ac_brd_t *msg, int len, int proto) 183 | { 184 | if(!__uuid_equ(&msg->header.acuuid[0], &sysstat.acuuid[0])) { 185 | if(__uuid_equ(&msg->takeover[0], &sysstat.acuuid[0])) { 186 | if(sysstat.sock >= 0) { 187 | close(sysstat.sock); 188 | sysstat.sock = -1; 189 | } 190 | _proc_brd(msg, len, proto); 191 | } else { 192 | /* tell the broadcast ac, ap have reg in other ac */ 193 | struct msg_ap_resp_t *resp = 194 | malloc(sizeof(struct msg_ap_resp_t)); 195 | if(resp == NULL) { 196 | sys_warn("Malloc for response failed:%s\n", 197 | strerror(errno)); 198 | return; 199 | } 200 | fill_msg_header(resp, MSG_AP_RESP, 201 | msg->header.acuuid, 202 | new_random(msg->header.mac)); 203 | 204 | /* calculate chap */ 205 | chap_fill_msg_md5(resp, sizeof(*resp), 206 | msg->header.random); 207 | net_send(proto, -1, &msg->header.mac[0], 208 | (void *)resp, sizeof(struct msg_ap_resp_t)); 209 | free(resp); 210 | } 211 | } 212 | } 213 | 214 | /* 215 | * reponse_brd recv broadcast msg from ac and update sysstat 216 | * */ 217 | static void proc_brd(struct msg_ac_brd_t *msg, int len, int proto) 218 | { 219 | assert(proto == MSG_PROTO_ETH); 220 | 221 | sys_debug("receive ac broadcast packet\n"); 222 | if(len < sizeof(*msg)) { 223 | sys_err("receive error msg ac broadcast packet\n"); 224 | return; 225 | } 226 | 227 | if(sysstat.isreg) 228 | _proc_brd_isreg(msg, len, proto); 229 | else 230 | _proc_brd(msg, len, proto); 231 | } 232 | 233 | static int addr_equ(struct sockaddr_in *addr) 234 | { 235 | if(addr->sin_addr.s_addr == argument.addr.sin_addr.s_addr) 236 | return 1; 237 | return 0; 238 | } 239 | 240 | static int setaddr(struct sockaddr *addr) 241 | { 242 | struct ifreq req; 243 | strncpy(req.ifr_name, argument.nic, IFNAMSIZ); 244 | req.ifr_addr = *addr; 245 | req.ifr_addr.sa_family = AF_INET; 246 | 247 | sys_debug("Set client nic ip: %s, addr: %s\n", req.ifr_name, 248 | inet_ntoa(((struct sockaddr_in *)&req.ifr_addr)->sin_addr)); 249 | 250 | int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 251 | if(sockfd < 0) { 252 | sys_err("Create socket failed: %s(%d)\n", 253 | strerror(errno), errno); 254 | return 0; 255 | } 256 | 257 | int ret; 258 | ret = ioctl(sockfd, SIOCSIFADDR, &req); 259 | if(ret < 0) { 260 | sys_err("Set ap addr failed: %s(%d)\n", 261 | strerror(errno), errno); 262 | close(sockfd); 263 | return 0; 264 | } 265 | close(sockfd); 266 | return 1; 267 | } 268 | 269 | static void 270 | proc_reg_resp(struct msg_ac_reg_resp_t *msg, int len, int proto) 271 | { 272 | sys_debug("Receive ac reg response packet\n"); 273 | if(len < sizeof(*msg)) { 274 | sys_err("Receive error msg ac reg response packet\n"); 275 | return; 276 | } 277 | 278 | /* md5sum3 = packet + random1 + password */ 279 | if(chap_msg_cmp_md5((void *)msg, sizeof(*msg), 280 | get_random(msg->header.mac))) { 281 | sys_err("ac reg response packet chap error\n"); 282 | return; 283 | } 284 | 285 | strncpy(sysstat.acuuid, msg->header.acuuid, UUID_LEN); 286 | memcpy(sysstat.dmac, msg->header.mac, ETH_ALEN); 287 | if(msg->acaddr.sin_addr.s_addr) 288 | sysstat.server = msg->acaddr; 289 | if(msg->apaddr.sin_addr.s_addr) 290 | setaddr((void *)&msg->apaddr); 291 | 292 | pr_ipv4(&msg->acaddr); 293 | 294 | /* if have connect to remote ac, close it. 295 | * and connect to local ac */ 296 | if(sysstat.sock >= 0) 297 | close(sysstat.sock); 298 | 299 | ac_reconnect(); 300 | sysstat.isreg = 1; 301 | } 302 | 303 | static void __exec_cmd(struct msg_ac_cmd_t *cmd) 304 | { 305 | sys_debug("receive ac command packet\n"); 306 | printf("cmd: %s\n", cmd->cmd); 307 | } 308 | 309 | static int is_mine(struct msg_head_t *msg) 310 | { 311 | return 1; 312 | } 313 | 314 | void msg_proc(struct msg_head_t *msg, int len, int proto) 315 | { 316 | if(!is_mine(msg)) 317 | return; 318 | 319 | switch(msg->msg_type) { 320 | case MSG_AC_BRD: 321 | proc_brd((void *)msg, len, proto); 322 | break; 323 | case MSG_AC_REG_RESP: 324 | proc_reg_resp((void *)msg, len, proto); 325 | break; 326 | case MSG_AC_CMD: 327 | __exec_cmd((struct msg_ac_cmd_t *)msg); 328 | break; 329 | default: 330 | break; 331 | } 332 | } 333 | 334 | void ac_lost() 335 | { 336 | sys_debug("ac lost\n"); 337 | delete_sockarr(sysstat.sock); 338 | sysstat.sock = -1; 339 | } 340 | 341 | void init_report() 342 | { 343 | /* init remote ac address */ 344 | sysstat.server = argument.acaddr; 345 | create_pthread(report_apstatus, NULL); 346 | } 347 | -------------------------------------------------------------------------------- /ap/process.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: process.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月26日 10时18分54秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __PROCESS_H__ 19 | #define __PROCESS_H__ 20 | #include 21 | #include 22 | #include "msg.h" 23 | struct sysstat_t { 24 | /* only used by local ac */ 25 | char acuuid[UUID_LEN]; 26 | char dmac[ETH_ALEN]; 27 | int isreg; 28 | 29 | /* used by local ac and remote ac */ 30 | int sock; 31 | struct sockaddr_in server; 32 | pthread_mutex_t lock; 33 | }; 34 | 35 | void ac_lost(); 36 | void init_report(); 37 | extern struct sysstat_t sysstat; 38 | void msg_proc(struct msg_head_t *msg, int len, int proto); 39 | #endif /* __PROCESS_H__ */ 40 | -------------------------------------------------------------------------------- /include/apstatus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: apstatus.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年09月01日 15时28分40秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __APSTATUS_H__ 19 | #define __APSTATUS_H__ 20 | #define SSID_MAXLEN (256) 21 | 22 | struct ssid_t { 23 | char ssid[SSID_MAXLEN]; 24 | int power; 25 | }; 26 | 27 | struct apstatus_t { 28 | int ssidnum; 29 | struct ssid_t ssid0; 30 | struct ssid_t ssid1; 31 | struct ssid_t ssid2; 32 | }; 33 | 34 | struct apstatus_t *get_apstatus(); 35 | #endif /* __APSTATUS_H__ */ 36 | -------------------------------------------------------------------------------- /include/arg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: arg.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月18日 17时37分02秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __ARG_H__ 19 | #define __ARG_H__ 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #define ACPORT (7960) 26 | struct arg_t { 27 | int port; 28 | #ifdef SERVER 29 | int brditv; 30 | int reschkitv; 31 | #endif 32 | #ifdef CLIENT 33 | int reportitv; 34 | struct sockaddr_in acaddr; 35 | #endif 36 | int msgitv; 37 | char nic[IFNAMSIZ]; 38 | char mac[ETH_ALEN]; 39 | struct sockaddr_in addr; 40 | }; 41 | 42 | enum { 43 | ARG_DEBUG = 1, 44 | ARG_WARN, 45 | ARG_LOCK, 46 | }; 47 | 48 | extern struct arg_t argument; 49 | extern int debug; 50 | extern int daemon_mode; 51 | 52 | void help(); 53 | void proc_cfgarg(); 54 | void proc_cmdarg(int argc, char *argv[]); 55 | void proc_arg(int argc, char *argv[]); 56 | #endif /* __ARG_H__ */ 57 | -------------------------------------------------------------------------------- /include/chap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: chap.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年10月28日 17时10分56秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __CHAP_H__ 19 | #define __CHAP_H__ 20 | 21 | #include 22 | #include "md5.h" 23 | 24 | struct msg_head_t; 25 | 26 | #define CHAP_LEN (16) 27 | void chap_get_md5(uint8_t *data, int len, uint32_t random, uint8_t *decrypt); 28 | int chap_cmp_md5(uint8_t *data, int len, uint32_t random, uint8_t *oldmd5); 29 | int chap_msg_cmp_md5(struct msg_head_t *msg, int len, uint32_t random); 30 | void chap_fill_msg_md5(struct msg_head_t *msg, int len, int random); 31 | uint32_t chap_get_random(); 32 | #endif /* __CHAP_H__ */ 33 | -------------------------------------------------------------------------------- /include/dllayer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: dllayer.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月19日 14时40分14秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __DLLLAYER_H__ 19 | #define __DLLLAYER_H__ 20 | #include 21 | 22 | #define ETH_INNO (0x8d8d) 23 | #define DLL_PKT_MAXLEN (512) 24 | #define DLL_PKT_DATALEN (DLL_PKT_MAXLEN - sizeof(struct ethhdr)) 25 | void dll_init(char *nic, int *rcvsock, int *sdrsock, int *brdsock); 26 | int dll_brdcast(char *data, int size); 27 | int dll_sendpkt(char *dmac, char *data, int size); 28 | int dll_rcv(char *data, int size); 29 | 30 | #endif /* __DLLAYER_H__ */ 31 | -------------------------------------------------------------------------------- /include/link.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: link.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月27日 09时43分55秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __LINK_H__ 19 | #define __LINK_H__ 20 | #include 21 | #include 22 | #include "dllayer.h" 23 | #include "netlayer.h" 24 | 25 | enum { 26 | MSG_PROTO_ETH = 8000, 27 | MSG_PROTO_TCP, 28 | }; 29 | 30 | struct sockarr_t { 31 | struct epoll_event ev; 32 | 33 | int sock; 34 | uint32_t retevents; 35 | void *(*func) (void *); 36 | void *arg; 37 | 38 | struct sockarr_t *next; 39 | }; 40 | 41 | void net_epoll_init(); 42 | 43 | int delete_sockarr(int sock); 44 | struct sockarr_t * insert_sockarr(int sock, void *(*func) (void *), void *arg); 45 | 46 | void * net_recv(void *arg); 47 | int net_send(int proto, int sock, char *dmac, char *msg, int size); 48 | #endif /* __LINK_H__ */ 49 | -------------------------------------------------------------------------------- /include/list.h: -------------------------------------------------------------------------------- 1 | #ifndef _LINUX_LIST_H 2 | #define _LINUX_LIST_H 3 | 4 | #define LIST_POISON1 (NULL) 5 | #define LIST_POISON2 (NULL) 6 | 7 | struct list_head { 8 | struct list_head *next, *prev; 9 | }; 10 | 11 | struct hlist_head { 12 | struct hlist_node *first; 13 | }; 14 | 15 | struct hlist_node { 16 | struct hlist_node *next, **pprev; 17 | }; 18 | 19 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 20 | /** 21 | * container_of - cast a member of a structure out to the containing structure 22 | * @ptr: the pointer to the member. 23 | * @type: the type of the container struct this is embedded in. 24 | * @member: the name of the member within the struct. 25 | * 26 | */ 27 | #define container_of(ptr, type, member) ({ \ 28 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 29 | (type *)( (char *)__mptr - offsetof(type,member) );}) 30 | 31 | /* 32 | * Simple doubly linked list implementation. 33 | * 34 | * Some of the internal functions ("__xxx") are useful when 35 | * manipulating whole lists rather than single entries, as 36 | * sometimes we already know the next/prev entries and we can 37 | * generate better code by using them directly rather than 38 | * using the generic single-entry routines. 39 | */ 40 | 41 | #define LIST_HEAD_INIT(name) { &(name), &(name) } 42 | 43 | #define LIST_HEAD(name) \ 44 | struct list_head name = LIST_HEAD_INIT(name) 45 | 46 | static inline void INIT_LIST_HEAD(struct list_head *list) 47 | { 48 | list->next = list; 49 | list->prev = list; 50 | } 51 | 52 | /* 53 | * Insert a new entry between two known consecutive entries. 54 | * 55 | * This is only for internal list manipulation where we know 56 | * the prev/next entries already! 57 | */ 58 | static inline void __list_add(struct list_head *new, 59 | struct list_head *prev, 60 | struct list_head *next) 61 | { 62 | next->prev = new; 63 | new->next = next; 64 | new->prev = prev; 65 | prev->next = new; 66 | } 67 | 68 | /** 69 | * _list_add - add a new entry 70 | * @new: new entry to be added 71 | * @head: list head to add it after 72 | * 73 | * Insert a new entry after the specified head. 74 | * This is good for implementing stacks. 75 | */ 76 | static inline void _list_add(struct list_head *new, struct list_head *head) 77 | { 78 | __list_add(new, head, head->next); 79 | } 80 | 81 | 82 | /** 83 | * list_add_tail - add a new entry 84 | * @new: new entry to be added 85 | * @head: list head to add it before 86 | * 87 | * Insert a new entry before the specified head. 88 | * This is useful for implementing queues. 89 | */ 90 | static inline void list_add_tail(struct list_head *new, struct list_head *head) 91 | { 92 | __list_add(new, head->prev, head); 93 | } 94 | 95 | /* 96 | * Delete a list entry by making the prev/next entries 97 | * point to each other. 98 | * 99 | * This is only for internal list manipulation where we know 100 | * the prev/next entries already! 101 | */ 102 | static inline void __list_del(struct list_head * prev, struct list_head * next) 103 | { 104 | next->prev = prev; 105 | prev->next = next; 106 | } 107 | 108 | /** 109 | * list_del - deletes entry from list. 110 | * @entry: the element to delete from the list. 111 | * Note: list_empty() on entry does not return true after this, the entry is 112 | * in an undefined state. 113 | */ 114 | static inline void __list_del_entry(struct list_head *entry) 115 | { 116 | __list_del(entry->prev, entry->next); 117 | } 118 | 119 | static inline void list_del(struct list_head *entry) 120 | { 121 | __list_del(entry->prev, entry->next); 122 | entry->next = LIST_POISON1; 123 | entry->prev = LIST_POISON2; 124 | } 125 | 126 | /** 127 | * list_replace - replace old entry by new one 128 | * @old : the element to be replaced 129 | * @new : the new element to insert 130 | * 131 | * If @old was empty, it will be overwritten. 132 | */ 133 | static inline void list_replace(struct list_head *old, 134 | struct list_head *new) 135 | { 136 | new->next = old->next; 137 | new->next->prev = new; 138 | new->prev = old->prev; 139 | new->prev->next = new; 140 | } 141 | 142 | static inline void list_replace_init(struct list_head *old, 143 | struct list_head *new) 144 | { 145 | list_replace(old, new); 146 | INIT_LIST_HEAD(old); 147 | } 148 | 149 | /** 150 | * list_del_init - deletes entry from list and reinitialize it. 151 | * @entry: the element to delete from the list. 152 | */ 153 | static inline void list_del_init(struct list_head *entry) 154 | { 155 | __list_del_entry(entry); 156 | INIT_LIST_HEAD(entry); 157 | } 158 | 159 | /** 160 | * list_move - delete from one list and add as another's head 161 | * @list: the entry to move 162 | * @head: the head that will precede our entry 163 | */ 164 | static inline void list_move(struct list_head *list, struct list_head *head) 165 | { 166 | __list_del_entry(list); 167 | _list_add(list, head); 168 | } 169 | 170 | /** 171 | * list_move_tail - delete from one list and add as another's tail 172 | * @list: the entry to move 173 | * @head: the head that will follow our entry 174 | */ 175 | static inline void list_move_tail(struct list_head *list, 176 | struct list_head *head) 177 | { 178 | __list_del_entry(list); 179 | list_add_tail(list, head); 180 | } 181 | 182 | /** 183 | * list_is_last - tests whether @list is the last entry in list @head 184 | * @list: the entry to test 185 | * @head: the head of the list 186 | */ 187 | static inline int list_is_last(const struct list_head *list, 188 | const struct list_head *head) 189 | { 190 | return list->next == head; 191 | } 192 | 193 | /** 194 | * list_empty - tests whether a list is empty 195 | * @head: the list to test. 196 | */ 197 | static inline int list_empty(const struct list_head *head) 198 | { 199 | return head->next == head; 200 | } 201 | 202 | /** 203 | * list_empty_careful - tests whether a list is empty and not being modified 204 | * @head: the list to test 205 | * 206 | * Description: 207 | * tests whether a list is empty _and_ checks that no other CPU might be 208 | * in the process of modifying either member (next or prev) 209 | * 210 | * NOTE: using list_empty_careful() without synchronization 211 | * can only be safe if the only activity that can happen 212 | * to the list entry is list_del_init(). Eg. it cannot be used 213 | * if another CPU could re-list_add() it. 214 | */ 215 | static inline int list_empty_careful(const struct list_head *head) 216 | { 217 | struct list_head *next = head->next; 218 | return (next == head) && (next == head->prev); 219 | } 220 | 221 | /** 222 | * list_rotate_left - rotate the list to the left 223 | * @head: the head of the list 224 | */ 225 | static inline void list_rotate_left(struct list_head *head) 226 | { 227 | struct list_head *first; 228 | 229 | if (!list_empty(head)) { 230 | first = head->next; 231 | list_move_tail(first, head); 232 | } 233 | } 234 | 235 | /** 236 | * list_is_singular - tests whether a list has just one entry. 237 | * @head: the list to test. 238 | */ 239 | static inline int list_is_singular(const struct list_head *head) 240 | { 241 | return !list_empty(head) && (head->next == head->prev); 242 | } 243 | 244 | static inline void __list_cut_position(struct list_head *list, 245 | struct list_head *head, struct list_head *entry) 246 | { 247 | struct list_head *new_first = entry->next; 248 | list->next = head->next; 249 | list->next->prev = list; 250 | list->prev = entry; 251 | entry->next = list; 252 | head->next = new_first; 253 | new_first->prev = head; 254 | } 255 | 256 | /** 257 | * list_cut_position - cut a list into two 258 | * @list: a new list to add all removed entries 259 | * @head: a list with entries 260 | * @entry: an entry within head, could be the head itself 261 | * and if so we won't cut the list 262 | * 263 | * This helper moves the initial part of @head, up to and 264 | * including @entry, from @head to @list. You should 265 | * pass on @entry an element you know is on @head. @list 266 | * should be an empty list or a list you do not care about 267 | * losing its data. 268 | * 269 | */ 270 | static inline void list_cut_position(struct list_head *list, 271 | struct list_head *head, struct list_head *entry) 272 | { 273 | if (list_empty(head)) 274 | return; 275 | if (list_is_singular(head) && 276 | (head->next != entry && head != entry)) 277 | return; 278 | if (entry == head) 279 | INIT_LIST_HEAD(list); 280 | else 281 | __list_cut_position(list, head, entry); 282 | } 283 | 284 | static inline void __list_splice(const struct list_head *list, 285 | struct list_head *prev, 286 | struct list_head *next) 287 | { 288 | struct list_head *first = list->next; 289 | struct list_head *last = list->prev; 290 | 291 | first->prev = prev; 292 | prev->next = first; 293 | 294 | last->next = next; 295 | next->prev = last; 296 | } 297 | 298 | /** 299 | * list_splice - join two lists, this is designed for stacks 300 | * @list: the new list to add. 301 | * @head: the place to add it in the first list. 302 | */ 303 | static inline void list_splice(const struct list_head *list, 304 | struct list_head *head) 305 | { 306 | if (!list_empty(list)) 307 | __list_splice(list, head, head->next); 308 | } 309 | 310 | /** 311 | * list_splice_tail - join two lists, each list being a queue 312 | * @list: the new list to add. 313 | * @head: the place to add it in the first list. 314 | */ 315 | static inline void list_splice_tail(struct list_head *list, 316 | struct list_head *head) 317 | { 318 | if (!list_empty(list)) 319 | __list_splice(list, head->prev, head); 320 | } 321 | 322 | /** 323 | * list_splice_init - join two lists and reinitialise the emptied list. 324 | * @list: the new list to add. 325 | * @head: the place to add it in the first list. 326 | * 327 | * The list at @list is reinitialised 328 | */ 329 | static inline void list_splice_init(struct list_head *list, 330 | struct list_head *head) 331 | { 332 | if (!list_empty(list)) { 333 | __list_splice(list, head, head->next); 334 | INIT_LIST_HEAD(list); 335 | } 336 | } 337 | 338 | /** 339 | * list_splice_tail_init - join two lists and reinitialise the emptied list 340 | * @list: the new list to add. 341 | * @head: the place to add it in the first list. 342 | * 343 | * Each of the lists is a queue. 344 | * The list at @list is reinitialised 345 | */ 346 | static inline void list_splice_tail_init(struct list_head *list, 347 | struct list_head *head) 348 | { 349 | if (!list_empty(list)) { 350 | __list_splice(list, head->prev, head); 351 | INIT_LIST_HEAD(list); 352 | } 353 | } 354 | 355 | /** 356 | * list_entry - get the struct for this entry 357 | * @ptr: the &struct list_head pointer. 358 | * @type: the type of the struct this is embedded in. 359 | * @member: the name of the list_struct within the struct. 360 | */ 361 | #define list_entry(ptr, type, member) \ 362 | container_of(ptr, type, member) 363 | 364 | /** 365 | * list_first_entry - get the first element from a list 366 | * @ptr: the list head to take the element from. 367 | * @type: the type of the struct this is embedded in. 368 | * @member: the name of the list_struct within the struct. 369 | * 370 | * Note, that list is expected to be not empty. 371 | */ 372 | #define list_first_entry(ptr, type, member) \ 373 | list_entry((ptr)->next, type, member) 374 | 375 | /** 376 | * list_for_each - iterate over a list 377 | * @pos: the &struct list_head to use as a loop cursor. 378 | * @head: the head for your list. 379 | */ 380 | #define list_for_each(pos, head) \ 381 | for (pos = (head)->next; pos != (head); pos = pos->next) 382 | 383 | /** 384 | * list_for_each_prev - iterate over a list backwards 385 | * @pos: the &struct list_head to use as a loop cursor. 386 | * @head: the head for your list. 387 | */ 388 | #define list_for_each_prev(pos, head) \ 389 | for (pos = (head)->prev; pos != (head); pos = pos->prev) 390 | 391 | /** 392 | * list_for_each_safe - iterate over a list safe against removal of list entry 393 | * @pos: the &struct list_head to use as a loop cursor. 394 | * @n: another &struct list_head to use as temporary storage 395 | * @head: the head for your list. 396 | */ 397 | #define list_for_each_safe(pos, n, head) \ 398 | for (pos = (head)->next, n = pos->next; pos != (head); \ 399 | pos = n, n = pos->next) 400 | 401 | /** 402 | * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry 403 | * @pos: the &struct list_head to use as a loop cursor. 404 | * @n: another &struct list_head to use as temporary storage 405 | * @head: the head for your list. 406 | */ 407 | #define list_for_each_prev_safe(pos, n, head) \ 408 | for (pos = (head)->prev, n = pos->prev; \ 409 | pos != (head); \ 410 | pos = n, n = pos->prev) 411 | 412 | /** 413 | * list_for_each_entry - iterate over list of given type 414 | * @pos: the type * to use as a loop cursor. 415 | * @head: the head for your list. 416 | * @member: the name of the list_struct within the struct. 417 | */ 418 | #define list_for_each_entry(pos, head, member) \ 419 | for (pos = list_entry((head)->next, typeof(*pos), member); \ 420 | &pos->member != (head); \ 421 | pos = list_entry(pos->member.next, typeof(*pos), member)) 422 | 423 | /** 424 | * list_for_each_entry_reverse - iterate backwards over list of given type. 425 | * @pos: the type * to use as a loop cursor. 426 | * @head: the head for your list. 427 | * @member: the name of the list_struct within the struct. 428 | */ 429 | #define list_for_each_entry_reverse(pos, head, member) \ 430 | for (pos = list_entry((head)->prev, typeof(*pos), member); \ 431 | &pos->member != (head); \ 432 | pos = list_entry(pos->member.prev, typeof(*pos), member)) 433 | 434 | /** 435 | * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() 436 | * @pos: the type * to use as a start point 437 | * @head: the head of the list 438 | * @member: the name of the list_struct within the struct. 439 | * 440 | * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). 441 | */ 442 | #define list_prepare_entry(pos, head, member) \ 443 | ((pos) ? : list_entry(head, typeof(*pos), member)) 444 | 445 | /** 446 | * list_for_each_entry_continue - continue iteration over list of given type 447 | * @pos: the type * to use as a loop cursor. 448 | * @head: the head for your list. 449 | * @member: the name of the list_struct within the struct. 450 | * 451 | * Continue to iterate over list of given type, continuing after 452 | * the current position. 453 | */ 454 | #define list_for_each_entry_continue(pos, head, member) \ 455 | for (pos = list_entry(pos->member.next, typeof(*pos), member); \ 456 | &pos->member != (head); \ 457 | pos = list_entry(pos->member.next, typeof(*pos), member)) 458 | 459 | /** 460 | * list_for_each_entry_continue_reverse - iterate backwards from the given point 461 | * @pos: the type * to use as a loop cursor. 462 | * @head: the head for your list. 463 | * @member: the name of the list_struct within the struct. 464 | * 465 | * Start to iterate over list of given type backwards, continuing after 466 | * the current position. 467 | */ 468 | #define list_for_each_entry_continue_reverse(pos, head, member) \ 469 | for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ 470 | &pos->member != (head); \ 471 | pos = list_entry(pos->member.prev, typeof(*pos), member)) 472 | 473 | /** 474 | * list_for_each_entry_from - iterate over list of given type from the current point 475 | * @pos: the type * to use as a loop cursor. 476 | * @head: the head for your list. 477 | * @member: the name of the list_struct within the struct. 478 | * 479 | * Iterate over list of given type, continuing from current position. 480 | */ 481 | #define list_for_each_entry_from(pos, head, member) \ 482 | for (; &pos->member != (head); \ 483 | pos = list_entry(pos->member.next, typeof(*pos), member)) 484 | 485 | /** 486 | * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry 487 | * @pos: the type * to use as a loop cursor. 488 | * @n: another type * to use as temporary storage 489 | * @head: the head for your list. 490 | * @member: the name of the list_struct within the struct. 491 | */ 492 | #define list_for_each_entry_safe(pos, n, head, member) \ 493 | for (pos = list_entry((head)->next, typeof(*pos), member), \ 494 | n = list_entry(pos->member.next, typeof(*pos), member); \ 495 | &pos->member != (head); \ 496 | pos = n, n = list_entry(n->member.next, typeof(*n), member)) 497 | 498 | /** 499 | * list_for_each_entry_safe_continue - continue list iteration safe against removal 500 | * @pos: the type * to use as a loop cursor. 501 | * @n: another type * to use as temporary storage 502 | * @head: the head for your list. 503 | * @member: the name of the list_struct within the struct. 504 | * 505 | * Iterate over list of given type, continuing after current point, 506 | * safe against removal of list entry. 507 | */ 508 | #define list_for_each_entry_safe_continue(pos, n, head, member) \ 509 | for (pos = list_entry(pos->member.next, typeof(*pos), member), \ 510 | n = list_entry(pos->member.next, typeof(*pos), member); \ 511 | &pos->member != (head); \ 512 | pos = n, n = list_entry(n->member.next, typeof(*n), member)) 513 | 514 | /** 515 | * list_for_each_entry_safe_from - iterate over list from current point safe against removal 516 | * @pos: the type * to use as a loop cursor. 517 | * @n: another type * to use as temporary storage 518 | * @head: the head for your list. 519 | * @member: the name of the list_struct within the struct. 520 | * 521 | * Iterate over list of given type from current point, safe against 522 | * removal of list entry. 523 | */ 524 | #define list_for_each_entry_safe_from(pos, n, head, member) \ 525 | for (n = list_entry(pos->member.next, typeof(*pos), member); \ 526 | &pos->member != (head); \ 527 | pos = n, n = list_entry(n->member.next, typeof(*n), member)) 528 | 529 | /** 530 | * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal 531 | * @pos: the type * to use as a loop cursor. 532 | * @n: another type * to use as temporary storage 533 | * @head: the head for your list. 534 | * @member: the name of the list_struct within the struct. 535 | * 536 | * Iterate backwards over list of given type, safe against removal 537 | * of list entry. 538 | */ 539 | #define list_for_each_entry_safe_reverse(pos, n, head, member) \ 540 | for (pos = list_entry((head)->prev, typeof(*pos), member), \ 541 | n = list_entry(pos->member.prev, typeof(*pos), member); \ 542 | &pos->member != (head); \ 543 | pos = n, n = list_entry(n->member.prev, typeof(*n), member)) 544 | 545 | /** 546 | * list_safe_reset_next - reset a stale list_for_each_entry_safe loop 547 | * @pos: the loop cursor used in the list_for_each_entry_safe loop 548 | * @n: temporary storage used in list_for_each_entry_safe 549 | * @member: the name of the list_struct within the struct. 550 | * 551 | * list_safe_reset_next is not safe to use in general if the list may be 552 | * modified concurrently (eg. the lock is dropped in the loop body). An 553 | * exception to this is if the cursor element (pos) is pinned in the list, 554 | * and list_safe_reset_next is called after re-taking the lock and before 555 | * completing the current iteration of the loop body. 556 | */ 557 | #define list_safe_reset_next(pos, n, member) \ 558 | n = list_entry(pos->member.next, typeof(*pos), member) 559 | 560 | /* 561 | * Double linked lists with a single pointer list head. 562 | * Mostly useful for hash tables where the two pointer list head is 563 | * too wasteful. 564 | * You lose the ability to access the tail in O(1). 565 | */ 566 | 567 | #define HLIST_HEAD_INIT { .first = NULL } 568 | #define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } 569 | #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) 570 | static inline void INIT_HLIST_NODE(struct hlist_node *h) 571 | { 572 | h->next = NULL; 573 | h->pprev = NULL; 574 | } 575 | 576 | static inline int hlist_unhashed(const struct hlist_node *h) 577 | { 578 | return !h->pprev; 579 | } 580 | 581 | static inline int hlist_empty(const struct hlist_head *h) 582 | { 583 | return !h->first; 584 | } 585 | 586 | static inline void __hlist_del(struct hlist_node *n) 587 | { 588 | struct hlist_node *next = n->next; 589 | struct hlist_node **pprev = n->pprev; 590 | *pprev = next; 591 | if (next) 592 | next->pprev = pprev; 593 | } 594 | 595 | static inline void hlist_del(struct hlist_node *n) 596 | { 597 | __hlist_del(n); 598 | n->next = LIST_POISON1; 599 | n->pprev = LIST_POISON2; 600 | } 601 | 602 | static inline void hlist_del_init(struct hlist_node *n) 603 | { 604 | if (!hlist_unhashed(n)) { 605 | __hlist_del(n); 606 | INIT_HLIST_NODE(n); 607 | } 608 | } 609 | 610 | static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) 611 | { 612 | struct hlist_node *first = h->first; 613 | n->next = first; 614 | if (first) 615 | first->pprev = &n->next; 616 | h->first = n; 617 | n->pprev = &h->first; 618 | } 619 | 620 | /* next must be != NULL */ 621 | static inline void hlist_add_before(struct hlist_node *n, 622 | struct hlist_node *next) 623 | { 624 | n->pprev = next->pprev; 625 | n->next = next; 626 | next->pprev = &n->next; 627 | *(n->pprev) = n; 628 | } 629 | 630 | static inline void hlist_add_after(struct hlist_node *n, 631 | struct hlist_node *next) 632 | { 633 | next->next = n->next; 634 | n->next = next; 635 | next->pprev = &n->next; 636 | 637 | if(next->next) 638 | next->next->pprev = &next->next; 639 | } 640 | 641 | /* after that we'll appear to be on some hlist and hlist_del will work */ 642 | static inline void hlist_add_fake(struct hlist_node *n) 643 | { 644 | n->pprev = &n->next; 645 | } 646 | 647 | /* 648 | * Move a list from one list head to another. Fixup the pprev 649 | * reference of the first entry if it exists. 650 | */ 651 | static inline void hlist_move_list(struct hlist_head *old, 652 | struct hlist_head *new) 653 | { 654 | new->first = old->first; 655 | if (new->first) 656 | new->first->pprev = &new->first; 657 | old->first = NULL; 658 | } 659 | 660 | #define hlist_entry(ptr, type, member) container_of(ptr,type,member) 661 | 662 | #define hlist_for_each(pos, head) \ 663 | for (pos = (head)->first; pos ; pos = pos->next) 664 | 665 | #define hlist_for_each_safe(pos, n, head) \ 666 | for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ 667 | pos = n) 668 | 669 | /** 670 | * hlist_for_each_entry - iterate over list of given type 671 | * @tpos: the type * to use as a loop cursor. 672 | * @pos: the &struct hlist_node to use as a loop cursor. 673 | * @head: the head for your list. 674 | * @member: the name of the hlist_node within the struct. 675 | */ 676 | #define hlist_for_each_entry(tpos, pos, head, member) \ 677 | for (pos = (head)->first; \ 678 | pos && \ 679 | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ 680 | pos = pos->next) 681 | 682 | /** 683 | * hlist_for_each_entry_continue - iterate over a hlist continuing after current point 684 | * @tpos: the type * to use as a loop cursor. 685 | * @pos: the &struct hlist_node to use as a loop cursor. 686 | * @member: the name of the hlist_node within the struct. 687 | */ 688 | #define hlist_for_each_entry_continue(tpos, pos, member) \ 689 | for (pos = (pos)->next; \ 690 | pos && \ 691 | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ 692 | pos = pos->next) 693 | 694 | /** 695 | * hlist_for_each_entry_from - iterate over a hlist continuing from current point 696 | * @tpos: the type * to use as a loop cursor. 697 | * @pos: the &struct hlist_node to use as a loop cursor. 698 | * @member: the name of the hlist_node within the struct. 699 | */ 700 | #define hlist_for_each_entry_from(tpos, pos, member) \ 701 | for (; pos && \ 702 | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ 703 | pos = pos->next) 704 | 705 | /** 706 | * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry 707 | * @tpos: the type * to use as a loop cursor. 708 | * @pos: the &struct hlist_node to use as a loop cursor. 709 | * @n: another &struct hlist_node to use as temporary storage 710 | * @head: the head for your list. 711 | * @member: the name of the hlist_node within the struct. 712 | */ 713 | #define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ 714 | for (pos = (head)->first; \ 715 | pos && ({ n = pos->next; 1; }) && \ 716 | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ 717 | pos = n) 718 | 719 | #endif 720 | -------------------------------------------------------------------------------- /include/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: log.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年06月16日 09时59分21秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __LOG_H__ 19 | #define __LOG_H__ 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "arg.h" 26 | 27 | extern int debug; 28 | 29 | #define SYSLOG_ERR (LOG_ERR|LOG_USER) 30 | #define SYSLOG_WARN (LOG_WARNING|LOG_USER) 31 | #define SYSLOG_DEBUG (LOG_DEBUG|LOG_USER) 32 | #define SYSLOG_INFO (LOG_INFO|LOG_USER) 33 | #define SYSLOG_LOCK (LOG_NOTICE|LOG_USER) 34 | 35 | #define __sys_log2(fmt, ...) \ 36 | do { \ 37 | syslog(SYSLOG_INFO, fmt, ##__VA_ARGS__); \ 38 | if(debug) fprintf(stderr, fmt, ##__VA_ARGS__); \ 39 | } while(0) 40 | 41 | #define __sys_log(LEVEL, fmt, ...) \ 42 | do { \ 43 | int __debug = 0; \ 44 | syslog(LEVEL, "(%u)%s +%d %s(): "fmt, \ 45 | (unsigned int)pthread_self(), __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); \ 46 | switch(debug) { \ 47 | case ARG_DEBUG: \ 48 | __debug = (LEVEL == SYSLOG_DEBUG) ? 1: 0; \ 49 | break; \ 50 | case ARG_WARN: \ 51 | __debug = (LEVEL == SYSLOG_WARN) ? 1: 0; \ 52 | break; \ 53 | case ARG_LOCK: \ 54 | __debug = (LEVEL == SYSLOG_LOCK) ? 1: 0; \ 55 | break; \ 56 | default: \ 57 | __debug = 1; \ 58 | } \ 59 | if(__debug) \ 60 | fprintf(stderr, "(%u)%s +%d %s(): "fmt, \ 61 | (unsigned int)pthread_self(), __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); \ 62 | } while(0) 63 | 64 | #define sys_err(fmt, ...) __sys_log(SYSLOG_ERR, "ERR: "fmt, ##__VA_ARGS__) 65 | 66 | #ifdef DEBUG 67 | #define sys_warn(fmt, ...) __sys_log(SYSLOG_WARN, "WARNING: "fmt, ##__VA_ARGS__) 68 | #define sys_debug(fmt, ...) __sys_log(SYSLOG_DEBUG, "DEBUG: "fmt, ##__VA_ARGS__) 69 | #define sys_lock(fmt, ...) __sys_log(SYSLOG_LOCK, "LOCK: "fmt, ##__VA_ARGS__) 70 | #define pure_info(fmt, ...) __sys_log2(fmt, ##__VA_ARGS__) 71 | #else 72 | #define sys_warn(fmt, ...) NULL 73 | #define sys_debug(fmt, ...) NULL 74 | #define sys_lock(fmt, ...) NULL 75 | #define pure_info(fmt, ...) NULL 76 | #endif 77 | 78 | #ifdef DEBUG 79 | #define pr_ap(mac, uuid) \ 80 | do { \ 81 | unsigned char *_mac = (void *)(mac); \ 82 | sys_debug("%02x:%02x:%02x:%02x:%02x:%02x reg in: %s\n", \ 83 | (_mac)[0], (_mac)[1], (_mac)[2], (_mac)[3], (_mac)[4], (_mac)[5], \ 84 | uuid); \ 85 | } while(0) 86 | 87 | #define pr_mac(mac) \ 88 | do { \ 89 | unsigned char *_mac = (void *)(mac); \ 90 | sys_debug("%02x:%02x:%02x:%02x:%02x:%02x\n", \ 91 | (_mac)[0], (_mac)[1], (_mac)[2], (_mac)[3], (_mac)[4], (_mac)[5]); \ 92 | } while(0) 93 | 94 | #define pr_ipv4(addr) \ 95 | do { \ 96 | char _buf[20]; \ 97 | inet_ntop(AF_INET, &(addr)->sin_addr, _buf, 19); \ 98 | sys_debug("address:%s, port:%d\n", _buf, ntohs((addr)->sin_port)); \ 99 | } while(0) 100 | 101 | #define pr_hash(key, aphash, mac) \ 102 | do { \ 103 | unsigned char *_mac = (void *)(mac); \ 104 | sys_debug("key: %d, aphash: %p, mac: %02x:%02x:%02x:%02x:%02x:%02x\n", \ 105 | key, aphash, \ 106 | (_mac)[0], (_mac)[1], (_mac)[2], (_mac)[3], (_mac)[4], (_mac)[5]); \ 107 | } while(0) 108 | 109 | #define pr_md5(md5) \ 110 | do { \ 111 | unsigned char *_md5 = (void *)(md5); \ 112 | sys_debug("md5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", \ 113 | (_md5)[0], (_md5)[1], (_md5)[2], (_md5)[3], \ 114 | (_md5)[4], (_md5)[5], (_md5)[6], (_md5)[7], \ 115 | (_md5)[8], (_md5)[9], (_md5)[10], (_md5)[11], \ 116 | (_md5)[12], (_md5)[13], (_md5)[14], (_md5)[15]); \ 117 | }while(0) 118 | 119 | #define pr_pkt(pkt, len) \ 120 | do { \ 121 | int _i; \ 122 | unsigned char *_pkt = (void *)pkt; \ 123 | for(_i = 0; _i < len; _i++) { \ 124 | pure_info("%02x ", _pkt[_i]); \ 125 | if(!((_i + 1) % 8)) pure_info("\t"); \ 126 | if(!((_i + 1) % 16)) pure_info("\n"); \ 127 | } \ 128 | pure_info("\n"); \ 129 | }while(0) 130 | 131 | #else 132 | #define pr_ap(mac, uuid) NULL 133 | #define pr_mac(mac) NULL 134 | #define pr_ipv4(addr) NULL 135 | #define pr_hash(key, aphash, mac) NULL 136 | #define pr_md5(md5) NULL 137 | #define pr_pkt(pkt, len) NULL 138 | #endif 139 | 140 | #endif /* __LOG_H__ */ 141 | -------------------------------------------------------------------------------- /include/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: md5_sum.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2013年09月17日 17时02分58秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef MD5_H 19 | #define MD5_H 20 | 21 | typedef struct 22 | { 23 | unsigned int count[2]; 24 | unsigned int state[4]; 25 | unsigned char buffer[64]; 26 | }MD5_CTX; 27 | 28 | 29 | #define F(x,y,z) ((x & y) | (~x & z)) 30 | #define G(x,y,z) ((x & z) | (y & ~z)) 31 | #define H(x,y,z) (x^y^z) 32 | #define I(x,y,z) (y ^ (x | ~z)) 33 | #define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) 34 | #define FF(a,b,c,d,x,s,ac) \ 35 | { \ 36 | a += F(b,c,d) + x + ac; \ 37 | a = ROTATE_LEFT(a,s); \ 38 | a += b; \ 39 | } 40 | #define GG(a,b,c,d,x,s,ac) \ 41 | { \ 42 | a += G(b,c,d) + x + ac; \ 43 | a = ROTATE_LEFT(a,s); \ 44 | a += b; \ 45 | } 46 | #define HH(a,b,c,d,x,s,ac) \ 47 | { \ 48 | a += H(b,c,d) + x + ac; \ 49 | a = ROTATE_LEFT(a,s); \ 50 | a += b; \ 51 | } 52 | #define II(a,b,c,d,x,s,ac) \ 53 | { \ 54 | a += I(b,c,d) + x + ac; \ 55 | a = ROTATE_LEFT(a,s); \ 56 | a += b; \ 57 | } 58 | void MD5Init(MD5_CTX *context); 59 | void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen); 60 | void MD5Final(MD5_CTX *context,unsigned char digest[16]); 61 | void MD5Transform(unsigned int state[4],unsigned char block[64]); 62 | void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len); 63 | void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len); 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /include/mjson.h: -------------------------------------------------------------------------------- 1 | /* Structures for JSON parsing using only fixed-extent memory 2 | * 3 | * This file is Copyright (c) 2014 by Eric S. Raymond. 4 | * BSD terms apply: see the file COPYING in the distribution root for details. 5 | */ 6 | #ifndef __MJSON_H__ 7 | #define __MJSON_H__ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define NITEMS(x) (int)(sizeof(x)/sizeof(x[0])) 15 | 16 | typedef enum {t_integer, t_uinteger, t_real, 17 | t_string, t_boolean, t_character, 18 | t_time, 19 | t_object, t_structobject, t_array, 20 | t_check, t_ignore} 21 | json_type; 22 | 23 | struct json_enum_t { 24 | char *name; 25 | int value; 26 | }; 27 | 28 | struct json_array_t { 29 | json_type element_type; 30 | union { 31 | struct { 32 | const struct json_attr_t *subtype; 33 | char *base; 34 | size_t stride; 35 | } objects; 36 | struct { 37 | char **ptrs; 38 | char *store; 39 | int storelen; 40 | } strings; 41 | struct { 42 | int *store; 43 | } integers; 44 | struct { 45 | unsigned int *store; 46 | } uintegers; 47 | struct { 48 | double *store; 49 | } reals; 50 | struct { 51 | bool *store; 52 | } booleans; 53 | } arr; 54 | int *count, maxlen; 55 | }; 56 | 57 | struct json_attr_t { 58 | char *attribute; 59 | json_type type; 60 | union { 61 | int *integer; 62 | unsigned int *uinteger; 63 | double *real; 64 | char *string; 65 | bool *boolean; 66 | char *character; 67 | struct json_array_t array; 68 | size_t offset; 69 | } addr; 70 | union { 71 | int integer; 72 | unsigned int uinteger; 73 | double real; 74 | bool boolean; 75 | char character; 76 | char *check; 77 | } dflt; 78 | size_t len; 79 | const struct json_enum_t *map; 80 | bool nodefault; 81 | }; 82 | 83 | #define JSON_ATTR_MAX 31 /* max chars in JSON attribute name */ 84 | #define JSON_VAL_MAX 512 /* max chars in JSON value part */ 85 | 86 | #ifdef __cplusplus 87 | extern "C" { 88 | #endif 89 | int json_read_object(const char *, const struct json_attr_t *, 90 | /*@null@*/const char **); 91 | int json_read_array(const char *, const struct json_array_t *, 92 | /*@null@*/const char **); 93 | const /*@observer@*/char *json_error_string(int); 94 | 95 | void json_enable_debug(int, FILE *); 96 | #ifdef __cplusplus 97 | } 98 | #endif 99 | 100 | #define JSON_ERR_OBSTART 1 /* non-WS when expecting object start */ 101 | #define JSON_ERR_ATTRSTART 2 /* non-WS when expecting attrib start */ 102 | #define JSON_ERR_BADATTR 3 /* unknown attribute name */ 103 | #define JSON_ERR_ATTRLEN 4 /* attribute name too long */ 104 | #define JSON_ERR_NOARRAY 5 /* saw [ when not expecting array */ 105 | #define JSON_ERR_NOBRAK 6 /* array element specified, but no [ */ 106 | #define JSON_ERR_STRLONG 7 /* string value too long */ 107 | #define JSON_ERR_TOKLONG 8 /* token value too long */ 108 | #define JSON_ERR_BADTRAIL 9 /* garbage while expecting comma or } or ] */ 109 | #define JSON_ERR_ARRAYSTART 10 /* didn't find expected array start */ 110 | #define JSON_ERR_OBJARR 11 /* error while parsing object array */ 111 | #define JSON_ERR_SUBTOOLONG 12 /* too many array elements */ 112 | #define JSON_ERR_BADSUBTRAIL 13 /* garbage while expecting array comma */ 113 | #define JSON_ERR_SUBTYPE 14 /* unsupported array element type */ 114 | #define JSON_ERR_BADSTRING 15 /* error while string parsing */ 115 | #define JSON_ERR_CHECKFAIL 16 /* check attribute not matched */ 116 | #define JSON_ERR_NOPARSTR 17 /* can't support strings in parallel arrays */ 117 | #define JSON_ERR_BADENUM 18 /* invalid enumerated value */ 118 | #define JSON_ERR_QNONSTRING 19 /* saw quoted value when expecting nonstring */ 119 | #define JSON_ERR_NONQSTRING 19 /* didn't see quoted value when expecting string */ 120 | #define JSON_ERR_MISC 20 /* other data conversion error */ 121 | #define JSON_ERR_BADNUM 21 /* error while parsing a numerical argument */ 122 | #define JSON_ERR_NULLPTR 22 /* unexpected null value or attribute pointer */ 123 | 124 | /* 125 | * Use the following macros to declare template initializers for structobject 126 | * arrays. Writing the equivalents out by hand is error-prone. 127 | * 128 | * STRUCTOBJECT takes a structure name s, and a fieldname f in s. 129 | * 130 | * STRUCTARRAY takes the name of a structure array, a pointer to a an 131 | * initializer defining the subobject type, and the address of an integer to 132 | * store the length in. 133 | */ 134 | #define STRUCTOBJECT(s, f) .addr.offset = offsetof(s, f) 135 | #define STRUCTARRAY(a, e, n) \ 136 | .addr.array.element_type = t_structobject, \ 137 | .addr.array.arr.objects.subtype = e, \ 138 | .addr.array.arr.objects.base = (char*)a, \ 139 | .addr.array.arr.objects.stride = sizeof(a[0]), \ 140 | .addr.array.count = n, \ 141 | .addr.array.maxlen = (int)(sizeof(a)/sizeof(a[0])) 142 | 143 | /* json.h ends here */ 144 | 145 | 146 | #define JSON_ENCODE_START(buf, len) \ 147 | do { \ 148 | int _hread = snprintf(buf, len, "{"); \ 149 | len -= _hread; buf+= _hread; \ 150 | }while(0) 151 | 152 | #define JSON_ENCODE(buf, len, key, value) \ 153 | do { \ 154 | int _hread = snprintf(buf, len, "\"%s\":\"%s\",", key, value); \ 155 | len -= _hread; buf+= _hread; \ 156 | }while(0) 157 | 158 | #define JSON_ENCODE_END(buf, len) \ 159 | do { \ 160 | assert(len >= 2); \ 161 | if(buf[-1] == ',') { \ 162 | buf[-1] = 0; \ 163 | len++; buf--; \ 164 | } \ 165 | snprintf(buf, len, "}"); \ 166 | }while(0) 167 | 168 | #endif /* __MJSON_H__*/ 169 | -------------------------------------------------------------------------------- /include/msg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: msg.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月21日 11时55分55秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __MSG_H__ 19 | #define __MSG_H__ 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "chap.h" 26 | #include "arg.h" 27 | 28 | #define UUID_LEN (50) 29 | 30 | #define MSG_TYPE_START (1000) 31 | /* msg type */ 32 | enum { 33 | MSG_AC_BRD = MSG_TYPE_START, 34 | MSG_AC_CMD, 35 | MSG_AC_REG_RESP, 36 | 37 | MSG_AP_REG, 38 | MAS_AP_ERR, 39 | MSG_AP_RESP, 40 | MSG_AP_STATUS, 41 | }; 42 | 43 | struct msg_head_t { 44 | uint32_t random; 45 | uint8_t chap[CHAP_LEN]; 46 | char acuuid[UUID_LEN]; 47 | char mac[ETH_ALEN]; 48 | int msg_type; 49 | }__attribute__((packed)); 50 | 51 | /* every ap will response ac broadcast */ 52 | #define msg_ap_resp_t msg_head_t 53 | 54 | struct msg_ac_brd_t { 55 | struct msg_head_t header; 56 | char takeover[UUID_LEN]; 57 | }__attribute__((packed)); 58 | 59 | struct msg_ac_cmd_t { 60 | struct msg_head_t header; 61 | char cmd[0]; 62 | }__attribute__((packed)); 63 | 64 | struct msg_ac_reg_resp_t { 65 | struct msg_head_t header; 66 | struct sockaddr_in acaddr; 67 | struct sockaddr_in apaddr; 68 | }__attribute__((packed)); 69 | 70 | struct msg_ap_reg_t { 71 | struct msg_head_t header; 72 | struct sockaddr_in ipv4; 73 | }__attribute__((packed)); 74 | 75 | struct msg_ap_status_t { 76 | struct msg_head_t header; 77 | char status[0]; 78 | }__attribute__((packed)); 79 | 80 | 81 | static void 82 | fill_msg_header(struct msg_head_t *msg, int msgtype, char *uuid, uint32_t random) 83 | { 84 | msg->random = random; 85 | if(uuid) 86 | memcpy(&msg->acuuid[0], 87 | uuid, UUID_LEN); 88 | memcpy(&msg->mac[0], 89 | &argument.mac[0], ETH_ALEN); 90 | msg->msg_type = msgtype; 91 | } 92 | 93 | #endif /* __MSG_H__ */ 94 | -------------------------------------------------------------------------------- /include/netlayer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: netlayer.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月26日 15时55分53秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __NETLAYER_H__ 19 | #define __NETLAYER_H__ 20 | #include 21 | 22 | #define NET_PKT_DATALEN (2048) 23 | 24 | struct nettcp_t { 25 | int sock; 26 | struct sockaddr_in addr; 27 | }; 28 | 29 | int tcp_connect(struct nettcp_t *tcp); 30 | int tcp_rcv(struct nettcp_t *tcp, char *data, int size); 31 | int tcp_sendpkt(struct nettcp_t *tcp, char *data, int size); 32 | void tcp_close(struct nettcp_t *tcp); 33 | #ifdef SERVER 34 | int tcp_listen(struct nettcp_t *tcp); 35 | int tcp_accept(struct nettcp_t *tcp, void *func(void *)); 36 | #endif 37 | #endif /* __NETLAYER_H__ */ 38 | -------------------------------------------------------------------------------- /include/thread.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: thread.h 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月25日 17时19分58秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __THREAD_H__ 19 | #define __THREAD_H__ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #define THREAD pthread_mutex_t 27 | 28 | #define INIT_LOCK(name) \ 29 | THREAD name = PTHREAD_MUTEX_INITIALIZER 30 | 31 | #define LOCK(name) \ 32 | pthread_mutex_lock(name) 33 | 34 | #define TRYLOCK(name) \ 35 | pthread_mutex_lock(name) 36 | 37 | #define UNLOCK(name) \ 38 | pthread_mutex_unlock(name) 39 | 40 | static inline void LOCK_INIT(THREAD *name) 41 | { 42 | pthread_mutex_init(name, NULL); 43 | } 44 | 45 | void create_pthread(void *(*start_routine) (void *), void *arg); 46 | #endif /* __THREAD_H__ */ 47 | -------------------------------------------------------------------------------- /lib/Makefile: -------------------------------------------------------------------------------- 1 | all:$(LIB) 2 | PASSWORD=wirelesser 3 | ifndef PASSWORD 4 | PASSWORD := $(shell read -p "please input chap passwd:" PASSWD; echo $$PASSWD) 5 | endif 6 | CFLAGS += -DPASSWD=\"$(PASSWORD)\" 7 | CMD=$(LIBDIR)/.tmp 8 | FILE = $(shell find . -name "*.c") 9 | OBJ=$(FILE:.c=.o) 10 | $(LIB):$(OBJ) 11 | $(AR) -r $@ $^ 12 | 13 | %.o:%.c $(CMD) 14 | $(CC) $(CFLAGS) -c $< -o $@ 15 | 16 | INFO=$(shell cat $(CMD) 2>/dev/null) 17 | $(CMD): FORCE 18 | -@if [ "$(CC) $(CFLAGS)" != "$(INFO)" ]; then \ 19 | echo "$(CC) $(CFLAGS)" > $@; \ 20 | fi 21 | 22 | FORCE: 23 | PHONY += FORCE 24 | .PHONY: $(PHONY) 25 | -------------------------------------------------------------------------------- /lib/arg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: arg.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月19日 10时19分07秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "arg.h" 29 | #include "log.h" 30 | 31 | struct arg_t argument = {0}; 32 | int debug = 0; 33 | int daemon_mode = 0; 34 | 35 | static void __getmac(char *nic, char *mac) 36 | { 37 | int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 38 | if(sockfd < 0) { 39 | sys_err("Create sock for get mac failed: %s\n", 40 | strerror(errno)); 41 | exit(-1); 42 | } 43 | 44 | struct ifreq req; 45 | strncpy(&req.ifr_name[0], nic, IFNAMSIZ); 46 | ioctl(sockfd, SIOCGIFHWADDR, &req); 47 | memcpy(mac, req.ifr_hwaddr.sa_data, ETH_ALEN); 48 | close(sockfd); 49 | pr_mac(mac); 50 | } 51 | 52 | static void __getaddr(char *nic, struct sockaddr_in *addr) 53 | { 54 | int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 55 | if(sockfd < 0) { 56 | sys_err("Create sock for get mac failed: %s\n", 57 | strerror(errno)); 58 | exit(-1); 59 | } 60 | 61 | struct ifreq req; 62 | strncpy(&req.ifr_name[0], nic, IFNAMSIZ); 63 | ioctl(sockfd, SIOCGIFADDR, &req); 64 | memcpy(addr, &req.ifr_addr, sizeof(struct sockaddr_in)); 65 | close(sockfd); 66 | pr_ipv4(addr); 67 | } 68 | 69 | /* check argment */ 70 | static void __check_arg() 71 | { 72 | if(argument.nic[0] == 0) { 73 | sys_err("No nic specified\n"); 74 | help(); 75 | exit(-1); 76 | } 77 | __getmac(&argument.nic[0], &argument.mac[0]); 78 | __getaddr(&argument.nic[0], &argument.addr); 79 | argument.port = (argument.port == 0) ? ACPORT : argument.port; 80 | #ifdef SERVER 81 | argument.reschkitv = (argument.reschkitv == 0) ? 300 : argument.reschkitv; 82 | /* default ac broadcast interval */ 83 | argument.brditv = (argument.brditv == 0) ? 30 : argument.brditv; 84 | argument.msgitv = (argument.msgitv == 0) ? argument.brditv / 10 : argument.msgitv; 85 | argument.addr.sin_port = htons(argument.port); 86 | pr_ipv4(&argument.addr); 87 | #endif 88 | #ifdef CLIENT 89 | argument.reportitv = (argument.reportitv == 0) ? 30 : argument.reportitv; 90 | argument.msgitv = (argument.msgitv == 0) ? argument.reportitv / 10 : argument.msgitv; 91 | argument.acaddr.sin_port = htons(argument.port); 92 | pr_ipv4(&argument.acaddr); 93 | #endif 94 | } 95 | 96 | void proc_arg(int argc, char *argv[]) 97 | { 98 | proc_cfgarg(); 99 | proc_cmdarg(argc, argv); 100 | __check_arg(); 101 | } 102 | -------------------------------------------------------------------------------- /lib/cfgarg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: cfgarg.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月19日 10时19分42秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | 21 | void proc_cfgarg() 22 | { 23 | return; 24 | } 25 | -------------------------------------------------------------------------------- /lib/chap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: chap.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年10月28日 16时14分55秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include "chap.h" 29 | #include "msg.h" 30 | #include "log.h" 31 | 32 | static char passwd[] = PASSWD; 33 | 34 | void chap_get_md5(uint8_t *data, int len, uint32_t random, uint8_t *decrypt) 35 | { 36 | pr_pkt(data, len); 37 | 38 | MD5_CTX md5; 39 | MD5Init(&md5); 40 | MD5Update(&md5, data, len); 41 | MD5Update(&md5, (void *)&random, sizeof(uint32_t)); 42 | MD5Update(&md5, (void *)&passwd[0], strlen(passwd)); 43 | MD5Final(&md5, decrypt); 44 | sys_debug("data: %p, len: %d, random: %u\n", data, len, random); 45 | pr_md5(decrypt); 46 | 47 | return; 48 | } 49 | 50 | int chap_cmp_md5(uint8_t *data, int len, uint32_t random, uint8_t *oldmd5) 51 | { 52 | uint8_t *decrypt = malloc(CHAP_LEN); 53 | if(!decrypt) { 54 | sys_err("Malloc decrypt failed: %s(%d)\n", 55 | strerror(errno), errno); 56 | return -1; 57 | } 58 | 59 | chap_get_md5(data, len, random, decrypt); 60 | 61 | int ret; 62 | ret = memcmp(decrypt, oldmd5, CHAP_LEN); 63 | free(decrypt); 64 | 65 | return ret; 66 | } 67 | 68 | int chap_msg_cmp_md5(struct msg_head_t *msg, int len, uint32_t random) 69 | { 70 | uint8_t oldmd5[CHAP_LEN]; 71 | memcpy(oldmd5, msg->chap, CHAP_LEN); 72 | memset(msg->chap, 0x0, CHAP_LEN); 73 | return chap_cmp_md5((void *)msg, len, random, oldmd5); 74 | } 75 | 76 | void chap_fill_msg_md5(struct msg_head_t *msg, int len, int random) 77 | { 78 | memset(msg->chap, 0, CHAP_LEN); 79 | chap_get_md5((void *)msg, len, random, msg->chap); 80 | } 81 | 82 | uint32_t chap_get_random() 83 | { 84 | uint32_t random; 85 | int fd = open("/dev/random", O_RDONLY); 86 | read(fd, &random, sizeof(random)); 87 | close(fd); 88 | 89 | sys_debug("Generate a random: %u\n", random); 90 | return random; 91 | } 92 | -------------------------------------------------------------------------------- /lib/cmdarg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: arg.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月19日 10时04分12秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "arg.h" 27 | #include "log.h" 28 | 29 | #define has_arg (1) 30 | static struct option long_arg[] = { 31 | {"nic", has_arg, 0, 'n'}, 32 | {"daemon", 0, 0, 'd'}, 33 | {"port", has_arg, 0, 'p'}, 34 | #ifdef SERVER 35 | {"brditv", has_arg, 0, 'b'}, 36 | {"reschkitv", has_arg, 0, 'c'}, 37 | #endif 38 | #ifdef CLIENT 39 | {"reportitv", has_arg, 0, 'r'}, 40 | {"domain", has_arg, 0, 'a'}, 41 | #endif 42 | {"msgitv", has_arg, 0, 'm'}, 43 | {"debug", has_arg, 0, 'l'}, 44 | {"help", 0, 0, 'h'}, 45 | {0, 0, 0 , 0}, 46 | }; 47 | 48 | #ifdef SERVER 49 | #define SHORT_STR "n:db:p:m:l::hc:" 50 | #endif 51 | #ifdef CLIENT 52 | #define SHORT_STR "n:dm:p:r:l::a:h" 53 | #endif 54 | #ifdef TEST 55 | #define SHORT_STR "n:dm:l::" 56 | #endif 57 | 58 | static char *help_array[] = { 59 | "USAGE: ac [options]", 60 | "acctl server", 61 | " -n, --nic \t\t nic which controller [required]", 62 | " -d, --daemon \t\t daemon mode", 63 | " -p, --port \t\t ac listen port (default 7960)", 64 | #ifdef SERVER 65 | " -b, --brditv \t ac broadcast interval (default 30)", 66 | " -c, --reschkitv \t resource check interval (default 300)", 67 | #endif 68 | #ifdef CLIENT 69 | " -r, --reportitv \t ap report status interval (default 30)", 70 | " -a, --domain \t\t remote ac address(e.g: www.baiud.com, localhost, 192.168.10.1), when no local ac, ap will connect to remote ac", 71 | #endif 72 | " -m, --msgitv \t interval travel all recevied message (default 30)", 73 | " --debug \t enable debug (DEBUG = 1, WARN = 2, LOCK = 3, ALL = other), will auto disable daemon_mode", 74 | " -h, --help \t help info", 75 | NULL, 76 | }; 77 | 78 | void help() 79 | { 80 | char **ptr = &help_array[0]; 81 | while(*ptr != NULL) { 82 | printf("%s\n", *ptr); 83 | ptr++; 84 | } 85 | } 86 | 87 | static void __early_is_debug(int argc,char *argv[]) 88 | { 89 | int i, ret; 90 | for(i = 0; i < argc; i++) { 91 | ret = strcmp(argv[i], "--debug"); 92 | if(ret == 0) { 93 | debug = 4; 94 | return; 95 | } 96 | } 97 | 98 | debug = 0; 99 | return; 100 | } 101 | 102 | static void __early_init(int argc, char *argv[]) 103 | { 104 | if(argc < 2) { 105 | help(); 106 | exit(-1); 107 | } 108 | 109 | memset(&argument, 0, sizeof(argument)); 110 | __early_is_debug(argc, argv); 111 | } 112 | 113 | static long int __strtol(const char *nptr, char **endptr, int base) 114 | { 115 | long int ret; 116 | errno = 0; 117 | ret = strtol(nptr, endptr, base); 118 | if(errno != 0) { 119 | sys_err("argument error:%s\n", nptr); 120 | exit(-1); 121 | } 122 | return ret; 123 | } 124 | 125 | void proc_cmdarg(int argc, char *argv[]) 126 | { 127 | int short_arg; 128 | __early_init(argc, argv); 129 | 130 | #ifdef CLIENT 131 | struct hostent * host; 132 | #endif 133 | while((short_arg = getopt_long(argc, argv, SHORT_STR, long_arg, NULL)) 134 | != -1) { 135 | switch(short_arg) { 136 | case 'n': 137 | strncpy(&argument.nic[0], optarg, IFNAMSIZ-1); 138 | break; 139 | case 'd': 140 | if(!debug) 141 | daemon_mode = 1; 142 | break; 143 | case 'p': 144 | argument.port = 145 | __strtol(optarg, NULL, 10); 146 | break; 147 | #ifdef SERVER 148 | case 'b': 149 | argument.brditv = 150 | __strtol(optarg, NULL, 10); 151 | break; 152 | case 'c': 153 | argument.reschkitv = 154 | __strtol(optarg, NULL, 10); 155 | break; 156 | #endif 157 | #ifdef CLIENT 158 | case 'r': 159 | argument.reportitv = 160 | __strtol(optarg, NULL, 10); 161 | break; 162 | case 'a': 163 | host = gethostbyname(optarg); 164 | if(!host) { 165 | sys_warn("Can not get ac address by: %s\n", 166 | optarg); 167 | break; 168 | } 169 | argument.acaddr.sin_addr = 170 | *((struct in_addr *)host->h_addr); 171 | break; 172 | #endif 173 | case 'l': 174 | debug = __strtol(optarg, NULL, 10); 175 | break; 176 | case 'm': 177 | argument.msgitv = 178 | __strtol(optarg, NULL, 10); 179 | break; 180 | case '?': 181 | break; 182 | case 'h': 183 | help(); 184 | exit(0); 185 | case '*': 186 | break; 187 | default: 188 | fprintf(stderr, "argument: %c error\n", short_arg); 189 | break; 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /lib/dllayer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: dllayer.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月19日 10时34分24秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "log.h" 38 | #include "dllayer.h" 39 | 40 | struct dlleth_t { 41 | struct ethhdr hdr; 42 | char data[0]; 43 | }__attribute__((packed)); 44 | 45 | struct dllnic_t { 46 | char nic[IFNAMSIZ]; 47 | char mac[ETH_ALEN]; 48 | int ifiindex; 49 | } dllnic; 50 | 51 | struct dllsdr_t { 52 | int sdrsock; 53 | char *sdrpkt; 54 | struct sockaddr_ll ll; 55 | pthread_mutex_t lock; 56 | } dllsdr; 57 | 58 | struct dllrcv_t { 59 | int rcvsock; 60 | char *rcvpkt; 61 | socklen_t recvlen; 62 | struct sockaddr_ll ll; 63 | pthread_mutex_t lock; 64 | } dllrcv; 65 | 66 | struct dllbrd_t { 67 | int brdsock; 68 | char *brdpkt; 69 | struct sockaddr_ll ll; 70 | pthread_mutex_t lock; 71 | } dllbrd; 72 | 73 | #define LOCK_RCV() pthread_mutex_lock(&dllrcv.lock) 74 | #define LOCK_BRD() pthread_mutex_lock(&dllbrd.lock) 75 | #define LOCK_SDR() pthread_mutex_lock(&dllsdr.lock) 76 | #define UNLOCK_RCV() pthread_mutex_unlock(&dllrcv.lock) 77 | #define UNLOCK_BRD() pthread_mutex_unlock(&dllbrd.lock) 78 | #define UNLOCK_SDR() pthread_mutex_unlock(&dllsdr.lock) 79 | 80 | static void __init_nic(int sock, char *nic) 81 | { 82 | assert(nic != NULL); 83 | 84 | int ret; 85 | struct ifreq req; 86 | strncpy(req.ifr_name, nic, IFNAMSIZ-1); 87 | ret = ioctl(sock, SIOCGIFINDEX, &req); 88 | if(ret < 0) { 89 | sys_err("Can not get ifiindex of %s: %s\n", 90 | nic, strerror(errno)); 91 | exit(-1); 92 | } 93 | dllnic.ifiindex = req.ifr_ifindex; 94 | 95 | ret = ioctl(sock, SIOCGIFHWADDR, &req); 96 | if(ret < 0) { 97 | sys_err("Can not get mac addr of %s: %s\n", 98 | nic, strerror(errno)); 99 | exit(-1); 100 | } 101 | 102 | strncpy(dllnic.nic, nic, IFNAMSIZ-1); 103 | memcpy(dllnic.mac, req.ifr_hwaddr.sa_data, ETH_ALEN); 104 | } 105 | 106 | static void __init_pktbuf(char *localmac) 107 | { 108 | assert(dllsdr.sdrpkt == NULL && dllrcv.rcvpkt == NULL); 109 | 110 | char *tmp; 111 | tmp = malloc(DLL_PKT_MAXLEN * 3); 112 | if(tmp == NULL) { 113 | sys_err("Init dllayer pkt buffer failed: %s\n", 114 | strerror(errno)); 115 | exit(-1); 116 | } 117 | dllsdr.sdrpkt = tmp; 118 | dllrcv.rcvpkt = tmp + DLL_PKT_MAXLEN; 119 | dllbrd.brdpkt = tmp + (DLL_PKT_MAXLEN << 1); 120 | 121 | struct ethhdr *eth = (void *)dllsdr.sdrpkt; 122 | memcpy(eth->h_source, localmac, ETH_ALEN); 123 | eth->h_proto = htons(ETH_INNO); 124 | 125 | eth = (void *)dllbrd.brdpkt; 126 | memcpy(eth->h_source, localmac, ETH_ALEN); 127 | memset(eth->h_dest, 0xff, ETH_ALEN); 128 | eth->h_proto = htons(ETH_INNO); 129 | } 130 | 131 | int __create_sock(int brdcst) 132 | { 133 | int sock; 134 | sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_INNO)); 135 | if(sock < 0) { 136 | sys_err("Create dllayer socket failed: %s\n", 137 | strerror(errno)); 138 | exit(-1); 139 | } 140 | 141 | if(brdcst) { 142 | int ret; 143 | ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, 144 | &brdcst, sizeof(brdcst)); 145 | if(ret < 0) { 146 | sys_err("Enable broadcast mode failed: %s\n", 147 | strerror(errno)); 148 | exit(-1); 149 | } 150 | } 151 | return sock; 152 | } 153 | 154 | void __build_brdll() 155 | { 156 | struct sockaddr_ll *ll = &dllbrd.ll; 157 | memset(ll, 0, sizeof(struct sockaddr_ll)); 158 | 159 | ll->sll_family = PF_PACKET; 160 | ll->sll_ifindex = dllnic.ifiindex; 161 | ll->sll_halen = ETH_ALEN; 162 | memset(ll->sll_addr, 0xff, 6); 163 | ll->sll_addr[6] = 0x00; 164 | ll->sll_addr[7] = 0x00; 165 | } 166 | 167 | void __build_rcvll(int bind) 168 | { 169 | dllrcv.recvlen = sizeof(struct sockaddr_ll); 170 | 171 | struct sockaddr_ll *ll = &dllrcv.ll; 172 | memset(ll, 0, sizeof(struct sockaddr_ll)); 173 | 174 | if(bind) { 175 | ll->sll_family = PF_PACKET; 176 | ll->sll_protocol = htons(ETH_INNO); 177 | ll->sll_ifindex = dllnic.ifiindex; 178 | } else { 179 | ll->sll_family = PF_PACKET; 180 | ll->sll_protocol = htons(ETH_INNO); 181 | ll->sll_ifindex = dllnic.ifiindex; 182 | ll->sll_pkttype = PACKET_HOST; 183 | } 184 | } 185 | 186 | void __build_sdrll(char *mac) 187 | { 188 | struct sockaddr_ll *ll = &dllsdr.ll; 189 | memset(ll, 0, sizeof(struct sockaddr_ll)); 190 | 191 | ll->sll_family = PF_PACKET; 192 | ll->sll_ifindex = dllnic.ifiindex; 193 | ll->sll_halen = ETH_ALEN; 194 | memcpy(ll->sll_addr, mac, ETH_ALEN); 195 | ll->sll_addr[6] = 0x00; 196 | ll->sll_addr[7] = 0x00; 197 | } 198 | 199 | void __init_brdcast(int *sock) 200 | { 201 | pthread_mutex_init(&dllbrd.lock, NULL); 202 | dllbrd.brdsock = __create_sock(1); 203 | if(sock) 204 | *sock = dllbrd.brdsock; 205 | __build_brdll(); 206 | } 207 | 208 | void __dll_buildpkt(char *dmac, char *data, int size) 209 | { 210 | assert(dmac != NULL && data != NULL && 211 | size <= DLL_PKT_DATALEN); 212 | 213 | struct dlleth_t *deth = (void *)dllsdr.sdrpkt; 214 | memcpy(&deth->hdr.h_dest[0], dmac, ETH_ALEN); 215 | 216 | memcpy(deth->data, data, size); 217 | } 218 | 219 | static void __init_sdr(int *sock) 220 | { 221 | pthread_mutex_init(&dllsdr.lock, NULL); 222 | dllsdr.sdrsock = __create_sock(0); 223 | if(sock) 224 | *sock = dllsdr.sdrsock; 225 | } 226 | 227 | static void __init_rcv(int *sock) 228 | { 229 | int ret; 230 | 231 | pthread_mutex_init(&dllrcv.lock, NULL); 232 | dllrcv.rcvsock = __create_sock(0); 233 | if(sock) 234 | *sock = dllrcv.rcvsock; 235 | 236 | __build_rcvll(1); 237 | ret = bind(dllrcv.rcvsock, (struct sockaddr *)&dllrcv.ll, 238 | dllrcv.recvlen); 239 | if(ret < 0) { 240 | sys_err("Bind recive socket failed: %s\n", 241 | strerror(errno)); 242 | exit(-1); 243 | } 244 | } 245 | 246 | int dll_sendpkt(char *dmac, char *data, int size) 247 | { 248 | assert(dmac != NULL && size <= DLL_PKT_DATALEN && 249 | data != NULL); 250 | int ret; 251 | 252 | LOCK_SDR(); 253 | __dll_buildpkt(dmac, data, size); 254 | __build_sdrll(dmac); 255 | 256 | ret = sendto(dllsdr.sdrsock, dllsdr.sdrpkt, 257 | size + sizeof(struct ethhdr), 0, 258 | (struct sockaddr *)&dllsdr.ll, sizeof(dllsdr.ll)); 259 | if(ret < 0) { 260 | sys_warn("send packet failed: %s\n", 261 | strerror(errno)); 262 | UNLOCK_SDR(); 263 | return -1; 264 | } 265 | UNLOCK_SDR(); 266 | return 0; 267 | } 268 | 269 | int dll_brdcast(char *data, int size) 270 | { 271 | assert(size <= DLL_PKT_DATALEN && data != NULL); 272 | 273 | int ret; 274 | struct dlleth_t *deth = (void *)dllbrd.brdpkt; 275 | 276 | LOCK_BRD(); 277 | memcpy(&deth->data, data, size); 278 | 279 | ret = sendto(dllbrd.brdsock, dllbrd.brdpkt, 280 | size + sizeof(struct ethhdr), 0, 281 | (struct sockaddr *)&dllbrd.ll, sizeof(dllbrd.ll)); 282 | if(ret < 0) { 283 | sys_warn("broad cast failed: %s\n", 284 | strerror(errno)); 285 | UNLOCK_BRD(); 286 | return -1; 287 | } 288 | 289 | UNLOCK_BRD(); 290 | return 0; 291 | } 292 | 293 | int dll_rcv(char *data, int size) 294 | { 295 | assert(size <= DLL_PKT_DATALEN && data != NULL); 296 | 297 | dllrcv.recvlen = sizeof(struct sockaddr_ll); 298 | 299 | int ret; 300 | LOCK_RCV(); 301 | __build_rcvll(0); 302 | ret = recvfrom(dllrcv.rcvsock, dllrcv.rcvpkt, 303 | DLL_PKT_MAXLEN, 0, 304 | (struct sockaddr *)&dllrcv.ll, &dllrcv.recvlen); 305 | if(ret < sizeof(struct ethhdr)) { 306 | sys_warn("recv pkt failed: %s\n", strerror(errno)); 307 | UNLOCK_RCV(); 308 | return -1; 309 | } 310 | 311 | struct ethhdr *hdr = (struct ethhdr *)dllrcv.rcvpkt; 312 | if(ntohs(hdr->h_proto) != ETH_INNO) { 313 | sys_warn("Reciv error dllayer packet\n"); 314 | return -1; 315 | } 316 | 317 | memcpy(data, dllrcv.rcvpkt + sizeof(struct ethhdr), size); 318 | UNLOCK_RCV(); 319 | return (ret > size) ? size: ret; 320 | } 321 | 322 | void dll_init(char *nic, int *rcvsock, int *sdrsock, int *brdsock) 323 | { 324 | assert(nic != NULL); 325 | 326 | int sock = __create_sock(0); 327 | __init_nic(sock, nic); 328 | close(sock); 329 | __init_pktbuf(&dllnic.mac[0]); 330 | __init_brdcast(brdsock); 331 | __init_rcv(rcvsock); 332 | __init_sdr(sdrsock); 333 | } 334 | 335 | -------------------------------------------------------------------------------- /lib/link.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: link.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年09月02日 14时27分53秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "log.h" 32 | #include "link.h" 33 | 34 | static pthread_mutex_t sockarr_lock = PTHREAD_MUTEX_INITIALIZER; 35 | static struct sockarr_t *__head = NULL; 36 | static struct sockarr_t **__tail = &__head; 37 | #define SOCKARR_LOCK() \ 38 | do { \ 39 | sys_lock("sockarr lock\n"); \ 40 | pthread_mutex_lock(&sockarr_lock); \ 41 | }while(0) 42 | 43 | #define SOCKARR_UNLOCK() \ 44 | do { \ 45 | sys_lock("sockarr unlock\n"); \ 46 | pthread_mutex_unlock(&sockarr_lock); \ 47 | }while(0) 48 | 49 | int epl; 50 | 51 | static int net_nonblock(int socket) 52 | { 53 | int flags; 54 | 55 | flags = fcntl(socket, F_GETFL, 0); 56 | if(flags < 0) { 57 | sys_err("Get socket flags failed: %s(%d)\n", 58 | strerror(errno), errno); 59 | return -1; 60 | } 61 | 62 | if(fcntl(socket, F_SETFL, flags | O_NONBLOCK) < 0) { 63 | sys_err("Set socket flags failed: %s(%d)\n", 64 | strerror(errno), errno); 65 | return -1; 66 | } 67 | 68 | return 0; 69 | } 70 | void net_epoll_init() 71 | { 72 | epl = epoll_create1(EPOLL_CLOEXEC); 73 | if(epl < 0) { 74 | sys_err("Create epoll failed: %s(%d)\n", 75 | strerror(epl), epl); 76 | exit(-1); 77 | } 78 | 79 | return; 80 | } 81 | 82 | #define EPOLLNUM (10) 83 | static struct epoll_event epollarr[EPOLLNUM]; 84 | 85 | void * net_recv(void *arg) 86 | { 87 | int ret, i; 88 | struct sockarr_t *sockarr; 89 | 90 | while(1) { 91 | ret = epoll_wait(epl, epollarr, EPOLLNUM, -1); 92 | if(ret < 0) { 93 | if(errno == EINTR) 94 | continue; 95 | sys_err("Epoll wait failed: %s(%d)\n", 96 | strerror(errno), errno); 97 | exit(-1); 98 | } 99 | 100 | for(i = 0; i < ret; i++) { 101 | sockarr = epollarr[i].data.ptr; 102 | sockarr->retevents = epollarr[i].events; 103 | if(epollarr[i].events & EPOLLRDHUP) { 104 | sys_debug("Epool get err: %s %s(%d)\n", 105 | "EPOLLRDHUP", strerror(errno), errno); 106 | } else if(epollarr[i].events & EPOLLERR) { 107 | sys_debug("Epool get err: %s %s(%d)\n", 108 | "EPOLLERR", strerror(errno), errno); 109 | } else if(epollarr[i].events & EPOLLHUP) { 110 | sys_debug("Epool get err: %s %s(%d)\n", 111 | "EPOLLHUP", strerror(errno), errno); 112 | } 113 | 114 | sockarr->func(sockarr); 115 | } 116 | } 117 | return NULL; 118 | } 119 | 120 | int net_send(int proto, int sock, char *dmac, char *msg, int size) 121 | { 122 | switch(proto) { 123 | case MSG_PROTO_ETH: 124 | sys_debug("Send packet through datalink layer\n"); 125 | return dll_sendpkt(dmac, msg, size); 126 | case MSG_PROTO_TCP: 127 | if(sock < 0) { 128 | sys_err("Invalid socket: %d\n", sock); 129 | return -1; 130 | } 131 | 132 | sys_debug("Send packet through net layer, sock: %d, msg: %p, size: %d\n", 133 | sock, msg, size); 134 | struct nettcp_t net; 135 | net.sock = sock; 136 | return tcp_sendpkt(&net, msg, size); 137 | default: 138 | sys_err("Invalid protocol\n"); 139 | return -1; 140 | } 141 | return -1; 142 | } 143 | 144 | struct sockarr_t * 145 | insert_sockarr(int sock, void *(*func) (void *), void *arg) 146 | { 147 | 148 | int ret; 149 | ret = net_nonblock(sock); 150 | if(ret < 0) 151 | return NULL; 152 | 153 | struct sockarr_t *__sock = malloc(sizeof(struct sockarr_t)); 154 | if(__sock == NULL) { 155 | sys_err("Malloc sockarr failed: %s\n", strerror(errno)); 156 | exit(-1); 157 | } 158 | __sock->ev.events = EPOLLIN | EPOLLRDHUP | EPOLLET; 159 | __sock->ev.data.ptr = __sock; 160 | __sock->sock = sock; 161 | __sock->func = func; 162 | __sock->arg = arg; 163 | __sock->next = NULL; 164 | 165 | /* add in epoll */ 166 | ret = epoll_ctl(epl, EPOLL_CTL_ADD, 167 | __sock->sock, &__sock->ev); 168 | if(ret < 0) { 169 | sys_err("Add epoll fd failed: %s(%d)\n", 170 | strerror(errno), errno); 171 | exit(-1); 172 | } 173 | 174 | SOCKARR_LOCK(); 175 | *__tail = __sock; 176 | __tail = &__sock->next; 177 | SOCKARR_UNLOCK(); 178 | 179 | return __sock; 180 | } 181 | 182 | int delete_sockarr(int sock) 183 | { 184 | struct sockarr_t *cur; 185 | struct sockarr_t **ppre; 186 | 187 | SOCKARR_LOCK(); 188 | cur = __head; 189 | ppre = &__head; 190 | 191 | int ret; 192 | while(cur) { 193 | if(cur->sock == sock) { 194 | *ppre = cur->next; 195 | if(&cur->next == __tail) 196 | __tail = ppre; 197 | SOCKARR_UNLOCK(); 198 | 199 | ret = epoll_ctl(epl, EPOLL_CTL_DEL, sock, NULL); 200 | if(ret < 0) 201 | sys_err("Delete epoll sock: %d failed: %s(%d)\n", 202 | sock, strerror(errno), errno); 203 | close(sock); 204 | free(cur); 205 | return 0; 206 | } 207 | ppre = &cur->next; 208 | cur = cur->next; 209 | } 210 | SOCKARR_UNLOCK(); 211 | return 0; 212 | } 213 | 214 | -------------------------------------------------------------------------------- /lib/md5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: md5.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2013年09月17日 17时03分53秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include "md5.h" 20 | 21 | unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 22 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 23 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 24 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 25 | 26 | void MD5Init(MD5_CTX *context) 27 | { 28 | context->count[0] = 0; 29 | context->count[1] = 0; 30 | context->state[0] = 0x67452301; 31 | context->state[1] = 0xEFCDAB89; 32 | context->state[2] = 0x98BADCFE; 33 | context->state[3] = 0x10325476; 34 | } 35 | void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen) 36 | { 37 | unsigned int i = 0,index = 0,partlen = 0; 38 | index = (context->count[0] >> 3) & 0x3F; 39 | partlen = 64 - index; 40 | context->count[0] += inputlen << 3; 41 | if(context->count[0] < (inputlen << 3)) 42 | context->count[1]++; 43 | context->count[1] += inputlen >> 29; 44 | 45 | if(inputlen >= partlen) 46 | { 47 | memcpy(&context->buffer[index],input,partlen); 48 | MD5Transform(context->state,context->buffer); 49 | for(i = partlen;i+64 <= inputlen;i+=64) 50 | MD5Transform(context->state,&input[i]); 51 | index = 0; 52 | } 53 | else 54 | { 55 | i = 0; 56 | } 57 | memcpy(&context->buffer[index],&input[i],inputlen-i); 58 | } 59 | void MD5Final(MD5_CTX *context,unsigned char digest[16]) 60 | { 61 | unsigned int index = 0,padlen = 0; 62 | unsigned char bits[8]; 63 | index = (context->count[0] >> 3) & 0x3F; 64 | padlen = (index < 56)?(56-index):(120-index); 65 | MD5Encode(bits,context->count,8); 66 | MD5Update(context,PADDING,padlen); 67 | MD5Update(context,bits,8); 68 | MD5Encode(digest,context->state,16); 69 | } 70 | void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len) 71 | { 72 | unsigned int i = 0,j = 0; 73 | while(j < len) 74 | { 75 | output[j] = input[i] & 0xFF; 76 | output[j+1] = (input[i] >> 8) & 0xFF; 77 | output[j+2] = (input[i] >> 16) & 0xFF; 78 | output[j+3] = (input[i] >> 24) & 0xFF; 79 | i++; 80 | j+=4; 81 | } 82 | } 83 | void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len) 84 | { 85 | unsigned int i = 0,j = 0; 86 | while(j < len) 87 | { 88 | output[i] = (input[j]) | 89 | (input[j+1] << 8) | 90 | (input[j+2] << 16) | 91 | (input[j+3] << 24); 92 | i++; 93 | j+=4; 94 | } 95 | } 96 | void MD5Transform(unsigned int state[4],unsigned char block[64]) 97 | { 98 | unsigned int a = state[0]; 99 | unsigned int b = state[1]; 100 | unsigned int c = state[2]; 101 | unsigned int d = state[3]; 102 | unsigned int x[64]; 103 | MD5Decode(x,block,64); 104 | FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ 105 | FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ 106 | FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ 107 | FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ 108 | FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ 109 | FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ 110 | FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ 111 | FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ 112 | FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ 113 | FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ 114 | FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ 115 | FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ 116 | FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ 117 | FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ 118 | FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ 119 | FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ 120 | 121 | /* Round 2 */ 122 | GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ 123 | GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ 124 | GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ 125 | GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ 126 | GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ 127 | GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */ 128 | GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ 129 | GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ 130 | GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ 131 | GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ 132 | GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ 133 | GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ 134 | GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ 135 | GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ 136 | GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ 137 | GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ 138 | 139 | /* Round 3 */ 140 | HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ 141 | HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ 142 | HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ 143 | HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ 144 | HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ 145 | HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ 146 | HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ 147 | HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ 148 | HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ 149 | HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ 150 | HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ 151 | HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */ 152 | HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ 153 | HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ 154 | HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ 155 | HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ 156 | 157 | /* Round 4 */ 158 | II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ 159 | II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ 160 | II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ 161 | II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ 162 | II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ 163 | II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ 164 | II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ 165 | II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ 166 | II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ 167 | II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ 168 | II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ 169 | II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ 170 | II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ 171 | II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ 172 | II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ 173 | II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ 174 | state[0] += a; 175 | state[1] += b; 176 | state[2] += c; 177 | state[3] += d; 178 | } 179 | -------------------------------------------------------------------------------- /lib/mjson.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | 3 | NAME 4 | mjson.c - parse JSON into fixed-extent data structures 5 | 6 | DESCRIPTION 7 | This module parses a large subset of JSON (JavaScript Object 8 | Notation). Unlike more general JSON parsers, it doesn't use malloc(3) 9 | and doesn't support polymorphism; you need to give it a set of 10 | template structures describing the expected shape of the incoming 11 | JSON, and it will error out if that shape is not matched. When the 12 | parse succeeds, attribute values will be extracted into static 13 | locations specified in the template structures. 14 | 15 | The "shape" of a JSON object in the type signature of its 16 | attributes (and attribute values, and so on recursively down through 17 | all nestings of objects and arrays). This parser is indifferent to 18 | the order of attributes at any level, but you have to tell it in 19 | advance what the type of each attribute value will be and where the 20 | parsed value will be stored. The template structures may supply 21 | default values to be used when an expected attribute is omitted. 22 | 23 | The preceding paragraph told one fib. A single attribute may 24 | actually have a span of multiple specifications with different 25 | syntactically distinguishable types (e.g. string vs. real vs. integer 26 | vs. boolean, but not signed integer vs. unsigned integer). The parser 27 | will match the right spec against the actual data. 28 | 29 | The dialect this parses has some limitations. First, it cannot 30 | recognize the JSON "null" value. Second, all elements of an array must 31 | be of the same type. Third, characters may not be array elements (this 32 | restriction could be lifted) 33 | 34 | There are separate entry points for beginning a parse of either 35 | JSON object or a JSON array. JSON "float" quantities are actually 36 | stored as doubles. 37 | 38 | This parser processes object arrays in one of two different ways, 39 | defending on whether the array subtype is declared as object or 40 | structobject. 41 | 42 | Object arrays take one base address per object subfield, and are 43 | mapped into parallel C arrays (one per subfield). Strings are not 44 | supported in this kind of array, as they don't have a "natural" size 45 | to use as an offset multiplier. 46 | 47 | Structobjects arrays are a way to parse a list of objects to a set 48 | of modifications to a corresponding array of C structs. The trick is 49 | that the array object initialization has to specify both the C struct 50 | array's base address and the stride length (the size of the C struct). 51 | If you initialize the offset fields with the correct offsetof calls, 52 | everything will work. Strings are supported but all string storage 53 | has to be inline in the struct. 54 | 55 | PERMISSIONS 56 | This file is Copyright (c) 2014 by Eric S. Raymond 57 | BSD terms apply: see the file COPYING in the distribution root for details. 58 | 59 | ***************************************************************************/ 60 | /* The strptime prototype is not provided unless explicitly requested. 61 | * We also need to set the value high enough to signal inclusion of 62 | * newer features (like clock_gettime). See the POSIX spec for more info: 63 | * http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_02_01_02 */ 64 | #define _XOPEN_SOURCE 600 65 | 66 | #include 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | #include 74 | #include /* for HUGE_VAL */ 75 | 76 | #include "mjson.h" 77 | 78 | #ifdef DEBUG_ENABLE 79 | static int debuglevel = 0; 80 | static FILE *debugfp; 81 | 82 | void json_enable_debug(int level, FILE * fp) 83 | /* control the level and destination of debug trace messages */ 84 | { 85 | debuglevel = level; 86 | debugfp = fp; 87 | } 88 | 89 | static void json_trace(int errlevel, const char *fmt, ...) 90 | /* assemble command in printf(3) style */ 91 | { 92 | if (errlevel <= debuglevel) { 93 | char buf[BUFSIZ]; 94 | va_list ap; 95 | 96 | (void)strncpy(buf, "json: ", BUFSIZ-1); 97 | buf[BUFSIZ-1] = '\0'; 98 | va_start(ap, fmt); 99 | (void)vsnprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), fmt, 100 | ap); 101 | va_end(ap); 102 | 103 | (void)fputs(buf, debugfp); 104 | } 105 | } 106 | 107 | # define json_debug_trace(args) (void) json_trace args 108 | #else 109 | # define json_debug_trace(args) /*@i1@*/do { } while (0) 110 | #endif /* DEBUG_ENABLE */ 111 | 112 | /*@-immediatetrans -dependenttrans -usereleased -compdef@*/ 113 | static /*@null@*/ char *json_target_address(const struct json_attr_t *cursor, 114 | /*@null@*/ 115 | const struct json_array_t 116 | *parent, int offset) 117 | { 118 | char *targetaddr = NULL; 119 | if (parent == NULL || parent->element_type != t_structobject) { 120 | /* ordinary case - use the address in the cursor structure */ 121 | switch (cursor->type) { 122 | case t_ignore: 123 | targetaddr = NULL; 124 | break; 125 | case t_integer: 126 | targetaddr = (char *)&cursor->addr.integer[offset]; 127 | break; 128 | case t_uinteger: 129 | targetaddr = (char *)&cursor->addr.uinteger[offset]; 130 | break; 131 | case t_time: 132 | case t_real: 133 | targetaddr = (char *)&cursor->addr.real[offset]; 134 | break; 135 | case t_string: 136 | targetaddr = cursor->addr.string; 137 | break; 138 | case t_boolean: 139 | targetaddr = (char *)&cursor->addr.boolean[offset]; 140 | break; 141 | case t_character: 142 | targetaddr = (char *)&cursor->addr.character[offset]; 143 | break; 144 | default: 145 | targetaddr = NULL; 146 | break; 147 | } 148 | } else 149 | /* tricky case - hacking a member in an array of structures */ 150 | targetaddr = 151 | parent->arr.objects.base + (offset * parent->arr.objects.stride) + 152 | cursor->addr.offset; 153 | json_debug_trace((1, "Target address for %s (offset %d) is %p\n", 154 | cursor->attribute, offset, targetaddr)); 155 | return targetaddr; 156 | } 157 | 158 | #ifdef TIME_ENABLE 159 | static double iso8601_to_unix( /*@in@*/ char *isotime) 160 | /* ISO8601 UTC to Unix UTC */ 161 | { 162 | char *dp = NULL; 163 | double usec; 164 | struct tm tm; 165 | 166 | /*@i1@*/ dp = strptime(isotime, "%Y-%m-%dT%H:%M:%S", &tm); 167 | if (dp == NULL) 168 | return (double)HUGE_VAL; 169 | if (*dp == '.') 170 | usec = strtod(dp, NULL); 171 | else 172 | usec = 0; 173 | return (double)timegm(&tm) + usec; 174 | } 175 | #endif /* TIME_ENABLE */ 176 | 177 | /*@-immediatetrans -dependenttrans +usereleased +compdef@*/ 178 | 179 | static int json_internal_read_object(const char *cp, 180 | const struct json_attr_t *attrs, 181 | /*@null@*/ 182 | const struct json_array_t *parent, 183 | int offset, 184 | /*@null@*/ const char **end) 185 | { 186 | /*@ -nullstate -nullderef -mustfreefresh -nullpass -usedef @*/ 187 | enum 188 | { init, await_attr, in_attr, await_value, in_val_string, 189 | in_escape, in_val_token, post_val, post_array 190 | } state = 0; 191 | #ifdef DEBUG_ENABLE 192 | char *statenames[] = { 193 | "init", "await_attr", "in_attr", "await_value", "in_val_string", 194 | "in_escape", "in_val_token", "post_val", "post_array", 195 | }; 196 | #endif /* DEBUG_ENABLE */ 197 | char attrbuf[JSON_ATTR_MAX + 1], *pattr = NULL; 198 | char valbuf[JSON_VAL_MAX + 1], *pval = NULL; 199 | bool value_quoted = false; 200 | char uescape[5]; /* enough space for 4 hex digits and a NUL */ 201 | const struct json_attr_t *cursor; 202 | int substatus, n, maxlen = 0; 203 | unsigned int u; 204 | const struct json_enum_t *mp; 205 | char *lptr; 206 | 207 | #ifdef S_SPLINT_S 208 | /* prevents gripes about buffers not being completely defined */ 209 | memset(valbuf, '\0', sizeof(valbuf)); 210 | memset(attrbuf, '\0', sizeof(attrbuf)); 211 | #endif /* S_SPLINT_S */ 212 | 213 | if (end != NULL) 214 | *end = NULL; /* give it a well-defined value on parse failure */ 215 | 216 | /* stuff fields with defaults in case they're omitted in the JSON input */ 217 | for (cursor = attrs; cursor->attribute != NULL; cursor++) 218 | if (!cursor->nodefault) { 219 | lptr = json_target_address(cursor, parent, offset); 220 | if (lptr != NULL) 221 | switch (cursor->type) { 222 | case t_integer: 223 | memcpy(lptr, &cursor->dflt.integer, sizeof(int)); 224 | break; 225 | case t_uinteger: 226 | memcpy(lptr, &cursor->dflt.uinteger, sizeof(unsigned int)); 227 | break; 228 | case t_time: 229 | case t_real: 230 | memcpy(lptr, &cursor->dflt.real, sizeof(double)); 231 | break; 232 | case t_string: 233 | if (parent != NULL 234 | && parent->element_type != t_structobject 235 | && offset > 0) 236 | return JSON_ERR_NOPARSTR; 237 | lptr[0] = '\0'; 238 | break; 239 | case t_boolean: 240 | memcpy(lptr, &cursor->dflt.boolean, sizeof(bool)); 241 | break; 242 | case t_character: 243 | lptr[0] = cursor->dflt.character; 244 | break; 245 | case t_object: /* silences a compiler warning */ 246 | case t_structobject: 247 | case t_array: 248 | case t_check: 249 | case t_ignore: 250 | break; 251 | } 252 | } 253 | 254 | json_debug_trace((1, "JSON parse of '%s' begins.\n", cp)); 255 | 256 | /* parse input JSON */ 257 | for (; *cp != '\0'; cp++) { 258 | json_debug_trace((2, "State %-14s, looking at '%c' (%p)\n", 259 | statenames[state], *cp, cp)); 260 | switch (state) { 261 | case init: 262 | if (isspace((unsigned char) *cp)) 263 | continue; 264 | else if (*cp == '{') 265 | state = await_attr; 266 | else { 267 | json_debug_trace((1, 268 | "Non-WS when expecting object start.\n")); 269 | if (end != NULL) 270 | *end = cp; 271 | return JSON_ERR_OBSTART; 272 | } 273 | break; 274 | case await_attr: 275 | if (isspace((unsigned char) *cp)) 276 | continue; 277 | else if (*cp == '"') { 278 | state = in_attr; 279 | pattr = attrbuf; 280 | if (end != NULL) 281 | *end = cp; 282 | } else if (*cp == '}') 283 | break; 284 | else { 285 | json_debug_trace((1, "Non-WS when expecting attribute.\n")); 286 | if (end != NULL) 287 | *end = cp; 288 | return JSON_ERR_ATTRSTART; 289 | } 290 | break; 291 | case in_attr: 292 | if (pattr == NULL) 293 | /* don't update end here, leave at attribute start */ 294 | return JSON_ERR_NULLPTR; 295 | if (*cp == '"') { 296 | *pattr++ = '\0'; 297 | json_debug_trace((1, "Collected attribute name %s\n", 298 | attrbuf)); 299 | for (cursor = attrs; cursor->attribute != NULL; cursor++) { 300 | json_debug_trace((2, "Checking against %s\n", 301 | cursor->attribute)); 302 | if (strcmp(cursor->attribute, attrbuf) == 0) 303 | break; 304 | } 305 | if (cursor->attribute == NULL) { 306 | json_debug_trace((1, 307 | "Unknown attribute name '%s' (attributes begin with '%s').\n", 308 | attrbuf, attrs->attribute)); 309 | /* don't update end here, leave at attribute start */ 310 | return JSON_ERR_BADATTR; 311 | } 312 | state = await_value; 313 | if (cursor->type == t_string) 314 | maxlen = (int)cursor->len - 1; 315 | else if (cursor->type == t_check) 316 | maxlen = (int)strlen(cursor->dflt.check); 317 | else if (cursor->type == t_time || cursor->type == t_ignore) 318 | maxlen = JSON_VAL_MAX; 319 | else if (cursor->map != NULL) 320 | maxlen = (int)sizeof(valbuf) - 1; 321 | pval = valbuf; 322 | } else if (pattr >= attrbuf + JSON_ATTR_MAX - 1) { 323 | json_debug_trace((1, "Attribute name too long.\n")); 324 | /* don't update end here, leave at attribute start */ 325 | return JSON_ERR_ATTRLEN; 326 | } else 327 | *pattr++ = *cp; 328 | break; 329 | case await_value: 330 | if (isspace((unsigned char) *cp) || *cp == ':') 331 | continue; 332 | else if (*cp == '[') { 333 | if (cursor->type != t_array) { 334 | json_debug_trace((1, 335 | "Saw [ when not expecting array.\n")); 336 | if (end != NULL) 337 | *end = cp; 338 | return JSON_ERR_NOARRAY; 339 | } 340 | substatus = json_read_array(cp, &cursor->addr.array, &cp); 341 | if (substatus != 0) 342 | return substatus; 343 | state = post_array; 344 | } else if (cursor->type == t_array) { 345 | json_debug_trace((1, 346 | "Array element was specified, but no [.\n")); 347 | if (end != NULL) 348 | *end = cp; 349 | return JSON_ERR_NOBRAK; 350 | } else if (*cp == '"') { 351 | value_quoted = true; 352 | state = in_val_string; 353 | pval = valbuf; 354 | } else { 355 | value_quoted = false; 356 | state = in_val_token; 357 | pval = valbuf; 358 | *pval++ = *cp; 359 | } 360 | break; 361 | case in_val_string: 362 | if (pval == NULL) 363 | /* don't update end here, leave at value start */ 364 | return JSON_ERR_NULLPTR; 365 | if (*cp == '\\') 366 | state = in_escape; 367 | else if (*cp == '"') { 368 | *pval++ = '\0'; 369 | json_debug_trace((1, "Collected string value %s\n", valbuf)); 370 | state = post_val; 371 | } else if (pval > valbuf + JSON_VAL_MAX - 1 372 | || pval > valbuf + maxlen) { 373 | json_debug_trace((1, "String value too long.\n")); 374 | /* don't update end here, leave at value start */ 375 | return JSON_ERR_STRLONG; /* */ 376 | } else 377 | *pval++ = *cp; 378 | break; 379 | case in_escape: 380 | if (pval == NULL) 381 | /* don't update end here, leave at value start */ 382 | return JSON_ERR_NULLPTR; 383 | switch (*cp) { 384 | case 'b': 385 | *pval++ = '\b'; 386 | break; 387 | case 'f': 388 | *pval++ = '\f'; 389 | break; 390 | case 'n': 391 | *pval++ = '\n'; 392 | break; 393 | case 'r': 394 | *pval++ = '\r'; 395 | break; 396 | case 't': 397 | *pval++ = '\t'; 398 | break; 399 | case 'u': 400 | for (n = 0; n < 4 && cp[n] != '\0'; n++) 401 | uescape[n] = *cp++; 402 | --cp; 403 | (void)sscanf(uescape, "%04x", &u); 404 | *pval++ = (char)u; /* will truncate values above 0xff */ 405 | break; 406 | default: /* handles double quote and solidus */ 407 | *pval++ = *cp; 408 | break; 409 | } 410 | state = in_val_string; 411 | break; 412 | case in_val_token: 413 | if (pval == NULL) 414 | /* don't update end here, leave at value start */ 415 | return JSON_ERR_NULLPTR; 416 | if (isspace((unsigned char) *cp) || *cp == ',' || *cp == '}') { 417 | *pval = '\0'; 418 | json_debug_trace((1, "Collected token value %s.\n", valbuf)); 419 | state = post_val; 420 | if (*cp == '}' || *cp == ',') 421 | --cp; 422 | } else if (pval > valbuf + JSON_VAL_MAX - 1) { 423 | json_debug_trace((1, "Token value too long.\n")); 424 | /* don't update end here, leave at value start */ 425 | return JSON_ERR_TOKLONG; 426 | } else 427 | *pval++ = *cp; 428 | break; 429 | case post_val: 430 | /* 431 | * We know that cursor points at the first spec matching 432 | * the current attribute. We don't know that it's *the* 433 | * correct spec; our dialect allows there to be any number 434 | * of adjacent ones with the same attrname but different 435 | * types. Here's where we try to seek forward for a 436 | * matching type/attr pair if we're not looking at one. 437 | */ 438 | for (;;) { 439 | int seeking = cursor->type; 440 | if (value_quoted && (cursor->type == t_string || cursor->type == t_time)) 441 | break; 442 | if ((strcmp(valbuf, "true")==0 || strcmp(valbuf, "false")==0) 443 | && seeking == t_boolean) 444 | break; 445 | if (isdigit((unsigned char) valbuf[0])) { 446 | bool decimal = strchr(valbuf, '.') != NULL; 447 | if (decimal && seeking == t_real) 448 | break; 449 | if (!decimal && (seeking == t_integer || seeking == t_uinteger)) 450 | break; 451 | } 452 | if (cursor[1].attribute==NULL) /* out of possiblities */ 453 | break; 454 | if (strcmp(cursor[1].attribute, attrbuf)!=0) 455 | break; 456 | ++cursor; 457 | } 458 | if (value_quoted 459 | && (cursor->type != t_string && cursor->type != t_character 460 | && cursor->type != t_check && cursor->type != t_time 461 | && cursor->type != t_ignore && cursor->map == 0)) { 462 | json_debug_trace((1, 463 | "Saw quoted value when expecting non-string.\n")); 464 | return JSON_ERR_QNONSTRING; 465 | } 466 | if (!value_quoted 467 | && (cursor->type == t_string || cursor->type == t_check 468 | || cursor->type == t_time || cursor->map != 0)) { 469 | json_debug_trace((1, 470 | "Didn't see quoted value when expecting string.\n")); 471 | return JSON_ERR_NONQSTRING; 472 | } 473 | if (cursor->map != 0) { 474 | for (mp = cursor->map; mp->name != NULL; mp++) 475 | if (strcmp(mp->name, valbuf) == 0) { 476 | goto foundit; 477 | } 478 | json_debug_trace((1, "Invalid enumerated value string %s.\n", 479 | valbuf)); 480 | return JSON_ERR_BADENUM; 481 | foundit: 482 | (void)snprintf(valbuf, sizeof(valbuf), "%d", mp->value); 483 | } 484 | lptr = json_target_address(cursor, parent, offset); 485 | if (lptr != NULL) 486 | switch (cursor->type) { 487 | case t_integer: 488 | { 489 | int tmp = atoi(valbuf); 490 | memcpy(lptr, &tmp, sizeof(int)); 491 | } 492 | break; 493 | case t_uinteger: 494 | { 495 | unsigned int tmp = (unsigned int)atoi(valbuf); 496 | memcpy(lptr, &tmp, sizeof(unsigned int)); 497 | } 498 | break; 499 | case t_time: 500 | #ifdef TIME_ENABLE 501 | { 502 | double tmp = iso8601_to_unix(valbuf); 503 | memcpy(lptr, &tmp, sizeof(double)); 504 | } 505 | #endif /* TIME_ENABLE */ 506 | break; 507 | case t_real: 508 | { 509 | double tmp = atof(valbuf); 510 | memcpy(lptr, &tmp, sizeof(double)); 511 | } 512 | break; 513 | case t_string: 514 | if (parent != NULL 515 | && parent->element_type != t_structobject 516 | && offset > 0) 517 | return JSON_ERR_NOPARSTR; 518 | (void)strncpy(lptr, valbuf, cursor->len); 519 | valbuf[sizeof(valbuf)-1] = '\0'; 520 | break; 521 | case t_boolean: 522 | { 523 | bool tmp = (strcmp(valbuf, "true") == 0); 524 | memcpy(lptr, &tmp, sizeof(bool)); 525 | } 526 | break; 527 | case t_character: 528 | if (strlen(valbuf) > 1) 529 | /* don't update end here, leave at value start */ 530 | return JSON_ERR_STRLONG; 531 | else 532 | lptr[0] = valbuf[0]; 533 | break; 534 | case t_ignore: /* silences a compiler warning */ 535 | case t_object: /* silences a compiler warning */ 536 | case t_structobject: 537 | case t_array: 538 | break; 539 | case t_check: 540 | if (strcmp(cursor->dflt.check, valbuf) != 0) { 541 | json_debug_trace((1, 542 | "Required attribute value %s not present.\n", 543 | cursor->dflt.check)); 544 | /* don't update end here, leave at start of attribute */ 545 | return JSON_ERR_CHECKFAIL; 546 | } 547 | break; 548 | } 549 | /*@fallthrough@*/ 550 | case post_array: 551 | if (isspace((unsigned char) *cp)) 552 | continue; 553 | else if (*cp == ',') 554 | state = await_attr; 555 | else if (*cp == '}') { 556 | ++cp; 557 | goto good_parse; 558 | } else { 559 | json_debug_trace((1, "Garbage while expecting comma or }\n")); 560 | if (end != NULL) 561 | *end = cp; 562 | return JSON_ERR_BADTRAIL; 563 | } 564 | break; 565 | } 566 | } 567 | 568 | good_parse: 569 | /* in case there's another object following, consume trailing WS */ 570 | while (isspace((unsigned char) *cp)) 571 | ++cp; 572 | if (end != NULL) 573 | *end = cp; 574 | json_debug_trace((1, "JSON parse ends.\n")); 575 | return 0; 576 | /*@ +nullstate +nullderef +mustfreefresh +nullpass +usedef @*/ 577 | } 578 | 579 | int json_read_array(const char *cp, const struct json_array_t *arr, 580 | const char **end) 581 | { 582 | /*@-nullstate -onlytrans@*/ 583 | int substatus, offset, arrcount; 584 | char *tp; 585 | 586 | if (end != NULL) 587 | *end = NULL; /* give it a well-defined value on parse failure */ 588 | 589 | json_debug_trace((1, "Entered json_read_array()\n")); 590 | 591 | while (isspace((unsigned char) *cp)) 592 | cp++; 593 | if (*cp != '[') { 594 | json_debug_trace((1, "Didn't find expected array start\n")); 595 | return JSON_ERR_ARRAYSTART; 596 | } else 597 | cp++; 598 | 599 | tp = arr->arr.strings.store; 600 | arrcount = 0; 601 | 602 | /* Check for empty array */ 603 | while (isspace((unsigned char) *cp)) 604 | cp++; 605 | if (*cp == ']') 606 | goto breakout; 607 | 608 | for (offset = 0; offset < arr->maxlen; offset++) { 609 | char *ep = NULL; 610 | json_debug_trace((1, "Looking at %s\n", cp)); 611 | switch (arr->element_type) { 612 | /* disable gcc warning */ 613 | case t_time: 614 | break; 615 | case t_string: 616 | if (isspace((unsigned char) *cp)) 617 | cp++; 618 | if (*cp != '"') 619 | return JSON_ERR_BADSTRING; 620 | else 621 | ++cp; 622 | arr->arr.strings.ptrs[offset] = tp; 623 | for (; tp - arr->arr.strings.store < arr->arr.strings.storelen; 624 | tp++) 625 | if (*cp == '"') { 626 | ++cp; 627 | *tp++ = '\0'; 628 | goto stringend; 629 | } else if (*cp == '\0') { 630 | json_debug_trace((1, 631 | "Bad string syntax in string list.\n")); 632 | return JSON_ERR_BADSTRING; 633 | } else { 634 | *tp = *cp++; 635 | } 636 | json_debug_trace((1, "Bad string syntax in string list.\n")); 637 | return JSON_ERR_BADSTRING; 638 | stringend: 639 | break; 640 | case t_object: 641 | case t_structobject: 642 | substatus = 643 | json_internal_read_object(cp, arr->arr.objects.subtype, arr, 644 | offset, &cp); 645 | if (substatus != 0) { 646 | if (end != NULL) 647 | end = &cp; 648 | return substatus; 649 | } 650 | break; 651 | case t_integer: 652 | arr->arr.integers.store[offset] = (int)strtol(cp, &ep, 0); 653 | if (ep == cp) 654 | return JSON_ERR_BADNUM; 655 | else 656 | cp = ep; 657 | break; 658 | case t_uinteger: 659 | arr->arr.uintegers.store[offset] = (unsigned int)strtoul(cp, &ep, 0); 660 | if (ep == cp) 661 | return JSON_ERR_BADNUM; 662 | else 663 | cp = ep; 664 | break; 665 | #ifdef TIME_ENABLE 666 | case t_time: 667 | if (*cp != '"') 668 | return JSON_ERR_BADSTRING; 669 | else 670 | ++cp; 671 | arr->arr.reals.store[offset] = iso8601_to_unix((char *)cp); 672 | if (arr->arr.reals.store[offset] >= HUGE_VAL) 673 | return JSON_ERR_BADNUM; 674 | while (*cp && *cp != '"') 675 | cp++; 676 | if (*cp != '"') 677 | return JSON_ERR_BADSTRING; 678 | else 679 | ++cp; 680 | break; 681 | #endif /* TIME_ENABLE */ 682 | case t_real: 683 | arr->arr.reals.store[offset] = strtod(cp, &ep); 684 | if (ep == cp) 685 | return JSON_ERR_BADNUM; 686 | else 687 | cp = ep; 688 | break; 689 | case t_boolean: 690 | if (strncmp(cp, "true", 4) == 0) { 691 | arr->arr.booleans.store[offset] = true; 692 | cp += 4; 693 | } 694 | else if (strncmp(cp, "false", 5) == 0) { 695 | arr->arr.booleans.store[offset] = false; 696 | cp += 5; 697 | } 698 | break; 699 | case t_character: 700 | case t_array: 701 | case t_check: 702 | case t_ignore: 703 | json_debug_trace((1, "Invalid array subtype.\n")); 704 | return JSON_ERR_SUBTYPE; 705 | } 706 | arrcount++; 707 | if (isspace((unsigned char) *cp)) 708 | cp++; 709 | if (*cp == ']') { 710 | json_debug_trace((1, "End of array found.\n")); 711 | goto breakout; 712 | } else if (*cp == ',') 713 | cp++; 714 | else { 715 | json_debug_trace((1, "Bad trailing syntax on array.\n")); 716 | return JSON_ERR_BADSUBTRAIL; 717 | } 718 | } 719 | json_debug_trace((1, "Too many elements in array.\n")); 720 | if (end != NULL) 721 | *end = cp; 722 | return JSON_ERR_SUBTOOLONG; 723 | breakout: 724 | if (arr->count != NULL) 725 | *(arr->count) = arrcount; 726 | if (end != NULL) 727 | *end = cp; 728 | /*@ -nullderef @*/ 729 | json_debug_trace((1, "leaving json_read_array() with %d elements\n", 730 | arrcount)); 731 | /*@ +nullderef @*/ 732 | return 0; 733 | /*@+nullstate +onlytrans@*/ 734 | } 735 | 736 | int json_read_object(const char *cp, const struct json_attr_t *attrs, 737 | /*@null@*/ const char **end) 738 | { 739 | int st; 740 | 741 | json_debug_trace((1, "json_read_object() sees '%s'\n", cp)); 742 | st = json_internal_read_object(cp, attrs, NULL, 0, end); 743 | return st; 744 | } 745 | 746 | const /*@observer@*/ char *json_error_string(int err) 747 | { 748 | const char *errors[] = { 749 | "unknown error while parsing JSON", 750 | "non-whitespace when expecting object start", 751 | "non-whitespace when expecting attribute start", 752 | "unknown attribute name", 753 | "attribute name too long", 754 | "saw [ when not expecting array", 755 | "array element specified, but no [", 756 | "string value too long", 757 | "token value too long", 758 | "garbage while expecting comma or } or ]", 759 | "didn't find expected array start", 760 | "error while parsing object array", 761 | "too many array elements", 762 | "garbage while expecting array comma", 763 | "unsupported array element type", 764 | "error while string parsing", 765 | "check attribute not matched", 766 | "can't support strings in parallel arrays", 767 | "invalid enumerated value", 768 | "saw quoted value when expecting nonstring", 769 | "didn't see quoted value when expecting string", 770 | "other data conversion error", 771 | "unexpected null value or attribute pointer", 772 | }; 773 | 774 | if (err <= 0 || err >= (int)(sizeof(errors) / sizeof(errors[0]))) 775 | return errors[0]; 776 | else 777 | return errors[err]; 778 | } 779 | 780 | /* end */ 781 | 782 | -------------------------------------------------------------------------------- /lib/netlayer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: netlayer.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月26日 15时55分51秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "log.h" 34 | #include "link.h" 35 | #include "netlayer.h" 36 | 37 | static int __tcp_alive(struct nettcp_t *tcp) 38 | { 39 | 40 | int optval = 1; 41 | int optlen = sizeof(optval); 42 | if(setsockopt(tcp->sock, SOL_SOCKET, 43 | SO_KEEPALIVE, &optval, optlen) < -1) { 44 | sys_err("Set tcp keepalive failed: %s\n", 45 | strerror(errno)); 46 | return -1; 47 | } 48 | 49 | optval = 30; 50 | if(setsockopt(tcp->sock, SOL_TCP, 51 | TCP_KEEPCNT, &optval, optlen) < -1) { 52 | sys_err("Set tcp_keepalive_probes failed: %s\n", 53 | strerror(errno)); 54 | return -1; 55 | } 56 | 57 | optval = 30; 58 | if(setsockopt(tcp->sock, SOL_TCP, 59 | TCP_KEEPIDLE, &optval, optlen) < -1) { 60 | sys_err("Set tcp_keepalive_time failed: %s\n", 61 | strerror(errno)); 62 | return -1; 63 | } 64 | 65 | optval = 5; 66 | if(setsockopt(tcp->sock, SOL_TCP, 67 | TCP_KEEPINTVL, &optval, optlen) < -1) { 68 | sys_err("Set tcp_keepalive_intvl failed: %s\n", 69 | strerror(errno)); 70 | return -1; 71 | } 72 | 73 | return 0; 74 | } 75 | 76 | int tcp_connect(struct nettcp_t *tcp) 77 | { 78 | int ret; 79 | if(tcp->addr.sin_addr.s_addr == 0) 80 | return -1; 81 | 82 | tcp->sock = socket(AF_INET, SOCK_STREAM, 0); 83 | if(tcp->sock < 0) { 84 | sys_err("Create tcp sock failed: %s\n", 85 | strerror(errno)); 86 | return -1; 87 | } 88 | 89 | ret = __tcp_alive(tcp); 90 | if(ret < 0) { 91 | sys_err("Set tcp alive failed\n"); 92 | tcp_close(tcp); 93 | return -1; 94 | } 95 | 96 | socklen_t addr_len = sizeof(struct sockaddr_in); 97 | ret = connect(tcp->sock, (struct sockaddr *)&tcp->addr, addr_len); 98 | if(ret < 0) { 99 | tcp_close(tcp); 100 | sys_err("Connect ac failed: %s\n", strerror(errno)); 101 | return -1; 102 | } 103 | 104 | return tcp->sock; 105 | } 106 | 107 | int tcp_rcv(struct nettcp_t *tcp, char *data, int size) 108 | { 109 | assert(data != NULL && tcp->sock >= 0); 110 | 111 | int recvlen = 0, len; 112 | 113 | while(1) { 114 | len = recv(tcp->sock, data, size, 0); 115 | if(len > 0) { 116 | data += len; 117 | size -= len; 118 | recvlen += len; 119 | continue; 120 | } else if(len < 0) { 121 | if(errno == EINTR) 122 | continue; 123 | if(errno == EAGAIN) 124 | break; 125 | sys_err("sock: %d, tcp recv failed: %s(%d)\n", 126 | tcp->sock, strerror(errno), errno); 127 | break; 128 | } 129 | assert(len != 0); 130 | } 131 | 132 | sys_debug("Recv msg from sock: %d, size: %d\n", tcp->sock, recvlen); 133 | return recvlen; 134 | } 135 | 136 | int tcp_sendpkt(struct nettcp_t *tcp, char *data, int size) 137 | { 138 | assert(data != NULL && size <= NET_PKT_DATALEN); 139 | 140 | if(tcp->sock == -1) return -1; 141 | 142 | int sdrlen; 143 | while(1) { 144 | sdrlen = send(tcp->sock, data, size, 0); 145 | if(sdrlen < 0) { 146 | if(errno == EAGAIN || errno == EINTR) 147 | continue; 148 | sys_err("sock: %d, tcp send failed: %s(%d)\n", 149 | tcp->sock, strerror(errno), errno); 150 | } 151 | break; 152 | } 153 | 154 | sys_debug("Send packet success: %d\n", sdrlen); 155 | return sdrlen; 156 | } 157 | 158 | void tcp_close(struct nettcp_t *tcp) 159 | { 160 | close(tcp->sock); 161 | tcp->sock = -1; 162 | } 163 | 164 | #ifdef SERVER 165 | #define BACKLOG (512) 166 | int tcp_listen(struct nettcp_t *tcp) 167 | { 168 | int ret; 169 | 170 | tcp->sock = socket(AF_INET, SOCK_STREAM, 0); 171 | if(tcp->sock < 0) { 172 | sys_err("Create tcp sock failed: %s\n", 173 | strerror(errno)); 174 | return -1; 175 | } 176 | 177 | int reuseaddr = 1; 178 | ret = setsockopt(tcp->sock, SOL_SOCKET, SO_REUSEADDR, 179 | &reuseaddr, sizeof(reuseaddr)); 180 | if(ret < 0) { 181 | sys_err("set sock reuse failed: %s\n", 182 | strerror(errno)); 183 | return -1; 184 | } 185 | 186 | socklen_t socklen = sizeof(struct sockaddr_in); 187 | ret = bind(tcp->sock, 188 | (struct sockaddr *)&tcp->addr, socklen); 189 | if(ret < 0) { 190 | sys_err("Bind tcp sock failed: %s\n", 191 | strerror(errno)); 192 | tcp_close(tcp); 193 | return -1; 194 | } 195 | 196 | ret = listen(tcp->sock, BACKLOG); 197 | if(ret < 0) { 198 | sys_err("Bind tcp sock failed: %s\n", 199 | strerror(errno)); 200 | tcp_close(tcp); 201 | return -1; 202 | } 203 | 204 | return tcp->sock; 205 | } 206 | 207 | 208 | 209 | int tcp_accept(struct nettcp_t *tcp, void *func(void *)) 210 | { 211 | int clisock; 212 | clisock = accept(tcp->sock, NULL, NULL); 213 | if(clisock < 0) { 214 | sys_err("Accept tcp sock failed: %s\n", 215 | strerror(errno)); 216 | return -1; 217 | } 218 | 219 | sys_debug("New client:%d\n", clisock); 220 | insert_sockarr(clisock, func, NULL); 221 | return clisock; 222 | } 223 | #endif 224 | -------------------------------------------------------------------------------- /lib/thread.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: thread.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年11月11日 16时15分18秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | 21 | #include "thread.h" 22 | #include "log.h" 23 | 24 | void create_pthread(void *(*start_routine) (void *), void *arg) 25 | { 26 | int ret; 27 | pthread_t pid; 28 | ret = pthread_create(&pid, NULL, start_routine, arg); 29 | if(ret != 0) { 30 | sys_err("Create pthread failed: %s(%d)\n", 31 | strerror(errno), errno); 32 | exit(-1); 33 | } 34 | 35 | ret = pthread_detach(pid); 36 | if(ret != 0) { 37 | sys_err("Create pthread failed: %s(%d)\n", 38 | strerror(errno), errno); 39 | exit(-1); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /scripts/Kbuild.include: -------------------------------------------------------------------------------- 1 | echo-cmd = $(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))';) 2 | cmd = @$(echo-cmd) $(cmd_$(1)) 3 | 4 | -------------------------------------------------------------------------------- /scripts/ac.sql: -------------------------------------------------------------------------------- 1 | -- phpMyAdmin SQL Dump 2 | -- version 4.0.4 3 | -- http://www.phpmyadmin.net 4 | -- 5 | -- 主机: 127.0.0.1 6 | -- 生成日期: 2014 年 10 月 25 日 14:42 7 | -- 服务器版本: 5.5.32 8 | -- PHP 版本: 5.4.16 9 | 10 | SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; 11 | SET time_zone = "+00:00"; 12 | 13 | 14 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 15 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 16 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 17 | /*!40101 SET NAMES utf8 */; 18 | 19 | -- 20 | -- 数据库: `ac` 21 | -- 22 | CREATE DATABASE IF NOT EXISTS `ac` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; 23 | USE `ac`; 24 | 25 | -- -------------------------------------------------------- 26 | 27 | -- 28 | -- 表的结构 `resource` 29 | -- 30 | 31 | CREATE TABLE IF NOT EXISTS `resource` ( 32 | `ip_start` varchar(15) COLLATE utf8_unicode_ci, 33 | `ip_end` varchar(15) COLLATE utf8_unicode_ci, 34 | `ip_mask` varchar(15) COLLATE utf8_unicode_ci 35 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 36 | 37 | -- -------------------------------------------------------- 38 | 39 | -- 40 | -- 表的结构 `node` 41 | -- 42 | 43 | CREATE TABLE IF NOT EXISTS `node` ( 44 | `hostname` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '设备自身的名称', 45 | `time_first` datetime DEFAULT NULL COMMENT '设备第一报告时间', 46 | `time` datetime DEFAULT NULL COMMENT 'Time of last checkin', 47 | `latitude` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, 48 | `longitude` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, 49 | `uptime` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'ROBIN', 50 | `memfree` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'ROBIN', 51 | `cpu` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL, 52 | `device_down` tinyint(1) NOT NULL DEFAULT '0' COMMENT '标示设备是否离线,并且发送短信了', 53 | `wan_iface` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 54 | `wan_ip` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 55 | `wan_mac` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 56 | `wan_gateway` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 57 | `wifi_iface` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 58 | `wifi_ip` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 59 | `wifi_mac` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 60 | `wifi_ssid` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 61 | `wifi_encryption` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '无线加密方式', 62 | `wifi_key` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 63 | `wifi_channel_mode` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'wifi终端采用的信道模式,自动还是手动', 64 | `wifi_channel` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 65 | `wifi_signal` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL, 66 | `lan_iface` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 67 | `lan_mac` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 68 | `lan_ip` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 69 | `wan_bup` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 70 | `wan_bup_sum` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 71 | `wan_bdown` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 72 | `wan_bdown_sum` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 73 | `firmware` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 74 | `firmware_revision` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 75 | `online_user_num` int(11) DEFAULT '0', 76 | UNIQUE KEY `wan_mac` (`wan_mac`) 77 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='node database' AUTO_INCREMENT=2 ; 78 | 79 | -- -------------------------------------------------------- 80 | 81 | -- 82 | -- 表的结构 `node_default` 83 | -- 84 | 85 | CREATE TABLE IF NOT EXISTS `node_default` ( 86 | `profile` varchar(12) COLLATE utf8_unicode_ci NOT NULL COMMENT '档案名称', 87 | `device_name` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '默认的设备标示', 88 | `wifi_ssid` varchar(128) COLLATE utf8_unicode_ci NOT NULL COMMENT '默认的SSID号码', 89 | `wifi_encryption` varchar(128) COLLATE utf8_unicode_ci NOT NULL COMMENT '默认的加密方式', 90 | `wifi_key` varchar(128) COLLATE utf8_unicode_ci NOT NULL COMMENT '默认的密钥', 91 | `wifi_channel_mode` varchar(128) COLLATE utf8_unicode_ci NOT NULL COMMENT '默认的频道方式', 92 | `wifi_channel` varchar(24) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '手工的频道', 93 | `wifi_signal` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '默认的信号强度', 94 | PRIMARY KEY (`profile`) 95 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='默认的设置表,没有注册的话就会读取此处的设置'; 96 | 97 | -- -------------------------------------------------------- 98 | 99 | -- 100 | -- 表的结构 `node_setting` 101 | -- 102 | 103 | CREATE TABLE IF NOT EXISTS `node_setting` ( 104 | `pre_device_name` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '预设设备名', 105 | `pre_device_mac` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '预设设备MAC', 106 | `pre_device_description` text COLLATE utf8_unicode_ci COMMENT '预设设备描述', 107 | `device_latitude` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, 108 | `device_longitude` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, 109 | `wan_ip` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 110 | `wan_mac` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 111 | `wifi_ip` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 112 | `wifi_ssid` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '需要修改的wifi_ssid', 113 | `wifi_encryption` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '修改后的加密方式', 114 | `wifi_key` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 115 | `wifi_channel_mode` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 116 | `wifi_channel` varchar(24) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '修改后的频道', 117 | `wifi_signal` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '修改后的功率', 118 | UNIQUE KEY `pre_device_mac` (`pre_device_mac`), 119 | UNIQUE KEY `wan_mac` (`wan_mac`) 120 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='node database' AUTO_INCREMENT=2 ; 121 | 122 | -- -------------------------------------------------------- 123 | 124 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 125 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 126 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 127 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | all:dllser dllcli 2 | 3 | LIB:= $(LIBDIR)/$(LIB) 4 | 5 | dllser:dllser.o $(LIB) 6 | $(CC) $^ $(LDFLAGS) -o $@ 7 | 8 | dllcli:dllcli.o $(LIB) 9 | $(CC) $^ $(LDFLAGS) -o $@ 10 | 11 | %.o:%.c 12 | $(CC) $(CFLAGS) -c $^ -o $@ 13 | -------------------------------------------------------------------------------- /test/dllcli.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: dllcli.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月19日 15时56分34秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | 22 | #include "dllayer.h" 23 | int debug = 1; 24 | int main() 25 | { 26 | dll_init("enp3s0", NULL, NULL, NULL); 27 | char data[100]; 28 | int ret; 29 | while(1) { 30 | memset(data, 0, 100); 31 | ret = dll_rcv(data, 99); 32 | printf("ret:%d, data:%s\n", ret, data + 14); 33 | } 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /test/dllser.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ============================================================================ 3 | * 4 | * Filename: dllser.c 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: 2014年08月19日 15时53分51秒 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: jianxi sun (jianxi), ycsunjane@gmail.com 14 | * Organization: 15 | * 16 | * ============================================================================ 17 | */ 18 | #include 19 | #include 20 | #include 21 | 22 | #include "dllayer.h" 23 | int debug = 1; 24 | int main() 25 | { 26 | dll_init("enp3s0", NULL, NULL, NULL); 27 | char *data = "wirelesserwirelesserwirelesserwirelesserwirelesserwirelesserwirelesserwirelesserwirelesserwirelesserirelesser"; 28 | int size = strlen(data); 29 | 30 | dll_brdcast(data, size); 31 | return 0; 32 | } 33 | --------------------------------------------------------------------------------