/********************************************************************** * * Copyright 2001, Lantronix * * All rights reserved, The contents of this file may not be used * and/or copied in any form or by any means without the written * permission of Lantronix. * * Finds all CoBox / UDSs on the attached subnets. For use with * Linux and WIN32 systems. **********************************************************************/ #include #include #include #include #ifdef linux #include #include #include #include #include typedef struct ifreq LTX_INTERFACE_INFO; typedef int LTX_SOCKET; void closesocket(LTX_SOCKET); #else #include #include typedef INTERFACE_INFO LTX_INTERFACE_INFO; typedef SOCKET LTX_SOCKET; #endif /* linux */ #define COBOX_UDP_PORT 0x77fe /* CoBox UDP config port 30718 */ #define UDS_CONF_QUERY 0xf8 /* LTX code to get cobox setup record */ #define UDP_BUF_SIZE 512 #define MAX_INTERFACES 10 long interface_up(LTX_SOCKET, struct sockaddr_in *, LTX_INTERFACE_INFO *); int main(int argc, char **argv) { // static unsigned char reqt[] = { 0x00,0x00,0x00,UDS_CONF_QUERY }; unsigned char reqt[18]; unsigned char buf[UDP_BUF_SIZE]; int i, len, n, timeout; unsigned long br = 0; LTX_SOCKET sock; LTX_INTERFACE_INFO ifo[MAX_INTERFACES]; struct sockaddr_in peer; fd_set rfds, efds; struct timeval timev; #ifdef linux struct ifconf if_conf; #else WSADATA info; #endif /* linux */ memset(reqt, 0, sizeof(reqt)); reqt[3] = UDS_CONF_QUERY; #ifdef WIN32 /* start up winsock */ if ((i = WSAStartup(MAKEWORD(1,1), &info)) < 0 ) { fprintf(stderr, "Error on WSAStartup(), error (%d)\n", i); return(i); } #endif /* WIN32 */ /* open a socket */ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { fprintf(stderr, "Could not open socket\n"); return(0); } /* It's a good idea to bind this socket to a local port number */ peer.sin_family = AF_INET; peer.sin_addr.s_addr = INADDR_ANY; peer.sin_port = 0; if (bind(sock, (struct sockaddr *) &peer, sizeof(peer))) { fprintf(stderr, "Error binding socket\n"); closesocket(sock); return(0); } #ifdef linux /* Set socket to allow broadcasting */ i = 1; if (( setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (void *)&i, sizeof(i))) < 0) { fprintf(stderr, "Failure to set SO_BROADCAST.\n"); closesocket(sock); return(0); } #endif /* Grab all the network interfaces */ #ifdef WIN32 memset(&ifo[0], 0, sizeof(ifo)); if ((WSAIoctl(sock, SIO_GET_INTERFACE_LIST, NULL, 0, &ifo[0], sizeof(ifo), &br, NULL, NULL)) != 0) { fprintf(stderr, "Get SIO_GET_INTERFACE_LIST error (%d)\n", (WSAGetLastError())); return(WSAGetLastError()); } #else if_conf.ifc_len = (sizeof (struct ifreq)) * MAX_INTERFACES; if_conf.ifc_buf = (char *) &ifo[0]; if ((ioctl(sock, SIOCGIFCONF, &if_conf)) == -1) { fprintf(stderr, "Failure SIOCGIFCONF.\n"); closesocket(sock); return(0); } br = if_conf.ifc_len; #endif /* WIN32 */ /* Query each network */ for (i = 0; i < (int)(br / sizeof(LTX_INTERFACE_INFO)); i++) { if (interface_up(sock, &peer, &ifo[i])) { // fprintf(stderr, "sendto %s port 0x%x family 0x%x\n", // inet_ntoa(peer.sin_addr), ntohs(peer.sin_port), // peer.sin_family); if ((n = sendto(sock, reqt, sizeof(reqt), 0, (struct sockaddr *) &peer, sizeof(struct sockaddr_in))) <= 0) { fprintf(stderr, "sendto (%s) failed!\n", inet_ntoa(peer.sin_addr)); } } else { // fprintf(stderr, "skipping interface %s\n", inet_ntoa(peer.sin_addr)); } } /* We've sent the queries, now see if anyone responded */ n = 0; while(1){ FD_ZERO(&rfds); FD_ZERO(&efds); FD_SET(sock, &rfds); FD_SET(sock, &efds); timev.tv_sec = 3; //three second timeout timev.tv_usec = 0; timeout = select(FD_SETSIZE, &rfds, (fd_set *) NULL, &efds, &timev); if (timeout == -1) { // fprintf(stderr, "OS interrupt during select - ignore\n"); continue; } else if (timeout == 0) { // fprintf(stderr, "Real timeout\n"); break; } else if (FD_ISSET(sock, &efds)) { fprintf(stderr, "Bad news, exception on socket\n"); break; } else if (FD_ISSET(sock, &rfds)) { memset(buf, 0, sizeof(buf)); len = sizeof(struct sockaddr_in); if ( recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &peer, &len) > 0) { printf("cobox %02d: at %s\n", ++n, inet_ntoa(peer.sin_addr)); } } } printf("\nDONE\n"); closesocket(sock); #ifdef WIN32 WSACleanup(); #endif return 0; } long interface_up(sock, peer, ifo) LTX_SOCKET sock; struct sockaddr_in *peer; LTX_INTERFACE_INFO *ifo; { #ifdef WIN32 peer->sin_addr.s_addr = ifo->iiAddress.AddressIn.sin_addr.s_addr; if ( (ifo->iiAddress.AddressIn.sin_addr.S_un.S_addr != 0) && ((ifo->iiFlags & IFF_LOOPBACK) == 0) && ((ifo->iiFlags & (IFF_UP | IFF_BROADCAST)) == (IFF_UP | IFF_BROADCAST)) ) { /* The iiBroadcastAddress field is bogus, so do it manually */ peer->sin_addr.s_addr = ifo->iiAddress.AddressIn.sin_addr.s_addr & ifo->iiNetmask.AddressIn.sin_addr.s_addr; peer->sin_addr.s_addr |= ~(ifo->iiNetmask.AddressIn.sin_addr.s_addr); peer->sin_port = htons(COBOX_UDP_PORT); peer->sin_family = AF_INET; return(1); } #else struct sockaddr_in *sptr; if ((ioctl(sock, SIOCGIFFLAGS, ifo)) != 0) { fprintf(stderr, "SIOCGIFFLAGS ioctl failed\n"); closesocket(sock); return(0); } if ( ((ifo->ifr_flags & IFF_LOOPBACK) == 0) && ((ifo->ifr_flags & (IFF_UP | IFF_BROADCAST)) == (IFF_UP | IFF_BROADCAST)) ) { if ((ioctl(sock, SIOCGIFBRDADDR, ifo)) != 0) { fprintf(stderr, "SIOCGIFBRDADDR ioctl failed\n"); closesocket(sock); return(0); } memcpy((void *) peer, (void *) &ifo->ifr_broadaddr, sizeof(struct sockaddr_in)); peer->sin_port = htons(COBOX_UDP_PORT); peer->sin_family = AF_INET; return(1); } #endif /* WIN32 */ return(0); } #ifdef linux void closesocket(sock) LTX_SOCKET sock; { shutdown(sock, 2); close(sock); } #endif