22.5 | Calling getaddrinfo without a hostname argument and without the AI_PASSIVE flag set causes it to assume the local host address: 0::1 (IPv6) and 127.0.0.1 (IPv4). Recall that an IPv6 socket address structure is returned before an IPv4 socket address structure by getaddrinfo , assuming IPv6 is supported. If both protocols are supported on the host, the call to socket in udp_client will succeed with the family equal to AF_INET6 . Figure E.15 is the protocol-independent version of this program. Figure E.15 Protocol-independent version of program from Section 22.6. advio/udpserv04.c 1 #include "unpifi.h" 2 void mydg_echo(int, SA *, socklen_t); 3 int 4 main(int argc, char **argv) 5 { 6 int sockfd, family, port; 7 const int on = 1; 8 pid_t pid; 9 socklen_t salen; 10 struct sockaddr *sa, *wild; 11 struct ifi_info *ifi, *ifihead; 12 if (argc == 2) 13 sockfd = Udp_client(NULL, argv[1], (void **) &sa, &salen); 14 else if (argc == 3) 15 sockfd = Udp_client(argv[1], argv[2], (void **) &sa, &salen); 16 else 17 err_quit("usage: udpserv04 [ <host> ] <service or port>"); 18 family = sa->sa_family; 19 port = sock_get_port(sa, salen); 20 Close(sockfd); /* we just want family, port, salen */ 21 for (ifihead = ifi = Get_ifi_info(family, 1); 22 ifi != NULL; ifi = ifi->ifi_next) { 23 /* bind unicast address */ 24 sockfd = Socket(family, SOCK_DGRAM, 0); 25 Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 26 sock_set_port(ifi->ifi_addr, salen, port); 27 Bind(sockfd, ifi->ifi_addr, salen); 28 printf("bound %s\n", Sock_ntop(ifi->ifi_addr, salen)); 29 if ( (pid = Fork()) == 0) { /* child */ 30 mydg_echo(sockfd, ifi->ifi_addr, salen); 31 exit(0); /* never executed */ 32 } 33 if (ifi->ifi_flags & IFF_BROADCAST) { 34 /* try to bind broadcast address */ 35 sockfd = Socket(family, SOCK_DGRAM, 0); 36 Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 37 sock_set_port(ifi->ifi_brdaddr, salen, port); 38 if (bind(sockfd, ifi->ifi_brdaddr, salen) < 0) { 39 if (errno == EADDRINUSE) { 40 printf("EADDRINUSE: %s\n", 41 Sock_ntop(ifi->ifi_brdaddr, salen)); 42 Close(sockfd); 43 continue; 44 } else 45 err_sys("bind error for %s", 46 Sock_ntop(ifi->ifi_brdaddr, salen)); 47 } 48 printf("bound %s\n", Sock_ntop(ifi->ifi_brdaddr, salen)); 49 if ( (pid = Fork()) == 0) { /* child */ 50 mydg_echo(sockfd, ifi->ifi_brdaddr, salen); 51 exit(0); /* never executed */ 52 } 53 } 54 } 55 /* bind wildcard address */ 56 sockfd = Socket(family, SOCK_DGRAM, 0); 57 Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 58 wild = Malloc(salen); 59 memcpy(wild, sa, salen); /* copy family and port */ 60 sock_set_wild(wild, salen); 61 Bind(sockfd, wild, salen); 62 printf("bound %s\n", Sock_ntop(wild, salen)); 63 if ( (pid = Fork()) == 0) { /* child */ 64 mydg_echo(sockfd, wild, salen); 65 exit(0); /* never executed */ 66 } 67 exit(0); 68 } 69 void 70 mydg_echo(int sockfd, SA *myaddr, socklen_t salen) 71 { 72 int n; 73 char mesg[MAXLINE]; 74 socklen_t len; 75 struct sockaddr *cli; 76 cli = Malloc(salen); 77 for ( ; ; ) { 78 len = salen; 79 n = Recvfrom(sockfd, mesg, MAXLINE, 0, cli, &len); 80 printf("child %d, datagram from %s", getpid(), Sock_ntop(cli, len)); 81 printf(", to %s\n", Sock_ntop(myaddr, salen)); 82 Sendto(sockfd, mesg, n, 0, cli, len); 83 } 84 } |