diff options
Diffstat (limited to 'sysdep')
-rw-r--r-- | sysdep/bsd/sysio.h | 63 | ||||
-rw-r--r-- | sysdep/linux/sysio.h | 38 | ||||
-rw-r--r-- | sysdep/unix/io.c | 44 |
3 files changed, 97 insertions, 48 deletions
diff --git a/sysdep/bsd/sysio.h b/sysdep/bsd/sysio.h index 085f16fa..031eac9a 100644 --- a/sysdep/bsd/sysio.h +++ b/sysdep/bsd/sysio.h @@ -113,7 +113,9 @@ sysio_leave_group(sock *s, ip_addr maddr) /* BSD RX/TX packet info handling for IPv4 */ /* it uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */ -#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in_addr)) + CMSG_SPACE(sizeof(struct sockaddr_dl))) +#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in_addr)) + \ + CMSG_SPACE(sizeof(struct sockaddr_dl)) + \ + CMSG_SPACE(sizeof(char))) #define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_addr)) static char * @@ -121,13 +123,18 @@ sysio_register_cmsgs(sock *s) { int ok = 1; if (s->flags & SKF_LADDR_RX) - { - if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &ok, sizeof(ok)) < 0) - return "IP_RECVDSTADDR"; + { + if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &ok, sizeof(ok)) < 0) + return "IP_RECVDSTADDR"; + + if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &ok, sizeof(ok)) < 0) + return "IP_RECVIF"; + } + + if ((s->flags & SKF_TTL_RX) && + (setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &ok, sizeof(ok)) < 0)) + return "IP_RECVTTL"; - if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &ok, sizeof(ok)) < 0) - return "IP_RECVIF"; - } return NULL; } @@ -136,27 +143,35 @@ static void sysio_process_rx_cmsgs(sock *s, struct msghdr *msg) { struct cmsghdr *cm; + struct in_addr *ra = NULL; + struct sockaddr_dl *ri = NULL; + unsigned char *ttl = NULL; - if (!(s->flags & SKF_LADDR_RX)) - return; + for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm)) + { + if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR) + ra = (struct in_addr *) CMSG_DATA(cm); - s->laddr = IPA_NONE; - s->lifindex = 0; + if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVIF) + ri = (struct sockaddr_dl *) CMSG_DATA(cm); - for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm)) - { - if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR) - { - struct in_addr *ra = (struct in_addr *) CMSG_DATA(cm); - get_inaddr(&s->laddr, ra); - } + if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVTTL) + ttl = (unsigned char *) CMSG_DATA(cm); + } - if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVIF) - { - struct sockaddr_dl *ri = (struct sockaddr_dl *) CMSG_DATA(cm); - s->lifindex = ri->sdl_index; - } - } + if (s->flags & SKF_LADDR_RX) + { + s->laddr = IPA_NONE; + s->lifindex = 0; + + if (ra) + get_inaddr(&s->laddr, ra); + if (ri) + s->lifindex = ri->sdl_index; + } + + if (s->flags & SKF_TTL_RX) + s->ttl = ttl ? *ttl : -1; // log(L_WARN "RX %I %d", s->laddr, s->lifindex); } diff --git a/sysdep/linux/sysio.h b/sysdep/linux/sysio.h index 41287e71..250ed586 100644 --- a/sysdep/linux/sysio.h +++ b/sysdep/linux/sysio.h @@ -194,17 +194,22 @@ sk_set_md5_auth_int(sock *s, sockaddr *sa, char *passwd) /* RX/TX packet info handling for IPv4 */ /* Mostly similar to standardized IPv6 code */ -#define CMSG_RX_SPACE CMSG_SPACE(sizeof(struct in_pktinfo)) +#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in_pktinfo)) + CMSG_SPACE(sizeof(int))) #define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_pktinfo)) static char * sysio_register_cmsgs(sock *s) { int ok = 1; + if ((s->flags & SKF_LADDR_RX) && - setsockopt(s->fd, IPPROTO_IP, IP_PKTINFO, &ok, sizeof(ok)) < 0) + (setsockopt(s->fd, IPPROTO_IP, IP_PKTINFO, &ok, sizeof(ok)) < 0)) return "IP_PKTINFO"; + if ((s->flags & SKF_TTL_RX) && + (setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &ok, sizeof(ok)) < 0)) + return "IP_RECVTTL"; + return NULL; } @@ -213,25 +218,34 @@ sysio_process_rx_cmsgs(sock *s, struct msghdr *msg) { struct cmsghdr *cm; struct in_pktinfo *pi = NULL; - - if (!(s->flags & SKF_LADDR_RX)) - return; + int *ttl = NULL; for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm)) + { + if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_PKTINFO) + pi = (struct in_pktinfo *) CMSG_DATA(cm); + + if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_TTL) + ttl = (int *) CMSG_DATA(cm); + } + + if (s->flags & SKF_LADDR_RX) + { + if (pi) { - if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_PKTINFO) - pi = (struct in_pktinfo *) CMSG_DATA(cm); + get_inaddr(&s->laddr, &pi->ipi_addr); + s->lifindex = pi->ipi_ifindex; } - - if (!pi) + else { s->laddr = IPA_NONE; s->lifindex = 0; - return; } + } + + if (s->flags & SKF_TTL_RX) + s->ttl = ttl ? *ttl : -1; - get_inaddr(&s->laddr, &pi->ipi_addr); - s->lifindex = pi->ipi_ifindex; return; } diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index 434a05be..93863885 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -673,7 +673,7 @@ get_sockaddr(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, unsigned *p #ifdef IPV6 /* PKTINFO handling is also standardized in IPv6 */ -#define CMSG_RX_SPACE CMSG_SPACE(sizeof(struct in6_pktinfo)) +#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int))) #define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in6_pktinfo)) /* @@ -685,15 +685,26 @@ get_sockaddr(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, unsigned *p #ifndef IPV6_RECVPKTINFO #define IPV6_RECVPKTINFO IPV6_PKTINFO #endif +/* + * Same goes for IPV6_HOPLIMIT -> IPV6_RECVHOPLIMIT. + */ +#ifndef IPV6_RECVHOPLIMIT +#define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT +#endif static char * sysio_register_cmsgs(sock *s) { int ok = 1; + if ((s->flags & SKF_LADDR_RX) && - setsockopt(s->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &ok, sizeof(ok)) < 0) + (setsockopt(s->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &ok, sizeof(ok)) < 0)) return "IPV6_RECVPKTINFO"; + if ((s->flags & SKF_TTL_RX) && + (setsockopt(s->fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &ok, sizeof(ok)) < 0)) + return "IPV6_RECVHOPLIMIT"; + return NULL; } @@ -702,25 +713,34 @@ sysio_process_rx_cmsgs(sock *s, struct msghdr *msg) { struct cmsghdr *cm; struct in6_pktinfo *pi = NULL; - - if (!(s->flags & SKF_LADDR_RX)) - return; + int *hlim = NULL; for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm)) + { + if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO) + pi = (struct in6_pktinfo *) CMSG_DATA(cm); + + if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_HOPLIMIT) + hlim = (int *) CMSG_DATA(cm); + } + + if (s->flags & SKF_LADDR_RX) + { + if (pi) { - if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO) - pi = (struct in6_pktinfo *) CMSG_DATA(cm); + get_inaddr(&s->laddr, &pi->ipi6_addr); + s->lifindex = pi->ipi6_ifindex; } - - if (!pi) + else { s->laddr = IPA_NONE; s->lifindex = 0; - return; } + } + + if (s->flags & SKF_TTL_RX) + s->ttl = hlim ? *hlim : -1; - get_inaddr(&s->laddr, &pi->ipi6_addr); - s->lifindex = pi->ipi6_ifindex; return; } |