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 bool decodeIpv4(const std::string& addr,
00087                 unsigned int&      p1,
00088                 unsigned int&      p2,
00089                 unsigned int&      p3,
00090                 unsigned int&      p4)
00091 {
00092     if (addr.empty() ||
00093         4 != sscanf(addr.c_str(), "%3u.%3u.%3u.%3u",
00094                     &p1, &p2, &p3, &p4) ||
00095         (p1 > 255 || p2 > 255 || p3 > 255 || p4 > 255)) {
00096         fprintf(stderr, "Unable to decode \"%s\" as IPV4 dotted-quad \n",
00097                         addr.c_str());
00098         fflush(stderr);
00099         return false;
00100     }
00101     return true;
00102 }
00103 
00104 }; // anonymous
00105 
00106 using namespace crl::multisense;
00107 
00108 int main(int    argc,
00109          char **argvPP)
00110 {
00111     std::string currentAddress = "10.66.171.21";
00112     std::string desiredAddress = "10.66.171.21";
00113     std::string desiredGateway = "10.66.171.1";
00114     std::string desiredNetmask = "255.255.240.0";
00115     std::string iface = "eth0";
00116     bool        blind=false;
00117     bool        prompt=true;
00118 
00119     //
00120     // Parse args
00121 
00122     int c;
00123 
00124     while(-1 != (c = getopt(argc, argvPP, "a:A:G:N:b:y")))
00125         switch(c) {
00126         case 'a': currentAddress = std::string(optarg);    break;
00127         case 'A': desiredAddress = std::string(optarg);    break;
00128         case 'G': desiredGateway = std::string(optarg);    break;
00129         case 'N': desiredNetmask = std::string(optarg);    break;
00130         case 'b': blind = true; iface = std::string(optarg); break;
00131         case 'y': prompt         = false;                  break;
00132         default: usage(*argvPP);                           break;
00133         }
00134 
00135     Status status;
00136     Channel *channelP = NULL;
00137     int sockfd = -1;
00138 
00139     system::DeviceInfo deviceInfo;
00140 
00141     uint32_t a1 = 0;
00142     uint32_t a2 = 0;
00143     uint32_t a3 = 0;
00144     uint32_t a4 = 0;
00145 
00146     if (!decodeIpv4(desiredAddress, a1, a2, a3, a4))
00147     {
00148         goto clean_out;
00149     }
00150 
00151 
00152     if(!blind)
00153     {
00154         //
00155         // Initialize communications.
00156 
00157         channelP = Channel::Create(currentAddress);
00158         if (NULL == channelP) {
00159         fprintf(stderr, "Failed to establish communications with \"%s\"\n",
00160             currentAddress.c_str());
00161         return -1;
00162         }
00163 
00164         //
00165         // Query version
00166 
00167         VersionType version;
00168 
00169         status = channelP->getSensorVersion(version);
00170         if (Status_Ok != status) {
00171             fprintf(stderr, "failed to query sensor version: %s\n",
00172                     Channel::statusString(status));
00173             goto clean_out;
00174         }
00175 
00176         status = channelP->getDeviceInfo(deviceInfo);
00177 
00178         if (Status_Ok != status) {
00179             fprintf(stderr, "failed to query device info %s\n",
00180                     Channel::statusString(status));
00181             goto clean_out;
00182         }
00183 
00184         if (deviceInfo.hardwareRevision == system::DeviceInfo::HARDWARE_REV_MULTISENSE_SL &&
00185             192 == a1  && 168 == a2 && 0 == a3)
00186         {
00187             fprintf(stderr, "MultiSense SL units use the 192.168.0 subnet to talk to the Hokuyo ");
00188             fprintf(stderr, "laser. Setting the IP address of the MultiSense to 192.168.0.X will ");
00189             fprintf(stderr, "interfere with the networking configuration.\n");
00190             fprintf(stderr, "\n");
00191             fprintf(stderr, "Aborting IP Change.\n");
00192             fflush(stderr);
00193             goto clean_out;
00194         }
00195     }
00196     else
00197     {
00198 #ifdef WIN32
00199         perror ("broadcast is not yet supported on Windows");
00200         goto clean_out;
00201 #else
00202         int broadcast=1;
00203 
00204         if (192 == a1  && 168 == a2 && 0 == a3)
00205         {
00206             fprintf(stderr, "MultiSense SL units use the 192.168.0 subnet to talk to the Hokuyo ");
00207             fprintf(stderr, "laser. Setting the IP address of the MultiSense to 192.168.0.X will ");
00208             fprintf(stderr, "interfere with the networking configuration.  This unit may be a ");
00209             fprintf(stderr, "MultiSense SL as in broadcast mode this tool cannot query the device.\n");
00210             fprintf(stderr, "\n");
00211             fprintf(stderr, "Aborting IP Change.\n");
00212             fflush(stderr);
00213             goto clean_out;
00214         }
00215 
00216         // create UDP socket
00217         sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00218         if(sockfd == -1) {
00219             perror("socket() failed");
00220             goto clean_out;
00221         }
00222 
00223         // enable support for sending to broadcast address
00224         if (setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,reinterpret_cast<char const*>(&broadcast),sizeof(broadcast))==-1) {
00225             perror("setsockopt(...SO_BROADCAST) failed");
00226             goto clean_out;
00227         }
00228 
00229         // bind to a specific interface so broadcast packet goes to the right place
00230         // note: on most systems, this will require elevated privileges
00231         if (setsockopt(sockfd,SOL_SOCKET,SO_BINDTODEVICE,iface.c_str(),iface.size()+1)==-1) {
00232             perror("setsockopt(...SO_BINDTODEVICE) failed (are you root?)");
00233             goto clean_out;
00234         }
00235 #endif
00236     }
00237 
00238     if(prompt)
00239     {
00240 
00241         fprintf(stdout, "NEW address: %s\n", desiredAddress.c_str());
00242         fprintf(stdout, "NEW gateway: %s\n", desiredGateway.c_str());
00243         fprintf(stdout, "NEW netmask: %s\n\n", desiredNetmask.c_str());
00244 
00245         if(blind) {
00246             fprintf(stdout, "** WARNING: All MultiSense devices attached to interface '%s' will have their addresses changed **\n\n", iface.c_str());
00247         }
00248 
00249         fprintf(stdout, "Really update network configuration? (y/n): ");
00250         fflush(stdout);
00251 
00252         int c = getchar();
00253         if ('Y' != c && 'y' != c) {
00254             fprintf(stdout, "Aborting\n");
00255             goto clean_out;
00256         }
00257     }
00258 
00259     if(!blind)
00260     {
00261         //
00262         // Try setting the new IP parameters. The device will
00263         // verify that the IP addresses are valid dotted-quads,
00264         // however, little complex verification is done.
00265 
00266         status = channelP->setNetworkConfig(system::NetworkConfig(desiredAddress,
00267                                                                   desiredGateway,
00268                                                                   desiredNetmask));
00269         if (Status_Ok != status)
00270             fprintf(stderr, "Failed to set the network configuration: %s\n",
00271                     Channel::statusString(status));
00272         else
00273             fprintf(stdout, "Network parameters changed successfully\n");
00274     }
00275     else
00276     {
00277 #ifndef WIN32
00278         struct sockaddr_in si;
00279 
00280         // construct destination address
00281         memset(&si,0,sizeof(si));
00282         si.sin_family = AF_INET;
00283         si.sin_port = htons(9001);
00284         si.sin_addr.s_addr = htonl(INADDR_BROADCAST);
00285 
00286         // manually construct SysNetwork message
00287         using namespace crl::multisense::details;
00288         utility::BufferStreamWriter buffer(256);
00289         wire::Header & header = *(reinterpret_cast<wire::Header*>(buffer.data()));
00290 
00291         // hide header area
00292         buffer.seek(sizeof(wire::Header));
00293 
00294         // set ID and version
00295         const wire::IdType      id      = wire::SysNetwork::ID;
00296         const wire::VersionType version = wire::SysNetwork::VERSION;
00297         buffer & id;
00298         buffer & version;
00299 
00300         // construct message
00301         wire::SysNetwork msg(desiredAddress,desiredGateway,desiredNetmask);
00302         msg.serialize(buffer,version);
00303 
00304         // install header
00305         header.magic              = wire::HEADER_MAGIC;
00306         header.version            = wire::HEADER_VERSION;
00307         header.group              = wire::HEADER_GROUP;
00308         header.flags              = 0;
00309         header.sequenceIdentifier = 0;
00310         header.messageLength      = buffer.tell() - sizeof(wire::Header);
00311         header.byteOffset         = 0;
00312 
00313         // send packet
00314         if(sendto(sockfd,reinterpret_cast<char const*>(buffer.data()),buffer.tell(),0,reinterpret_cast<sockaddr*>(&si),sizeof(si)) == -1) {
00315             perror("sendto() failed");
00316             goto clean_out;
00317         }
00318 
00319         fprintf(stdout, "Successfully transmitted network parameter change command\n");
00320 #endif
00321     }
00322 
00323 clean_out:
00324 
00325     if(channelP)
00326         Channel::Destroy(channelP);
00327     if(sockfd != -1)
00328 #ifdef WIN32
00329         closesocket(sockfd);
00330 #else
00331         close(sockfd);
00332 #endif
00333 
00334     return 0;
00335 }


multisense_lib
Author(s):
autogenerated on Mon Oct 9 2017 03:06:21