+ }
+ else if(proto==ETHERTYPE_IPV6)
+ {
+ const struct ip6_hdr *ip6 = (const struct ip6_hdr *)(eth+1);
+ for(unsigned i=0; i<monitor->n_addresses; ++i)
+ if(monitor->addresses[i].address.ss_family==AF_INET6)
+ {
+ int s = get_inet6_scope(&ip6->ip6_src, &monitor->addresses[i]);
+ if(s>src_scope)
+ src_scope = s;
+
+ s = get_inet6_scope(&ip6->ip6_dst, &monitor->addresses[i]);
+ if(s>dst_scope)
+ dst_scope = s;
+ }
+ }
+
+ Time timestamp = header->ts.tv_sec*1000000ULL+header->ts.tv_usec;
+ if(src_scope==0 && dst_scope>0)
+ monitor->last_receive = timestamp;
+ else if(src_scope>0 && dst_scope==0)
+ monitor->last_transmit = timestamp;
+}
+
+int trigger_init(Trigger *trigger)
+{
+ trigger->next = trigger->delay;
+ trigger->child_pid = 0;
+
+ return 0;
+}
+
+void trigger_check(Trigger *trigger, Time time)
+{
+ Monitor *monitor = trigger->monitor;
+
+ if(monitor->connection_status)
+ trigger->next = trigger->delay;
+ else if(time>=monitor->last_receive+trigger->next)
+ {
+ if(no_daemon)
+ printf("Running %s\n", trigger->command);
+ else
+ syslog(LOG_INFO, "Running %s", trigger->command);
+ trigger->child_pid = run_command(trigger->command);
+ trigger->next += trigger->interval;
+ }
+
+ /* Reap any finished child process */
+ if(trigger->child_pid)
+ {
+ if(waitpid(trigger->child_pid, NULL, WNOHANG)==trigger->child_pid)
+ trigger->child_pid = 0;
+ }
+}
+
+int get_inet_scope(uint32_t addr, const Address *local_addr)
+{
+ uint32_t diff = addr^((struct sockaddr_in *)&local_addr->address)->sin_addr.s_addr;
+ if(!diff)
+ return 2;
+ else if(!(diff&((struct sockaddr_in *)&local_addr->mask)->sin_addr.s_addr))
+ return 1;
+ else
+ return 0;
+}
+
+int get_inet6_scope(const struct in6_addr *addr, const Address *local_addr)
+{
+ int result = 2;
+ for(unsigned i=0; i<16; ++i)
+ {
+ uint8_t diff = addr->s6_addr[i]^((struct sockaddr_in6 *)&local_addr->address)->sin6_addr.s6_addr[i];
+ if(diff)
+ {
+ diff &= ((struct sockaddr_in6 *)&local_addr->mask)->sin6_addr.s6_addr[i];
+ if(diff)
+ return 0;
+ else
+ result = 1;