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 {
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 };
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
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
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
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
00217 sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00218 if(sockfd == -1) {
00219 perror("socket() failed");
00220 goto clean_out;
00221 }
00222
00223
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
00230
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
00263
00264
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
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
00287 using namespace crl::multisense::details;
00288 utility::BufferStreamWriter buffer(256);
00289 wire::Header & header = *(reinterpret_cast<wire::Header*>(buffer.data()));
00290
00291
00292 buffer.seek(sizeof(wire::Header));
00293
00294
00295 const wire::IdType id = wire::SysNetwork::ID;
00296 const wire::VersionType version = wire::SysNetwork::VERSION;
00297 buffer & id;
00298 buffer & version;
00299
00300
00301 wire::SysNetwork msg(desiredAddress,desiredGateway,desiredNetmask);
00302 msg.serialize(buffer,version);
00303
00304
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
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 }