From: Ralph Ronnquist Date: Fri, 11 Nov 2022 09:33:28 +0000 (+1100) Subject: added ipv6 sending X-Git-Tag: 1.6.1~3 X-Git-Url: https://git.rrq.au/?a=commitdiff_plain;h=f861a198150c18d51ae736f1ce0ccca56cae72b4;p=rrq%2Frrqnet.git added ipv6 sending --- diff --git a/rrqnet.c b/rrqnet.c index 8f09381..7c70220 100644 --- a/rrqnet.c +++ b/rrqnet.c @@ -946,35 +946,63 @@ static void sendpacket4(unsigned char *buf, int n,struct Remote *r) { .msg_controllen = CMSG_SPACE( sizeof( struct in_pktinfo ) ), .msg_flags = 0 // unused }; - if ( r->laddr.in.sa_family && 0 ) { - msg.msg_control = &control; - msg.msg_controllen = CMSG_SPACE( sizeof( struct in_pktinfo ) ); - } - VERBOSE2OUT( "sendmsg %lu from %s to %s\n", + VERBOSE2OUT( "sendmsg ipv4 %lu from %s to %s\n", msg.msg_controllen, inet_stoa( &r->laddr ), inet_stoa( &r->uaddr ) ); if ( sendmsg( udp_fd, &msg, 0 ) < n ) { perror( "Writing socket" ); } -#if 0 // ILLUSTRATION - struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = IPPROTO_IP; - cmsg->cmsg_type = IP_PKTINFO; - cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); - struct in_pktinfo *pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg); - pktinfo->ipi_ifindex = src_interface_index; - pktinfo->ipi_spec_dst = src_addr; - msg.msg_controllen = - return sendmsg( fd, &msg, IP_PKTINFO ); -#endif } static void sendpacket6(unsigned char *buf, int n,struct Remote *r) { - //NYI - (void)buf; - (void)n; - (void)r; + // The UDP socket is ipv6, possibly with mapped ipv4 address(es) + struct iovec data[1] = {{ .iov_base = buf, .iov_len = n }}; + struct { + struct cmsghdr hdr; + union { + struct in_pktinfo in4; + struct in6_pktinfo in6; + } data; + } control; + struct msghdr msg = { + .msg_name = &r->uaddr.in6, + .msg_namelen = sizeof( struct sockaddr_in6 ), + .msg_iov = data, + .msg_iovlen = 1, + .msg_control = 0, + .msg_controllen = 0, + .msg_flags = 0 // unused + }; + if ( r->ifindex ) { + switch ( r->laddr.in.sa_family ) { + case AF_INET6: + control.hdr.cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + control.hdr.cmsg_level = IPPROTO_IPV6; + control.hdr.cmsg_type = IPV6_PKTINFO; + control.data.in6.ipi6_ifindex = r->ifindex; + memcpy( &control.data.in6.ipi6_addr, &r->laddr.in6.sin6_addr, 16 ); + msg.msg_control = &control; + msg.msg_controllen = CMSG_SPACE( sizeof( struct in6_pktinfo ) ); + break; + case AF_INET: + control.hdr.cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + control.hdr.cmsg_level = IPPROTO_IP; + control.hdr.cmsg_type = IP_PKTINFO; + control.data.in4.ipi_ifindex = r->ifindex; + control.data.in4.ipi_spec_dst = r->laddr.in4.sin_addr; + msg.msg_control = &control; + msg.msg_controllen = CMSG_SPACE( sizeof( struct in_pktinfo ) ); + break; + } + } + VERBOSE2OUT( "sendmsg ipv6 %d from %s to %s\n", + r->ifindex, + inet_stoa( &r->laddr ), + inet_stoa( &r->uaddr ) ); + if ( sendmsg( udp_fd, &msg, 0 ) < n ) { + perror( "Writing socket" ); + } } // Write a packet via the given Interface with encryption as specified. @@ -1188,21 +1216,24 @@ static void route_packet(PacketItem *pi) { VERBOSE2OUT( "not a nice packet\n" ); return; // not a nice packet } - // Set the local addressing for the remote - if ( udp6 ) { - x->remote->ifindex = pi->dstinfo.in6.ipi6_ifindex; - x->remote->laddr.in6.sin6_family = AF_INET6; - x->remote->laddr.in6.sin6_port = htons( udp_port ); - memcpy( &x->remote->laddr.in6.sin6_addr, - &pi->dstinfo.in6.ipi6_addr, - 16 ); - } else { - x->remote->ifindex = pi->dstinfo.in4.ipi_ifindex; - x->remote->laddr.in4.sin_family = AF_INET; - x->remote->laddr.in4.sin_port = htons( udp_port ); - memcpy( &x->remote->laddr.in4.sin_addr, - &pi->dstinfo.in4.ipi_spec_dst, - 4 ); + // Set the local addressing for the remote, unless set already + if ( x->remote->ifindex == 0 ) { + if ( udp6 ) { + x->remote->ifindex = pi->dstinfo.in6.ipi6_ifindex; + x->remote->laddr.in6.sin6_family = AF_INET6; + x->remote->laddr.in6.sin6_port = htons( udp_port ); + memcpy( &x->remote->laddr.in6.sin6_addr, + &pi->dstinfo.in6.ipi6_addr, + 16 ); + unmap_if_mapped( &x->remote->laddr ); + } else { + x->remote->ifindex = pi->dstinfo.in4.ipi_ifindex; + x->remote->laddr.in4.sin_family = AF_INET; + x->remote->laddr.in4.sin_port = htons( udp_port ); + memcpy( &x->remote->laddr.in4.sin_addr, + &pi->dstinfo.in4.ipi_spec_dst, + 4 ); + } } if ( ( *buf & 1 ) == 0 ) { // unicast