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 };
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
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
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
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
00154 sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00155 if(sockfd == -1) {
00156 perror("socket() failed");
00157 goto clean_out;
00158 }
00159
00160
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
00167
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
00199
00200
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
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
00223 using namespace crl::multisense::details;
00224 utility::BufferStreamWriter buffer(256);
00225 wire::Header & header = *(reinterpret_cast<wire::Header*>(buffer.data()));
00226
00227
00228 buffer.seek(sizeof(wire::Header));
00229
00230
00231 const wire::IdType id = wire::SysNetwork::ID;
00232 const wire::VersionType version = wire::SysNetwork::VERSION;
00233 buffer & id;
00234 buffer & version;
00235
00236
00237 wire::SysNetwork msg(desiredAddress,desiredGateway,desiredNetmask);
00238 msg.serialize(buffer,version);
00239
00240
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
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 }