diff --git a/dhcp4.c b/dhcp4.c index 286cbdb..6824968 100644 --- a/dhcp4.c +++ b/dhcp4.c @@ -36,20 +36,20 @@ enum SendReplyType { // things precisely. We optimize for cache locality. struct D4State { - struct timespec ts_; // Set once at creation - uint64_t hwaddr_; - uint32_t xid_; - uint32_t state_; + struct timespec ts; // Set once at creation + uint64_t hwaddr; + uint32_t xid; + uint32_t state; }; struct D4Listener { - int fd_; - int ifindex_; - struct dhcpmsg dhcpmsg_; - struct in6_addr local_ip_; - char ifname_[IFNAMSIZ]; - struct D4State map_[D4_CLIENT_STATE_TABLESIZE]; + int fd; + int ifindex; + struct dhcpmsg dhcpmsg; + struct in6_addr local_ip; + char ifname[IFNAMSIZ]; + struct D4State map[D4_CLIENT_STATE_TABLESIZE]; }; // hwaddr must be exactly 6 bytes @@ -71,10 +71,10 @@ static inline bool ip4_to_string(char *buf, size_t buflen, uint32_t addr) static struct D4State *find(struct D4State *self, uint64_t h) { for (size_t i = 0; i < D4_CLIENT_STATE_TABLESIZE; ++i) { - if (self[i].hwaddr_ == h) { + if (self[i].hwaddr == h) { struct timespec now; clock_gettime(CLOCK_BOOTTIME, &now); - if (now.tv_sec > self[i].ts_.tv_sec + D4_XID_LIFE_SECS) { + if (now.tv_sec > self[i].ts.tv_sec + D4_XID_LIFE_SECS) { self[i] = (struct D4State){0}; break; } @@ -93,11 +93,11 @@ static bool D4State_add(struct D4State *self, uint32_t xid, uint8_t *hwaddr, uin struct D4State *m = NULL, *e = NULL; struct D4State zi = {0}; for (size_t i = 0; i < D4_CLIENT_STATE_TABLESIZE; ++i) { - if (self[i].ts_.tv_sec && now.tv_sec > self[i].ts_.tv_sec + D4_XID_LIFE_SECS) { + if (self[i].ts.tv_sec && now.tv_sec > self[i].ts.tv_sec + D4_XID_LIFE_SECS) { // Expire entries as we see them. self[i] = (struct D4State){0}; } else { - if (self[i].hwaddr_ == key) { + if (self[i].hwaddr == key) { m = &self[i]; break; } @@ -109,10 +109,10 @@ static bool D4State_add(struct D4State *self, uint32_t xid, uint8_t *hwaddr, uin m = e; } *m = (struct D4State){ - .ts_ = now, - .hwaddr_ = key, - .xid_ = xid, - .state_ = state, + .ts = now, + .hwaddr = key, + .xid = xid, + .state = state, }; return true; } @@ -121,8 +121,8 @@ static uint8_t D4State_get(struct D4State *self, uint32_t xid, uint8_t *hwaddr) { uint64_t key = hwaddr_to_int64(hwaddr); struct D4State *m = find(self, key); - if (!m || m->xid_ != xid) return DHCPNULL; - return m->state_; + if (!m || m->xid != xid) return DHCPNULL; + return m->state; } static void D4State_kill(struct D4State *self, uint8_t *hwaddr) @@ -132,51 +132,51 @@ static void D4State_kill(struct D4State *self, uint8_t *hwaddr) if (m) *m = (struct D4State){0}; } -// Must be called after ifname_ is set and only should be called once. +// Must be called after ifname is set and only should be called once. static bool create_dhcp4_socket(struct D4Listener *self) { struct ifreq ifr = {0}; const int iv = 1; - size_t ifname_len = strlen(self->ifname_); + size_t ifname_len = strlen(self->ifname); struct sockaddr_in sai = { .sin_family = AF_INET, .sin_port = htons(67), }; - self->fd_ = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP); - if (self->fd_ < 0) { - log_line("dhcp4: Failed to create v4 UDP socket on %s: %s\n", self->ifname_, strerror(errno)); + self->fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP); + if (self->fd < 0) { + log_line("dhcp4: Failed to create v4 UDP socket on %s: %s\n", self->ifname, strerror(errno)); goto err0; } - if (setsockopt(self->fd_, SOL_SOCKET, SO_BROADCAST, &iv, sizeof iv) == -1) { - log_line("dhcp4: Failed to set broadcast flag on %s: %s\n", self->ifname_, strerror(errno)); + if (setsockopt(self->fd, SOL_SOCKET, SO_BROADCAST, &iv, sizeof iv) == -1) { + log_line("dhcp4: Failed to set broadcast flag on %s: %s\n", self->ifname, strerror(errno)); goto err1; } - if (setsockopt(self->fd_, SOL_SOCKET, SO_DONTROUTE, &iv, sizeof iv) == -1) { - log_line("dhcp4: Failed to set do not route flag on %s: %s\n", self->ifname_, strerror(errno)); + if (setsockopt(self->fd, SOL_SOCKET, SO_DONTROUTE, &iv, sizeof iv) == -1) { + log_line("dhcp4: Failed to set do not route flag on %s: %s\n", self->ifname, strerror(errno)); goto err1; } - if (setsockopt(self->fd_, SOL_SOCKET, SO_REUSEADDR, &iv, sizeof iv) == -1) { - log_line("dhcp4: Failed to set reuse address flag on %s: %s\n", self->ifname_, strerror(errno)); + if (setsockopt(self->fd, SOL_SOCKET, SO_REUSEADDR, &iv, sizeof iv) == -1) { + log_line("dhcp4: Failed to set reuse address flag on %s: %s\n", self->ifname, strerror(errno)); goto err1; } - if (bind(self->fd_, (const struct sockaddr *)&sai, sizeof sai)) { - log_line("dhcp4: Failed to bind to UDP 67 on %s: %s\n", self->ifname_, strerror(errno)); + if (bind(self->fd, (const struct sockaddr *)&sai, sizeof sai)) { + log_line("dhcp4: Failed to bind to UDP 67 on %s: %s\n", self->ifname, strerror(errno)); goto err1; } if (ifname_len >= sizeof ifr.ifr_name) { log_line("dhcp4: Interface name '%s' is too long: %zu >= %zu\n", - self->ifname_, ifname_len, sizeof ifr.ifr_name); + self->ifname, ifname_len, sizeof ifr.ifr_name); goto err1; } - memcpy(ifr.ifr_name, self->ifname_, ifname_len); - if (setsockopt(self->fd_, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof ifr) < 0) { - log_line("dhcp4: Failed to bind socket to device on %s: %s\n", self->ifname_, strerror(errno)); + memcpy(ifr.ifr_name, self->ifname, ifname_len); + if (setsockopt(self->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof ifr) < 0) { + log_line("dhcp4: Failed to bind socket to device on %s: %s\n", self->ifname, strerror(errno)); goto err1; } return true; err1: - close(self->fd_); - self->fd_ = -1; + close(self->fd); + self->fd = -1; err0: return false; } @@ -186,7 +186,7 @@ struct D4Listener *D4Listener_create(const char *ifname, const struct netif_info { struct D4Listener *self; size_t ifname_src_size = strlen(ifname); - if (ifname_src_size >= sizeof self->ifname_) { + if (ifname_src_size >= sizeof self->ifname) { log_line("D4Listener: Interface name (%s) too long\n", ifname); return NULL; } @@ -197,13 +197,13 @@ struct D4Listener *D4Listener_create(const char *ifname, const struct netif_info self = calloc(1, sizeof(struct D4Listener)); if (!self) return NULL; - self->ifindex_ = ifinfo->index; - *(char *)(mempcpy(self->ifname_, ifname, ifname_src_size)) = 0; - self->local_ip_ = ifinfo->v4_address; + self->ifindex = ifinfo->index; + *(char *)(mempcpy(self->ifname, ifname, ifname_src_size)) = 0; + self->local_ip = ifinfo->v4_address; char abuf[48]; if (!create_dhcp4_socket(self)) goto err; - if (!ipaddr_to_string(abuf, sizeof abuf, &self->local_ip_)) goto err; + if (!ipaddr_to_string(abuf, sizeof abuf, &self->local_ip)) goto err; log_line("dhcp4: IP address for %s is %s\n", ifname, abuf); return self; @@ -221,12 +221,12 @@ void D4Listener_process_input(struct D4Listener *self) for (;;) { struct sockaddr_in sai; socklen_t sailen = sizeof sai; - ssize_t buflen = recvfrom(self->fd_, buf, sizeof buf, MSG_DONTWAIT, (struct sockaddr *)&sai, &sailen); + ssize_t buflen = recvfrom(self->fd, buf, sizeof buf, MSG_DONTWAIT, (struct sockaddr *)&sai, &sailen); if (buflen < 0) { int err = errno; if (err == EINTR) continue; if (err == EAGAIN || err == EWOULDBLOCK) break; - suicide("dhcp4: recvfrom failed on %s: %s\n", self->ifname_, strerror(err)); + suicide("dhcp4: recvfrom failed on %s: %s\n", self->ifname, strerror(err)); } process_receive(self, buf, (size_t)buflen, &sai); } @@ -234,13 +234,13 @@ void D4Listener_process_input(struct D4Listener *self) int D4Listener_fd(const struct D4Listener *self) { - return self->fd_; + return self->fd; } static uint32_t local_ip(const struct D4Listener *self) { uint32_t ret; - memcpy(&ret, ipaddr_v4_bytes(&self->local_ip_), sizeof ret); + memcpy(&ret, ipaddr_v4_bytes(&self->local_ip), sizeof ret); return ret; } @@ -254,7 +254,7 @@ static void dhcpmsg_init(const struct D4Listener *self, struct dhcpmsg *dm, uint .cookie = htonl(DHCP_MAGIC), .options[0] = DCODE_END, }; - memcpy(dm->chaddr, &self->dhcpmsg_.chaddr, sizeof self->dhcpmsg_.chaddr); + memcpy(dm->chaddr, &self->dhcpmsg.chaddr, sizeof self->dhcpmsg.chaddr); add_option_msgtype(dm, type); add_option_serverid(dm, local_ip(self)); } @@ -277,27 +277,27 @@ static void send_reply_do(struct D4Listener *self, const struct dhcpmsg *dm, enu size_t dmlen = sizeof *dm - (sizeof dm->options - 1 - (size_t)endloc); switch (srt) { - case SRT_UnicastCi: send_to(self->fd_, dm, dmlen, self->dhcpmsg_.ciaddr, 68); break; + case SRT_UnicastCi: send_to(self->fd, dm, dmlen, self->dhcpmsg.ciaddr, 68); break; case SRT_Broadcast: { - const struct in6_addr *broadcast = query_broadcast(self->ifindex_); + const struct in6_addr *broadcast = query_broadcast(self->ifindex); if (!broadcast) suicide("dhcp4: misconfigured -- must have a broadcast address\n"); uint32_t bcaddr; memcpy(&bcaddr, ipaddr_v4_bytes(broadcast), sizeof bcaddr); - send_to(self->fd_, dm, dmlen, bcaddr, 68); + send_to(self->fd, dm, dmlen, bcaddr, 68); break; } - case SRT_Relay: send_to(self->fd_, dm, dmlen, self->dhcpmsg_.giaddr, 67); break; - case SRT_UnicastYiCh: send_to(self->fd_, dm, dmlen, self->dhcpmsg_.yiaddr, 68); break; + case SRT_Relay: send_to(self->fd, dm, dmlen, self->dhcpmsg.giaddr, 67); break; + case SRT_UnicastYiCh: send_to(self->fd, dm, dmlen, self->dhcpmsg.yiaddr, 68); break; } } static void send_reply(struct D4Listener *self, const struct dhcpmsg *reply) { - if (self->dhcpmsg_.giaddr) send_reply_do(self, reply, SRT_Relay); - else if (self->dhcpmsg_.ciaddr) send_reply_do(self, reply, SRT_UnicastCi); - else if (ntohs(self->dhcpmsg_.flags) & 0x8000u) send_reply_do(self, reply, SRT_Broadcast); - else if (self->dhcpmsg_.yiaddr) send_reply_do(self, reply, SRT_UnicastYiCh); - else send_reply_do(self, reply, SRT_Broadcast); + if (self->dhcpmsg.giaddr) send_reply_do(self, reply, SRT_Relay); + else if (self->dhcpmsg.ciaddr) send_reply_do(self, reply, SRT_UnicastCi); + else if (ntohs(self->dhcpmsg.flags) & 0x8000u) send_reply_do(self, reply, SRT_Broadcast); + else if (self->dhcpmsg.yiaddr) send_reply_do(self, reply, SRT_UnicastYiCh); + else send_reply_do(self, reply, SRT_Broadcast); } static bool iplist_option(struct dhcpmsg *reply, uint8_t code, const struct addrlist *ipl) @@ -327,19 +327,19 @@ static struct in6_addr u32_ipaddr(uint32_t v) static bool allot_dynamic_ip(struct D4Listener *self, struct dhcpmsg *reply, const uint8_t *hwaddr, bool do_assign) { uint32_t dynamic_lifetime; - if (!query_use_dynamic_v4(self->ifindex_, &dynamic_lifetime)) + if (!query_use_dynamic_v4(self->ifindex, &dynamic_lifetime)) return false; log_line("dhcp4: Checking dynamic IP.\n"); struct in6_addr dr_lo, dr_hi; - if (!query_dynamic_range(self->ifindex_, &dr_lo, &dr_hi)) { + if (!query_dynamic_range(self->ifindex, &dr_lo, &dr_hi)) { log_line("dhcp4: No dynamic range is associated. Can't assign an IP.\n"); return false; } int64_t expire_time = get_current_ts() + dynamic_lifetime; - struct in6_addr v4a = dynlease4_query_refresh(self->ifindex_, hwaddr, expire_time); + struct in6_addr v4a = dynlease4_query_refresh(self->ifindex, hwaddr, expire_time); if (memcmp(&v4a, &in6addr_any, 16)) { if (!ipaddr_is_v4(&v4a)) { log_line("dhcp4: allot_dynamic_ip - bad address\n"); @@ -368,8 +368,8 @@ static bool allot_dynamic_ip(struct D4Listener *self, struct dhcpmsg *reply, con // If no success, then all IPs are taken, so return false. for (uint32_t i = al + rqs; i <= ah; ++i) { struct in6_addr iaddr = u32_ipaddr(htonl(i)); - bool matched = do_assign ? dynlease4_add(self->ifindex_, &iaddr, hwaddr, expire_time) - : dynlease4_exists(self->ifindex_, &iaddr, hwaddr); + bool matched = do_assign ? dynlease4_add(self->ifindex, &iaddr, hwaddr, expire_time) + : dynlease4_exists(self->ifindex, &iaddr, hwaddr); if (matched) { reply->yiaddr = htonl(i); add_u32_option(reply, DCODE_LEASET, htonl(dynamic_lifetime)); @@ -378,8 +378,8 @@ static bool allot_dynamic_ip(struct D4Listener *self, struct dhcpmsg *reply, con } for (uint32_t i = al; i < al + rqs; ++i) { struct in6_addr iaddr = u32_ipaddr(htonl(i)); - bool matched = do_assign ? dynlease4_add(self->ifindex_, &iaddr, hwaddr, expire_time) - : dynlease4_exists(self->ifindex_, &iaddr, hwaddr); + bool matched = do_assign ? dynlease4_add(self->ifindex, &iaddr, hwaddr, expire_time) + : dynlease4_exists(self->ifindex, &iaddr, hwaddr); if (matched) { reply->yiaddr = htonl(i); add_u32_option(reply, DCODE_LEASET, htonl(dynamic_lifetime)); @@ -391,7 +391,7 @@ static bool allot_dynamic_ip(struct D4Listener *self, struct dhcpmsg *reply, con static bool create_reply(struct D4Listener *self, struct dhcpmsg *reply, const uint8_t *hwaddr, bool do_assign) { - const struct dhcpv4_entry *dv4s = query_dhcp4_state(self->ifindex_, hwaddr); + const struct dhcpv4_entry *dv4s = query_dhcp4_state(self->ifindex, hwaddr); if (!dv4s) { if (!allot_dynamic_ip(self, reply, hwaddr, do_assign)) return false; @@ -399,32 +399,32 @@ static bool create_reply(struct D4Listener *self, struct dhcpmsg *reply, const u memcpy(&reply->yiaddr, ipaddr_v4_bytes(&dv4s->address), sizeof reply->yiaddr); add_u32_option(reply, DCODE_LEASET, htonl(dv4s->lifetime)); } - const struct in6_addr *subnet = query_subnet(self->ifindex_); + const struct in6_addr *subnet = query_subnet(self->ifindex); if (!subnet) return false; uint32_t subnet_addr; memcpy(&subnet_addr, ipaddr_v4_bytes(subnet), sizeof subnet_addr); add_option_subnet_mask(reply, subnet_addr); - const struct in6_addr *broadcast = query_broadcast(self->ifindex_); + const struct in6_addr *broadcast = query_broadcast(self->ifindex); if (!broadcast) return false; uint32_t broadcast_addr; memcpy(&broadcast_addr, ipaddr_v4_bytes(broadcast), sizeof broadcast_addr); add_option_broadcast(reply, broadcast_addr); - const struct in6_addr *router = query_gateway_v4(self->ifindex_); + const struct in6_addr *router = query_gateway_v4(self->ifindex); if (router) { uint32_t router_addr; memcpy(&router_addr, ipaddr_v4_bytes(router), sizeof router_addr); add_option_router(reply, router_addr); } - struct addrlist dns_servers = query_dns_servers(self->ifindex_); + struct addrlist dns_servers = query_dns_servers(self->ifindex); if (dns_servers.n) iplist_option(reply, DCODE_DNS, &dns_servers); - struct addrlist ntp_servers = query_ntp_servers(self->ifindex_); + struct addrlist ntp_servers = query_ntp_servers(self->ifindex); if (ntp_servers.n) iplist_option(reply, DCODE_NTPSVR, &ntp_servers); - struct blob d4b = query_dns4_search_blob(self->ifindex_); + struct blob d4b = query_dns4_search_blob(self->ifindex); if (d4b.n && d4b.s) add_option_domain_name(reply, d4b.s, d4b.n); log_line("dhcp4: Sending reply %u.%u.%u.%u\n", reply->yiaddr & 255, @@ -436,40 +436,40 @@ static bool create_reply(struct D4Listener *self, struct dhcpmsg *reply, const u static void reply_discover(struct D4Listener *self) { struct dhcpmsg reply; - dhcpmsg_init(self, &reply, DHCPOFFER, self->dhcpmsg_.xid); - if (create_reply(self, &reply, self->dhcpmsg_.chaddr, true)) + dhcpmsg_init(self, &reply, DHCPOFFER, self->dhcpmsg.xid); + if (create_reply(self, &reply, self->dhcpmsg.chaddr, true)) send_reply(self, &reply); } static void reply_request(struct D4Listener *self) { struct dhcpmsg reply; - dhcpmsg_init(self, &reply, DHCPACK, self->dhcpmsg_.xid); - if (create_reply(self, &reply, self->dhcpmsg_.chaddr, true)) { + dhcpmsg_init(self, &reply, DHCPACK, self->dhcpmsg.xid); + if (create_reply(self, &reply, self->dhcpmsg.chaddr, true)) { send_reply(self, &reply); } - D4State_kill(self->map_, self->dhcpmsg_.chaddr); + D4State_kill(self->map, self->dhcpmsg.chaddr); } static void reply_inform(struct D4Listener *self) { struct dhcpmsg reply; - dhcpmsg_init(self, &reply, DHCPACK, self->dhcpmsg_.xid); - if (create_reply(self, &reply, self->dhcpmsg_.chaddr, false)) { + dhcpmsg_init(self, &reply, DHCPACK, self->dhcpmsg.xid); + if (create_reply(self, &reply, self->dhcpmsg.chaddr, false)) { // http://tools.ietf.org/html/draft-ietf-dhc-dhcpinform-clarify-06 - reply.htype = self->dhcpmsg_.htype; - reply.hlen = self->dhcpmsg_.hlen; - memcpy(&reply.chaddr, &self->dhcpmsg_.chaddr, sizeof reply.chaddr); - reply.ciaddr = self->dhcpmsg_.ciaddr; + reply.htype = self->dhcpmsg.htype; + reply.hlen = self->dhcpmsg.hlen; + memcpy(&reply.chaddr, &self->dhcpmsg.chaddr, sizeof reply.chaddr); + reply.ciaddr = self->dhcpmsg.ciaddr; // xid was already set equal - reply.flags = self->dhcpmsg_.flags; + reply.flags = self->dhcpmsg.flags; reply.hops = 0; reply.secs = 0; reply.yiaddr = 0; reply.siaddr = 0; - if (self->dhcpmsg_.ciaddr) + if (self->dhcpmsg.ciaddr) send_reply_do(self, &reply, SRT_UnicastCi); - else if (self->dhcpmsg_.giaddr) { + else if (self->dhcpmsg.giaddr) { uint16_t fl = ntohs(reply.flags); reply.flags = htons(fl | 0x8000u); send_reply_do(self, &reply, SRT_Relay); @@ -480,43 +480,43 @@ static void reply_inform(struct D4Listener *self) static void do_release(struct D4Listener *self) { - struct in6_addr ciaddr = u32_ipaddr(self->dhcpmsg_.ciaddr); - if (!dynlease4_exists(self->ifindex_, &ciaddr, self->dhcpmsg_.chaddr)) { + struct in6_addr ciaddr = u32_ipaddr(self->dhcpmsg.ciaddr); + if (!dynlease4_exists(self->ifindex, &ciaddr, self->dhcpmsg.chaddr)) { char buf[32] = "invalid ip"; - ip4_to_string(buf, sizeof buf, self->dhcpmsg_.ciaddr); + ip4_to_string(buf, sizeof buf, self->dhcpmsg.ciaddr); log_line("dhcp4: do_release: ignoring spoofed release request for %s.\n", buf); return; } - dynlease4_del(self->ifindex_, &ciaddr, self->dhcpmsg_.chaddr); + dynlease4_del(self->ifindex, &ciaddr, self->dhcpmsg.chaddr); } static uint8_t validate_dhcp(const struct D4Listener *self, size_t len) { if (len < offsetof(struct dhcpmsg, options)) return DHCPNULL; - if (ntohl(self->dhcpmsg_.cookie) != DHCP_MAGIC) + if (ntohl(self->dhcpmsg.cookie) != DHCP_MAGIC) return DHCPNULL; - return get_option_msgtype(&self->dhcpmsg_); + return get_option_msgtype(&self->dhcpmsg); } static void process_receive(struct D4Listener *self, const char *buf, size_t buflen, const struct sockaddr_in *sai) { if (sai->sin_family != AF_INET) return; - size_t msglen = buflen < sizeof self->dhcpmsg_ ? buflen : sizeof self->dhcpmsg_; - self->dhcpmsg_ = (struct dhcpmsg){0}; - memcpy(&self->dhcpmsg_, buf, msglen); + size_t msglen = buflen < sizeof self->dhcpmsg ? buflen : sizeof self->dhcpmsg; + self->dhcpmsg = (struct dhcpmsg){0}; + memcpy(&self->dhcpmsg, buf, msglen); uint8_t msgtype = validate_dhcp(self, msglen); if (!msgtype) return; - uint8_t cs = D4State_get(self->map_, self->dhcpmsg_.xid, self->dhcpmsg_.chaddr); + uint8_t cs = D4State_get(self->map, self->dhcpmsg.xid, self->dhcpmsg.chaddr); if (cs == DHCPNULL) { switch (msgtype) { case DHCPREQUEST: case DHCPDISCOVER: cs = msgtype; - if (!D4State_add(self->map_, self->dhcpmsg_.xid, self->dhcpmsg_.chaddr, cs)) + if (!D4State_add(self->map, self->dhcpmsg.xid, self->dhcpmsg.chaddr, cs)) return; // Possible DoS; silently drop. break; case DHCPINFORM: diff --git a/dhcp6.c b/dhcp6.c index 987f7c5..c9c944d 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -35,15 +35,15 @@ extern struct NLSocket nl_socket; struct D6Listener { - struct in6_addr local_ip_; - struct in6_addr local_ip_prefix_; - struct in6_addr link_local_ip_; - char ifname_[IFNAMSIZ]; - int ifindex_; - int fd_; - unsigned char prefixlen_; - uint8_t preference_; - bool using_bpf_:1; + struct in6_addr local_ip; + struct in6_addr local_ip_prefix; + struct in6_addr link_local_ip; + char ifname[IFNAMSIZ]; + int ifindex; + int fd; + unsigned char prefixlen; + uint8_t preference; + bool using_bpf:1; }; enum dhcp6_msgtype { @@ -139,21 +139,21 @@ static bool dhcp6_opt_write(const struct dhcp6_opt *self, struct sbufs *sbuf) // Server Identifier Option struct dhcp6_opt_serverid { - const char *duid_string_; - size_t duid_len_; + const char *duid_string; + size_t duid_len; }; static struct dhcp6_opt_serverid dhcp6_opt_serverid_create(const char *s, size_t slen) { - return (struct dhcp6_opt_serverid){ .duid_string_ = s, .duid_len_ = slen }; + return (struct dhcp6_opt_serverid){ .duid_string = s, .duid_len = slen }; } static bool dhcp6_opt_serverid_write(const struct dhcp6_opt_serverid *self, struct sbufs *sbuf) { - const size_t size = DHCP6_OPT_SIZE + self->duid_len_; + const size_t size = DHCP6_OPT_SIZE + self->duid_len; if (sbufs_brem(sbuf) < size) return false; - struct dhcp6_opt header = dhcp6_opt_create(2, self->duid_len_); + struct dhcp6_opt header = dhcp6_opt_create(2, self->duid_len); if (!dhcp6_opt_write(&header, sbuf)) return false; - memcpy(sbuf->si, self->duid_string_, self->duid_len_); - sbuf->si += self->duid_len_; + memcpy(sbuf->si, self->duid_string, self->duid_len); + sbuf->si += self->duid_len; return true; } @@ -255,24 +255,24 @@ static bool create_dhcp6_socket(struct D6Listener *self) .sin6_family = AF_INET6, .sin6_port = htons(547), }; - self->fd_ = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP); - if (self->fd_ < 0) { - log_line("dhcp6: Failed to create v6 UDP socket on %s: %s\n", self->ifname_, strerror(errno)); + self->fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP); + if (self->fd < 0) { + log_line("dhcp6: Failed to create v6 UDP socket on %s: %s\n", self->ifname, strerror(errno)); goto err0; } if (!ipaddr_from_string(&mc6_alldhcp_ras, "ff02::1:2")) goto err1; - if (!attach_multicast_in6_addr(self->fd_, self->ifname_, &mc6_alldhcp_ras)) goto err1; - self->using_bpf_ = attach_bpf_dhcp6_info(self->fd_, self->ifname_); + if (!attach_multicast_in6_addr(self->fd, self->ifname, &mc6_alldhcp_ras)) goto err1; + self->using_bpf = attach_bpf_dhcp6_info(self->fd, self->ifname); - if (bind(self->fd_, (const struct sockaddr *)&sai, sizeof sai)) { - log_line("dhcp6: Failed to bind to UDP 547 on %s: %s\n", self->ifname_, strerror(errno)); + if (bind(self->fd, (const struct sockaddr *)&sai, sizeof sai)) { + log_line("dhcp6: Failed to bind to UDP 547 on %s: %s\n", self->ifname, strerror(errno)); goto err1; } return true; err1: - close(self->fd_); - self->fd_ = -1; + close(self->fd); + self->fd = -1; err0: return false; } @@ -281,7 +281,7 @@ struct D6Listener *D6Listener_create(const char *ifname, const struct netif_info { struct D6Listener *self; size_t ifname_src_size = strlen(ifname); - if (ifname_src_size >= sizeof self->ifname_) { + if (ifname_src_size >= sizeof self->ifname) { log_line("D6Listener: Interface name (%s) too long\n", ifname); return NULL; } @@ -292,26 +292,26 @@ struct D6Listener *D6Listener_create(const char *ifname, const struct netif_info self = calloc(1, sizeof(struct D6Listener)); if (!self) return NULL; - self->ifindex_ = ifinfo->index; - self->using_bpf_ = false; - self->preference_ = preference; - *(char *)(mempcpy(self->ifname_, ifname, ifname_src_size)) = 0; - self->local_ip_ = ifinfo->v6_address_global; - self->prefixlen_ = ifinfo->v6_prefixlen_global; - self->link_local_ip_ = ifinfo->v6_address_link; - self->local_ip_prefix_ = mask_v6_addr(&self->local_ip_, self->prefixlen_); + self->ifindex = ifinfo->index; + self->using_bpf = false; + self->preference = preference; + *(char *)(mempcpy(self->ifname, ifname, ifname_src_size)) = 0; + self->local_ip = ifinfo->v6_address_global; + self->prefixlen = ifinfo->v6_prefixlen_global; + self->link_local_ip = ifinfo->v6_address_link; + self->local_ip_prefix = mask_v6_addr(&self->local_ip, self->prefixlen); if (!create_dhcp6_socket(self)) goto err; char abuf[48]; char abufp[48]; - if (!ipaddr_to_string(abuf, sizeof abuf, &self->local_ip_)) abort(); - if (!ipaddr_to_string(abufp, sizeof abufp, &self->local_ip_prefix_)) abort(); + if (!ipaddr_to_string(abuf, sizeof abuf, &self->local_ip)) abort(); + if (!ipaddr_to_string(abufp, sizeof abufp, &self->local_ip_prefix)) abort(); log_line("dhcp6: IP address for %s is %s/%u. Prefix is %s.\n", - ifname, abuf, +self->prefixlen_, abufp); - if (!ipaddr_to_string(abuf, sizeof abuf, &self->link_local_ip_)) abort(); + ifname, abuf, +self->prefixlen, abufp); + if (!ipaddr_to_string(abuf, sizeof abuf, &self->link_local_ip)) abort(); log_line("dhcp6: Link-local IP address for %s is %s.\n", ifname, abuf); - log_line("dhcp6: DHCPv6 Preference is %u on %s\n", self->preference_, self->ifname_); + log_line("dhcp6: DHCPv6 Preference is %u on %s\n", self->preference, self->ifname); return self; err: @@ -321,7 +321,7 @@ struct D6Listener *D6Listener_create(const char *ifname, const struct netif_info void D6Listener_destroy(struct D6Listener *self) { - close(self->fd_); + close(self->fd); free(self); } @@ -411,42 +411,42 @@ static bool allot_dynamic_ip(struct D6Listener *self, const char *client_duid, s enum dhcp6_code failcode, bool *use_dynamic) { uint32_t dynamic_lifetime; - if (!query_use_dynamic_v6(self->ifindex_, &dynamic_lifetime)) { + if (!query_use_dynamic_v6(self->ifindex, &dynamic_lifetime)) { if (!emit_IA_code(ss, iaid, failcode)) return false; *use_dynamic = false; return true; } - log_line("dhcp6: Checking dynamic IP on %s...\n", self->ifname_); + log_line("dhcp6: Checking dynamic IP on %s...\n", self->ifname); int64_t expire_time = get_current_ts() + dynamic_lifetime; - struct in6_addr v6a = dynlease6_query_refresh(self->ifindex_, client_duid, client_duid_size, iaid, expire_time); + struct in6_addr v6a = dynlease6_query_refresh(self->ifindex, client_duid, client_duid_size, iaid, expire_time); if (memcmp(&v6a, &in6addr_any, sizeof v6a)) { if (!emit_IA_addr(ss, v6a, iaid, dynamic_lifetime)) return false; char abuf[48]; if (!ipaddr_to_string(abuf, sizeof abuf, &v6a)) abort(); - log_line("dhcp6: Assigned existing dynamic IP (%s) on %s\n", abuf, self->ifname_); + log_line("dhcp6: Assigned existing dynamic IP (%s) on %s\n", abuf, self->ifname); *use_dynamic = true; return true; } // This check guards against OOM via DoS. - if (dynlease6_count(self->ifindex_) >= MAX_DYN_LEASES) { + if (dynlease6_count(self->ifindex) >= MAX_DYN_LEASES) { log_line("dhcp6: Maximum number of dynamic leases (%u) reached on %s\n", - MAX_DYN_LEASES, self->ifname_); + MAX_DYN_LEASES, self->ifname); if (!emit_IA_code(ss, iaid, failcode)) return false; *use_dynamic = false; return true; } - log_line("dhcp6: Selecting an unused dynamic IP on %s\n", self->ifname_); + log_line("dhcp6: Selecting an unused dynamic IP on %s\n", self->ifname); // Given a prefix, choose a random address. Then check it against our // existing static and dynamic leases. If no collision, assign a // dynamic lease to the random address and return it. for (unsigned attempt = 0; attempt < MAX_DYN_ATTEMPTS; ++attempt) { - v6a = v6_addr_random(&self->local_ip_prefix_, self->prefixlen_); - if (!query_unused_addr_v6(self->ifindex_, &v6a)) continue; - bool assigned = dynlease6_add(self->ifindex_, &v6a, client_duid, + v6a = v6_addr_random(&self->local_ip_prefix, self->prefixlen); + if (!query_unused_addr_v6(self->ifindex, &v6a)) continue; + bool assigned = dynlease6_add(self->ifindex, &v6a, client_duid, client_duid_size, iaid, expire_time); if (assigned) { if (!emit_IA_addr(ss, v6a, iaid, dynamic_lifetime)) return false; @@ -455,7 +455,7 @@ static bool allot_dynamic_ip(struct D6Listener *self, const char *client_duid, s } } log_line("dhcp6: Unable to select an unused dynamic IP after %u attempts on %s\n", - MAX_DYN_ATTEMPTS, self->ifname_); + MAX_DYN_ATTEMPTS, self->ifname); if (!emit_IA_code(ss, iaid, failcode)) return false; *use_dynamic = false; return true; @@ -478,11 +478,11 @@ static bool write_response_header(struct D6Listener *self, const struct d6msg_st memcpy(ss->si, d6s->client_duid_blob, d6s->client_duid_blob_size); ss->si += d6s->client_duid_blob_size; - if (self->preference_ > 0) { + if (self->preference > 0) { struct dhcp6_opt send_pref = dhcp6_opt_create(7, 1); if (!dhcp6_opt_write(&send_pref, ss)) return false; if (ss->si == ss->se) return false; - *ss->si++ = (char)self->preference_; + *ss->si++ = (char)self->preference; } return true; } @@ -495,13 +495,13 @@ static bool attach_address_info(struct D6Listener *self, const struct d6msg_stat // Look through IAs and send IA with assigned address as an option. for (size_t i = 0; i < d6s->ias_n; ++i) { log_line("dhcp6: Querying duid='%s' iaid=%u...\n", d6s->client_duid_str, d6s->ias[i].iaid); - const struct dhcpv6_entry *x = query_dhcp6_state(self->ifindex_, d6s->client_duid_str, + const struct dhcpv6_entry *x = query_dhcp6_state(self->ifindex, d6s->client_duid_str, d6s->client_duid_str_size, d6s->ias[i].iaid); if (x) { ha = true; char abuf[48]; if (!ipaddr_to_string(abuf, sizeof abuf, &x->address)) abort(); - log_line("dhcp6: Found static address %s on %s\n", abuf, self->ifname_); + log_line("dhcp6: Found static address %s on %s\n", abuf, self->ifname); if (!emit_IA_addr(ss, x->address, x->iaid, x->lifetime)) return false; continue; } @@ -510,7 +510,7 @@ static bool attach_address_info(struct D6Listener *self, const struct d6msg_stat ss, d6s->ias[i].iaid, failcode, &use_dynamic)) return false; if (use_dynamic) ha = true; } - if (!ha) log_line("dhcp6: Unable to assign any IPs on %s!\n", self->ifname_); + if (!ha) log_line("dhcp6: Unable to assign any IPs on %s!\n", self->ifname); if (has_addrs) *has_addrs = ha; return true; } @@ -520,7 +520,7 @@ static bool attach_address_info(struct D6Listener *self, const struct d6msg_stat // see if it is in the opt_req before adding it to the reply. static bool attach_dns_ntp_info(struct D6Listener *self, const struct d6msg_state *d6s, struct sbufs *ss) { - struct addrlist dns_servers = query_dns_servers(self->ifindex_); + struct addrlist dns_servers = query_dns_servers(self->ifindex); if (!dns_servers.n) return true; if (d6s->optreq_dns && dns_servers.n) { @@ -531,7 +531,7 @@ static bool attach_dns_ntp_info(struct D6Listener *self, const struct d6msg_stat memcpy(ss->si, dns_servers.addrs, siz); ss->si += siz; } - struct blob d6b = query_dns6_search_blob(self->ifindex_); + struct blob d6b = query_dns6_search_blob(self->ifindex); if (d6s->optreq_dns_search && (d6b.s && d6b.n)) { struct dhcp6_opt send_dns_search = dhcp6_opt_create(24, d6b.n); if (!dhcp6_opt_write(&send_dns_search, ss)) return false; @@ -539,7 +539,7 @@ static bool attach_dns_ntp_info(struct D6Listener *self, const struct d6msg_stat memcpy(ss->si, d6b.s, d6b.n); ss->si += d6b.n; } - struct addrlist ntp_servers = query_ntp_servers(self->ifindex_); + struct addrlist ntp_servers = query_ntp_servers(self->ifindex); if (d6s->optreq_ntp && ntp_servers.n) { size_t siz = ntp_servers.n * 20; if (ss->se - ss->si < (ptrdiff_t)(siz + 4)) return false; @@ -570,13 +570,13 @@ static bool confirm_match(struct D6Listener *self, const struct d6msg_state *d6s log_line("dhcp6: Confirming match for duid='%s' iaid=%u...\n", d6s->client_duid_str, d6s->ias[i].iaid); if (!d6s->ias[i].ia_na_addrs_n) return false; // See RFC8415 18.3.3 p3 for (size_t j = 0; j < d6s->ias[i].ia_na_addrs_n; ++j) { - if (!ipaddr_compare_masked(&d6s->ias[i].ia_na_addrs[j].addr, &self->local_ip_prefix_, self->prefixlen_)) { + if (!ipaddr_compare_masked(&d6s->ias[i].ia_na_addrs[j].addr, &self->local_ip_prefix, self->prefixlen)) { char abuf[48]; if (!ipaddr_to_string(abuf, sizeof abuf, &d6s->ias[i].ia_na_addrs[j].addr)) abort(); - log_line("dhcp6: Invalid prefix for IA IP %s on %s. NAK.\n", abuf, self->ifname_); + log_line("dhcp6: Invalid prefix for IA IP %s on %s. NAK.\n", abuf, self->ifname); return true; } else { - log_line("dhcp6: IA iaid=%u has a valid prefix on %s\n", d6s->ias[i].iaid, self->ifname_); + log_line("dhcp6: IA iaid=%u has a valid prefix on %s\n", d6s->ias[i].iaid, self->ifname); } } } @@ -589,29 +589,29 @@ static bool mark_addr_unused(struct D6Listener *self, const struct d6msg_state * for (size_t i = 0; i < d6s->ias_n; ++i) { bool freed_ia_addr = false; log_line("dhcp6: Marking duid='%s' iaid=%u unused on %s...\n", - d6s->client_duid_str, d6s->ias[i].iaid, self->ifname_); - const struct dhcpv6_entry *x = query_dhcp6_state(self->ifindex_, d6s->client_duid_str, + d6s->client_duid_str, d6s->ias[i].iaid, self->ifname); + const struct dhcpv6_entry *x = query_dhcp6_state(self->ifindex, d6s->client_duid_str, d6s->client_duid_str_size, d6s->ias[i].iaid); for (size_t j = 0; j < d6s->ias[i].ia_na_addrs_n; ++j) { if (x && !memcmp(&d6s->ias[i].ia_na_addrs[j].addr, &x->address, 16)) { - log_line("dhcp6: found static lease on %s\n", self->ifname_); + log_line("dhcp6: found static lease on %s\n", self->ifname); freed_ia_addr = true; - } else if (dynlease6_del(self->ifindex_, &d6s->ias[i].ia_na_addrs[j].addr, d6s->client_duid_str, + } else if (dynlease6_del(self->ifindex, &d6s->ias[i].ia_na_addrs[j].addr, d6s->client_duid_str, d6s->client_duid_str_size, d6s->ias[i].iaid)) { - log_line("dhcp6: found dynamic lease on %s\n", self->ifname_); + log_line("dhcp6: found dynamic lease on %s\n", self->ifname); freed_ia_addr = true; } } if (!freed_ia_addr) { if (!emit_IA_code(ss, d6s->ias[i].iaid, D6_CODE_NOBINDING)) return false; - log_line("dhcp6: no dynamic lease found on %s\n", self->ifname_); + log_line("dhcp6: no dynamic lease found on %s\n", self->ifname); } } return true; } #define OPTIONS_CONSUME(BLD_VAL) do { \ - if (!options_consume(&d6s, (BLD_VAL), self->ifname_)) return; \ + if (!options_consume(&d6s, (BLD_VAL), self->ifname)) return; \ } while (0) static bool options_consume(struct d6msg_state *d6s, size_t v, const char *ifname) @@ -643,26 +643,26 @@ static void process_receive(struct D6Listener *self, char *buf, size_t buflen, char ip[32]; struct sbufs rs = { buf, buf + buflen }; - if (!self->using_bpf_ && buflen < DHCP6_HEADER_SIZE) { + if (!self->using_bpf && buflen < DHCP6_HEADER_SIZE) { // Discard if the DHCP6 length < the size of a DHCP6 header. ipaddr_to_string(ip, sizeof ip, &sai->sin6_addr); - log_line("dhcp6: Packet from %s is too short (%zu) on %s\n", ip, buflen, self->ifname_); + log_line("dhcp6: Packet from %s is too short (%zu) on %s\n", ip, buflen, self->ifname); return; } struct d6msg_state d6s = {0}; if (!dhcp6_header_read(&d6s.header, &rs)) { ipaddr_to_string(ip, sizeof ip, &sai->sin6_addr); - log_line("dhcp6: Packet from %s has no valid option headers on %s\n", ip, self->ifname_); + log_line("dhcp6: Packet from %s has no valid option headers on %s\n", ip, self->ifname); return; } OPTIONS_CONSUME(DHCP6_HEADER_SIZE); enum dhcp6_msgtype msgtype = dhcp6_header_msgtype(&d6s.header); - log_line("dhcp6: Message (%s) on %s\n", dhcp6_msgtype_to_string(msgtype), self->ifname_); + log_line("dhcp6: Message (%s) on %s\n", dhcp6_msgtype_to_string(msgtype), self->ifname); // These message types are not allowed to be sent to servers. - if (!self->using_bpf_) { + if (!self->using_bpf) { switch (d6s.header.type) { case D6_MSGTYPE_ADVERTISE: case D6_MSGTYPE_REPLY: @@ -681,7 +681,7 @@ static void process_receive(struct D6Listener *self, char *buf, size_t buflen, uint16_t ot = dhcp6_opt_type(&opt); if (l > sbufs_brem(&rs)) { - log_debug("dhcp6: Option is too long on %s\n", self->ifname_); + log_debug("dhcp6: Option is too long on %s\n", self->ifname); return; } @@ -704,12 +704,12 @@ static void process_receive(struct D6Listener *self, char *buf, size_t buflen, OPTIONS_CONSUME(l); } else if (ot == 3) { // Option_IA_NA if (l < 12) { - log_debug("dhcp6: Client-sent option IA_NA has a bad length on %s\n", self->ifname_); + log_debug("dhcp6: Client-sent option IA_NA has a bad length on %s\n", self->ifname); return; } if (d6s.ias_n >= D6_MAX_IAS) { log_debug("dhcp6: Client sent too many >(%zu) IA_NA options on %s\n", - d6s.ias_n, self->ifname_); + d6s.ias_n, self->ifname); return; } if (!dhcp6_ia_na_read(&d6s.ias[d6s.ias_n], &rs)) return; @@ -720,7 +720,7 @@ static void process_receive(struct D6Listener *self, char *buf, size_t buflen, if (na_options_len > 0) { if (d6s.prev_opt_n >= D6_MAX_ENCAP_DEPTH) { log_line("dhcp6: Client sent too deep >(%zu) of option encapsulation on %s\n", - d6s.prev_opt_n, self->ifname_); + d6s.prev_opt_n, self->ifname); return; } d6s.prev_opt_code[d6s.prev_opt_n] = 3; @@ -728,25 +728,25 @@ static void process_receive(struct D6Listener *self, char *buf, size_t buflen, } } else if (ot == 5) { // Address if (l < 24) { - log_debug("dhcp6: Client-sent option IAADDR has a bad length (%u) on %s\n", l, self->ifname_); + log_debug("dhcp6: Client-sent option IAADDR has a bad length (%u) on %s\n", l, self->ifname); return; } if (d6s.prev_opt_n != 1) { - log_debug("dhcp6: Client-sent option IAADDR is not nested on %s\n", self->ifname_); + log_debug("dhcp6: Client-sent option IAADDR is not nested on %s\n", self->ifname); return; } if (d6s.prev_opt_code[0] != 3) { - log_debug("dhcp6: Client-sent option IAADDR must follow IA_NA on %s\n", self->ifname_); + log_debug("dhcp6: Client-sent option IAADDR must follow IA_NA on %s\n", self->ifname); return; } if (!d6s.ias_n) { - log_debug("dhcp6: d6.ias is empty on %s\n", self->ifname_); + log_debug("dhcp6: d6.ias is empty on %s\n", self->ifname); return; } size_t niana = d6s.ias[d6s.ias_n - 1].ia_na_addrs_n; if (d6s.ias[d6s.ias_n - 1].ia_na_addrs_n >= D6_MAX_IA_ADDRS) { log_line("dhcp6: Client sent too many >(%zu) IA_NA addresses on %s\n", - niana, self->ifname_); + niana, self->ifname); return; } if (!dhcp6_ia_addr_read(&d6s.ias[d6s.ias_n - 1].ia_na_addrs[niana], &rs)) return; @@ -760,7 +760,7 @@ static void process_receive(struct D6Listener *self, char *buf, size_t buflen, d6s.ias[d6s.ias_n - 1].ia_na_addrs_n++; } else if (ot == 6) { // OptionRequest if (l % 2) { - log_debug("dhcp6: Client-sent option Request has a bad length (%d) on %s\n", l, self->ifname_); + log_debug("dhcp6: Client-sent option Request has a bad length (%d) on %s\n", l, self->ifname); return; } d6s.optreq_exists = true; @@ -780,20 +780,20 @@ static void process_receive(struct D6Listener *self, char *buf, size_t buflen, } else if (ot == 8) { // ElapsedTime // 16-bit hundreths of a second since start of exchange if (l != 2) { - log_debug("dhcp6: Client-sent option ElapsedTime has a bad length on %s\n", self->ifname_); + log_debug("dhcp6: Client-sent option ElapsedTime has a bad length on %s\n", self->ifname); return; } d6s.elapsed_time = decode16be(rs.si); rs.si += 2; OPTIONS_CONSUME(2); } else if (ot == 14) { // Rapid Commit if (l != 0) { - log_debug("dhcp6: Client-sent option Rapid Commit has a bad length on %s\n", self->ifname_); + log_debug("dhcp6: Client-sent option Rapid Commit has a bad length on %s\n", self->ifname); return; } d6s.use_rapid_commit = true; } else if (ot == 39) { // Client FQDN if (l < 3) { - log_debug("dhcp6: Client-sent option Client FQDN has a bad length on %s\n", self->ifname_); + log_debug("dhcp6: Client-sent option Client FQDN has a bad length on %s\n", self->ifname); return; } uint8_t flags = (uint8_t)*rs.si++; @@ -801,10 +801,10 @@ static void process_receive(struct D6Listener *self, char *buf, size_t buflen, OPTIONS_CONSUME(2); l -= 2; if (l != namelen) { - log_debug("dhcp6: Client-sent option Client FQDN namelen disagrees with length on %s\n", self->ifname_); + log_debug("dhcp6: Client-sent option Client FQDN namelen disagrees with length on %s\n", self->ifname); return; } - log_line("dhcp6: Client FQDN: flags='%u' '%.*s' on %s\n", flags, namelen, rs.si, self->ifname_); + log_line("dhcp6: Client FQDN: flags='%u' '%.*s' on %s\n", flags, namelen, rs.si, self->ifname); rs.si += l; OPTIONS_CONSUME(l); } else { @@ -888,7 +888,7 @@ static void process_receive(struct D6Listener *self, char *buf, size_t buflen, if (!d6s.ias_n) return; if (!write_response_header(self, &d6s, &ss, D6_MSGTYPE_REPLY)) return; if (!attach_dns_ntp_info(self, &d6s, &ss)) return; - log_line("dhcp6: Sending Information Message in response on %s\n", self->ifname_); + log_line("dhcp6: Sending Information Message in response on %s\n", self->ifname); break; default: return; } @@ -897,9 +897,9 @@ static void process_receive(struct D6Listener *self, char *buf, size_t buflen, memcpy(&sao, sai, sizeof sao); sao.sin6_port = htons(546); size_t slen = ss.si > sbuf ? (size_t)(ss.si - sbuf) : 0; - if (safe_sendto(self->fd_, sbuf, slen, 0, (const struct sockaddr *)&sao, sizeof sao) < 0) { + if (safe_sendto(self->fd, sbuf, slen, 0, (const struct sockaddr *)&sao, sizeof sao) < 0) { ipaddr_to_string(ip, sizeof ip, &sai->sin6_addr); - log_line("dhcp6: sendto (%s) failed on %s: %s\n", ip, self->ifname_, strerror(errno)); + log_line("dhcp6: sendto (%s) failed on %s: %s\n", ip, self->ifname, strerror(errno)); return; } } @@ -910,15 +910,15 @@ void D6Listener_process_input(struct D6Listener *self) for (;;) { struct sockaddr_in6 sai; socklen_t sailen = sizeof sai; - ssize_t buflen = recvfrom(self->fd_, buf, sizeof buf, MSG_DONTWAIT, (struct sockaddr *)&sai, &sailen); + ssize_t buflen = recvfrom(self->fd, buf, sizeof buf, MSG_DONTWAIT, (struct sockaddr *)&sai, &sailen); if (buflen < 0) { int err = errno; if (err == EINTR) continue; if (err == EAGAIN || err == EWOULDBLOCK) break; - suicide("dhcp6: recvfrom failed on %s: %s\n", self->ifname_, strerror(err)); + suicide("dhcp6: recvfrom failed on %s: %s\n", self->ifname, strerror(err)); } process_receive(self, buf, (size_t)buflen, &sai); } } -int D6Listener_fd(const struct D6Listener *self) { return self->fd_; } +int D6Listener_fd(const struct D6Listener *self) { return self->fd; } diff --git a/ndhs.c b/ndhs.c index b8d1f8f..32841a5 100644 --- a/ndhs.c +++ b/ndhs.c @@ -130,7 +130,7 @@ static void init_listeners(void) bound_interfaces_foreach(get_interface_addresses, NULL); - poll_array[0] = (struct pollfd){ .fd = nl_socket.fd_, .events = POLLIN|POLLHUP|POLLERR }; + poll_array[0] = (struct pollfd){ .fd = nl_socket.fd, .events = POLLIN|POLLHUP|POLLERR }; poll_meta[0] = (struct pfd_meta){ .pfdt = PFD_TYPE_NETLINK }; size_t pfdc = 1; diff --git a/nlsocket.c b/nlsocket.c index 2409ed7..133a320 100644 --- a/nlsocket.c +++ b/nlsocket.c @@ -32,17 +32,17 @@ static void process_receive(struct NLSocket *self, const char *buf, size_t bytes void NLSocket_init(struct NLSocket *self) { - self->nlseq_ = nk_random_u64(&g_rngstate); - self->got_newlink_ = false; - self->query_ifindex_ = -1; + self->nlseq = nk_random_u64(&g_rngstate); + self->got_newlink = false; + self->query_ifindex = -1; - self->fd_ = nl_open(NETLINK_ROUTE, RTMGRP_LINK, 0); - if (self->fd_ < 0) suicide("NLSocket: failed to create netlink socket\n"); + self->fd = nl_open(NETLINK_ROUTE, RTMGRP_LINK, 0); + if (self->fd < 0) suicide("NLSocket: failed to create netlink socket\n"); request_links(self); - struct pollfd pfd = { .fd = self->fd_, .events = POLLIN|POLLHUP|POLLERR }; - for (;(self->got_newlink_ == false);) { + struct pollfd pfd = { .fd = self->fd, .events = POLLIN|POLLHUP|POLLERR }; + for (;(self->got_newlink == false);) { if (poll(&pfd, 1, -1) < 0) { if (errno == EINTR) continue; suicide("poll failed\n"); @@ -58,12 +58,12 @@ void NLSocket_init(struct NLSocket *self) bool NLSocket_get_interface_addresses(struct NLSocket *self, int ifindex) { - self->query_ifindex_ = ifindex; - if (self->query_ifindex_ < 0) return false; - request_addrs(self, self->query_ifindex_); + self->query_ifindex = ifindex; + if (self->query_ifindex < 0) return false; + request_addrs(self, self->query_ifindex); - struct pollfd pfd = { .fd = self->fd_, .events = POLLIN|POLLHUP|POLLERR }; - while (self->query_ifindex_ >= 0) { + struct pollfd pfd = { .fd = self->fd, .events = POLLIN|POLLHUP|POLLERR }; + while (self->query_ifindex >= 0) { if (poll(&pfd, 1, -1) < 0) { if (errno == EINTR) continue; suicide("poll failed\n"); @@ -82,7 +82,7 @@ void NLSocket_process_input(struct NLSocket *self) { char buf[8192]; for (;;) { - ssize_t buflen = recv(self->fd_, buf, sizeof buf, MSG_DONTWAIT); + ssize_t buflen = recv(self->fd, buf, sizeof buf, MSG_DONTWAIT); if (buflen < 0) { int err = errno; if (err == EINTR) continue; @@ -95,15 +95,15 @@ void NLSocket_process_input(struct NLSocket *self) static void request_links(struct NLSocket *self) { - uint32_t link_seq = self->nlseq_++; - if (nl_sendgetlinks(self->fd_, link_seq) < 0) + uint32_t link_seq = self->nlseq++; + if (nl_sendgetlinks(self->fd, link_seq) < 0) suicide("nlsocket: failed to get initial rtlink state\n"); } static void request_addrs(struct NLSocket *self, int ifidx) { - uint32_t addr_seq = self->nlseq_++; - if (nl_sendgetaddr(self->fd_, addr_seq, (uint32_t)ifidx) < 0) + uint32_t addr_seq = self->nlseq++; + if (nl_sendgetaddr(self->fd, addr_seq, (uint32_t)ifidx) < 0) suicide("nlsocket: failed to get initial rtaddr state\n"); } @@ -167,9 +167,9 @@ static void process_rt_addr_msgs(struct NLSocket *self, const struct nlmsghdr *n switch (nlh->nlmsg_type) { case RTM_NEWADDR: { - if (self->query_ifindex_ == nia.if_index) self->query_ifindex_ = -1; + if (self->query_ifindex == nia.if_index) self->query_ifindex = -1; if (nia.if_index >= 0 && nia.if_index < MAX_NL_INTERFACES) { - struct netif_info *n = &self->interfaces_[nia.if_index]; + struct netif_info *n = &self->interfaces[nia.if_index]; if (nia.addr_type == AF_INET || ipaddr_is_v4(&nia.address)) { n->has_v4_address = true; n->v4_address = nia.address; @@ -201,7 +201,7 @@ static void process_rt_addr_msgs(struct NLSocket *self, const struct nlmsghdr *n } case RTM_DELADDR: { if (nia.if_index >= 0 && nia.if_index < MAX_NL_INTERFACES) { - struct netif_info *n = &self->interfaces_[nia.if_index]; + struct netif_info *n = &self->interfaces[nia.if_index]; if (n->has_v4_address && (nia.addr_type == AF_INET || ipaddr_is_v4(&nia.address))) { if (!memcmp(&n->v4_address, &nia.address, sizeof nia.address)) { memset(&n->v4_address, 0, sizeof n->v4_address); @@ -272,10 +272,10 @@ static void process_rt_link_msgs(struct NLSocket *self, const struct nlmsghdr *n break; } bool update = false; - if (!strcmp(self->interfaces_[ifm->ifi_index].name, nii.name)) { + if (!strcmp(self->interfaces[ifm->ifi_index].name, nii.name)) { // We don't alter name or index, and addresses are not // sent in this message, so don't alter those. - struct netif_info *n = &self->interfaces_[ifm->ifi_index]; + struct netif_info *n = &self->interfaces[ifm->ifi_index]; n->family = nii.family; n->device_type = nii.device_type; n->flags = nii.flags; @@ -287,7 +287,7 @@ static void process_rt_link_msgs(struct NLSocket *self, const struct nlmsghdr *n n->is_active = nii.is_active; update = true; } - if (!update) memcpy(&self->interfaces_[ifm->ifi_index], &nii, sizeof self->interfaces_[0]); + if (!update) memcpy(&self->interfaces[ifm->ifi_index], &nii, sizeof self->interfaces[0]); log_line("nlsocket: Adding link info: %s\n", nii.name); break; } @@ -296,7 +296,7 @@ static void process_rt_link_msgs(struct NLSocket *self, const struct nlmsghdr *n log_line("nlsocket: Attempt to delete interface with out-of-range index (%d)\n", ifm->ifi_index); break; } - memset(&self->interfaces_[ifm->ifi_index], 0, sizeof self->interfaces_[0]); + memset(&self->interfaces[ifm->ifi_index], 0, sizeof self->interfaces[0]); break; } default: @@ -349,7 +349,7 @@ static void process_receive(struct NLSocket *self, const char *buf, size_t bytes } case NLMSG_OVERRUN: log_line("nlsocket: Received a NLMSG_OVERRUN.\n"); case NLMSG_NOOP: break; - case NLMSG_DONE: self->got_newlink_ = true; break; + case NLMSG_DONE: self->got_newlink = true; break; default: break; } } diff --git a/nlsocket.h b/nlsocket.h index c647089..513a74a 100644 --- a/nlsocket.h +++ b/nlsocket.h @@ -35,11 +35,11 @@ struct netif_info struct NLSocket { - struct netif_info interfaces_[MAX_NL_INTERFACES]; - int query_ifindex_; - int fd_; - uint32_t nlseq_; - bool got_newlink_:1; + struct netif_info interfaces[MAX_NL_INTERFACES]; + int query_ifindex; + int fd; + uint32_t nlseq; + bool got_newlink:1; }; void NLSocket_init(struct NLSocket *self); @@ -49,7 +49,7 @@ void NLSocket_process_input(struct NLSocket *self); static inline int NLSocket_get_ifindex(const struct NLSocket *self, const char *name) { for (int i = 0; i < MAX_NL_INTERFACES; ++i) { - if (!strcmp(name, self->interfaces_[i].name)) return i; + if (!strcmp(name, self->interfaces[i].name)) return i; } return -1; } @@ -59,12 +59,12 @@ static inline int NLSocket_get_ifindex(const struct NLSocket *self, const char * static inline struct netif_info *NLSocket_get_ifinfo(struct NLSocket *self, int ifindex) { if (ifindex < 0 || ifindex >= MAX_NL_INTERFACES) return NULL; - return &self->interfaces_[ifindex]; + return &self->interfaces[ifindex]; } static inline struct netif_info *NLSocket_get_ifinfo_by_name(struct NLSocket *self, const char *name) { for (size_t i = 0; i < MAX_NL_INTERFACES; ++i) { - if (!strcmp(name, self->interfaces_[i].name)) return &self->interfaces_[i]; + if (!strcmp(name, self->interfaces[i].name)) return &self->interfaces[i]; } return NULL; } diff --git a/radv6.c b/radv6.c index 8429f30..f75ca06 100644 --- a/radv6.c +++ b/radv6.c @@ -25,12 +25,12 @@ extern struct nk_random_state g_rngstate; struct RA6Listener { - struct timespec advert_ts_; - char ifname_[IFNAMSIZ]; + struct timespec advert_ts; + char ifname[IFNAMSIZ]; int ifindex; - int fd_; - unsigned advi_s_max_; - bool using_bpf_:1; + int fd; + unsigned advi_s_max; + bool using_bpf:1; }; static inline void toggle_bit(bool v, void *data, size_t arrayidx, unsigned char bitidx) @@ -232,23 +232,23 @@ static bool ra6_dns_search_opt_write(const struct ra6_dns_search_opt *self, stru static void attach_bpf(struct RA6Listener *self) { - self->using_bpf_ = attach_bpf_icmp6_ra(self->fd_, self->ifname_); + self->using_bpf = attach_bpf_icmp6_ra(self->fd, self->ifname); } static void set_next_advert_ts(struct RA6Listener *self) { - unsigned advi_s_min = self->advi_s_max_ / 3 > 3u ? self->advi_s_max_ / 3 : 3u; + unsigned advi_s_min = self->advi_s_max / 3 > 3u ? self->advi_s_max / 3 : 3u; // The extremely small distribution skew does not matter here. - unsigned advi_s = (unsigned)(nk_random_u64(&g_rngstate) % (self->advi_s_max_ - advi_s_min)) + advi_s_min; - clock_gettime(CLOCK_BOOTTIME, &self->advert_ts_); - self->advert_ts_.tv_sec += advi_s; + unsigned advi_s = (unsigned)(nk_random_u64(&g_rngstate) % (self->advi_s_max - advi_s_min)) + advi_s_min; + clock_gettime(CLOCK_BOOTTIME, &self->advert_ts); + self->advert_ts.tv_sec += advi_s; } static void set_advi_s_max(struct RA6Listener *self, unsigned v) { v = v > 4u ? v : 4u; v = v < 1800u ? v : 1800u; - self->advi_s_max_ = v; + self->advi_s_max = v; } static bool send_advert(struct RA6Listener *self); @@ -277,7 +277,7 @@ struct RA6Listener *RA6Listener_create(const char *ifname, const struct netif_in struct RA6Listener *self; struct sockaddr_in6 sai = { .sin6_family = AF_INET6, }; size_t ifname_src_size = strlen(ifname); - if (ifname_src_size >= sizeof self->ifname_) { + if (ifname_src_size >= sizeof self->ifname) { log_line("RA6Listener: Interface name (%s) too long\n", ifname); return NULL; } @@ -290,33 +290,33 @@ struct RA6Listener *RA6Listener_create(const char *ifname, const struct netif_in self->ifindex = ifinfo->index; set_advi_s_max(self, 600); - self->using_bpf_ = false; - *(char *)(mempcpy(self->ifname_, ifname, ifname_src_size)) = 0; + self->using_bpf = false; + *(char *)(mempcpy(self->ifname, ifname, ifname_src_size)) = 0; - if (self->fd_ >= 0) close(self->fd_); - self->fd_ = socket(AF_INET6, SOCK_RAW|SOCK_CLOEXEC, IPPROTO_ICMPV6); - if (self->fd_ < 0) { - log_line("ra6: Failed to create v6 ICMP socket on %s: %s\n", self->ifname_, strerror(errno)); + if (self->fd >= 0) close(self->fd); + self->fd = socket(AF_INET6, SOCK_RAW|SOCK_CLOEXEC, IPPROTO_ICMPV6); + if (self->fd < 0) { + log_line("ra6: Failed to create v6 ICMP socket on %s: %s\n", self->ifname, strerror(errno)); goto err0; } - if (!attach_multicast_sockaddr_in6(self->fd_, self->ifname_, &mc6_allrouters)) { + if (!attach_multicast_sockaddr_in6(self->fd, self->ifname, &mc6_allrouters)) { goto err1; } attach_bpf(self); - if (bind(self->fd_, (const struct sockaddr *)&sai, sizeof sai)) { - log_line("ra6: Failed to bind ICMP route advertisement listener on %s: %s\n", self->ifname_, strerror(errno)); + if (bind(self->fd, (const struct sockaddr *)&sai, sizeof sai)) { + log_line("ra6: Failed to bind ICMP route advertisement listener on %s: %s\n", self->ifname, strerror(errno)); goto err1; } if (!send_advert(self)) - log_line("ra6: Failed to send initial router advertisement on %s\n", self->ifname_); + log_line("ra6: Failed to send initial router advertisement on %s\n", self->ifname); set_next_advert_ts(self); return self; err1: - close(self->fd_); - self->fd_ = -1; + close(self->fd); + self->fd = -1; err0: free(self); return NULL; @@ -336,7 +336,7 @@ static bool send_advert(struct RA6Listener *self) struct netif_info *ifinfo = NLSocket_get_ifinfo(&nl_socket, self->ifindex); if (!ifinfo) { - log_line("ra6: Failed to get interface info for %s\n", self->ifname_); + log_line("ra6: Failed to get interface info for %s\n", self->ifname); return false; } @@ -346,7 +346,7 @@ static bool send_advert(struct RA6Listener *self) ra6_advert_header_set_hoplimit(&ra6adv_hdr, 0); ra6_advert_header_set_managed_addresses(&ra6adv_hdr, true); ra6_advert_header_set_other_stateful(&ra6adv_hdr, true); - ra6_advert_header_set_router_lifetime(&ra6adv_hdr, 3 * self->advi_s_max_); + ra6_advert_header_set_router_lifetime(&ra6adv_hdr, 3 * self->advi_s_max); ra6_advert_header_set_reachable_time(&ra6adv_hdr, 0); ra6_advert_header_set_retransmit_timer(&ra6adv_hdr, 0); csum = net_checksum16_add @@ -374,7 +374,7 @@ static bool send_advert(struct RA6Listener *self) if (dns_servers.n) { ra6_rdns_opt_set_length(&ra6_dns, dns_servers.n); - ra6_rdns_opt_set_lifetime(&ra6_dns, self->advi_s_max_ * 2); + ra6_rdns_opt_set_lifetime(&ra6_dns, self->advi_s_max * 2); csum = net_checksum16_add(csum, net_checksum16(&ra6_dns, sizeof ra6_dns)); pktl += sizeof ra6_dns + 16 * dns_servers.n; } @@ -382,7 +382,7 @@ static bool send_advert(struct RA6Listener *self) size_t dns_search_slack = 0; if (d6b.s && d6b.n) { dns_search_slack = ra6_dns_search_opt_set_length(&ra6_dsrch, d6b.n); - ra6_dns_search_opt_set_lifetime(&ra6_dsrch, self->advi_s_max_ * 2); + ra6_dns_search_opt_set_lifetime(&ra6_dsrch, self->advi_s_max * 2); csum = net_checksum16_add(csum, net_checksum16(&ra6_dsrch, sizeof ra6_dsrch)); csum = net_checksum16_add(csum, net_checksum16(d6b.s, d6b.n)); pktl += sizeof ra6_dsrch + d6b.n + dns_search_slack; @@ -425,8 +425,8 @@ static bool send_advert(struct RA6Listener *self) } size_t slen = ss.si > sbuf ? (size_t)(ss.si - sbuf) : 0; - if (safe_sendto(self->fd_, sbuf, slen, 0, (const struct sockaddr *)&mc6_allhosts, sizeof mc6_allhosts) < 0) { - log_line("ra6: sendto failed on %s: %s\n", self->ifname_, strerror(errno)); + if (safe_sendto(self->fd, sbuf, slen, 0, (const struct sockaddr *)&mc6_allhosts, sizeof mc6_allhosts) < 0) { + log_line("ra6: sendto failed on %s: %s\n", self->ifname, strerror(errno)); return false; } return true; @@ -436,13 +436,13 @@ int RA6Listener_send_periodic_advert(struct RA6Listener *self) { struct timespec now; clock_gettime(CLOCK_BOOTTIME, &now); - if (now.tv_sec > self->advert_ts_.tv_sec - || (now.tv_sec == self->advert_ts_.tv_sec && now.tv_nsec > self->advert_ts_.tv_nsec)) { + if (now.tv_sec > self->advert_ts.tv_sec + || (now.tv_sec == self->advert_ts.tv_sec && now.tv_nsec > self->advert_ts.tv_nsec)) { if (!send_advert(self)) - log_line("ra6: Failed to send periodic router advertisement on %s\n", self->ifname_); + log_line("ra6: Failed to send periodic router advertisement on %s\n", self->ifname); set_next_advert_ts(self); } - return 1000 + (self->advert_ts_.tv_sec - now.tv_sec) * 1000; // Always wait at least 1s + return 1000 + (self->advert_ts.tv_sec - now.tv_sec) * 1000; // Always wait at least 1s } static bool ip6_is_unspecified(const struct sockaddr_in6 *sa) @@ -468,15 +468,15 @@ static void process_receive(struct RA6Listener *self, char *buf, size_t buflen, struct icmp_header icmp_hdr; if (!icmp_header_read(&icmp_hdr, &rs)) return; - if (!self->using_bpf_) { + if (!self->using_bpf) { // Discard if the ICMP code is not 0. if (icmp_header_code(&icmp_hdr) != 0) { - log_line("ra6: ICMP code != 0 on %s\n", self->ifname_); + log_line("ra6: ICMP code != 0 on %s\n", self->ifname); return; } if (icmp_header_type(&icmp_hdr) != 133) { - log_line("ra6: ICMP type != 133 on %s\n", self->ifname_); + log_line("ra6: ICMP type != 133 on %s\n", self->ifname); return; } } @@ -493,17 +493,17 @@ static void process_receive(struct RA6Listener *self, char *buf, size_t buflen, size_t opt_length = 8 * (size_t)(*rs.si++); // Discard if any included option has a length <= 0. if (opt_length <= 0) { - log_line("ra6: Solicitation option length <= 0 on %s\n", self->ifname_); + log_line("ra6: Solicitation option length <= 0 on %s\n", self->ifname); return; } if (opt_type == 1) { if (got_macaddr) { - log_line("ra6: More than one Source Link-Layer Address option on %s; dropping\n", self->ifname_); + log_line("ra6: More than one Source Link-Layer Address option on %s; dropping\n", self->ifname); return; } if (opt_length == 8) { if (rs.se - rs.si < (ptrdiff_t)sizeof macaddr) { - log_line("ra6: Source Link-Layer Address is wrong size for ethernet on %s\n", self->ifname_); + log_line("ra6: Source Link-Layer Address is wrong size for ethernet on %s\n", self->ifname); return; } got_macaddr = true; @@ -511,15 +511,15 @@ static void process_receive(struct RA6Listener *self, char *buf, size_t buflen, macaddr[i] = (uint8_t)(*rs.si++); } } else { - log_line("ra6: Source Link-Layer Address is wrong size for ethernet on %s\n", self->ifname_); + log_line("ra6: Source Link-Layer Address is wrong size for ethernet on %s\n", self->ifname); return; } } else { if (rs.se - rs.si < (ptrdiff_t)opt_length - 2) { - log_line("ra6: Invalid length(%zu) for option type(%u) on %s\n", opt_length, +opt_type, self->ifname_); + log_line("ra6: Invalid length(%zu) for option type(%u) on %s\n", opt_length, +opt_type, self->ifname); return; } - log_line("ra6: Ignoring unknown option type(%u) on %s\n", +opt_type, self->ifname_); + log_line("ra6: Ignoring unknown option type(%u) on %s\n", +opt_type, self->ifname); for (size_t i = 0; i < opt_length - 2; ++i) rs.si++; } } @@ -527,13 +527,13 @@ static void process_receive(struct RA6Listener *self, char *buf, size_t buflen, // Discard if the source address is unspecified and // there is no source link-layer address option included. if (!got_macaddr && ip6_is_unspecified(sai)) { - log_line("ra6: Solicitation provides no specified source address or option on %s\n", self->ifname_); + log_line("ra6: Solicitation provides no specified source address or option on %s\n", self->ifname); return; } // Send a router advertisement in reply. if (!send_advert(self)) - log_line("ra6: Failed to send router advertisement on %s\n", self->ifname_); + log_line("ra6: Failed to send router advertisement on %s\n", self->ifname); set_next_advert_ts(self); } @@ -543,15 +543,15 @@ void RA6Listener_process_input(struct RA6Listener *self) for (;;) { struct sockaddr_in6 sai; socklen_t sailen = sizeof sai; - ssize_t buflen = recvfrom(self->fd_, buf, sizeof buf, MSG_DONTWAIT, (struct sockaddr *)&sai, &sailen); + ssize_t buflen = recvfrom(self->fd, buf, sizeof buf, MSG_DONTWAIT, (struct sockaddr *)&sai, &sailen); if (buflen < 0) { int err = errno; if (err == EINTR) continue; if (err == EAGAIN || err == EWOULDBLOCK) break; - suicide("ra6: recvfrom failed on %s: %s\n", self->ifname_, strerror(err)); + suicide("ra6: recvfrom failed on %s: %s\n", self->ifname, strerror(err)); } process_receive(self, buf, (size_t)buflen, &sai); } } -int RA6Listener_fd(const struct RA6Listener *self) { return self->fd_; } +int RA6Listener_fd(const struct RA6Listener *self) { return self->fd; }