usb_moded  0.86.0+mer57
usb_moded-network.c
Go to the documentation of this file.
1 
32 /*============================================================================= */
33 
34 #include "usb_moded-network.h"
35 
37 #include "usb_moded-control.h"
38 #include "usb_moded-log.h"
39 #include "usb_moded-modesetting.h"
40 #include "usb_moded-worker.h"
41 #include "usb_moded-dbus-private.h"
42 
43 #include <sys/stat.h>
44 
45 #include <unistd.h>
46 
47 /* ========================================================================= *
48  * Constants
49  * ========================================================================= */
50 
51 #define UDHCP_CONFIG_PATH "/run/usb-moded/udhcpd.conf"
52 #define UDHCP_CONFIG_DIR "/run/usb-moded"
53 #define UDHCP_CONFIG_LINK "/etc/udhcpd.conf"
54 
55 /* ========================================================================= *
56  * Types
57  * ========================================================================= */
58 
60 typedef struct ipforward_data_t
61 {
63  char *dns1;
65  char *dns2;
69 
70 /* ========================================================================= *
71  * Prototypes
72  * ========================================================================= */
73 
74 /* ------------------------------------------------------------------------- *
75  * IPFORWARD_DATA
76  * ------------------------------------------------------------------------- */
77 
78 static ipforward_data_t *ipforward_data_create (void);
79 static void ipforward_data_delete (ipforward_data_t *self);
80 static void ipforward_data_clear (ipforward_data_t *self);
81 static void ipforward_data_set_dns1 (ipforward_data_t *self, const char *dns);
82 static void ipforward_data_set_dns2 (ipforward_data_t *self, const char *dns);
83 static void ipforward_data_set_nat_interface(ipforward_data_t *self, const char *interface);
84 
85 /* ------------------------------------------------------------------------- *
86  * OFONO
87  * ------------------------------------------------------------------------- */
88 
89 #ifdef OFONO
90 static gchar *ofono_get_default_modem (void);
91 static gchar *ofono_get_modem_status (const char *modem);
92 static bool ofono_get_roaming_status(void);
93 #endif
94 
95 /* ------------------------------------------------------------------------- *
96  * CONNMAN
97  * ------------------------------------------------------------------------- */
98 
99 #ifdef CONNMAN
100 static bool connman_technology_set_tethering (DBusConnection *con, const char *technology, bool on, DBusError *err);
101 static gchar *connman_manager_get_service_path (DBusConnection *con, const char *type);
102 static bool connman_service_get_connection_data(DBusConnection *con, const char *service, ipforward_data_t *ipforward);
103 static bool connman_get_connection_data (ipforward_data_t *ipforward);
104 bool connman_set_tethering (const char *technology, bool on);
105 #endif
106 
107 /* ------------------------------------------------------------------------- *
108  * LEGACY
109  * ------------------------------------------------------------------------- */
110 
111 #ifndef CONNMAN
112 static bool legacy_get_connection_data(ipforward_data_t *ipforward);
113 #endif
114 
115 /* ------------------------------------------------------------------------- *
116  * NETWORK
117  * ------------------------------------------------------------------------- */
118 
119 static bool network_interface_exists (char *interface);
120 static char *network_get_interface (const modedata_t *data);
121 static int network_setup_ip_forwarding (const modedata_t *data, ipforward_data_t *ipforward);
122 static void network_cleanup_ip_forwarding(void);
123 static int network_check_udhcpd_symlink (void);
124 static int network_write_udhcpd_config (const modedata_t *data, ipforward_data_t *ipforward);
125 int network_update_udhcpd_config (const modedata_t *data);
126 int network_up (const modedata_t *data);
127 void network_down (const modedata_t *data);
128 void network_update (void);
129 
130 /* ========================================================================= *
131  * Data
132  * ========================================================================= */
133 
134 static const char default_interface[] = "usb0";
135 
136 /* ========================================================================= *
137  * IPFORWARD_DATA
138  * ========================================================================= */
139 
140 static ipforward_data_t *
141 ipforward_data_create(void)
142 {
143  LOG_REGISTER_CONTEXT;
144 
145  ipforward_data_t *self = g_malloc0(sizeof *self);
146 
147  self->dns1 = 0;
148  self->dns2 = 0;
149  self->nat_interface = 0;
150 
151  return self;
152 }
153 
154 static void
155 ipforward_data_delete(ipforward_data_t *self)
156 {
157  LOG_REGISTER_CONTEXT;
158 
159  if( self )
160  {
161  ipforward_data_clear(self);
162  g_free(self);
163  }
164 }
165 
166 static void
167 ipforward_data_clear(ipforward_data_t *self)
168 {
169  LOG_REGISTER_CONTEXT;
170 
171  ipforward_data_set_dns1(self, 0);
172  ipforward_data_set_dns2(self, 0);
173  ipforward_data_set_nat_interface(self, 0);
174 }
175 
176 static void
177 ipforward_data_set_dns1(ipforward_data_t *self, const char *dns)
178 {
179  LOG_REGISTER_CONTEXT;
180 
181  g_free(self->dns1),
182  self->dns1 = dns ? g_strdup(dns) : 0;
183 }
184 
185 static void
186 ipforward_data_set_dns2(ipforward_data_t *self, const char *dns)
187 {
188  LOG_REGISTER_CONTEXT;
189 
190  g_free(self->dns2),
191  self->dns2 = dns ? g_strdup(dns) : 0;
192 }
193 
194 static void
195 ipforward_data_set_nat_interface(ipforward_data_t *self, const char *interface)
196 {
197  LOG_REGISTER_CONTEXT;
198 
199  g_free(self->nat_interface),
200  self->nat_interface = interface ? g_strdup(interface) : 0;
201 }
202 
203 /* ========================================================================= *
204  * OFONO
205  * ========================================================================= */
206 
207 #ifdef OFONO
208 
216 static gchar *
217 ofono_get_default_modem(void)
218 {
219  gchar *modem = 0;
220  DBusConnection *con = 0;
221  DBusError err = DBUS_ERROR_INIT;
222  DBusMessage *rsp = 0;
223 
224  if( !(con = umdbus_get_connection()) )
225  goto EXIT;
226 
227  rsp = umdbus_blocking_call(con,
228  "org.ofono",
229  "/",
230  "org.ofono.Manager",
231  "GetModems",
232  &err,
233  DBUS_TYPE_INVALID);
234  if( !rsp )
235  goto EXIT;
236 
237  // a(oa{sv}) -> get object path in the first struct in the array
238  DBusMessageIter body;
239  if( umdbus_parser_init(&body, rsp) ) {
240  DBusMessageIter iter_array;
241  if( umdbus_parser_get_array(&body, &iter_array) ) {
242  DBusMessageIter astruct;
243  if( umdbus_parser_get_struct(&iter_array, &astruct) ) {
244  const char *object = 0;
245  if( umdbus_parser_get_object(&astruct, &object) ) {
246  modem = g_strdup(object);
247  }
248  }
249  }
250  }
251 
252 EXIT:
253  if( rsp )
254  dbus_message_unref(rsp);
255 
256  if( con )
257  dbus_connection_unref(con);
258 
259  dbus_error_free(&err);
260 
261  log_warning("default modem = %s", modem ?: "n/a");
262 
263  return modem;
264 }
265 
274 static gchar *
275 ofono_get_modem_status(const char *modem)
276 {
277  gchar *status = 0;
278  DBusConnection *con = 0;
279  DBusError err = DBUS_ERROR_INIT;
280  DBusMessage *rsp = 0;
281 
282  if( !(con = umdbus_get_connection()) )
283  goto EXIT;
284 
285  rsp = umdbus_blocking_call(con,
286  "org.ofono",
287  modem,
288  "org.ofono.NetworkRegistration",
289  "GetProperties",
290  &err,
291  DBUS_TYPE_INVALID);
292  if( !rsp )
293  goto EXIT;
294 
295  DBusMessageIter body;
296  if( umdbus_parser_init(&body, rsp) ) {
297  DBusMessageIter iter_array;
298  if( umdbus_parser_get_array(&body, &iter_array) ) {
299  DBusMessageIter entry;
300  while( umdbus_parser_get_entry(&iter_array, &entry) ) {
301  const char *key = 0;
302  if( !umdbus_parser_get_string(&entry, &key) )
303  break;
304  if( strcmp(key, "Status") )
305  continue;
306  DBusMessageIter var;
307  if( !umdbus_parser_get_variant(&entry, &var) )
308  break;
309  const char *val = 0;
310  if( !umdbus_parser_get_string(&var, &val) )
311  break;
312  status = g_strdup(val);
313  break;
314  }
315  }
316  }
317 
318 EXIT:
319  if( rsp )
320  dbus_message_unref(rsp);
321 
322  if( con )
323  dbus_connection_unref(con);
324 
325  dbus_error_free(&err);
326 
327  log_warning("modem status = %s", status ?: "n/a");
328 
329  return status;
330 }
331 
336 static bool
337 ofono_get_roaming_status(void)
338 {
339  LOG_REGISTER_CONTEXT;
340 
341  bool roaming = false;
342  gchar *modem = 0;
343  gchar *status = 0;
344 
345  if( !(modem = ofono_get_default_modem()) )
346  goto EXIT;
347 
348  if( !(status = ofono_get_modem_status(modem)) )
349  goto EXIT;
350 
351  if( !strcmp(status, "roaming") )
352  roaming = true;
353 
354 EXIT:
355  g_free(status);
356  g_free(modem);
357 
358  log_warning("modem roaming = %d", roaming);
359 
360  return roaming;
361 }
362 #endif /* OFONO */
363 
364 /* ========================================================================= *
365  * CONNMAN
366  * ========================================================================= */
367 
368 #ifdef CONNMAN
369 # define CONNMAN_SERVICE "net.connman"
370 # define CONNMAN_TECH_INTERFACE "net.connman.Technology"
371 # define CONNMAN_ERROR_ALREADY_ENABLED "net.connman.Error.AlreadyEnabled"
372 # define CONNMAN_ERROR_ALREADY_DISABLED "net.connman.Error.AlreadyDisabled"
373 
374 /* ------------------------------------------------------------------------- *
375  * TECHNOLOGY interface
376  * ------------------------------------------------------------------------- */
377 
387 static bool
388 connman_technology_set_tethering(DBusConnection *con, const char *technology, bool on,
389  DBusError *err)
390 {
391  LOG_REGISTER_CONTEXT;
392 
393  bool res = FALSE;
394  DBusMessage *rsp = 0;
395  const char *key = "Tethering";
396  dbus_bool_t val = on;
397 
398  rsp = umdbus_blocking_call(con,
399  CONNMAN_SERVICE,
400  technology,
401  CONNMAN_TECH_INTERFACE,
402  "SetProperty",
403  err,
404  DBUS_TYPE_STRING, &key,
405  DBUS_TYPE_VARIANT,
406  DBUS_TYPE_BOOLEAN, &val,
407  DBUS_TYPE_INVALID);
408 
409  if( !rsp ) {
410  if( on ) {
411  if( !g_strcmp0(err->name, CONNMAN_ERROR_ALREADY_ENABLED) )
412  goto SUCCESS;
413  }
414  else {
415  if( !g_strcmp0(err->name, CONNMAN_ERROR_ALREADY_DISABLED) )
416  goto SUCCESS;
417  }
418  log_err("%s.%s method call failed: %s: %s",
419  CONNMAN_TECH_INTERFACE, "SetProperty",
420  err->name, err->message);
421  goto FAILURE;
422  }
423 
424 SUCCESS:
425  log_debug("%s tethering %s", technology, on ? "on" : "off");
426  dbus_error_free(err);
427  res = TRUE;
428 
429 FAILURE:
430  if( rsp )
431  dbus_message_unref(rsp);
432 
433  return res;
434 }
435 
436 /* ------------------------------------------------------------------------- *
437  * MANAGER interface
438  * ------------------------------------------------------------------------- */
439 
448 static gchar *
449 connman_manager_get_service_path(DBusConnection *con, const char *type)
450 {
451  LOG_REGISTER_CONTEXT;
452 
453  gchar *service = 0;
454  DBusError err = DBUS_ERROR_INIT;
455  DBusMessage *rsp = 0;
456 
457  rsp = umdbus_blocking_call(con,
458  "net.connman",
459  "/",
460  "net.connman.Manager",
461  "GetServices",
462  &err,
463  DBUS_TYPE_INVALID);
464  if( !rsp )
465  goto EXIT;
466 
467  // a(oa{sv}) -> get object path in the first struct matching given type
468  DBusMessageIter body;
469  if( umdbus_parser_init(&body, rsp) ) {
470  // @ body
471  DBusMessageIter array_of_structs;
472  if( umdbus_parser_get_array(&body, &array_of_structs) ) {
473  // @ array of structs
474  DBusMessageIter astruct;
475  while( umdbus_parser_get_struct(&array_of_structs, &astruct) ) {
476  // @ struct
477  const char *object = 0;
478  if( !umdbus_parser_get_object(&astruct, &object) )
479  break;
480  DBusMessageIter array_of_entries;
481  if( !umdbus_parser_get_array(&astruct, &array_of_entries) )
482  break;
483  // @ array of dict entries
484  DBusMessageIter entry;
485  while( umdbus_parser_get_entry(&array_of_entries, &entry) ) {
486  // @ dict entry
487  const char *key = 0;
488  if( !umdbus_parser_get_string(&entry, &key) )
489  break;
490  if( strcmp(key, "Type") )
491  continue;
492  DBusMessageIter var;
493  if( !umdbus_parser_get_variant(&entry, &var) )
494  break;
495  const char *value = 0;
496  if( !umdbus_parser_get_string(&var, &value) )
497  break;
498  if( strcmp(value, type) )
499  continue;
500  service = g_strdup(object);
501  goto EXIT;
502  }
503  }
504  }
505  }
506 
507 EXIT:
508  if( rsp )
509  dbus_message_unref(rsp);
510 
511  dbus_error_free(&err);
512 
513  log_warning("%s service = %s", type, service ?: "n/a");
514 
515  return service;
516 }
517 
526 static bool
527 connman_service_get_connection_data(DBusConnection *con,
528  const char *service,
529  ipforward_data_t *ipforward)
530 {
531  LOG_REGISTER_CONTEXT;
532 
533  bool ack = false;
534  DBusMessage *rsp = NULL;
535  DBusError err = DBUS_ERROR_INIT;
536 
537  log_debug("Filling in dns data");
538 
539  rsp = umdbus_blocking_call(con,
540  "net.connman",
541  service,
542  "net.connman.Service",
543  "GetProperties",
544  &err,
545  DBUS_TYPE_INVALID);
546  if( !rsp )
547  goto EXIT;
548 
549  const char *dns1 = 0;
550  const char *dns2 = 0;
551  const char *state = 0;
552  const char *interface = 0;
553 
554  DBusMessageIter body;
555  if( umdbus_parser_init(&body, rsp) ) {
556  // @ body
557  DBusMessageIter array_of_entries;
558  if( umdbus_parser_get_array(&body, &array_of_entries) ) {
559  // @ array of entries
560  DBusMessageIter entry;
561  while( umdbus_parser_get_entry(&array_of_entries, &entry) ) {
562  // @ dict entry
563  const char *key = 0;
564  if( !umdbus_parser_get_string(&entry, &key) )
565  break;
566  DBusMessageIter var;
567  if( !umdbus_parser_get_variant(&entry, &var) )
568  break;
569 
570  if( !strcmp(key, "Nameservers"))
571  {
572  DBusMessageIter array_of_strings;
573  if( umdbus_parser_get_array(&var, &array_of_strings) ) {
574  // expect 0, 1, or 2 entries
575  if( !umdbus_parser_at_end(&array_of_strings) )
576  umdbus_parser_get_string(&array_of_strings, &dns1);
577  if( !umdbus_parser_at_end(&array_of_strings) )
578  umdbus_parser_get_string(&array_of_strings, &dns2);
579  }
580  }
581  else if( !strcmp(key, "State"))
582  {
583  umdbus_parser_get_string(&var, &state);
584  }
585  else if( !strcmp(key, "Ethernet"))
586  {
587  DBusMessageIter array_of_en_entries;
588  if( umdbus_parser_get_array(&var, &array_of_en_entries) ) {
589  DBusMessageIter en_entry;
590  while( umdbus_parser_get_entry(&array_of_en_entries, &en_entry) ) {
591  const char *en_key = 0;
592  if( !umdbus_parser_get_string(&en_entry, &en_key) )
593  break;
594  if( strcmp(en_key, "Interface") )
595  continue;
596  DBusMessageIter en_var;
597  if( umdbus_parser_get_variant(&en_entry, &en_var) )
598  umdbus_parser_get_string(&en_var, &interface);
599  }
600  }
601  }
602  }
603  }
604  }
605 
606  bool connected = (!g_strcmp0(state, "ready") ||
607  !g_strcmp0(state, "online"));
608 
609  log_debug("state = %s", state ?: "n/a");
610  log_debug("connected = %s", connected ? "true" : "false");
611  log_debug("interface = %s", interface ?: "n/a");
612  log_debug("dns1 = %s", dns1 ?: "n/a");
613  log_debug("dns2 = %s", dns2 ?: "n/a");
614 
615  if( !dns1 || !interface || !connected )
616  goto EXIT;
617 
618  ipforward_data_set_dns1(ipforward, dns1);
619  ipforward_data_set_dns2(ipforward, dns2 ?: dns1);
620  ipforward_data_set_nat_interface(ipforward, interface);
621 
622  ack = true;
623 
624 EXIT:
625  if( rsp )
626  dbus_message_unref(rsp);
627 
628  dbus_error_free(&err);
629 
630  return ack;
631 }
632 
633 /* ------------------------------------------------------------------------- *
634  * USB-MODED interface
635  * ------------------------------------------------------------------------- */
636 
643 static bool
644 connman_get_connection_data(ipforward_data_t *ipforward)
645 {
646  LOG_REGISTER_CONTEXT;
647 
648  bool ack = false;
649  DBusConnection *con = 0;
650  gchar *cellular = 0;
651  gchar *wifi = 0;
652 
653  if( !(con = umdbus_get_connection()) )
654  goto FAILURE;
655 
656  /* Try to get connection data from cellular service */
657  if( !(cellular = connman_manager_get_service_path(con, "cellular")) )
658  log_warning("no sellular service");
659  else if( connman_service_get_connection_data(con, cellular, ipforward) )
660  goto SUCCESS;
661 
662  /* Try to get connection data from wifi service */
663  if( !(wifi = connman_manager_get_service_path(con, "wifi")) )
664  log_warning("no wifi service");
665  else if( connman_service_get_connection_data(con, wifi, ipforward) )
666  goto SUCCESS;
667 
668  /* Abandon hope */
669  goto FAILURE;
670 
671 SUCCESS:
672  ack = true;
673 
674 FAILURE:
675  if( !ack )
676  log_warning("no connection data");
677  else
678  log_debug("got connection data");
679 
680  g_free(wifi);
681  g_free(cellular);
682 
683  if( con )
684  dbus_connection_unref(con);
685 
686  return ack;
687 }
688 
696 bool
697 connman_set_tethering(const char *technology, bool on)
698 {
699  LOG_REGISTER_CONTEXT;
700 
701  bool res = false;
702  DBusError err = DBUS_ERROR_INIT;
703  DBusConnection *con = 0;
704 
705  if( !(con = umdbus_get_connection()) )
706  goto EXIT;
707 
708  res = connman_technology_set_tethering(con, technology, on, &err);
709 
710 EXIT:
711  dbus_error_free(&err);
712 
713  if( con )
714  dbus_connection_unref(con);
715 
716  log_debug("set tethering(%s) = %s -> %s", technology,
717  on ? "on" : "off", res ? "ack" : "nak");
718 
719  return res;
720 }
721 #endif /* CONNMAN */
722 
723 /* ========================================================================= *
724  * LEGACY
725  * ========================================================================= */
726 
727 #ifndef CONNMAN
728 
732 static bool
733 legacy_get_connection_data(ipforward_data_t *ipforward)
734 {
735  LOG_REGISTER_CONTEXT;
736 
737  static const char path[] = "/etc/resolv.conf";
738 
739  bool ack = false;
740  FILE *file = 0;
741  char *buff = 0;
742  size_t size = 0;
743 
744  if( !(file = fopen(path, "r")) ) {
745  log_warning("%s: can't open for reading: %m", path);
746  goto EXIT;
747  }
748 
749  int count = 0;
750  while( count < 2 && getline(&buff, &size, file) >= 0 ) {
751  /* skip comment and empty lines */
752  if( strchr("#\n", *buff) )
753  continue;
754 
755  gchar **tokens = g_strsplit(buff, " ", 3);
756  if( !tokens || !tokens[0] || !tokens[1] ) {
757  // ignore
758  }
759  else if( !g_strcmp0(tokens[0], "nameserver") ) {
760  // TODO: can have '\n' at eol?
761  g_strstrip(tokens[1]);
762  if( ++count == 1 )
763  ipforward_data_set_dns1(ipforward, tokens[1]);
764  else
765  ipforward_data_set_dns2(ipforward, tokens[1]);
766  }
767  g_strfreev(tokens);
768  }
769 
770  if( count < 1 ) {
771  log_warning("%s: no nameserver lines found", path);
772  goto EXIT;
773  }
774 
775  /* FIXME: connman_service_get_connection_data() duplicates
776  * dns1 if dns2 is not set - is this necessary?
777  */
778  if( count == 1 )
779  ipforward_data_set_dns2(ipforward, ipforward->dns1);
780 
781  ack = true;
782 
783 EXIT:
784  free(buff);
785 
786  if( file )
787  fclose(file);
788 
789  return ack;
790 }
791 #endif
792 
793 /* ========================================================================= *
794  * NETWORK
795  * ========================================================================= */
796 
801 static bool
802 network_interface_exists(char *interface)
803 {
804  LOG_REGISTER_CONTEXT;
805 
806  bool ack = false;
807 
808  if(interface)
809  {
810  char path[PATH_MAX];
811  snprintf(path, sizeof path, "/sys/class/net/%s", interface);
812  ack = (access(path, F_OK) == 0);
813  }
814 
815  return ack;
816 }
817 
824 static char *
825 network_get_interface(const modedata_t *data)
826 {
827  LOG_REGISTER_CONTEXT;
828 
829  (void)data; // FIXME: why is this passed in the 1st place?
830 
831  char *interface = 0;
832  char *setting = config_get_network_setting(NETWORK_INTERFACE_KEY);
833 
834  if( network_interface_exists(setting) )
835  {
836  /* Use the configured value */
837  interface = setting, setting = 0;
838  }
839  else
840  {
841  /* Fall back to default value */
842  interface = strdup(default_interface);
843  if( !network_interface_exists(interface) )
844  {
845  log_warning("Neither configured %s nor fallback %s interface exists."
846  " Check your config!",
847  setting ?: "NULL",
848  interface ?: "NULL");
849  free(interface), interface = 0;
850  }
851  }
852 
853  log_debug("interface = %s", interface ?: "NULL");
854  free(setting);
855  return interface;
856 }
857 
866 static int
867 network_setup_ip_forwarding(const modedata_t *data, ipforward_data_t *ipforward)
868 {
869  LOG_REGISTER_CONTEXT;
870 
871  int failed = 1;
872  char *interface = 0;
873  char *nat_interface = 0;
874 
875  char command[256];
876 
877  if( !(interface = network_get_interface(data)) )
878  goto EXIT;
879 
880  nat_interface = config_get_network_setting(NETWORK_NAT_INTERFACE_KEY);
881  if( !nat_interface ) {
882  if( !ipforward->nat_interface ) {
883  log_debug("No nat interface available!");
884  goto EXIT;
885  }
886  nat_interface = strdup(ipforward->nat_interface);
887  }
888 
889  write_to_file("/proc/sys/net/ipv4/ip_forward", "1");
890 
891  snprintf(command, sizeof command, "/sbin/iptables -t nat -A POSTROUTING -o %s -j MASQUERADE", nat_interface);
892  common_system(command);
893 
894  snprintf(command, sizeof command, "/sbin/iptables -A FORWARD -i %s -o %s -m state --state RELATED,ESTABLISHED -j ACCEPT", nat_interface, interface);
895  common_system(command);
896 
897  snprintf(command, sizeof command, "/sbin/iptables -A FORWARD -i %s -o %s -j ACCEPT", interface, nat_interface);
898  common_system(command);
899 
900  log_debug("ipforwarding success!");
901  failed = 0;
902 
903 EXIT:
904  free(interface);
905  free(nat_interface);
906 
907  return failed;
908 }
909 
912 static void
913 network_cleanup_ip_forwarding(void)
914 {
915  LOG_REGISTER_CONTEXT;
916 
917  write_to_file("/proc/sys/net/ipv4/ip_forward", "0");
918 
919  common_system("/sbin/iptables -F FORWARD");
920 }
921 
926 static int
927 network_check_udhcpd_symlink(void)
928 {
929  LOG_REGISTER_CONTEXT;
930 
931  int ret = -1;
932  char dest[sizeof UDHCP_CONFIG_PATH + 1];
933  ssize_t rc = readlink(UDHCP_CONFIG_LINK, dest, sizeof dest - 1);
934 
935  if( rc < 0 ) {
936  if( errno != ENOENT )
937  log_err("%s: can't read symlink: %m", UDHCP_CONFIG_LINK);
938  }
939  else if( (size_t)rc < sizeof dest ) {
940  dest[rc] = 0;
941  if( strcmp(dest, UDHCP_CONFIG_PATH) )
942  log_warning("%s: symlink is invalid", UDHCP_CONFIG_LINK);
943  else
944  ret = 0;
945  }
946  return ret;
947 }
948 
956 static int
957 network_write_udhcpd_config(const modedata_t *data, ipforward_data_t *ipforward)
958 {
959  LOG_REGISTER_CONTEXT;
960 
961  // assume failure
962  int err = -1;
963 
964  FILE *conffile = 0;
965  char *interface = 0;
966  char *ip = 0;
967  char *netmask = 0;
968 
969  if( !(interface = network_get_interface(data)) ) {
970  log_err("no network interface");
971  goto EXIT;
972  }
973 
974  /* generate start and end ip based on the setting */
975  if( !(ip = config_get_network_setting(NETWORK_IP_KEY)) ) {
976  log_err("no network address");
977  goto EXIT;
978  }
979 
980  int len = 0;
981  if( sscanf(ip, "%*d.%*d.%*d%n.%*d", &len) == EOF || ip[len] != '.') {
982  log_err("malformed network address: %s", ip);
983  goto EXIT;
984  }
985 
986  if( !(netmask = config_get_network_setting(NETWORK_NETMASK_KEY)) ) {
987  log_err("no network address mask");
988  goto EXIT;
989  }
990 
991  /* /tmp and /run is often tmpfs, so we avoid writing to flash */
992  if( mkdir(UDHCP_CONFIG_DIR, 0775) == -1 && errno != EEXIST ) {
993  log_warning("%s: can't create directory: %m", UDHCP_CONFIG_DIR);
994  }
995 
996  /* print all data in the file */
997  if( !(conffile = fopen(UDHCP_CONFIG_PATH, "w")) ) {
998  log_err("%s: can't open for writing: %m", UDHCP_CONFIG_PATH);
999  goto EXIT;
1000  }
1001 
1002  fprintf(conffile, "start\t%.*s.1\n", len, ip);
1003  fprintf(conffile, "end\t%.*s.15\n", len, ip);
1004  fprintf(conffile, "interface\t%s\n", interface);
1005  fprintf(conffile, "option\tsubnet\t%s\n", netmask);
1006  fprintf(conffile, "option\tlease\t3600\n");
1007  fprintf(conffile, "max_leases\t15\n");
1008 
1009  if(ipforward != NULL)
1010  {
1011  if( !ipforward->dns1 || !ipforward->dns2 )
1012  log_debug("No dns info!");
1013  else
1014  fprintf(conffile, "opt\tdns\t%s %s\n", ipforward->dns1, ipforward->dns2);
1015  fprintf(conffile, "opt\trouter\t%s\n", ip);
1016  }
1017 
1018  fclose(conffile), conffile = 0;
1019 
1020  /* check that we have a valid symlink */
1021  if( network_check_udhcpd_symlink() != 0 ) {
1022  if( unlink(UDHCP_CONFIG_LINK) == -1 && errno != ENOENT )
1023  log_warning("%s: can't remove invalid config: %m", UDHCP_CONFIG_LINK);
1024 
1025  if( symlink(UDHCP_CONFIG_PATH, UDHCP_CONFIG_LINK) == -1 ) {
1026  log_err("%s: can't create symlink to %s: %m",
1027  UDHCP_CONFIG_LINK, UDHCP_CONFIG_PATH);
1028  goto EXIT;
1029  }
1030  log_debug("%s: symlink to %s created",
1031  UDHCP_CONFIG_LINK, UDHCP_CONFIG_PATH);
1032  }
1033 
1034  // success
1035  err = 0;
1036 
1037 EXIT:
1038  free(netmask);
1039  free(ip);
1040  free(interface);
1041  if( conffile )
1042  fclose(conffile);
1043 
1044  return err;
1045 }
1046 
1058 int
1060 {
1061  LOG_REGISTER_CONTEXT;
1062 
1063  ipforward_data_t *ipforward = NULL;
1064  int ret = 1;
1065 
1066  /* Set up nat info only if it is required */
1067  if( data->nat )
1068  {
1069 #ifdef OFONO
1070  /* check if we are roaming or not */
1071  if( ofono_get_roaming_status() ) {
1072  /* get permission to use roaming */
1073  if(config_is_roaming_not_allowed())
1074  goto EXIT;
1075  }
1076 #endif
1077 
1078  ipforward = ipforward_data_create();
1079 
1080 #ifdef CONNMAN
1081  if( !connman_get_connection_data(ipforward) )
1082  {
1083  log_debug("data connection not available from connman!");
1084  /* TODO: send a message to the UI */
1085  goto EXIT;
1086  }
1087 #else
1088  if( !legacy_get_connection_data(ipforward) ) {
1089  log_debug("data connection not available in resolv.conf!");
1090  goto EXIT;
1091  }
1092 #endif
1093  }
1094 
1095  /* ipforward can be NULL here, which is expected and handled in this function */
1096  ret = network_write_udhcpd_config(data, ipforward);
1097 
1098  if( ret == 0 && data->nat )
1099  ret = network_setup_ip_forwarding(data, ipforward);
1100 
1101 EXIT:
1102  ipforward_data_delete(ipforward);
1103 
1104  return ret;
1105 }
1106 
1113 int
1115 {
1116  LOG_REGISTER_CONTEXT;
1117 
1118  // assume failure
1119  int ret = 1;
1120 
1121  gchar *interface = 0;
1122  gchar *address = 0;
1123  gchar *netmask = 0;
1124  gchar *gateway = 0;
1125 
1126  char command[256];
1127 
1128  if( !(interface = network_get_interface(data)) ) {
1129  log_err("no network interface");
1130  goto EXIT;
1131  }
1132 
1133  if( !(address = config_get_network_setting(NETWORK_IP_KEY)) ) {
1134  log_err("no network address");
1135  goto EXIT;
1136  }
1137 
1138  if( !(netmask = config_get_network_setting(NETWORK_NETMASK_KEY)) ) {
1139  log_err("no network address mask");
1140  goto EXIT;
1141  }
1142 
1143  if( !(gateway = config_get_network_setting(NETWORK_GATEWAY_KEY)) ) {
1144  /* gateway is optional */
1145  log_warning("no network gateway");
1146  }
1147 
1148  if( !strcmp(address, "dhcp") )
1149  {
1150  snprintf(command, sizeof command,"dhclient -d %s", interface);
1151  if( common_system(command) != 0 ) {
1152  snprintf(command, sizeof command,"udhcpc -i %s", interface);
1153  if( common_system(command) != 0 )
1154  goto EXIT;
1155  }
1156  }
1157  else
1158  {
1159  snprintf(command, sizeof command,"ifconfig %s %s netmask %s", interface, address, netmask);
1160  if( common_system(command) != 0 )
1161  goto EXIT;
1162  }
1163 
1164  /* TODO: Check first if there is a gateway set */
1165  if( gateway )
1166  {
1167  snprintf(command, sizeof command,"route add default gw %s", gateway);
1168  if( common_system(command) != 0 )
1169  goto EXIT;
1170  }
1171 
1172  ret = 0;
1173 
1174 EXIT:
1175  log_debug("iface=%s addr=%s mask=%s gw=%s -> %s",
1176  interface ?: "n/a",
1177  address ?: "n/a",
1178  netmask ?: "n/a",
1179  gateway ?: "n/a",
1180  ret ? "failure" : "success");
1181 
1182  g_free(gateway);
1183  g_free(netmask);
1184  g_free(address);
1185  g_free(interface);
1186  return ret;
1187 }
1188 
1193 void
1195 {
1196  LOG_REGISTER_CONTEXT;
1197 
1198  gchar *interface = network_get_interface(data);
1199 
1200  char command[256];
1201 
1202  log_debug("iface=%s nat=%d", interface ?: "n/a", data->nat);
1203 
1204  if( interface ) {
1205  snprintf(command, sizeof command,"ifconfig %s down", interface);
1206  common_system(command);
1207  }
1208 
1209  /* dhcp client shutdown happens on disconnect automatically */
1210  if(data->nat)
1211  network_cleanup_ip_forwarding();
1212 
1213  g_free(interface);
1214 }
1215 
1220 void
1222 {
1223  LOG_REGISTER_CONTEXT;
1224 
1225  if( control_get_cable_state() == CABLE_STATE_PC_CONNECTED ) {
1227  if( data && data->network ) {
1228  network_down(data);
1229  network_up(data);
1230  }
1231  modedata_free(data);
1232  }
1233 }
modedata_free
void modedata_free(modedata_t *self)
Definition: usb_moded-dyn-config.c:76
modedata_t::nat
int nat
Definition: usb_moded-dyn-config.h:121
usb_moded-dbus-private.h
worker_dup_usb_mode_data
modedata_t * worker_dup_usb_mode_data(void)
Definition: usb_moded-worker.c:554
ipforward_data_t::dns2
char * dns2
Definition: usb_moded-network.c:65
ipforward_data_t
Definition: usb_moded-network.c:60
usb_moded-modesetting.h
modedata_t::network
int network
Definition: usb_moded-dyn-config.h:105
network_up
int network_up(const modedata_t *data)
Definition: usb_moded-network.c:1114
ipforward_data_t::nat_interface
char * nat_interface
Definition: usb_moded-network.c:67
usb_moded-network.h
usb_moded-config-private.h
usb_moded-control.h
ipforward_data_t::dns1
char * dns1
Definition: usb_moded-network.c:63
network_update_udhcpd_config
int network_update_udhcpd_config(const modedata_t *data)
Definition: usb_moded-network.c:1059
ipforward_data_t
struct ipforward_data_t ipforward_data_t
network_down
void network_down(const modedata_t *data)
Definition: usb_moded-network.c:1194
usb_moded-log.h
modedata_t
Definition: usb_moded-dyn-config.h:100
control_get_cable_state
cable_state_t control_get_cable_state(void)
Definition: usb_moded-control.c:846
usb_moded-worker.h
network_update
void network_update(void)
Definition: usb_moded-network.c:1221