chiark / gitweb /
pathmtu/pathmtu.c (raw): Switchify the code.
[tripe] / pathmtu / pathmtu.c
index 65028edc1e76f45d87681c562bf5aad7a1195968..c1494796de4afc9d0aa75a9a11fc874896967d30 100644 (file)
@@ -475,8 +475,14 @@ static int raw_setup(void *stv, int sk, const struct param *pp)
     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
@@ -535,41 +541,51 @@ static int raw_xmit(void *stv, int mtu)
   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.
@@ -600,40 +616,51 @@ static int raw_selproc(void *stv, fd_set *fd_in, struct probestate *ps)
   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