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 }
|