From owner-freebsd-hackers@FreeBSD.ORG Thu Jan 31 18:47:19 2008 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 60E1316A417 for ; Thu, 31 Jan 2008 18:47:19 +0000 (UTC) (envelope-from wundram@beenic.net) Received: from mail.beenic.net (mail.beenic.net [83.246.72.40]) by mx1.freebsd.org (Postfix) with ESMTP id F15C713C465 for ; Thu, 31 Jan 2008 18:47:18 +0000 (UTC) (envelope-from wundram@beenic.net) Received: from phoenix (hnvr-4dbbaa0f.pool.einsundeins.de [77.187.170.15]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.beenic.net (Postfix) with ESMTP id 31B1BA44529; Thu, 31 Jan 2008 19:46:57 +0100 (CET) From: "Heiko Wundram (Beenic)" Organization: Beenic Networks GmbH To: Dag-Erling =?utf-8?q?Sm=C3=B8rgrav?= Date: Thu, 31 Jan 2008 19:47:41 +0100 User-Agent: KMail/1.9.7 References: <200801310923.16029.wundram@beenic.net> <200801311701.49792.wundram@beenic.net> <86myqmvt0z.fsf@ds4.des.no> In-Reply-To: <86myqmvt0z.fsf@ds4.des.no> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Message-Id: <200801311947.42545.wundram@beenic.net> Cc: freebsd-hackers@freebsd.org Subject: Re: OT: getting the protocol family of a file descriptor X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 31 Jan 2008 18:47:19 -0000 Am Donnerstag, 31. Januar 2008 17:50:20 schrieb Dag-Erling Sm=C3=B8rgrav: > "Heiko Wundram (Beenic)" writes: > > Currently, you're basically required to do a getsockname to a struct > > sockaddr_storage and typecast that to the actual socket addres type > > based on the ss_family member (to be able to pass it to one of the > > *_ntop-functions, for example), but generally, I don't find this too > > beautiful. But, maybe, that's just my (horribly broken) taste. ;-) > > Uh, I'm pretty sure there's a function in the getaddr* family that will > give you a string representation of any struct sockaddr. Actually, I'm > absolutely sure of it: getnameinfo() with NI_NUMERICHOST|NI_NUMERICSERV > will format the numerical address for you instead of looking it up in > DNS. > > But what I really don't understand is this: you say you just want the > address family so you'll know how to format the address. If you have > the address, you already know the family. So what's the issue, really? Okay, formatting the address was just an example (and probably a bad one at= =20 that), and is actually a negligible (diagnostic) part in the backend servic= e=20 which gets passed a file-descriptor over a Unix Domain socket from other=20 daemons (actually, filters) running on the same machine. What is the case here is that the server I'm building is basically a servic= e=20 which works over any kind of SOCK_STREAM, but has to adapt its behaviour=20 slightly depending on the type of the socket being passed in. At the moment= ,=20 there are two different kinds of connections being handled by front-end=20 plugins (which basically accept on a listening socket, set up a certain=20 initial state and pass it to the backend): AF_INET(6) and AF_BLUETOOTH. The= =20 latter won't work with the getaddr*-functions or getnameinfo() to format th= e=20 address, and also requires me to handle the connection slightly differently= =20 in parts (because the information being served is adapted for RFCOMM [i.e.,= =20 mobile] delivery). The plugins which accept connections and pass them back aren't written by m= e,=20 and as such, I wanted to do at least some error checking on the passed in=20 socket (i.e., is SOCK_STREAM, has a family I support, isn't a listening=20 socket, etc.), and what I currently do is similar to the following (that's= =20 just pseudo-code, beware of anything I got wrong from my head now): struct sockaddr_storage addr; socklen_t addrlen =3D sizeof(addr); getsockname(fd,reinterpret_cast(&addr),&addrlen); switch( addr->ss_family ) { case AF_INET: // ... break; case AF_INET6: // Set up some stuff... getpeername(fd,reinterpret_cast(&addr),&addrlen); ...inet_ntop(reinterpret_cast(&addr)); break; case AF_BLUETOOTH: // Set up some other stuff... getpeername(fd,reinterpret_cast(&addr),&addrlen); bt_ntoa(reinterpret_cast(&addr)->rfcomm_bdaddr); break; default: // We don't know this, ignore. } I personally don't find this especially beautiful, and generally, as there = is=20 a getsockopt(SO_TYPE), I'd have thought the above should look (somewhat)=20 similar to the following: int opt; socklen_t optlen =3D sizeof(opt); getsockopt(fd,SOL_SOCKET,SO_DOMAIN,&opt,&optlen); switch( opt ) { case PF_INET: // ... break; case PF_INET6: // Initialize inet connection. initInet6(); break; case PF_BLUETOOTH: // Initialize bluetooth. initBluetooth(); break; default: // Do something else. } where initBluetooth() is struct sockaddr_rfcomm addr; socklen_t addrlen =3D sizeof(addr); getpeername(fd,reinterpret_cast(&addr),&addrlen); bt_ntoa(...addr.rfcomm_bdaddr); There's just one explicit type-cast in the latter (which makes it so much m= ore=20 readable IMHO). Anyway, as I said before, this is basically a style issue, and because a=20 socket is constructed with an explicit domain parameter I'd have thought th= at=20 there is some way to query that constructor argument (and explicitly _only_= =20 that constructor argument), but apparently, nobody else feels the way I do,= =20 which I can accept, don't worry. ;-) =2D-=20 Heiko Wundram Product & Application Development