106{
107 long bits;
108 char *endptr;
109
110 if (numbits == NULL)
111 {
112 bits = (family == AF_INET) ? 32 : 128;
113 }
114 else
115 {
116 bits = strtol(numbits, &endptr, 10);
117 if (*numbits == '0円' || *endptr != '0円')
118 return -1;
119 }
120
121 switch (family)
122 {
123 case AF_INET:
124 {
125 struct sockaddr_in mask4;
126 long maskl;
127
128 if (bits < 0 || bits > 32)
129 return -1;
130 memset(&mask4, 0, sizeof(mask4));
131 /* avoid "x << 32", which is not portable */
132 if (bits > 0)
133 maskl = (0xffffffffUL << (32 - (int) bits))
134 & 0xffffffffUL;
135 else
136 maskl = 0;
137 mask4.sin_addr.s_addr =
pg_hton32(maskl);
138 memcpy(mask, &mask4, sizeof(mask4));
139 break;
140 }
141
142 case AF_INET6:
143 {
144 struct sockaddr_in6 mask6;
146
147 if (bits < 0 || bits > 128)
148 return -1;
149 memset(&mask6, 0, sizeof(mask6));
150 for (
i = 0;
i < 16;
i++)
151 {
152 if (bits <= 0)
153 mask6.sin6_addr.s6_addr[
i] = 0;
154 else if (bits >= 8)
155 mask6.sin6_addr.s6_addr[
i] = 0xff;
156 else
157 {
158 mask6.sin6_addr.s6_addr[
i] =
159 (0xff << (8 - (int) bits)) & 0xff;
160 }
161 bits -= 8;
162 }
163 memcpy(mask, &mask6, sizeof(mask6));
164 break;
165 }
166
167 default:
168 return -1;
169 }
170
171 mask->ss_family = family;
172 return 0;
173}