ChangeIpUtility.cc
Go to the documentation of this file.
00001 
00037 #ifdef WIN32
00038 #ifndef WIN32_LEAN_AND_MEAN
00039 #define WIN32_LEAN_AND_MEAN 1
00040 #endif
00041 
00042 #include <windows.h>
00043 #include <winsock2.h>
00044 #else
00045 #include <unistd.h>
00046 #include <netdb.h>
00047 #include <sys/socket.h>
00048 #include <netinet/in.h>
00049 #include <arpa/inet.h>
00050 #endif
00051 
00052 #include <stdio.h>
00053 #include <stdlib.h>
00054 #include <string>
00055 
00056 #include <errno.h>
00057 #include <string.h>
00058 
00059 #include <LibMultiSense/details/utility/Portability.hh>
00060 #include <LibMultiSense/MultiSenseChannel.hh>
00061 
00062 #include <LibMultiSense/details/utility/BufferStream.hh>
00063 #include <LibMultiSense/details/wire/Protocol.h>
00064 #include <LibMultiSense/details/wire/SysNetworkMessage.h>
00065 
00066 #include <Utilities/portability/getopt/getopt.h>
00067 
00068 namespace {  // anonymous
00069 
00070 void usage(const char *programNameP) 
00071 {
00072     fprintf(stderr, "USAGE: %s [<options>]\n", programNameP);
00073     fprintf(stderr, "Where <options> are:\n");
00074     fprintf(stderr, "\t-a <current_address>    : CURRENT IPV4 address (default=10.66.171.21)\n");
00075     fprintf(stderr, "\t-A <new_address>        : NEW IPV4 address     (default=10.66.171.21)\n");
00076     fprintf(stderr, "\t-G <new_gateway>        : NEW IPV4 gateway     (default=10.66.171.1)\n");
00077     fprintf(stderr, "\t-N <new_netmask>        : NEW IPV4 address     (default=255.255.240.0)\n");
00078 #ifndef WIN32
00079     fprintf(stderr, "\t-b <interface>          : send broadcast packet to specified network interface (requires root)\n");
00080 #endif
00081     fprintf(stderr, "\t-y                      : disable confirmation prompt\n");
00082     
00083     exit(-1);
00084 }
00085 
00086 }; // anonymous
00087 
00088 using namespace crl::multisense;
00089 
00090 int main(int    argc, 
00091          char **argvPP)
00092 {
00093     std::string currentAddress = "10.66.171.21";
00094     std::string desiredAddress = "10.66.171.21";
00095     std::string desiredGateway = "10.66.171.1";
00096     std::string desiredNetmask = "255.255.240.0";
00097     std::string iface = "eth0";
00098     bool        blind=false;
00099     bool        prompt=true;
00100 
00101     //
00102     // Parse args
00103 
00104     int c;
00105 
00106     while(-1 != (c = getopt(argc, argvPP, "a:A:G:N:b:y")))
00107         switch(c) {
00108         case 'a': currentAddress = std::string(optarg);    break;
00109         case 'A': desiredAddress = std::string(optarg);    break;
00110         case 'G': desiredGateway = std::string(optarg);    break;
00111         case 'N': desiredNetmask = std::string(optarg);    break;
00112         case 'b': blind = true; iface = std::string(optarg); break;
00113         case 'y': prompt         = false;                  break;
00114         default: usage(*argvPP);                           break;
00115         }
00116 
00117     Status status;
00118     Channel *channelP = NULL;
00119     int sockfd = -1;
00120 
00121     if(!blind)
00122     {
00123         //
00124         // Initialize communications.
00125 
00126         channelP = Channel::Create(currentAddress);
00127         if (NULL == channelP) {
00128         fprintf(stderr, "Failed to establish communications with \"%s\"\n",
00129             currentAddress.c_str());
00130         return -1;
00131         }
00132 
00133         //
00134         // Query version
00135 
00136         VersionType version;
00137 
00138         status = channelP->getSensorVersion(version);
00139         if (Status_Ok != status) {
00140             fprintf(stderr, "failed to query sensor version: %s\n",
00141                     Channel::statusString(status));
00142             goto clean_out;
00143         }
00144     }
00145     else
00146     {
00147 #ifdef WIN32
00148         perror ("broadcast is not yet supported on Windows");
00149         goto clean_out;
00150 #else
00151         int broadcast=1;
00152 
00153         // create UDP socket
00154         sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00155         if(sockfd == -1) {
00156             perror("socket() failed");
00157             goto clean_out;
00158         }
00159 
00160         // enable support for sending to broadcast address
00161         if (setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,reinterpret_cast<char const*>(&broadcast),sizeof(broadcast))==-1) {
00162             perror("setsockopt(...SO_BROADCAST) failed");
00163             goto clean_out;
00164         }
00165         
00166         // bind to a specific interface so broadcast packet goes to the right place
00167         // note: on most systems, this will require elevated privileges
00168         if (setsockopt(sockfd,SOL_SOCKET,SO_BINDTODEVICE,iface.c_str(),iface.size()+1)==-1) {
00169             perror("setsockopt(...SO_BINDTODEVICE) failed (are you root?)");
00170             goto clean_out;
00171         }
00172 #endif
00173     }
00174     
00175     if(prompt)
00176     {
00177         fprintf(stdout, "NEW address: %s\n", desiredAddress.c_str());
00178         fprintf(stdout, "NEW gateway: %s\n", desiredGateway.c_str());
00179         fprintf(stdout, "NEW netmask: %s\n\n", desiredNetmask.c_str());
00180 
00181         if(blind) {
00182             fprintf(stdout, "** WARNING: All MultiSense devices attached to interface '%s' will have their addresses changed **\n\n", iface.c_str());
00183         }
00184 
00185         fprintf(stdout, "Really update network configuration? (y/n): ");
00186         fflush(stdout);
00187 
00188         int c = getchar();
00189         if ('Y' != c && 'y' != c) {
00190             fprintf(stdout, "Aborting\n");
00191             goto clean_out;
00192         }
00193     }
00194 
00195     if(!blind)
00196     {
00197         //
00198         // Try setting the new IP parameters. The device will
00199         // verify that the IP addresses are valid dotted-quads,
00200         // however, little complex verification is done.
00201 
00202         status = channelP->setNetworkConfig(system::NetworkConfig(desiredAddress,
00203                                                                   desiredGateway,
00204                                                                   desiredNetmask));
00205         if (Status_Ok != status)
00206             fprintf(stderr, "Failed to set the network configuration: %s\n",
00207                     Channel::statusString(status));
00208         else 
00209             fprintf(stdout, "Network parameters changed successfully\n");
00210     }
00211     else
00212     {
00213 #ifndef WIN32
00214         struct sockaddr_in si;
00215 
00216         // construct destination address
00217         memset(&si,0,sizeof(si));
00218         si.sin_family = AF_INET;
00219         si.sin_port = htons(9001);
00220         si.sin_addr.s_addr = htonl(INADDR_BROADCAST);
00221 
00222         // manually construct SysNetwork message
00223         using namespace crl::multisense::details;
00224         utility::BufferStreamWriter buffer(256);
00225         wire::Header & header = *(reinterpret_cast<wire::Header*>(buffer.data()));
00226 
00227         // hide header area
00228         buffer.seek(sizeof(wire::Header));
00229 
00230         // set ID and version
00231         const wire::IdType      id      = wire::SysNetwork::ID;
00232         const wire::VersionType version = wire::SysNetwork::VERSION;
00233         buffer & id;
00234         buffer & version;
00235 
00236         // construct message
00237         wire::SysNetwork msg(desiredAddress,desiredGateway,desiredNetmask);
00238         msg.serialize(buffer,version);
00239 
00240         // install header
00241         header.magic              = wire::HEADER_MAGIC;
00242         header.version            = wire::HEADER_VERSION;
00243         header.group              = wire::HEADER_GROUP;
00244         header.flags              = 0;
00245         header.sequenceIdentifier = 0;
00246         header.messageLength      = buffer.tell() - sizeof(wire::Header);
00247         header.byteOffset         = 0;
00248 
00249         // send packet
00250         if(sendto(sockfd,reinterpret_cast<char const*>(buffer.data()),buffer.tell(),0,reinterpret_cast<sockaddr*>(&si),sizeof(si)) == -1) {
00251             perror("sendto() failed");
00252             goto clean_out;
00253         }
00254 
00255         fprintf(stdout, "Successfully transmitted network parameter change command\n");
00256 #endif
00257     }
00258 
00259 clean_out:
00260 
00261     if(channelP)
00262         Channel::Destroy(channelP);
00263     if(sockfd != -1)
00264 #ifdef WIN32
00265         closesocket(sockfd);
00266 #else
00267         close(sockfd);
00268 #endif
00269 
00270     return 0;
00271 }


multisense_lib
Author(s):
autogenerated on Thu Aug 27 2015 14:01:11