/* * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * mslpd_parse.c : Parses messages in and out of the mini slpv2 SA. * * Version: 1.7 * Date: 10/05/99 * * Licensee will, at its expense, defend and indemnify Sun Microsystems, * Inc. ("Sun") and its licensors from and against any third party * claims, including costs and reasonable attorneys' fees, and be wholly * responsible for any liabilities arising out of or related to the * Licensee's use of the Software or Modifications. The Software is not * designed or intended for use in on-line control of aircraft, air * traffic, aircraft navigation, or aircraft communications; or in the * design, construction, operation or maintenance of any nuclear facility * and Sun disclaims any express or implied warranty of fitness for such * uses. THE SOFTWARE IS PROVIDED TO LICENSEE "AS IS" AND ALL EXPRESS OR * IMPLIED CONDITION AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF * MERCHANTABILITY, FITNESS FOR WARRANTIES, INCLUDING ANY IMPLIED * WARRANTY OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE OR NON- * INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT WILL SUN BE LIABLE HEREUNDER * FOR ANY DIRECT DAMAGES OR ANY INDIRECT, PUNITIVE, SPECIAL, INCIDENTAL * OR CONSEQUENTIAL DAMAGES OF ANY KIND. * * (c) Sun Microsystems, 1998, All Rights Reserved. * Author: Erik Guttman */ /* Portions Copyright (c) 2002 Apple Computer, Inc. All rights reserved. */ #include #include //#include #include "mslp_sd.h" #include "slp.h" #include "mslp.h" #include "mslp_dat.h" #include "mslpd_store.h" #include "mslpd.h" #include "mslpd_mask.h" #include "mslpd_parse.h" /* ------------------------------------------------------------------------- */ /* * parse the request in */ SLPInternalError srvrqst_in(Slphdr *pslphdr, const char *pcInBuf, int iInSz, char **ppcPRList, char **ppcSrvType, char **ppcScopes, char **ppcPredicate) { SLPInternalError err; int offset = HDRLEN + strlen(pslphdr->h_pcLangTag); *ppcPRList = NULL; *ppcSrvType = NULL; *ppcScopes = NULL; if ((err = get_string(pcInBuf, iInSz, &offset, ppcPRList)) < 0) goto srvrqst_in_fail; if ((err = get_string(pcInBuf, iInSz, &offset, ppcSrvType)) < 0) goto srvrqst_in_fail; if ((err = get_string(pcInBuf, iInSz, &offset, ppcScopes)) < 0) goto srvrqst_in_fail; if ((err = get_string(pcInBuf, iInSz, &offset, ppcPredicate)) < 0) goto srvrqst_in_fail; /* ignore SLP SPI */ /* ignore options */ return SLP_OK; srvrqst_in_fail: if (*ppcPRList) SLPFree((void*)ppcPRList); *ppcPRList = NULL; if (*ppcSrvType) SLPFree((void*)ppcSrvType); *ppcSrvType = NULL; if (*ppcScopes) SLPFree((void*)ppcScopes); *ppcScopes = NULL; return err; } /* * srvrply_out * * Parse the reply out, into a SRVRPLY. Use the result mask to determine * which services were matched by the request. The request's header is * used to set the fields in the reply header. * * ps A pointer to the service store. * errcode The error code of the reply. If nonzero, just return this. * pm The mask of results. * pslphdr The header of the request. * ppcOutBuf A pointer to the buffer to allocate. * piOutSz A pointer to the size of the buffer that was allocated. * piGot A pointer to the number of results serialized out. * * Return: * SLPInternalError result. The ppcOutBuf is set to a new buffer allocated by * this function. The piOutSz parameter is set to the size of this buffer. * * Side Effects: * The caller must SLPFree the ppcOutBuf. It is wise to do mask_reset on * pm if it is used again as it might have been iterated upon here. * */ SLPInternalError srvrply_out(SAStore *ps, SLPInternalError err, Mask *pm, Slphdr *pslphdr, char **ppcOutBuf, int *piOutSz, int *piGot) { char* endPtr = NULL; int iMTU = (SLPGetProperty("net.slp.MTU"))?strtol(SLPGetProperty("net.slp.MTU"),&endPtr,10):1400; int iOverflow = 0; int iIsMcast = (pslphdr->h_usFlags & MCASTFLAG)?1:0; int hdrsz = HDRLEN + strlen(pslphdr->h_pcLangTag); int offset = 0; int count = 0; /* number of urlentries to return*/ *piOutSz = hdrsz + 4; /* error code and number of results fields */ *piGot = 0; if (err == SLP_OK) { int item; mask_reset(pm); while((item = mask_next(pm,1)) >= 0) { count++; /* 6 is from reserved (1) + lifetime (2) + url len (2) + # auths (1) */ *piOutSz += 6 + strlen(ps->url[item]); } } /* in the case of overflow in a unicast request, send 0 results & flag */ if (iIsMcast && *piOutSz >= iMTU) { *piOutSz = hdrsz + 4; iOverflow = 1; } *piGot = count; *ppcOutBuf = safe_malloc(*piOutSz, 0, 0); if( !*ppcOutBuf ) return SLP_PARSE_ERROR; /* parse header out */ SETVER(*ppcOutBuf,2); SETFUN(*ppcOutBuf,SRVRPLY); SETLEN(*ppcOutBuf,*piOutSz); SETLANG(*ppcOutBuf,pslphdr->h_pcLangTag); SETXID(*ppcOutBuf,pslphdr->h_usXID); if (iOverflow) { SETFLAGS(*ppcOutBuf,OVERFLOWFLAG); return SLP_OK; } /* parse payload out */ offset = hdrsz; SETSHT(*ppcOutBuf,api2slp(err),offset); offset += 2; if (err == SLP_OK) { SETSHT(*ppcOutBuf,count,offset); offset += 2; mask_reset(pm); while (count--) { /* if there are no URLs (ie. on error), skip this */ int item = mask_next(pm,1); offset++; /* skip reserved */ if ((err = add_sht(*ppcOutBuf,*piOutSz, (0xFFFF & ps->life[item]),&offset)) < 0 || (err = add_string(*ppcOutBuf,*piOutSz,ps->url[item],&offset)) < 0) { return err; } offset++; /* skip # auths field, none will be supplied */ } } return SLP_OK; } #ifdef EXTRA_MSGS int saadvert_out(SAState *ps, Slphdr *pslph, char **ppc, int *piOutSz){ int offset = 0; const char *pcLang = (pslph->h_pcLangTag)?pslph->h_pcLangTag:"en"; const char *pcScopeList = SLPGetProperty("net.slp.useScopes"); const char *pcSrvTypeList = SLPGetProperty("com.sun.slp.saSrvTypes"); char *pcSAAttrs; if (!pcScopeList) pcScopeList = ""; if (!pcSrvTypeList) pcSrvTypeList = ""; pcSAAttrs = safe_malloc(strlen(pcSrvTypeList)+strlen("(service-types=")+2, "(service-types=",strlen("(service-types=")); if( !pcSAAttrs ) return SLP_MEMORY_ALLOC_FAILED; strcat(pcSAAttrs,pcSrvTypeList); strcat(pcSAAttrs,")"); *piOutSz = strlen(ps->pcSAURL) + 2 + strlen(pcScopeList) + 2 + HDRLEN + strlen(pcLang) + strlen(pcSAAttrs) + 1; *ppc = safe_malloc(*piOutSz,0,0); if( !*ppc ) return SLP_MEMORY_ALLOC_FAILED; /* parse header out */ SETVER(*ppc,2); SETFUN(*ppc,SAADVERT); SETLEN(*ppc,*piOutSz); SETLANG(*ppc,pslph->h_pcLangTag); SETXID(*ppc,pslph->h_usXID); /* parse payload out */ offset = HDRLEN + strlen(pcLang); add_string(*ppc,*piOutSz,ps->pcSAURL, &offset); add_string(*ppc,*piOutSz,pcScopeList, &offset); add_string(*ppc,*piOutSz,pcSAAttrs, &offset); (*ppc)[offset] = '\0'; /* set the # of auth blocks to 0 */ SLPFree(pcSAAttrs); return SLP_OK; } #endif /* EXTRA_MSGS */ #ifdef MAC_OS_X int daadvert_out(SAState *ps, SLPBoolean viaTCP, Slphdr *pslph, char **ppc, int *piOutSz) { const char * pcAttributeList = ""; char* advertMessage = NULL; char* scopeListToAdvertise = (char*)malloc( strlen(SLPGetProperty("com.apple.slp.daScopeList")) + 1 ); // start out with a copy SLPBoolean needToSetOverflow = SLP_FALSE; SLP_LOG( SLP_LOG_DEBUG, "daadvert_out called"); if ( SLPGetProperty("com.apple.slp.daAttributeList") ) pcAttributeList = SLPGetProperty("com.apple.slp.daAttributeList"); if ( !viaTCP && SLPGetProperty("com.apple.slp.daPrunedScopeList") && SLPGetProperty("com.apple.slp.daPrunedScopeList") != "" ) { strcpy( scopeListToAdvertise, SLPGetProperty("com.apple.slp.daPrunedScopeList") ); needToSetOverflow = SLP_TRUE; } else if ( SLPGetProperty("com.apple.slp.daScopeList") ) strcpy( scopeListToAdvertise, SLPGetProperty("com.apple.slp.daScopeList") ); else return -1; // no Scope list! advertMessage = MakeDAAdvertisementMessage( pslph, ps->pcDAURL, scopeListToAdvertise, pcAttributeList, GetStatelessBootTime(), piOutSz ); if ( needToSetOverflow ) SETFLAGS(advertMessage,(unsigned char) OVERFLOWFLAG); // we want clients to make a TCP connection *ppc = advertMessage; if ( strlen(scopeListToAdvertise) < strlen(SLPGetProperty("com.apple.slp.daScopeList")) ) { SLP_LOG( SLP_LOG_DEBUG, "daadvert_out, advertising scopelist of size:%d out of original size:%d", strlen(scopeListToAdvertise), strlen(SLPGetProperty("com.apple.slp.daScopeList")) ); } if ( scopeListToAdvertise ) free( scopeListToAdvertise ); return SLP_OK; } char* MakeDAAdvertisementMessage( Slphdr* pslph, char* url, const char* scopeList, const char* attributeList, long timeStamp, int* outSize ) { short urlLength =strlen( url ); short scopeListLength = strlen(scopeList); short attributeListLength = strlen(attributeList); const char* pcLang = (pslph && pslph->h_pcLangTag)?pslph->h_pcLangTag:"en"; char* newRequest = NULL; char* curPtr; short sizeofNewMessage = HDRLEN + strlen(pcLang) + 2 // error code + 4 // Time stamp + urlLength + sizeof(urlLength) + scopeListLength + sizeof(scopeListLength) + attributeListLength + sizeof(attributeListLength) + 2 // SPI List length + 1; // num Auth blocks if ( ServerScopeSponsoringEnabled() ) { sizeofNewMessage += 2 + SizeOfServerScopeSponsorData(); // including scope data } newRequest = (char*)safe_malloc( sizeofNewMessage, 0, 0 ); if( newRequest ) { // first fill out the header SETVER(newRequest,2); SETFUN(newRequest, DAADVERT); SETLEN(newRequest, sizeofNewMessage); SETLANG(newRequest,pcLang); SETXID(newRequest, (pslph)?pslph->h_usXID:0); // only is zero if this is an unsolicited DAAdvert curPtr = newRequest+GETHEADERLEN(newRequest); // point to beyond the header *((short*)curPtr) = SLP_OK; // set the error code curPtr += 2; *(long*)curPtr = timeStamp; // if we are stateless then we need to remember last time all regs were lost curPtr += 4; *(short*)curPtr = urlLength; curPtr += sizeof(urlLength); // advance past the length bytes strcpy( curPtr, url ); // now add the url curPtr += urlLength; *((short*)curPtr) = scopeListLength; // set the scope list length curPtr += sizeof(scopeListLength); if ( scopeListLength > 0 ) strcpy( curPtr, scopeList ); curPtr += scopeListLength; *((short*)curPtr) = attributeListLength; // set the attributeListLength curPtr += sizeof(attributeListLength); if ( attributeListLength > 0 ) strcpy( curPtr, attributeList ); curPtr += attributeListLength; // now we don't support SLP SPI yet *((short*)curPtr) = 0; curPtr += 2; // nor auth blocks so... *((char*)curPtr) = 0; curPtr += 2; // but perhaps we have it this configured to use SCOPE_SPONSER_EXTENSION_ID if ( ServerScopeSponsoringEnabled() ) { memcpy( curPtr, GetServerScopeSponsorData(), SizeOfServerScopeSponsorData() ); // including scope data curPtr += SizeOfServerScopeSponsorData(); } *outSize = sizeofNewMessage; } else *outSize = 0; return newRequest; } #endif /* MAC_OS_X */ /* ------------------------------------------------------------------------- */ unsigned char api2slp(SLPInternalError se) { switch(se) { case SLP_OK: return 0; case SLP_LANGUAGE_NOT_SUPPORTED: return LANGUAGE_NOT_SUPPORTED; case SLP_PARSE_ERROR: return PARSE_ERROR; case SLP_SCOPE_NOT_SUPPORTED: return SCOPE_NOT_SUPPORTED; default: return INTERNAL_ERROR; } }