1 /*
2 20131206
3 Jan Mojzis
4 Public domain.
5 */
6 
7 #include <sys/types.h>
8 #include <sys/param.h>
9 #include <sys/socket.h>
10 #include <netinet/in.h>
11 #include <unistd.h>
12 #include "e.h"
13 #include "byte.h"
14 #include "hasipv6.h"
15 #include "xsocket.h"
16 
xsocket_accept6(int s,unsigned char * ip,unsigned char * port,long long * id)17 static int xsocket_accept6(int s, unsigned char *ip, unsigned char *port, long long *id) {
18 
19 #ifdef HASIPV6
20     struct sockaddr_in6 sa;
21     socklen_t salen = sizeof sa;
22     int fd;
23 
24     byte_zero(&sa, sizeof sa);
25     fd = accept(s, (struct sockaddr *)&sa, &salen);
26     if (fd == -1) return -1;
27 
28     if (((struct sockaddr *)&sa)->sa_family != PF_INET6) { close(fd); errno = EPROTO; return -1; }
29 
30     if (ip) byte_copy(ip, 16, &sa.sin6_addr);
31     if (port) byte_copy(port, 2, &sa.sin6_port);
32     if (id) *id = sa.sin6_scope_id;
33     return fd;
34 #else
35     errno = EPROTONOSUPPORT;
36     return -1;
37 #endif
38 
39 }
40 
xsocket_accept4(int s,unsigned char * ip,unsigned char * port,long long * id)41 static int xsocket_accept4(int s, unsigned char *ip, unsigned char *port, long long *id) {
42 
43     struct sockaddr_in sa;
44     socklen_t salen = sizeof sa;
45     int fd;
46 
47     byte_zero(&sa, sizeof sa);
48     fd = accept(s, (struct sockaddr *)&sa, &salen);
49     if (fd == -1) return -1;
50 
51     if (((struct sockaddr *)&sa)->sa_family != PF_INET) { close(fd); errno = EPROTO; return -1; }
52 
53     if (ip) byte_copy(ip, 12, "\0\0\0\0\0\0\0\0\0\0\377\377");
54     if (ip) byte_copy(ip + 12, 4, &sa.sin_addr);
55     if (port) byte_copy(port, 2, &sa.sin_port);
56     if (id) *id = 0;
57     return fd;
58 }
59 
xsocket_accept(int fd,int type,unsigned char * ip,unsigned char * port,long long * id)60 int xsocket_accept(int fd, int type, unsigned char *ip, unsigned char *port, long long *id) {
61 
62     if (type == XSOCKET_V4) {
63         return xsocket_accept4(fd, ip, port, id);
64     }
65     if (type == XSOCKET_V6) {
66         return xsocket_accept6(fd, ip, port, id);
67     }
68     errno = EPROTO;
69     return -1;
70 }
71