The Linux raw-IPv6-sockets machinery doesn't like port numbers in socket
addresses, so keep track of the ports separately and clear out the port
numbers in the address structures.
struct raw_state {
union addr me, a;
int sk, rawicmp, rawudp;
struct raw_state {
union addr me, a;
int sk, rawicmp, rawudp;
+ uint16_t srcport, dstport;
if (getsockname(sk, &st->me.sa, &sz))
goto fail_0;
if (getsockname(sk, &st->me.sa, &sz))
goto fail_0;
+ /* An unfortunate bodge which will make sense in the future. */
+ st->srcport = st->me.sin.sin_port; st->me.sin.sin_port = 0;
+ st->dstport = st->a.sin.sin_port; st->a.sin.sin_port = 0;
+
/* There isn't a portable way to force the DF flag onto a packet through
* UDP, or even through raw IP, unless we write the entire IP header
* ourselves. This is somewhat annoying, especially since we have an
/* There isn't a portable way to force the DF flag onto a packet through
* UDP, or even through raw IP, unless we write the entire IP header
* ourselves. This is somewhat annoying, especially since we have an
/* Build a UDP packet in the output buffer. */
udp = (struct udphdr *)(ip + 1);
/* Build a UDP packet in the output buffer. */
udp = (struct udphdr *)(ip + 1);
- udp->uh_sport = st->me.sin.sin_port;
- udp->uh_dport = st->a.sin.sin_port;
+ udp->uh_sport = st->srcport;
+ udp->uh_dport = st->dstport;
udp->uh_ulen = htons(mtu - sizeof(*ip));
udp->uh_sum = 0;
udp->uh_ulen = htons(mtu - sizeof(*ip));
udp->uh_sum = 0;
n -= sizeof(*ip);
udp = (struct udphdr *)(ip + 1);
n -= sizeof(*ip);
udp = (struct udphdr *)(ip + 1);
- if (n < sizeof(*udp) || udp->uh_sport != st->me.sin.sin_port ||
- udp->uh_dport != st->a.sin.sin_port)
+ if (n < sizeof(*udp) || udp->uh_sport != st->srcport ||
+ udp->uh_dport != st->dstport)
goto skip_icmp;
n -= sizeof(*udp);
goto skip_icmp;
n -= sizeof(*udp);