/** * @brief 解析IP头 * @param ptr: IP头结构体指针,用来存放解析后的数据 * @param offset: 偏移量指针,表示IP头信息在buffer中的偏移量 * @retval 错误标志,mIP_OK: 成功, mIP_ERROR: 失败 */ mIPErr IP_analyzeHead(IPHeadStruct *ptr, UINT32 *offset) { UINT8 *buf = mIP.buf + *offset; ptr->version = (UINT8)(*buf >> 4); ptr->headLength = *buf++ & 0x0F; ptr->diffServices = *buf++; ptr->totalLength = MKUINT16BIG(buf); buf += 2; ptr->identification = MKUINT16BIG(buf); buf += 2; ptr->flag = *buf >> 5; ptr->offset = ((UINT16)(*buf & 0x1F) << 8) | (UINT16)(*(buf + 1)); buf += 2; ptr->timeToLive = *buf++; ptr->protocol = *buf++; ptr->checkSum = MKUINT16BIG(buf); buf += 2; bufCopy(ptr->srcAdd, buf, 4); buf += 4; bufCopy(ptr->dstAdd, buf, 4); buf += 4; *offset += ptr->headLength * 4; return mIP_OK; }
/** * @brief 通过IP头结构体制作IP头到buffer中 * @param ptr: IP头结构体指针 * @param offset: buffer中偏移量指针 * @retval none */ void IP_makeHead(IPHeadStruct *ptr, UINT32 *offset) { UINT8 *buf = mIP.buf + *offset; UINT16 sum; *buf++ = (ptr->version << 4) | ptr->headLength; *buf++ = ptr->diffServices; UINT16TOPTRBIG(buf, ptr->totalLength); buf += 2; UINT16TOPTRBIG(buf, ptr->identification); buf += 2; UINT16TOPTRBIG( buf, (((UINT16)ptr->flag << 5) | (ptr->offset & 0x1FFF)) ); buf += 2; *buf++ = ptr->timeToLive; *buf++ = ptr->protocol; UINT16TOPTRBIG(buf, 0x0000); /* 首部校验和先设置为0 */ buf += 2; bufCopy(buf, ptr->srcAdd, 4); buf += 4; bufCopy(buf, ptr->dstAdd, 4); buf += 4; sum = calcuCheckSum(mIP.buf + *offset, ptr->headLength * 4); /* 计算首部校验和 */ UINT16TOPTRBIG((mIP.buf + *offset + 10), sum); *offset = buf - mIP.buf; }
/** * @brief 解析ARP首部 * @param ptr: ARP首部结构体指针,接收解析后数据 * @param offset: buffer偏移量指针 * @retval 错误标志,mIP_OK: 成功, mIP_ERROR: 失败 */ static mIPErr ARP_analyzeHead(ARPHeadStruct *ptr, UINT32 *offset) { UINT8 *buf = mIP.buf + *offset; ptr->hardwareType = MKUINT16BIG(buf); buf += 2; ptr->protocolType = MKUINT16BIG(buf); buf += 2; ptr->hardwareSize = *buf; buf += 1; ptr->protocolSize = *buf; buf += 1; ptr->opCode = MKUINT16BIG(buf); buf += 2; bufCopy(ptr->senderMACAdd, buf, 6); buf += 6; bufCopy(ptr->senderIPAdd, buf, 4); buf += 4; bufCopy(ptr->targetMACAdd, buf, 6); buf += 6; bufCopy(ptr->targetIPAdd, buf, 4); buf += 4; *offset = buf - mIP.buf; return mIP_OK; }
/** * @brief 添加一条IP和MAC到ARP高速缓存中,如果缓存已满则清空缓存并添加到起始位置 * @param addIP: 添加的IP * @param macBuf: 对应IP的MAC地址 * @retval none */ void ARP_addCache(UINT8 *addIP, UINT8 *macBuf) { if(mIP.arpCache.num >= ARP_CACHE_MAXNUM) { /* 如果超过了缓存最大允许条目,则设置缓存条目为0(清空缓存) */ mIP.arpCache.num = 0; mIP.arpCache.arpUpdataTime = myTCPIP_getTime(); /* 更新缓存时间 */ } /* 把刚查询的IP,MAC信息记录到缓存中 */ bufCopy(mIP.arpCache.ip[mIP.arpCache.num], addIP, 4); bufCopy(mIP.arpCache.mac[mIP.arpCache.num], macBuf, 6); mIP.arpCache.num++; }
/** * @brief IP处理 * @param offset: buffer中偏移量指针 * @retval none */ void IP_process(UINT32 *offset) { IPHeadStruct ip; UINT16 sum; sum = calcuCheckSum(mIP.buf + *offset, 20); /* IP只检验头部 */ if(sum != 0) return; /* 校验不通过,丢弃此包 */ IP_analyzeHead(&ip, offset); /* 解析IP固定的20byte头 */ if(ARP_checkCache(ip.srcAdd, mIP.macTmp) == 0) { /* 检查请求的客户端的IP与MAC是否在ARP缓存中,如果不在则追加 */ ARP_addCache(ip.srcAdd, mIP.macTmp); } if(bufMatch(ip.dstAdd, mIP.ip, 4) == 0) { /* 如果目标地址不是本机IP,丢弃 */ return; } bufCopy(mIP.ipTmp, ip.srcAdd, 4); /* 临时存储客户端IP */ if(ip.protocol == IP_PROTOCOL_ICMP) { /* 如果是ICMP协议(一般情况是ping本机) */ ICMP_process(&ip, offset); } if((ip.protocol == IP_PROTOCOL_UDP) && (mIP.enFlag & ENFLAG_UDP)) { /* UDP协议 */ UDP_process(&ip, offset); } if((ip.protocol == IP_PROTOCOL_TCP) && (mIP.enFlag & ENFLAG_TCP)) { /* TCP协议 */ TCP_process(&ip, offset); } }
/** * @brief 制作默认IP头,默认版本号为IPv4,首部大小为20byte,源IP为本机IP,生存时间为128 * @param totalLength: 数据的大小 * @param identification: 标识符,维护在mIP.identification中,在分片发送时用同一标识符以便区分 * @param flag: 标志,只有3位有效,0x00或0x20表示后面没有分片, 0x01表示后面还有分片 * @param fOffset: 偏移量,表示不同分片在数据中的偏移量,只有13位有效,以8byte为单位,这样每个分片的长度位8字节的整数倍 * @param protocol: 高层使用的协议 * @param offset: buffer中偏移量指针 * @retval none */ void IP_makeHeadDefault(UINT16 datLen, UINT16 identification, UINT8 flag, UINT16 fOffset, UINT8 protocol, UINT32 *offset) { IPHeadStruct ip; ip.version = 4; ip.headLength = 5; ip.diffServices = 0x00; ip.totalLength = datLen + 20; ip.identification = identification; ip.flag = flag; ip.offset = fOffset; ip.timeToLive = 0x80; ip.protocol = protocol; ip.checkSum = 0x0000; bufCopy(ip.srcAdd, mIP.ip, 4); bufCopy(ip.dstAdd, mIP.ipTmp, 4); IP_makeHead(&ip, offset); }
/** * @brief 发送一个ARP查询,然后等待回应或超时 * @param dstIP: 目标IP地址 * @param macBuf: 用来接收目标IP对应的MAC地址 * @retval 错误标志,mIP_OK: 成功, mIP_ERROR: 失败 */ mIPErr ARP_request(UINT8 *dstIP, UINT8 *macBuf) { ETHHeadStruct ethTmp; ARPHeadStruct arp; UINT32 offset = 0, len = 0, time = 0; UINT8 dstEthMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; UINT8 dstArpMac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /* 载入ETH头 */ bufCopy(ethTmp.dstAdd, dstEthMac, 6); bufCopy(ethTmp.srcAdd, mIP.mac, 6); ethTmp.type = PROTOCOL_TYPE_ARP; offset = 0; ETH_makeHead(ðTmp, &offset); /* 载入ARP头 */ arp.hardwareType = HARDWARE_TYPE_ETH; arp.protocolType = PROTOCOL_TYPE_IP; arp.hardwareSize = 6; arp.protocolSize = 4; arp.opCode = ARP_OPCODE_REQ; /* 请求 */ bufCopy(arp.senderMACAdd, mIP.mac, 6); bufCopy(arp.senderIPAdd, mIP.ip, 4); bufCopy(arp.targetMACAdd, dstArpMac, 6); bufCopy(arp.targetIPAdd, dstIP, 4); ARP_makeHead(&arp, &offset); /* 发送ARP查询 */ myTCPIP_sendPacket(mIP.buf, offset); /* 等待主机的回应 */ time = myTCPIP_getTime(); while(1) { len = myTCPIP_getPacket(mIP.buf, myICPIP_bufSize); if(len == 0) { if(myTCPIP_getTime() - time > ARP_TIMEWAIT || mIP.arpCache.arpUpdataTime > myTCPIP_getTime()) { /* 如果等待超时或定时器溢出,则认为没有此主机 */ return mIP_NOACK; } continue; } offset = 0; /* 设置buf的偏移量为0 */ ETH_analyzeHead(ÐHead, &offset); if(ETHHead.type == PROTOCOL_TYPE_ARP) { /* ARP协议 */ ARP_analyzeHead(&arp, &offset); if(arp.opCode == ARP_OPCODE_REPLY) { /* 如果是回应操作 */ if(bufMatch(arp.targetIPAdd, mIP.ip, 4)) { /* 如果请求的IP与本机相匹配 */ bufCopy(macBuf, arp.senderMACAdd, 6); break; } } } } return mIP_OK; }
/** * @brief 通过ARP首部结构体制作ARP首部到buffer中 * @param ptr: ARP首部结构体指针 * @param offset: buffer偏移量指针 * @retval none */ static void ARP_makeHead(ARPHeadStruct *ptr, UINT32 *offset) { UINT8 *buf = mIP.buf + *offset; UINT16TOPTRBIG(buf, ptr->hardwareType); buf += 2; UINT16TOPTRBIG(buf, ptr->protocolType); buf += 2; *buf++ = ptr->hardwareSize; *buf++ = ptr->protocolSize; UINT16TOPTRBIG(buf, ptr->opCode); buf += 2; bufCopy(buf, ptr->senderMACAdd, 6); buf += 6; bufCopy(buf, ptr->senderIPAdd, 4); buf += 4; bufCopy(buf, ptr->targetMACAdd, 6); buf += 6; bufCopy(buf, ptr->targetIPAdd, 4); buf += 4; *offset = buf - mIP.buf; }
/** * @brief 检查ARP高速缓存中是否有dstIP对应的MAC地址,并检查是否需要更新缓存 * @param dstIP: 目标IP * @param macBuf: 接收目标IP对应的MAC地址 * @retval 1: 查询并获取成功 0:目标IP不在缓存中 */ UINT8 ARP_checkCache(UINT8 *dstIP, UINT8 *macBuf) { UINT16 i; /* 检查是否缓存是否过期 */ if(myTCPIP_getTime() - mIP.arpCache.arpUpdataTime > (ARP_CACHE_UPDATETIME * 1000) || mIP.arpCache.arpUpdataTime > myTCPIP_getTime()) { /* 如果到了缓存更新时间或者定时器溢出,清空缓存 */ mIP.arpCache.num = 0; mIP.arpCache.arpUpdataTime = myTCPIP_getTime(); /* 更新缓存时间 */ return 0; } /* 检查缓存中是否有对应IP */ for(i = 0; i < mIP.arpCache.num; i++) { if(bufMatch(dstIP, mIP.arpCache.ip[i], 4)) { bufCopy(macBuf, mIP.arpCache.mac[i], 6); return 1; } } return 0; }
/** * @brief ARP回应,发送本机mac地址 * @param ptr: ARP首部结构体 * @retval none */ static void ARP_reply(ARPHeadStruct *ptr) { ETHHeadStruct ethTmp; UINT32 offset = 0; /* 载入ETH头 */ bufCopy(ethTmp.dstAdd, ptr->senderMACAdd, 6); bufCopy(ethTmp.srcAdd, mIP.mac, 6); ethTmp.type = PROTOCOL_TYPE_ARP; offset = 0; ETH_makeHead(ðTmp, &offset); /* 载入ARP头 */ ptr->opCode = ARP_OPCODE_REPLY; /* 响应操作 */ bufCopy(ptr->targetMACAdd, ptr->senderMACAdd, 6); bufCopy(ptr->targetIPAdd, ptr->senderIPAdd, 4); bufCopy(ptr->senderMACAdd, mIP.mac, 6); bufCopy(ptr->senderIPAdd, mIP.ip, 4); ARP_makeHead(ptr, &offset); /* 发送ARP响应 */ myTCPIP_sendPacket(mIP.buf, offset); }
void httpParseStream(HTTP *http, App *app, unsigned char *url) { Buf *buf; unsigned short c; unsigned char *contentType; int chunked; int i; unsigned char *line; unsigned int size; chunked = 0; c = httpReadHeaders(http, app, http->in, url, &contentType, &chunked); if (chunked) { buf = bufAlloc(-1); while (1) { bufMark(http->in, 0); c = bufGetByte(http->in); c = readLine(http->in, c); bufMark(http->in, -1); line = bufCopy(http->in); size = 0; sscanf((char *) line, "%x", &size); free(line); if (!size) { break; } bufUnGetByte(http->in); for (i = 0; i < size; i++) { c = bufGetByte(http->in); if (c == 256) { break; } else { bufPutChar(buf, c); } } c = bufGetByte(http->in); if (c != '\r') { break; } c = bufGetByte(http->in); if (c != '\n') { break; } } bufSet(buf, 0); bufMark(buf, 0); } else { buf = http->in; } http->body = bufCurrent(buf); if (contentType) { if ( (contentType != emptyHTTPResponse) && (contentType != http09Response) && (contentType != locationURLWasAdded) ) { app->contentType(app, contentType); if (!strcasecmp((char *) contentType, "text/html")) { htmlRead(app, buf, url); } else { httpDefaultType(http, app); } free(contentType); } } else { httpDefaultType(http, app); } if (chunked) { bufFree(buf); } app->printHTML(app, "</pre>"); }
static unsigned short httpReadHeaders(HTTP *http, App *app, Buf *buf, unsigned char *url, unsigned char **ct, int *chunked) { unsigned short c; unsigned char *charset; unsigned char *contentType; int locationFound; unsigned char *name; URL *rel; ContentType *type; unsigned char *value; char *version; app->printHTML(app, "<h4>Response</h4>"); app->printHTML(app, "<pre>"); contentType = NULL; locationFound = 0; bufMark(buf, 0); c = bufGetByte(buf); if (c == 256) { *ct = emptyHTTPResponse; return c; } nonEmptyHTTPResponseCount++; c = readNonWhiteSpace(buf, c); bufMark(buf, -1); app->httpResponse(app, buf); version = (char *) bufCopy(buf); if (!strcmp(version, "HTTP/1.0")) { } else if (!strcmp(version, "HTTP/1.1")) { } else if (!strncmp(version, "HTTP/", 5)) { } else { /* XXX deal with HTTP/0.9? */ *ct = http09Response; return c; } free(version); http10OrGreaterCount++; c = readSpaceTab(buf, c); c = readNumber(buf, c, &http->status); c = readLine(buf, c); while (1) { if (c == 256) { bufMark(buf, 0); app->httpResponse(app, buf); break; } bufMark(buf, -1); app->httpResponse(app, buf); if ((c == '\r') || (c == '\n')) { readLine(buf, c); bufUnGetByte(buf); bufMark(buf, 0); app->httpResponse(app, buf); break; } while ( (c != 256) && (c != '\r') && (c != '\n') && (c != ':') ) { c = bufGetByte(buf); } if (c != ':') { bufMark(buf, -1); fprintf(stderr, "no colon in HTTP header \"%s\": %s\n", bufCopy(buf), url); *ct = NULL; return c; } bufMark(buf, -1); app->httpResponseHeaderName(app, buf); name = bufCopyLower(buf); c = readSpaceTab(buf, bufGetByte(buf)); bufMark(buf, -1); app->httpResponse(app, buf); c = readLine(buf, c); if ((c == ' ') || (c == '\t')) { do { c = readLine(buf, c); } while ((c == ' ') || (c == '\t')); } c = bufTrimTrailingWhiteSpace(buf); bufMark(buf, -1); value = bufCopy(buf); if (!strcasecmp((char *) name, "content-type")) { app->httpResponseHeaderValue(app, buf, NULL); type = mimeParseContentType(value); contentType = mimeGetContentType(type); charset = mimeGetContentTypeParameter(type, "charset"); if (charset) { app->httpResponseCharSet(app, charset); free(charset); } mimeFreeContentType(type); } else if (!strcasecmp((char *) name, "location")) { /* XXX supposed to be absolute URL? */ rel = urlRelative(url, value); addURL(app, rel->url); app->httpResponseHeaderValue(app, buf, rel->url); urlFree(rel); locationFound = 1; } else if (!strcasecmp((char *) name, "transfer-encoding")) { app->httpResponseHeaderValue(app, buf, NULL); if (!strcasecmp((char *) value, "chunked")) { *chunked = 1; } } else { app->httpResponseHeaderValue(app, buf, NULL); } free(name); free(value); c = readLine(buf, c); bufMark(buf, -1); app->httpResponse(app, buf); } if (!contentType) { if (locationFound) { *ct = locationURLWasAdded; return c; } } *ct = contentType; return c; }