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


multisense_lib
Author(s):
autogenerated on Thu Apr 17 2025 02:49:08