From owner-svn-src-stable-8@FreeBSD.ORG Fri Oct 23 14:43:17 2009 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 891FC106566B; Fri, 23 Oct 2009 14:43:17 +0000 (UTC) (envelope-from philip@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 768A68FC15; Fri, 23 Oct 2009 14:43:17 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n9NEhHh9064002; Fri, 23 Oct 2009 14:43:17 GMT (envelope-from philip@svn.freebsd.org) Received: (from philip@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n9NEhHw6063998; Fri, 23 Oct 2009 14:43:17 GMT (envelope-from philip@svn.freebsd.org) Message-Id: <200910231443.n9NEhHw6063998@svn.freebsd.org> From: Philip Paeps Date: Fri, 23 Oct 2009 14:43:17 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r198405 - stable/8/sbin/dhclient X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Oct 2009 14:43:17 -0000 Author: philip Date: Fri Oct 23 14:43:17 2009 New Revision: 198405 URL: http://svn.freebsd.org/changeset/base/198405 Log: MFC r198352 Make dhclient use bootpc (68) as the source port for unicast DHCPREQUEST packets instead of allowing the protocol stack to pick a random source port. This fixes the behaviour where dhclient would never transition from RENEWING to BOUND without going through REBINDING in networks which are paranoid about DHCP spoofing, such as most mainstream cable-broadband ISP networks. Obtained from: OpenBSD Reviewed by: brooks Approved by: re (kib) Modified: stable/8/sbin/dhclient/ (props changed) stable/8/sbin/dhclient/bpf.c stable/8/sbin/dhclient/dhcpd.h stable/8/sbin/dhclient/packet.c Modified: stable/8/sbin/dhclient/bpf.c ============================================================================== --- stable/8/sbin/dhclient/bpf.c Fri Oct 23 14:40:38 2009 (r198404) +++ stable/8/sbin/dhclient/bpf.c Fri Oct 23 14:43:17 2009 (r198405) @@ -90,11 +90,23 @@ if_register_bpf(struct interface_info *i void if_register_send(struct interface_info *info) { + int sock, on = 1; + /* * If we're using the bpf API for sending and receiving, we * don't need to register this interface twice. */ info->wfdesc = info->rfdesc; + + /* + * Use raw socket for unicast send. + */ + if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) + error("socket(SOCK_RAW): %m"); + if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, + sizeof(on)) == -1) + error("setsockopt(IP_HDRINCL): %m"); + info->ufdesc = sock; } /* @@ -244,35 +256,32 @@ send_packet(struct interface_info *inter { unsigned char buf[256]; struct iovec iov[2]; + struct msghdr msg; int result, bufp = 0; - int sock; - - if (to->sin_addr.s_addr != INADDR_BROADCAST) { - note("SENDING DIRECT"); - /* We know who the server is, send the packet via - normal socket interface */ - - if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0) { - result = sendto (sock, (char *)raw, len, 0, - (struct sockaddr *)to, sizeof *to); - close(sock); - if (result > 0) - return result; - } - } /* Assemble the headers... */ - assemble_hw_header(interface, buf, &bufp, hto); + if (to->sin_addr.s_addr == INADDR_BROADCAST) + assemble_hw_header(interface, buf, &bufp, hto); assemble_udp_ip_header(buf, &bufp, from.s_addr, to->sin_addr.s_addr, to->sin_port, (unsigned char *)raw, len); - /* Fire it off */ iov[0].iov_base = (char *)buf; iov[0].iov_len = bufp; iov[1].iov_base = (char *)raw; iov[1].iov_len = len; - result = writev(interface->wfdesc, iov, 2); + /* Fire it off */ + if (to->sin_addr.s_addr == INADDR_BROADCAST) + result = writev(interface->wfdesc, iov, 2); + else { + memset(&msg, 0, sizeof(msg)); + msg.msg_name = (struct sockaddr *)to; + msg.msg_namelen = sizeof(*to); + msg.msg_iov = iov; + msg.msg_iovlen = 2; + result = sendmsg(interface->ufdesc, &msg, 0); + } + if (result < 0) warning("send_packet: %m"); return (result); Modified: stable/8/sbin/dhclient/dhcpd.h ============================================================================== --- stable/8/sbin/dhclient/dhcpd.h Fri Oct 23 14:40:38 2009 (r198404) +++ stable/8/sbin/dhclient/dhcpd.h Fri Oct 23 14:43:17 2009 (r198405) @@ -37,6 +37,8 @@ * Enterprises. To learn more about the Internet Software Consortium, * see ``http://www.vix.com/isc''. To learn more about Vixie * Enterprises, see ``http://www.vix.com''. + * + * $FreeBSD$ */ #include @@ -194,6 +196,7 @@ struct interface_info { char name[IFNAMSIZ]; int rfdesc; int wfdesc; + int ufdesc; unsigned char *rbuf; size_t rbuf_max; size_t rbuf_offset; Modified: stable/8/sbin/dhclient/packet.c ============================================================================== --- stable/8/sbin/dhclient/packet.c Fri Oct 23 14:40:38 2009 (r198404) +++ stable/8/sbin/dhclient/packet.c Fri Oct 23 14:43:17 2009 (r198405) @@ -135,6 +135,17 @@ assemble_udp_ip_header(unsigned char *bu ip.ip_dst.s_addr = to; ip.ip_sum = wrapsum(checksum((unsigned char *)&ip, sizeof(ip), 0)); + + /* + * While the BPF -- used for broadcasts -- expects a "true" IP header + * with all the bytes in network byte order, the raw socket interface + * which is used for unicasts expects the ip_len field to be in host + * byte order. In both cases, the checksum has to be correct, so this + * is as good a place as any to turn the bytes around again. + */ + if (to != INADDR_BROADCAST) + ip.ip_len = ntohs(ip.ip_len); + memcpy(&buf[*bufix], &ip, sizeof(ip)); *bufix += sizeof(ip);