ChangeIpUtility.cc
Go to the documentation of this file.
1 
37 #ifdef WIN32
38 #ifndef WIN32_LEAN_AND_MEAN
39 #define WIN32_LEAN_AND_MEAN 1
40 #endif
41 
42 #include <windows.h>
43 #include <winsock2.h>
44 #else
45 #include <unistd.h>
46 #include <netdb.h>
47 #include <sys/socket.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
50 #endif
51 
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string>
55 
56 #include <errno.h>
57 #include <string.h>
58 
61 
65 
67 
68 namespace { // anonymous
69 
70 void usage(const char *programNameP)
71 {
72  fprintf(stderr, "USAGE: %s [<options>]\n", programNameP);
73  fprintf(stderr, "Where <options> are:\n");
74  fprintf(stderr, "\t-a <current_address> : CURRENT IPV4 address (default=10.66.171.21)\n");
75  fprintf(stderr, "\t-A <new_address> : NEW IPV4 address (default=10.66.171.21)\n");
76  fprintf(stderr, "\t-G <new_gateway> : NEW IPV4 gateway (default=10.66.171.1)\n");
77  fprintf(stderr, "\t-N <new_netmask> : NEW IPV4 address (default=255.255.240.0)\n");
78 #ifndef WIN32
79  fprintf(stderr, "\t-b <interface> : send broadcast packet to specified network interface (requires root)\n");
80 #endif
81  fprintf(stderr, "\t-y : disable confirmation prompt\n");
82 
83  exit(-1);
84 }
85 
86 bool decodeIpv4(const std::string& addr,
87  unsigned int& p1,
88  unsigned int& p2,
89  unsigned int& p3,
90  unsigned int& p4)
91 {
92  if (addr.empty() ||
93  4 != sscanf(addr.c_str(), "%3u.%3u.%3u.%3u",
94  &p1, &p2, &p3, &p4) ||
95  (p1 > 255 || p2 > 255 || p3 > 255 || p4 > 255)) {
96  fprintf(stderr, "Unable to decode \"%s\" as IPV4 dotted-quad \n",
97  addr.c_str());
98  fflush(stderr);
99  return false;
100  }
101  return true;
102 }
103 
104 }; // anonymous
105 
106 using namespace crl::multisense;
107 
108 int main(int argc,
109  char **argvPP)
110 {
111  std::string currentAddress = "10.66.171.21";
112  std::string desiredAddress = "10.66.171.21";
113  std::string desiredGateway = "10.66.171.1";
114  std::string desiredNetmask = "255.255.240.0";
115  std::string iface = "eth0";
116  bool blind=false;
117  bool prompt=true;
118 
119  //
120  // Parse args
121 
122  int c;
123 
124  while(-1 != (c = getopt(argc, argvPP, "a:A:G:N:b:y")))
125  switch(c) {
126  case 'a': currentAddress = std::string(optarg); break;
127  case 'A': desiredAddress = std::string(optarg); break;
128  case 'G': desiredGateway = std::string(optarg); break;
129  case 'N': desiredNetmask = std::string(optarg); break;
130  case 'b': blind = true; iface = std::string(optarg); break;
131  case 'y': prompt = false; break;
132  default: usage(*argvPP); break;
133  }
134 
135  Status status;
136  Channel *channelP = NULL;
137  int sockfd = -1;
138 
139  system::DeviceInfo deviceInfo;
140 
141  uint32_t a1 = 0;
142  uint32_t a2 = 0;
143  uint32_t a3 = 0;
144  uint32_t a4 = 0;
145 
146  if (!decodeIpv4(desiredAddress, a1, a2, a3, a4))
147  {
148  goto clean_out;
149  }
150 
151 
152  if(!blind)
153  {
154  //
155  // Initialize communications.
156 
157  channelP = Channel::Create(currentAddress);
158  if (NULL == channelP) {
159  fprintf(stderr, "Failed to establish communications with \"%s\"\n",
160  currentAddress.c_str());
161  return -1;
162  }
163 
164  //
165  // Query version
166 
167  VersionType version;
168 
169  status = channelP->getSensorVersion(version);
170  if (Status_Ok != status) {
171  fprintf(stderr, "failed to query sensor version: %s\n",
172  Channel::statusString(status));
173  goto clean_out;
174  }
175 
176  status = channelP->getDeviceInfo(deviceInfo);
177 
178  if (Status_Ok != status) {
179  fprintf(stderr, "failed to query device info %s\n",
180  Channel::statusString(status));
181  goto clean_out;
182  }
183 
185  192 == a1 && 168 == a2 && 0 == a3)
186  {
187  fprintf(stderr, "MultiSense SL units use the 192.168.0 subnet to talk to the Hokuyo ");
188  fprintf(stderr, "laser. Setting the IP address of the MultiSense to 192.168.0.X will ");
189  fprintf(stderr, "interfere with the networking configuration.\n");
190  fprintf(stderr, "\n");
191  fprintf(stderr, "Aborting IP Change.\n");
192  fflush(stderr);
193  goto clean_out;
194  }
195  }
196  else
197  {
198 #ifdef WIN32
199  perror ("broadcast is not yet supported on Windows");
200  goto clean_out;
201 #else
202  int broadcast=1;
203 
204  if (192 == a1 && 168 == a2 && 0 == a3)
205  {
206  fprintf(stderr, "MultiSense SL units use the 192.168.0 subnet to talk to the Hokuyo ");
207  fprintf(stderr, "laser. Setting the IP address of the MultiSense to 192.168.0.X will ");
208  fprintf(stderr, "interfere with the networking configuration. This unit may be a ");
209  fprintf(stderr, "MultiSense SL as in broadcast mode this tool cannot query the device.\n");
210  fprintf(stderr, "\n");
211  fprintf(stderr, "Aborting IP Change.\n");
212  fflush(stderr);
213  goto clean_out;
214  }
215 
216  // create UDP socket
217  sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
218  if(sockfd == -1) {
219  perror("socket() failed");
220  goto clean_out;
221  }
222 
223  // enable support for sending to broadcast address
224  if (setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,reinterpret_cast<char const*>(&broadcast),sizeof(broadcast))==-1) {
225  perror("setsockopt(...SO_BROADCAST) failed");
226  goto clean_out;
227  }
228 
229  // bind to a specific interface so broadcast packet goes to the right place
230  // note: on most systems, this will require elevated privileges
231  if (setsockopt(sockfd,SOL_SOCKET,SO_BINDTODEVICE,iface.c_str(),iface.size()+1)==-1) {
232  perror("setsockopt(...SO_BINDTODEVICE) failed (are you root?)");
233  goto clean_out;
234  }
235 #endif
236  }
237 
238  if(prompt)
239  {
240 
241  fprintf(stdout, "NEW address: %s\n", desiredAddress.c_str());
242  fprintf(stdout, "NEW gateway: %s\n", desiredGateway.c_str());
243  fprintf(stdout, "NEW netmask: %s\n\n", desiredNetmask.c_str());
244 
245  if(blind) {
246  fprintf(stdout, "** WARNING: All MultiSense devices attached to interface '%s' will have their addresses changed **\n\n", iface.c_str());
247  }
248 
249  fprintf(stdout, "Really update network configuration? (y/n): ");
250  fflush(stdout);
251 
252  int c = getchar();
253  if ('Y' != c && 'y' != c) {
254  fprintf(stdout, "Aborting\n");
255  goto clean_out;
256  }
257  }
258 
259  if(!blind)
260  {
261  //
262  // Try setting the new IP parameters. The device will
263  // verify that the IP addresses are valid dotted-quads,
264  // however, little complex verification is done.
265 
266  status = channelP->setNetworkConfig(system::NetworkConfig(desiredAddress,
267  desiredGateway,
268  desiredNetmask));
269  if (Status_Ok != status)
270  fprintf(stderr, "Failed to set the network configuration: %s\n",
271  Channel::statusString(status));
272  else
273  fprintf(stdout, "Network parameters changed successfully\n");
274  }
275  else
276  {
277 #ifndef WIN32
278  struct sockaddr_in si;
279 
280  // construct destination address
281  memset(&si,0,sizeof(si));
282  si.sin_family = AF_INET;
283  si.sin_port = htons(9001);
284  si.sin_addr.s_addr = htonl(INADDR_BROADCAST);
285 
286  // manually construct SysNetwork message
287  using namespace crl::multisense::details;
288  utility::BufferStreamWriter buffer(256);
289  wire::Header & header = *(reinterpret_cast<wire::Header*>(buffer.data()));
290 
291  // hide header area
292  buffer.seek(sizeof(wire::Header));
293 
294  // set ID and version
297  buffer & id;
298  buffer & version;
299 
300  // construct message
301  wire::SysNetwork msg(desiredAddress,desiredGateway,desiredNetmask);
302  msg.serialize(buffer,version);
303 
304  // install header
305  header.magic = wire::HEADER_MAGIC;
306  header.version = wire::HEADER_VERSION;
307  header.group = wire::HEADER_GROUP;
308  header.flags = 0;
309  header.sequenceIdentifier = 0;
310  header.messageLength = buffer.tell() - sizeof(wire::Header);
311  header.byteOffset = 0;
312 
313  // send packet
314  if(sendto(sockfd,reinterpret_cast<char const*>(buffer.data()),buffer.tell(),0,reinterpret_cast<sockaddr*>(&si),sizeof(si)) == -1) {
315  perror("sendto() failed");
316  goto clean_out;
317  }
318 
319  fprintf(stdout, "Successfully transmitted network parameter change command\n");
320 #endif
321  }
322 
323 clean_out:
324 
325  if(channelP)
326  Channel::Destroy(channelP);
327  if(sockfd != -1)
328 #ifdef WIN32
329  closesocket(sockfd);
330 #else
331  close(sockfd);
332 #endif
333 
334  return 0;
335 }
virtual Status setNetworkConfig(const system::NetworkConfig &c)=0
static CRL_CONSTEXPR uint32_t HARDWARE_REV_MULTISENSE_SL
static const char * statusString(Status status)
Definition: channel.cc:609
static Channel * Create(const std::string &sensorAddress)
Definition: channel.cc:583
std_msgs::Header * header(M &m)
#define closesocket
Definition: Portability.hh:89
void serialize(Archive &message, const VersionType version)
static CRL_CONSTEXPR uint16_t HEADER_VERSION
Definition: Protocol.h:67
int getopt(int argc, char **argv, char *opts)
Definition: getopt.c:34
static CRL_CONSTEXPR VersionType VERSION
static CRL_CONSTEXPR Status Status_Ok
static CRL_CONSTEXPR uint16_t HEADER_MAGIC
Definition: Protocol.h:66
def usage(progname)
virtual Status getDeviceInfo(system::DeviceInfo &info)=0
static void Destroy(Channel *instanceP)
Definition: channel.cc:596
static CRL_CONSTEXPR uint16_t HEADER_GROUP
Definition: Protocol.h:72
char * optarg
Definition: getopt.c:32
int main(int argc, char **argvPP)
virtual Status getSensorVersion(VersionType &version)=0


multisense_lib
Author(s):
autogenerated on Sat Apr 6 2019 02:16:46