/** Convert an array of sockaddr_storage buffers to a comma-delimited list. * * Converts an array of sockaddr_storage buffers to a comma-delimited list of * addresses in presentation (string) format. * * @param[in] addrs - A pointer to array of sockaddr_storages to convert. * @param[in] addrcount - The number of elements in @p addrs. * @param[out] addrstr - The address in which to return a pointer to an * allocated comma-delimited list of addresses. * * @return Zero on success, non-zero (with errno set) on error. * * @remarks The caller must free @p addrstr when no longer needed. */ int SLPIfaceSockaddrsToString(struct sockaddr_storage const * addrs, int addrcount, char ** addrstr) { int i; SLP_ASSERT(addrs && addrcount && addrstr); if (!addrs || !addrcount || !addrstr) return (errno = EINVAL), -1; /* 40 is the maximum size of a string representation of * an IPv6 address (including the comma for the list) */ if ((*addrstr = xmalloc(addrcount * 40)) == 0) return (errno = ENOMEM), -1; **addrstr = 0; for (i = 0; i < addrcount; i++) { char buf[1024] = ""; SLPNetSockAddrStorageToString(&addrs[i], buf, sizeof(buf)); strcat(*addrstr, buf); if (i != addrcount - 1) strcat(*addrstr, ","); } return 0; }
/*-------------------------------------------------------------------------*/ void SLPDLogPeerAddr(struct sockaddr_storage* peeraddr) /*-------------------------------------------------------------------------*/ { char addr_str[INET6_ADDRSTRLEN]; SLPDLog("Peer IP address: %s\n", SLPNetSockAddrStorageToString(peeraddr, addr_str, sizeof(addr_str))); }
/** Dump outbound socket data. * * @note This routine is compiled in Debug code only. */ void SLPDOutgoingSocketDump(void) { char str1[INET6_ADDRSTRLEN]; char str2[INET6_ADDRSTRLEN]; char str3[INET6_ADDRSTRLEN]; SLPDSocket * sock = (SLPDSocket *) G_OutgoingSocketList.head; SLPDLog("========================================================================\n"); SLPDLog("Dumping OutgoingSocketList\n"); SLPDLog("========================================================================\n"); while (sock) { SLPDLog("localaddr=%s peeraddr=%s mcastaddr=%s\n", SLPNetSockAddrStorageToString(&(sock->localaddr), str1, sizeof(str1)), SLPNetSockAddrStorageToString(&(sock->peeraddr), str2, sizeof(str2)), SLPNetSockAddrStorageToString(&(sock->mcastaddr), str3, sizeof(str3))); sock = (SLPDSocket *) sock->listitem.next; } }
/*=========================================================================*/ void SLPDLogRegistration(const char* prefix, SLPDatabaseEntry* entry) /* Log record of having added a registration to the database. Logging of */ /* registraions will only occur if registration trace is enabled */ /* G_SlpProperty.traceReg != 0 */ /* */ /* prefix (IN) an informative prefix for the log entry */ /* */ /* entry (IN) the database entry that was affected */ /* */ /* Returns: none */ /*=========================================================================*/ { char addr_str[INET6_ADDRSTRLEN]; if (prefix == NULL || entry == NULL) { return; } if (G_SlpdProperty.traceReg) { SLPDLog("\n"); SLPDLogTime(); SLPDLog("DATABASE - %s:\n",prefix); SLPDLog(" SA address = "); switch (entry->msg->body.srvreg.source) { case SLP_REG_SOURCE_UNKNOWN: SLPDLog("<unknown>\n"); break; case SLP_REG_SOURCE_REMOTE: SLPDLog("remote (%s)\n", SLPNetSockAddrStorageToString(&(entry->msg->peer), addr_str, sizeof(addr_str))); break; case SLP_REG_SOURCE_LOCAL: SLPDLog("IPC (libslp)\n"); break; case SLP_REG_SOURCE_STATIC: SLPDLog("static (slp.reg)\n"); break; } SLPDLogBuffer(" service-url = ", entry->msg->body.srvreg.urlentry.urllen, entry->msg->body.srvreg.urlentry.url); SLPDLogBuffer(" scope = ", entry->msg->body.srvreg.scopelistlen, entry->msg->body.srvreg.scopelist); SLPDLogBuffer(" attributes = ", entry->msg->body.srvreg.attrlistlen, entry->msg->body.srvreg.attrlist); } }
/*=========================================================================*/ void SLPDLogDAAdvertisement(const char* prefix, SLPDatabaseEntry* entry) /* Log record of addition or removal of a DA to the store of known DAs. */ /* Will only occur if DA Advertisment message logging is enabled */ /* G_SlpProperty.traceDATraffic != 0 */ /* */ /* prefix (IN) an informative prefix for the log entry */ /* */ /* entry (IN) the database entry that was affected */ /* */ /* Returns: none */ /*=========================================================================*/ { char addr_str[INET6_ADDRSTRLEN]; if (prefix == NULL || entry == NULL) { return; } if (G_SlpdProperty.traceDATraffic) { SLPDLog("\n"); SLPDLogTime(); SLPDLog("KNOWNDA - %s:\n",prefix); SLPDLog(" DA address = %s\n",SLPNetSockAddrStorageToString(&(entry->msg->peer), addr_str, sizeof(addr_str))); SLPDLogBuffer(" directory-agent-url = ", entry->msg->body.daadvert.urllen, entry->msg->body.daadvert.url); SLPDLog(" bootstamp = %x\n",entry->msg->body.daadvert.bootstamp); SLPDLogBuffer(" scope = ", entry->msg->body.daadvert.scopelistlen, entry->msg->body.daadvert.scopelist); SLPDLogBuffer(" attributes = ", entry->msg->body.daadvert.attrlistlen, entry->msg->body.daadvert.attrlist); #ifdef ENABLE_SLPV2_SECURITY SLPDLogBuffer(" SPI list = ", entry->msg->body.daadvert.spilistlen, entry->msg->body.daadvert.spilist); #endif /*ENABLE_SLPV2_SECURITY*/ } }
/*=========================================================================*/ void SLPDLogMessage(int msglogflags, struct sockaddr_storage* peerinfo, struct sockaddr_storage* localaddr, 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 */ /* */ /* peerinfo (IN) the local address */ /* */ /* msg (IN) the message to log */ /* */ /* Returns: none */ /*=========================================================================*/ { SLPMessage msg; char addr_str[INET6_ADDRSTRLEN]; 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 (!SLPNetIsLocal(peerinfo) && 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,localaddr,buf,msg) == 0) { SLPDLogMessageInternals(msg); } else { SLPDLog("Message parsing failed\n"); SLPDLog("Peer: \n"); SLPDLog(" IP address: %s\n", SLPNetSockAddrStorageToString(&(msg->peer), addr_str, sizeof(addr_str))); } SLPMessageFree(msg); } } } }
/*=========================================================================*/ void SLPDLogMessageInternals(SLPMessage message) /*=========================================================================*/ { char addr_str[INET6_ADDRSTRLEN]; SLPDLog("Peer: \n"); SLPDLog(" IP address: %s\n", SLPNetSockAddrStorageToString(&(message->peer), addr_str, sizeof(addr_str))); SLPDLog("Header:\n"); SLPDLog(" version = %i\n",message->header.version); SLPDLog(" functionid = %i\n",message->header.functionid); SLPDLog(" length = %i\n",message->header.length); SLPDLog(" flags = %i\n",message->header.flags); SLPDLog(" extoffset = %i\n",message->header.extoffset); SLPDLog(" xid = %i\n",message->header.xid); SLPDLogBuffer(" langtag = ", message->header.langtaglen, message->header.langtag); switch (message->header.functionid) { case SLP_FUNCT_SRVRQST: SLPDLogSrvRqstMessage(&(message->body.srvrqst)); break; case SLP_FUNCT_SRVRPLY: SLPDLogSrvRplyMessage(&(message->body.srvrply)); break; case SLP_FUNCT_SRVREG: SLPDLogSrvRegMessage(&(message->body.srvreg)); break; case SLP_FUNCT_SRVDEREG: SLPDLogSrvDeRegMessage(&(message->body.srvdereg)); break; case SLP_FUNCT_SRVACK: SLPDLogSrvAckMessage(&(message->body.srvack)); break; case SLP_FUNCT_ATTRRQST: SLPDLogAttrRqstMessage(&(message->body.attrrqst)); break; case SLP_FUNCT_ATTRRPLY: SLPDLogAttrRplyMessage(&(message->body.attrrply)); break; case SLP_FUNCT_DAADVERT: SLPDLogDAAdvertMessage(&(message->body.daadvert)); break; case SLP_FUNCT_SRVTYPERQST: SLPDLogSrvTypeRqstMessage(&(message->body.srvtyperqst)); break; case SLP_FUNCT_SRVTYPERPLY: SLPDLogSrvTypeRplyMessage(&(message->body.srvtyperply)); break; case SLP_FUNCT_SAADVERT: SLPDLogSAAdvertMessage(&(message->body.saadvert)); break; default: SLPDLog("Message %i UNKNOWN:\n",message->header.functionid); SLPDLog(" This is really bad\n"); break; } }
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 }
/** 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 main(int argc, char * argv[]) { int i; int addrscount = 10; struct sockaddr_storage addrs[10]; SLPIfaceInfo ifaceinfo; char * addrstr; #ifdef _WIN32 WSADATA wsadata; WSAStartup(MAKEWORD(2, 2), &wsadata); #endif if (SLPIfaceGetInfo(0, &ifaceinfo, AF_INET) == 0) for (i = 0; i < ifaceinfo.iface_count; i++) { char myname[MAX_HOST_NAME]; SLPNetSockAddrStorageToString(&ifaceinfo.iface_addr[i], myname, sizeof(myname)); printf("v4 found iface = %s\n", myname); SLPNetSockAddrStorageToString(&ifaceinfo.bcast_addr[i], myname, sizeof(myname)); printf("v4 bcast addr = %s\n", myname); } if (SLPIfaceGetInfo(0, &ifaceinfo, AF_INET6) == 0) { for (i = 0; i < ifaceinfo.iface_count; i++) { char myname[MAX_HOST_NAME]; SLPNetSockAddrStorageToString(&ifaceinfo.iface_addr[i], myname, sizeof(myname)); printf("v6 found iface = %s\n", myname); } for (i = 0; i < ifaceinfo.bcast_count; i++) { char myname[MAX_HOST_NAME]; SLPNetSockAddrStorageToString(&ifaceinfo.bcast_addr[i], myname, sizeof(myname)); printf("v6 bcast addr = %s\n", myname); } } SLPIfaceGetInfo("fec0:0:0:0001:0:0:0:3,5:6::7,10.0.25.82", &ifaceinfo, AF_INET6); SLPIfaceGetInfo("fec0:0:0:0001:0:0:0:3,5:6::7,10.0.25.82", &ifaceinfo, AF_INET); if (SLPIfaceStringToSockaddrs("192.168.100.1,192.168.101.1", addrs, &addrscount) == 0) if (SLPIfaceSockaddrsToString(addrs, addrscount, &addrstr) == 0) { printf("sock addr string v4 = %s\n", addrstr); xfree(addrstr); } if (SLPIfaceStringToSockaddrs("1:2:0:0:0::4,10:0:0:0:0:0:0:11", addrs, &addrscount) == 0) if (SLPIfaceSockaddrsToString(addrs, addrscount, &addrstr) == 0) { printf("sock addr string v6 = %s\n", addrstr); xfree(addrstr); } #ifdef _WIN32 WSACleanup(); #endif }
/** Reconnect an outbound socket. * * @param[in] socklist - The list of sockets being monitored. * @param[in] sock - The socket to be reconnected. */ void OutgoingStreamReconnect(SLPList * socklist, SLPDSocket * sock) { char addr_str[INET6_ADDRSTRLEN]; (void)socklist; /*-----------------------------------------------------------------*/ /* If socket is already being reconnected but is reconnect blocked */ /* just return. Blocking connect sockets will eventually time out */ /*-----------------------------------------------------------------*/ if (sock->state == STREAM_CONNECT_BLOCK) return; #ifdef DEBUG /* Log that reconnect warning */ SLPDLog("WARNING: Reconnect to agent at %s. " "Agent may not be making efficient \n" " use of TCP.\n", SLPNetSockAddrStorageToString(&sock->peeraddr, addr_str, sizeof(addr_str))); #endif /*----------------------------------------------------------------*/ /* Make sure we have not reconnected too many times */ /* We only allow SLPD_CONFIG_MAX_RECONN reconnection retries */ /* before we stop */ /*----------------------------------------------------------------*/ sock->reconns += 1; if (sock->reconns > SLPD_CONFIG_MAX_RECONN) { SLPDLog("WARNING: Reconnect tries to agent at %s " "exceeded maximum. It\n is possible that " "the agent is malicious. Check it out!\n", SLPNetSockAddrStorageToString(&sock->peeraddr, addr_str, sizeof(addr_str))); /*Since we can't connect, remove it as a DA*/ SLPDKnownDARemove(&(sock->peeraddr)); sock->state = SOCKET_CLOSE; return; } /*----------------------------------------------------------------*/ /* Close the existing socket to clean the stream and open an new */ /* socket */ /*----------------------------------------------------------------*/ closesocket(sock->fd); if (sock->peeraddr.ss_family == AF_INET) sock->fd = socket(PF_INET, SOCK_STREAM, 0); else if (sock->peeraddr.ss_family == AF_INET6) sock->fd = socket(PF_INET6, SOCK_STREAM, 0); if (sock->fd == SLP_INVALID_SOCKET) { sock->state = SOCKET_CLOSE; return; } /*---------------------------------------------*/ /* Set the new socket to enable nonblocking IO */ /*---------------------------------------------*/ #ifdef _WIN32 { u_long fdflags = 1; ioctlsocket(sock->fd, FIONBIO, &fdflags); } #else { int fdflags = fcntl(sock->fd, F_GETFL, 0); fcntl(sock->fd, F_SETFL, fdflags | O_NONBLOCK); } #endif /*--------------------------*/ /* Connect a the new socket */ /*--------------------------*/ if (connect(sock->fd, (struct sockaddr *)&sock->peeraddr, sizeof(struct sockaddr_storage))) { #ifdef _WIN32 if (WSAEWOULDBLOCK == WSAGetLastError()) #else if (errno == EINPROGRESS) #endif { /* Connect blocked */ sock->state = STREAM_CONNECT_BLOCK; return; } } /* Connection occured immediately. Set to WRITE_FIRST so whole */ /* packet will be written */ sock->state = STREAM_WRITE_FIRST; }
/** Resend messages on sockets whose timeout has expired * * @param[in] seconds - The number of seconds old a socket must be to have * its messages resent. * * @remarks - Ideally, this would be at a resolution lower than one second, * but given the default timeout values, this isn't too far off the mark, and * should not add too much of a burden to the main loop. */ void SLPDOutgoingRetry(time_t seconds) { SLPDSocket * del = 0; SLPDSocket * sock = (SLPDSocket *) G_OutgoingSocketList.head; if(seconds <= 0) return; while (sock) { switch (sock->state) { case DATAGRAM_UNICAST: if(0 == sock->sendlist.count) /*Clean up as fast as we can, as all messages were sent*/ del = sock; else { sock->age += seconds; if(sock->age >= G_SlpdProperty.unicastTimeouts[sock->reconns] / 1000) { ++sock->reconns; if(sock->reconns >= MAX_RETRANSMITS) { char addr_str[INET6_ADDRSTRLEN]; SLPDLog("SLPD: Didn't receive response from DA at %s, removing it from list.\n", SLPNetSockAddrStorageToString(&sock->peeraddr, addr_str, sizeof(addr_str))); SLPDKnownDARemove(&(sock->peeraddr)); del = sock; } else { SLPBuffer pbuf; sock->age = 0; for(pbuf = (SLPBuffer) sock->sendlist.head; pbuf; pbuf = (SLPBuffer) pbuf->listitem.next) SLPDOutgoingDatagramWrite(sock, pbuf); } } } break; case DATAGRAM_MULTICAST: case DATAGRAM_BROADCAST: case STREAM_READ_FIRST: case STREAM_WRITE_FIRST: case STREAM_CONNECT_BLOCK: case STREAM_READ: case STREAM_WRITE: case STREAM_CONNECT_IDLE: case STREAM_WRITE_WAIT: default: break; } sock = (SLPDSocket *) sock->listitem.next; if (del) { SLPDSocketFree((SLPDSocket *) SLPListUnlink(&G_OutgoingSocketList, (SLPListItem *) del)); del = 0; } } }
/** Read an inbound datagram. * * @param[in] socklist - The list of monitored sockets. * @param[in] sock - The socket to be read. * * @internal */ static void IncomingDatagramRead(SLPList * socklist, SLPDSocket * sock) { int bytesread; int byteswritten; socklen_t peeraddrlen = sizeof(struct sockaddr_storage); char addr_str[INET6_ADDRSTRLEN]; sockfd_t sendsock = SLP_INVALID_SOCKET; (void)socklist; bytesread = recvfrom(sock->fd, (char*)sock->recvbuf->start, G_SlpdProperty.MTU, 0, (struct sockaddr *)&sock->peeraddr, &peeraddrlen); if (bytesread > 0) { sock->recvbuf->end = sock->recvbuf->start + bytesread; if (!sock->sendbuf) /* Some of the error handling code expects a sendbuf to be available * to be emptied, so make sure there is at least a minimal buffer */ sock->sendbuf = SLPBufferAlloc(1); switch (SLPDProcessMessage(&sock->peeraddr, &sock->localaddr, sock->recvbuf, &sock->sendbuf, 0)) { case SLP_ERROR_PARSE_ERROR: case SLP_ERROR_VER_NOT_SUPPORTED: case SLP_ERROR_MESSAGE_NOT_SUPPORTED: break; default: #ifdef DARWIN /* If the socket is a multicast socket, find the designated UDP output socket for sending */ if (sock->state == DATAGRAM_MULTICAST) if ((sendsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != SLP_INVALID_SOCKET) SLPNetworkSetSndRcvBuf(sendsock); #endif if (sendsock == SLP_INVALID_SOCKET) sendsock = sock->fd; /* check to see if we should send anything, breaking up individual packets in the buffer into different sendto calls (should only be an issue with the loopback DA response)*/ if (sock->sendbuf) { sock->sendbuf->curpos = sock->sendbuf->start; while (sock->sendbuf->curpos < sock->sendbuf->end) { int packetbytes = AS_UINT24(sock->sendbuf->curpos + 2); byteswritten = sendto(sendsock, (char*)sock->sendbuf->curpos, packetbytes, 0, (struct sockaddr *)&sock->peeraddr, SLPNetAddrLen(&sock->peeraddr)); if (byteswritten != packetbytes) { /* May be an overflow reply */ int flags = AS_UINT16(sock->sendbuf->curpos + 5); if ((byteswritten == -1) && #ifdef _WIN32 (WSAGetLastError() == WSAEMSGSIZE) && #else (errno == EMSGSIZE) && #endif (flags & SLP_FLAG_OVERFLOW)) { int byteswrittenmax = sendto(sendsock, (char*)sock->sendbuf->curpos, G_SlpdProperty.MTU, 0, (struct sockaddr *)&sock->peeraddr, SLPNetAddrLen(&sock->peeraddr)); if (byteswrittenmax == G_SlpdProperty.MTU) byteswritten = packetbytes; } } if (byteswritten != packetbytes) SLPDLog("NETWORK_ERROR - %d replying %s\n", errno, SLPNetSockAddrStorageToString(&(sock->peeraddr), addr_str, sizeof(addr_str))); sock->sendbuf->curpos += packetbytes; } /* Only close if we allocated a new socket */ if (sendsock != sock->fd) closesocket(sendsock); } break; } } }