/*=========================================================================*/ void SLPDLogMessage(int msglogflags, struct sockaddr_in* peerinfo, SLPBuffer buf) /* Log record of receiving or sending an SLP Message. Logging will only */ /* occur if message logging is enabled G_SlpProperty.traceMsg != 0 */ /* */ /* msglogflags (IN) What type of message to log */ /* */ /* peerinfo (IN) the source or destination peer */ /* */ /* msg (IN) the message to log */ /* */ /* Returns: none */ /*=========================================================================*/ { SLPMessage msg; if (peerinfo == NULL || buf == NULL) { return; } if ((G_SlpdProperty.traceMsg && (msglogflags & SLPDLOG_TRACEMSG)) || (G_SlpdProperty.traceDrop && (msglogflags & SLPDLOG_TRACEDROP)) ) { /* Don't log localhost traffic since it is probably IPC */ /* and don't log empty messages */ if (!ISLOCAL(peerinfo->sin_addr) && buf->end != buf->start) { msg = SLPMessageAlloc(); if (msg) { SLPDLog("\n"); SLPDLogTime(); SLPDLog("MESSAGE - "); if (msglogflags == SLPDLOG_TRACEMSG_OUT) { SLPDLog("Trace message (OUT)\n"); } else if (msglogflags == SLPDLOG_TRACEMSG_IN) { SLPDLog("Trace message (IN)\n"); } else if (msglogflags == SLPDLOG_TRACEDROP) { SLPDLog("Dropped message (following message silently ignored)\n"); } else { SLPDLog("\n"); } if (SLPMessageParseBuffer(peerinfo,buf,msg) == 0) { SLPDLogMessageInternals(msg); } else { SLPDLog("Message parsing failed\n"); SLPDLog("Peer: \n"); SLPDLog(" IP address: %s\n", inet_ntoa(msg->peer.sin_addr)); } SLPMessageFree(msg); } } } }
/*-------------------------------------------------------------------------*/ int ProcessSrvReg(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /* */ /* Returns: non-zero if message should be silently dropped */ /*-------------------------------------------------------------------------*/ { unsigned int regtype; SLPBuffer result = *sendbuf; /*--------------------------------------------------------------*/ /* If errorcode is set, we can not be sure that message is good */ /* Go directly to send response code also do not process mcast */ /* srvreg or srvdereg messages */ /*--------------------------------------------------------------*/ if(errorcode || message->header.flags & SLP_FLAG_MCAST) { goto RESPOND; } /*------------------------------------*/ /* Make sure that we handle the scope */ /*------ -----------------------------*/ if(SLPIntersectStringList(message->body.srvreg.scopelistlen, message->body.srvreg.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes)) { /*-------------------------------*/ /* TODO: Validate the authblocks */ /*-------------------------------*/ /*---------------------------------*/ /* put the service in the database */ /*---------------------------------*/ regtype = 0; if(message->header.flags & SLP_FLAG_FRESH) { regtype |= SLPDDATABASE_REG_FRESH; } if(ISLOCAL(peeraddr->sin_addr)) { regtype |= SLPDDATABASE_REG_LOCAL; } errorcode = SLPDDatabaseReg(&(message->body.srvreg),regtype); if(errorcode > 0) { errorcode = SLP_ERROR_INVALID_REGISTRATION; } else if(errorcode < 0) { errorcode = SLP_ERROR_INTERNAL_ERROR; } } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } RESPOND: /*--------------------------------------------------------------------*/ /* don't send back reply anything multicast SrvReg (set result empty) */ /*--------------------------------------------------------------------*/ if(message->header.flags & SLP_FLAG_MCAST || ISMCAST(peeraddr->sin_addr)) { result->end = result->start; goto FINISHED; } /*------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvack */ /*------------------------------------------------------------*/ result = SLPBufferRealloc(result,message->header.langtaglen + 16); if(result == 0) { errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 2; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVACK; /*length*/ ToUINT24(result->start + 2,message->header.langtaglen + 16); /*flags*/ ToUINT16(result->start + 5,0); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ ToUINT16(result->start + 10,message->header.xid); /*lang tag len*/ ToUINT16(result->start + 12,message->header.langtaglen); /*lang tag*/ memcpy(result->start + 14, message->header.langtag, message->header.langtaglen); /*-------------------*/ /* Add the errorcode */ /*-------------------*/ ToUINT16(result->start + 14 + message->header.langtaglen, errorcode); FINISHED: *sendbuf = result; return errorcode; }
/*-------------------------------------------------------------------------*/ int v1ProcessSrvReg(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer recvbuf, SLPBuffer* sendbuf, int errorcode) /* */ /* Returns: non-zero if message should be silently dropped */ /*-------------------------------------------------------------------------*/ { SLPBuffer result = *sendbuf; /*--------------------------------------------------------------*/ /* If errorcode is set, we can not be sure that message is good */ /* Go directly to send response code also do not process mcast */ /* srvreg or srvdereg messages */ /*--------------------------------------------------------------*/ if (errorcode || message->header.flags & SLP_FLAG_MCAST) { goto RESPOND; } /*------------------------------------*/ /* Make sure that we handle the scope */ /*------ -----------------------------*/ if (SLPIntersectStringList(message->body.srvreg.scopelistlen, message->body.srvreg.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes)) { /*---------------------------------*/ /* put the service in the database */ /*---------------------------------*/ if (ISLOCAL(message->peer.sin_addr)) { message->body.srvreg.source= SLP_REG_SOURCE_LOCAL; } else { message->body.srvreg.source = SLP_REG_SOURCE_REMOTE; } errorcode = SLPDDatabaseReg(message,recvbuf); } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } RESPOND: /*--------------------------------------------------------------------*/ /* don't send back reply anything multicast SrvReg (set result empty) */ /*--------------------------------------------------------------------*/ if (message->header.flags & SLP_FLAG_MCAST) { result->end = result->start; goto FINISHED; } /*------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole srvack */ /*------------------------------------------------------------*/ result = SLPBufferRealloc(result, 14); if (result == 0) { errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 1; /*function id*/ *(result->start + 1) = SLP_FUNCT_SRVACK; /*length*/ ToUINT16(result->start + 2, 14); /*flags - TODO set the flags correctly */ *(result->start + 4) = 0; /*dialect*/ *(result->start + 5) = 0; /*language code*/ memcpy(result->start + 6, message->header.langtag, 2); ToUINT16(result->start + 8, message->header.encoding); /*xid*/ ToUINT16(result->start + 10, message->header.xid); /*-------------------*/ /* Add the errorcode */ /*-------------------*/ ToUINT16(result->start + 12, errorcode); FINISHED: *sendbuf = result; return errorcode; }
/*-------------------------------------------------------------------------*/ int ProcessDASrvRqst(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /*-------------------------------------------------------------------------*/ { SLPDAEntry daentry; SLPBuffer tmp = 0; SLPDAEntry* entry = 0; void* i = 0; /* set up local data */ memset(&daentry,0,sizeof(daentry)); /*---------------------------------------------------------------------*/ /* Special case for when libslp asks slpd (through the loopback) about */ /* a known DAs. Fill sendbuf with DAAdverts from all known DAs. */ /*---------------------------------------------------------------------*/ if(ISLOCAL(peeraddr->sin_addr)) { /* TODO: be smarter about how much memory is allocated here! */ /* 4096 may not be big enough to handle all DAAdverts */ *sendbuf = SLPBufferRealloc(*sendbuf, 4096); 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 */ while(SLPDKnownDAEnum(&i,&entry) == 0) { if(SLPDKnownDAEntryToDAAdvert(errorcode, message->header.xid, entry, &tmp) == 0) { if(((*sendbuf)->curpos) + (tmp->end - tmp->start) > (*sendbuf)->end) { break; } memcpy((*sendbuf)->curpos, tmp->start, tmp->end - tmp->start); (*sendbuf)->curpos = ((*sendbuf)->curpos) + (tmp->end - tmp->start); } } /* Tack on a "terminator" DAAdvert */ SLPDKnownDAEntryToDAAdvert(SLP_ERROR_INTERNAL_ERROR, message->header.xid, &daentry, &tmp); if(((*sendbuf)->curpos) + (tmp->end - tmp->start) <= (*sendbuf)->end) { 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; if(tmp) { SLPBufferFree(tmp); } } return errorcode; } /*---------------------------------------------------------------------*/ /* Normal case where a remote Agent asks for a DA */ /*---------------------------------------------------------------------*/ 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)) { /* fill out real structure */ G_SlpdProperty.DATimestamp += 1; daentry.bootstamp = G_SlpdProperty.DATimestamp; daentry.langtaglen = G_SlpdProperty.localeLen; daentry.langtag = (char*)G_SlpdProperty.locale; daentry.urllen = G_SlpdProperty.myUrlLen; daentry.url = (char*)G_SlpdProperty.myUrl; daentry.scopelistlen = G_SlpdProperty.useScopesLen; daentry.scopelist = (char*)G_SlpdProperty.useScopes; daentry.attrlistlen = 0; daentry.attrlist = 0; daentry.spilistlen = 0; daentry.spilist = 0; } 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 || ISMCAST(peeraddr->sin_addr)) { (*sendbuf)->end = (*sendbuf)->start; return errorcode; } } errorcode = SLPDKnownDAEntryToDAAdvert(errorcode, message->header.xid, &daentry, sendbuf); return errorcode; }
/*=========================================================================*/ int SLPDDatabaseReg(SLPMessage msg, SLPBuffer buf) /* Add a service registration to the database */ /* */ /* msg (IN) SLPMessage of a SrvReg message as returned by */ /* SLPMessageParse() */ /* */ /* buf (IN) Otherwise unreferenced buffer interpreted by the msg */ /* structure */ /* */ /* Returns - Zero on success. Nonzero on error */ /* */ /* NOTE: All registrations are treated as fresh */ /*=========================================================================*/ { SLPDatabaseHandle dh; SLPDatabaseEntry* entry; SLPSrvReg* entryreg; SLPSrvReg* reg; int result; /* reg is the SrvReg message being registered */ reg = &(msg->body.srvreg); /* check service-url syntax */ if ( SLPCheckServiceUrlSyntax(reg->urlentry.url, reg->urlentry.urllen) ) { return SLP_ERROR_INVALID_REGISTRATION; } /* check attr-list syntax */ if ( reg->attrlistlen && SLPCheckAttributeListSyntax(reg->attrlist,reg->attrlistlen) ) { return SLP_ERROR_INVALID_REGISTRATION; } dh = SLPDatabaseOpen(&G_SlpdDatabase.database); if ( dh ) { /*-----------------------------------------------------*/ /* Check to see if there is already an identical entry */ /*-----------------------------------------------------*/ while ( 1 ) { entry = SLPDatabaseEnum(dh); if ( entry == NULL ) break; /* entry reg is the SrvReg message from the database */ entryreg = &(entry->msg->body.srvreg); if ( SLPCompareString(entryreg->urlentry.urllen, entryreg->urlentry.url, reg->urlentry.urllen, reg->urlentry.url) == 0 ) { if ( SLPIntersectStringList(entryreg->scopelistlen, entryreg->scopelist, reg->scopelistlen, reg->scopelist) > 0 ) { /* Check to ensure the source addr is the same */ /* as the original */ if ( G_SlpdProperty.checkSourceAddr && memcmp(&(entry->msg->peer.sin_addr), &(msg->peer.sin_addr), sizeof(struct in_addr)) ) { SLPDatabaseClose(dh); return SLP_ERROR_AUTHENTICATION_FAILED; } #ifdef ENABLE_SLPv2_SECURITY if ( entryreg->urlentry.authcount && entryreg->urlentry.authcount != reg->urlentry.authcount ) { SLPDatabaseClose(dh); return SLP_ERROR_AUTHENTICATION_FAILED; } #endif /* Remove the identical entry */ SLPDatabaseRemove(dh,entry); break; } } } /*------------------------------------*/ /* Add the new srvreg to the database */ /*------------------------------------*/ entry = SLPDatabaseEntryCreate(msg,buf); if ( entry ) { /* set the source (allows for quicker aging ) */ if ( msg->body.srvreg.source == SLP_REG_SOURCE_UNKNOWN ) { if ( ISLOCAL(msg->peer.sin_addr) ) { msg->body.srvreg.source = SLP_REG_SOURCE_LOCAL; } else { msg->body.srvreg.source = SLP_REG_SOURCE_REMOTE; } } /* add to database */ SLPDatabaseAdd(dh, entry); SLPDLogRegistration("Registration",entry); /* SUCCESS! */ result = 0; } else { result = SLP_ERROR_INTERNAL_ERROR; } SLPDatabaseClose(dh); } else { result = SLP_ERROR_INTERNAL_ERROR; } return result; }