static int urandom_fd = -1;
+static void sighandler(_unused int signal)
+{
+ uloop_end();
+}
+
+
int main()
{
openlog("odhcpd", LOG_PERROR | LOG_PID, LOG_DAEMON);
- setlogmask(LOG_UPTO(LOG_INFO));
+ setlogmask(LOG_UPTO(LOG_WARNING));
uloop_init();
if (getuid() != 0) {
return 4;
signal(SIGUSR1, SIG_IGN);
+ signal(SIGINT, sighandler);
+ signal(SIGTERM, sighandler);
if (init_router())
return 4;
ssize_t sent = sendmsg(socket, &msg, MSG_DONTWAIT);
if (sent < 0)
- syslog(LOG_WARNING, "Failed to send to %s%%%s (%s)",
+ syslog(LOG_NOTICE, "Failed to send to %s%%%s (%s)",
ipbuf, iface->ifname, strerror(errno));
else
syslog(LOG_DEBUG, "Sent %li bytes to %s%%%s",
struct ifaddrmsg *ifa = NLMSG_DATA(nhm);
if (ifa->ifa_scope != RT_SCOPE_UNIVERSE ||
- ifa->ifa_index != (unsigned)ifindex)
+ (ifindex && ifa->ifa_index != (unsigned)ifindex))
continue;
struct rtattr *rta = (struct rtattr*)&ifa[1];
return ret;
}
+int odhcpd_get_preferred_interface_address(int ifindex, struct in6_addr *addr)
+{
+ struct odhcpd_ipaddr ipaddrs[8];
+ ssize_t ip_cnt = odhcpd_get_interface_addresses(ifindex, ipaddrs, ARRAY_SIZE(ipaddrs));
+ uint32_t preferred = 0;
+ int ret = 0;
+
+ for (ssize_t i = 0; i < ip_cnt; i++) {
+ struct odhcpd_ipaddr *ipaddr = &ipaddrs[i];
+
+ if (ipaddr->preferred > preferred || !preferred) {
+ preferred = ipaddr->preferred;
+ *addr = ipaddr->addr;
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
struct interface* odhcpd_get_interface_by_index(int ifindex)
{
// Extract destination interface
int destiface = 0;
int *hlim = NULL;
+ void *dest = NULL;
struct in6_pktinfo *pktinfo;
struct in_pktinfo *pkt4info;
for (struct cmsghdr *ch = CMSG_FIRSTHDR(&msg); ch != NULL; ch = CMSG_NXTHDR(&msg, ch)) {
ch->cmsg_type == IPV6_PKTINFO) {
pktinfo = (struct in6_pktinfo*)CMSG_DATA(ch);
destiface = pktinfo->ipi6_ifindex;
+ dest = &pktinfo->ipi6_addr;
} else if (ch->cmsg_level == IPPROTO_IP &&
ch->cmsg_type == IP_PKTINFO) {
pkt4info = (struct in_pktinfo*)CMSG_DATA(ch);
destiface = pkt4info->ipi_ifindex;
+ dest = &pkt4info->ipi_addr;
} else if (ch->cmsg_level == IPPROTO_IPV6 &&
ch->cmsg_type == IPV6_HOPLIMIT) {
hlim = (int*)CMSG_DATA(ch);
syslog(LOG_DEBUG, "Received %li Bytes from %s%%%s", (long)len,
ipbuf, (iface) ? iface->ifname : "netlink");
- e->handle_dgram(&addr, data_buf, len, iface);
+ e->handle_dgram(&addr, data_buf, len, iface, dest);
}
}
return uloop_fd_add(&event->uloop, ULOOP_READ);
}
+void odhcpd_process(struct odhcpd_event *event)
+{
+ odhcpd_receive_packets(&event->uloop, 0);
+}
+
void odhcpd_urandom(void *data, size_t len)
{
read(urandom_fd, data, len);
}
*dst = 0;
}
+
+
+int odhcpd_bmemcmp(const void *av, const void *bv, size_t bits)
+{
+ const uint8_t *a = av, *b = bv;
+ size_t bytes = bits / 8;
+ bits %= 8;
+
+ int res = memcmp(a, b, bytes);
+ if (res == 0 && bits > 0)
+ res = (a[bytes] >> (8 - bits)) - (b[bytes] >> (8 - bits));
+
+ return res;
+}
+
+
+void odhcpd_bmemcpy(void *av, const void *bv, size_t bits)
+{
+ uint8_t *a = av;
+ const uint8_t *b = bv;
+
+ size_t bytes = bits / 8;
+ bits %= 8;
+ memcpy(a, b, bytes);
+
+ if (bits > 0) {
+ uint8_t mask = (1 << (8 - bits)) - 1;
+ a[bytes] = (a[bytes] & mask) | ((~mask) & b[bytes]);
+ }
+}