This is the mail archive of the ecos-discuss@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Re: Does FreeBSD stack support multiple IP addresses?


On 02/23/2016 04:59 PM, Grant Edwards wrote:
> On 2016-02-23, Lambrecht JÃrgen <J.Lambrecht@TELEVIC.com> wrote:
>> On 02/22/2016 04:05 PM, Grant Edwards wrote:
>>> When I tried it, the SIOCAIFADDR ioctl() let me set both address and
>>> netmask in a single call.  The "case SIOCAIFADDR" code falls through
>>> into SIOCSIFNETMASK code.  That didn't work for you?
>> Indeed, I remember now that I saw that in the code, but then you have
>> the netmask according to the class A/B/C rules, and that is not what we
>> want.
>>
>>>> - It is only possible to assign a class A/B/C netmask. CIDR netmasks are
>>>>     not possible.
>>> I think that's always been the case for this version of the stack,
>>> hasn't it?
>> Indeed.
> I just re-ran my tests and verified again that I'm able to set the IP
> and netmask in a single call to ioctl(SIOCAIFADDR).  In my tests, I
> tried:
>
>   Address         Netmask
> -----------      --------------
>   11.0.0.104      255.0.0.0
>   11.0.0.104      255.255.0.0
>   11.0.0.104      255.255.255.0
>   11.0.0.104      255.240.0.0
I don't understand how you can do those 3 above. The netmask is 
calculated, and 11.0.0.104 is class A, so the netmask is 255.0.0.0 
(IN_CLASSA_NET).
It is only possible to change the netmask by using the subnetmask, but 
that is ANDed with the netmask, so you can only put bits to 0, not to 1!
See net/bsd_tcpip/current/src/sys/netinet/in.c, in_ifinit(ifp, ia, sin, 
scrub):
     if (IN_CLASSA(i))
         ia->ia_netmask = IN_CLASSA_NET;
     else if (IN_CLASSB(i))
         ia->ia_netmask = IN_CLASSB_NET;
     else
         ia->ia_netmask = IN_CLASSC_NET;
     /*
      * The subnet mask usually includes at least the standard network part,
      * but may may be smaller in the case of supernetting.
      * If it is set, we believe it.
      */
     if (ia->ia_subnetmask == 0) {
         ia->ia_subnetmask = ia->ia_netmask;
         ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
     } else
         ia->ia_netmask &= ia->ia_subnetmask;


OK, now I see it: you use
   SIOCAIFADDR
we use
   SIOCSIFADDR
(from http://sourceware.org/ml/ecos-discuss/2005-08/msg00015.html)

Where did you learn to use SIOCAIFADDR?
Could you send me your application code? (then I can also try it)
Our code is below.

Because, when I read SIOCAIFADDR it still calls in_ifinit (but with ifra 
instead of ifr (sin) and 0 instead of 1 (scrub, but in_ifscrub() is 
called separately) arguments...
So I still don't understand it.
You _do_ use net/bsd_tcpip right?
Or you don't use *'AF_INET'*? (then it does not call in_ifinit())
Maybe in our application, we use SIOCSIFADDR wrong?

>   11.0.0.104      240.0.0.0
>   192.168.222.104 240.0.0.0
>   192.168.222.104 255.0.0.0
>   192.168.222.104 255.240.0.0
>   192.168.222.104 255.255.0.0
>   192.168.222.104 255.255.240.0
>   192.168.222.104 255.255.255.0
>   192.168.222.104 255.255.255.240
>
> In all cases, subsequent calls to show_network_tables() showed the IP
> address and netmask I requested in the ioctl() call and the correct
> corresponding broadcast address.
>
> I'm using an eCos snapshot from 2014.
I update regurarely, I also applied the patch of Bernd for raw sockets 
and other fixes.
But that file bsd_tcpip/current/src/sys/netinet/in.c last change in CVS 
is from 2009.
>
>>>>     I fixed current/src/sys/netinet/in.c for it, but I also adapted
>>>>     the ioctl to combine setting IP address and netmask in 1 call
>>>>     (so I cannot commit it back). Let me know if you want my fix.
> The current SIOCAIFADDR code works fine for me.
>
>> I changed a bit the use of the members of the "inet"-something
>> struct (in the ioctl call) to also use the netmask struct member
>> that is already in it. Because normally, when you call ioctl
>> SIOCSIFNETMASK separately, you specify the netmask in the same
>> struct member where you put the IP address for the SIOCAIFADDR call.
> But the SIOCAIFADDR call as a _separate_ place where you put the
> desired netmask, and AFIACT, that works.
Where? in.c::in_ifinit() as I say above (from the second 
switch-case(SIOCAIFADDR)?
>
>> (I did a fast search in the linux code, but I am not used to that,
>> so I did not find the "Linux way")
>>
>>> I'm confused: based on my experiments and examination of the source
>>> code, it already works that way.
>>>
>> Well, it is both.  Indeed, as you say above, "code falls through
>> into SIOCSIFNETMASK code",
>> but then it sets "the netmask according to the class A/B/C rules",
>> so the netmask is _calculated_, not strictly _set_.  I am completely
>> sure about this, I read that whole code part.  (And my collegues did
>> the experimentation to set a 255.248.0.0 netmask resulting in a
>> 255.255.0.0 mask for 172.24.0.0 which is class B)
> I don't know what to tell you other than "it works fine for
> me". Unless the output from show_network_tables() is wrong...
>
No, I don't think so.
When I changed our SIOCSIFADDR code, I also saw the output of 
show_network_tables() changing.


Here some code how we did the ioctl's (before I changed it).

   set_ip_address(ETH_INTERFACE, IP_ADDRESS);
   set_netmask_address(ETH_INTERFACE, NETMASK_ADDRESS);
   set_broadcast_address(ETH_INTERFACE, BROADCAST_ADDRESS);


TLV_BOOL set_ip_address(const char *interface, const char *ip_address)
{
   int test_sock;
   struct sockaddr_in* addr=NULL;
   struct ifreq ifr;

   test_sock = socket( AF_INET, SOCK_DGRAM, 0 );
   //This can also be another type of socket, see 
http://ecos.sourceware.org/ml/ecos-discuss/2007-10/msg00012.html
   if( test_sock == -1 )
   {
     debug_printf("Cannot obtain IP sock\n");
     return TLV_FALSE;
   }

   memset(&ifr,0,sizeof( struct ifreq ) );
   strncpy(ifr.ifr_name,interface,IFNAMSIZ);
   //Delete old IP address, else there will be 2 IP addresses!
   if( ioctl( test_sock, SIOCGIFADDR, &ifr ) == -1 )
   {
     debug_printf("Cannot obtain IP address of %s: 
%s\n",interface,strerror(errno));
   }
   else
   {
     if( ioctl( test_sock, SIOCDIFADDR, &ifr ) != 0 )
     {
       debug_printf("Cannot suppress old IP for %s: 
%s\n",interface,strerror(errno));
     }
   }

   memset( &ifr, 0, sizeof( struct ifreq ) );
   addr= (struct sockaddr_in *)&(ifr.ifr_addr);
   memset(addr, 0, sizeof( struct sockaddr_in) );
   addr->sin_len=sizeof(struct sockaddr_in);
   addr->sin_family=AF_INET;
   addr->sin_addr.s_addr=inet_addr(ip_address);
   strncpy(ifr.ifr_name,interface,IFNAMSIZ);

   if( ioctl( test_sock, SIOCSIFADDR, &ifr ) != 0 )
   {
     debug_printf("Cannot set IP address of %s to %s: 
%s\n",interface,ip_address,strerror(errno));
     close(test_sock);
     return TLV_FALSE;;
   }
   else
   {
     close(test_sock);
     return TLV_TRUE;
   }
}

TLV_BOOL set_netmask_address(const char* interface,const char * address)
{
  int test_sock=0;
  struct sockaddr_in* addr=NULL;
  struct sockaddr * addrp=NULL;
  struct ifreq ifr;

  memset( &ifr, 0, sizeof( struct ifreq ) );
  addrp = (struct sockaddr *)&(ifr.ifr_addr);
  addr= (struct sockaddr_in *)addrp;
  memset(addr, 0, sizeof( struct sockaddr) );
  addr->sin_len=sizeof(struct sockaddr_in);
  addr->sin_family=AF_INET;
  addr->sin_addr.s_addr=inet_addr(address);

  test_sock = socket( AF_INET, SOCK_DGRAM, 0 );
  if( test_sock == -1 )
  {
   diag_printf("Cannot obtain ip socket:%s",strerror(errno));
   return TLV_FALSE;
  }

  strncpy( ifr.ifr_name,interface,IFNAMSIZ);
  if( ioctl( test_sock, SIOCSIFNETMASK, &ifr ) == -1 )
  {
   diag_printf("Impossible to set netmask of interface '%s' to '%s': 
'%s'",interface,address,strerror(errno));
   close(test_sock);
   return TLV_FALSE;
  }
close(test_sock);
  return TLV_TRUE;
}

TLV_BOOL set_broadcast_address(const char* interface,const char * address)
{
  int test_sock=0;
  struct sockaddr_in* addr=NULL;
  struct sockaddr * addrp=NULL;
  struct ifreq ifr;

  memset( &ifr, 0, sizeof( struct ifreq ) );
  addrp = (struct sockaddr *)&(ifr.ifr_addr);
  addr= (struct sockaddr_in *)addrp;
  memset(addr, 0, sizeof( struct sockaddr) );
  addr->sin_len=sizeof(struct sockaddr_in);
  addr->sin_family=AF_INET;
  addr->sin_addr.s_addr=inet_addr(address);

  test_sock = socket( AF_INET, SOCK_DGRAM, 0 );
  if( test_sock == -1 )
  {
   diag_printf("Cannot obtain ip socket:%s",strerror(errno));
   return TLV_FALSE;
  }

  strncpy( ifr.ifr_name,interface,IFNAMSIZ);
  if( ioctl( test_sock, SIOCSIFBRDADDR, &ifr ) == -1 )
  {
   diag_printf("Impossible to set broadcast of interface '%s' to '%s': 
'%s'",interface,address,strerror(errno));
   close(test_sock);
   return TLV_FALSE;
  }
close(test_sock);
  return TLV_TRUE;
}


Kind regards,
JÃrgen

-- 
JÃrgen Lambrecht
R&D Associate
Mobile: +32 499 644 531
Twitter: JGRLambrecht
Tel: +32 (0)51 303045    Fax: +32 (0)51 310670
http://www.televic-rail.com
https://www.facebook.com/TelevicRail
Televic Rail NV - Leo Bekaertlaan 1 - 8870 Izegem - Belgium
Company number 0825.539.581 - RPR Kortrijk

This electronic transmission is intended exclusively for the person or entity
to whom it is addressed and may contain confidential and/or privileged
material. Any disclosure, copying, distribution or other action based upon the
information by persons or entities other than the intended recipient is
prohibited. All e-mail correspondence from Televic Rail NV is only intended for
information purposes and can not result in contractual obligations. Commitments
under Televic Rail NV can only occur through regular exchange of letters,
signed by authorized persons in accordance with publication in the Belgian
Official Gazette.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]