usb_moded 0.86.0+mer58
usb_moded-network.c
Go to the documentation of this file.
1
31
32/*============================================================================= */
33
34#include "usb_moded-network.h"
35
37#include "usb_moded-control.h"
38#include "usb_moded-log.h"
40#include "usb_moded-worker.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
60typedef struct ipforward_data_t
61{
63 char *dns1;
65 char *dns2;
69
70/* ========================================================================= *
71 * Prototypes
72 * ========================================================================= */
73
74/* ------------------------------------------------------------------------- *
75 * IPFORWARD_DATA
76 * ------------------------------------------------------------------------- */
77
78static ipforward_data_t *ipforward_data_create (void);
79static void ipforward_data_delete (ipforward_data_t *self);
80static void ipforward_data_clear (ipforward_data_t *self);
81static void ipforward_data_set_dns1 (ipforward_data_t *self, const char *dns);
82static void ipforward_data_set_dns2 (ipforward_data_t *self, const char *dns);
83static void ipforward_data_set_nat_interface(ipforward_data_t *self, const char *interface);
84
85/* ------------------------------------------------------------------------- *
86 * OFONO
87 * ------------------------------------------------------------------------- */
88
89#ifdef OFONO
90static gchar *ofono_get_default_modem (void);
91static gchar *ofono_get_modem_status (const char *modem);
92static bool ofono_get_roaming_status(void);
93#endif
94
95/* ------------------------------------------------------------------------- *
96 * CONNMAN
97 * ------------------------------------------------------------------------- */
98
99#ifdef CONNMAN
100static bool connman_technology_set_tethering (DBusConnection *con, const char *technology, bool on, DBusError *err);
101static gchar *connman_manager_get_service_path (DBusConnection *con, const char *type);
102static bool connman_service_get_connection_data(DBusConnection *con, const char *service, ipforward_data_t *ipforward);
103static bool connman_get_connection_data (ipforward_data_t *ipforward);
104bool connman_set_tethering (const char *technology, bool on);
105#endif
106
107/* ------------------------------------------------------------------------- *
108 * LEGACY
109 * ------------------------------------------------------------------------- */
110
111#ifndef CONNMAN
112static bool legacy_get_connection_data(ipforward_data_t *ipforward);
113#endif
114
115/* ------------------------------------------------------------------------- *
116 * NETWORK
117 * ------------------------------------------------------------------------- */
118
119static bool network_interface_exists (char *interface);
120static char *network_get_interface (const modedata_t *data);
121static int network_setup_ip_forwarding (const modedata_t *data, ipforward_data_t *ipforward);
122static void network_cleanup_ip_forwarding(void);
123static int network_check_udhcpd_symlink (void);
124static int network_write_udhcpd_config (const modedata_t *data, ipforward_data_t *ipforward);
126int network_up (const modedata_t *data);
127void network_down (const modedata_t *data);
128void network_update (void);
129
130/* ========================================================================= *
131 * Data
132 * ========================================================================= */
133
134static const char default_interface[] = "usb0";
135
136/* ========================================================================= *
137 * IPFORWARD_DATA
138 * ========================================================================= */
139
140static ipforward_data_t *
141ipforward_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
154static void
155ipforward_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
166static void
167ipforward_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
176static void
177ipforward_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
185static void
186ipforward_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
194static void
195ipforward_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
215
216static gchar *
217ofono_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
252EXIT:
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
274static gchar *
275ofono_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
318EXIT:
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
336static bool
337ofono_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
354EXIT:
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
387static bool
388connman_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
424SUCCESS:
425 log_debug("%s tethering %s", technology, on ? "on" : "off");
426 dbus_error_free(err);
427 res = TRUE;
428
429FAILURE:
430 if( rsp )
431 dbus_message_unref(rsp);
432
433 return res;
434}
435
436/* ------------------------------------------------------------------------- *
437 * MANAGER interface
438 * ------------------------------------------------------------------------- */
439
448static gchar *
449connman_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
507EXIT:
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
526static bool
527connman_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
624EXIT:
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
643static bool
644connman_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
671SUCCESS:
672 ack = true;
673
674FAILURE:
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
696bool
697connman_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
710EXIT:
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
732static bool
733legacy_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
783EXIT:
784 free(buff);
785
786 if( file )
787 fclose(file);
788
789 return ack;
790}
791#endif
792
793/* ========================================================================= *
794 * NETWORK
795 * ========================================================================= */
796
801static bool
802network_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
824static char *
825network_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
866static int
867network_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
903EXIT:
904 free(interface);
905 free(nat_interface);
906
907 return failed;
908}
909
912static void
913network_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
926static int
927network_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
956static int
957network_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
1037EXIT:
1038 free(netmask);
1039 free(ip);
1040 free(interface);
1041 if( conffile )
1042 fclose(conffile);
1043
1044 return err;
1045}
1046
1058int
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
1101EXIT:
1102 ipforward_data_delete(ipforward);
1103
1104 return ret;
1105}
1106
1113int
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
1174EXIT:
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
1193void
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
1220void
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}
cable_state_t control_get_cable_state(void)
void modedata_free(modedata_t *self)
struct modedata_t modedata_t
void network_update(void)
int network_up(const modedata_t *data)
struct ipforward_data_t ipforward_data_t
int network_update_udhcpd_config(const modedata_t *data)
void network_down(const modedata_t *data)
modedata_t * worker_dup_usb_mode_data(void)