On Wed, Dec 14, 2022 at 10:52 AM David Laight <[email protected]> wrote:
>
> From: John Lemonovich
> > Sent: 13 December 2022 20:35
> >
> > How are you getting a solicit message through with  ::  as the source 
> > address, which I've found no
> > server likes as I've tested 3 of them?  Or is mine not using the link local 
> > address because I'm not
> > doing anything with the default.script?
> >
> > The kernel is 5.4.13
>
> I've just run a quick test.
>
> strace of uhdcpc6 shows it doing something with a routing socket,
> creating an IPv6 UDP socket, binding (probably to the interface)
> and then doing s sendto() that specifies the multicast MAC.
> (It puts the mcast address in the bind as well - probably ignored?)

This code?

int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex(
                struct d6_packet *d6_pkt, unsigned d6_pkt_size,
                struct in6_addr *src_ipv6, int source_port,
                struct in6_addr *dst_ipv6, int dest_port, const
uint8_t *dest_arp)
{
        struct sockaddr_ll dest_sll;
        struct ip6_udp_d6_packet packet;
        int fd;
        int result = -1;
        const char *msg;

        fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
        if (fd < 0) {
                msg = "socket(%s)";
                goto ret_msg;
        }

        memset(&dest_sll, 0, sizeof(dest_sll));
        memset(&packet, 0, offsetof(struct ip6_udp_d6_packet, data));
        packet.data = *d6_pkt; /* struct copy */

        dest_sll.sll_family = AF_PACKET;
        dest_sll.sll_protocol = htons(ETH_P_IPV6);
        dest_sll.sll_ifindex = client_data.ifindex;
        /*dest_sll.sll_hatype = ARPHRD_???;*/
        /*dest_sll.sll_pkttype = PACKET_???;*/
        dest_sll.sll_halen = 6;
        memcpy(dest_sll.sll_addr, dest_arp, 6);

        if (bind(fd, (struct sockaddr *)&dest_sll, sizeof(dest_sll)) < 0) {
                msg = "bind(%s)";
                goto ret_close;
        }


> The kernel is providing the source IPv6 address as part of its
> normal UDP routing operations - the same as it does for any
> other outbound packet.

If it's the code from the above, then no, kernel will not fill in
any IPv6 source addresses, as it does not even know it's
an IPv6/UDP packet - we use raw sockets here,
and we format UDP packet "by hand":

        packet.ip6.ip6_vfc = (6 << 4); /* 4 bits version, top 4 bits
of tclass */
        if (src_ipv6)
                packet.ip6.ip6_src = *src_ipv6; /* struct copy */
^^^^^^^^^^^^^^^^^^^^^^^^^ this is where source IPv6 address filled in
        packet.ip6.ip6_dst = *dst_ipv6; /* struct copy */
        packet.udp.source = htons(source_port);
        packet.udp.dest = htons(dest_port);
        /* size, excluding IP header: */
        packet.udp.len = htons(sizeof(struct udphdr) + d6_pkt_size);
        packet.ip6.ip6_plen = packet.udp.len;
        /*
         * Someone was smoking weed (at least) while inventing UDP checksumming:
         * UDP checksum skips first four bytes of IPv6 header.
         * 'next header' field should be summed as if it is one more byte
         * to the right, therefore we write its value (IPPROTO_UDP)
         * into ip6_hlim, and its 'real' location remains zero-filled for now.
         */
        packet.ip6.ip6_hlim = IPPROTO_UDP;
        packet.udp.check = inet_cksum(
                        (uint8_t *)&packet + 4,
                        offsetof(struct ip6_udp_d6_packet, data) - 4 +
d6_pkt_size
        );
        /* fix 'hop limit' and 'next header' after UDP checksumming */
        packet.ip6.ip6_hlim = 1; /* observed Windows machines to use hlim=1 */
        packet.ip6.ip6_nxt = IPPROTO_UDP;

        d6_dump_packet(d6_pkt);
        result = sendto(fd, &packet, offsetof(struct
ip6_udp_d6_packet, data) + d6_pkt_size,
                        /*flags:*/ 0,
                        (struct sockaddr *) &dest_sll, sizeof(dest_sll)
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to