/* * i host = 0 mean INADDR_ANY only ipv4 */ dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr) { struct in_addr inaddr; IPADDR *addr = 0; const char *errmsg; #ifdef HAVE_IPV6 struct in6_addr inaddr6; #endif dlist *addr_list = New(dlist(addr, &addr->link)); if (!host || host[0] == '\0') { if (family != 0) { addr_list->append(add_any(family)); } else { addr_list->append(add_any(AF_INET)); #ifdef HAVE_IPV6 addr_list->append(add_any(AF_INET6)); #endif } } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */ addr = New(IPADDR(AF_INET)); addr->set_type(IPADDR::R_MULTIPLE); addr->set_addr4(&inaddr); addr_list->append(addr); #ifdef HAVE_IPV6 } else if (inet_pton(AF_INET6, host, &inaddr6) == 1) { addr = New(IPADDR(AF_INET6)); addr->set_type(IPADDR::R_MULTIPLE); addr->set_addr6(&inaddr6); addr_list->append(addr); #endif } else { if (family != 0) { errmsg = resolv_host(family, host, addr_list); if (errmsg) { *errstr = errmsg; free_addresses(addr_list); return 0; } } else { #ifdef HAVE_IPV6 /* We try to resolv host for ipv6 and ipv4, the connection procedure * will try to reach the host for each protocols. We report only "Host * not found" ipv4 message (no need to have ipv6 and ipv4 messages). */ resolv_host(AF_INET6, host, addr_list); #endif errmsg = resolv_host(AF_INET, host, addr_list); if (addr_list->size() == 0) { *errstr = errmsg; free_addresses(addr_list); return 0; } } } return addr_list; }
/*** main ***/ int main (int argc, char **argv) { int rc = EXIT_FAILURE; int i, nls; unsigned int version = 0, help = 0; program = argv[0]; /* get the verbose status */ while ((i = getopt_long(argc, argv, optstring, options_long, NULL)) != -1) { switch (i) { case 'h': help++; break; case 't': notification_timeout = atof(optarg) * 1000; break; case 'v': verbose++; break; case 'V': verbose++; version++; break; } } if (verbose > 0) printf ("%s: %s v%s" #ifdef HAVE_SYSTEMD " +systemd" #endif " (compiled: " __DATE__ ", " __TIME__ ")\n", program, PROGNAME, VERSION); if (help > 0) printf("usage: %s [-h] [-t TIMEOUT] [-v[v]] [-V]\n", program); if (version > 0 || help > 0) return EXIT_SUCCESS; if ((nls = open_netlink()) < 0) { fprintf (stderr, "%s: Error opening netlink socket!\n", program); goto out40; } if (notify_init(PROGNAME) == FALSE) { fprintf (stderr, "%s: Can't create notify.\n", program); goto out30; } signal(SIGINT, received_signal); signal(SIGTERM, received_signal); #ifdef HAVE_SYSTEMD sd_notify(0, "READY=1\nSTATUS=Waiting for netlink events..."); #endif while (doexit == 0) { if (read_event(nls) != EXIT_SUCCESS) { fprintf(stderr, "%s: read_event returned error.\n", program); goto out10; } } if (verbose > 0) printf("%s: Exiting...\n", program); /* report stopping to systemd */ #ifdef HAVE_SYSTEMD sd_notify(0, "STOPPING=1\nSTATUS=Stopping..."); #endif for(; maxinterface > 0; maxinterface--) { if (verbose > 0) printf("%s: Freeing interface %d: %s\n", program, maxinterface, ifs[maxinterface].name); free_addresses(ifs[maxinterface].addresses_seen); if (ifs[maxinterface].notification != NULL) g_object_unref(G_OBJECT(ifs[maxinterface].notification)); } rc = EXIT_SUCCESS; out10: if (ifs != NULL) free(ifs); /* out20: */ notify_uninit(); out30: if (close(nls) < 0) fprintf(stderr, "%s: Failed to close socket.\n", program); out40: #ifdef HAVE_SYSTEMD sd_notify(0, "STATUS=Stopped. Bye!"); #endif return rc; }
int main(int argc, char *argv[]) { struct sigaction sa; char c; int option_index = 0; // Program name program_name = strrchr(argv[0], '/'); if (program_name) program_name ++; else program_name = argv[0]; // Parse command line options do { c = getopt_long(argc, argv, short_options, long_options, &option_index); switch (c) { case -1: break; case 'r': capture_file = fopen(optarg, "r"); if (!capture_file) { LOGGER(ERROR, "Cannot open file '%s': %s\n", optarg, strerror(errno)); return EXIT_FAILURE; } break; case 'l': specified_addresses = 1; if (parse_addresses(optarg)) { LOGGER(ERROR, "Error parsing local addresses\n"); return EXIT_FAILURE; } break; case 'p': port = strdup(optarg); break; case 'f': if (!check_format(optarg)) { LOGGER(ERROR, "Bad format provided: `%s'\n", optarg); return EXIT_FAILURE; } global_options.format = optarg; break; case 't': global_options.interval = strtoul(optarg, NULL, 10); if (interval <= 0 || interval >= MAX_OUTPUT_INTERVAL) { LOGGER(ERROR, "Bad interval provided\n"); return EXIT_FAILURE; } break; case 'n': global_options.iterations = strtol(optarg, NULL, 10); if (interval < 0) { LOGGER(ERROR, "Bad iterations provided\n"); return EXIT_FAILURE; } break; case 'T': global_options.threshold = strtol(optarg, NULL, 10) * 1000; if (global_options.threshold < 0) { LOGGER(ERROR, "Bad threshold provided\n"); return EXIT_FAILURE; } break; case 'd': global_options.server = strdup(optarg); break; case 'i': global_options.interface = strdup(optarg); break; case 'c': global_options.is_client = 1; break; case 's': global_options.header = optarg; global_options.show_header = 1; break; case 'S': global_options.show_header = 0; break; case 'h': dump_help(stdout); return EXIT_SUCCESS; case 'V': dump_version(stdout); return EXIT_SUCCESS; default: dump_usage(stderr); return EXIT_FAILURE; } } while (c != -1); if(! global_options.interface) { global_options.interface = "any"; } if(global_options.is_client) { if(!global_options.server) { LOGGER(ERROR, "%s -d destination server is required.\n", argv[0]); return 0; } } if(global_options.server) { global_options.is_client = 1; } if(!port) { LOGGER(ERROR, "%s -p port is required.\n", argv[0]); return 0; } // Set up signals sa.sa_handler = terminate; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGTERM); sigaddset(&sa.sa_mask, SIGINT); sa.sa_flags = 0; sa.sa_restorer = NULL; sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); // Get local addresses if (!specified_addresses && get_addresses() != 0) return EXIT_FAILURE; // Operations timestamp time(×tamp); // Stats init_stats(); if (capture_file) { output_offline_start(&global_options); offline_capture(capture_file); fclose(capture_file); } else { // Fire up capturing thread pthread_create(&capture_thread_id, NULL, capture, NULL); if(!global_options.threshold) { // Options thread pthread_create(&output_thread_id, NULL, output_thread, &global_options); pthread_kill(output_thread_id, SIGINT); } pthread_join(capture_thread_id, NULL); } free_stats(); free_addresses(); free(global_options.server); return EXIT_SUCCESS; }
/*** msg_handler ***/ int msg_handler (struct sockaddr_nl *nl, struct nlmsghdr *msg) { int rc = EXIT_FAILURE; char *notifystr = NULL; unsigned int errcount = 0; GError *error = NULL; struct ifaddrmsg *ifa; struct ifinfomsg *ifi; struct rtattr *rth; int rtl; char buf[INET6_ADDRSTRLEN]; NotifyNotification *tmp_notification = NULL, *notification = NULL; char *icon = NULL; ifa = (struct ifaddrmsg *) NLMSG_DATA (msg); ifi = (struct ifinfomsg *) NLMSG_DATA (msg); /* make sure we have alloced memory for NotifyNotification and addresses_seen struct array */ if (maxinterface < ifi->ifi_index) { ifs = realloc(ifs, (ifi->ifi_index + 1) * sizeof(struct ifs)); while(maxinterface < ifi->ifi_index) { maxinterface++; if (verbose > 0) printf("%s: Initializing interface %d: ", program, maxinterface); /* get interface name and store it * in case the interface does no longer exist this may fail, * use static string '(unknown)' instead */ if (if_indextoname(maxinterface, ifs[maxinterface].name) == NULL) strcpy(ifs[maxinterface].name, "(unknown)"); if (verbose > 0) printf("%s\n", ifs[maxinterface].name); ifs[maxinterface].state = -1; ifs[maxinterface].deleted = 0; ifs[maxinterface].notification = # if NOTIFY_CHECK_VERSION(0, 7, 0) notify_notification_new(TEXT_TOPIC, NULL, NULL); # else notify_notification_new(TEXT_TOPIC, NULL, NULL, NULL); # endif notify_notification_set_category(ifs[maxinterface].notification, PROGNAME); notify_notification_set_urgency(ifs[maxinterface].notification, NOTIFY_URGENCY_NORMAL); notify_notification_set_timeout(ifs[maxinterface].notification, notification_timeout); ifs[maxinterface].addresses_seen = NULL; } } else if (ifs[ifi->ifi_index].deleted == 1) { if (verbose > 0) printf("%s: Ignoring event for deleted interface %d.\n", program, ifi->ifi_index); rc = EXIT_SUCCESS; goto out; } /* make notification point to the array element, will be overwritten * later when needed for address notification */ notification = ifs[ifi->ifi_index].notification; /* get interface name and store it * in case the interface does no longer exist this may fail, but it does not overwrite */ if_indextoname(ifi->ifi_index, ifs[ifi->ifi_index].name); if (verbose > 1) printf("%s: Event for interface %s (%d): flags = %x, msg type = %d\n", program, ifs[ifi->ifi_index].name, ifi->ifi_index, ifa->ifa_flags, msg->nlmsg_type); switch (msg->nlmsg_type) { /* just return for cases we want to ignore * use break if a notification has to be displayed */ case RTM_NEWADDR: rth = IFA_RTA (ifa); rtl = IFA_PAYLOAD (msg); while (rtl && RTA_OK (rth, rtl)) { if ((rth->rta_type == IFA_LOCAL /* IPv4 */ || rth->rta_type == IFA_ADDRESS /* IPv6 */) && ifa->ifa_scope == RT_SCOPE_UNIVERSE /* no IPv6 scope link */) { inet_ntop(ifa->ifa_family, RTA_DATA (rth), buf, sizeof(buf)); /* check if we already notified about this address */ if (match_address(ifs[ifi->ifi_index].addresses_seen, buf, ifa->ifa_prefixlen)) { if (verbose > 0) printf("%s: Address %s/%d already known for %s, ignoring.\n", program, buf, ifa->ifa_prefixlen, ifs[ifi->ifi_index].name); break; } /* add address to struct */ ifs[ifi->ifi_index].addresses_seen = add_address(ifs[ifi->ifi_index].addresses_seen, buf, ifa->ifa_prefixlen); if (verbose > 1) list_addresses(ifs[ifi->ifi_index].addresses_seen, ifs[ifi->ifi_index].name); /* display notification */ notifystr = newstr_addr(ifs[ifi->ifi_index].name, ifa->ifa_family, buf, ifa->ifa_prefixlen); /* we are done, no need to run more loops */ break; } rth = RTA_NEXT (rth, rtl); } /* we did not find anything to notify */ if (notifystr == NULL) { rc = EXIT_SUCCESS; goto out; } /* do we want new notification, not update the notification about link status */ tmp_notification = # if NOTIFY_CHECK_VERSION(0, 7, 0) notify_notification_new(TEXT_TOPIC, NULL, NULL); # else notify_notification_new(TEXT_TOPIC, NULL, NULL, NULL); # endif notify_notification_set_category(tmp_notification, PROGNAME); notify_notification_set_urgency(tmp_notification, NOTIFY_URGENCY_NORMAL); notify_notification_set_timeout(tmp_notification, notification_timeout); notification = tmp_notification; icon = ICON_NETWORK_ADDRESS; break; case RTM_DELADDR: rth = IFA_RTA (ifa); rtl = IFA_PAYLOAD (msg); while (rtl && RTA_OK (rth, rtl)) { if ((rth->rta_type == IFA_LOCAL /* IPv4 */ || rth->rta_type == IFA_ADDRESS /* IPv6 */) && ifa->ifa_scope == RT_SCOPE_UNIVERSE /* no IPv6 scope link */) { inet_ntop(ifa->ifa_family, RTA_DATA (rth), buf, sizeof(buf)); ifs[ifi->ifi_index].addresses_seen = remove_address(ifs[ifi->ifi_index].addresses_seen, buf, ifa->ifa_prefixlen); if (verbose > 1) list_addresses(ifs[ifi->ifi_index].addresses_seen, ifs[ifi->ifi_index].name); /* we are done, no need to run more loops */ break; } rth = RTA_NEXT (rth, rtl); } rc = EXIT_SUCCESS; goto out; case RTM_NEWROUTE: rc = EXIT_SUCCESS; goto out; case RTM_DELROUTE: rc = EXIT_SUCCESS; goto out; case RTM_NEWLINK: /* ignore if state did not change */ if ((ifi->ifi_flags & CHECK_CONNECTED) == ifs[ifi->ifi_index].state) { rc = EXIT_SUCCESS; goto out; } ifs[ifi->ifi_index].state = ifi->ifi_flags & CHECK_CONNECTED; notifystr = newstr_link(ifs[ifi->ifi_index].name, ifi->ifi_flags); icon = ifi->ifi_flags & CHECK_CONNECTED ? ICON_NETWORK_UP : ICON_NETWORK_DOWN; /* free only if interface goes down */ if (!(ifi->ifi_flags & CHECK_CONNECTED)) { free_addresses(ifs[ifi->ifi_index].addresses_seen); ifs[ifi->ifi_index].addresses_seen = NULL; } break; case RTM_DELLINK: notifystr = newstr_away(ifs[ifi->ifi_index].name); icon = ICON_NETWORK_AWAY; free_addresses(ifs[ifi->ifi_index].addresses_seen); /* marking interface deleted makes events for this interface to be ignored */ ifs[ifi->ifi_index].deleted = 1; break; default: /* we should not get here... */ fprintf(stderr, "msg_handler: Unknown netlink nlmsg_type %d.\n", msg->nlmsg_type); goto out; } if (verbose > 0) printf("%s: %s\n", program, notifystr); notify_notification_update(notification, TEXT_TOPIC, notifystr, icon); while (notify_notification_show(notification, &error) == FALSE) { if (errcount > 1) { fprintf(stderr, "%s: Looks like we can not reconnect to notification daemon... Exiting.\n", program); goto out; } else { g_printerr("%s: Error \"%s\" while trying to show notification. Trying to reconnect.\n", program, error->message); errcount++; g_error_free(error); error = NULL; notify_uninit(); usleep (500 * 1000); if (notify_init(PROGNAME) == FALSE) { fprintf(stderr, "%s: Can't create notify.\n", program); goto out; } } } rc = EXIT_SUCCESS; out: if (tmp_notification) g_object_unref(G_OBJECT(tmp_notification)); errcount = 0; free(notifystr); return rc; }
int irc_connect_generic(irc_session_t * session, const char * server, unsigned short port, const char * server_password, const char * nick, const char * username, const char * realname, int protocol_family) { struct irc_addr_t **addresses; int numAddresses = 0; if (!server || !nick) { session->lasterror = LIBIRC_ERR_INVAL; return 1; } if (session->state != LIBIRC_STATE_INIT) { session->lasterror = LIBIRC_ERR_STATE; return 1; } // Free the strings if defined; may be the case when the session is reused after the connection fails free_ircsession_strings(session); if (server[0] == SSL_PREFIX) { #if defined (ENABLE_SSL) server++; session->flags |= SESSIONFL_SSL_CONNECTION; #else session->lasterror = LIBIRC_ERR_SSL_NOT_SUPPORTED; return 1; #endif } if (username) session->username = strdup(username); if (server_password) session->server_password = strdup(server_password); if (realname) session->realname = strdup(realname); session->nick = strdup(nick); session->server = strdup(server); addresses = resolve_hostname_by_dns(session->server, &numAddresses, protocol_family); if (addresses == NULL) { session->lasterror = LIBIRC_ERR_RESOLV; return 1; } int selectedAddress = rand_range(0, numAddresses - 1); // and connect to the IRC server for (; addresses[selectedAddress] != NULL; selectedAddress++) { struct irc_addr_t *currentAddress = addresses[selectedAddress]; int ret = -1; if (currentAddress->family == AF_INET) ret = try_to_connect_ipv4(session, currentAddress, port); #if defined (ENABLE_IPV6) else if (currentAddress->family == AF_INET6) ret = try_to_connect_ipv6(session, currentAddress, port); #endif if (ret == -1) { goto err_out; } if (hasConnection(session)) { break; } else { socket_close(&session->sock); } } if (addresses[selectedAddress] == NULL) { session->lasterror = LIBIRC_ERR_CONNECT; goto err_out; } logprintf(LOG_INFO, "Connection successful!"); free_addresses(addresses); session->state = LIBIRC_STATE_CONNECTING; if (protocol_family == AF_INET6) session->flags |= SESSIONFL_USES_IPV6; return 0; err_out: free_addresses(addresses); return 1; }