/*=========================================================================*/ void SLPDKnownDARegister(SLPDPeerInfo* peerinfo, SLPMessage msg, SLPBuffer buf) /* Echo a message to a known DA */ /* */ /* peerinfo (IN) the peer that the registration came from */ /* */ /* msg (IN) the translated message to echo */ /* */ /* buf (IN) the message buffer to echo */ /* */ /* Returns: Zero on success, non-zero on error */ /*=========================================================================*/ { SLPDAEntry* daentry; SLPDSocket* sock; SLPBuffer dup; daentry = (SLPDAEntry*)G_KnownDAList.head; while (daentry) { sock = (SLPDSocket*)G_OutgoingSocketList.head; while (sock) { if (sock->peerinfo.peeraddr.sin_addr.s_addr == daentry->daaddr.s_addr) { break; } sock = (SLPDSocket*)sock->listitem.next; } if (sock == 0) { /* Create a new socket to the known DA */ sock = SLPDSocketCreateConnected(&(daentry->daaddr)); if (sock) { sock->daentry = daentry; SLPListLinkTail(&G_OutgoingSocketList,(SLPListItem*)sock); } } /* Load the socket with the message to send */ dup = SLPBufferDup(buf); if (dup) { if (sock->state == STREAM_CONNECT_IDLE) { sock->state = STREAM_WRITE_FIRST; } SLPListLinkTail(&(sock->sendlist),(SLPListItem*)dup); } daentry = (SLPDAEntry*)daentry->listitem.next; } }
int CheckAndResizeBuffer(SLPBuffer * sendbuf, SLPBuffer tmp, size_t grow_size) { int retVal = 0; if( (*sendbuf)->curpos + (tmp->end - tmp->start) > ( (*sendbuf)->start + (*sendbuf)->allocated) ) { /* Grow the sendbuf buffer - note that SLPBufferRealloc may potentially do a memset if the DEBUG flag is set Therefore we have to copy the old contents into the buffer afterwards to be sure */ #ifdef DEBUG SLPBuffer duplicate = SLPBufferDup( (*sendbuf) ); #endif /* store how far we are from the start of the buffer */ size_t currentPosFromStart = (*sendbuf)->curpos - (*sendbuf)->start; /* check to make sure we're growing by at least the size of the tmp buffer */ *sendbuf = SLPBufferRealloc( (*sendbuf), ((*sendbuf)->allocated + ((size_t)(tmp->end - tmp->start) > grow_size?(tmp->end - tmp->start):grow_size)) ); if (*sendbuf == 0) { retVal = SLP_ERROR_INTERNAL_ERROR; } else { /* update the current position to what it was before */ (*sendbuf)->curpos = (*sendbuf)->start + currentPosFromStart; #ifdef DEBUG memcpy( (*sendbuf)->start, duplicate->start, duplicate->end - duplicate->start ); #endif } #ifdef DEBUG SLPBufferFree(duplicate); duplicate = 0; #endif } return retVal; }
/*-------------------------------------------------------------------------*/ SLPBoolean KnownDADiscoveryCallback(SLPError errorcode, struct sockaddr_in* peerinfo, SLPBuffer rplybuf, void* cookie) /*-------------------------------------------------------------------------*/ { SLPMessage replymsg; SLPBuffer dupbuf; struct hostent* he; SLPSrvURL* srvurl; int* count; SLPBoolean result = SLP_TRUE; count = (int*)cookie; if(errorcode == 0) { dupbuf = SLPBufferDup(rplybuf); if(dupbuf) { replymsg = SLPMessageAlloc(); if(replymsg) { if(SLPMessageParseBuffer(peerinfo,dupbuf,replymsg) == 0 && replymsg->header.functionid == SLP_FUNCT_DAADVERT) { if(replymsg->body.daadvert.errorcode == 0) { /* TRICKY: NULL terminate the DA url */ ((char*)(replymsg->body.daadvert.url))[replymsg->body.daadvert.urllen] = 0; if(SLPParseSrvURL(replymsg->body.daadvert.url, &srvurl) == 0) { he = gethostbyname(srvurl->s_pcHost); SLPFree(srvurl); if(he) { /* Reset the peer to the one in the URL */ replymsg->peer.sin_addr.s_addr = *((unsigned int*)(he->h_addr_list[0])); (*count) += 1; KnownDAAdd(replymsg,dupbuf); if(replymsg->header.flags & SLP_FLAG_MCAST) { return SLP_FALSE; } return SLP_TRUE; } } } else if(replymsg->body.daadvert.errorcode == SLP_ERROR_INTERNAL_ERROR) { /* SLP_ERROR_INTERNAL_ERROR is a "end of stream" */ /* marker for looppack IPC */ result = SLP_FALSE; } } SLPMessageFree(replymsg); } SLPBufferFree(dupbuf); } } return result; }
/** Processes the recvbuf and places the results in sendbuf * * @param[in] peerinfo - The remote address the message was received from. * @param[in] localaddr - The local address the message was received on. * @param[in] recvbuf - The message to process. * @param[out] sendbuf - The address of storage for the results of the * processed message. * @param[out] sendlist - if non-0, this function will prune the message * with the processed xid from the sendlist. * * @return Zero on success if @p sendbuf contains a response to send, * or a non-zero value if @p sendbuf does not contain a response * to send. */ int SLPDProcessMessage(struct sockaddr_storage * peerinfo, struct sockaddr_storage * localaddr, SLPBuffer recvbuf, SLPBuffer * sendbuf, SLPList * psendlist) { SLPHeader header; SLPMessage * message = 0; int errorcode = 0; #ifdef DEBUG char addr_str[INET6_ADDRSTRLEN]; #endif SLPDLogMessage(SLPDLOG_TRACEMSG_IN, peerinfo, localaddr, recvbuf); /* set the sendbuf empty */ if (*sendbuf) (*sendbuf)->end = (*sendbuf)->start; /* zero out the header before parsing it */ memset(&header, 0, sizeof(header)); /* Parse just the message header */ recvbuf->curpos = recvbuf->start; errorcode = SLPMessageParseHeader(recvbuf, &header); /* Reset the buffer "curpos" pointer so that full message can be parsed later */ recvbuf->curpos = recvbuf->start; #if defined(ENABLE_SLPv1) /* if version == 1 and the header was correct then parse message as a version 1 message */ if ((errorcode == 0) && (header.version == 1)) errorcode = SLPDv1ProcessMessage(peerinfo, recvbuf, sendbuf); else #endif if (errorcode == 0) { /* TRICKY: Duplicate SRVREG recvbufs *before* parsing them * we do this because we are going to keep track of in the * registration database. */ if (header.functionid == SLP_FUNCT_SRVREG || header.functionid == SLP_FUNCT_DAADVERT) { recvbuf = SLPBufferDup(recvbuf); if (recvbuf == 0) return SLP_ERROR_INTERNAL_ERROR; } /* Allocate the message descriptor */ message = SLPMessageAlloc(); if (message) { /* Parse the message and fill out the message descriptor */ errorcode = SLPMessageParseBuffer(peerinfo, localaddr, recvbuf, message); if (errorcode == 0) { /* Process messages based on type */ switch (message->header.functionid) { case SLP_FUNCT_SRVRQST: errorcode = ProcessSrvRqst(message, sendbuf, errorcode); break; case SLP_FUNCT_SRVREG: errorcode = ProcessSrvReg(message, recvbuf, sendbuf, errorcode); if (errorcode == 0) SLPDKnownDAEcho(message, recvbuf); break; case SLP_FUNCT_SRVDEREG: errorcode = ProcessSrvDeReg(message, sendbuf, errorcode); if (errorcode == 0) SLPDKnownDAEcho(message, recvbuf); break; case SLP_FUNCT_SRVACK: errorcode = ProcessSrvAck(message, sendbuf, errorcode); break; case SLP_FUNCT_ATTRRQST: errorcode = ProcessAttrRqst(message, sendbuf, errorcode); break; case SLP_FUNCT_DAADVERT: errorcode = ProcessDAAdvert(message, recvbuf, sendbuf, errorcode); break; case SLP_FUNCT_SRVTYPERQST: errorcode = ProcessSrvTypeRqst(message, sendbuf, errorcode); break; case SLP_FUNCT_SAADVERT: errorcode = ProcessSAAdvert(message, sendbuf, errorcode); break; default: /* Should never happen... but we're paranoid */ errorcode = SLP_ERROR_PARSE_ERROR; break; } } else SLPDLogParseWarning(peerinfo, recvbuf); /*If there was a send list, prune the xid, since the request has been processed*/ if(psendlist) { SLPHeader bufhead; SLPBuffer pnext; SLPBuffer pbuf = (SLPBuffer) psendlist->head; while(pbuf) { pnext = (SLPBuffer) pbuf->listitem.next; if((0 == SLPMessageParseHeader(pbuf, &bufhead)) && (bufhead.xid == header.xid)) SLPBufferFree((SLPBuffer)SLPListUnlink(psendlist, (SLPListItem*)pbuf)); else pbuf->curpos = pbuf->start; /*We parsed the buffer enough to attempt the xid check, we need to reset it for the next parse*/ pbuf = pnext; } } if (header.functionid == SLP_FUNCT_SRVREG || header.functionid == SLP_FUNCT_DAADVERT) { /* TRICKY: If this is a reg or daadvert message we do not free * the message descriptor or duplicated recvbuf because they are * being kept in the database! */ if (errorcode == 0) goto FINISHED; /* TRICKY: If there is an error we need to free the * duplicated recvbuf */ SLPBufferFree(recvbuf); } SLPMessageFree(message); } else errorcode = SLP_ERROR_INTERNAL_ERROR; /* out of memory */ } else SLPDLogParseWarning(peerinfo,recvbuf); FINISHED: #ifdef DEBUG if (errorcode) SLPDLog("\n*** DEBUG *** errorcode %i during processing " "of message from %s\n", errorcode, SLPNetSockAddrStorageToString( peerinfo, addr_str, sizeof(addr_str))); #endif /* Log message silently ignored because of an error */ if (errorcode) if (*sendbuf == 0 || (*sendbuf)->end == (*sendbuf)->start) SLPDLogMessage(SLPDLOG_TRACEDROP,peerinfo,localaddr,recvbuf); /* Log trace message */ SLPDLogMessage(SLPDLOG_TRACEMSG_OUT, peerinfo, localaddr, *sendbuf); return errorcode; }
/*=========================================================================*/ int SLPDv1ProcessMessage(struct sockaddr_in* peeraddr, SLPBuffer recvbuf, SLPBuffer* sendbuf) /* Processes the SLPv1 message and places the results in sendbuf */ /* */ /* peeraddr - the socket the message was received on */ /* */ /* recvbuf - message to process */ /* */ /* sendbuf - results of the processed message */ /* */ /* Returns - zero on success SLP_ERROR_PARSE_ERROR or */ /* SLP_ERROR_INTERNAL_ERROR on ENOMEM. */ /*=========================================================================*/ { SLPHeader header; SLPMessage message; int errorcode = 0; if (!G_SlpdProperty.isDA) { /* SLPv1 messages are handled only by DAs */ errorcode = SLP_ERROR_VER_NOT_SUPPORTED; } /* Parse just the message header the reset the buffer "curpos" pointer */ recvbuf->curpos = recvbuf->start; errorcode = SLPv1MessageParseHeader(recvbuf, &header); /* TRICKY: Duplicate SRVREG recvbufs *before* parsing them */ /* it because we are going to keep them in the */ if (header.functionid == SLP_FUNCT_SRVREG) { recvbuf = SLPBufferDup(recvbuf); if (recvbuf == NULL) { return SLP_ERROR_INTERNAL_ERROR; } } /* Allocate the message descriptor */ message = SLPMessageAlloc(); if (message) { /* Parse the message and fill out the message descriptor */ errorcode = SLPv1MessageParseBuffer(peeraddr,recvbuf, message); if (errorcode == 0) { /* Process messages based on type */ switch (message->header.functionid) { case SLP_FUNCT_SRVRQST: errorcode = v1ProcessSrvRqst(peeraddr, message, sendbuf, errorcode); break; case SLP_FUNCT_SRVREG: errorcode = v1ProcessSrvReg(peeraddr, message, recvbuf, sendbuf, errorcode); if (errorcode == 0) { SLPDKnownDAEcho(message, recvbuf); } break; case SLP_FUNCT_SRVDEREG: errorcode = v1ProcessSrvDeReg(peeraddr, message, sendbuf, errorcode); if (errorcode == 0) { SLPDKnownDAEcho(message, recvbuf); } break; case SLP_FUNCT_ATTRRQST: errorcode = v1ProcessAttrRqst(peeraddr, message, sendbuf, errorcode); break; case SLP_FUNCT_SRVTYPERQST: errorcode = v1ProcessSrvTypeRqst(peeraddr, message, sendbuf, errorcode); break; case SLP_FUNCT_DAADVERT: /* we are a SLPv2 DA, ignore other v1 DAs */ (*sendbuf)->end = (*sendbuf)->start; break; default: /* Should never happen... but we're paranoid */ errorcode = SLP_ERROR_PARSE_ERROR; break; } } if (header.functionid == SLP_FUNCT_SRVREG) { /* TRICKY: Do not free the message descriptor for SRVREGs */ /* because we are keeping them in the database */ /* unless there is an error then we free memory */ if (errorcode) { SLPMessageFree(message); SLPBufferFree(recvbuf); } } else { SLPMessageFree(message); } } else { /* out of memory */ errorcode = SLP_ERROR_INTERNAL_ERROR; } return errorcode; }