1 /* these functions are useful for dealing with IPv4 */
2 #ifndef __ip4_h
3 #define __ip4_h
4
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <sys/param.h>
8 #include <netinet/in.h>
9 #include <arpa/inet.h>
10 #include <sys/types.h>
11 #include <fcntl.h>
12
13 #include "str.h"
14 #include "mem.h"
15
16 #ifndef IP_LEN
17 #define IP_LEN 4
18 #endif
19
ipv4_null(unsigned char * ip)20 static int inline ipv4_null(unsigned char *ip)
21 {
22 int i;
23 for (i = 0; ip[i] == 0 && i < 4; i++);
24 return i == 4 ? 1 : 0;
25 }
ipv4_scan(const char * str,unsigned char ip[4])26 static int inline ipv4_scan(const char *str, unsigned char ip[4])
27 {
28 int p, v;
29
30 ip[0] = ip[1] = ip[2] = ip[3] = 0;
31 for (p = v = 0; *str && p < 4;) {
32 switch (*str) {
33 case '0': v *= 10; break;
34 case '1': v *= 10; v ++; break;
35 case '2': v *= 10; v += 2; break;
36 case '3': v *= 10; v += 3; break;
37 case '4': v *= 10; v += 4; break;
38 case '5': v *= 10; v += 5; break;
39 case '6': v *= 10; v += 6; break;
40 case '7': v *= 10; v += 7; break;
41 case '8': v *= 10; v += 8; break;
42 case '9': v *= 10; v += 9; break;
43 case '.': ip[p] = v; v = 0; p++; break;
44 default: return 0;
45 };
46 str++;
47 }
48 if (p == 4) return 0;
49 ip[p] = v;
50 return 4;
51 }
ipv4_in_subnet(unsigned char cidr[8],unsigned char ip[4])52 static int inline ipv4_in_subnet(unsigned char cidr[8], unsigned char ip[4])
53 {
54 register int i;
55 if (ipv4_null(cidr)) return 1;
56 for (i = 0; i < 4; i++) {
57 if (cidr[i] != (ip[i] & cidr[4+i]))
58 return 0;
59 }
60 return 1;
61 }
ipv4_cidr(char * str,unsigned char cidr[8])62 static int inline ipv4_cidr(char *str, unsigned char cidr[8])
63 {
64 int r;
65 str_t s;
66 char *p;
67
68 /* like ipv4_scan but parses a CIDR number */
69 str_init(s);
70 str_copy(s, str);
71 for (p = str(s); *p && *p != '/'; p++);
72 if (*p == '/') {
73 *p = 0; p++;
74 if (!ipv4_scan(str(s), cidr)) {
75 mem_free(str(s));
76 return 0;
77 }
78 for (r = 0; p[r]; r++)
79 if (p[r] == '.' && ipv4_scan(p, cidr+4)) {
80 /* form of IN/IN */
81 mem_free(str(s));
82 return 8;
83 }
84 /* must be in cidr notation (really) */
85 r = atoi(p);
86 if (r == -1) {
87 mem_free(str(s));
88 return 0;
89 }
90 cidr[4] = cidr[5] = cidr[6] = cidr[7] = 0xFF;
91 if (r < 8) {
92 cidr[4] = (0xFF << (8 - r));
93 cidr[5] = cidr[6] = cidr[7] = 0x00;
94 } else if (r < 16) {
95 cidr[5] = (0xFF << (16 - r));
96 cidr[6] = cidr[7] = 0x00;
97 } else if (r < 24) {
98 cidr[6] = (0xFF << (24 - r));
99 cidr[7] = 0x00;
100 } else {
101 cidr[7] = (0xFF << (32 - r));
102 }
103 mem_free(str(s));
104 return 8;
105 } else {
106 mem_free(str(s));
107 return 0;
108 }
109 }
socket_bind4(int fd,unsigned char ip[4],int port)110 static int inline socket_bind4(int fd, unsigned char ip[4], int port)
111 {
112 struct sockaddr_in sin;
113
114 memzero(&sin, sizeof(sin));
115
116 sin.sin_family = PF_INET;
117 /* Clib */
118 sin.sin_port = htons(port);
119 memcpy(&sin.sin_addr, ip, 4);
120
121 return bind(fd, (struct sockaddr *)&sin, sizeof(sin));
122 }
socket_bind4_reuse(int fd,unsigned char ip[4],int port)123 static int inline socket_bind4_reuse(int fd, unsigned char ip[4], int port)
124 {
125 int opt = 1;
126 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
127 return socket_bind4(fd, ip, port);
128 }
socket_peer4(int fd,unsigned char ip[4],int * port)129 static int inline socket_peer4(int fd, unsigned char ip[4], int *port)
130 {
131 struct sockaddr_in sin;
132 int silen;
133
134 memzero(&sin, sizeof(sin));
135
136 silen = sizeof(sin);
137 sin.sin_family = PF_INET;
138 if (getpeername(fd, (struct sockaddr *)&sin, (int *)&silen) == -1) {
139 return 0;
140 }
141
142 if (sin.sin_family != PF_INET)
143 return 0;
144
145 memcpy(ip, &sin.sin_addr, 4);
146 *port = ntohs(sin.sin_port);
147 return 1;
148 }
socket_local4(int fd,unsigned char ip[4],int * port)149 static int inline socket_local4(int fd, unsigned char ip[4], int *port)
150 {
151 struct sockaddr_in sin;
152 int silen;
153
154 memzero(&sin, sizeof(sin));
155
156 silen = sizeof(sin);
157 sin.sin_family = PF_INET;
158 if (getsockname(fd, (struct sockaddr *)&sin, (int *)&silen) == -1) {
159 return 0;
160 }
161
162 if (sin.sin_family != PF_INET)
163 return 0;
164
165 memcpy(ip, &sin.sin_addr, 4);
166 *port = ntohs(sin.sin_port);
167 return 1;
168 }
169
socket_tcp4(void)170 static int inline socket_tcp4(void)
171 {
172 int fd;
173
174 fd = socket(PF_INET, SOCK_STREAM, 0);
175 if (fd == -1) return -1;
176 if (ndelay_on(fd) == -1) { close(fd); return -1; }
177 return fd;
178 }
socket_udp4(void)179 static int inline socket_udp4(void)
180 {
181 int fd;
182
183 fd = socket(PF_INET, SOCK_DGRAM, 0);
184 if (fd == -1) return -1;
185 if (ndelay_on(fd) == -1) { close(fd); return -1; }
186 return fd;
187 }
socket_accept4(int s,unsigned char ip[4],int * port)188 static int inline socket_accept4(int s, unsigned char ip[4], int *port)
189 {
190 struct sockaddr_in sa;
191 int dummy = sizeof sa;
192 int r;
193
194 memzero(&sa, sizeof(sa));
195
196 r = accept(s, (struct sockaddr *)&sa, &dummy);
197 if (r == -1) return -1;
198
199 memcpy(ip, &sa.sin_addr, 4);
200 *port = ntohs(sa.sin_port);
201
202 return r;
203 }
socket_recv4(int s,char * buf,int len,unsigned char ip[4],int * port)204 static int inline socket_recv4(int s, char *buf, int len, unsigned char ip[4], int *port)
205 {
206 struct sockaddr_in sa;
207 int dummy = sizeof sa;
208 int r;
209
210 memzero(&sa, sizeof(sa));
211
212 r = recvfrom(s, buf, len, 0, (struct sockaddr *)&sa, &dummy);
213 if (r == -1) return -1;
214
215 memcpy(ip, &sa.sin_addr, 4);
216 *port = ntohs(sa.sin_port);
217
218 return r;
219 }
socket_send4(int s,const char * buf,int len,const unsigned char ip[4],int port)220 static int inline socket_send4(int s, const char *buf, int len, const unsigned char ip[4], int port)
221 {
222 struct sockaddr_in sa;
223
224 memzero(&sa, sizeof(sa));
225
226 sa.sin_family = PF_INET;
227 sa.sin_port = htons(port);
228 memcpy(&sa.sin_addr, ip, 4);
229
230 return sendto(s, buf, len, 0, (struct sockaddr *)&sa, sizeof(sa));
231 }
232
233 #endif
234