/[cvs]/eggdrop1.9/testcode/my_socket.c
ViewVC logotype

Contents of /eggdrop1.9/testcode/my_socket.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (show annotations) (download) (as text)
Fri Aug 9 23:42:04 2002 UTC (16 years, 7 months ago) by stdarg
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +24 -6 lines
File MIME type: text/x-chdr
* Some updates to network code

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/socket.h>
4 #include <netinet/in.h>
5 #include <arpa/inet.h>
6 #include <fcntl.h>
7 #include <errno.h>
8
9 #include "my_socket.h"
10
11 #define DO_IPV6
12 #define DO_IPV4
13
14 typedef struct {
15 int len;
16 int family;
17 union {
18 struct sockaddr addr;
19 #ifdef DO_IPV4
20 struct sockaddr_in ipv4;
21 #endif
22 #ifdef DO_IPV6
23 struct sockaddr_in6 ipv6;
24 #endif
25 } u;
26 } sockname_t;
27
28 static int socket_name(sockname_t *name, char *ipaddr, int port)
29 {
30 memset(name, 0, sizeof(*name));
31
32 if (!ipaddr) {
33 #ifdef DO_IPV6
34 ipaddr = "::";
35 #else
36 ipaddr = "0.0.0.0";
37 #endif
38 }
39
40 #ifdef DO_IPV6
41 if (inet_pton(AF_INET6, ipaddr, &name->u.ipv6.sin6_addr) > 0) {
42 name->len = sizeof(name->u.ipv6);
43 name->family = PF_INET6;
44 name->u.ipv6.sin6_port = htons(port);
45 name->u.ipv6.sin6_family = AF_INET6;
46 return(0);
47 }
48 #endif
49
50 #ifdef DO_IPV4
51 if (inet_pton(AF_INET, ipaddr, &name->u.ipv4.sin_addr) > 0) {
52 name->len = sizeof(name->u.ipv4);
53 name->family = PF_INET;
54 name->u.ipv4.sin_port = htons(port);
55 name->u.ipv4.sin_family = AF_INET;
56 return(0);
57 }
58 #endif
59
60 return(-1);
61 }
62
63 int socket_get_peer_name(int sock, char **peer_ip, int *peer_port)
64 {
65 sockname_t name;
66 int namelen;
67
68 *peer_ip = NULL;
69 *peer_port = 0;
70
71 #ifdef DO_IPV4
72 namelen = sizeof(name.u.ipv4);
73 if (!getpeername(sock, &name.u.addr, &namelen) && namelen == sizeof(name.u.ipv4)) {
74 *peer_ip = (char *)malloc(32);
75 *peer_port = ntohs(name.u.ipv4.sin_port);
76 inet_ntop(AF_INET, &name.u.ipv4.sin_addr, *peer_ip, 32);
77 return(0);
78 }
79 #endif
80 #ifdef DO_IPV6
81 namelen = sizeof(name.u.ipv6);
82 if (!getpeername(sock, &name.u.addr, &namelen) && namelen == sizeof(name.u.ipv6)) {
83 *peer_ip = (char *)malloc(128);
84 *peer_port = ntohs(name.u.ipv6.sin6_port);
85 inet_ntop(AF_INET6, &name.u.ipv6.sin6_addr, *peer_ip, 128);
86 return(0);
87 }
88 #endif
89
90 return(-1);
91 }
92
93 int socket_get_error(int sock)
94 {
95 int size, err;
96
97 size = sizeof(int);
98 err = 0;
99 getsockopt(sock, SOL_PACKET, SO_ERROR, &err, &size);
100 return(err);
101 }
102
103 int socket_accept(int sock, char **peer_ip, int *peer_port)
104 {
105 int newsock, len;
106 sockname_t name;
107
108 *peer_ip = NULL;
109 *peer_port = 0;
110 memset(&name, 0, sizeof(name));
111 len = sizeof(name.u);
112 newsock = accept(sock, &name.u.addr, &len);
113 #ifdef DO_IPV4
114 if (len == sizeof(name.u.ipv4)) {
115 *peer_ip = (char *)malloc(32);
116 *peer_port = ntohs(name.u.ipv4.sin_port);
117 inet_ntop(AF_INET, &name.u.ipv4.sin_addr, *peer_ip, 32);
118 }
119 #endif
120 #ifdef DO_IPV6
121 if (len == sizeof(name.u.ipv6)) {
122 *peer_ip = (char *)malloc(128);
123 *peer_port = ntohs(name.u.ipv6.sin6_port);
124 inet_ntop(AF_INET6, &name.u.ipv6.sin6_addr, *peer_ip, 128);
125 }
126 #endif
127 return(newsock);
128 }
129
130 /* Return values: */
131 /* -1: invalid ip address */
132 /* -2: socket() failure */
133 /* -3: bind() failure */
134 /* -4: connect() failure */
135 int socket_create(char *dest_ip, int dest_port, char *src_ip, int src_port, int flags)
136 {
137 int sock, pfamily;
138 sockname_t dest_name, src_name;
139
140 /* Resolve the ip addresses. */
141 socket_name(&dest_name, dest_ip, dest_port);
142 socket_name(&src_name, src_ip, src_port);
143
144 if (src_ip || src_port) flags |= SOCKET_BIND;
145
146 if (flags & SOCKET_CLIENT) pfamily = dest_name.family;
147 else if (flags & SOCKET_SERVER) pfamily = src_name.family;
148 else {
149 errno = EADDRNOTAVAIL;
150 return(-1);
151 }
152
153 /* Create the socket. */
154 if (flags & SOCKET_UDP) sock = socket(pfamily, SOCK_DGRAM, 0);
155 else sock = socket(pfamily, SOCK_STREAM, 0);
156
157 if (sock < 0) return(-2);
158
159 if (flags & SOCKET_NONBLOCK) socket_set_nonblock(sock, 1);
160
161 /* Do the bind if necessary. */
162 if (flags & (SOCKET_SERVER|SOCKET_BIND)) {
163 int yes = 1;
164
165 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
166 if (bind(sock, &src_name.u.addr, src_name.len) != 0) return(-3);
167 if (flags & SOCKET_SERVER) listen(sock, 50);
168 }
169
170 if (flags & SOCKET_CLIENT) {
171 if (connect(sock, &dest_name.u.addr, dest_name.len) != 0) {
172 if (errno != EINPROGRESS) return(-4);
173 }
174 }
175
176 errno = 0;
177
178 /* Yay, we're done. */
179 return(sock);
180 }
181
182 int socket_set_nonblock(int sock, int value)
183 {
184 int oldflags = fcntl(sock, F_GETFL, 0);
185 if (oldflags == -1) return -1;
186 if (value != 0) oldflags |= O_NONBLOCK;
187 else oldflags &= ~O_NONBLOCK;
188
189 return fcntl(sock, F_SETFL, oldflags);
190 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23