ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/s_bsd_win32.c
Revision: 34
Committed: Sun Oct 2 21:05:51 2005 UTC (18 years, 5 months ago) by lusky
Content type: text/x-csrc
File size: 12777 byte(s)
Log Message:
create 7.2 branch, we can move/rename it as needed.


File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * s_bsd_win32.c: Winsock WSAAsyncSelect() compatible network routines.
4 *
5 * Copyright (C) 2002 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include <iphlpapi.h>
27 #include "fdlist.h"
28 #include "ircd.h"
29 #include "s_bsd.h"
30 #include "common.h"
31 #include "client.h"
32 #include "numeric.h"
33 #include "restart.h"
34
35 #define WM_SOCKET (WM_USER + 0)
36 #define WM_DNS (WM_USER + 1)
37 #define WM_REHASH (WM_USER + 0x100)
38 #define WM_REMOTD (WM_USER + 0x101)
39
40 static HWND wndhandle;
41 static dlink_list dns_queries = {NULL, NULL, 0};
42 static dlink_node *setupfd_hook;
43 static DWORD (WINAPI * _GetNetworkParams) (PFIXED_INFO, PULONG) = NULL;
44
45 extern int main(int, char *[]);
46
47 /*
48 * Initial entry point for Win32 GUI applications, called by the C runtime.
49 *
50 * It should be only a wrapper for main(), since when compiled as a console
51 * application, main() is called instead.
52 */
53 int WINAPI
54 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
55 LPSTR lpCmdLine, int nCmdShow)
56 {
57 /* Do we really need these pidfile, logfile etc arguments?
58 * And we are not on a console, so -help or -foreground is meaningless. */
59
60 char *argv[2] = {"ircd", NULL};
61
62 return main(1, argv);
63 }
64
65 /*
66 * Handler for Win32 messages.
67 */
68 static LRESULT CALLBACK
69 hybrid_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
70 {
71 switch (uMsg)
72 {
73 case WM_SOCKET:
74 {
75 fde_t *F = lookup_fd((int) wParam);
76 PF *hdl;
77
78 if (F != NULL && F->flags.open)
79 switch (WSAGETSELECTEVENT(lParam))
80 {
81 case FD_ACCEPT:
82 case FD_CLOSE:
83 case FD_READ:
84 if ((hdl = F->read_handler) != NULL)
85 {
86 F->read_handler = NULL;
87 hdl(F, F->read_data);
88 if (F->flags.open)
89 comm_setselect(F, 0, NULL, NULL, 0);
90 }
91 break;
92
93 case FD_CONNECT:
94 case FD_WRITE:
95 if ((hdl = F->write_handler) != NULL)
96 {
97 F->write_handler = NULL;
98 hdl(F, F->write_data);
99 if (F->flags.open)
100 comm_setselect(F, 0, NULL, NULL, 0);
101 }
102 }
103
104 return 0;
105 }
106
107 case WM_DNS:
108 {
109 dlink_node *ptr;
110
111 DLINK_FOREACH(ptr, dns_queries.head)
112 if (((struct DNSQuery *) ptr->data)->handle == wParam)
113 {
114 struct DNSQuery *query = ptr->data;
115 struct DNSReply *reply = NULL;
116
117 dlinkDelete(&query->node, &dns_queries);
118
119 if (WSAGETASYNCERROR(lParam) == 0)
120 {
121 struct hostent *h = (struct hostent *) &query->reply;
122 static struct DNSReply _reply;
123 reply = &_reply;
124
125 reply->h_name = h->h_name;
126 reply->addr.ss.ss_family = h->h_addrtype;
127
128 switch (h->h_addrtype)
129 {
130 case AF_INET:
131 memcpy(&((struct sockaddr_in *) &reply->addr)->sin_addr,
132 h->h_addr_list[0], h->h_length);
133 break;
134
135 #ifdef IPV6
136 case AF_INET6:
137 memcpy(&((struct sockaddr_in6 *) &reply->addr)->sin6_addr,
138 h->h_addr_list[0], h->h_length);
139 break;
140 #endif
141
142 default: /* shouldn't happen */
143 reply = NULL;
144 }
145 }
146
147 query->callback(query->ptr, reply);
148 return 0;
149 }
150
151 return 0;
152 }
153
154 case WM_REHASH:
155 dorehash = 1;
156 return 0;
157
158 case WM_REMOTD:
159 doremotd = 1;
160 return 0;
161
162 case WM_DESTROY:
163 PostQuitMessage(0);
164 return 0;
165
166 default:
167 return DefWindowProc(hwnd, uMsg, wParam, lParam);
168 }
169 }
170
171 /*
172 * Associates a window message with the given socket.
173 * This will automagically switch it to nonblocking.
174 */
175 static void *
176 setup_winsock_fd(va_list args)
177 {
178 int fd = va_arg(args, int);
179
180 WSAAsyncSelect(fd, wndhandle, WM_SOCKET, 0);
181
182 return pass_callback(setupfd_hook, fd);
183 }
184
185 /*
186 * Initialize Winsock, create a window handle.
187 */
188 void
189 init_netio(void)
190 {
191 WNDCLASS wndclass;
192 WSADATA wsa;
193 HMODULE lib;
194
195 /* Initialize Winsock networking */
196 if (WSAStartup(0x101, &wsa) != 0)
197 {
198 MessageBox(NULL, "Cannot initialize Winsock -- terminating ircd",
199 NULL, MB_OK | MB_ICONERROR);
200 exit(1);
201 }
202
203 /* First, we need a class for our window that has message handler
204 * set to hybrid_wndproc() */
205 memset(&wndclass, 0, sizeof(wndclass));
206
207 wndclass.lpfnWndProc = hybrid_wndproc;
208 wndclass.hInstance = GetModuleHandle(NULL);
209 wndclass.lpszClassName = PACKAGE_NAME;
210
211 RegisterClass(&wndclass);
212
213 /* Now, initialize the window */
214 wndhandle = CreateWindow(PACKAGE_NAME, NULL, 0,
215 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
216 NULL, NULL, wndclass.hInstance, NULL);
217
218 if (!wndhandle)
219 {
220 MessageBox(NULL, "Cannot allocate window handle -- terminating ircd",
221 NULL, MB_OK | MB_ICONERROR);
222 exit(1);
223 }
224
225 /* Set up a timer which will periodically post a message to our queue.
226 * This way, ircd won't wait infinitely for a network event */
227 SetTimer(wndhandle, 0, SELECT_DELAY, NULL);
228
229 if ((lib = LoadLibrary("IPHLPAPI.DLL")) != NULL)
230 _GetNetworkParams = GetProcAddress(lib, "GetNetworkParams");
231
232 setupfd_hook = install_hook(setup_socket_cb, setup_winsock_fd);
233 }
234
235 /*
236 * comm_setselect
237 *
238 * This is a needed exported function which will be called to register
239 * and deregister interest in a pending IO state for a given FD.
240 */
241 void
242 comm_setselect(fde_t *F, unsigned int type, PF *handler,
243 void *client_data, time_t timeout)
244 {
245 int new_events = 0;
246
247 if ((type & COMM_SELECT_READ))
248 {
249 F->read_handler = handler;
250 F->read_data = client_data;
251 }
252
253 if ((type & COMM_SELECT_WRITE))
254 {
255 F->write_handler = handler;
256 F->write_data = client_data;
257 }
258
259 new_events = (F->read_handler ? (FD_ACCEPT | FD_CLOSE | FD_READ) : 0) |
260 (F->write_handler ? (FD_CONNECT | FD_WRITE) : 0);
261
262 if (timeout != 0)
263 F->timeout = CurrentTime + (timeout / 1000);
264
265 if (new_events != F->evcache)
266 {
267 WSAAsyncSelect(F->fd, wndhandle, WM_SOCKET, new_events);
268 F->evcache = new_events;
269 }
270 }
271
272 /*
273 * Waits until a message is posted in our window queue and deals with it.
274 */
275 void
276 comm_select(void)
277 {
278 MSG msg;
279
280 if (!GetMessage(&msg, NULL, 0, 0))
281 server_die("WM_QUIT received", NO);
282
283 set_time();
284
285 DispatchMessage(&msg);
286 }
287
288 /* This is our win32 super-light resolver ;) */
289
290 void
291 delete_resolver_queries(const struct DNSQuery *query)
292 {
293 WSACancelAsyncRequest(query->handle);
294 dlinkDelete(&query->node, &dns_queries);
295 }
296
297 void
298 gethost_byname_type(const char *name, struct DNSQuery *query, int type)
299 {
300 gethost_byname(name, query);
301 }
302
303 void
304 gethost_byname(const char *name, struct DNSQuery *query)
305 {
306 query->handle = WSAAsyncGetHostByName(wndhandle, WM_DNS, name, query->reply,
307 sizeof(query->reply));
308
309 if (!query->handle)
310 query->callback(query->ptr, NULL);
311 else
312 dlinkAdd(query, &query->node, &dns_queries);
313 }
314
315 void
316 gethost_byaddr(const struct irc_ssaddr *addr, struct DNSQuery *query)
317 {
318 query->handle = WSAAsyncGetHostByAddr(
319 wndhandle, WM_DNS,
320 #ifdef IPV6
321 addr.ss.ss_family == AF_INET6 ? &((struct sockaddr_in6*)addr)->sin6_addr) :
322 #endif
323 &((struct sockaddr_in *) addr)->sin_addr,
324 #ifdef IPV6
325 addr.ss.ss_family == AF_INET6 ? sizeof(struct in6_addr) :
326 #endif
327 sizeof(struct in_addr),
328 addr->ss.ss_family, query->reply, sizeof(query->reply)
329 );
330
331 if (!query->handle)
332 query->callback(query->ptr, NULL);
333 else
334 dlinkAdd(query, &query->node, &dns_queries);
335 }
336
337 void
338 report_dns_servers(struct Client *source_p)
339 {
340 FIXED_INFO *FixedInfo;
341 ULONG ulOutBufLen;
342 IP_ADDR_STRING *ip;
343
344 if (_GetNetworkParams == NULL)
345 return;
346
347 FixedInfo = MyMalloc(sizeof(FIXED_INFO));
348 ulOutBufLen = sizeof(FIXED_INFO);
349
350 if (_GetNetworkParams(FixedInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW)
351 {
352 MyFree(FixedInfo);
353 FixedInfo = MyMalloc(ulOutBufLen);
354
355 if (_GetNetworkParams(FixedInfo, &ulOutBufLen) != ERROR_SUCCESS)
356 return;
357 }
358
359 for (ip = &FixedInfo->DnsServerList; ip != NULL; ip = ip->Next)
360 sendto_one(source_p, form_str(RPL_STATSALINE), me.name, source_p->name,
361 ip->IpAddress.String);
362
363 MyFree(FixedInfo);
364 }
365
366 /* Copyright (C) 2001 Free Software Foundation, Inc.
367 *
368 * Get name and information about current kernel.
369 */
370 int
371 uname(struct utsname *uts)
372 {
373 enum { WinNT, Win95, Win98, WinUnknown };
374 OSVERSIONINFO osver;
375 SYSTEM_INFO sysinfo;
376 DWORD sLength;
377 DWORD os = WinUnknown;
378
379 memset(uts, 0, sizeof(*uts));
380
381 osver.dwOSVersionInfoSize = sizeof (osver);
382 GetVersionEx (&osver);
383 GetSystemInfo (&sysinfo);
384
385 switch (osver.dwPlatformId)
386 {
387 case VER_PLATFORM_WIN32_NT: /* NT, Windows 2000 or Windows XP */
388 if (osver.dwMajorVersion == 4)
389 strcpy (uts->sysname, "Windows NT4x"); /* NT4x */
390 else if (osver.dwMajorVersion <= 3)
391 strcpy (uts->sysname, "Windows NT3x"); /* NT3x */
392 else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion < 1)
393 strcpy (uts->sysname, "Windows 2000"); /* 2k */
394 else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2)
395 strcpy (uts->sysname, "Windows 2003"); /* 2003 */
396 else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 1)
397 strcpy (uts->sysname, "Windows XP"); /* XP */
398 os = WinNT;
399 break;
400
401 case VER_PLATFORM_WIN32_WINDOWS: /* Win95, Win98 or WinME */
402 if ((osver.dwMajorVersion > 4) ||
403 ((osver.dwMajorVersion == 4) && (osver.dwMinorVersion > 0)))
404 {
405 if (osver.dwMinorVersion >= 90)
406 strcpy (uts->sysname, "Windows ME"); /* ME */
407 else
408 strcpy (uts->sysname, "Windows 98"); /* 98 */
409 os = Win98;
410 }
411 else
412 {
413 strcpy (uts->sysname, "Windows 95"); /* 95 */
414 os = Win95;
415 }
416 break;
417
418 case VER_PLATFORM_WIN32s: /* Windows 3.x */
419 strcpy (uts->sysname, "Windows");
420 break;
421 }
422
423 sprintf (uts->version, "%ld.%02ld",
424 osver.dwMajorVersion, osver.dwMinorVersion);
425
426 if (osver.szCSDVersion[0] != '\0' &&
427 (strlen (osver.szCSDVersion) + strlen (uts->version) + 1) <
428 sizeof (uts->version))
429 {
430 strcat (uts->version, " ");
431 strcat (uts->version, osver.szCSDVersion);
432 }
433
434 sprintf (uts->release, "build %ld", osver.dwBuildNumber & 0xFFFF);
435
436 switch (sysinfo.wProcessorArchitecture)
437 {
438 case PROCESSOR_ARCHITECTURE_PPC:
439 strcpy (uts->machine, "ppc");
440 break;
441 case PROCESSOR_ARCHITECTURE_ALPHA:
442 strcpy (uts->machine, "alpha");
443 break;
444 case PROCESSOR_ARCHITECTURE_MIPS:
445 strcpy (uts->machine, "mips");
446 break;
447 case PROCESSOR_ARCHITECTURE_INTEL:
448 /*
449 * dwProcessorType is only valid in Win95 and Win98 and WinME
450 * wProcessorLevel is only valid in WinNT
451 */
452 switch (os)
453 {
454 case Win95:
455 case Win98:
456 switch (sysinfo.dwProcessorType)
457 {
458 case PROCESSOR_INTEL_386:
459 case PROCESSOR_INTEL_486:
460 case PROCESSOR_INTEL_PENTIUM:
461 sprintf (uts->machine, "i%ld", sysinfo.dwProcessorType);
462 break;
463 default:
464 strcpy (uts->machine, "i386");
465 break;
466 }
467 break;
468 case WinNT:
469 switch(sysinfo.wProcessorArchitecture)
470 {
471 case PROCESSOR_ARCHITECTURE_INTEL:
472 sprintf (uts->machine, "x86(%d)", sysinfo.wProcessorLevel);
473 break;
474 case PROCESSOR_ARCHITECTURE_IA64:
475 sprintf (uts->machine, "ia64(%d)", sysinfo.wProcessorLevel);
476 break;
477 #ifdef PROCESSOR_ARCHITECTURE_AMD64
478 case PROCESSOR_ARCHITECTURE_AMD64:
479 sprintf (uts->machine, "x86_64(%d)", sysinfo.wProcessorLevel);
480 break;
481 #endif
482 default:
483 sprintf (uts->machine, "unknown(%d)", sysinfo.wProcessorLevel);
484 break;
485 }
486 break;
487 default:
488 strcpy (uts->machine, "unknown");
489 break;
490 }
491 break;
492 default:
493 strcpy (uts->machine, "unknown");
494 break;
495 }
496
497 sLength = sizeof (uts->nodename) - 1;
498 GetComputerName (uts->nodename, &sLength);
499 return 0;
500 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision