| /* Example from getaddrinfo.3 manpage, which has this license: |
| |
| Copyright (c) 2007, 2008 Michael Kerrisk <mtk.manpages@gmail.com> |
| and Copyright (c) 2006 Ulrich Drepper <drepper@redhat.com> |
| A few pieces of an earlier version remain: |
| Copyright 2000, Sam Varshavchik <mrsam@courier-mta.com> |
| |
| Permission is granted to make and distribute verbatim copies of this |
| manual provided the copyright notice and this permission notice are |
| preserved on all copies. |
| |
| Permission is granted to copy and distribute modified versions of this |
| manual under the conditions for verbatim copying, provided that the |
| entire resulting derived work is distributed under the terms of a |
| permission notice identical to this one. |
| |
| Since the Linux kernel and libraries are constantly changing, this |
| manual page may be incorrect or out-of-date. The author(s) assume no |
| responsibility for errors or omissions, or for damages resulting from |
| the use of the information contained herein. The author(s) may not |
| have taken the same level of care in the production of this manual, |
| which is licensed free of charge, as they might when working |
| professionally. |
| |
| Formatted or processed versions of this manual, if unaccompanied by |
| the source, must acknowledge the copyright and authors of this work. |
| */ |
| |
| #include <sys/types.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <sys/socket.h> |
| #include <netdb.h> |
| |
| #define BUF_SIZE 500 |
| |
| int |
| main(int argc, char *argv[]) |
| { |
| struct addrinfo hints; |
| struct addrinfo *result, *rp; |
| int sfd, s; |
| struct sockaddr_storage peer_addr; |
| socklen_t peer_addr_len; |
| ssize_t nread; |
| char buf[BUF_SIZE]; |
| |
| if (argc != 2) { |
| fprintf(stderr, "Usage: %s port\n", argv[0]); |
| exit(EXIT_FAILURE); |
| } |
| |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ |
| hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ |
| hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ |
| hints.ai_protocol = 0; /* Any protocol */ |
| hints.ai_canonname = NULL; |
| hints.ai_addr = NULL; |
| hints.ai_next = NULL; |
| |
| s = getaddrinfo(NULL, argv[1], &hints, &result); |
| if (s != 0) { |
| fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); |
| exit(EXIT_FAILURE); |
| } |
| |
| /* getaddrinfo() returns a list of address structures. |
| Try each address until we successfully bind(2). |
| If socket(2) (or bind(2)) fails, we (close the socket |
| and) try the next address. */ |
| |
| for (rp = result; rp != NULL; rp = rp->ai_next) { |
| sfd = socket(rp->ai_family, rp->ai_socktype, |
| rp->ai_protocol); |
| if (sfd == -1) |
| continue; |
| |
| if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) |
| break; /* Success */ |
| |
| close(sfd); |
| } |
| |
| freeaddrinfo(result); /* No longer needed */ |
| |
| if (rp == NULL) { /* No address succeeded */ |
| fprintf(stderr, "Could not bind\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| /* Read datagrams and echo them back to sender. */ |
| |
| for (;;) { |
| peer_addr_len = sizeof(peer_addr); |
| nread = recvfrom(sfd, buf, BUF_SIZE, 0, |
| (struct sockaddr *) &peer_addr, &peer_addr_len); |
| if (nread == -1) |
| continue; /* Ignore failed request */ |
| |
| char host[NI_MAXHOST], service[NI_MAXSERV]; |
| |
| s = getnameinfo((struct sockaddr *) &peer_addr, |
| peer_addr_len, host, NI_MAXHOST, |
| service, NI_MAXSERV, NI_NUMERICSERV); |
| if (s == 0) |
| printf("Received %zd bytes from %s:%s\n", |
| nread, host, service); |
| else |
| fprintf(stderr, "getnameinfo: %s\n", gai_strerror(s)); |
| |
| if (sendto(sfd, buf, nread, 0, |
| (struct sockaddr *) &peer_addr, |
| peer_addr_len) != nread) |
| fprintf(stderr, "Error sending response\n"); |
| } |
| } |