Hello,
There seems to be a problem with the source address selection for UDP
datagrams. I use Linux kernel 2.3.99-pre6 and glibc 2.1.3.
I would expect that if I bind() a socket to a specific global scope
unicast address and send a datagram on the socket, that the source address
of the datagram would be the bound address. This doesn't seem to be the
case.
I have attached 2 small programs, a server and a client, that demonstrates
my problem. Here is a sample session:
h83% ./server &
Waiting
[2] 2127
h83% ./client 3ffe:200:13::3
Received message of length: 6
Source address: ::1
h83%
Is this a bug in the kernel, or have I misunderstood something?
Regards,
Pontus
--
Pontus Lidman, [EMAIL PROTECTED], Software Engineer
No matter how cynical you get, it's impossible to keep up.
Scene: www.dc-s.com | MUD: tyme.envy.com 6969 | irc: irc.quakenet.eu.org
/* IPv6 UDP listen, prints source address */
#include <stdio.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
#define PORT 9999
int main() {
int s6;
int len2;
char msgbuf[16384];
struct protoent *prent;
struct sockaddr_in6 from6;
struct sockaddr_in6 lstn6;
int sendersize;
prent=getprotobyname("udp");
if (!prent) perror("Can't get protocol");
if (-1==(s6=socket(PF_INET6,SOCK_DGRAM,prent->p_proto)))
perror("Can't create IPv6 socket");
bzero(&lstn6,sizeof(struct sockaddr_in6));
lstn6.sin6_port=htons((short) PORT);
lstn6.sin6_addr=in6addr_any;
if (-1==bind(s6,&lstn6,sizeof(lstn6))) perror("bind");
printf("Waiting\n");
while (1) {
sendersize=sizeof(struct sockaddr_in6);
len2=recvfrom(s6,msgbuf,8192,0,&from6,&sendersize);
if (len2==-1) perror("recvfrom");
else {
char sadr[1024];
printf("Received message of length: %d\n",len2);
if (getnameinfo((struct sockaddr *) &from6,sizeof(from6),
sadr,1024,NULL,0,NI_NUMERICHOST))
strcpy(sadr,"<unknown>");
printf("Source address: %s\n",sadr);
}
}
}
/* IPv6 UDP send with source address */
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <arpa/inet.h>
#define PORT 9999
#define SRC_PORT 9998
int main(int argc, char **argv) {
int s;
char *msg="hej!!\0";
struct protoent *prent;
struct sockaddr_in6 to,from;
struct in6_addr my_addr;
if (argc<2) {
printf("Give IPv6 address to bind to\n");
exit(1);
}
if (NULL==(prent=getprotobyname("udp"))) {
perror("getprotobyname");
}
bzero(&to,sizeof(struct sockaddr_in6));
to.sin6_port=htons((short) PORT);
inet_pton(AF_INET6,argv[1],&my_addr);
to.sin6_addr=my_addr;
bzero(&from,sizeof(struct sockaddr_in6));
from.sin6_port=htons((short) SRC_PORT);
from.sin6_addr=my_addr;
if (-1==(s=socket(PF_INET6,SOCK_DGRAM,prent->p_proto))) {
perror("socket");
}
if (-1==bind(s,&from,sizeof(from)))
perror("bind");
if (-1==sendto(s,msg,6,0,&to,sizeof(struct sockaddr_in6))) {
perror("sendto");
}
return 0;
}