/* SendArpRequest(): */ int SendArpRequest(uchar *ip) { struct arphdr *ta; struct ether_header *te; unsigned long arppkt[ARPSIZE/2]; /* Populate the ethernet header: */ te = (struct ether_header *) arppkt; memcpy((char *)&(te->ether_shost), (char *)thismac.ether_addr_octet,6); memcpy((char *)&(te->ether_dhost), (char *)BroadcastAddr,6); te->ether_type = ecs(ETHERTYPE_ARP); /* Populate the arp header: */ ta = (struct arphdr *) (te + 1); ta->hardware = ecs(1); /* 1 for ethernet */ ta->protocol = ecs(ETHERTYPE_IP); ta->hlen = 6; /* Length of hdware (ethernet) address */ ta->plen = 4; /* Length of protocol (ip) address */ ta->operation = ecs(ARP_REQUEST); memcpy((char *)ta->senderha, (char *)thismac.ether_addr_octet,6); memcpy((char *)ta->senderia, (char *)&thisip.s_addr,4); memcpy((char *)ta->targetha, (char *)BroadcastAddr,6); memcpy((char *)ta->targetia, (char *)ip,4); mon_sendenetpkt((char *)arppkt,ARPSIZE); return(0); }
void CPostableObject::DetachThread() { if (!m_dwThreadId) return; // Get current thread info POSTABLETHREADINFO* pti=GetThreadInfo(m_dwThreadId, false); ASSERT(pti!=NULL); { // Remove any messages for this object from the queue CEnterCriticalSection ecs(&pti->m_Section); if (m_iQueuedMessages) { for (int i=pti->m_MessageQueue.GetSize()-1; i>=0; i--) { // Message for this object? if (pti->m_MessageQueue[i]->pTarget==this) { // Mark as an obsolete message pti->m_MessageQueue[i]->pTarget=NULL; } } } pti->m_dwCount--; if (pti->m_dwCount==0) { PostMessage(pti->m_hWndDispatcher, WM_POSTABLE_CLOSE, 0, 0); } } m_iQueuedMessages=0; m_dwThreadId=0; }
/* SendArpResp(): * Called in response to an ARP REQUEST. The incoming ethernet * header pointer points to the memory area that contains the incoming * ethernet packet that this function is called in response to. * In other words, it is used to fill the majority of the response * packet fields. */ int SendArpResp(struct ether_header *re) { struct arphdr *ta, *ra; struct ether_header *te; unsigned long arppkt[ARPSIZE/2]; te = (struct ether_header *) arppkt; memcpy((char *)&(te->ether_shost), (char *)thismac.ether_addr_octet,6); memcpy((char *)&(te->ether_dhost),(char *)&(re->ether_shost),6); te->ether_type = ecs(ETHERTYPE_ARP); ta = (struct arphdr *) (te + 1); ra = (struct arphdr *) (re + 1); ta->hardware = ra->hardware; ta->protocol = ra->protocol; ta->hlen = ra->hlen; ta->plen = ra->plen; ta->operation = ARP_RESPONSE; memcpy((char *)ta->senderha, (char *)thismac.ether_addr_octet,6); memcpy((char *)ta->senderia, (char *)ra->targetia,4); memcpy((char *)ta->targetha, (char *)ra->senderha,6); memcpy((char *)ta->targetia, (char *)ra->senderia,4); self_ecs(ta->hardware); self_ecs(ta->protocol); self_ecs(ta->operation); mon_sendenetpkt((char *)arppkt,ARPSIZE); return(0); }
LRESULT CPostableObject::PostAndWait(UINT nMessage, WPARAM wParam, LPARAM lParam) { ASSERT(m_dwThreadId!=0); // Get thread info POSTABLETHREADINFO* pti=GetThreadInfo(m_dwThreadId, false); ASSERT(pti!=NULL); // Setup for response... CEvent hReplyEvent(true); LRESULT lResult=0; // Setup a new message POSTABLEMESSAGE* p=new POSTABLEMESSAGE; p->pTarget=this; p->nMessage=nMessage; p->wParam=wParam; p->lParam=lParam; p->hReplyEvent=hReplyEvent; p->pResult=&lResult; { CEnterCriticalSection ecs(&pti->m_Section); m_iQueuedMessages++; pti->m_MessageQueue.Add(p); // If no pending Windows message, post one... if (!pti->m_bPostPending) { // Unless we're currently dispatching messages... in which case we'll post at the end of that. if (!pti->m_bDispatching) { PostMessage(pti->m_hWndDispatcher, WM_POSTABLE_DISPATCH, 0, 0); } // Set flag saying post is pending pti->m_bPostPending=true; } } while (true) { // Dispatch messages... MSG msg; while (PeekMessage(&msg, 0, 0, NULL, PM_REMOVE)) { if (!IsInputMessage(msg.message)) { DispatchMessage(&msg); } } // Wait for response... if (MsgWaitForMultipleObjects(1, &hReplyEvent.m_hObject, FALSE, INFINITE, QS_ALLEVENTS)==WAIT_OBJECT_0) return lResult; } }
// Helper to retrieve info about a thread... static POSTABLETHREADINFO* GetThreadInfo(DWORD dwThread, bool bCreate) { CEnterCriticalSection ecs(&g_Section); POSTABLETHREADINFO* pti=g_ThreadInfos.Get(dwThread, NULL); if (pti || !bCreate) return pti; pti=new POSTABLETHREADINFO(); g_ThreadInfos.Add(dwThread, pti); return pti; }
/* * === FUNCTION ====================================================================== * Name: Pop * Description: 以互斥的方式从队列中取出一条消息 * ===================================================================================== */ CMessage * CUsrDefMsgQueue::Pop() { CEnterCriticalSection ecs(&m_Mutex); if( IsEmpty() ) { return 0; } CMessage * pMsg = m_pQueueSpace[m_iQueueHead]; m_iQueueHead = (m_iQueueHead + 1) % m_iTotalRoom; return pMsg; }
void Dispatch() { CEnterCriticalSection ecs(&m_Section); // This should never go reentrant ASSERT(!m_bDispatching); // Clear flag m_bPostPending=false; // Dispatch all pending messages... m_bDispatching=true; int iCount=m_MessageQueue.GetSize(); for (int i=0; i<iCount; i++) { POSTABLEMESSAGE* p=m_MessageQueue[i]; if (p->pTarget!=NULL) { // Update queued message count p->pTarget->m_iQueuedMessages--; // Release lock while we send it ecs.Leave(); // Dispatch the message ASSERT(p->pTarget->GetThreadId()==GetCurrentThreadId()); LRESULT lResult=p->pTarget->OnMessage(p->nMessage, p->wParam, p->lParam); if (p->hReplyEvent) { *p->pResult=lResult; SetEvent(p->hReplyEvent); } // Reclaim lock ecs.Enter(&m_Section); } } m_bDispatching=false; // Remove messages just dispatched... m_MessageQueue.RemoveAt(0, iCount); // If messages got posted while dispatching messages, post the Windows message now... if (m_MessageQueue.GetSize()>0) { ASSERT(m_bPostPending); PostMessage(m_hWndDispatcher, WM_POSTABLE_DISPATCH, 0, 0); } }
/* * === FUNCTION ====================================================================== * Name: Push * Description: 以互斥的方式向消息队列中插入一条消息 * ===================================================================================== */ CStatus CUsrDefMsgQueue::Push(CMessage * pMsg) { CEnterCriticalSection ecs(&m_Mutex); if( IsFull() ) { CStatus s = EnlargeQueue(); if(!s.IsSuccess()) return CStatus(-1,0,"failed to Enlarge the queue!"); } m_pQueueSpace[m_iQueueTail] = pMsg; m_iQueueTail = (m_iQueueTail + 1) % m_iTotalRoom; return CStatus(0,0); }
void CPostableObject::AttachThread() { // Save the current thread ID m_dwThreadId=GetCurrentThreadId(); m_iQueuedMessages=0; CEnterCriticalSection ecs1(&g_Section); // Get info for this thread, creating it if need be POSTABLETHREADINFO* pti=GetThreadInfo(m_dwThreadId, true); ASSERT(pti!=NULL); // Bump the count... CEnterCriticalSection ecs(&pti->m_Section); pti->m_dwCount++; }
// Post a message to this object void CPostableObject::Post(UINT nMessage, WPARAM wParam, LPARAM lParam) { ASSERT(m_dwThreadId!=0); // Get thread info POSTABLETHREADINFO* pti=GetThreadInfo(m_dwThreadId, false); ASSERT(pti!=NULL); // Setup a new message POSTABLEMESSAGE* p=new POSTABLEMESSAGE; p->pTarget=this; p->nMessage=nMessage; p->wParam=wParam; p->lParam=lParam; p->hReplyEvent=NULL; p->pResult=NULL; { CEnterCriticalSection ecs(&pti->m_Section); pti->m_MessageQueue.Add(p); m_iQueuedMessages++; // If no pending Windows message, post one... if (!pti->m_bPostPending) { // Unless we're currently dispatching messages... in which case we'll post at the end of that. if (!pti->m_bDispatching) { PostMessage(pti->m_hWndDispatcher, WM_POSTABLE_DISPATCH, 0, 0); } // Set flag saying post is pending pti->m_bPostPending=true; } } }
uchar * ArpEther(struct udpinfo *u, uchar *ecpy) { struct ether_header *ehdr; uchar *binip, *gbinip, *Ip, *ep; int size, retry, timeoutsecs; binip = (uchar *)&u->dip.s_addr; gbinip = (uchar *)&thisgip.s_addr; /* First check local cache. If found, return with pointer to MAC. */ ep = EtherFromCache(binip); if (ep) { if (ecpy) { memcpy((char *)ecpy, (char *)ep,6); ep = ecpy; } return(ep); } retry = 0; while(1) { /* If IP is not on this net, the get the GATEWAY IP address. */ if (!IpIsOnThisNet(binip)) { ep = EtherFromCache(gbinip); if (ep) { if (ecpy) { memcpy((char *)ecpy, (char *)ep,6); ep = ecpy; } return(ep); } SendArpRequest(gbinip); Ip = gbinip; } else { SendArpRequest(binip); Ip = binip; } /* Now that the request has been issued, wait for a while to see if * the ARP cache is loaded with the result of the request. */ for(timeoutsecs=0; timeoutsecs<1000000; timeoutsecs++) { ep = EtherFromCache(Ip); if (ep) break; size = mon_recvenetpkt(u->packet,u->plen); if (size == 0) continue; ehdr = (struct ether_header *)u->packet; if (!memcmp(ehdr->ether_shost.ether_addr_octet, thismac.ether_addr_octet,6)) { continue; } if (ehdr->ether_type == ecs(ETHERTYPE_ARP)) { processARP(ehdr,size); } } if (ep) { if (ecpy) { memcpy((char *)ecpy, (char *)ep,6); ep = ecpy; } return(ep); } retry++; } return(0); }
int sendSyslog(uchar *syslogsrvr,char *msg, short port, int null) { int msglen; uchar *syslogmsg; ushort ip_len, sport; struct ether_header *enetp; struct ip *ipp; struct Udphdr *udpp; uchar binip[8], binenet[8], *enetaddr; /* msglen is the length of the message, plus optionally the * terminating null character (-n option of syslog command).. */ msglen = strlen(msg) + null; /* Convert IP address to binary: */ if (IpToBin((char *)syslogsrvr,(unsigned char *)binip) < 0) return(0); /* Get the ethernet address for the IP: */ enetaddr = ArpEther(binip,binenet,0); if (!enetaddr) { printf("ARP failed for %s\n",syslogsrvr); return(0); } /* Retrieve an ethernet buffer from the driver and populate the * ethernet level of packet: */ enetp = (struct ether_header *) getXmitBuffer(); memcpy((char *)&enetp->ether_shost,(char *)BinEnetAddr,6); memcpy((char *)&enetp->ether_dhost,(char *)binenet,6); enetp->ether_type = ecs(ETHERTYPE_IP); /* Move to the IP portion of the packet and populate it * appropriately: */ ipp = (struct ip *) (enetp + 1); ipp->ip_vhl = IP_HDR_VER_LEN; ipp->ip_tos = 0; ip_len = sizeof(struct ip) + sizeof(struct Udphdr) + msglen; ipp->ip_len = ecs(ip_len); ipp->ip_id = ipId(); ipp->ip_off = 0; ipp->ip_ttl = UDP_TTL; ipp->ip_p = IP_UDP; memcpy((char *)&ipp->ip_src.s_addr,(char *)BinIpAddr,4); memcpy((char *)&ipp->ip_dst.s_addr,(char *)binip,4); /* Now UDP... */ sport = port+1; udpp = (struct Udphdr *) (ipp + 1); udpp->uh_sport = ecs(sport); udpp->uh_dport = ecs(port); udpp->uh_ulen = ecs((ushort)(ip_len - sizeof(struct ip))); /* Finally, the SYSLOG data ... */ syslogmsg = (uchar *)(udpp+1); strcpy((char *)syslogmsg,(char *)msg); ipChksum(ipp); /* Compute csum of ip hdr */ udpChksum(ipp); /* Compute UDP checksum */ sendBuffer(ETHERSIZE + IPSIZE + UDPSIZE + msglen); return(0); }
/* processGDB(): * This is the function that allows a remote gdb host to connect to * the monitor with gdb at the udp level. The connection command in * gdb to do this is: * * target remote udp:TARGET_IP:TARGET_PORT */ int processGDB(struct ether_header *ehdr,ushort size) { char *gdbp; struct ip *ihdr, *ti, *ri; struct Udphdr *uhdr, *tu, *ru; struct ether_header *te; /* If SHOW_GDB is set (via ether -vg), then we dump the trace to * the console; otherwise, we use mtrace. */ #if INCLUDE_ETHERVERBOSE if (EtherVerbose & SHOW_GDB) gdbTrace = printf; else #endif gdbTrace = Mtrace; ihdr = (struct ip *)(ehdr + 1); uhdr = (struct Udphdr *)((char *)ihdr + IP_HLEN(ihdr)); gdbp = (char *)(uhdr + 1); size = ecs(uhdr->uh_ulen) - sizeof(struct Udphdr); /* Check for ACK/NAK here: */ if (size == 1) { if ((*gdbp == '+') || (*gdbp == '-')) { gdbTrace("GDB_%s\n",*gdbp == '+' ? "ACK" : "NAK"); return(0); } } /* Copy the incoming udp payload (the gdb command) to gdbIbuf[] * and NULL terminate it... */ memcpy((char *)gdbIbuf,(char *)gdbp,size); gdbIbuf[size] = 0; /* Now that we've stored away the GDB command request, we * initially respond with the GDB acknowledgement ('+')... */ te = EtherCopy(ehdr); ti = (struct ip *) (te + 1); ri = (struct ip *) (ehdr + 1); ti->ip_vhl = ri->ip_vhl; ti->ip_tos = ri->ip_tos; ti->ip_len = ecs((1 + (sizeof(struct ip) + sizeof(struct Udphdr)))); ti->ip_id = ipId(); ti->ip_off = ri->ip_off; ti->ip_ttl = UDP_TTL; ti->ip_p = IP_UDP; memcpy((char *)&(ti->ip_src.s_addr),(char *)BinIpAddr, sizeof(struct in_addr)); memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), sizeof(struct in_addr)); tu = (struct Udphdr *) (ti + 1); ru = (struct Udphdr *) (ri + 1); tu->uh_sport = ru->uh_dport; tu->uh_dport = ru->uh_sport; tu->uh_ulen = ecs((ushort)(sizeof(struct Udphdr) + 1)); gdbp = (char *)(tu+1); *gdbp = '+'; ipChksum(ti); /* Compute checksum of ip hdr */ udpChksum(ti); /* Compute UDP checksum */ sendBuffer(sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct Udphdr) + 1); /* Wrap the processing of the incoming packet with a set/clear * of the gdbUdp flag so that the other gdb code can act * accordingly. */ gdbUdp = 1; if (gdb_cmd(gdbIbuf) == 0) { gdbUdp = 0; return(0); } gdbUdp = 0; /* Add 1 to the gdbRlen to include the NULL termination. */ gdbRlen++; /* The second respons is only done if gdb_cmd returns non-zero. * It is the response to the gdb command issued by the debugger * on the host. */ te = EtherCopy(ehdr); ti = (struct ip *) (te + 1); ri = (struct ip *) (ehdr + 1); ti->ip_vhl = ri->ip_vhl; ti->ip_tos = ri->ip_tos; ti->ip_len = ecs((gdbRlen + (sizeof(struct ip) + sizeof(struct Udphdr)))); ti->ip_id = ipId(); ti->ip_off = ri->ip_off; ti->ip_ttl = UDP_TTL; ti->ip_p = IP_UDP; memcpy((char *)&(ti->ip_src.s_addr),(char *)BinIpAddr, sizeof(struct in_addr)); memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), sizeof(struct in_addr)); tu = (struct Udphdr *) (ti + 1); ru = (struct Udphdr *) (ri + 1); tu->uh_sport = ru->uh_dport; tu->uh_dport = ru->uh_sport; tu->uh_ulen = ecs((ushort)(sizeof(struct Udphdr) + gdbRlen)); memcpy((char *)(tu+1),(char *)gdbRbuf,gdbRlen); ipChksum(ti); /* Compute checksum of ip hdr */ udpChksum(ti); /* Compute UDP checksum */ sendBuffer(sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct Udphdr) + gdbRlen); return(1); }
/* BOOTPStartup() * The DHCPDISCOVER is issued as an ethernet broadcast. IF the bootp * flag is non-zero then just do a bootp request (a subset of the * DHCPDISCOVER stuff). */ int BOOTPStartup(short seconds) { struct dhcphdr *dhcpdata; struct bootphdr *bootpdata; struct ether_header *te; struct ip *ti; struct Udphdr *tu; ushort uh_ulen; int optlen; /* Retrieve an ethernet buffer from the driver and populate the * ethernet level of packet: */ te = (struct ether_header *) getXmitBuffer(); memcpy((char *)&te->ether_shost,(char *)BinEnetAddr,6); memcpy((char *)&te->ether_dhost,(char *)BroadcastAddr,6); te->ether_type = ecs(ETHERTYPE_IP); /* Move to the IP portion of the packet and populate it appropriately: */ ti = (struct ip *) (te + 1); ti->ip_vhl = IP_HDR_VER_LEN; ti->ip_tos = 0; ti->ip_id = 0; ti->ip_off = ecs(0x4000); /* No fragmentation allowed */ ti->ip_ttl = UDP_TTL; ti->ip_p = IP_UDP; memset((char *)&ti->ip_src.s_addr,0,4); memset((char *)&ti->ip_dst.s_addr,0xff,4); /* Now udp... */ tu = (struct Udphdr *) (ti + 1); tu->uh_sport = ecs(DhcpClientPort); tu->uh_dport = ecs(DhcpServerPort); /* First the stuff that is the same for BOOTP or DHCP... */ bootpdata = (struct bootphdr *)(tu+1); dhcpdata = (struct dhcphdr *)(tu+1); dhcpdata->op = DHCPBOOTP_REQUEST; dhcpdata->htype = 1; dhcpdata->hlen = 6; dhcpdata->hops = 0; dhcpdata->seconds = ecs(seconds); memset((char *)dhcpdata->bootfile,0, sizeof(dhcpdata->bootfile)); memset((char *)dhcpdata->server_hostname,0, sizeof(dhcpdata->server_hostname)); /* For the first request issued, establish a transaction id based * on a crc32 of the mac address. For each request after that, * just increment. */ if (!BOOTPTransactionId) BOOTPTransactionId = BinEnetAddr[5]; else BOOTPTransactionId++; memcpy((char *)&dhcpdata->transaction_id,(char *)&BOOTPTransactionId,4); memset((char *)&dhcpdata->client_ip,0,4); memset((char *)&dhcpdata->your_ip,0,4); memset((char *)&dhcpdata->server_ip,0,4); memset((char *)&dhcpdata->router_ip,0,4); memcpy((char *)dhcpdata->client_macaddr,(char *)BinEnetAddr,6); dhcpdata->flags = 0; self_ecs(dhcpdata->flags); /* Finally, the DHCP or BOOTP specific stuff... * Based on RFC1534 (Interoperation Between DHCP and BOOTP), any message * received by a DHCP server that contains a 'DHCP_MESSAGETYPE' option * is assumed to have been sent by a DHCP client. A message without the * DHCP_MESSAGETYPE option is assumed to have been sent by a BOOTP * client. */ uh_ulen = optlen = 0; memset((char *)bootpdata->vsa,0,sizeof(bootpdata->vsa)); uh_ulen = sizeof(struct Udphdr) + sizeof(struct bootphdr); tu->uh_ulen = ecs(uh_ulen); ti->ip_len = ecs((sizeof(struct ip) + uh_ulen)); ipChksum(ti); /* Compute checksum of ip hdr */ udpChksum(ti); /* Compute UDP checksum */ DHCPState = BOOTPSTATE_REQUEST; sendBuffer(BOOTPSIZE); return(0); }