Subject: Re: set/getsockopt SO_LINGER problem
To: None <netbsd-help@NetBSD.org>
From: Prasanta Sadhukhan <Prasanta.Sadhukhan@Sun.COM>
List: netbsd-help
Date: 12/07/2006 12:21:26
The following code in src/sys/kern/uipc_socket.c#sogetopt() seems to be 
the culprit in my opinion

mtod(m, struct linger *)->l_onoff = so->so_options & SO_LINGER;
mtod(m, struct linger *)->l_linger = so->so_linger;

Since SO_LINGER is 0x80, I am getting 128
also so->so_linger is short unlike l_linger which is int so anything 
 >32767 is curtailed

Regards
Prasanta
Prasanta Sadhukhan wrote:

> David Laight wrote:
>
>> On Wed, Dec 06, 2006 at 01:03:56PM +0530, Prasanta Sadhukhan wrote:
>>  
>>
>>> Hi,
>>>
>>> I am trying to use get/setsockopt for SO_LINGER option but am facing 
>>> a problem
>>> I used setsockopt with opt as SO_LINGER passing linger structure 
>>> with l_onoff as 1 and l_linger as 65535
>>> but when I try to get back through getsockopt, I am getting l_onoff 
>>> as 128 and l_linger as -1.
>>> For other values of l_linger (like 1, 2, 10) during set, though I 
>>> get l_onoff as 128 but l_linger is returned correctly
>>>   
>>
>>
>> I suspect this has something to do with:
>>    /usr/include/sys/socketvar.h:   short    so_linger;
>> and:
>>    /usr/include/sys/socket.h: #define SO_LINGER     0x0080
>>
>>     David
>>
>>  
>>
> I have attached a program that shows the problem. Is it a known issue 
> with NetBSD3.0?
>
> Regards
> Prasanta
>
>------------------------------------------------------------------------
>
>#include <stdio.h>
>#include <sys/socket.h>
>
>void testlinger();
>
>int main(int argc, char *argv[])
>{
>	testlinger();
>}
>
>void testlinger()
>{
>	int fd, ret, optlen;
>	union {
>		int i;
>		struct linger ling;
>	} optval;
>	void *result;
>	fd = socket(PF_INET, SOCK_DGRAM, 0);
>	printf("socket fd %d\n", fd);
>	
>	struct linger ling;
>	optval.ling.l_onoff = 1;
>	optval.ling.l_linger = 65535;
>	optlen = sizeof(optval.ling);
>	ret = setsockopt(fd, SOL_SOCKET, SO_LINGER, (const void *)&optval, optlen);
>	printf("setsockopt retval %d, optlen %d\n", ret,optlen);
>
>	ret = getsockopt(fd, SOL_SOCKET, SO_LINGER, result, &optlen);
>	printf("getsockopt retval %d\n", ret);
>	printf("get linger onoff %d, linger value %d, optlen %d\n",
>			((struct linger*)result)->l_onoff,
>			((struct linger*)result)->l_linger, optlen);
>}
>	
>  
>