+
+ mosquitto_log_callback_set(mosq, mosq_log_callback);
+
+ /* DTRT if username is NULL */
+ mosquitto_username_pw_set(mosq,
+ config->mqtt_username,
+ config->mqtt_password);
+ if (config->capath)
+ mosquitto_tls_set(mosq, config->capath,
+ NULL, NULL, NULL, NULL);
+
+ ret = mosquitto_connect(mosq, config->mqtt_host,
+ config->mqtt_port, 60);
+ if (ret) {
+ printf("Unable to connect to MQTT server.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ ret = mosquitto_loop_start(mosq);
+ if (ret) {
+ printf("Unable to start Mosquitto loop.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ return mosq;
+}
+
+int netlink_init(void)
+{
+ int sock;
+ struct sockaddr_nl group_addr;
+
+ bzero(&group_addr, sizeof(group_addr));
+ group_addr.nl_family = AF_NETLINK;
+ group_addr.nl_pid = getpid();
+ group_addr.nl_groups = RTMGRP_NEIGH;
+
+ sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (sock < 0) {
+ perror("Couldn't open netlink socket");
+ exit(EXIT_FAILURE);
+ }
+
+ if (bind(sock, (struct sockaddr *) &group_addr,
+ sizeof(group_addr)) < 0) {
+ perror("Failed to bind to netlink socket");
+ exit(EXIT_FAILURE);
+ }
+
+ return sock;
+}
+
+struct option long_options[] = {
+ { "capath", required_argument, 0, 'c' },
+ { "host", required_argument, 0, 'h' },
+ { "location", required_argument, 0, 'l' },
+ { "mac", required_argument, 0, 'm' },
+ { "port", required_argument, 0, 'p' },
+ { "topic", required_argument, 0, 't' },
+ { "verbose", no_argument, 0, 'v' },
+ { 0, 0, 0, 0 }
+};
+
+int main(int argc, char *argv[])
+{
+ int sock;
+ struct mosquitto *mosq;
+ struct ma_config config;
+ int option_index = 0;
+ int macs = 0;
+ char c;
+
+ bzero(&config, sizeof(config));
+ config.mqtt_port = MQTT_PORT;
+
+ while (1) {
+ c = getopt_long(argc, argv, "c:h:l:m:p:t:v",
+ long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'c':
+ config.capath = optarg;
+ break;
+ case 'h':
+ config.mqtt_host = optarg;
+ break;
+ case 'l':
+ config.location = optarg;
+ break;
+ case 'm':
+ if (macs >= MAX_MACS) {
+ printf("Can only accept %d MAC addresses to"
+ " watch for.\n", MAX_MACS);
+ exit(EXIT_FAILURE);
+ }
+ sscanf(optarg,
+ "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+ &config.macs[macs].mac[0],
+ &config.macs[macs].mac[1],
+ &config.macs[macs].mac[2],
+ &config.macs[macs].mac[3],
+ &config.macs[macs].mac[4],
+ &config.macs[macs].mac[5]);
+ break;
+ case 'p':
+ config.mqtt_port = atoi(optarg);
+ break;
+ case 't':
+ config.mqtt_topic = optarg;
+ break;
+ case 'v':
+ debug = true;
+ break;
+ default:
+ printf("Unrecognized option: %c\n", c);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (!config.mqtt_host)
+ config.mqtt_host = MQTT_HOST;
+ if (!config.mqtt_topic)
+ config.mqtt_host = MQTT_TOPIC;
+ if (!config.location)
+ config.mqtt_host = LOCATION;
+
+ sock = netlink_init();
+ mosq = mqtt_init(&config);
+
+ main_loop(&config, mosq, sock);