Linux actually has the correct behaviour and updates the timeout
argument to reflect the time remaining. Unfortunately we don't actually
want to do that. So reset it each time.
int mtu;
int i;
size_t sz;
int mtu;
int i;
size_t sz;
+ struct timeval tv, tvproto;
- tv.tv_sec = to; tv.tv_usec = (to - tv.tv_sec) * 1000000;
+ tvproto.tv_sec = to; tvproto.tv_usec = (to - tvproto.tv_sec) * 1000000;
if ((sk = socket(PF_INET, SOCK_DGRAM, 0)) < 0) goto fail_0;
i = IP_PMTUDISC_DO;
if (setsockopt(sk, SOL_IP, IP_MTU_DISCOVER, &i, sizeof(i)))
if ((sk = socket(PF_INET, SOCK_DGRAM, 0)) < 0) goto fail_0;
i = IP_PMTUDISC_DO;
if (setsockopt(sk, SOL_IP, IP_MTU_DISCOVER, &i, sizeof(i)))
sz = sizeof(mtu);
if (getsockopt(sk, SOL_IP, IP_MTU, &mtu, &sz)) goto fail_1;
if (write(sk, buf, mtu - 28) < 0) goto fail_1;
sz = sizeof(mtu);
if (getsockopt(sk, SOL_IP, IP_MTU, &mtu, &sz)) goto fail_1;
if (write(sk, buf, mtu - 28) < 0) goto fail_1;
+ FD_SET(sk, &fd_in); tv = tvproto;
if (select(sk + 1, &fd_in, 0, 0, &tv) < 0) goto fail_1;
if (!FD_ISSET(sk, &fd_in)) break;
if (read(sk, &i, 1) >= 0 ||
if (select(sk + 1, &fd_in, 0, 0, &tv) < 0) goto fail_1;
if (!FD_ISSET(sk, &fd_in)) break;
if (read(sk, &i, 1) >= 0 ||