📄 update386.c
字号:
/*Copyright 当代天启(北京) 2008主要功能:维护下接的386软件版本,实现386软件在线升级作者:周天民生成日期:2008年10月23日修改记录:*/#include <stdio.h>#include <unistd.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>#include <pthread.h>#include <stdlib.h>#include "debug_level.h"#include "pcap.h"#include "lcom.h"#include <net/ethernet.h>#include <net/if.h>#include <sys/ioctl.h> #include <string.h>#include <sys/socket.h>#include "../dhcp/sniff.h"/*for byte's orderliness when allloc a buffer of a package */#define ALLIGNMENT(addr) (u_char*)((uint32_t)(addr) - (uint32_t)(addr) % 4 + 4) /*588的386ip*/#define IPADDR_386GATE 0x0102a8c0/*令牌信号宏定义*/#define GIVETOKEN SIGCONT/*386数量最大值宏定义*/#define MAX386NUM 8/*主线程通信端口宏定义*/#define MAINTHREADUPDPORT 4455/*第一个升级线程通信端口宏定义*/#define FIRSTTHREADUPDPORT 4456/*文件名全局变量 */char *g386version = "/tmp/588/version386.conf";char *g386software = "/tmp/588/soft386.bin";/*当前最新的386版本*/char cur386ver[10] = {0};/*发包缓存,初始化时设置包头各字段*/u_char up386sbuf[2][ETH_HLEN + IP_HLEN +UDP_HLEN +16];/*线程相关,mac386表示该线程对应的386的mac;udpport表示该线程使用的udp端口ifbeused表示该线程是否已经被使用,0表示未使用,非0表示正在使用*/struct stThread{ unsigned char mac386[6]; unsigned short udpPort; char ifBeUsed;};struct stThread threadbook[MAX386NUM];/*本地socket通信id*/static int update386_local_sock_fd= 0;/*调试信息级别第2位*/#define DEBUGLEVEL2 2/*操作命令字*/#define UP386_ASKIFNEED 1 /*询问升级命令,占用十个字节(由juno288发送)*/#define UP386_NEEDNOTPDATE 2 /*通知juno288不需要升级(由588发送)*/#define UP386_NEEDUPDATE 3 /*通知juno288需要升级(由588发送)*/#define UP386_PLEASESEND 4 /*通知588现在可以开始发送升级包(由juno288发送)*/#define UP386_ALLPACKEND 5 /*通知juno288升级包发送结束(由588发送)*/#define UP386_DOWNLOADEND 6 /*通知588已经全部下载结束(由juno288发送)*/#define UP386_DATAACK 7 /*正常数据包的ack(由juno288发送)*/#define UP386_DATA 8 /*正常数据包(由588发送)*//*ip头序号*/static u_short ipheadid=0;static pcap_t *pup386 = NULL ; char update386filter_exp[] = "udp dst port 4455 && dst host 192.168.2.1";char update386dev[] = "eth0";unsigned short checksum(unsigned short *buf,int nword){ unsigned long sum; for(sum=0;nword>0;nword--) sum += *buf++; sum = (sum>>16) + (sum&0xffff); sum += (sum>>16); return ~sum;}pcap_t* pcap_start(const char* dev, char *filter_exp){ char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */ pcap_t *handle; /* packet capture handle */ struct bpf_program fp; /* compiled filter program (expression) */ bpf_u_int32 mask; /* subnet mask */ bpf_u_int32 net; /* ip */ if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) { fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev, errbuf); net = 0; mask = 0; } /* print capture info */ pd(DEBUGLEVEL2,"Device: %s\n", dev); pd(DEBUGLEVEL2,"Filter expression: %s\n", filter_exp); /* open capture device */ handle = pcap_open_live(dev, SNAP_LEN, 0, 1000, errbuf); if (handle == NULL) { fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf); exit(EXIT_FAILURE); } pd(DEBUGLEVEL2,"cpcap_open_live ok!\n"); /* make sure we're capturing on an Ethernet device [2] */ if (pcap_datalink(handle) != DLT_EN10MB) { fprintf(stderr, "%s is not an Ethernet\n", dev); exit(EXIT_FAILURE); } pd(DEBUGLEVEL2,"pcap_datalink ok!\n"); /* compile the filter expression */ if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) { fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle)); exit(EXIT_FAILURE); } pd(DEBUGLEVEL2,"pcap_compile ok!\n"); /* apply the compiled filter */ if (pcap_setfilter(handle, &fp) == -1) { fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle)); exit(EXIT_FAILURE); } pd(DEBUGLEVEL2,"pcap_setfilter ok!\n"); return handle;}/*主要功能:比较两个版本,决定是否需要升级输入:cur ,收到的版本,newver,保存的版本输出:NULL返回值:1表示需要升级,-1表示版本号错误,其他值表示不需升级*/int vercmp386(char *cur, char * newver){ if(( strcmp(cur,newver) )<0) return 1; if(( strcmp(cur,newver) )>0) return 0; return 0;}/*get version ,return 0:ok; return -1:error*/int get386Version(char *ver){ struct stat *fstat = NULL; FILE* f = NULL; char line[128] = {0}; //read a line from file /*open ipfile*/ fstat = (struct stat* )malloc(sizeof(struct stat)); if (fstat == NULL) { pd(DEBUGLEVEL2,"can't malloc space for struct stat\n"); return -1; } if (( stat(g386version,fstat) < 0) ) { pd(DEBUGLEVEL2,"read version file %s err\n",g386version); pe("stat:"); free(fstat); return -1; } f = fopen(g386version,"r"); if ( f== NULL) { pd(DEBUGLEVEL2,"open version file %s err\n",g386version); pe("fopen"); free(fstat); return -1; } file_rlock(fileno(f)); while (fscanf(f,"%s\n",line) >0) { pd(DEBUGLEVEL2,"line = %s, ",line); strcpy(ver,line); } free(fstat); fclose(f); return 0;}/*主要功能:初始化线程记录数组输入:null输出:null返回值:null*/void init_thread_book(){ int i = 0; unsigned short thisudpport = FIRSTTHREADUPDPORT; for(i = 0;i<MAX386NUM;i++) { memset(threadbook[i].mac386,0,6); threadbook[i].udpPort = thisudpport++; threadbook[i].ifBeUsed = 0; } return;}/*主要功能:初始化发包缓存,设置各个公用字段输入:null输出:null返回值:null*/void sbuf_init(){ struct ether_header *eth_out = NULL; struct sniff_ip *ip_out = NULL; struct udphdr *udp_out = NULL; u_char * buf = NULL; int i = 0; int sock, ret; struct ifreq ifr; sock = socket( AF_INET, SOCK_STREAM, 0 ); if ( sock < 0 ) { pe("getmac socket"); return; } memset( &ifr, 0, sizeof(ifr) ); strcpy( ifr.ifr_name, "eth0" ); ret = ioctl( sock, SIOCGIFHWADDR, &ifr, sizeof(ifr) ); if ( ret != 0 ) { pe("get mac error"); return; } for (i=0;i<2;i++) { buf = ALLIGNMENT(up386sbuf[i]) + 2; eth_out = (struct ether_header *)buf; ip_out = (struct sniff_ip *) (buf + ETH_HLEN); udp_out = (struct udphdr *) (buf +ETH_HLEN + IP_HLEN); memcpy(eth_out->ether_shost,ifr.ifr_hwaddr.sa_data,ETH_ALEN); memset(eth_out->ether_dhost,0xff,ETH_ALEN); eth_out->ether_type = htons(0x0800); ip_out->ip_vhl = 0x45; ip_out->ip_tos = 0x00; ip_out->ip_len = htons(IP_HLEN + UDP_HLEN + 4); ip_out->ip_id = 0; ip_out->ip_off = 0x00; ip_out->ip_ttl = 128; ip_out->ip_p = 0x11; ip_out->ip_sum = 0; //need to add check sum ip_out->ip_dst.s_addr = 0; ip_out->ip_src.s_addr = 0; udp_out->source = htons(MAINTHREADUPDPORT); udp_out->dest = htons(MAINTHREADUPDPORT); udp_out->len = htons(UDP_HLEN + 4); udp_out->check = 0; pd(DEBUGLEVEL2,"init sbuf%d:\n",i); } return;}/** *主要功能:开始升级 *输入:NULL *输出:NULL *返回值:NULL */void *startUpdate(void * arg){ int xb= *((int *)arg); unsigned short udpport = threadbook[xb].udpPort; int sockfd; struct sockaddr_in servaddr, cliaddr; char rec[128] = {0}; int reclen = sizeof(cliaddr); int n,i,j; char *ptmp = rec; int time0,time1; int fd; int readlen=0; int sendret = 0; char updateend = UP386_ALLPACKEND; unsigned long sendbuf[256] ; unsigned char *sendhead = sendbuf ; unsigned short * packnum = (unsigned short * )(sendhead +2); unsigned short * packlen = (unsigned short * )(sendhead +4); char *senddata = sendhead + 6; unsigned short packnumcount =0; int enable = 1; sockfd = socket(AF_INET, SOCK_DGRAM, 0); /* create a socket */ /* init servaddr */ bzero(&(servaddr.sin_zero), 8); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(0xc0a80201); servaddr.sin_port = htons(udpport); /* bind address and port to socket */ if(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) <0) { pe("bind\n"); goto endthread; } pd(DEBUGLEVEL2,"bindok,port = %d\n",udpport); /*等待juno288请求升级的命令,5秒内收不到请求升级包,则关闭该线程*/ time0=time(NULL); while(1) { n = recvfrom(sockfd, rec, 128, 0,(struct sockaddr *)(&cliaddr), &reclen); pd(DEBUGLEVEL2,"got a pack from port :%d\n",udpport); if((n>=0)&&(rec[0] == UP386_PLEASESEND)) { break; } time1 = time(NULL); if(time1-time0>50) { pd(DEBUGLEVEL2,"has wait 5sec ,not rec a PLEASESEND PACK"); goto endthread; } sleep(1); }; pd(DEBUGLEVEL2,"recv please pack\n"); /*开始发送升级包*/ fd = open(g386software, O_RDWR); if (fd < 0) { pe("Can't open %s", g386software); goto endthread; } pd(DEBUGLEVEL2,"open ok ,start to send pack :%s\n",g386software); while((readlen = read(fd,(void *)senddata,256))>0) { packnumcount +=1; *packnum = packnumcount; pd(DEBUGLEVEL2,"\npacknumcount = %d,fuwanzhi = %d\n",packnumcount,*packnum); *packlen = readlen; sendhead[0] = UP386_DATA; for(i = 0; i<3;i++) { sendret = sendto(sockfd, sendbuf, readlen + 6, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr)); if(sendret != readlen+6) { pe("sendto"); continue; } sleep(2); pd(DEBUGLEVEL2,"send a pack,count = %d\n",packnumcount); for(j = 0;j<sendret;j++) { pd(DEBUGLEVEL2,"%2x ",sendhead[j]); } n = recvfrom(sockfd, rec, 128, 0,(struct sockaddr *)(&cliaddr), &reclen); pd(DEBUGLEVEL2,"recv a pack,count = %d\n",n); for(j = 0;j<n;j++) { pd(DEBUGLEVEL2,"%2x ",rec[j]); } if((n>=4)&&(rec[0] == UP386_DATAACK)) { ptmp = rec; ptmp +=2; if(*((unsigned short *)ptmp) == packnumcount) { break; } pd(DEBUGLEVEL2,"\nsend count %d ,rec count %d\n ",packnumcount,*((unsigned short *)ptmp) ); } } if(i >=3) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -