static void ParseMasterArgs(netadr_t *broadcast) { void *data; ssize_t len; void (*parse)(void *, size_t, size_t); size_t chunk; char *s, *p; int i, argc; Cmd_TokenizeString(m_servers.args, qfalse); argc = Cmd_Argc(); if (!argc) { // default action to take when no URLs are given ParseAddressBook(); broadcast->type = NA_BROADCAST; broadcast->port = BigShort(PORT_SERVER); return; } for (i = 0; i < argc; i++) { s = Cmd_Argv(i); if (!*s) continue; // parse binary format specifier parse = ParsePlain; chunk = 0; if (*s == '+' || *s == '-') { parse = ParseBinary; chunk = strtoul(s, &p, 10); if (s == p) { chunk = 6; s = p + 1; } else { if (chunk < 6) goto ignore; s = p; } } if (!strncmp(s, "file://", 7)) { len = FS_LoadFile(s + 7, &data); if (len < 0) continue; (*parse)(data, len, chunk); FS_FreeFile(data); continue; } if (!strncmp(s, "http://", 7)) { #if USE_CURL len = HTTP_FetchFile(s + 7, &data); if (len < 0) continue; (*parse)(data, len, chunk); Z_Free(data); #else Com_Printf("Can't fetch '%s', no HTTP support compiled in.\n", s); #endif continue; } if (!strncmp(s, "favorites://", 12)) { ParseAddressBook(); continue; } if (!strncmp(s, "broadcast://", 12)) { broadcast->type = NA_BROADCAST; broadcast->port = BigShort(PORT_SERVER); continue; } if (!strncmp(s, "quake2://", 9)) { AddServer(NULL, s + 9); continue; } ignore: Com_Printf("Ignoring invalid master URL: %s\n", s); } }
/* ** CreateAsc( ) --- Create an association. ** ** Inputs: ** asipc ASSOC_IPC for association ** name name of server creating association. ** Output: ** returns TRUE if succeeds. ** ** GClisten( ) calls CreateAsc( ) when a server wishes to create ** a new association. CrateAsc( ) allocates the resources required by ** the association, and exposes shared information available to other processes. ** The only requirements are that it create four handles in the ASSOC_IPC: ** standard send, standard receive, expedited send, and expeditied receive. ** These handles are the only members created here used by gcacl. In ** this implementation handles to anonymous pipes are used. ** ** If there are no existing connections to the server spicified in the ** name parameter, CreateAsc( ) creates the server specific resources and ** adds the server to the internally maintained list of servers. A memory mapped ** mapped file is created for passing information between the client and ** server. This file contains a temporary area for passing process id and ** handles which the client needs to copy to its own ASSOC_IPC. It also ** contains and array of assoc_info structures. These structures contain ** information that must be shared per connection for the duration of each ** association. A mutex is created to protect access to the temporary area. ** The temporary area is only used when a connectionis first established ** to copy handles to the pipes and other information to the requester's ** ASSOC_IPC. ** ** Two events are also created to arbitrate the connection process. When ** a server is ready for a connection, it signals a "listening event". ** and waits for a client to set a requesting event. Before connecting ** a client waits on the listening event before trying to connect. When ** the client tries to connect it sets a requesting event to tell the server ** that a client has connected. ** ** The names for the memory mapped file, the mutex, and the events are ** based on the server name. ** ** History: ** 10-Dec-98 (lunbr01) Bug 94183 ** Eliminate use of *Ct fields (using PeekNamedPipe instead). */ BOOL CreateAsc(ASSOC_IPC * asipc, char *name ) { HANDLE hMapping; /* for memory mapped file */ static HANDLE hMutex; /* for memory mapped file */ ASSOC_IPC *asipc_temp; ASSOC_INFO *assoc_info; struct _Asc_ipc_area *svr_ipc_area; SERVER_ENTRY *server; short i; SECURITY_ATTRIBUTES sa; /* Set up security attributes */ sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* If there are no existing connections to this server. Open the ** memory mapped file, events, and mutex for this server. */ if( NULL == ( server = LookUpServer( name ) ) ) { char ReqEventName[MAXPNAME + 4 ]; char LstEventName[MAXPNAME + 4 ]; if ((hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, sizeof( struct _Asc_ipc_area ), name )) == NULL) { DWORD err = GetLastError( ); return FALSE ; } if (NULL == (svr_ipc_area= (struct _Asc_ipc_area *)MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 ) ) ) { return FALSE; } /* Create an event that will be signaled when an ** association is requested. */ wsprintf( ReqEventName, "%s-%s", name, "req" ); wsprintf( LstEventName, "%s-%s", name, "lst" ); /* Create SERVER_ENTRY */ server = AddServer( name, svr_ipc_area, hMapping, CreateEvent( &sa, FALSE, FALSE, ReqEventName ), CreateEvent( &sa, FALSE, FALSE, LstEventName ) ); /* Create a mutex to coordinate access to asipc_temp */ hMutex = CreateMutex( &sa, FALSE, name ); /* Create a proces handle so other processes can use DuplicateHandle */ svr_ipc_area->nProcId = GetCurrentProcessId( ); } /* Get a pointer to the Memory mapped file for this server. */ svr_ipc_area = server->lpMapping; if ( server->nConnections == MAX_ASSOCS ) /* no more assocs allowed */ return FALSE ; asipc_temp = &( svr_ipc_area->asipc ); assoc_info = (ASSOC_INFO *)&( svr_ipc_area->assoc_info ); /* Make sure that it is safe to change temporary connection info. ** Copy the connection information the local ASSOC_IPC. */ WaitForSingleObject( hMutex, INFINITE ); /* Find a valid id and set up the assoc_info. */ for( i = 0; i < MAX_ASSOCS; i++ ) { if ( assoc_info[i].refs == 0 ) break; } asipc->IpcInternal.hMapping = hMapping; /* for save and restore */ asipc->IpcInternal.AssocInfo = &assoc_info[i]; asipc_temp->IpcInternal.AscID = asipc->IpcInternal.AscID = i; assoc_info[i].bPipesClosed = FALSE; assoc_info[i].refs++; /* Set the AssocInfo */ assoc_info[i].out_buffer_size = Pipe_buffer_size; assoc_info[i].in_buffer_size = Pipe_buffer_size; if(!CreatePipe( &asipc->RcvStdChan, &asipc_temp->SndStdChan, &sa, Pipe_buffer_size ) || !CreatePipe( &asipc_temp->RcvStdChan, &asipc->SndStdChan, &sa, Pipe_buffer_size ) || !CreatePipe( &asipc->RcvExpChan, &asipc_temp->SndExpChan, &sa, Pipe_buffer_size ) || !CreatePipe( &asipc_temp->RcvExpChan, &asipc->SndExpChan, &sa, Pipe_buffer_size ) ) { CloseAsc( asipc ); CloseAsc( asipc_temp ); return FALSE ; } /* We need to duplicate the client side of standard read handle asipc_temp->RcvStdChan for PeekNamedPipe() because it gets closed by the DUPLICATE_CLOSE_SOURCE option of DuplicateHandle() after a front end client connects to the server and duplicates it into their address space. */ if (!DuplicateHandle( GetCurrentProcess(), asipc_temp->RcvStdChan, GetCurrentProcess(), &asipc->ClientReadHandle, GENERIC_READ, TRUE, DUPLICATE_SAME_ACCESS ) ) { CloseAsc( asipc ); CloseAsc( asipc_temp ); return FALSE ; } /* We need to duplicate the server side of standard read handle asipc->RcvStdChan for PeekNamedPipe() in the client because it gets closed by the DUPLICATE_CLOSE_SOURCE option of DuplicateHandle() after a front end client connects to the server and duplicates it into their address space. */ if (!DuplicateHandle( GetCurrentProcess(), asipc->RcvStdChan, GetCurrentProcess(), &asipc_temp->ClientReadHandle, GENERIC_READ, TRUE, DUPLICATE_SAME_ACCESS ) ) { CloseAsc( asipc ); CloseAsc( asipc_temp ); return FALSE ; } ReleaseMutex( hMutex ); /* ** Set up pointer to server and increment the number of connections. */ asipc->IpcInternal.server = server; asipc->IpcInternal.server->nConnections++; return TRUE; }
STATUS OpenAsc(ASSOC_IPC * asipc, char *name, DWORD timeout ) { HANDLE hMapping; HANDLE hMutex; HANDLE hSrcProc; struct _Asc_ipc_area *cli_ipc_area; SERVER_ENTRY *server; /* ** If there are no connections to this server, set up a ** SERVER_ENTRY and open the required resources. */ if ( NULL == ( server = LookUpServer( name) ) ) { char ReqEventName[MAXPNAME + 4 ];/*Event for requesting connection*/ char LstEventName[MAXPNAME + 4 ];/*Event to see server is lstning */ HANDLE revent, levent; /* Create an event that will be signaled when an ** association is requested. */ wsprintf( ReqEventName, "%s-%s", name, "req" ); wsprintf( LstEventName, "%s-%s", name, "lst" ); if( NULL == (revent = OpenEvent( EVENT_ALL_ACCESS, FALSE, ReqEventName ) ) ) return ~OK; if( NULL == (levent = OpenEvent( EVENT_ALL_ACCESS, FALSE, LstEventName ) ) ) { CloseHandle( revent ); return ~OK; } if( NULL == (hMapping = OpenFileMapping( FILE_MAP_ALL_ACCESS, TRUE, name ) ) ) { CloseHandle( levent ); CloseHandle( revent ); return ~OK; } if ( NULL == ( cli_ipc_area = (struct _Asc_ipc_area *) MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 ) ) ) { CloseHandle( hMapping ); CloseHandle( levent ); CloseHandle( revent ); return~OK; } if ( PCis_alive( cli_ipc_area->nProcId ) == FALSE ) { UnmapViewOfFile( hMapping ); CloseHandle( hMapping ); CloseHandle( levent ); CloseHandle( revent ); return ~OK; } /* Create SERVER_ENTRY */ server = AddServer( name, cli_ipc_area, hMapping, revent, levent ); } /* Get pointer to memory mapped file with shared data. */ cli_ipc_area = server->lpMapping; /* wait for a server to listen. */ if( WAIT_TIMEOUT == WaitForSingleObject( server->ListeningEvent, timeout == GC_WAIT_FOREVER ? INFINITE : timeout ) ) { return GC_TIME_OUT; } /* ** Setup the ASSOC_IPC */ hMutex = OpenMutex( MUTEX_ALL_ACCESS, TRUE, name ); WaitForSingleObject( hMutex, INFINITE ); asipc->IpcInternal.hMapping = server->hMapping; /*for save and restore*/ asipc->IpcInternal.AscID = cli_ipc_area->asipc.IpcInternal.AscID; asipc->IpcInternal.AssocInfo = &cli_ipc_area->assoc_info[asipc->IpcInternal.AscID]; /* Increment Reference Count for AssocInfo */ asipc->IpcInternal.AssocInfo->refs++; hSrcProc = OpenProcess( PROCESS_DUP_HANDLE, TRUE, cli_ipc_area->nProcId ); /* Get the pipe handles. */ if (!DuplicateHandle( hSrcProc, cli_ipc_area->asipc.SndStdChan, GetCurrentProcess( ), &asipc->SndStdChan, GENERIC_READ | GENERIC_WRITE, TRUE, DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS ) ) { CloseAsc( asipc ); return ~OK; } if (!DuplicateHandle( hSrcProc, cli_ipc_area->asipc.RcvStdChan, GetCurrentProcess( ), &asipc->RcvStdChan, GENERIC_READ | GENERIC_WRITE, TRUE, DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS) ) { CloseAsc( asipc ); return ~OK; } if (!DuplicateHandle( hSrcProc, cli_ipc_area->asipc.SndExpChan, GetCurrentProcess( ), &asipc->SndExpChan, GENERIC_READ | GENERIC_WRITE, TRUE, DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS ) ) { CloseAsc( asipc ); return ~OK; } if (!DuplicateHandle( hSrcProc, cli_ipc_area->asipc.RcvExpChan, GetCurrentProcess( ), &asipc->RcvExpChan, GENERIC_READ | GENERIC_WRITE, TRUE, DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS ) ) { CloseAsc( asipc ); return ~OK; } if (!DuplicateHandle( hSrcProc, cli_ipc_area->asipc.ClientReadHandle, GetCurrentProcess( ), &asipc->ClientReadHandle, GENERIC_READ | GENERIC_WRITE, TRUE, DUPLICATE_CLOSE_SOURCE) ) { CloseAsc( asipc ); return ~OK; } /* Set the handles in the temporary area to NULL before ** releaseing mutex so no one else steals them. */ cli_ipc_area->asipc.SndStdChan = NULL; cli_ipc_area->asipc.RcvStdChan = NULL; cli_ipc_area->asipc.SndExpChan = NULL; cli_ipc_area->asipc.RcvExpChan = NULL; cli_ipc_area->asipc.ClientReadHandle = NULL; /* Point AssocInfo to propper structure in shared memory. */ asipc->IpcInternal.AssocInfo = &( cli_ipc_area->assoc_info[asipc->IpcInternal.AscID] ); /* Set flag to indicate Pipe is open */ asipc->IpcInternal.AssocInfo->bPipesClosed = FALSE; ReleaseMutex( hMutex ); CloseHandle( hMutex ); /* Tell the server that we are ready to request a connection. */ SetEvent( server->RequestingEvent ); server->nConnections++; asipc->IpcInternal.server = server; return OK; }
static void ProcessLine(char *Linebuf) { char *Directive; char *Param1; char *Param2; char *Param3; /* Ignore empty lines */ if (strlen(Linebuf) == 0) return; /* Break up on whitespaces */ if ((Directive = strtok(Linebuf, " \t\n")) == NULL) return; /* Check for a comment line. If found, stop . */ if (Directive[0] == '#') return; /* Check for server line. Check for 3 parameters. */ if (strcasecmp(Directive, "server") == 0) { Param1 = strtok(NULL, " \t\n"); if (NULL == Param1) { syslog(LOG_ERR, "ProcessLine: 'server' missing PDC parameter."); return; } Param2 = strtok(NULL, " \t\n"); if (NULL == Param2) { syslog(LOG_ERR, "ProcessLine: 'server' missing BDC parameter."); return; } Param3 = strtok(NULL, " \t\n"); if (NULL == Param3) { syslog(LOG_ERR, "ProcessLine: 'server' missing domain parameter."); return; } AddServer(Param1, Param2, Param3); return; } /* Check for denyusers line */ if (strcasecmp(Directive, "denyusers") == 0) { Param1 = strtok(NULL, " \t\n"); if (NULL == Param1) { syslog(LOG_ERR, "ProcessLine: A 'denyusers' line needs a filename parameter."); return; } memset(Denyuserpath, '\0', MAXPATHLEN); strncpy(Denyuserpath, Param1, MAXPATHLEN - 1); return; } /* Check for allowusers line */ if (strcasecmp(Directive, "allowusers") == 0) { Param1 = strtok(NULL, " \t\n"); if (NULL == Param1) { syslog(LOG_ERR, "ProcessLine: An 'allowusers' line needs a filename parameter."); return; } memset(Allowuserpath, '\0', MAXPATHLEN); strncpy(Allowuserpath, Param1, MAXPATHLEN - 1); return; } /* Reports error for unknown line */ syslog(LOG_ERR, "ProcessLine: Ignoring '%s' line.", Directive); }