[Xastir-Dev] IPv6?
Alan Crosswell
alan at columbia.edu
Tue Aug 5 13:10:27 EDT 2003
You have to do some small code changes which are then backward compatible with
IPv4, but the normal struct sockaddr union doesn't have enough space in it. See
my aprsdigi code for some examples. It's not that terrible to make the change
if your code is written using sizeof(foo), and getaddrinfo() etc.
Some sample snippets:
#ifdef IPV6
struct sockaddr_storage rsa,tsa,rsafrom; /* and their sockaddrs */
#else
struct sockaddr rsa,tsa,rsafrom; /* and their sockaddrs */
#endif /*IPV6*/
...
static void
do_port_udp(struct interface *i)
{
struct hostent *hp;
struct servent *sp;
char *name, *service, *ttl;
const int one=1;
int ttlval;
struct addrinfo *ai, hints = {0, PF_UNSPEC, SOCK_DGRAM, 0};
i->dev = i->port; /* might as well just use the same thing */
/* hostname/service(port)/ttl */
name = i->port;
service = strchr(name,'/');
if (!service || *service != '/')
usage_udp();
*service++ = '\0';
ttl = strchr(service,'/');
if (!ttl || *ttl != '/')
usage_udp();
*ttl++ = '\0';
if ((ttlval = atoi(ttl)) <= 0)
usage_udp();
if (Verbose)
fprintf(stderr,"opening UDP socket on %s/%s/%d\n", name, service, ttlval);
if (getaddrinfo(name,service,&hints,&ai) < 0)
die(name);
if (Verbose)
fprintf(stderr,"UDP address info: family %d type %d proto %d next 0x%0x\n",
ai->ai_family,ai->ai_socktype,ai->ai_protocol,ai->ai_next);
if (ai->ai_socktype != SOCK_DGRAM) {
die("getaddrinfo returned non SOCK_DGRAM!\n");
}
if (!(i->i_flags & I_TX)) {
i->tsock = -1;
} else {
if ((i->tsock = socket(ai->ai_family, SOCK_DGRAM, 0)) == -1)
die(name);
if (setsockopt(i->tsock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
die(i->port);
if (ai->ai_family == AF_INET) { /* IPv4 */
i->tsa_size = sizeof(struct sockaddr);
if (IN_MULTICAST(ntohl(((struct
sockaddr_in*)ai->ai_addr)->sin_addr.s_addr))) {
if (setsockopt(i->tsock, SOL_IP, IP_MULTICAST_TTL, &ttlval,
sizeof(ttlval)) < 0
)
die(i->port);
} else {
if (setsockopt(i->tsock, SOL_IP, IP_TTL, &ttlval, sizeof(ttlval)) < 0)
die(i->port);
}
#ifdef IPV6
} else if (ai->ai_family == AF_INET6) { /* IPv6 */
i->tsa_size = sizeof(struct sockaddr_storage);
/* XXX ??? */
#endif /* IPV6 */
} else {
fprintf(stderr,"%s: unsupported protocol family\n",i->port);
exit(1);
}
bzero(&i->tsa,sizeof(i->tsa));
bcopy((struct sockaddr*)ai->ai_addr,&i->tsa,sizeof(i->tsa)); /* fill
sockaddr w/soc
kaddr_in */
if (connect(i->tsock, (struct sockaddr *)&i->tsa, i->tsa_size) < 0) {
die(i->dev);
}
}
/* now the receive socket */
if (!(i->i_flags & I_RX)) {
i->rsock = -1;
} else {
if ((i->rsock = socket(ai->ai_family, SOCK_DGRAM, 0)) == -1) {
die(i->port);
}
if (setsockopt(i->rsock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
die(i->port);
if (ai->ai_family == AF_INET && !IN_MULTICAST(ntohl(((struct
sockaddr_in*)ai->ai_ad
dr)->sin_addr.s_addr))) {
((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr = INADDR_ANY; /* not
mcast s
o wildcard listen */
i->rsa_size = sizeof(struct sockaddr);
#ifdef IPV6
} else if (ai->ai_family == AF_INET6) { /* IPv6 */
/* XXX ??? */
#endif /* IPV6 */
}
i->rsa_size = sizeof(struct sockaddr_storage);
bzero(&i->rsa,sizeof(i->rsa));
bcopy((struct sockaddr*)ai->ai_addr,&i->rsa,sizeof(i->rsa));
if (bind(i->rsock, (struct sockaddr *)&i->rsa, i->rsa_size) < 0) {
die(i->dev);
}
/* if the UDP socket is a multicast group, then do IGMP join for rsock */
if (ai->ai_family == AF_INET && IN_MULTICAST(ntohl(((struct
sockaddr_in*)ai->ai_add
r)->sin_addr.s_addr))) {
struct ip_mreq mreq;
mreq.imr_multiaddr = ((struct sockaddr_in*)ai->ai_addr)->sin_addr;
mreq.imr_interface.s_addr = INADDR_ANY;
if (setsockopt(i->rsock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
sizeof(mreq)) < 0)
die(i->port);
#ifdef IPV6
} else if (ai->ai_family == AF_INET6) { /* IPv6 */
/* XXX ??? */
#endif /* IPV6 */
}
}
}
More information about the Xastir-dev
mailing list