Ejemplo n.º 1
0
/*
 * 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;
}
Ejemplo n.º 2
0
/*** 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;
}
Ejemplo n.º 3
0
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(&timestamp);
    
    // 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;

}
Ejemplo n.º 4
0
/*** 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;
}
Ejemplo n.º 5
0
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;
}