void recv_data(int len) { static i32 i; static u32 buffer[4]; const __builtin_quad *b = (__builtin_quad *)buffer; i32 tout; while (len >= 4) { tout = 0x1000; buffer[i] = (u32)(RECEIVE_NETWORK_B() & 0xFF) << 24 | (u32)(RECEIVE_NETWORK_B() & 0xFF) << 16 | (u32)(RECEIVE_NETWORK_B() & 0xFF) << 8 | (u32)(RECEIVE_NETWORK_B() & 0xFF); i = (i + 1) % 4; if (i == 0) { while (!link_ready() && --tout) { asm("nop;nop;nop;nop;;"); } if (tout) { link_send(b); } } if (tout) { len -= 4; } else { len = 0; } } }
/* * Event listener invoked when TCP/IP stack receives UDP datagram for * a given socket. Parameters: * - cbhandle - handle of the socket this packet is intended for. Check it * just to be sure, but in general case not needed * - event - event that is notified. For UDP, only UDP_EVENT_DATA * - ipaddr - IP address of remote host who sent the UDP datagram * - port - port number of remote host who sent the UDP datagram * - buffindex - buffer index in RTL8019AS allowing you to read * received data more than once from Ethernet controller by * invoking NETWORK_RECEIVE_INITIALIZE(buffindex) and then start * reading the bytes all over again */ INT32 udp_demo_eventlistener(INT8 cbhandle, UINT8 event, UINT32 ipaddr, UINT16 port, UINT16 buffindex, UINT16 datalen){ UINT16 i; if(cbhandle!=udp_demo_soch){ DEBUGOUT("Not my handle!!!!"); return (-1); } switch(event){ case UDP_EVENT_DATA: /* read data that was received (and * probably do something with it :-) */ for(i=0;i<datalen;i++) RECEIVE_NETWORK_B(); /* If needed initialize data sending * by setting udp_demo_senddata variable or * send data directly from event listener ( * only possible for UDP applications!!!! */ break; default: /* should never get here */ DEBUGOUT("Unknown UDP event :-("); break; } return 0; }
/********************************************************************* * * FUNCTION: GetNameValuePair * * ARGUMENTS: None * * RETURNS: None * * DESCRIPTION: * * RESTRICTIONS: * *********************************************************************/ UINT16 GetNameValuePair(UINT16 wLen, char* pszName, char* pszValue) { UINT8 ch; UINT8 i; char* pStr; char cBuild; pStr = pszName; for(i = 0; i < wLen; i++) { ch = RECEIVE_NETWORK_B(); switch(ch) { case ' ': *pStr = 0; return 0; break; case '&': *pStr = 0; return i; break; case '=': *pStr = 0; pStr = pszValue; break; case '%': ch = RECEIVE_NETWORK_B(); cBuild = ch - 0x30; ch = RECEIVE_NETWORK_B(); cBuild = (0x10 * cBuild) + (ch - 0x30); break; default: *pStr++ = ch; break; } } return 0; }
/** \brief BOOTP event listener * \author * \li Jari Lahti ([email protected]) * \date 07.10.2002 * \param cbhandle handle of the socket this packet is intended for. * \param event event that is notified. For UDP, only UDP_EVENT_DATA. * \param ipaddr IP address of remote host who sent the UDP datagram * \param port port number of remote host who sent the UDP datagram * \param buffindex buffer index in RTL8019AS * \return * \li - 1 - error in processing * \li >0 - BOOTP reply successfully processed * \note * \li Event listeners are NOT to be invoked directly. They are * callback functions invoked by the TCP/IP stack to notify events. * * Analyze received UDP packet and see if it contains what we need. If * yes, get new network settings. * */ INT32 bootpc_eventlistener (INT8 cbhandle, UINT8 event, UINT32 remip, UINT16 remport, UINT16 bufindex, UINT16 dlen) { INT16 i,j,k; UINT32 ip = 0; UINT32 nm = 0; UINT32 dgw = 0; UINT8 ch; /* This function is called by UDP stack to inform about events */ if(bootp_app_init == 0) return(-1); if( cbhandle != bootp.sochandle) /* Not our handle */ return(-1); /* The only event is data */ if(bootp.state != BOOTPC_STATE_WAITING_REPLY) return(-1); /* Process reply */ NETWORK_RECEIVE_INITIALIZE(bufindex); if(dlen < 300) return(-1); if( RECEIVE_NETWORK_B() != BOOTP_REPLY) return(-1); if( RECEIVE_NETWORK_B() != BOOTP_HTYPE_ETHERNET) return(-1); if( RECEIVE_NETWORK_B() != BOOTP_HWLEN_ETHERNET) return(-1); RECEIVE_NETWORK_B(); /* Skip hops */ /* Check transaction ID */ if( RECEIVE_NETWORK_B() != 0xCA) return(-1); if( RECEIVE_NETWORK_B() != 0x03) return(-1); if( RECEIVE_NETWORK_B() != 0x32) return(-1); if( RECEIVE_NETWORK_B() != 0xF1) return(-1); /* Skip elapsed, unused, client address */ for(i=0; i<8; i++) RECEIVE_NETWORK_B(); /* Get IP */ ip = RECEIVE_NETWORK_B(); ip <<= 8; ip |= RECEIVE_NETWORK_B(); ip <<= 8; ip |= RECEIVE_NETWORK_B(); ip <<= 8; ip |= RECEIVE_NETWORK_B(); /* Skip server ip & bootp router address */ for(i=0; i<8; i++) RECEIVE_NETWORK_B(); /* Check MAC */ if( RECEIVE_NETWORK_B() != localmachine.localHW[5]) return(-1); if( RECEIVE_NETWORK_B() != localmachine.localHW[4]) return(-1); if( RECEIVE_NETWORK_B() != localmachine.localHW[3]) return(-1); if( RECEIVE_NETWORK_B() != localmachine.localHW[2]) return(-1); if( RECEIVE_NETWORK_B() != localmachine.localHW[1]) return(-1); if( RECEIVE_NETWORK_B() != localmachine.localHW[0]) return(-1); RECEIVE_NETWORK_B(); RECEIVE_NETWORK_B(); for(i=0; i<200; i++) RECEIVE_NETWORK_B(); /* Check options */ dlen -= 236; i = 0; while(i<dlen) { ch = RECEIVE_NETWORK_B(); i++; if( (ch != BOOTP_OPTION_SUBNETMASK) && (ch != BOOTP_OPTION_DEFGW) ) { /* Not supported option, skip it */ j = RECEIVE_NETWORK_B(); i++; if(j >= 2) { j -= 2; while(j--) { RECEIVE_NETWORK_B(); i++; } } continue; } if( ch == BOOTP_OPTION_SUBNETMASK) { RECEIVE_NETWORK_B(); /* Skip totlen */ nm = RECEIVE_NETWORK_B(); nm <<= 8; nm |= RECEIVE_NETWORK_B(); nm <<= 8; nm |= RECEIVE_NETWORK_B(); nm <<= 8; nm |= RECEIVE_NETWORK_B(); i += 5; } if( ch == BOOTP_OPTION_DEFGW) { j = RECEIVE_NETWORK_B(); /* Get totlen */ dgw = RECEIVE_NETWORK_B(); dgw <<= 8; dgw |= RECEIVE_NETWORK_B(); dgw <<= 8; dgw |= RECEIVE_NETWORK_B(); dgw <<= 8; dgw |= RECEIVE_NETWORK_B(); i += 5; /* Skip others */ if( j>5 ) { j -= 5; while(j--) { RECEIVE_NETWORK_B(); i++; } } } } /* Store parameters */ localmachine.localip = ip; localmachine.defgw = dgw; localmachine.netmask = nm; /* Change state */ bootp.state = BOOTPC_STATE_REPLY_GET; return(1); }
INT32 smtpc_eventlistener (INT8 cbhandle, UINT8 event, UINT32 par1, UINT32 par2) { /* This function is called by TCP stack to inform about events */ UINT16 cmd; par2++; if( cbhandle != smtp_client.sochandle) /* Not our handle */ return(-1); switch( event ) { case TCP_EVENT_CONREQ: /* We don't allow incoming connections */ return(-1); case TCP_EVENT_ABORT: if(smtp_client.state > SMTP_CLOSED) { /* Inform application */ smtpc_error(); } smtpc_changestate(SMTP_CLOSED); smtp_client.unacked = 0; return(1); break; case TCP_EVENT_CONNECTED: if(smtp_client.state == SMTP_CONNECTIONOPEN_SENT) { DEBUGOUT("SMTP TCP connection opened\r\n"); smtpc_changestate(SMTP_CONNECTION_OPENED); smtp_client.unacked = 0; smtp_client.bufindex = TCP_APP_OFFSET; return(-1); } break; case TCP_EVENT_CLOSE: smtpc_changestate(SMTP_CLOSED); smtp_client.unacked = 0; return(1); break; case TCP_EVENT_ACK: /* Our message is acked */ smtp_client.unacked = 0; break; case TCP_EVENT_DATA: /* Do we have unacked data? */ if(smtp_client.unacked) return(-1); /* Get reply from server */ if(par1 < 3) /* Long enough? */ return(-1); /* Get command */ NETWORK_RECEIVE_INITIALIZE(received_tcp_packet.buf_index); cmd = RECEIVE_NETWORK_B(); cmd += RECEIVE_NETWORK_B(); cmd += RECEIVE_NETWORK_B(); switch(smtp_client.state) { case SMTP_CONNECTION_OPENED: if(cmd == SMTP_CMD_SERVER_READY) { DEBUGOUT("SMTP Server is ready\r\n"); smtpc_changestate(SMTP_SERVER_READY); return(1); } break; case SMTP_HELO_SENT: if(cmd == SMTP_CMD_OK) { DEBUGOUT("HELO acked by SMTP server\r\n"); smtpc_changestate(SMTP_HELO_ACKED); return(1); } break; case SMTP_MAILFROM_SENT: if(cmd == SMTP_CMD_OK) { DEBUGOUT("MAIL FROM Acked by SMTP server\r\n"); smtpc_changestate(SMTP_MAILFROM_ACKED); return(1); } break; case SMTP_RCPTTO_SENT: if(cmd == SMTP_CMD_OK) { DEBUGOUT("RCPT TO Acked by SMTP server\r\n"); smtpc_changestate(SMTP_RCPTTO_ACKED); return(1); } break; case SMTP_DATAREQ_SENT: if(cmd == SMTP_CMD_DATAOK) { DEBUGOUT("DATA Acked by SMTP Server\r\n"); smtpc_changestate(SMTP_DATAREQ_ACKED); return(1); } break; case SMTP_DATAEND_SENT: if(cmd == SMTP_CMD_OK) { DEBUGOUT("CRLF.CRLF Acked by SMTP Server\r\n"); smtpc_changestate(SMTP_DATAEND_ACKED); return(1); } break; case SMTP_QUIT_SENT: if(cmd == SMTP_CMD_QUITOK) { DEBUGOUT("QUIT Acked by SMTP Server\r\n"); smtpc_changestate(SMTP_QUIT_ACKED); return(1); } break; default: break; } return(1); case TCP_EVENT_REGENERATE: /* Send last packet again */ DEBUGOUT("SMTP is regenerating...\r\n"); switch (smtp_client.state) { case SMTP_HELO_SENT: smtpc_sendhelo(); return(1); case SMTP_MAILFROM_SENT: smtpc_sendmailfrom(); return(1); case SMTP_RCPTTO_SENT: smtpc_sendrcptto(); return(1); case SMTP_DATAREQ_SENT: smtpc_senddatareq(); return(1); case SMTP_BODY_SENT: smtpc_sendbody(); return(1); case SMTP_SENDING_DATA: smtpc_senddata(); return(1); case SMTP_DATAEND_SENT: smtpc_senddataend(); return(1); case SMTP_QUIT_SENT: smtpc_sendquit(); return(1); default: return(-1); } break; default: return(-1); } return(-1); }
/** \brief Process recieved ICMP datagram * \ingroup periodic_functions * \author * \li Jari Lahti ([email protected]) * \date 08.07.2002 * \param frame - pointer to received IP frame structure * \param len - length of the received IP datagram (in bytes) * \return * \li -1 - packet not OK (not proper ICMP or not ICMP at all) * \li >=0 - packet OK * * Invoke process_icmp_in whenever IP datagram containing ICMP message * is detected (see main_demo.c for example main loop implementing this). * * This function simply checks correctnes of received ICMP message and * send ICMP replies when requested. * */ INT16 process_icmp_in (struct ip_frame* frame, UINT16 len) { UINT8 type; UINT8 code; UINT16 checksum; UINT16 i; UINT16 j; UINT8 tbuf[16]; /* Is this ICMP? */ ICMP_DEBUGOUT("Processing ICMP...\n\r"); if( frame->protocol != IP_ICMP ) { ICMP_DEBUGOUT("ERROR: The protocol is not ICMP\n\r"); return(-1); } /* Calculate checksum for received packet */ checksum = 0; i = len; NETWORK_RECEIVE_INITIALIZE(frame->buf_index); while(i>15) { RECEIVE_NETWORK_BUF(tbuf, 16); checksum = (UINT16)ip_checksum_buf (checksum, tbuf, 16); i -= 16; } for(j=0; j < i; j++) checksum = ip_checksum(checksum, RECEIVE_NETWORK_B(), (UINT8)j); checksum = ~ checksum; if(checksum != IP_GOOD_CS) { ICMP_DEBUGOUT("ERROR: ICMP Checksum failed!\n\r"); return (-1); } ICMP_DEBUGOUT("ICMP Checksum OK\n\r"); /* Start processing the message */ NETWORK_RECEIVE_INITIALIZE(frame->buf_index); type = RECEIVE_NETWORK_B(); code = RECEIVE_NETWORK_B(); /* We have already checked the CS, skip it */ (void)RECEIVE_NETWORK_B(); (void)RECEIVE_NETWORK_B(); switch(type) { case ICMP_ECHO_REQUEST: if(code != 0) { ICMP_DEBUGOUT("ERROR:Misformed ICMP ECHO Request\n\r"); return(-1); } ICMP_DEBUGOUT("ICMP ECHO Request received\n\r"); /* Is it a packet for setting temporary IP? */ if(len == (ICMP_ECHOREQ_HLEN + ICMP_TEMPIPSET_DATALEN) ) { /* Yep, set temporary IP address */ ICMP_DEBUGOUT("PING with 102 bytes of data, getting temp. IP\r\n"); localmachine.localip = frame->dip; localmachine.defgw = frame->sip; localmachine.netmask = 0; } /* Same IP? */ if(localmachine.localip != frame->dip) return(-1); /* Reply it */ TXBUF[0] = ICMP_ECHO_REPLY; TXBUF[1] = 0; TXBUF[2] = 0; TXBUF[3] = 0; /* Copy with truncate if needed */ if(len > NETWORK_TX_BUFFER_SIZE) len = NETWORK_TX_BUFFER_SIZE; RECEIVE_NETWORK_BUF(&TXBUF[4], len); /* Calculate Checksum for packet to be sent */ checksum = 0; checksum = (UINT16)ip_checksum_buf(checksum, &TXBUF[0], len); checksum = ~ checksum; /* Put the checksum on place */ TXBUF[2] = (UINT8)(checksum>>8); TXBUF[3] = (UINT8)checksum; /* Send it */ (void)process_ip_out(frame->sip, IP_ICMP, 0, 100, &TXBUF[0], len); ICMP_DEBUGOUT("ICMP Reply sent\n\r"); return(0); break; case ICMP_ECHO_REPLY: break; default: /* Unrecognized ICMP message */ ICMP_DEBUGOUT("Unregognized ICMP message\n\r"); return(-1); } }