Index: sys/netinet/in_pcb.c =================================================================== RCS file: /cvs/src/sys/netinet/in_pcb.c,v retrieving revision 1.261 diff -u -p -r1.261 in_pcb.c --- sys/netinet/in_pcb.c 14 Mar 2022 22:38:43 -0000 1.261 +++ sys/netinet/in_pcb.c 20 Mar 2022 23:09:33 -0000 @@ -476,7 +476,7 @@ in_pcbpickport(u_int16_t *lport, void *l int in_pcbconnect(struct inpcb *inp, struct mbuf *nam) { - struct in_addr *ina = NULL; + struct in_addr ina; struct sockaddr_in *sin; int error; @@ -495,7 +495,7 @@ in_pcbconnect(struct inpcb *inp, struct return (error); if (in_pcbhashlookup(inp->inp_table, sin->sin_addr, sin->sin_port, - *ina, inp->inp_lport, inp->inp_rtableid) != NULL) + ina, inp->inp_lport, inp->inp_rtableid) != NULL) return (EADDRINUSE); KASSERT(inp->inp_laddr.s_addr == INADDR_ANY || inp->inp_lport); @@ -506,13 +506,13 @@ in_pcbconnect(struct inpcb *inp, struct if (error) return (error); if (in_pcbhashlookup(inp->inp_table, sin->sin_addr, - sin->sin_port, *ina, inp->inp_lport, + sin->sin_port, ina, inp->inp_lport, inp->inp_rtableid) != NULL) { inp->inp_lport = 0; return (EADDRINUSE); } } - inp->inp_laddr = *ina; + inp->inp_laddr = ina; } inp->inp_faddr = sin->sin_addr; inp->inp_fport = sin->sin_port; @@ -870,7 +870,7 @@ in_pcbrtentry(struct inpcb *inp) * an entry to the caller for later use. */ int -in_pcbselsrc(struct in_addr **insrc, struct sockaddr_in *sin, +in_pcbselsrc(struct in_addr *insrc, struct sockaddr_in *sin, struct inpcb *inp) { struct ip_moptions *mopts = inp->inp_moptions; @@ -886,18 +886,21 @@ in_pcbselsrc(struct in_addr **insrc, str * If the socket(if any) is already bound, use that bound address * unless it is INADDR_ANY or INADDR_BROADCAST. */ - if (laddr && laddr->s_addr != INADDR_ANY && + if (laddr->s_addr != INADDR_ANY && laddr->s_addr != INADDR_BROADCAST) { - *insrc = laddr; + *insrc = *laddr; return (0); } /* - * If the destination address is multicast and an outgoing - * interface has been set as a multicast option, use the - * address of that interface as our source address. + * If the destination address is multicast or limited + * broadcast (255.255.255.255) and an outgoing interface has + * been set as a multicast option, use the address of that + * interface as our source address. */ - if (IN_MULTICAST(sin->sin_addr.s_addr) && mopts != NULL) { + if ((IN_MULTICAST(sin->sin_addr.s_addr) || + sin->sin_addr.s_addr == INADDR_BROADCAST) && + (mopts != NULL && mopts->imo_ifidx != 0)) { struct ifnet *ifp; ifp = if_get(mopts->imo_ifidx); @@ -906,10 +909,14 @@ in_pcbselsrc(struct in_addr **insrc, str IFP_TO_IA(ifp, ia); if (ia == NULL) { if_put(ifp); + if (sin->sin_addr.s_addr == INADDR_BROADCAST) { + insrc->s_addr = INADDR_ANY; + return (0); + } return (EADDRNOTAVAIL); } - *insrc = &ia->ia_addr.sin_addr; + *insrc = ia->ia_addr.sin_addr; if_put(ifp); return (0); } @@ -960,7 +967,7 @@ in_pcbselsrc(struct in_addr **insrc, str struct ifaddr *ifa; if ((ifa = ifa_ifwithaddr(ip4_source, rtableid)) != NULL && ISSET(ifa->ifa_ifp->if_flags, IFF_UP)) { - *insrc = &satosin(ip4_source)->sin_addr; + *insrc = satosin(ip4_source)->sin_addr; return (0); } } @@ -969,7 +976,7 @@ in_pcbselsrc(struct in_addr **insrc, str if (ia == NULL) return (EADDRNOTAVAIL); - *insrc = &ia->ia_addr.sin_addr; + *insrc = ia->ia_addr.sin_addr; return (0); } Index: sys/netinet/in_pcb.h =================================================================== RCS file: /cvs/src/sys/netinet/in_pcb.h,v retrieving revision 1.125 diff -u -p -r1.125 in_pcb.h --- sys/netinet/in_pcb.h 14 Mar 2022 22:38:43 -0000 1.125 +++ sys/netinet/in_pcb.h 20 Mar 2022 23:09:33 -0000 @@ -305,7 +305,7 @@ void in_setpeeraddr(struct inpcb *, str void in_setsockaddr(struct inpcb *, struct mbuf *); int in_baddynamic(u_int16_t, u_int16_t); int in_rootonly(u_int16_t, u_int16_t); -int in_pcbselsrc(struct in_addr **, struct sockaddr_in *, struct inpcb *); +int in_pcbselsrc(struct in_addr *, struct sockaddr_in *, struct inpcb *); struct rtentry * in_pcbrtentry(struct inpcb *); Index: sys/netinet/udp_usrreq.c =================================================================== RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v retrieving revision 1.274 diff -u -p -r1.274 udp_usrreq.c --- sys/netinet/udp_usrreq.c 14 Mar 2022 22:38:43 -0000 1.274 +++ sys/netinet/udp_usrreq.c 20 Mar 2022 23:09:33 -0000 @@ -857,7 +857,7 @@ udp_output(struct inpcb *inp, struct mbu u_int32_t ipsecflowinfo = 0; struct sockaddr_in src_sin; int len = m->m_pkthdr.len; - struct in_addr *laddr; + struct in_addr laddr; int error = 0; #ifdef DIAGNOSTIC @@ -957,14 +957,14 @@ udp_output(struct inpcb *inp, struct mbu (error = in_pcbaddrisavail(inp, &src_sin, 0, curproc))) goto release; - laddr = &src_sin.sin_addr; + laddr = src_sin.sin_addr; } } else { if (inp->inp_faddr.s_addr == INADDR_ANY) { error = ENOTCONN; goto release; } - laddr = &inp->inp_laddr; + laddr = inp->inp_laddr; } /* @@ -985,7 +985,7 @@ udp_output(struct inpcb *inp, struct mbu bzero(ui->ui_x1, sizeof ui->ui_x1); ui->ui_pr = IPPROTO_UDP; ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr)); - ui->ui_src = *laddr; + ui->ui_src = laddr; ui->ui_dst = sin ? sin->sin_addr : inp->inp_faddr; ui->ui_sport = inp->inp_lport; ui->ui_dport = sin ? sin->sin_port : inp->inp_fport; Index: sbin/dhcpleased/Makefile =================================================================== RCS file: /cvs/src/sbin/dhcpleased/Makefile,v retrieving revision 1.2 diff -u -p -r1.2 Makefile --- sbin/dhcpleased/Makefile 26 Jul 2021 09:26:36 -0000 1.2 +++ sbin/dhcpleased/Makefile 20 Mar 2022 23:09:33 -0000 @@ -1,7 +1,7 @@ # $OpenBSD: Makefile,v 1.2 2021/07/26 09:26:36 florian Exp $ PROG= dhcpleased -SRCS= bpf.c checksum.c control.c dhcpleased.c engine.c frontend.c log.c +SRCS= checksum.c control.c dhcpleased.c engine.c frontend.c log.c SRCS+= parse.y printconf.c MAN= dhcpleased.8 dhcpleased.conf.5 Index: sbin/dhcpleased/dhcpleased.c =================================================================== RCS file: /cvs/src/sbin/dhcpleased/dhcpleased.c,v retrieving revision 1.23 diff -u -p -r1.23 dhcpleased.c --- sbin/dhcpleased/dhcpleased.c 4 Jan 2022 06:20:37 -0000 1.23 +++ sbin/dhcpleased/dhcpleased.c 20 Mar 2022 23:09:33 -0000 @@ -51,7 +51,6 @@ #include #include -#include "bpf.h" #include "log.h" #include "dhcpleased.h" #include "frontend.h" @@ -81,6 +80,7 @@ void configure_routes(uint8_t, struct i void configure_route(uint8_t, uint32_t, int, struct sockaddr_in *, struct sockaddr_in *, struct sockaddr_in *, struct sockaddr_in *, int); void read_lease_file(struct imsg_ifinfo *); +int setsockoptint(int, int, int, int); static int main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *); int main_imsg_compose_frontend(int, int, void *, uint16_t); @@ -97,7 +97,8 @@ static struct imsgev *iev_engine; #ifndef SMALL struct dhcpleased_conf *main_conf; #endif -char *conffile; +const char default_conffile[] = _PATH_CONF_FILE; +const char *conffile = default_conffile; pid_t frontend_pid; pid_t engine_pid; @@ -308,15 +309,8 @@ main(int argc, char *argv[]) warnx("control socket setup failed"); #endif /* SMALL */ - if (conffile != NULL) { - if (unveil(conffile, "r") == -1) - fatal("unveil %s", conffile); - } else { - if (unveil(_PATH_CONF_FILE, "r") == -1) - fatal("unveil %s", _PATH_CONF_FILE); - } - if (unveil("/dev/bpf", "rw") == -1) - fatal("unveil /dev/bpf"); + if (unveil(conffile, "r") == -1) + fatal("unveil %s", conffile); if (unveil(_PATH_LEASE, "rwc") == -1) { no_lease_files = 1; @@ -326,7 +320,7 @@ main(int argc, char *argv[]) if (unveil(NULL, NULL) == -1) fatal("unveil"); #if notyet - if (pledge("stdio inet rpath wpath sendfd wroute bpf", NULL) == -1) + if (pledge("stdio inet rpath wpath sendfd wroute", NULL) == -1) fatal("pledge"); #endif main_imsg_compose_frontend(IMSG_ROUTESOCK, frontend_routesock, NULL, 0); @@ -1121,10 +1115,33 @@ sin_to_str(struct sockaddr_in *sin) } #endif /* SMALL */ +int +setsockoptint(int s, int level, int optname, int opt) +{ + return (setsockopt(s, level, optname, &opt, sizeof(opt))); +} + void open_bpfsock(uint32_t if_index) { - int bpfsock; + int s; + struct sockaddr_in csin = { + .sin_family = AF_INET, + .sin_addr = { htonl(INADDR_ANY) }, + .sin_port = htons(CLIENT_PORT), + }; +#if 0 + struct sockaddr_in ssin = { + .sin_family = AF_INET, + .sin_addr = { htonl(INADDR_BROADCAST) }, + .sin_port = htons(SERVER_PORT), + }; +#endif + struct ip_mreqn mreqn = { + .imr_ifindex = if_index, + }; + +#if 0 char ifname[IF_NAMESIZE]; if (if_indextoname(if_index, ifname) == NULL) { @@ -1134,9 +1151,67 @@ open_bpfsock(uint32_t if_index) if ((bpfsock = get_bpf_sock(ifname)) == -1) return; +#endif + + s = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); + if (s == -1) { + log_warn("bcast socket"); + return; + } + + if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, + &mreqn, sizeof(mreqn)) == -1) { + log_warn("bcast multicast interface %d", mreqn.imr_ifindex); + goto nope; + } + + if (setsockoptint(s, SOL_SOCKET, SO_REUSEADDR, 1) == -1) { + log_warn("bcast enable SO_REUSEADDR"); + goto nope; + } - main_imsg_compose_frontend(IMSG_BPFSOCK, bpfsock, &if_index, + if (setsockoptint(s, IPPROTO_IP, IP_RECVIF, 1) == -1) { + log_warn("bcast enable recvif message"); + goto nope; + } + + if (setsockoptint(s, IPPROTO_IP, IP_RECVDSTADDR, 1) == -1) { + log_warn("bcast enable recv destination address"); + goto nope; + } + + if (setsockoptint(s, IPPROTO_IP, IP_RECVDSTPORT, 1) == -1) { + log_warn("bcast enable recv destination port"); + goto nope; + } + + if (bind(s, (struct sockaddr *)&csin, sizeof(csin)) == -1) { + log_warn("bcast bind"); + goto nope; + } + + { + u_char loop = 0; + if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, + &loop, sizeof(loop)) == -1) { + log_warn("bcast disable multicast loopback"); + goto nope; + } + } + +#if 0 + if (connect(s, (struct sockaddr *)&ssin, sizeof(ssin)) == -1) { + log_warn("bcast connect"); + goto nope; + } +#endif + + main_imsg_compose_frontend(IMSG_BPFSOCK, s, &if_index, sizeof(if_index)); + return; + +nope: + close(s); } void Index: sbin/dhcpleased/dhcpleased.h =================================================================== RCS file: /cvs/src/sbin/dhcpleased/dhcpleased.h,v retrieving revision 1.13 diff -u -p -r1.13 dhcpleased.h --- sbin/dhcpleased/dhcpleased.h 4 Jan 2022 06:20:37 -0000 1.13 +++ sbin/dhcpleased/dhcpleased.h 20 Mar 2022 23:09:33 -0000 @@ -285,7 +285,8 @@ struct imsg_propose_rdns { struct imsg_dhcp { uint32_t if_index; ssize_t len; - uint8_t ether_align[2]; + struct sockaddr_in src; + struct sockaddr_in dst; uint8_t packet[1500]; }; @@ -318,7 +319,7 @@ int *changed_ifaces(struct dhcpleased_ void print_config(struct dhcpleased_conf *); /* parse.y */ -struct dhcpleased_conf *parse_config(char *); +struct dhcpleased_conf *parse_config(const char *); int cmdline_symset(char *); #else #define sin_to_str(x...) "" Index: sbin/dhcpleased/engine.c =================================================================== RCS file: /cvs/src/sbin/dhcpleased/engine.c,v retrieving revision 1.36 diff -u -p -r1.36 engine.c --- sbin/dhcpleased/engine.c 16 Feb 2022 10:35:57 -0000 1.36 +++ sbin/dhcpleased/engine.c 20 Mar 2022 23:09:33 -0000 @@ -712,26 +712,19 @@ void parse_dhcp(struct dhcpleased_iface *iface, struct imsg_dhcp *dhcp) { static uint8_t cookie[] = DHCP_COOKIE; - static struct ether_addr bcast_mac; #ifndef SMALL struct iface_conf *iface_conf; #endif /* SMALL */ - struct ether_header *eh; - struct ether_addr ether_src, ether_dst; - struct ip *ip; - struct udphdr *udp; struct dhcp_hdr *dhcp_hdr; struct in_addr server_identifier, subnet_mask; struct in_addr nameservers[MAX_RDNS_COUNT]; struct dhcp_route routes[MAX_DHCP_ROUTES]; size_t rem, i; - uint32_t sum, usum, lease_time = 0, renewal_time = 0; + uint32_t lease_time = 0, renewal_time = 0; uint32_t rebinding_time = 0; uint8_t *p, dho = DHO_PAD, dho_len, slen; uint8_t dhcp_message_type = 0; int routes_len = 0, routers = 0, csr = 0; - char from[sizeof("xx:xx:xx:xx:xx:xx")]; - char to[sizeof("xx:xx:xx:xx:xx:xx")]; char hbuf_src[INET_ADDRSTRLEN]; char hbuf_dst[INET_ADDRSTRLEN]; char hbuf[INET_ADDRSTRLEN]; @@ -739,9 +732,6 @@ parse_dhcp(struct dhcpleased_iface *ifac char hostname[4 * 255 + 1]; char ifnamebuf[IF_NAMESIZE], *if_name; - if (bcast_mac.ether_addr_octet[0] == 0) - memset(bcast_mac.ether_addr_octet, 0xff, ETHER_ADDR_LEN); - if_name = if_indextoname(iface->if_index, ifnamebuf); #ifndef SMALL @@ -754,55 +744,19 @@ parse_dhcp(struct dhcpleased_iface *ifac p = dhcp->packet; rem = dhcp->len; - if (rem < sizeof(*eh)) { - log_warnx("%s: message too short", __func__); - return; - } - eh = (struct ether_header *)p; - memcpy(ether_src.ether_addr_octet, eh->ether_shost, - sizeof(ether_src.ether_addr_octet)); - strlcpy(from, ether_ntoa(ðer_src), sizeof(from)); - memcpy(ether_dst.ether_addr_octet, eh->ether_dhost, - sizeof(ether_dst.ether_addr_octet)); - strlcpy(to, ether_ntoa(ðer_dst), sizeof(to)); - p += sizeof(*eh); - rem -= sizeof(*eh); - - if (memcmp(ðer_dst, &iface->hw_address, sizeof(ether_dst)) != 0 && - memcmp(ðer_dst, &bcast_mac, sizeof(ether_dst)) != 0) - return ; /* silently ignore packet not for us */ - - if (rem < sizeof(*ip)) - goto too_short; - - if (log_getverbose() > 1) - log_debug("%s, from: %s, to: %s", __func__, from, to); - - ip = (struct ip *)p; - - if (rem < (size_t)ip->ip_hl << 2) - goto too_short; - - if (wrapsum(checksum((uint8_t *)ip, ip->ip_hl << 2, 0)) != 0) { - log_warnx("%s: bad IP checksum", __func__); - return; - } - if (rem < ntohs(ip->ip_len)) - goto too_short; - - p += ip->ip_hl << 2; - rem -= ip->ip_hl << 2; - - if (inet_ntop(AF_INET, &ip->ip_src, hbuf_src, sizeof(hbuf_src)) == NULL) + if (inet_ntop(AF_INET, &dhcp->src.sin_addr, + hbuf_src, sizeof(hbuf_src)) == NULL) hbuf_src[0] = '\0'; - if (inet_ntop(AF_INET, &ip->ip_dst, hbuf_dst, sizeof(hbuf_dst)) == NULL) + if (inet_ntop(AF_INET, &dhcp->dst.sin_addr, + hbuf_dst, sizeof(hbuf_dst)) == NULL) hbuf_dst[0] = '\0'; #ifndef SMALL if (iface_conf != NULL) { for (i = 0; (int)i < iface_conf->ignore_servers_len; i++) { if (iface_conf->ignore_servers[i].s_addr == - ip->ip_src.s_addr) { + dhcp->src.sin_addr.s_addr) { +/* XXX check siaddr too? */ log_debug("ignoring server %s", hbuf_src); return; } @@ -810,40 +764,10 @@ parse_dhcp(struct dhcpleased_iface *ifac } #endif /* SMALL */ - if (rem < sizeof(*udp)) - goto too_short; - - udp = (struct udphdr *)p; - if (rem < ntohs(udp->uh_ulen)) - goto too_short; - - if (rem > ntohs(udp->uh_ulen)) { - if (log_getverbose() > 1) { - log_debug("%s: accepting packet with %lu bytes of data" - " after udp payload", __func__, rem - - ntohs(udp->uh_ulen)); - } - rem = ntohs(udp->uh_ulen); - } - - p += sizeof(*udp); - rem -= sizeof(*udp); - - usum = udp->uh_sum; - udp->uh_sum = 0; - - sum = wrapsum(checksum((uint8_t *)udp, sizeof(*udp), checksum(p, rem, - checksum((uint8_t *)&ip->ip_src, 2 * sizeof(ip->ip_src), - IPPROTO_UDP + ntohs(udp->uh_ulen))))); - - if (usum != 0 && usum != sum) { - log_warnx("%s: bad UDP checksum", __func__); - return; - } - if (log_getverbose() > 1) { - log_debug("%s: %s:%d -> %s:%d", __func__, hbuf_src, - ntohs(udp->uh_sport), hbuf_dst, ntohs(udp->uh_dport)); + log_debug("%s: %s:%d -> %s:%d", __func__, + hbuf_src, ntohs(dhcp->src.sin_port), + hbuf_dst, ntohs(dhcp->dst.sin_port)); } if (rem < sizeof(*dhcp_hdr)) @@ -860,7 +784,8 @@ parse_dhcp(struct dhcpleased_iface *ifac log_dhcp_hdr(dhcp_hdr); if (dhcp_hdr->op != DHCP_BOOTREPLY) { - log_warnx("%s: ignorning non-reply packet", __func__); + log_warnx("%s: ignorning non-reply packet %u %u", __func__, + dhcp_hdr->op, DHCP_BOOTREPLY); return; } @@ -872,7 +797,7 @@ parse_dhcp(struct dhcpleased_iface *ifac if (memcmp(p, cookie, sizeof(cookie)) != 0) { log_warnx("%s: no dhcp cookie in packet from %s", __func__, - from); + hbuf_src); return; } p += sizeof(cookie); @@ -1179,11 +1104,11 @@ parse_dhcp(struct dhcpleased_iface *ifac } if (rem != 0) log_warnx("%s: %lu bytes garbage data from %s", __func__, rem, - from); + hbuf_src); - log_debug("%s on %s from %s/%s to %s/%s", + log_debug("%s on %s from %s to %s", dhcp_message_type2str(dhcp_message_type), if_name == NULL ? "?" : - if_name, from, hbuf_src, to, hbuf_dst); + if_name, hbuf_src, hbuf_dst); switch (dhcp_message_type) { case DHCPOFFER: @@ -1220,12 +1145,13 @@ parse_dhcp(struct dhcpleased_iface *ifac return; } if (lease_time == 0) { - log_warnx("%s no lease time from %s", __func__, from); + log_warnx("%s no lease time from %s", __func__, + hbuf_src); return; } if (subnet_mask.s_addr == INADDR_ANY) { log_warnx("%s: no subnetmask received from %s", - __func__, from); + __func__, hbuf_src); return; } @@ -1240,12 +1166,12 @@ parse_dhcp(struct dhcpleased_iface *ifac if (renewal_time >= rebinding_time) { log_warnx("%s: renewal_time(%u) >= rebinding_time(%u) " "from %s: using defaults", - __func__, renewal_time, rebinding_time, from); + __func__, renewal_time, rebinding_time, hbuf_src); renewal_time = rebinding_time = 0; } else if (rebinding_time >= lease_time) { log_warnx("%s: rebinding_time(%u) >= lease_time(%u) " "from %s: using defaults", - __func__, rebinding_time, lease_time, from); + __func__, rebinding_time, lease_time, hbuf_src); renewal_time = rebinding_time = 0; } @@ -1320,7 +1246,7 @@ parse_dhcp(struct dhcpleased_iface *ifac } return; too_short: - log_warnx("%s: message from %s too short", __func__, from); + log_warnx("%s: message from %s too short", __func__, hbuf_src); return; wrong_length: log_warnx("%s: received option %d with wrong length: %d", __func__, Index: sbin/dhcpleased/frontend.c =================================================================== RCS file: /cvs/src/sbin/dhcpleased/frontend.c,v retrieving revision 1.28 diff -u -p -r1.28 frontend.c --- sbin/dhcpleased/frontend.c 4 Jan 2022 06:20:37 -0000 1.28 +++ sbin/dhcpleased/frontend.c 20 Mar 2022 23:09:33 -0000 @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -49,7 +48,6 @@ #include #include -#include "bpf.h" #include "log.h" #include "dhcpleased.h" #include "frontend.h" @@ -61,7 +59,7 @@ struct bpf_ev { struct event ev; - uint8_t buf[BPFLEN]; + uint8_t buf[2048]; /* XXX */ }; struct iface { @@ -849,54 +847,80 @@ get_rtaddrs(int addrs, struct sockaddr * void bpf_receive(int fd, short events, void *arg) { - struct bpf_hdr *hdr; struct imsg_dhcp imsg_dhcp; - struct iface *iface; - ssize_t len, rem; - uint8_t *p; - iface = (struct iface *)arg; + struct iface *iface = arg; + struct bpf_ev *bpfev = &iface->bpfev; - if ((len = read(fd, iface->bpfev.buf, BPFLEN)) == -1) { - log_warn("%s: read", __func__); - return; - } + struct iovec iov = { + .iov_base = imsg_dhcp.packet, + .iov_len = sizeof(imsg_dhcp.packet), + }; + struct sockaddr_dl *sdl = NULL; + union { + struct cmsghdr hdr; + char buf[CMSG_SPACE(sizeof(*sdl)) + + CMSG_SPACE(sizeof(struct in_addr)) + + CMSG_SPACE(sizeof(in_port_t))]; + } cmsgbuf; + struct msghdr msg = { + .msg_name = &imsg_dhcp.src, + .msg_namelen = sizeof(imsg_dhcp.src), + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = &cmsgbuf.buf, + .msg_controllen = sizeof(cmsgbuf.buf), + }; - if (len == 0) - fatal("%s len == 0", __func__); + struct cmsghdr *cmsg; + ssize_t len; memset(&imsg_dhcp, 0, sizeof(imsg_dhcp)); - imsg_dhcp.if_index = iface->ifinfo.if_index; - - rem = len; - p = iface->bpfev.buf; - while (rem > 0) { - if ((size_t)rem < sizeof(*hdr)) { - log_warnx("packet too short"); - return; - } - hdr = (struct bpf_hdr *)p; - if (hdr->bh_caplen != hdr->bh_datalen) { - log_warnx("skipping truncated packet"); - goto cont; + if ((len = recvmsg(fd, &msg, 0)) == -1) { + if (errno != EAGAIN && errno != EINTR) { + log_debug("%s: read error: %s", __func__, + strerror(errno)); } - if (rem < hdr->bh_hdrlen + hdr->bh_caplen) - /* we are done */ + return; + } + + imsg_dhcp.dst.sin_family = AF_INET; + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level != IPPROTO_IP) + continue; + + switch (cmsg->cmsg_type) { + case IP_RECVIF: + sdl = (struct sockaddr_dl *)CMSG_DATA(cmsg); + break; + case IP_RECVDSTADDR: + imsg_dhcp.dst.sin_addr = + *(struct in_addr *)CMSG_DATA(cmsg); + break; + case IP_RECVDSTPORT: + imsg_dhcp.dst.sin_port = *(in_port_t *)CMSG_DATA(cmsg); break; - if (hdr->bh_caplen > sizeof(imsg_dhcp.packet)) { - log_warn("packet too big"); - goto cont; } - memcpy(&imsg_dhcp.packet, p + hdr->bh_hdrlen, hdr->bh_caplen); - imsg_dhcp.len = hdr->bh_caplen; - frontend_imsg_compose_engine(IMSG_DHCP, 0, 0, &imsg_dhcp, - sizeof(imsg_dhcp)); - cont: - p += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); - rem -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); - } + if (sdl == NULL) { + log_debug("%s: message received without interface index", + __func__); + return; + } + if (sdl->sdl_index != iface->ifinfo.if_index) + return; + + imsg_dhcp.if_index = sdl->sdl_index; + + /* XXX could just recv it into the imsg */ + //memcpy(imsg_dhcp.packet, bpfev->buf, len); + imsg_dhcp.len = len; + + frontend_imsg_compose_engine(IMSG_DHCP, 0, 0, &imsg_dhcp, + sizeof(imsg_dhcp)); } void @@ -950,6 +974,7 @@ build_packet(uint8_t message_type, char hdr->hops = 0; hdr->xid = htonl(xid); hdr->secs = 0; + hdr->flags = htons(0x8000); hdr->ciaddr = *ciaddr; memcpy(hdr->chaddr, hw_address, sizeof(*hw_address)); p += sizeof(struct dhcp_hdr); @@ -1084,64 +1109,19 @@ udp_send_packet(struct iface *iface, uin void bpf_send_packet(struct iface *iface, uint8_t *packet, ssize_t len) { - struct iovec iov[4]; - struct ether_header eh; - struct ip ip; - struct udphdr udp; - ssize_t total, result; - int iovcnt = 0, i; - - memset(eh.ether_dhost, 0xff, sizeof(eh.ether_dhost)); - memcpy(eh.ether_shost, &iface->ifinfo.hw_address, - sizeof(eh.ether_dhost)); - eh.ether_type = htons(ETHERTYPE_IP); - iov[0].iov_base = &eh; - iov[0].iov_len = sizeof(eh); - iovcnt++; - - ip.ip_v = 4; - ip.ip_hl = 5; - ip.ip_tos = IPTOS_LOWDELAY; - ip.ip_len = htons(sizeof(ip) + sizeof(udp) + len); - ip.ip_id = 0; - ip.ip_off = 0; - ip.ip_ttl = 128; - ip.ip_p = IPPROTO_UDP; - ip.ip_sum = 0; - ip.ip_src.s_addr = INADDR_ANY; - ip.ip_dst.s_addr = INADDR_BROADCAST; - ip.ip_sum = wrapsum(checksum((unsigned char *)&ip, sizeof(ip), 0)); - iov[iovcnt].iov_base = &ip; - iov[iovcnt].iov_len = sizeof(ip); - iovcnt++; - - udp.uh_sport = htons(CLIENT_PORT); - udp.uh_dport = htons(SERVER_PORT); - udp.uh_ulen = htons(sizeof(udp) + len); - udp.uh_sum = 0; - udp.uh_sum = wrapsum(checksum((unsigned char *)&udp, sizeof(udp), - checksum((unsigned char *)packet, len, - checksum((unsigned char *)&ip.ip_src, - 2 * sizeof(ip.ip_src), - IPPROTO_UDP + (uint32_t)ntohs(udp.uh_ulen))))); - iov[iovcnt].iov_base = &udp; - iov[iovcnt].iov_len = sizeof(udp); - iovcnt++; - - iov[iovcnt].iov_base = packet; - iov[iovcnt].iov_len = len; - iovcnt++; - - total = 0; - for (i = 0; i < iovcnt; i++) - total += iov[i].iov_len; + struct sockaddr_in sin = { + .sin_family = AF_INET, + .sin_addr = { htonl(INADDR_BROADCAST) }, + .sin_port = htons(SERVER_PORT), + }; + ssize_t result; - result = writev(EVENT_FD(&iface->bpfev.ev), iov, iovcnt); + result = sendto(EVENT_FD(&iface->bpfev.ev), packet, len, 0, + (struct sockaddr *)&sin, sizeof(sin)); if (result == -1) log_warn("%s: writev", __func__); - else if (result < total) { - log_warnx("%s, writev: %zd of %zd bytes", __func__, result, - total); + else if (result < len) { + log_warnx("%s, send %zd of %zd bytes", __func__, result, len); } } Index: sbin/dhcpleased/parse.y =================================================================== RCS file: /cvs/src/sbin/dhcpleased/parse.y,v retrieving revision 1.6 diff -u -p -r1.6 parse.y --- sbin/dhcpleased/parse.y 4 Jan 2022 06:20:37 -0000 1.6 +++ sbin/dhcpleased/parse.y 20 Mar 2022 23:09:33 -0000 @@ -720,16 +720,17 @@ popfile(void) } struct dhcpleased_conf * -parse_config(char *filename) +parse_config(const char *filename) { + extern const char default_conffile[]; struct sym *sym, *next; conf = config_new_empty(); - file = pushfile(filename != NULL ? filename : _PATH_CONF_FILE, 0); + file = pushfile(filename, 0); if (file == NULL) { /* no default config file is fine */ - if (errno == ENOENT && filename == NULL) + if (errno == ENOENT && filename == default_conffile) return (conf); log_warn("%s", filename); free(conf);