host_netutil.c
Go to the documentation of this file.
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2009, 2010 Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include <sys/ioctl.h>
40 #include <netinet/in.h>
41 #include <sys/time.h>
42 #include <net/if.h>
43 #include <unistd.h>
44 #include <net/if_arp.h>
45 
46 #include "wge100_camera/list.h"
48 
49 
61 int wge100ArpAdd(IpCamList *camInfo) {
62  // Create new permanent mapping in the system ARP table
63  struct arpreq arp;
64  int s;
65 
66  // Create a dummy socket
67  if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) {
68  perror("wge100ArpAdd can't create socket");
69  return -1;
70  }
71 
72  wge100_debug("Registering ARP info for S/N %d \n", camInfo->serial);
73 
74  // Populate the arpreq structure for this mapping
75  ((struct sockaddr_in*)&arp.arp_pa)->sin_family = AF_INET;
76  memcpy(&((struct sockaddr_in*)&arp.arp_pa)->sin_addr, &camInfo->ip, sizeof(struct in_addr));
77 
78  // This is a 'permanent' mapping; it will not time out (but will be cleared by a reboot)
79  arp.arp_flags = ATF_PERM;
80 
81  arp.arp_ha.sa_family = ARPHRD_ETHER;
82  memcpy(&arp.arp_ha.sa_data, camInfo->mac, 6);
83 
84  strncpy(arp.arp_dev, camInfo->ifName, sizeof(arp.arp_dev));
85 
86  if( ioctl(s, SIOCSARP, &arp) == -1 ) {
87  //perror("Warning, was unable to create ARP entry (are you root?)");
88  close(s);
89  return -1;
90  } else {
91  wge100_debug("Camera %u successfully configured\n", camInfo->serial);
92  }
93  return 0;
94 }
95 
96 
107 int wge100ArpDel(IpCamList *camInfo) {
108  // Create new permanent mapping in the system ARP table
109  struct arpreq arp;
110  int s;
111 
112  // Create a dummy socket
113  if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) {
114  perror("wge100ArpDel can't create socket");
115  return -1;
116  }
117 
118  wge100_debug("Removing ARP info for S/N %d \n", camInfo->serial);
119 
120  // Populate the arpreq structure for this mapping
121  ((struct sockaddr_in*)&arp.arp_pa)->sin_family = AF_INET;
122  memcpy(&((struct sockaddr_in*)&arp.arp_pa)->sin_addr, &camInfo->ip, sizeof(struct in_addr));
123 
124  // No flags required for removal
125  arp.arp_flags = 0;
126 
127  arp.arp_ha.sa_family = ARPHRD_ETHER;
128  memcpy(&arp.arp_ha.sa_data, camInfo->mac, 6);
129 
130  strncpy(arp.arp_dev, camInfo->ifName, sizeof(arp.arp_dev));
131 
132  // Make the request to the kernel
133  if( ioctl(s, SIOCDARP, &arp) == -1 ) {
134  perror("Warning, was unable to remove ARP entry");
135  close(s);
136  return -1;
137  } else {
138  wge100_debug("Camera %u successfully removed from ARP table\n", camInfo->serial);
139  }
140 
141  return 0;
142 }
143 
144 
154 int wge100EthGetLocalMac(const char *ifName, struct sockaddr *macAddr) {
155  struct ifreq ifr;
156  int s;
157 
158  // Create a dummy socket
159  if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) {
160  perror("wge100EthGetLocalMac can't create socket");
161  return -1;
162  }
163 
164  // Initialize the ifreq structure with the interface name
165  strncpy(ifr.ifr_name,ifName,sizeof(ifr.ifr_name)-1);
166  ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0';
167 
168  // Use socket ioctl to retrieve the HW (MAC) address of this interface
169  if( ioctl(s, SIOCGIFHWADDR, &ifr) == -1 ) {
170  fprintf(stderr, "On interface '%s': ", ifName);
171  perror("wge100EthGetLocalMac ioctl failed");
172  close(s);
173  return -1;
174  }
175 
176  // Transfer address from ifreq struct to output pointer
177  memcpy(macAddr, &ifr.ifr_addr, sizeof(struct sockaddr));
178 
179  close(s);
180  return 0;
181 }
182 
183 
193 int wge100IpGetLocalBcast(const char *ifName, struct in_addr *bcast) {
194  struct ifreq ifr;
195  int s;
196 
197  // Create a dummy socket
198  if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) {
199  perror("wge100IpGetLocalBcast can't create socket");
200  return -1;
201  }
202 
203  // Initialize the ifreq structure
204  strncpy(ifr.ifr_name,ifName,sizeof(ifr.ifr_name)-1);
205  ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0';
206 
207  // Use socket ioctl to get broadcast address for this interface
208  if( ioctl(s,SIOCGIFBRDADDR , &ifr) == -1 ) {
209  //perror("wge100IpGetLocalBcast ioctl failed");
210  close(s);
211  return -1;
212  }
213 
214  // Requires some fancy casting because the IP portion of a sockaddr_in is stored
215  // after the port (which we don't need) in the struct
216  memcpy(&(bcast->s_addr), &((struct sockaddr_in *)(&ifr.ifr_broadaddr))->sin_addr, sizeof(struct in_addr));
217 
218  close(s);
219  return 0;
220 }
221 
231 int wge100IpGetLocalAddr(const char *ifName, struct in_addr *addr) {
232  struct ifreq ifr;
233  int s;
234 
235  // Create a dummy socket
236  if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) {
237  perror("wge100IpGetLocalAddr can't create socket");
238  return -1;
239  }
240 
241  // Initialize the ifreq structure
242  strncpy(ifr.ifr_name,ifName,sizeof(ifr.ifr_name)-1);
243  ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0';
244 
245  // Use socket ioctl to get the IP address for this interface
246  if( ioctl(s,SIOCGIFADDR , &ifr) == -1 ) {
247  //perror("wge100IpGetLocalAddr ioctl failed");
248  close(s);
249  return -1;
250  }
251 
252  // Requires some fancy casting because the IP portion of a sockaddr_in after the port (which we don't need) in the struct
253  memcpy(&(addr->s_addr), &((struct sockaddr_in *)(&ifr.ifr_broadaddr))->sin_addr, sizeof(struct in_addr));
254  close(s);
255 
256  return 0;
257 }
258 
259 
269 int wge100IpGetLocalNetmask(const char *ifName, struct in_addr *addr) {
270  struct ifreq ifr;
271  int s;
272 
273  // Create a dummy socket
274  if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) {
275  perror("wge100IpGetLocalAddr can't create socket");
276  return -1;
277  }
278 
279  // Initialize the ifreq structure
280  strncpy(ifr.ifr_name,ifName,sizeof(ifr.ifr_name)-1);
281  ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0';
282 
283  // Use socket ioctl to get the netmask for this interface
284  if( ioctl(s,SIOCGIFNETMASK , &ifr) == -1 ) {
285  //perror("wge100IpGetLocalNetmask ioctl failed");
286  close(s);
287  return -1;
288  }
289 
290  // Requires some fancy casting because the IP portion of a sockaddr_in after the port (which we don't need) in the struct
291  memcpy(&(addr->s_addr), &((struct sockaddr_in *)(&ifr.ifr_broadaddr))->sin_addr, sizeof(struct in_addr));
292  close(s);
293 
294  return 0;
295 }
296 
297 
306 int wge100SocketCreate(const struct in_addr *addr, uint16_t port) {
307 
308  // Create a UDP socket for communicating with the network
309  int s;
310  if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1 ) {
311  perror("wge100SocketCreate can't create socket");
312  return -1;
313  }
314 
315  // Define the address we'll be listening on
316  struct sockaddr_in si_host;
317  memset( (uint8_t*)&si_host, 0, sizeof(si_host) );
318  si_host.sin_family = AF_INET; // This is an INET address
319  memcpy(&si_host.sin_addr, addr, sizeof(struct in_addr)); // Bind only to this address
320  si_host.sin_port = htons(port); // If port==0,bind chooses an ephemeral source port
321 
322 
323  // Bind the socket to the requested port
324  if( bind(s, (struct sockaddr *)&si_host, sizeof(si_host)) == -1 ) {
325  //perror("wge100SocketCreate unable to bind");
326  close(s);
327  return -1;
328  }
329 
330  // Setting the broadcast flag allows us to transmit to the broadcast address
331  // from this socket if we want to. Some platforms do not allow unprivileged
332  // users to set this flag, but Linux does.
333  int flags = 1;
334  if( setsockopt(s, SOL_SOCKET,SO_BROADCAST, &flags, sizeof(flags)) == -1) {
335  perror("wge100SocketCreate unable to set broadcast socket option");
336  close(s);
337  return -1;
338  }
339 
340  return s;
341 }
342 
343 
353 int wge100SocketConnect(int s, const IPAddress *ip) {
354 
355  struct sockaddr_in camIP;
356 
358  // work until a few days ago (late july/early june 09). Now the
359  // regression tests won't work without the hack, but real cameras work
360  // just fine. Perhaps the simulated camera was being discovered on
361  // another interface.
362  if (*ip == 0x0100007F)
363  return 0;
364 
365  camIP.sin_family = AF_INET;
366  camIP.sin_port = 0; // Unused by connect
367  camIP.sin_addr.s_addr=*ip;
368 
369  if( connect(s, (struct sockaddr *)&camIP, sizeof(camIP)) == -1 ) {
370  perror("Could not connect datagram socket");
371  close(s);
372  return -1;
373  }
374 
375  return 0;
376 }
377 
378 
387 int wge100CmdSocketCreate(const char *ifName, NetHost *localHost) {
388  // Identify the IP address of the requested interface
389  struct in_addr host_addr;
390  wge100IpGetLocalAddr(ifName, &host_addr);
391 
392  // Create & bind a new listening socket, s
393  // We specify a port of 0 to have bind choose an available host port
394  int s;
395  if( (s=wge100SocketCreate(&host_addr, 0)) == -1 ) {
396  //perror("Unable to create socket");
397  return -1;
398  }
399 
400  if(localHost != NULL) {
401  struct sockaddr_in socketAddr;
402  socklen_t socketAddrSize = sizeof(socketAddr);
403  if( getsockname(s, (struct sockaddr *)&socketAddr, &socketAddrSize) == -1) {
404  perror("wge100SocketToNetHost Could not get socket name");
405  close(s);
406  return -1;
407  }
408 
409  struct sockaddr macAddr;
410  if( wge100EthGetLocalMac(ifName, &macAddr) == -1) {
411  close(s);
412  return -1;
413  }
414 
415  memcpy(localHost->mac, macAddr.sa_data, sizeof(localHost->mac));
416  localHost->addr = socketAddr.sin_addr.s_addr;
417  localHost->port = socketAddr.sin_port;
418  }
419 
420  return s;
421 }
422 
435 int wge100SendUDP(int s, const IPAddress *ip, const void *data, size_t dataSize) {
436  // Create and initialize a sockaddr_in structure to hold remote port & IP
437  struct sockaddr_in si_cam;
438  memset( (uint8_t *)&si_cam, 0, sizeof(si_cam) );
439  si_cam.sin_family = AF_INET;
440  si_cam.sin_port = htons(WG_CAMCMD_PORT);
441  si_cam.sin_addr.s_addr = *ip;
442 
443  // Send the datagram
444  if( sendto(s, data, dataSize, 0, (struct sockaddr*)&si_cam, sizeof(si_cam)) == -1 ) {
445  perror("wge100SendUDP unable to send packet");
446  close(s);
447  return -1;
448  }
449  return 0;
450 }
451 
464 int wge100SendUDPBcast(int s, const char *ifName, const void *data, size_t dataSize) {
465  // Identify the broadcast address on the specified interface
466  struct in_addr bcastIP;
467  wge100IpGetLocalBcast(ifName, &bcastIP);
468 
469  // Use wge100SendUDP to send the broadcast packet
470  return wge100SendUDP(s, &bcastIP.s_addr, data, dataSize);
471 }
472 
473 
493 int wge100WaitForPacket( int *s, int nums, uint32_t type, size_t pktLen, uint32_t *wait_us ) {
494  int i;
495  // Convert wait_us argument into a struct timeval
496  struct timeval timeout;
497  timeout.tv_sec = *wait_us / 1000000UL;
498  timeout.tv_usec = *wait_us % 1000000UL;
499 
500  // We have been asked to wait wait_us microseconds for a response; compute the time
501  // at which the timeout will expire and store it into "timeout"
502  struct timeval timestarted;
503  struct timeval timenow;
504  gettimeofday(&timestarted, NULL);
505  gettimeofday(&timenow, NULL);
506  timeradd( &timeout, &timestarted, &timeout );
507 
508  struct timeval looptimeout;
509  fd_set set;
510  while( timercmp( &timeout, &timenow, >= ) ) {
511  int maxs = 0;
512  // Since we could receive multiple packets, we need to decrease the timeout
513  // to select() as we go. (Multiple packets should be an unlikely event, but
514  // UDP provides no guarantees)
515  timersub(&timeout, &timestarted, &looptimeout);
516 
517  FD_ZERO(&set);
518  for (i = 0; i < nums; i++)
519  {
520  FD_SET(s[i], &set);
521  if (s[i] > maxs)
522  maxs = s[i];
523  }
524 
525  // Wait for either a packet to be received or for timeout
526  if( select(maxs+1, &set, NULL, NULL, &looptimeout) == -1 ) {
527  perror("wge100WaitForPacket select failed");
528  return -1;
529  }
530 
531  for (i = 0; i < nums; i++) {
532  // If we received a packet
533  if( FD_ISSET(s[i], &set) ) {
534  PacketGeneric gPkt;
535  int r;
536  // Inspect the packet in the buffer without removing it
537  if( (r=recvfrom( s[i], &gPkt, sizeof(PacketGeneric), MSG_PEEK|MSG_TRUNC, NULL, NULL )) == -1 ) {
538  perror("wge100WaitForPacket unable to receive from socket");
539  return -1;
540  }
541 
542  // All valid WG command packets have magic_no == WG_MAGIC NO
543  // We also know the minimum packet size we're looking for
544  // So we can drop short or invalid packets at this stage
545  if( ((unsigned int) r < pktLen) ||
546  gPkt.magic_no != htonl(WG_MAGIC_NO) ||
547  gPkt.type != htonl(type) ) {
548  wge100_debug("Dropping packet with magic #%08X, type 0x%02X (looking for 0x%02X), length %d (looking for %d)\n", ntohl(gPkt.magic_no), ntohl(gPkt.type), type, r, pktLen);
549  // Pull it out of the buffer (we used MSG_PEEK before, so it's still in there)
550  if( recvfrom( s[i], &gPkt, sizeof(PacketGeneric), 0, NULL, NULL ) == -1 ) {
551  perror("wge100WaitForPacket unable to receive from socket");
552  return -1;
553  }
554  } else { // The packet appears to be valid and correct
555  // Compute the amount of time left on the timeout in case the calling function
556  // decides this is not the packet we're looking for
557  struct timeval timeleft;
558  gettimeofday(&timenow, NULL);
559  timersub(&timeout, &timenow, &timeleft);
560 
561  if (timeleft.tv_sec < 0)
562  // Otherwise we risk returning a very large number.
563  *wait_us = 0;
564  else
565  *wait_us = timeleft.tv_usec+timeleft.tv_sec*1000000UL;
566  return i;
567  }
568 
569  }
570  }
571  gettimeofday(&timenow, NULL);
572  }
573  // If we reach here, we've timed out
574  *wait_us = 0;
575  return 0;
576 }
MACAddress mac
Definition: ipcam_packet.h:79
uint32_t type
The packet type (see list of packet types, above)
Definition: ipcam_packet.h:156
int wge100ArpDel(IpCamList *camInfo)
Definition: host_netutil.c:107
#define WG_CAMCMD_PORT
Definition: ipcam_packet.h:101
int wge100IpGetLocalBcast(const char *ifName, struct in_addr *bcast)
Definition: host_netutil.c:193
XmlRpcServer s
IPAddress ip
Definition: list.h:295
int wge100SendUDPBcast(int s, const char *ifName, const void *data, size_t dataSize)
Definition: host_netutil.c:464
int wge100SendUDP(int s, const IPAddress *ip, const void *data, size_t dataSize)
Definition: host_netutil.c:435
int wge100SocketConnect(int s, const IPAddress *ip)
Definition: host_netutil.c:353
uint32_t IPAddress
Definition: ipcam_packet.h:74
int wge100IpGetLocalAddr(const char *ifName, struct in_addr *addr)
Definition: host_netutil.c:231
int wge100WaitForPacket(int *s, int nums, uint32_t type, size_t pktLen, uint32_t *wait_us)
Definition: host_netutil.c:493
IPAddress addr
Definition: ipcam_packet.h:80
uint8_t mac[6]
Definition: list.h:294
int wge100IpGetLocalNetmask(const char *ifName, struct in_addr *addr)
Definition: host_netutil.c:269
#define WG_MAGIC_NO
Definition: ipcam_packet.h:94
int wge100SocketCreate(const struct in_addr *addr, uint16_t port)
Definition: host_netutil.c:306
int wge100ArpAdd(IpCamList *camInfo)
Definition: host_netutil.c:61
uint32_t magic_no
The Willow Garage Magic number (always WG_MAGIC_NO)
Definition: ipcam_packet.h:155
int wge100CmdSocketCreate(const char *ifName, NetHost *localHost)
Definition: host_netutil.c:387
int wge100EthGetLocalMac(const char *ifName, struct sockaddr *macAddr)
Definition: host_netutil.c:154
char ifName[128]
Definition: list.h:293
uint32_t serial
Definition: list.h:275
UDPPort port
Definition: ipcam_packet.h:81


wge100_camera
Author(s): Blaise Gassend, Patrick Mihelich, Eric MacIntosh, David Palchak
autogenerated on Mon Jun 10 2019 15:44:15