unsigned __int8 PrologEncoderMD::GetXmmRegToSave(IR::Instr *instr, unsigned __int16 *scaledOffset)
{
    Assert(scaledOffset);
    Assert(instr->m_opcode == Js::OpCode::MOVAPD || instr->m_opcode == Js::OpCode::MOVAPS);
    Assert(instr->GetDst() && instr->GetDst()->IsIndirOpnd());

    unsigned __int8 reg = ((instr->GetSrc1()->AsRegOpnd()->GetReg() - FIRST_XMM_REG) & 0xFF);
    unsigned __int32 offsetFromInstr = instr->GetDst()->AsIndirOpnd()->GetOffset();

    // The offset in the instruction is relative to the stack pointer before the saved reg size and stack args size were
    // subtracted, but the offset in the unwind info needs to be relative to the final stack pointer value
    // (see LowererMDArch::LowerEntryInstr), so adjust for that
    Assert(instr->GetDst()->AsIndirOpnd()->GetBaseOpnd()->GetReg() == LowererMDArch::GetRegStackPointer());
    Func *const topFunc = instr->m_func->GetTopFunc();
    offsetFromInstr += topFunc->GetArgsSize() + topFunc->GetSavedRegSize();

    // Can only encode nonnegative 16-byte-aligned offsets in the unwind info
    Assert(static_cast<int32>(offsetFromInstr) >= 0);
    Assert(::Math::Align(offsetFromInstr, static_cast<unsigned __int32>(MachDouble * 2)) == offsetFromInstr);

    // Stored offset is scaled by 16
    offsetFromInstr /= MachDouble * 2;

    // We currently don't allow a total stack size greater than 1 MB. If we start allowing that, we will need to handle offsets
    // greater than (1 MB - 16) in the unwind info as well, for which a FAR version of the op-code is necessary.
    Assert(IS_UINT16(offsetFromInstr));

    *scaledOffset = TO_UINT16(offsetFromInstr);

    return reg;
}
Exemple #2
0
/**
 * Handle Modbus requests
 * Checks for new TCP data and looks for new modbus messages
**/
void mb_handleRequest(void) {
	// read packet, handle ping and wait for a tcp packet
	uint16_t dat_p = packetloop_icmp_tcp(buf,enc28j60PacketReceive(BUFFER_SIZE, buf));
	
	// check if data was received
	if (dat_p == 0)
		return;

	// make structure pointer to buffer 
	modbusmsg_t* msg = (modbusmsg_t*)&buf[dat_p];

	// check for modbus protocol id
	if (FROM_UINT16(msg->mbap.protoId) > 0)
		return;

	uint16_t len;
	switch (msg->function) {
		// Modbus read function
		case MB_FUNC_READREG: {
			readreg_req_t* req = (readreg_req_t*)&(msg->function);
			readreg_res_t* res = (readreg_res_t*)&(msg->function);
			uint16_t amount = FROM_UINT16(req->amount);
			uint16_t addr = FROM_UINT16(req->start_address);
			
			if (amount == 0 || amount > 0x7D) {
				len = mb_set_error(msg,MB_ERR_DATA);
				break;
			}
			if (addr + amount <= MODBUS_REGISTER_COUNT) {
				uint16_t *ptr = (uint16_t*)&(res->function);
				uint16_t cnt = 0;
				for (; cnt < amount; cnt++) {
					if (registers[addr+cnt] == NULL) {
						len = mb_set_error(msg,MB_ERR_PROC);
						break;
					}
					++ptr;
					*ptr = TO_UINT16(*(registers[addr+cnt]));
				}
				// if an error occurred
				if (cnt < amount)
					break;
				
				res->bytecount = cnt*sizeof(uint16_t);
				len = sizeof(readreg_res_t)+cnt*sizeof(uint16_t);
			} else
				len = mb_set_error(msg,MB_ERR_ADDR);
			break;
			}
		// Modbus write function
		case MB_FUNC_WRITEREG: {
			writereg_req_t* req = (writereg_req_t*)&(msg->function);
			uint16_t addr = FROM_UINT16(req->start_address);
			uint16_t value = FROM_UINT16(req->value);
			
			if (addr >= MODBUS_REGISTER_COUNT || writecbs[addr] == NULL) {
				len = mb_set_error(msg,MB_ERR_ADDR);
				break;
			}
			if (writecbs[addr](addr,value))
				len = sizeof(writereg_req_t);
			else
				len = mb_set_error(msg,MB_ERR_PROC);
			break;
			}
		// Modbus device id function
		// Not implemented completely
		case MB_FUNC_DEV_ID: {
			devid_req_t* req = (devid_req_t*)&(msg->function);
			devid_res_t* res = (devid_res_t*)&(msg->function);
			devid_obj_t* obj = (devid_obj_t*)&(res->nextobjid);
			uint8_t i = req->objid;
			
			if (req->type != 0x0E) {
				len = mb_set_error(msg,MB_ERR_FUNC);
				break;
			}
			if (!req->code || req->code > 4) {
				len = mb_set_error(msg,MB_ERR_DATA);
				break;
			}
			res->conflevel = 0x01;
			res->more = 0x00;
			res->nextobjid = 0x00;
			res->amount = 3;
			len = sizeof(devid_res_t);
			if (i > 2)
				i = 0;
			// add requested objects
			for (; i < 3; i++) {
				++obj;
				obj->id = i;
				obj->length = 0;
				len += sizeof(devid_obj_t)+obj->length;
			}
			break;
			}
		default: // set error
			len = mb_set_error(msg,MB_ERR_FUNC);
			break;
	}
	msg->mbap.length = TO_UINT16(len+1);
	// send response
	www_server_reply(buf,sizeof(mbap_t)+len);
}
Exemple #3
0
/** Process a general service request message.
 *
 * @param[in] message - The message to process.
 * @param[out] sendbuf - The response buffer to fill.
 * @param[in] errorcode - The error code from the client request.
 *
 * @return Zero on success, or a non-zero SLP error on failure.
 *
 * @internal
 */
static int ProcessSrvRqst(SLPMessage * message, SLPBuffer * sendbuf, 
      int errorcode)
{
   int i;
   SLPUrlEntry * urlentry;
   SLPDDatabaseSrvRqstResult * db = 0;
   size_t size = 0;
   SLPBuffer result = *sendbuf;

#ifdef ENABLE_SLPv2_SECURITY
   SLPAuthBlock * authblock = 0;
   int j;
#endif

   /* If errorcode is set, we can not be sure that message is good
      Go directly to send response code 
    */
   if (errorcode)
      goto RESPOND;

   /* Check for one of our IP addresses in the prlist */
   if (SLPIntersectStringList(message->body.srvrqst.prlistlen, 
         message->body.srvrqst.prlist, G_SlpdProperty.interfacesLen,
         G_SlpdProperty.interfaces))
   {
      /* silently ignore */
      result->end = result->start;
      goto FINISHED;
   }

   /* Make sure that we handle at least verify registrations made with
      the requested SPI.  If we can't then have to return an error
      because there is no way we can return URL entries that are
      signed in a way the requester can understand
    */
#ifdef ENABLE_SLPv2_SECURITY
   if (G_SlpdProperty.securityEnabled)
   {
      if (SLPSpiCanVerify(G_SlpdSpiHandle, message->body.srvrqst.spistrlen,
            message->body.srvrqst.spistr) == 0)
      {
         errorcode = SLP_ERROR_AUTHENTICATION_UNKNOWN;
         goto RESPOND;
      }
   }
   else if (message->body.srvrqst.spistrlen)
   {
      errorcode = SLP_ERROR_AUTHENTICATION_UNKNOWN;
      goto RESPOND;
   }
#else
   if (message->body.srvrqst.spistrlen)
   {
      errorcode = SLP_ERROR_AUTHENTICATION_UNKNOWN;
      goto RESPOND;
   }
#endif

   /* check to to see if a this is a special SrvRqst */
   if (SLPCompareString(message->body.srvrqst.srvtypelen, 
         message->body.srvrqst.srvtype, 23, SLP_DA_SERVICE_TYPE) == 0)
   {
      errorcode = ProcessDASrvRqst(message, sendbuf, errorcode);
      if (errorcode == 0)
      {
         /* Since we have an errorcode of 0, we were successful,
            and have already formed a response packet; return now.
          */
         return errorcode;
      }
      goto RESPOND;
   }
   if (SLPCompareString(message->body.srvrqst.srvtypelen, 
         message->body.srvrqst.srvtype, 21, SLP_SA_SERVICE_TYPE) == 0)
   {
      errorcode = ProcessSASrvRqst(message, sendbuf, errorcode);
      if (errorcode == 0)
      {
         /* Since we have an errorcode of 0, we were successful,
            and have already formed a response packet; return now.
          */
         return errorcode;
      }
      goto RESPOND;
   }

   /* make sure that we handle the scope */
   if (SLPIntersectStringList(message->body.srvrqst.scopelistlen, 
         message->body.srvrqst.scopelist, G_SlpdProperty.useScopesLen,
         G_SlpdProperty.useScopes) != 0)
      errorcode = SLPDDatabaseSrvRqstStart(message, &db);
   else
      errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;

RESPOND:

   /* do not send error codes or empty replies to multicast requests */
   if (errorcode != 0 || db->urlcount == 0)
   {
      if (message->header.flags & SLP_FLAG_MCAST 
            || SLPNetIsMCast(&(message->peer)))
      {
         result->end = result->start;
         goto FINISHED;  
      }
   }

   /* ensure the buffer is big enough to handle the whole srvrply */
   size = message->header.langtaglen + 18;/* 14 bytes for header     */
                                          /*  2 bytes for error code */
                                          /*  2 bytes for url count  */
   if (errorcode == 0)
   {
      for (i = 0; i < db->urlcount; i++)
      {
         /* urlentry is the url from the db result */
         urlentry = db->urlarray[i];

         size += urlentry->urllen + 6; /*  1 byte for reserved  */
                                       /*  2 bytes for lifetime */
                                       /*  2 bytes for urllen   */
                                       /*  1 byte for authcount */
#ifdef ENABLE_SLPv2_SECURITY
         /* make room to include the authblock that was asked for */
         if (G_SlpdProperty.securityEnabled 
               && message->body.srvrqst.spistrlen)
         {
            for (j = 0; j < urlentry->authcount; j++)
            {
               if (SLPCompareString(urlentry->autharray[j].spistrlen,
                     urlentry->autharray[j].spistr,
                     message->body.srvrqst.spistrlen,
                     message->body.srvrqst.spistr) == 0)
               {
                  authblock = &(urlentry->autharray[j]);
                  size += authblock->length;
                  break;
               }
            }
         }
#endif 
      }
   }

   /* reallocate the result buffer */
   result = SLPBufferRealloc(result, size);
   if (result == 0)
   {
      errorcode = SLP_ERROR_INTERNAL_ERROR;
      goto FINISHED;
   }

   /* add the header */

   /* version */
   *result->curpos++ = 2;

   /* function id */
   *result->curpos++ = SLP_FUNCT_SRVRPLY;

   /* length */
   PutUINT24(&result->curpos, size);

   /* flags */
   PutUINT16(&result->curpos, (size > (size_t)G_SlpdProperty.MTU? 
         SLP_FLAG_OVERFLOW: 0));

   /* ext offset */
   PutUINT24(&result->curpos, 0);

   /* xid */
   PutUINT16(&result->curpos, message->header.xid);

   /* lang tag len */
   PutUINT16(&result->curpos, message->header.langtaglen);

   /* lang tag */
   memcpy(result->curpos, message->header.langtag,
         message->header.langtaglen);
   result->curpos += message->header.langtaglen;

   /* add rest of the SrvRply */

   /* error code*/
   PutUINT16(&result->curpos, errorcode);
   if (errorcode == 0)
   {
      /* urlentry count */
      PutUINT16(&result->curpos, db->urlcount);
      for (i = 0; i < db->urlcount; i++)
      {
         /* urlentry is the url from the db result */
         urlentry = db->urlarray[i]; 

#ifdef ENABLE_SLPv1
         if (urlentry->opaque == 0)
         {
            /* url-entry reserved */
            *result->curpos++ = 0;        

            /* url-entry lifetime */
            PutUINT16(&result->curpos, urlentry->lifetime);

            /* url-entry urllen */
            PutUINT16(&result->curpos, urlentry->urllen);

            /* url-entry url */
            memcpy(result->curpos, urlentry->url, urlentry->urllen);
            result->curpos += urlentry->urllen;

            /* url-entry auths */
            *result->curpos++ = 0;
         }
         else
#endif
         {
            /* Use an opaque copy if available (and authentication is 
             * not being used).
             */

            /* TRICKY: Fix up the lifetime. */
            TO_UINT16(urlentry->opaque + 1, urlentry->lifetime);
            memcpy(result->curpos, urlentry->opaque, urlentry->opaquelen);
            result->curpos += urlentry->opaquelen;
         }
      }
   }
   else
      PutUINT16(&result->curpos, 0); /* set urlentry count to 0*/

FINISHED:   

   if (db) 
      SLPDDatabaseSrvRqstEnd(db);

   *sendbuf = result;

   return errorcode;
}
Exemple #4
0
/** Process a DA service request message.
 *
 * @param[in] message - The message to process.
 * @param[out] sendbuf - The response buffer to fill.
 * @param[in] errorcode - The error code from the client request.
 *
 * @return Zero on success, or a non-zero SLP error on failure.
 *
 * @internal
 */
static int ProcessDASrvRqst(SLPMessage * message, SLPBuffer * sendbuf, int errorcode)
{
   SLPBuffer tmp = 0;
   SLPMessage * msg = 0;
   void * eh = 0;
   /* TODO should really be a configurable property, maybe G_SlpdProperty.MTU? Left at 4096 to retain same behaviour */
   size_t initial_buffer_size = 4096;
   size_t grow_size = initial_buffer_size;

   /* Special case for when libslp asks slpd (through the loopback) about
      a known DAs. Fill sendbuf with DAAdverts from all known DAs.        
    */
   if (SLPNetIsLoopback(&message->peer))
   {
      *sendbuf = SLPBufferRealloc(*sendbuf, initial_buffer_size);
      if (*sendbuf == 0)
         return SLP_ERROR_INTERNAL_ERROR;

      if (errorcode == 0)
      {
         /* Note: The weird *sendbuf code is making a single SLPBuffer
            that contains multiple DAAdverts.  This is a special
            process that only happens for the DA SrvRqst through
            loopback to the SLPAPI
          */

         /*If we are a DA, always have ourself at the start of the list, so the
           lib requests can be handled locally for speed */
         if(G_SlpdProperty.isDA)
         {
            struct sockaddr_storage loaddr;

            if(SLPNetIsIPV4())
            {
               int addr = INADDR_LOOPBACK;
               SLPNetSetAddr(&loaddr, AF_INET, G_SlpdProperty.port, &addr);
            }
            else
			{
               SLPNetSetAddr(&loaddr, AF_INET6, G_SlpdProperty.port, &slp_in6addr_loopback);
			}

            if(0 == SLPDKnownDAGenerateMyDAAdvert(&loaddr, 0, 0, 0, message->header.xid, &tmp))
            {
               memcpy((*sendbuf)->curpos, tmp->start, tmp->end - tmp->start);
               (*sendbuf)->curpos = ((*sendbuf)->curpos) + (tmp->end - tmp->start);
               SLPBufferFree(tmp);
               tmp = 0;
            }
			else 
			{
				SLPDLog("Unable to add initial DAAdvert due to error\n");
			}
         }

         eh = SLPDKnownDAEnumStart();
         if (eh)
         {
            while (1)
            {
               /* iterate over all database entries */
               if (SLPDKnownDAEnum(eh, &msg, &tmp) == 0) 
			   {
                  break;
			   }

               /* if we resize succesfully.. */
               if( CheckAndResizeBuffer(sendbuf, tmp, grow_size) == 0 )
               {
            	   /* buffer should now be resized to an appropriate size to handle all current database entries */

                   /* TRICKY: Fix up the XID and clear the flags. */
                   tmp->curpos = tmp->start + 10;
                   TO_UINT16(tmp->curpos, message->header.xid);
                   if (*(tmp->start) == 1)
                       *(tmp->start + 4) = 0;
                   else
                       TO_UINT16(tmp->start + 5, 0);   

    			   /* copy all data out of tmp into the sendbuf */
                   memcpy((*sendbuf)->curpos, tmp->start, tmp->end - tmp->start);
    			   /* increment the current position in sendbuf */
                   (*sendbuf)->curpos = ((*sendbuf)->curpos) + (tmp->end - tmp->start);
               }
               else
               {
            	   errorcode = SLP_ERROR_INTERNAL_ERROR;
               }
            }
            SLPDKnownDAEnumEnd(eh);
         }
 		/* tmp can store database entries which should not be freed by anyone else so reset the pointer to prevent double deletion */
 		tmp = 0;

 		/* Tack on a "terminator" DAAdvert
 		   Note that this function *always* returns the error code passed as its second parameter (or SLP_ERROR_INTERNAL_ERROR if the buffer fails to resize)
 		   The errorcode is also inserted into the srvrply header by this function
 		*/
 		SLPDKnownDAGenerateMyDAAdvert(&message->localaddr, SLP_ERROR_INTERNAL_ERROR, 0, 0, message->header.xid, &tmp);

 		/* if we resize succesfully.. */
        if ( CheckAndResizeBuffer(sendbuf, tmp, grow_size) == 0 )
        {
     		memcpy((*sendbuf)->curpos, tmp->start, tmp->end - tmp->start);
     		(*sendbuf)->curpos = ((*sendbuf)->curpos) + (tmp->end - tmp->start);

     		/* mark the end of the sendbuf */
     		(*sendbuf)->end = (*sendbuf)->curpos;

        }
        else
        {
     	   errorcode = SLP_ERROR_INTERNAL_ERROR;
        }

        SLPBufferFree(tmp);
 		tmp = 0;
      }
      return errorcode;
   }
   
   /* Normal case where a remote Agent asks for a DA */

   *sendbuf = SLPBufferRealloc(*sendbuf, G_SlpdProperty.MTU);
   if (*sendbuf == 0)
      return SLP_ERROR_INTERNAL_ERROR;
   if (G_SlpdProperty.isDA)
   {
      if (message->body.srvrqst.scopelistlen == 0 
            || SLPIntersectStringList(message->body.srvrqst.scopelistlen,
                  message->body.srvrqst.scopelist, G_SlpdProperty.useScopesLen,
                  G_SlpdProperty.useScopes))
      {
         errorcode = SLPDKnownDAGenerateMyDAAdvert(&message->localaddr, 
               errorcode, 0, 0, message->header.xid, sendbuf);           
      }
      else
         errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
   }
   else
      errorcode = SLP_ERROR_MESSAGE_NOT_SUPPORTED;       

   /* don't return errorcodes to multicast messages */
   if (errorcode != 0)
   {
      if (message->header.flags & SLP_FLAG_MCAST 
            || SLPNetIsMCast(&(message->peer)))
         (*sendbuf)->end = (*sendbuf)->start;
   }
   return errorcode;
}