Example #1
0
/** 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;
}
Example #2
0
/** 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;
}
Example #3
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;
}
Example #4
0
/** 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;
}   
Example #5
0
/** 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()*/

}
Example #6
0
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
}
Example #7
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;
}
Example #8
0
/** 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;
}