Date: Thu, 31 Jan 2008 19:47:41 +0100 From: "Heiko Wundram (Beenic)" <wundram@beenic.net> To: Dag-Erling =?utf-8?q?Sm=C3=B8rgrav?= <des@des.no> Cc: freebsd-hackers@freebsd.org Subject: Re: OT: getting the protocol family of a file descriptor Message-ID: <200801311947.42545.wundram@beenic.net> In-Reply-To: <86myqmvt0z.fsf@ds4.des.no> References: <200801310923.16029.wundram@beenic.net> <200801311701.49792.wundram@beenic.net> <86myqmvt0z.fsf@ds4.des.no>
next in thread | previous in thread | raw e-mail | index | archive | help
Am Donnerstag, 31. Januar 2008 17:50:20 schrieb Dag-Erling Sm=C3=B8rgrav: > "Heiko Wundram (Beenic)" <wundram@beenic.net> 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<struct sockaddr*>(&addr),&addrlen); switch( addr->ss_family ) { case AF_INET: // ... break; case AF_INET6: // Set up some stuff... getpeername(fd,reinterpret_cast<struct sockaddr*>(&addr),&addrlen); ...inet_ntop(reinterpret_cast<struct sockaddr*>(&addr)); break; case AF_BLUETOOTH: // Set up some other stuff... getpeername(fd,reinterpret_cast<struct sockaddr*>(&addr),&addrlen); bt_ntoa(reinterpret_cast<struct sockaddr_rfcomm*>(&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<struct sockaddr*>(&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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200801311947.42545.wundram>