iface.c File Reference

interface handling for the Commotion daemon More...

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <linux/sockios.h>
#include "extern/wpa_ctrl.h"
#include "obj.h"
#include "debug.h"
#include "iface.h"
#include "util.h"
#include "id.h"
#include "list.h"

Functions

int co_ifaces_create (void)
 checks for available interfaces
 
void co_ifaces_shutdown (void)
 removes all interfaces
 
int co_iface_remove (char *iface_name)
 removes an interface from the list of available interfaces More...
 
co_obj_tco_iface_add (const char *iface_name, const int family)
 adds a new interface to the list of available interfaces, and checks whether it is IPv4 and IPv6 capable, and whether it is wireless More...
 
int co_iface_get_mac (co_obj_t *iface, unsigned char *output, int output_size)
 
int co_iface_set_ip (co_obj_t *iface_obj, const char *ip_addr, const char *netmask)
 sets ip address and netmask for commotion interface More...
 
int co_iface_unset_ip (co_obj_t *iface_obj)
 Resets ip address of chosen interface. More...
 
int co_iface_wpa_disconnect (co_obj_t *iface_obj)
 turns off wpa supplicant More...
 
int co_iface_wpa_connect (co_obj_t *iface_obj)
 connects the commotion interface to wpa supplicant More...
 
int co_iface_set_ssid (co_obj_t *iface, const char *ssid)
 sets SSID from profile or uses default More...
 
int co_iface_set_bssid (co_obj_t *iface, const char *bssid)
 sets BSSID from profile or uses default More...
 
int co_iface_set_frequency (co_obj_t *iface, const int frequency)
 sets wireless frequency (eg. channel) from profile or uses default More...
 
int co_iface_set_encryption (co_obj_t *iface, const char *proto)
 specifies the wpa encryption protocol More...
 
int co_iface_set_key (co_obj_t *iface, const char *key)
 specifies the wpa encryption key More...
 
int co_iface_set_mode (co_obj_t *iface, const char *mode)
 specifies the Wi-Fi mode More...
 
int co_iface_set_apscan (co_obj_t *iface, const int value)
 sets AP_SCAN value More...
 
int co_iface_wireless_enable (co_obj_t *iface)
 enables specified wireless network More...
 
int co_iface_wireless_disable (co_obj_t *iface)
 disables specified wireless network More...
 
int co_set_dns (const char *dnsserver, const char *searchdomain, const char *resolvpath)
 sets DNS name server and sets search domain More...
 
int co_generate_ip (const char *base, const char *genmask, const nodeid_t id, char *output, int type)
 generates an ip table for a commotion interface More...
 
char * co_iface_profile (char *iface_name)
 sets node configuration profile More...
 
co_obj_tco_iface_get (char *iface_name)
 retrieves node configuration profile More...
 

Detailed Description

interface handling for the Commotion daemon

Author
Josh King (jheretic), jking.nosp@m.@cha.nosp@m.mbana.nosp@m..net

Function Documentation

int co_generate_ip ( const char *  base,
const char *  genmask,
const nodeid_t  id,
char *  output,
int  type 
)

generates an ip table for a commotion interface

Parameters
basebase address
genmaskgenmask
idthe node id
typewhether the device is a gateway (1) or not (0)
437  {
438  nodeid_t addr;
439  addr.id = 0;
440  struct in_addr baseaddr;
441  struct in_addr generatedaddr;
442  struct in_addr genmaskaddr;
443  CHECK(inet_aton(base, &baseaddr) != 0, "Invalid base ip address %s", base);
444  CHECK(inet_aton(genmask, &genmaskaddr) != 0, "Invalid genmask address %s", genmask);
445 
446  /*
447  * Turn the IP address into a
448  * network address.
449  */
450  generatedaddr.s_addr = (baseaddr.s_addr & genmaskaddr.s_addr);
451 
452  /*
453  * get the matching octet from
454  * the mac and and then move it
455  * left to the proper spot.
456  */
457  for (int i = 0; i < 4; i++)
458  addr.bytes[i] = (id.bytes[i]&0xff)%0xfe;
459 
460  /*
461  * if address is of a gateway
462  * type, then set the last byte
463  * to '1'
464  * */
465  if(type) {
466  /*
467  * shift us over by one
468  * to ensure that we are
469  * getting maximum entropy
470  * from the mac address.
471  */
472  addr.bytes[1] = addr.bytes[2];
473  addr.bytes[2] = addr.bytes[3];
474  addr.bytes[3] = 1;
475  }
476 
477  /*
478  * mask out the parts of address
479  * that overlap with the genmask
480  */
481  addr.id &= ~(genmaskaddr.s_addr);
482  /*
483  * add back the user-supplied
484  * base ip address.
485  */
486  generatedaddr.s_addr = (generatedaddr.s_addr|addr.id);
487 
488  strcpy(output, inet_ntoa(generatedaddr));
489  return 1;
490 error:
491  return 0;
492 }
Definition: id.h:40
co_obj_t* co_iface_add ( const char *  iface_name,
const int  family 
)

adds a new interface to the list of available interfaces, and checks whether it is IPv4 and IPv6 capable, and whether it is wireless

Parameters
iface_namename of the interface
familyaddress family of the interface. Must be AF_INET (IPv4) or AF_INET6 (IPv6), which uses host and port number for addressing

References co_list_append(), and strlcpy().

180  {
181  co_iface_t *iface = h_calloc(1,sizeof(co_iface_t));
182  iface->_len = (sizeof(co_iface_t));
183  iface->_exttype = _iface;
184  iface->_header._type = _ext8;
185  iface->_header._flags = 0;
186  iface->_header._ref = 0;
187 
188  iface->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
189  strlcpy(iface->ifr.ifr_name, iface_name, IFNAMSIZ);
190 
191  /* Check whether interface is IPv4 or IPv6 */
192  if((family & AF_INET) == AF_INET) {
193  iface->ifr.ifr_addr.sa_family = AF_INET;
194  } else if((family & AF_INET6) == AF_INET6) {
195  iface->ifr.ifr_addr.sa_family = AF_INET6;
196  } else {
197  ERROR("Invalid address family!");
198  co_obj_free((co_obj_t*)iface);
199  return NULL;
200  }
201 
202  /* Check whether interface is wireless or not */
203  if(_co_iface_is_wireless((co_obj_t*)iface)) iface->wireless = true;
204  iface->wpa_id = -1;
205 
206  co_list_append(ifaces, (co_obj_t*)iface);
207  return (co_obj_t*)iface;
208 }
int co_list_append(co_obj_t *list, co_obj_t *new_obj)
insert new item at end of list
Definition: list.c:425
size_t strlcpy(char *dest, const char *src, const size_t size)
copies a string
Definition: util.c:50
contains the file descriptor, interface status (up or down), profile name, interface frequency struct...
Definition: iface.h:60
Definition: obj.h:131
co_obj_t* co_iface_get ( char *  iface_name)

retrieves node configuration profile

Parameters
iface_namename of interface

References co_list_parse().

502  {
503  co_obj_t *iface = NULL;
504  CHECK((iface = co_list_parse(ifaces, _co_iface_match_i, iface_name)) != NULL, "Failed to get interface %s!", iface_name);
505  return iface;
506 error:
507  return NULL;
508 }
Definition: obj.h:131
co_obj_t * co_list_parse(co_obj_t *list, co_iter_t iter, void *context)
process list with given iterator function
Definition: list.c:233
int co_iface_get_mac ( co_obj_t iface,
unsigned char *  output,
int  output_size 
)
Parameters
ifaceinterface object
outputoutput of hardware MAC address lookup
output_sizesize of MAC address. Must be six bytes
210  {
211  CHECK(IS_IFACE(iface),"Not an iface.");
212  co_iface_t *maciface = NULL;
213  CHECK(output_size == 6, "output_size does not equal six");
214 
215  maciface = malloc(sizeof(co_iface_t));
216  memset(maciface, '\0', sizeof(co_iface_t));
217  memmove(maciface, iface, sizeof(co_iface_t));
218  if (0 == ioctl(((co_iface_t*)iface)->fd, SIOCGIFHWADDR, &maciface->ifr)) {
219  DEBUG("Received MAC Address : %02x:%02x:%02x:%02x:%02x:%02x\n",
220  maciface->ifr.ifr_hwaddr.sa_data[0],maciface->ifr.ifr_hwaddr.sa_data[1],maciface->ifr.ifr_hwaddr.sa_data[2]
221  ,maciface->ifr.ifr_hwaddr.sa_data[3],maciface->ifr.ifr_hwaddr.sa_data[4],maciface->ifr.ifr_hwaddr.sa_data[5]);
222  memmove(output, maciface->ifr.ifr_addr.sa_data, output_size);
223  free(maciface);
224  return 1;
225  }
226  free(maciface);
227 error:
228  return 0;
229 }
contains the file descriptor, interface status (up or down), profile name, interface frequency struct...
Definition: iface.h:60
char* co_iface_profile ( char *  iface_name)

sets node configuration profile

Parameters
iface_namename of interface

References co_list_parse().

494  {
495  co_obj_t *iface = NULL;
496  CHECK((iface = co_list_parse(ifaces, _co_iface_match_i, iface_name)) != NULL, "Failed to get interface %s profile!", iface_name);
497  return ((co_iface_t*)iface)->profile;
498 error:
499  return NULL;
500 }
contains the file descriptor, interface status (up or down), profile name, interface frequency struct...
Definition: iface.h:60
Definition: obj.h:131
co_obj_t * co_list_parse(co_obj_t *list, co_iter_t iter, void *context)
process list with given iterator function
Definition: list.c:233
int co_iface_remove ( char *  iface_name)

removes an interface from the list of available interfaces

Parameters
iface_namename of interface to be removed

References co_iface_unset_ip(), co_iface_wireless_disable(), co_iface_wpa_disconnect(), co_list_delete(), and co_list_parse().

166  {
167  co_obj_t *iface = NULL;
168  CHECK((iface = co_list_parse(ifaces, _co_iface_match_i, iface_name)) != NULL, "Failed to delete interface %s!", iface_name);
169  iface = co_list_delete(ifaces, iface);
170  co_iface_unset_ip(iface);
173  co_obj_free(iface);
174  return 1;
175 
176 error:
177  return 0;
178 }
int co_iface_wpa_disconnect(co_obj_t *iface_obj)
turns off wpa supplicant
Definition: iface.c:273
int co_iface_wireless_disable(co_obj_t *iface)
disables specified wireless network
Definition: iface.c:401
co_obj_t * co_list_delete(co_obj_t *list, co_obj_t *item)
delete specified item from list
Definition: list.c:457
Definition: obj.h:131
int co_iface_unset_ip(co_obj_t *iface_obj)
Resets ip address of chosen interface.
Definition: iface.c:259
co_obj_t * co_list_parse(co_obj_t *list, co_iter_t iter, void *context)
process list with given iterator function
Definition: list.c:233
int co_iface_set_apscan ( co_obj_t iface,
const int  value 
)

sets AP_SCAN value

Parameters
ifaceinterface object
valuedesired value for AP_SCAN
373  {
374  CHECK(IS_IFACE(iface),"Not an iface.");
375  char cmd[256];
376  char buf[WPA_REPLY_SIZE];
377  size_t len;
378 
379  snprintf(cmd, sizeof(cmd), "AP_SCAN %d", value);
380  cmd[sizeof(cmd) - 1] = '\0';
381 
382  return _co_iface_wpa_command(iface, cmd, buf, &len);
383 error:
384  return 0;
385 }
int co_iface_set_bssid ( co_obj_t iface,
const char *  bssid 
)

sets BSSID from profile or uses default

Parameters
ifaceinterface object
bssiddesired BSSID
316  {
317  CHECK(IS_IFACE(iface),"Not an iface.");
318  char cmd[256], *pos, *end;
319  int ret;
320  char buf[WPA_REPLY_SIZE];
321  size_t len;
322 
323  end = cmd + sizeof(cmd);
324  pos = cmd;
325  ret = snprintf(pos, end - pos, "BSSID");
326  if (ret < 0 || ret >= end - pos) {
327  ERROR("Too long BSSID command.");
328  return 0;
329  }
330  pos += ret;
331  ret = snprintf(pos, end - pos, " %d %s", ((co_iface_t*)iface)->wpa_id, bssid);
332  if (ret < 0 || ret >= end - pos) {
333  ERROR("Too long BSSID command.");
334  return 0;
335  }
336  pos += ret;
337 
338  return _co_iface_wpa_command(iface, cmd, buf, &len);
339 error:
340  return 0;
341 }
contains the file descriptor, interface status (up or down), profile name, interface frequency struct...
Definition: iface.h:60
int co_iface_set_encryption ( co_obj_t iface,
const char *  proto 
)

specifies the wpa encryption protocol

Parameters
ifaceinterface object
protodesired protocol
352  {
353  CHECK(IS_IFACE(iface),"Not an iface.");
354  return _co_iface_wpa_set(iface, "proto", proto);
355 error:
356  return 0;
357 }
int co_iface_set_frequency ( co_obj_t iface,
const int  frequency 
)

sets wireless frequency (eg. channel) from profile or uses default

Parameters
ifaceinterface object
frequencydesired frequency
343  {
344  CHECK(IS_IFACE(iface),"Not an iface.");
345  char freq[FREQ_LEN];
346  snprintf(freq, FREQ_LEN, "%d", frequency);
347  return _co_iface_wpa_set(iface, "frequency", freq);
348 error:
349  return 0;
350 }
int co_iface_set_ip ( co_obj_t iface,
const char *  ip_addr,
const char *  netmask 
)

sets ip address and netmask for commotion interface

Parameters
ifaceinterface object
ip_addrip address for the socket
netmasknetmask for the socket
232  {
233  CHECK_MEM(iface_obj);
234  co_iface_t *iface = (co_iface_t*)iface_obj;
235  struct sockaddr_in *addr = (struct sockaddr_in *)&iface->ifr.ifr_addr;
236 
237  DEBUG("Setting address %s and netmask %s.", ip_addr, netmask);
238 
239  // Convert IP from numbers and dots to binary notation
240  inet_pton(AF_INET, ip_addr, &addr->sin_addr);
241  CHECK((ioctl(iface->fd, SIOCSIFADDR, &iface->ifr) == 0), "Failed to set IP address for interface: %s", iface->ifr.ifr_name);
242 
243  inet_pton(AF_INET, netmask, &addr->sin_addr);
244  CHECK((ioctl(iface->fd, SIOCSIFNETMASK, &iface->ifr) == 0), "Failed to set IP address for interface: %s", iface->ifr.ifr_name);
245 
246  //Get and set interface flags.
247  CHECK((ioctl(iface->fd, SIOCGIFFLAGS, &iface->ifr) == 0), "Interface shutdown: %s", iface->ifr.ifr_name);
248  iface->ifr.ifr_flags |= IFF_UP;
249  iface->ifr.ifr_flags |= IFF_RUNNING;
250  CHECK((ioctl(iface->fd, SIOCSIFFLAGS, &iface->ifr) == 0), "Interface up failed: %s", iface->ifr.ifr_name);
251 
252  DEBUG("Addressing for interface %s is done!", iface->ifr.ifr_name);
253  return 1;
254 
255 error:
256  return 0;
257 }
contains the file descriptor, interface status (up or down), profile name, interface frequency struct...
Definition: iface.h:60
int co_iface_set_key ( co_obj_t iface,
const char *  key 
)

specifies the wpa encryption key

Parameters
ifaceinterface object
keydesired key
359  {
360  CHECK(IS_IFACE(iface),"Not an iface.");
361  return _co_iface_wpa_set(iface, "psk", key);
362 error:
363  return 0;
364 }
int co_iface_set_mode ( co_obj_t iface,
const char *  mode 
)

specifies the Wi-Fi mode

Parameters
ifaceinterface object
modedesired mode
366  {
367  CHECK(IS_IFACE(iface),"Not an iface.");
368  return _co_iface_wpa_set(iface, "mode", mode);
369 error:
370  return 0;
371 }
int co_iface_set_ssid ( co_obj_t iface,
const char *  ssid 
)

sets SSID from profile or uses default

Parameters
ifaceinterface object
ssiddesired SSID
309  {
310  CHECK(IS_IFACE(iface),"Not an iface.");
311  return _co_iface_wpa_set(iface, "ssid", ssid);
312 error:
313  return 0;
314 }
int co_iface_unset_ip ( co_obj_t iface)

Resets ip address of chosen interface.

Parameters
ifaceinterface object

Referenced by co_iface_remove().

259  {
260  CHECK_MEM(iface_obj);
261  CHECK(IS_IFACE(iface_obj),"Not an iface.");
262  co_iface_t *iface = (co_iface_t*)iface_obj;
263  //Get and set interface flags.
264  CHECK((ioctl(iface->fd, SIOCGIFFLAGS, &iface->ifr) == 0), "Interface shutdown: %s", iface->ifr.ifr_name);
265  iface->ifr.ifr_flags &= ~IFF_UP;
266  iface->ifr.ifr_flags &= ~IFF_RUNNING;
267  CHECK((ioctl(iface->fd, SIOCSIFFLAGS, &iface->ifr) == 0), "Interface up failed: %s", iface->ifr.ifr_name);
268  return 1;
269 error:
270  return 0;
271 }
contains the file descriptor, interface status (up or down), profile name, interface frequency struct...
Definition: iface.h:60
int co_iface_wireless_disable ( co_obj_t iface)

disables specified wireless network

Parameters
ifaceinterface object

Referenced by co_iface_remove().

401  {
402  CHECK(IS_IFACE(iface),"Not an iface.");
403  CHECK(_co_iface_wpa_disable_network(iface), "Failed to disable network %s", ((co_iface_t*)iface)->ifr.ifr_name);
404  CHECK(_co_iface_wpa_remove_network(iface), "Failed to remove network %s", ((co_iface_t*)iface)->ifr.ifr_name);
405  return 1;
406 error:
407  return 0;
408 }
contains the file descriptor, interface status (up or down), profile name, interface frequency struct...
Definition: iface.h:60
int co_iface_wireless_enable ( co_obj_t iface)

enables specified wireless network

Parameters
ifaceinterface object
387  {
388  CHECK(IS_IFACE(iface),"Not an iface.");
389  char cmd[256];
390  char buf[WPA_REPLY_SIZE];
391  size_t len;
392 
393  snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %d", ((co_iface_t*)iface)->wpa_id);
394  cmd[sizeof(cmd) - 1] = '\0';
395 
396  return _co_iface_wpa_command(iface, cmd, buf, &len);
397 error:
398  return 0;
399 }
contains the file descriptor, interface status (up or down), profile name, interface frequency struct...
Definition: iface.h:60
int co_iface_wpa_connect ( co_obj_t iface)

connects the commotion interface to wpa supplicant

Parameters
ifaceinterface object
285  {
286  CHECK(IS_IFACE(iface_obj),"Not an iface.");
287  co_iface_t *iface = (co_iface_t*)iface_obj;
288  char *filename = NULL;
289  size_t length;
290 
291  CHECK(iface->wireless, "Not a wireless interface: %s", iface->ifr.ifr_name);
292 
293  length = strlen(wpa_control_dir) + strlen(iface->ifr.ifr_name) + 2;
294  filename = calloc(1, length);
295  CHECK_MEM(filename);
296  snprintf(filename, length, "%s/%s", wpa_control_dir, iface->ifr.ifr_name);
297  DEBUG("WPA control file: %s", filename);
298 
299  CHECK((iface->ctrl = wpa_ctrl_open(filename)), "Failed to connect to wpa_supplicant.");
300  free(filename);
301  return 1;
302 
303 error:
304  free(filename);
305  return 0;
306 }
contains the file descriptor, interface status (up or down), profile name, interface frequency struct...
Definition: iface.h:60
int co_iface_wpa_disconnect ( co_obj_t iface)

turns off wpa supplicant

Parameters
ifaceinterface object

Referenced by co_iface_remove().

273  {
274  CHECK(IS_IFACE(iface_obj),"Not an iface.");
275  co_iface_t *iface = (co_iface_t*)iface_obj;
276  if(iface->ctrl) {
277  wpa_ctrl_detach(iface->ctrl);
278  wpa_ctrl_close(iface->ctrl);
279  return 1;
280  }
281 error:
282  return 0;
283 }
contains the file descriptor, interface status (up or down), profile name, interface frequency struct...
Definition: iface.h:60
int co_set_dns ( const char *  dnsserver,
const char *  searchdomain,
const char *  resolvpath 
)

sets DNS name server and sets search domain

Parameters
dnsserverIP addresss of DNS server
searchdomaindesired search domain
resolvpathfilepath to resolv.conf
426  {
427  FILE *fp = fopen(resolvpath, "w+");
428  if(fp != NULL) {
429  if(searchdomain != NULL) fprintf(fp, "search %s\n", searchdomain);
430  fprintf(fp, "nameserver %s\n", dnsserver);
431  fclose(fp);
432  return 1;
433  } else ERROR("Could not open file: %s", resolvpath);
434  return 0;
435 }