2 $Id: socket.c,v 1.2 2009-11-05 14:38:08 franklahm Exp $
3 Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
18 #endif /* HAVE_CONFIG_H */
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <arpa/inet.h>
27 #include <atalk/logger.h>
29 static char ipv4mapprefix[] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff};
31 int setnonblock(int fd, int cmd)
36 if ((fdflags = ofdflags = fcntl(fd, F_GETFL, 0)) == -1)
40 fdflags |= O_NONBLOCK;
42 fdflags &= ~O_NONBLOCK;
44 if (fdflags != ofdflags)
45 if (fcntl(fd, F_SETFL, fdflags) == -1)
51 const char *getip_string(const struct sockaddr *sa)
53 static char ip4[INET_ADDRSTRLEN];
54 static char ip6[INET6_ADDRSTRLEN];
56 switch (sa->sa_family) {
59 const struct sockaddr_in *sai4 = (const struct sockaddr_in *)sa;
60 if ((inet_ntop(AF_INET, &(sai4->sin_addr), ip4, INET_ADDRSTRLEN)) == NULL)
65 const struct sockaddr_in6 *sai6 = (const struct sockaddr_in6 *)sa;
66 if ((inet_ntop(AF_INET6, &(sai6->sin6_addr), ip6, INET6_ADDRSTRLEN)) == NULL)
69 /* Deal with IPv6 mapped IPv4 addresses*/
70 if ((memcmp(sai6->sin6_addr.s6_addr, ipv4mapprefix, sizeof(ipv4mapprefix))) == 0)
71 return (strrchr(ip6, ':') + 1);
75 return "getip_string ERROR";
78 /* We never get here */
81 unsigned int getip_port(const struct sockaddr *sa)
83 if (sa->sa_family == AF_INET) { /* IPv4 */
84 const struct sockaddr_in *sai4 = (const struct sockaddr_in *)sa;
85 return ntohs(sai4->sin_port);
87 const struct sockaddr_in6 *sai6 = (const struct sockaddr_in6 *)sa;
88 return ntohs(sai6->sin6_port);
91 /* We never get here */
94 void apply_ip_mask(struct sockaddr *sa, uint32_t mask)
99 switch (sa->sa_family) {
104 struct sockaddr_in *si = (struct sockaddr_in *)sa;
105 uint32_t nmask = mask ? ~((1 << (32 - mask)) - 1) : 0;
106 si->sin_addr.s_addr &= htonl(nmask);
113 int i, maskbytes, maskbits;
114 struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)sa;
116 /* Deal with IPv6 mapped IPv4 addresses*/
117 if ((memcmp(si6->sin6_addr.s6_addr, ipv4mapprefix, sizeof(ipv4mapprefix))) == 0) {
123 maskbytes = (128 - mask) / 8; /* maskbytes really are those that will be 0'ed */
126 for (i = maskbytes - 1; i >= 0; i--)
127 si6->sin6_addr.s6_addr[15 - i] = 0;
129 si6->sin6_addr.s6_addr[15 - maskbytes] &= ~((1 << (8 - maskbits)) - 1);
137 int compare_ip(const struct sockaddr *sa1, const struct sockaddr *sa2)
143 ip1 = strdup(getip_string(sa1));
144 ip2 = getip_string(sa2);
146 ret = strcmp(ip1, ip2);