#include "findmtu.h"
/**
* Set up ICMPv6 error reception
* Input: sending socket fd
*/
int recv_init(int sendfd) {
int on;
on = IPV6_PMTUDISC_DO;
if (setsockopt(sendfd, SOL_IPV6, IPV6_MTU_DISCOVER, &on, sizeof(on))) {
perror("sockopt IPV6_MTU_DISCOVER");
exit(1);
}
on = 1;
if (setsockopt(sendfd, SOL_IPV6, IPV6_RECVERR, &on, sizeof(on))) {
perror("sockopt IPV6_RECVERR");
exit(1);
}
return sendfd;
}
/**
* Wait for reply to a probe packet
* Input: socket fd
* Output: 0 for timeout, 1 if a reply arrives
*/
int wait_for_reply(int fd, struct icmpv6responsefilter *filter) {
fd_set fds;
struct timeval tv;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = 2;
tv.tv_usec = 0;
return select(fd+1, &fds, NULL, NULL, &tv);
}
/**
* Process ICMPv6 messages from a socket
* Input: socket fd
* Output: struct mtureply with address of reporting host, MTU, and ICMP type/code
*/
struct mtureply recvmtu(int fd) {
struct msghdr msg;
struct iovec iov;
struct probehdr rcvbuf;
struct sock_extended_err *e;
struct cmsghdr *cmsg;
char cbuf[512];
struct mtureply reply;
time(&rcvbuf.tv.tv_sec);
iov.iov_base = &rcvbuf;
iov.iov_len = sizeof(rcvbuf);
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
msg.msg_control = cbuf;
msg.msg_controllen = sizeof(cbuf);
memset(reply.addr, 0, sizeof(reply.addr));
reply.mtu = 0;
reply.ee_type = reply.ee_code = 0;
if(recvmsg(fd, &msg, MSG_ERRQUEUE) < 0)
return reply;
for(cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
if (cmsg->cmsg_level == SOL_IPV6)
if (cmsg->cmsg_type == IPV6_RECVERR)
e = (struct sock_extended_err *)CMSG_DATA(cmsg);
if(e->ee_origin == SO_EE_ORIGIN_ICMP6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)(e+1);
inet_ntop(AF_INET6, &sin6->sin6_addr, reply.addr, sizeof(reply.addr));
}
switch(e->ee_errno) {
case EMSGSIZE:
reply.mtu = e->ee_info;
break;
case ECONNREFUSED: /* Target reached */
reply.mtu = -1;
break;
default: /* Other error. Set it and bail */
reply.mtu = -1;
reply.ee_type = e->ee_type;
reply.ee_code = e->ee_code;
break;
}
return(reply);
}
struct icmpv6responsefilter *getfilter(int fd) {
return NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1