void dhcp_init(void) { #if defined(HAVE_BSD_NETWORK) int oneopt = 1; #endif daemon->dhcpfd = make_fd(daemon->dhcp_server_port); if (daemon->enable_pxe) daemon->pxefd = make_fd(PXE_PORT); else daemon->pxefd = -1; #if defined(HAVE_BSD_NETWORK) /* When we're not using capabilities, we need to do this here before we drop root. Also, set buffer size small, to avoid wasting kernel buffers */ if (option_bool(OPT_NO_PING)) daemon->dhcp_icmp_fd = -1; else if ((daemon->dhcp_icmp_fd = make_icmp_sock()) == -1 || setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) == -1 ) die(_("cannot create ICMP raw socket: %s."), NULL, EC_BADNET); /* Make BPF raw send socket */ init_bpf(); #endif }
void dhcp_init(void) { int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); struct sockaddr_in saddr; int oneopt = 1; struct dhcp_config *configs, *cp; if (fd == -1) die (_("cannot create DHCP socket : %s"), NULL, EC_BADNET); if (!fix_fd(fd) || #if defined(HAVE_LINUX_NETWORK) setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 || #elif defined(IP_RECVIF) setsockopt(fd, IPPROTO_IP, IP_RECVIF, &oneopt, sizeof(oneopt)) == -1 || #endif setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1) die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET); /* When bind-interfaces is set, there might be more than one dnmsasq instance binding port 67. That's OK if they serve different networks. Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. OpenBSD <= 4.0 screws up IP_RECVIF when SO_REUSEPORT is set, but OpenBSD <= 3.9 doesn't have IP_RECVIF anyway, so we just have to elide this for OpenBSD 4.0, if you want more than one instance on oBSD4.0, tough. */ #ifndef OpenBSD4_0 if (daemon->options & OPT_NOWILD) { #ifdef SO_REUSEPORT int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt)); #else int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt)); #endif if (rc == -1) die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET); } #endif memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons(DHCP_SERVER_PORT); saddr.sin_addr.s_addr = INADDR_ANY; #ifdef HAVE_SOCKADDR_SA_LEN saddr.sin_len = sizeof(struct sockaddr_in); #endif if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in))) die(_("failed to bind DHCP server socket: %s"), NULL, EC_BADNET); daemon->dhcpfd = fd; #ifndef HAVE_LINUX_NETWORK /* When we're not using capabilities, we need to do this here before we drop root. Also, set buffer size small, to avoid wasting kernel buffers */ if (daemon->options & OPT_NO_PING) daemon->dhcp_icmp_fd = -1; else if ((daemon->dhcp_icmp_fd = make_icmp_sock()) == -1 || setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) == -1 ) die(_("cannot create ICMP raw socket: %s."), NULL, EC_BADNET); /* Make BPF raw send socket */ init_bpf(); #endif /* If the same IP appears in more than one host config, then DISCOVER for one of the hosts will get the address, but REQUEST will be NAKed, since the address is reserved by the other one -> protocol loop. Also check that FQDNs match the domain we are using. */ for (configs = daemon->dhcp_conf; configs; configs = configs->next) { char *domain; for (cp = configs->next; cp; cp = cp->next) if ((configs->flags & cp->flags & CONFIG_ADDR) && configs->addr.s_addr == cp->addr.s_addr) die(_("duplicate IP address %s in dhcp-config directive."), inet_ntoa(cp->addr), EC_BADCONF); if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname))) die(_("illegal domain %s in dhcp-config directive."), domain, EC_BADCONF); } daemon->dhcp_packet.iov_len = sizeof(struct dhcp_packet); daemon->dhcp_packet.iov_base = safe_malloc(daemon->dhcp_packet.iov_len); }
void dhcp_init(void) { int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); struct sockaddr_in saddr; int oneopt = 1; #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) int mtu = IP_PMTUDISC_DONT; #endif if (fd == -1) die (_("cannot create DHCP socket: %s"), NULL, EC_BADNET); if (!fix_fd(fd) || #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu)) == -1 || #endif #if defined(HAVE_LINUX_NETWORK) setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 || #else setsockopt(fd, IPPROTO_IP, IP_RECVIF, &oneopt, sizeof(oneopt)) == -1 || #endif setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1) die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET); if (daemon->options & OPT_NOWILD) { #ifdef SO_REUSEPORT int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt)); #else int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt)); #endif if (rc == -1) die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET); } memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons(daemon->dhcp_server_port); saddr.sin_addr.s_addr = INADDR_ANY; #ifdef HAVE_SOCKADDR_SA_LEN saddr.sin_len = sizeof(struct sockaddr_in); #endif if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in))) die(_("failed to bind DHCP server socket: %s"), NULL, EC_BADNET); daemon->dhcpfd = fd; #if defined(HAVE_BSD_NETWORK) if (daemon->options & OPT_NO_PING) daemon->dhcp_icmp_fd = -1; else if ((daemon->dhcp_icmp_fd = make_icmp_sock()) == -1 || setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) == -1 ) die(_("cannot create ICMP raw socket: %s."), NULL, EC_BADNET); init_bpf(); #endif check_dhcp_hosts(1); daemon->dhcp_packet.iov_len = sizeof(struct dhcp_packet); daemon->dhcp_packet.iov_base = safe_malloc(daemon->dhcp_packet.iov_len); }