From owner-freebsd-bugs@FreeBSD.ORG Mon Nov 8 07:00:18 2010 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 687E31065672 for ; Mon, 8 Nov 2010 07:00:18 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 1C5168FC1F for ; Mon, 8 Nov 2010 07:00:18 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id oA870H53099978 for ; Mon, 8 Nov 2010 07:00:17 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id oA870HW1099968; Mon, 8 Nov 2010 07:00:17 GMT (envelope-from gnats) Resent-Date: Mon, 8 Nov 2010 07:00:17 GMT Resent-Message-Id: <201011080700.oA870HW1099968@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Kelly Yancey Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6A3F8106566C for ; Mon, 8 Nov 2010 06:50:31 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 587A28FC16 for ; Mon, 8 Nov 2010 06:50:31 +0000 (UTC) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id oA86oVch089521 for ; Mon, 8 Nov 2010 06:50:31 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id oA86oVQL089520; Mon, 8 Nov 2010 06:50:31 GMT (envelope-from nobody) Message-Id: <201011080650.oA86oVQL089520@www.freebsd.org> Date: Mon, 8 Nov 2010 06:50:31 GMT From: Kelly Yancey To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/152036: getifaddrs(3) returns truncated sockaddrs for netmasks X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 08 Nov 2010 07:00:18 -0000 >Number: 152036 >Category: kern >Synopsis: getifaddrs(3) returns truncated sockaddrs for netmasks >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Nov 08 07:00:17 UTC 2010 >Closed-Date: >Last-Modified: >Originator: Kelly Yancey >Release: 6.4, 8.1 >Organization: >Environment: FreeBSD gateway.posi.net 6.4-STABLE FreeBSD 6.4-STABLE #0: Thu Jan 7 13:48:25 JST 2010 root@gateway.posi.net:/usr/obj/usr/src/sys/GATEWAY i386 -- AND -- FreeBSD gateway.posi.net 8.1-RELEASE FreeBSD 8.1-RELEASE #0: Mon Jul 19 02:55:53 UTC 2010 root@almeida.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386 >Description: The getifaddrs(3) function returns a pointer to a sockaddr for each of the interface's address, netmask, broadcast address, and destination address (for peer-to-peer links). However, the sockaddr for IPv4 netmasks is frequently truncated to less than a full sockaddr_in. In fact, it is typically truncated in the middle of the sin_addr field. The sockaddr_in structures appear to be truncated to the minimum number of bytes necessary to hold the netmask. For example, if the netmask was 255.255.254.0, then the sockaddr is truncated to just 7 bytes, with the sin_addr field consisting of just 3 bytes: 0xff, 0xff, 0xfe. In other words, the sockaddr_in structure isn't just truncated for IPv4 netmasks, it is truncated in the middle of a primitive type (in this case, an uint32_t). >How-To-Repeat: Attached is a simple program that fetches and prints all of the interface addresses using the getifaddrs(3) API. You will notice that the netmasks associated with the IPv4 addresses are all truncated to less than a full sockaddr_in. >Fix: Patch attached with submission follows: /* * * */ #include #include #include #include #include #include #include #include #include static void print_addr(const struct sockaddr *sa); void print_addr(const struct sockaddr *sa) { char buffer[100]; const struct sockaddr_in *sin; const struct sockaddr_in6 *sin6; const struct sockaddr_dl *sdl; int i; if (sa == NULL) { printf("NULL"); return; } printf("(family: %d, len:%d", sa->sa_family, sa->sa_len); #define SIZECHECK(type) \ if (sa->sa_len < sizeof(type)) { \ printf(", TRUNCATED -- should be %zu bytes", sizeof(type)); \ break; \ } switch (sa->sa_family) { case AF_INET: SIZECHECK(struct sockaddr_in) sin = (const struct sockaddr_in *)sa; inet_ntop(AF_INET, &sin->sin_addr, buffer, sizeof(buffer)); printf("addr:%s", buffer); break; case AF_INET6: SIZECHECK(struct sockaddr_in6) sin6 = (const struct sockaddr_in6 *)sa; inet_ntop(AF_INET6, &sin6->sin6_addr, buffer, sizeof(buffer)); printf(", addr:%s", buffer); break; case AF_LINK: SIZECHECK(struct sockaddr_dl) sdl = (const struct sockaddr_dl *)sa; printf(", addr:%s", buffer); /* * Could use link_ntoa() but its output format is a little * unusual so print the address manually. */ for (i = 0; i < sdl->sdl_alen; i++) { if (i > 0) printf(":"); printf("%02x", sdl->sdl_data[sdl->sdl_nlen + i]); } break; default: /* nothing */ break; } #undef SIZECHECK printf(")"); } int main(int ac __unused, char **av __unused) { struct ifaddrs *addrlist, *addr; getifaddrs(&addrlist); for (addr = addrlist; addr != NULL; addr = addr->ifa_next) { printf("%s:\n", addr->ifa_name); printf("\tifa_addr = "); print_addr(addr->ifa_addr); printf("\n"); printf("\tifa_netmask = "); print_addr(addr->ifa_netmask); printf("\n"); printf("\tdstaddr = "); print_addr(addr->ifa_dstaddr); printf("\n\n"); } freeifaddrs(addrlist); return 0; } >Release-Note: >Audit-Trail: >Unformatted: