static int urandom_fd = -1;
+static void sighandler(_unused int signal)
+{
+ uloop_end();
+}
+
+
int main()
{
openlog("odhcpd", LOG_PERROR | LOG_PID, LOG_DAEMON);
return 4;
signal(SIGUSR1, SIG_IGN);
+ signal(SIGINT, sighandler);
+ signal(SIGTERM, sighandler);
if (init_router())
return 4;
// Read IPv6 MTU for interface
-int odhcpd_get_interface_mtu(const char *ifname)
+int odhcpd_get_interface_config(const char *ifname, const char *what)
{
char buf[64];
- const char *sysctl_pattern = "/proc/sys/net/ipv6/conf/%s/mtu";
- snprintf(buf, sizeof(buf), sysctl_pattern, ifname);
+ const char *sysctl_pattern = "/proc/sys/net/ipv6/conf/%s/%s";
+ snprintf(buf, sizeof(buf), sysctl_pattern, ifname, what);
int fd = open(buf, O_RDONLY);
ssize_t len = read(fd, buf, sizeof(buf) - 1);
if (len < 0)
return -1;
-
buf[len] = 0;
return atoi(buf);
-
}
{
// Construct headers
uint8_t cmsg_buf[CMSG_SPACE(sizeof(struct in6_pktinfo))] = {0};
- struct msghdr msg = {(void*)dest, sizeof(*dest), iov, iov_len,
- cmsg_buf, sizeof(cmsg_buf), 0};
+ struct msghdr msg = {
+ .msg_name = (void *) dest,
+ .msg_namelen = sizeof(*dest),
+ .msg_iov = iov,
+ .msg_iovlen = iov_len,
+ .msg_control = cmsg_buf,
+ .msg_controllen = sizeof(cmsg_buf),
+ .msg_flags = 0
+ };
// Set control data (define destination interface)
struct cmsghdr *chdr = CMSG_FIRSTHDR(&msg);
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];
if (ifa->ifa_flags & IFA_F_DEPRECATED)
addrs[ret].preferred = 0;
- addrs[ret].has_class = false;
- addrs[ret].class = 0;
-#ifdef WITH_UBUS
- struct interface *iface = odhcpd_get_interface_by_index(ifindex);
- if (iface)
- addrs[ret].has_class = ubus_get_class(iface->ifname,
- &addrs[ret].addr, &addrs[ret].class);
-#endif
++ret;
}
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)
{
while (true) {
struct iovec iov = {data_buf, sizeof(data_buf)};
- struct msghdr msg = {&addr, sizeof(addr), &iov, 1,
- cmsg_buf, sizeof(cmsg_buf), 0};
+ struct msghdr msg = {
+ .msg_name = (void *) &addr,
+ .msg_namelen = sizeof(addr),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = cmsg_buf,
+ .msg_controllen = sizeof(cmsg_buf),
+ .msg_flags = 0
+ };
ssize_t len = recvmsg(u->fd, &msg, MSG_DONTWAIT);
if (len < 0) {
// 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_urandom(void *data, size_t len)
+void odhcpd_process(struct odhcpd_event *event)
+{
+ odhcpd_receive_packets(&event->uloop, 0);
+}
+
+int odhcpd_urandom(void *data, size_t len)
{
- read(urandom_fd, data, len);
+ return 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]);
+ }
+}