Current-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: [5.0_RC3] pppd: Couldn't add proxy arp entry: Invalid argument



Andreas Wrede <andreas%wrede.ca@localhost> writes:

> Except for the length and seq, this is the same when doing an arp -s 
> 10.99.3.16 0.d.88.6f.2d.37
>
> got message of size 154 on Thu Apr  2 11:46:57 2009
> RTM_ADD: Add Route: len 154, pid 16031, seq 1, errno 22, flags:
> <HOST,STATIC,PROTO2>
> locks:  inits: <expire>
> sockaddrs: <DST,GATEWAY>
>  10.99.3.16 0.d.88.6f.2d.37
>
> I compared the actual data written by arp and by pppd to the routing
> socket. The differences:
>
> 1. pppd's request has the interface name in the sockaddr_dl structure,
> arp does not
> 2. arp's  sdl_len is padded by 6 bytes, pppd's is not
> 3. arp's rtm_msglen is padded by 4 byes, pppd's is not
>
> Changing pppd's arpmsg packet accordingly makes the proxy arp request
> in pppd work!

very interesting.  Would you be able to back out the changes one by one
to find the one that matters, or the minimal set needed.

I am guessing that for rtm_msglen, the message was not a multiple of 8,
and that there is some ROUND macro that can be used so that it gets
rounded to sizeof(void *).

> The diff below illustrates the changes:
>
> --- sys-bsd.c   25 Oct 2008 22:12:20 -0000      1.58
> +++ sys-bsd.c   2 Apr 2009 17:25:32 -0000
> @@ -1598,6 +1598,13 @@
>         return 0;
>      }
>
> +    /* remove the intrafce name from the sdl struct */
> +    memcpy((char *)&arpmsg.hwa.sdl_data, (char *)&arpmsg.hwa.sdl_data
> +arpmsg.hwa.sdl_nlen, arpmsg.hwa.sdl_alen);
> +    arpmsg.hwa.sdl_len-=arpmsg.hwa.sdl_nlen;
> +    arpmsg.hwa.sdl_nlen=0;
> +    /* pad the packet */
> +    arpmsg.hwa.sdl_len+=6;
> +

This is the first one I would back out to try.

>      if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
>         error("Couldn't add proxy arp entry: socket: %m");
>         return 0;
> @@ -1615,7 +1622,7 @@
>      arpmsg.dst.sin_other = SIN_PROXY;
>
>      arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
> -       + arpmsg.hwa.sdl_len;
> +       + arpmsg.hwa.sdl_len + 4;
>      if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
>         error("Couldn't add proxy arp entry: %m");
>         close(routes);
>
> I don't understand why the padding is needed, maybe i386 vs. amd64?

In some user/kernel communications, the real rules (the code in the
kernel) expects padding to sizeof(long) or sizeof(void *) between
structures, or alternatively that structures are lined up on 4/8
boundaries with the padding internal to them.  It maybe that the kernel
is rounding to find the start of next structure, and it ends up in the
wrong place.

But we can't add 4 - we have to do some sort of rounding.


If you are in the mood this can probably be figured out by reading
kernel source code.  Look for structs that have long or * in them that
when compiled on amd64 won't endup on 8 byte boundaries, and see if the
kernel code handles finding the next structure differently.

Attachment: pgpenhjJcETnz.pgp
Description: PGP signature



Home | Main Index | Thread Index | Old Index