ip/gping: icmpv6 support

This commit is contained in:
cinap_lenrek 2018-04-10 20:04:20 +02:00
parent 829a451c2b
commit eac7a2b12a

View file

@ -54,6 +54,7 @@ struct Machine
{ {
Lock; Lock;
char *name; char *name;
int version;
int pingfd; int pingfd;
int nproc; int nproc;
@ -423,7 +424,7 @@ pingreply(Machine *m, Req *r)
void void
pingclean(Machine *m, ushort seq, vlong now, int) pingclean(Machine *m, ushort seq, vlong now)
{ {
Req **l, *r; Req **l, *r;
vlong x, y; vlong x, y;
@ -445,31 +446,31 @@ pingclean(Machine *m, ushort seq, vlong now, int)
} }
} }
/* IPv4 only */
void void
pingsend(Machine *m) pingsend(Machine *m)
{ {
int i; int i;
char buf[128], err[ERRMAX]; uchar buf[128];
char err[ERRMAX];
Icmphdr *ip; Icmphdr *ip;
Req *r; Req *r;
ip = (Icmphdr *)(buf + IPV4HDR_LEN); ip = (Icmphdr *)(buf + (m->version==4? IPV4HDR_LEN: IPV6HDR_LEN));
memset(buf, 0, sizeof buf); memset(buf, 0, sizeof buf);
r = malloc(sizeof *r); r = malloc(sizeof *r);
if(r == nil) if(r == nil)
return; return;
for(i = 32; i < MSGLEN; i++) for(i = ip->data-buf; i < MSGLEN; i++)
buf[i] = i; buf[i] = i;
ip->type = EchoRequest; ip->type = m->version==4? EchoRequest: EchoRequestV6;
ip->code = 0; ip->code = 0;
ip->seq[0] = m->seq; ip->seq[0] = m->seq;
ip->seq[1] = m->seq>>8; ip->seq[1] = m->seq>>8;
r->seq = m->seq; r->seq = m->seq;
r->time = nsec(); r->time = nsec();
lock(m); lock(m);
pingclean(m, -1, r->time, 0); pingclean(m, -1, r->time);
r->next = m->list; r->next = m->list;
m->list = r; m->list = r;
unlock(m); unlock(m);
@ -481,7 +482,6 @@ pingsend(Machine *m)
m->seq++; m->seq++;
} }
/* IPv4 only */
void void
pingrcv(void *arg) pingrcv(void *arg)
{ {
@ -489,27 +489,25 @@ pingrcv(void *arg)
uchar buf[512]; uchar buf[512];
ushort x; ushort x;
Icmphdr *ip; Icmphdr *ip;
Ip4hdr *ip4;
Machine *m = arg; Machine *m = arg;
ip4 = (Ip4hdr *)buf; ip = (Icmphdr *)(buf + (m->version==4? IPV4HDR_LEN: IPV6HDR_LEN));
ip = (Icmphdr *)(buf + IPV4HDR_LEN);
for(;;){ for(;;){
n = read(m->pingfd, buf, sizeof(buf)); n = read(m->pingfd, buf, sizeof(buf));
if(n <= 0) if(n <= 0)
break; break;
if(n < MSGLEN) if(n < MSGLEN)
continue; continue;
for(i = 32; i < MSGLEN; i++) for(i = ip->data-buf; i < MSGLEN; i++)
if(buf[i] != (i&0xff)) if(buf[i] != (i&0xff))
break; break;
if(i != MSGLEN) if(i != MSGLEN)
continue; continue;
x = (ip->seq[1]<<8) | ip->seq[0]; x = (ip->seq[1]<<8) | ip->seq[0];
if(ip->type != EchoReply || ip->code != 0) if(ip->type != (m->version==4? EchoReply: EchoReplyV6) || ip->code != 0)
continue; continue;
lock(m); lock(m);
pingclean(m, x, nsec(), ip4->ttl); pingclean(m, x, nsec());
unlock(m); unlock(m);
} }
} }
@ -527,12 +525,21 @@ initmach(Machine *m, char *name)
m->name = estrdup(p+1); m->name = estrdup(p+1);
}else }else
p = name; p = name;
m->name = estrdup(p); m->name = estrdup(p);
m->nproc = 1; m->nproc = 1;
m->pingfd = dial(netmkaddr(m->name, "icmp", "1"), nil, nil, &cfd);
if(m->pingfd < 0) m->version = 4;
if(strstr(name, "icmpv6!") != nil)
m->version = 6;
again:
m->pingfd = dial(netmkaddr(m->name, m->version==4? "icmp": "icmpv6", "1"), nil, nil, &cfd);
if(m->pingfd < 0){
if(m->version == 4){
m->version = 6;
goto again;
}
sysfatal("dialing %s: %r", m->name); sysfatal("dialing %s: %r", m->name);
}
write(cfd, "ignoreadvice", 12); write(cfd, "ignoreadvice", 12);
close(cfd); close(cfd);
startproc(pingrcv, m); startproc(pingrcv, m);