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