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;
+ switch (pp->a.sa.sa_family) {
+ case AF_INET:
+ 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;
+ break;
+ default:
+ abort();
+ }
/* 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
struct phdr ph;
unsigned ck;
- /* Build the IP header. */
- ip = (struct ip *)b;
- ip->ip_v = 4;
- ip->ip_hl = sizeof(*ip)/4;
- ip->ip_tos = IPTOS_RELIABILITY;
- ip->ip_len = sane_htons(mtu);
- STEP(st->q); ip->ip_id = htons(st->q);
- ip->ip_off = sane_htons(0 | IP_DF);
- ip->ip_ttl = 64;
- ip->ip_p = IPPROTO_UDP;
- ip->ip_sum = 0;
- ip->ip_src = st->me.sin.sin_addr;
- ip->ip_dst = st->a.sin.sin_addr;
-
- /* Build a UDP packet in the output buffer. */
- udp = (struct udphdr *)(ip + 1);
- udp->uh_sport = st->srcport;
- udp->uh_dport = st->dstport;
- udp->uh_ulen = htons(mtu - sizeof(*ip));
- udp->uh_sum = 0;
-
- /* Copy the payload. */
- p = (unsigned char *)(udp + 1);
- memcpy(p, buf, mtu - (p - b));
-
- /* Calculate the UDP checksum. */
- ph.ph_src = ip->ip_src;
- ph.ph_dst = ip->ip_dst;
- ph.ph_z = 0;
- ph.ph_p = IPPROTO_UDP;
- ph.ph_len = udp->uh_ulen;
- ck = IPCK_INIT;
- ck = ipcksum(&ph, sizeof(ph), ck);
- ck = ipcksum(udp, mtu - sizeof(*ip), ck);
- udp->uh_sum = htons(ck);
+ switch (st->a.sa.sa_family) {
+
+ case AF_INET:
+
+ /* Build the IP header. */
+ ip = (struct ip *)b;
+ ip->ip_v = 4;
+ ip->ip_hl = sizeof(*ip)/4;
+ ip->ip_tos = IPTOS_RELIABILITY;
+ ip->ip_len = sane_htons(mtu);
+ STEP(st->q); ip->ip_id = htons(st->q);
+ ip->ip_off = sane_htons(0 | IP_DF);
+ ip->ip_ttl = 64;
+ ip->ip_p = IPPROTO_UDP;
+ ip->ip_sum = 0;
+ ip->ip_src = st->me.sin.sin_addr;
+ ip->ip_dst = st->a.sin.sin_addr;
+
+ /* Build a UDP packet in the output buffer. */
+ udp = (struct udphdr *)(ip + 1);
+ udp->uh_sport = st->srcport;
+ udp->uh_dport = st->dstport;
+ udp->uh_ulen = htons(mtu - sizeof(*ip));
+ udp->uh_sum = 0;
+
+ /* Copy the payload. */
+ p = (unsigned char *)(udp + 1);
+ memcpy(p, buf, mtu - (p - b));
+
+ /* Calculate the UDP checksum. */
+ ph.ph_src = ip->ip_src;
+ ph.ph_dst = ip->ip_dst;
+ ph.ph_z = 0;
+ ph.ph_p = IPPROTO_UDP;
+ ph.ph_len = udp->uh_ulen;
+ ck = IPCK_INIT;
+ ck = ipcksum(&ph, sizeof(ph), ck);
+ ck = ipcksum(udp, mtu - sizeof(*ip), ck);
+ udp->uh_sum = htons(ck);
+
+ break;
+
+ default:
+ abort();
+ }
/* Send the whole thing off. If we're too big for the interface then we
* might need to trim immediately.
if (FD_ISSET(st->rawicmp, fd_in)) {
if ((n = read(st->rawicmp, b, sizeof(b))) < 0) goto fail_0;
- ip = (struct ip *)b;
- if (n < sizeof(*ip) || n < sizeof(4*ip->ip_hl) ||
- ip->ip_v != 4 || ip->ip_p != IPPROTO_ICMP)
- goto skip_icmp;
- n -= sizeof(4*ip->ip_hl);
-
- icmp = (struct icmp *)(b + 4*ip->ip_hl);
- if (n < sizeof(*icmp) || icmp->icmp_type != ICMP_UNREACH)
- goto skip_icmp;
- n -= offsetof(struct icmp, icmp_ip);
-
- ip = &icmp->icmp_ip;
- if (n < sizeof(*ip) ||
- ip->ip_p != IPPROTO_UDP || ip->ip_hl != sizeof(*ip)/4 ||
- ip->ip_id != htons(st->q) ||
- ip->ip_src.s_addr != st->me.sin.sin_addr.s_addr ||
- ip->ip_dst.s_addr != st->a.sin.sin_addr.s_addr)
- goto skip_icmp;
- n -= sizeof(*ip);
-
- udp = (struct udphdr *)(ip + 1);
- if (n < sizeof(*udp) || udp->uh_sport != st->srcport ||
- udp->uh_dport != st->dstport)
- goto skip_icmp;
- n -= sizeof(*udp);
-
- payload = (const unsigned char *)(udp + 1);
- if (!mypacketp(ps, payload, n)) goto skip_icmp;
-
- if (icmp->icmp_code == ICMP_UNREACH_PORT) return (RC_HIGHER);
- else if (icmp->icmp_code != ICMP_UNREACH_NEEDFRAG) goto skip_icmp;
- else if (icmp->icmp_nextmtu) return (htons(icmp->icmp_nextmtu));
- else return (RC_LOWER);
+ switch (st->me.sa.sa_family) {
+
+ case AF_INET:
+
+ ip = (struct ip *)b;
+ if (n < sizeof(*ip) || n < sizeof(4*ip->ip_hl) ||
+ ip->ip_v != 4 || ip->ip_p != IPPROTO_ICMP)
+ goto skip_icmp;
+ n -= sizeof(4*ip->ip_hl);
+
+ icmp = (struct icmp *)(b + 4*ip->ip_hl);
+ if (n < sizeof(*icmp) || icmp->icmp_type != ICMP_UNREACH)
+ goto skip_icmp;
+ n -= offsetof(struct icmp, icmp_ip);
+
+ ip = &icmp->icmp_ip;
+ if (n < sizeof(*ip) ||
+ ip->ip_p != IPPROTO_UDP || ip->ip_hl != sizeof(*ip)/4 ||
+ ip->ip_id != htons(st->q) ||
+ ip->ip_src.s_addr != st->me.sin.sin_addr.s_addr ||
+ ip->ip_dst.s_addr != st->a.sin.sin_addr.s_addr)
+ goto skip_icmp;
+ n -= sizeof(*ip);
+
+ udp = (struct udphdr *)(ip + 1);
+ if (n < sizeof(*udp) || udp->uh_sport != st->srcport ||
+ udp->uh_dport != st->dstport)
+ goto skip_icmp;
+ n -= sizeof(*udp);
+
+ payload = (const unsigned char *)(udp + 1);
+ if (!mypacketp(ps, payload, n)) goto skip_icmp;
+
+ if (icmp->icmp_code == ICMP_UNREACH_PORT) return (RC_HIGHER);
+ else if (icmp->icmp_code != ICMP_UNREACH_NEEDFRAG) goto skip_icmp;
+ else if (icmp->icmp_nextmtu) return (htons(icmp->icmp_nextmtu));
+ else return (RC_LOWER);
+
+ break;
+
+ default:
+ abort();
+ }
}
+
skip_icmp:;
/* If we got a reply to the current probe then we're good. If we got an