/** Set the multicast interface for a socket. -- Copied from slpd_socket.c * * @param[in] sockfd - the socket file descriptor for which to set the multicast IF * @param[in] addr - A pointer to the address of the local network interface * * @return Zero on success, or a non-zero value on failure. * * @internal */ static int SetMulticastIF(int family, sockfd_t sockfd, const struct sockaddr_storage * addr) { if (SLPNetIsIPV4() && ((family == AF_INET) || (family == AF_UNSPEC))) return setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, (char*)(&(((struct sockaddr_in*)addr)->sin_addr)), sizeof(struct in_addr)); else if (SLPNetIsIPV6() && ((family == AF_INET6) || (family == AF_UNSPEC))) return setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char*)(&((struct sockaddr_in6 *)addr)->sin6_scope_id), sizeof(unsigned int)); return -1; }
/** Checks a string-list for the occurence of a string * * @param[in] list - A pointer to the string-list to be checked. * @param[in] listlen - The length in bytes of @p list. * @param[in] string - A pointer to a string to find in @p list. * @param[in] stringlen - The length in bytes of @p string. * * @return Zero if @p string is NOT contained in @p list; * A non-zero value if it is. * * @internal */ static int SLPIfaceContainsAddr(size_t listlen, const char * list, size_t stringlen, const char * string) { char * listend = (char *) list + listlen; char * itembegin = (char *) list; char * itemend = itembegin; struct sockaddr_storage addr; char buffer[INET6_ADDRSTRLEN]; /* must be at least 40 characters */ int buffer_len; while (itemend < listend) { itembegin = itemend; /* seek to the end of the next list item */ while (1) { if (itemend == listend || *itemend == ',') if (*(itemend - 1) != '\\') break; itemend ++; } if (itemend - itembegin < sizeof(buffer)) buffer_len = (int)(itemend - itembegin); else buffer_len = sizeof(buffer); strncpy(buffer, itembegin, buffer_len); buffer[itemend - itembegin] = '\0'; if (SLPNetIsIPV6() && inet_pton(AF_INET6, buffer, &addr) == 1) { inet_ntop(AF_INET6, &addr, buffer, sizeof(buffer)); if (SLPCompareString(strlen(buffer), buffer, stringlen, string) == 0) return 1; } else if (SLPNetIsIPV4() && inet_pton(AF_INET, buffer, &addr) == 1) { inet_ntop(AF_INET, &addr, buffer, sizeof(buffer)); if (SLPCompareString(strlen(buffer), buffer, stringlen, string) == 0) return 1; } itemend ++; } return 0; }
/** Set the socket options for ttl (time-to-live). -- Copied from slpd_socket.c * * @param[in] sockfd - the socket file descriptor for which to set TTL state. * @param[in] ttl - A boolean value indicating whether to enable or disable * the time-to-live option. * * @return Zero on success, or a non-zero value on failure. * * @internal */ static int SetMulticastTTL(int family, sockfd_t sockfd, int ttl) { if (SLPNetIsIPV4() && ((family == AF_INET) || (family == AF_UNSPEC))) { #if defined(linux) || defined(_WIN32) int optarg = ttl; #else /*Solaris and Tru64 expect an unsigned char parameter*/ unsigned char optarg = (unsigned char)ttl; #endif return setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&optarg, sizeof(optarg)); } else if (SLPNetIsIPV6() && ((family == AF_INET6) || (family == AF_UNSPEC))) { int optarg = ttl; return setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&optarg, sizeof(optarg)); } return -1; }
/** Formats and sends an SLPFindSrvs wire buffer request. * * @param handle - The OpenSLP session handle, containing request * parameters. See docs for SLPFindSrvs. * * @return Zero on success, or an SLP API error code. * * @internal */ static SLPError ProcessSrvRqst(SLPHandleInfo * handle) { uint8_t * buf; uint8_t * curpos; SLPError serr; size_t spistrlen = 0; char * spistr = 0; struct sockaddr_storage peeraddr; struct sockaddr_in* destaddrs = 0; sockfd_t sock = SLP_INVALID_SOCKET; /* Is this a special attempt to locate DAs? */ if (strncasecmp(handle->params.findsrvs.srvtype, SLP_DA_SERVICE_TYPE, handle->params.findsrvs.srvtypelen) == 0) { KnownDAProcessSrvRqst(handle); return 0; } #ifdef ENABLE_SLPv2_SECURITY if (SLPPropertyAsBoolean("net.slp.securityEnabled")) SLPSpiGetDefaultSPI(handle->hspi, SLPSPI_KEY_TYPE_PUBLIC, &spistrlen, &spistr); #endif /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of <service-type> | <service-type> String \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of <scope-list> | <scope-list> String \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of predicate string | Service Request <predicate> \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | length of <SLP SPI> string | <SLP SPI> String \ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ buf = curpos = xmalloc( + 2 + handle->params.findsrvs.srvtypelen + 2 + handle->params.findsrvs.scopelistlen + 2 + handle->params.findsrvs.predicatelen + 2 + spistrlen); if (buf == 0) { xfree(spistr); return SLP_MEMORY_ALLOC_FAILED; } /* <service-type> */ PutL16String(&curpos, handle->params.findsrvs.srvtype, handle->params.findsrvs.srvtypelen); /* <scope-list> */ PutL16String(&curpos, handle->params.findsrvs.scopelist, handle->params.findsrvs.scopelistlen); /* predicate string */ PutL16String(&curpos, handle->params.findsrvs.predicate, handle->params.findsrvs.predicatelen); /* <SLP SPI> */ PutL16String(&curpos, (char *)spistr, spistrlen); /* Call the RqstRply engine. */ do { #ifndef UNICAST_NOT_SUPPORTED if (handle->dounicast == 1) { serr = NetworkUcastRqstRply(handle, buf, SLP_FUNCT_SRVRQST, curpos - buf, ProcessSrvRplyCallback, handle, false); break; } if (SLPNetIsIPV4()) { if (KnownDASpanningListFromCache(handle, (int)handle->params.findsrvs.scopelistlen, handle->params.findsrvs.scopelist, &destaddrs) > 0) { serr = NetworkMultiUcastRqstRply(destaddrs, handle->langtag, (char*)buf, SLP_FUNCT_SRVRQST, curpos - buf, ProcessSrvRplyCallback, handle, false); xfree(destaddrs); break; } } #endif if (strncasecmp(handle->params.findsrvs.srvtype, SLP_SA_SERVICE_TYPE, handle->params.findsrvs.srvtypelen) != 0) sock = NetworkConnectToDA(handle, handle->params.findsrvs.scopelist, handle->params.findsrvs.scopelistlen, &peeraddr); if (sock == SLP_INVALID_SOCKET) { /* Use multicast as a last resort. */ serr = NetworkMcastRqstRply(handle, buf, SLP_FUNCT_SRVRQST, curpos - buf, ProcessSrvRplyCallback, 0, false); break; } serr = NetworkRqstRply(sock, &peeraddr, handle->langtag, 0, buf, SLP_FUNCT_SRVRQST, curpos - buf, ProcessSrvRplyCallback, handle, false); if (serr) NetworkDisconnectDA(handle); } while (serr == SLP_NETWORK_ERROR); xfree(buf); xfree(spistr); return serr; }
/** Reinitialize the slpd property management subsystem. * * Clears and rereads configuration parameters from files into the system. * Resets slpd-specific overrides. */ void SLPDPropertyReinit(void) { int sts; char * myinterfaces = 0; int family = AF_UNSPEC; /* free previous settings (if any) */ xfree(G_SlpdProperty.useScopes); xfree(G_SlpdProperty.DAAddresses); xfree(G_SlpdProperty.interfaces); xfree(G_SlpdProperty.locale); /* reinitialize property sub-system */ (void)SLPPropertyReinit(); /* set the properties without hard defaults */ G_SlpdProperty.isDA = SLPPropertyAsBoolean("net.slp.isDA"); G_SlpdProperty.activeDADetection = SLPPropertyAsBoolean("net.slp.activeDADetection"); if (G_SlpdProperty.activeDADetection) { G_SlpdProperty.DAActiveDiscoveryInterval = SLPPropertyAsInteger("net.slp.DAActiveDiscoveryInterval"); if (G_SlpdProperty.DAActiveDiscoveryInterval > 1 && G_SlpdProperty.DAActiveDiscoveryInterval < SLPD_CONFIG_DA_FIND) G_SlpdProperty.DAActiveDiscoveryInterval = SLPD_CONFIG_DA_FIND; } else G_SlpdProperty.DAActiveDiscoveryInterval = 0; G_SlpdProperty.passiveDADetection = SLPPropertyAsBoolean("net.slp.passiveDADetection"); G_SlpdProperty.staleDACheckPeriod = SLPPropertyAsInteger("net.slp.staleDACheckPeriod"); if (G_SlpdProperty.staleDACheckPeriod > 0) { if (G_SlpdProperty.staleDACheckPeriod < (SLPD_HEARTBEATS_PER_CHECK_PERIOD + 1) * SLPD_AGE_INTERVAL) G_SlpdProperty.staleDACheckPeriod = (SLPD_HEARTBEATS_PER_CHECK_PERIOD + 1) * SLPD_AGE_INTERVAL; SLPDLog("staleDACheckPeriod = %ds\n", G_SlpdProperty.staleDACheckPeriod); } G_SlpdProperty.isBroadcastOnly = SLPPropertyAsBoolean("net.slp.isBroadcastOnly"); G_SlpdProperty.multicastTTL = SLPPropertyAsInteger("net.slp.multicastTTL"); G_SlpdProperty.multicastMaximumWait = SLPPropertyAsInteger("net.slp.multicastMaximumWait"); G_SlpdProperty.unicastMaximumWait = SLPPropertyAsInteger("net.slp.unicastMaximumWait"); SLPPropertyAsIntegerVector("net.slp.unicastTimeouts", G_SlpdProperty.unicastTimeouts, MAX_RETRANSMITS); G_SlpdProperty.randomWaitBound = SLPPropertyAsInteger("net.slp.randomWaitBound"); G_SlpdProperty.maxResults = SLPPropertyAsInteger("net.slp.maxResults"); G_SlpdProperty.traceMsg = SLPPropertyAsBoolean("net.slp.traceMsg"); G_SlpdProperty.traceReg = SLPPropertyAsBoolean("net.slp.traceReg"); G_SlpdProperty.traceDrop = SLPPropertyAsBoolean("net.slp.traceDrop"); G_SlpdProperty.traceDATraffic = SLPPropertyAsBoolean("net.slp.traceDATraffic"); G_SlpdProperty.appendLog = SLPPropertyAsBoolean("net.slp.appendLog"); if ((G_SlpdProperty.DAAddresses = SLPPropertyXDup("net.slp.DAAddresses")) != 0) G_SlpdProperty.DAAddressesLen = strlen(G_SlpdProperty.DAAddresses); /** @todo Make sure that we are using scopes correctly. What about DHCP, etc? */ if ((G_SlpdProperty.useScopes = SLPPropertyXDup("net.slp.useScopes")) != 0) G_SlpdProperty.useScopesLen = strlen(G_SlpdProperty.useScopes); if ((G_SlpdProperty.locale = SLPPropertyXDup("net.slp.locale")) != 0) G_SlpdProperty.localeLen = strlen(G_SlpdProperty.locale); G_SlpdProperty.securityEnabled = SLPPropertyAsBoolean("net.slp.securityEnabled"); G_SlpdProperty.checkSourceAddr = SLPPropertyAsBoolean("net.slp.checkSourceAddr"); G_SlpdProperty.DAHeartBeat = SLPPropertyAsInteger("net.slp.DAHeartBeat"); if (G_SlpdProperty.staleDACheckPeriod > 0) { /* Adjust the heartbeat interval if we need to send it faster for * stale DA detection */ int maxHeartbeat = G_SlpdProperty.staleDACheckPeriod / SLPD_HEARTBEATS_PER_CHECK_PERIOD; if ((G_SlpdProperty.DAHeartBeat == 0) || (G_SlpdProperty.DAHeartBeat > maxHeartbeat)) { SLPDLog("Overriding heartbeat to %ds for stale DA check\n", maxHeartbeat); G_SlpdProperty.DAHeartBeat = maxHeartbeat; } } /* Can't send it out more frequently than every interval */ if (G_SlpdProperty.DAHeartBeat < SLPD_AGE_INTERVAL) G_SlpdProperty.DAHeartBeat = SLPD_AGE_INTERVAL; G_SlpdProperty.port = (uint16_t)SLPPropertyAsInteger("net.slp.port"); /* set the net.slp.interfaces property */ if (SLPNetIsIPV4() && SLPNetIsIPV6()) family = AF_UNSPEC; else if (SLPNetIsIPV4()) family = AF_INET; else if (SLPNetIsIPV6()) family = AF_INET6; myinterfaces = SLPPropertyXDup("net.slp.interfaces"); sts = SLPIfaceGetInfo(myinterfaces, &G_SlpdProperty.ifaceInfo, family); xfree(myinterfaces); if (!G_SlpdProperty.indexingPropertiesSet) { #ifdef ENABLE_PREDICATES G_SlpdProperty.indexedAttributesLen = 0; if ((G_SlpdProperty.indexedAttributes = SLPPropertyXDup("net.slp.indexedAttributes")) != 0) G_SlpdProperty.indexedAttributesLen = strlen(G_SlpdProperty.indexedAttributes); #endif G_SlpdProperty.srvtypeIsIndexed = SLPPropertyAsBoolean("net.slp.indexSrvtype"); G_SlpdProperty.indexingPropertiesSet = 1; } else { #ifdef ENABLE_PREDICATES int attrchg = 0; char *indexedAttributes = SLPPropertyXDup("net.slp.indexedAttributes"); if (!indexedAttributes && G_SlpdProperty.indexedAttributes) attrchg = 1; else if (indexedAttributes && !G_SlpdProperty.indexedAttributes) attrchg = 1; else if (indexedAttributes) { if (strcmp(indexedAttributes, G_SlpdProperty.indexedAttributes) != 0) attrchg = 1; } if (attrchg) SLPDLog("Cannot change value of net.slp.indexedAttributes without restarting the daemon\n"); xfree(indexedAttributes); #endif if (G_SlpdProperty.srvtypeIsIndexed != SLPPropertyAsBoolean("net.slp.indexSrvtype")) SLPDLog("Cannot change value of net.slp.indexSrvtype without restarting the daemon\n"); } if (sts == 0) { myinterfaces = 0; if (SLPIfaceSockaddrsToString(G_SlpdProperty.ifaceInfo.iface_addr, G_SlpdProperty.ifaceInfo.iface_count, &myinterfaces) == 0) { SLPPropertySet("net.slp.interfaces", myinterfaces, SLP_PA_USERSET); G_SlpdProperty.interfaces = myinterfaces; G_SlpdProperty.interfacesLen = strlen(G_SlpdProperty.interfaces); } } /* set the value used internally as the url for this agent */ strcpy(G_SlpdProperty.urlPrefix, G_SlpdProperty.isDA? SLP_DA_SERVICE_TYPE: SLP_SA_SERVICE_TYPE); strcat(G_SlpdProperty.urlPrefix, "://"); G_SlpdProperty.urlPrefixLen = strlen(G_SlpdProperty.urlPrefix); /* set other values used internally */ G_SlpdProperty.DATimestamp = (uint32_t)time(0); /* DATimestamp must be the boot time of the process */ G_SlpdProperty.activeDiscoveryXmits = 3; /* ensures xmit on first 3 calls to SLPDKnownDAActiveDiscovery() */ G_SlpdProperty.nextActiveDiscovery = 0; /* ensures xmit on first call to SLPDKnownDAActiveDiscovery() */ G_SlpdProperty.nextPassiveDAAdvert = 0; /* ensures xmit on first call to SLPDKnownDAPassiveDiscovery()*/ }
int main(int argc, char * argv[]) { char addrString[1024]; int sts; int errorCount = 0; struct sockaddr_storage addr; #ifdef _WIN32 WSADATA wsadata; WSAStartup(MAKEWORD(2, 2), &wsadata); #endif sts = SLPNetResolveHostToAddr("localhost", &addr); if (sts != 0) { printf("error %d with SLPNetResolveHostToAddr.\r\n", sts); errorCount++; } else { printf("addr family = %d\r\n", addr.ss_family); SLPNetSockAddrStorageToString(&addr, addrString, sizeof(addrString)); printf("address = %s\r\n", addrString); } sts = SLPNetResolveHostToAddr("::1", &addr); if (sts != 0) { printf("error %d with SLPNetResolveHostToAddr.\r\n", sts); errorCount++; } else { printf("addr family = %d\r\n", addr.ss_family); SLPNetSockAddrStorageToString(&addr, addrString, sizeof(addrString)); printf("address = %s\r\n", addrString); } sts = SLPPropertyReadFile("e:\\source\\Hogwarts_ActiveX\\OpenSLP\\" "ipv6\\win32\\slpd\\slp.conf"); if (sts == 0) printf("Read config file\r\n"); else printf("No config file found - using defaults.\r\n"); sts = SLPNetIsIPV6(); if (sts == 0) printf("Not using ipv6\r\n"); else printf("Using ipv6\r\n"); sts = SLPNetIsIPV4(); if (sts == 0) printf("Not using ipv4\r\n"); else printf("Using ipv4\r\n"); { struct sockaddr_storage a1; struct sockaddr_storage a2; char testaddr[] = "1:2:3:4:5::6"; struct sockaddr_in * p41 = (struct sockaddr_in *)&a1; struct sockaddr_in6 * p61 = (struct sockaddr_in6 *)&a1; struct sockaddr_in * p42 = (struct sockaddr_in *)&a2; struct sockaddr_in6 * p62 = (struct sockaddr_in6 *)&a2; memset(&a1, 0, sizeof(a1)); memset(&a2, 0, sizeof(a2)); SLPNetSetAddr(&a1, AF_INET6, 2, testaddr, sizeof(testaddr)); memcpy(&a2, &a1, sizeof(a1)); sts = SLPNetCompareAddrs(&a1, &a2); if (sts != 0) printf("Error, address a1 does not equal a2 - copy failed\r\n"); memset(&a2, 0, sizeof(a2)); a2.ss_family = AF_INET6; memcpy(p62->sin6_addr.s6_addr, testaddr, sizeof(testaddr)); p62->sin6_family = AF_INET6; p62->sin6_port = htons(2); sts = SLPNetCompareAddrs(&a1, &a2); if (sts != 0) printf("Error, address a1 does not equal a2\r\n"); } /* now test the ipv6 expansion */ { char t1[] = "::"; char a1[] = "0000:0000:0000:0000:0000:0000:0000:0000"; char t2[] = "1::"; char a2[] = "0001:0000:0000:0000:0000:0000:0000:0000"; char t3[] = "::1"; char a3[] = "0000:0000:0000:0000:0000:0000:0000:0001"; char t4[] = "12::34"; char a4[] = "0012:0000:0000:0000:0000:0000:0000:0034"; char t5[] = "1111:2222:3333::5555:6666:7777:8888"; char a5[] = "1111:2222:3333:0000:5555:6666:7777:8888"; char t6[] = "1:02::003:0004"; char a6[] = "0001:0002:0000:0000:0000:0000:0003:0004"; char t7[] = "0001:0002:0003:0004:0005:0006:0007:0008"; char a7[] = "0001:0002:0003:0004:0005:0006:0007:0008"; char t8[] = "1:02:003:0004:0005:006:07:8"; char a8[] = "0001:0002:0003:0004:0005:0006:0007:0008"; char i1[] = "1::2::3"; char i2[] = "1:::3"; char buf[40]; /* min buf size - 8*4 + 7 + null */ int sts; sts = SLPNetExpandIpv6Addr(t1, buf, sizeof(buf)); if ((sts != 0) || (strcmp(buf, a1) != 0)) printf("Error expanding ipv6 address t1\r\n"); sts = SLPNetExpandIpv6Addr(t2, buf, sizeof(buf)); if ((sts != 0) || (strcmp(buf, a2) != 0)) printf("Error expanding ipv6 address t2\r\n"); sts = SLPNetExpandIpv6Addr(t3, buf, sizeof(buf)); if ((sts != 0) || (strcmp(buf, a3) != 0)) printf("Error expanding ipv6 address t3\r\n"); sts = SLPNetExpandIpv6Addr(t4, buf, sizeof(buf)); if ((sts != 0) || (strcmp(buf, a4) != 0)) printf("Error expanding ipv6 address t4\r\n"); sts = SLPNetExpandIpv6Addr(t5, buf, sizeof(buf)); if ((sts != 0) || (strcmp(buf, a5) != 0)) printf("Error expanding ipv6 address t5\r\n"); sts = SLPNetExpandIpv6Addr(t6, buf, sizeof(buf)); if ((sts != 0) || (strcmp(buf, a6) != 0)) printf("Error expanding ipv6 address t6\r\n"); sts = SLPNetExpandIpv6Addr(t7, buf, sizeof(buf)); if ((sts != 0) || (strcmp(buf, a7) != 0)) printf("Error expanding ipv6 address t7\r\n"); sts = SLPNetExpandIpv6Addr(t8, buf, sizeof(buf)); if ((sts != 0) || (strcmp(buf, a8) != 0)) printf("Error expanding ipv6 address t8\r\n"); sts = SLPNetExpandIpv6Addr(i1, buf, sizeof(buf)); sts = SLPNetExpandIpv6Addr(i2, buf, sizeof(buf)); sts = SLPNetExpandIpv6Addr(t6, buf, 5); if (sts == 0) printf("Error, size not checked for expansion\r\n"); } /* int SLPNetIsMCast(const struct sockaddr_storage *addr); * int SLPNetIsLocal(const struct sockaddr_storage *addr); */ #ifdef _WIN32 WSACleanup(); #endif }
/** 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; }
/** Get the network interface addresses for this host. * * Returns either a complete list or a subset of the list of network interface * addresses for this host. If the user specifies a list, then network interfaces * * @param[in] useifaces - Pointer to comma delimited string of interface * IPv4 addresses to get interface information for. Pass 0 or the empty * string to get all interfaces (except the loopback interface). * @param[out] ifaceinfo - The address of a buffer in which to return * information about the requested interfaces. * @param[in] family - A hint indicating the address family to get info * for - can be AF_INET, AF_INET6, or AF_UNSPEC for both. * * @return Zero on success; A non-zero value (with errno set) on error. * * @remarks Does NOT return the loopback interface. */ int SLPIfaceGetInfo(const char * useifaces, SLPIfaceInfo * ifaceinfo, int family) { size_t useifaceslen = useifaces? strlen(useifaces): 0; int sts = 0; ifaceinfo->iface_count = 0; ifaceinfo->bcast_count = 0; if (!useifaceslen) { /* no specified list - get all available interface addresses */ if (SLPIfaceGetDefaultInfo(ifaceinfo, family) != 0) return -1; } else { /* list specified: parse it and use it */ /* only allow addresses in configured address set */ char * p = SLPPropertyXDup("net.slp.interfaces"); /* If there are no configured addresses, use the passed in addresses*/ if(p && (0 == strlen(p))) { xfree(p); p = xstrdup(useifaces); } if (p) { char * ep = p + strlen(p); char * slider1 = p; char * slider2 = p; while (slider1 < ep) { while (*slider2 != 0 && *slider2 != ',') slider2++; *slider2 = 0; if (SLPIfaceContainsAddr(useifaceslen, useifaces, strlen(slider1), slider1)) { sockfd_t fd; struct sockaddr_in v4addr; struct sockaddr_in6 v6addr; /* check if an ipv4 address was given */ if (inet_pton(AF_INET, slider1, &v4addr.sin_addr) == 1) { if (SLPNetIsIPV4() && ((family == AF_INET) || (family == AF_UNSPEC))) { fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd != SLP_INVALID_SOCKET) { v4addr.sin_family = AF_INET; v4addr.sin_port = 0; memset(v4addr.sin_zero, 0, sizeof(v4addr.sin_zero)); if ((sts = bind(fd, (struct sockaddr *)&v4addr, sizeof(v4addr))) == 0) memcpy(&ifaceinfo->iface_addr[ifaceinfo->iface_count++], &v4addr, sizeof(v4addr)); closesocket(fd); } } } else if (inet_pton(AF_INET6, slider1, &v6addr.sin6_addr) == 1) { if (SLPNetIsIPV6() && ((family == AF_INET6) || (family == AF_UNSPEC))) { v6addr.sin6_family = AF_INET6; v6addr.sin6_port = 0; v6addr.sin6_flowinfo = 0; if((sts = GetV6Scope(&v6addr)) == 0) memcpy(&ifaceinfo->iface_addr[ifaceinfo->iface_count++], &v6addr, sizeof(v6addr)); } } else sts = (errno = EINVAL), -1; /* not v4, not v6 */ } slider1 = ++slider2; } } xfree(p); } /* now stuff in a v4 broadcast address */ if (SLPNetIsIPV4() && ((family == AF_INET) || (family == AF_UNSPEC))) { struct sockaddr_storage sa; char * str = SLPPropertyXDup("net.slp.broadcastAddr"); if (!str || !*str) { unsigned long addr = INADDR_BROADCAST; SLPNetSetAddr(&sa, AF_INET, 0, &addr); memcpy(&ifaceinfo->bcast_addr[ifaceinfo->bcast_count++], &sa, sizeof(sa)); } else { unsigned long addr; if (inet_pton(AF_INET, str, &addr) == 1) { SLPNetSetAddr(&sa, AF_INET, 0, &addr); memcpy(&ifaceinfo->bcast_addr[ifaceinfo->bcast_count++], &sa, sizeof(sa)); } } xfree(str); } return sts; }