user-0 提问: DHCP 网络通信

回复:
user: user-0
content: void proc_dhcp_renew(tEthpkt* pkthdr, tIp* pIp, tUser* pUser) {     tUdp*   pudp;     tDhcp*  pdhcp;     UINT4   rip;     tTlv*   pTlv = NULL;     UINT4   yaddr;      pudp = (tUdp*)pIp->data;     if(!pudp)         return ;      pdhcp = (tDhcp*)pudp->data;     if(!pdhcp)         return ;      if(pdhcp->cipaddr == 0)     {         rip = GetOptionInt((char*)pdhcp->data, 50);     }     else     {         rip = pdhcp->cipaddr;     }     if(rip != 0)     {         if((ntohl(rip) & 0xffffff00) != (ntohl(dhcp_config.gateway)& 0xffffff00))  //不在同一网段         {             proc_dhcp_nak(pkthdr, pIp, pUser);             return ;         }     }     if(rip)     {         yaddr = rip;     }     else     {         if(pUser->dhcp_flag)         {             yaddr = pUser->ip;         }         else         {             yaddr = get_dhcp_request_ip(pUser->mac);             pUser->dhcp_flag = TRUE;             pUser->ip = yaddr;         }     }     memcpy(pkthdr->pEth->dest, pkthdr->pEth->src, MAC_ALEN);     memcpy(pkthdr->pEth->src,  dhcp_config.mac,   MAC_ALEN);      pIp->dest = yaddr;     pIp->src = dhcp_config.gateway;      pudp->dport = htons(68);     pudp->sport = htons(67);      if(pdhcp->opt == 0x01)         pdhcp->opt = 0x02;      if(pdhcp->htype != 0x01)         pdhcp->htype = 0x01;      pdhcp->hlen = 0x06;     pdhcp->hops = 1;     pdhcp->xid  = htonl(rand());     pdhcp->secd = 0;     pdhcp->flg = 0;     pdhcp->cipaddr = 0;     pdhcp->yipaddr = yaddr;     pdhcp->sipaddr = 0;     pdhcp->gipaddr = 0;     memcpy(pdhcp->cmcaddr, pkthdr->pEth->dest, MAC_ALEN);     pdhcp->hostname[0] = 0xff;     memset(pdhcp->filename, 0, 128);     pdhcp->sname = htonl(0x63825363);      //dhcp ack     pTlv = (tTlv *)pdhcp->data;     pTlv->type = 0x35;     pTlv->len  = 0x01;     pTlv->data[0] = 0x05;              //server ip address     pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0x36;     pTlv->len  = 0x04;         memcpy(pTlv->data, &dhcp_config.gateway, 4);          //time     pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0x33;     pTlv->len  = 0x04;     pTlv->data[0] = 0x00;     pTlv->data[1] = 0x01;     pTlv->data[2] = 0x51;     pTlv->data[3] = 0x80;          //net mask     pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0x01;     pTlv->len  = 0x04;     pTlv->data[0]=0xff;     pTlv->data[1]=0xff;     pTlv->data[2]=0xff;     pTlv->data[3]=0x00;      //gateway     pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0x03;     pTlv->len  = 0x04;     memcpy(pTlv->data, &dhcp_config.gateway, 4);      //dns     pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0x06;     pTlv->len  = 0x04;     //pTlv->len  = 0x08;     memcpy(pTlv->data, &dhcp_config.main_dns, 4);     memcpy(pTlv->data + 4, &dhcp_config.back_dns, 4);      #if 0     //netbios     pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0x2e;     pTlv->len  = 0x01;     pTlv->data[0] = 0x08;     #endif      pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0xff;     pTlv->len  = 0xff;     memset(pTlv->data, 0 , 10);      pIp->cksum = 0;     pIp->cksum = IpCksum(pIp, IP_HLEN(pIp));      pudp->cksum = 0;     pudp->cksum = UdpCksum(pIp, ntohs(pIp->len) - 20);      xmit_packet(pkthdr->ifindex, pkthdr->pid, pkthdr); }  void proc_dhcp_nak(tEthpkt* pkthdr, tIp* pIp, tUser* pUser) {     tUdp*   pudp;     tDhcp*  pdhcp;     tTlv*   pTlv = NULL;      memcpy(pkthdr->pEth->dest, pkthdr->pEth->src, MAC_ALEN);     memcpy(pkthdr->pEth->src, dhcp_config.mac, MAC_ALEN);      pudp = (tUdp*)pIp->data;     if(!pudp)         return ;      pudp->dport = htons(68);     pudp->sport = htons(67);      pdhcp = (tDhcp *)pudp->data;      if (!pdhcp)         return ;         pIp->dest = htonl(0xffffffff);     pIp->src = dhcp_config.gateway;      if(pdhcp->opt == 0x01)         pdhcp->opt = 0x02;      if(pdhcp->htype != 0x01)         pdhcp->htype = 0x01;      pdhcp->hlen = 0x06;     pdhcp->cipaddr = htonl(0x00);     memcpy(pdhcp->cmcaddr, pkthdr->pEth->dest, MAC_ALEN);      pTlv = (tTlv*)pdhcp->data;     pTlv->type = 0x35;     pTlv->len = 0x01;     pTlv->data[0] = 0x06;      pTlv = (tTlv*)(pTlv->data + pTlv->len);     pTlv->type = 0x36;     pTlv->len = 0x04;     memcpy(pTlv->data, &dhcp_config.gateway, 4);      pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0xff;     pTlv->len  = 0xff;     memset(pTlv->data, 0 , 10);      pIp->cksum = 0;     pIp->cksum = IpCksum(pIp, IP_HLEN(pIp));      pudp->cksum = 0;     pudp->cksum = UdpCksum(pIp, ntohs(pIp->len) - 20);      xmit_packet(pkthdr->ifindex, pkthdr->pid, pkthdr);  }  void proc_dhcp_decline(tUser* pUser) {     int         i = 0;      for (i=0;i<0xfff;i++)     {         if (memcmp(dnode[i].mac, pUser->mac, MAC_ALEN) == 0)         {             memset(dnode[i].mac, 0xff, MAC_ALEN);               pUser->dhcp_flag = FALSE;             break;         }     }      for (i=0; i<0xfff; i++)     {         if (dnode[i].isused == FALSE)         {             dnode[i].isused     = TRUE;             dnode[i].renew_time = time(NULL);             memcpy(dnode[i].mac, pUser->mac, MAC_ALEN);             pUser->dhcp_flag = FALSE;             break;         }     } }  UINT4 GetOptionInt(char* data, UINT1 type) {     tTlv*  ptlv;     UINT4  result = 0;      ptlv = (tTlv*)data;     while(ptlv)     {         if(!ptlv)             break;         if(ptlv->len == 0)             break;         if(ptlv->type == 0xff ||            ptlv->type == 0)             break;         if(ptlv->type== type && ptlv->len == 4)         {             memcpy(&result, ptlv->data, 4);             break;         }         ptlv = (tTlv*)(ptlv->data + ptlv->len);     }     return result; }  static UINT4 get_dhcp_request_ip(UINT1* mac) {     int i = 0;     for (i = 0; i < DHCP_NODE_MAX; i++)     {         if(memcmp(dnode[i].mac, mac, MAC_ALEN) == 0)         {             dnode[i].isused = TRUE;             dnode[i].renew_time = time(NULL);             if(dnode[i].ipaddr)             {                 return dnode[i].ipaddr;             }         }     }      for(i = 0; i < DHCP_NODE_MAX; i++)     {         if(dnode[i].isused == FALSE)         {             dnode[i].isused = TRUE;             memcpy(dnode[i].mac, mac, MAC_ALEN);             dnode[i].renew_time = time(NULL);             return dnode[i].ipaddr;         }     }     return 0; }

user: user-0
content: void dhcp_server(tEthpkt* pkthdr) {     tEther*  pEth;     tIp*     pIp;      pEth = (tEther*)pkthdr->pEth;     pIp = (tIp*)pEth->data;      proc_dhcp_pkt(pkthdr,  pIp); }  inline tUser*  CheckUserExit(UINT1*  mac) {     tUser*  pUser = NULL;     int     hsindex = 0;      mutex_lock(UserTable.mutex);     hsindex = MacHash(mac, UserTable.capcity);     while(pUser)     {         if(!pUser)             break;         if(pUser->mac[5] == mac[5] &&            pUser->mac[4] == mac[4] &&            pUser->mac[3] == mac[3])         {             if(pUser->mac[2] == mac[2] &&                pUser->mac[1] == mac[1] &&                pUser->mac[0] == mac[0])             {                 mutex_unlock(UserTable.mutex);                 return pUser;             }         }           pUser = pUser->next;     }     mutex_unlock(UserTable.mutex);      return NULL; } void User_Tm_out(void* para, tTimer* tid) {     tUser*  pUser;      pUser = (tUser*)para;     if(!pUser)     {         kill_timer(tid);     }      if(time_now - pUser->time > 86400)     {        pUser->clear_flag = TRUE;     } } inline tUser* add_newuser_toTb(tUser* pUser) {     tUser*  pTmpScan = NULL;     int     uindex = 0;      uindex = MacHash(pUser->mac, UserTable.capcity);     pTmpScan = UserTable.user_arr[uindex];      mutex_lock(UserTable.mutex);     if(pTmpScan)     {         while(pTmpScan)         {             if(pTmpScan->mac[5] == pUser->mac[5] &&                pTmpScan->mac[4] == pUser->mac[4] &&                pTmpScan->mac[3] == pUser->mac[3])             {                 if(pTmpScan->mac[2] == pUser->mac[2] &&                    pTmpScan->mac[1] == pUser->mac[1] &&                    pTmpScan->mac[0] == pUser->mac[0])                 {                     ReleaseMemToPool(UserTable.pool, (char*)pUser);                     pUser = pTmpScan;                     break;                 }             }                 pTmpScan = pTmpScan->next;         }         if(!pTmpScan)         {             create_ctimer(UserTable.timerID, 5, pUser, &pUser->time_id, User_Tm_out);             pUser->next = UserTable.user_arr[uindex];             UserTable.user_arr[uindex] = pUser;         }     }     else     {         create_ctimer(UserTable.timerID, 5, pUser, &pUser->time_id, User_Tm_out);         pUser->next = UserTable.user_arr[uindex];         UserTable.user_arr[uindex] = pUser;     }     mutex_unlock(UserTable.mutex);     return pUser; } void proc_dhcp_pkt(tEthpkt* pkthdr, tIp*  pIp) {     tDhcp*  pdhcp;     tUser*  pUser;     tUdp*   pudp;     tTlv*   ptlv;      pUser = CheckUserExit(pkthdr->pEth->src);     if(!pUser)     {         pUser = (tUser*)GetMemFromPool(UserTable.pool);         if(pUser)         {             pUser->ip = pIp->src;    //  ip: 0:0:0:0             memcpy(pUser->mac, pkthdr->pEth->src, MAC_ALEN);             pUser->time = time_now;             add_newuser_toTb(pUser);         }         else         {             return ;         }     }      pudp = (tUdp*)pIp->data;     if(!pudp)         return ;      pdhcp = (tDhcp*)pudp->data;     if(!pdhcp)         return ;      if(pdhcp->opt == 0x01)     {         ptlv = (tTlv*)pdhcp->data;         if(ptlv->type == 0x35)         {             if(ptlv->data[0] == 0x01)//dhcp discovery             {                 printf("bootp offer!\n");                 proc_dhcp_offer(pkthdr, pIp, pUser);             }             else if (ptlv->data[0] == 0x03)//dhcp request/renew             {                 printf("bootp request\n");                 proc_dhcp_renew(pkthdr, pIp, pUser);             }             else if (ptlv->data[0] == 0x04)//dhcp decline             {                 printf("bootp decline\n");                 proc_dhcp_decline(pUser);             }             else if (ptlv->data[0] == 0x07)// dhcp release             {                 printf("bootp release\n");             }         }     } } void proc_dhcp_offer(tEthpkt* pkthdr, tIp* pIp, tUser* pUser) {     tUdp*  pudp;     tDhcp* pdhcp;     tTlv*  ptlv = NULL;     UINT4  yaddr;      memcpy(pkthdr->pEth->dest, pkthdr->pEth->src, MAC_ALEN);     memcpy(pkthdr->pEth->src, dhcp_config.mac, MAC_ALEN);      pudp = (tUdp*)pIp->data;     if(!pudp)         return ;      pudp->dport = htons(68);     pudp->sport = htons(67);      pdhcp = (tDhcp*)pudp->data;      if(!pdhcp)         return ;      if(pUser->dhcp_flag)     {         yaddr = pUser->ip;     }     else     {         yaddr = get_dhcp_request_ip(pUser->mac);         pUser->dhcp_flag = TRUE;         pUser->ip = yaddr;     }         pIp->dest = yaddr;     pIp->src = dhcp_config.gateway;      if(pdhcp->opt == 0x01)         pdhcp->opt = 0x02;      if(pdhcp->htype != 0x01)         pdhcp->htype == 0x01;      pdhcp->hlen = 0x06;     pdhcp->hops = 1;     //dhcp报文经过的dhcp中继的数目，dhcp请求报文每经过一个dhcp中继，该字段就会加1     pdhcp->xid  = htonl(rand());     pdhcp->secd = htons(0x00);     pdhcp->flg = htons(0x00);     pdhcp->cipaddr = 0;     pdhcp->yipaddr = yaddr;     pdhcp->sipaddr = 0;     pdhcp->gipaddr = 0;     memcpy(pdhcp->cmcaddr, pkthdr->pEth->dest, MAC_ALEN);     pdhcp->hostname[0] = 0xff;     memset(pdhcp->filename, 0, 128);     pdhcp->sname = htonl(0x63825363);      ptlv = (tTlv *)pdhcp->data;     ptlv->type = 0x35;     ptlv->len  = 0x01;     ptlv->data[0] = 0x02;              //server ip address     ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0x36;     ptlv->len  = 0x04;         memcpy(ptlv->data, &dhcp_config.gateway, 4);          //time     ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0x33;     ptlv->len  = 0x04;     ptlv->data[0] = 0x00;     ptlv->data[1] = 0x01;     ptlv->data[2] = 0x51;     ptlv->data[3] = 0x80;          //net mask     ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0x01;     ptlv->len  = 0x04;     ptlv->data[0]=0xff;     ptlv->data[1]=0xff;     ptlv->data[2]=0xff;     ptlv->data[3]=0x00;      //gateway     ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0x03;     ptlv->len  = 0x04;     memcpy(ptlv->data, &dhcp_config.gateway, 4);      //dns     ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0x06;     ptlv->len  = 0x04;     //ptlv->len  = 0x08;     memcpy(ptlv->data,  &dhcp_config.main_dns, 4);     //memcpy(ptlv->data + 4, &dhcp_config.back_dns, 4);      #if 0     //netbios     ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0x2e;     ptlv->len  = 0x01;     ptlv->data[0] = 0x08;     #endif          ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0xff;     ptlv->len  = 0xff;     memset(ptlv->data, 0 , 10);      pIp->cksum = 0;     pIp->cksum = IpCksum(pIp, IP_HLEN(pIp));      pudp->cksum = 0;     pudp->cksum = UdpCksum(pIp, ntohs(pIp->len) - 20);      xmit_packet(pkthdr->ifindex, pkthdr->pid, pkthdr);     }