11592Srgrimes/* 21592Srgrimes * Copyright (c) 1983, 1993 31592Srgrimes * The Regents of the University of California. All rights reserved. 41592Srgrimes * 51592Srgrimes * Redistribution and use in source and binary forms, with or without 61592Srgrimes * modification, are permitted provided that the following conditions 71592Srgrimes * are met: 81592Srgrimes * 1. Redistributions of source code must retain the above copyright 91592Srgrimes * notice, this list of conditions and the following disclaimer. 101592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111592Srgrimes * notice, this list of conditions and the following disclaimer in the 121592Srgrimes * documentation and/or other materials provided with the distribution. 13262435Sbrueffer * 3. Neither the name of the University nor the names of its contributors 141592Srgrimes * may be used to endorse or promote products derived from this software 151592Srgrimes * without specific prior written permission. 161592Srgrimes * 171592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271592Srgrimes * SUCH DAMAGE. 281592Srgrimes */ 291592Srgrimes 301592Srgrimes#ifndef lint 3131491Scharnier#if 0 321592Srgrimesstatic char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/4/93"; 3331491Scharnier#endif 3431491Scharnierstatic const char rcsid[] = 3550476Speter "$FreeBSD$"; 361592Srgrimes#endif /* not lint */ 371592Srgrimes 381592Srgrimes/* 391592Srgrimes * Routines to handle insertion, deletion, etc on the table 401592Srgrimes * of requests kept by the daemon. Nothing fancy here, linear 418870Srgrimes * search on a double-linked list. A time is kept with each 421592Srgrimes * entry so that overly old invitations can be eliminated. 431592Srgrimes * 441592Srgrimes * Consider this a mis-guided attempt at modularity 451592Srgrimes */ 461592Srgrimes#include <sys/param.h> 471592Srgrimes#include <sys/time.h> 481592Srgrimes#include <sys/socket.h> 49112998Sjmallett#include <netinet/in.h> 501592Srgrimes#include <protocols/talkd.h> 511592Srgrimes#include <stdio.h> 521592Srgrimes#include <stdlib.h> 531592Srgrimes#include <string.h> 5431491Scharnier#include <syslog.h> 5531491Scharnier#include <unistd.h> 561592Srgrimes 5790261Simp#include "extern.h" 5890261Simp 591592Srgrimes#define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ 601592Srgrimes 611592Srgrimes#define NIL ((TABLE_ENTRY *)0) 621592Srgrimes 63241777Sedstatic struct timeval tp; 641592Srgrimes 651592Srgrimestypedef struct table_entry TABLE_ENTRY; 661592Srgrimes 671592Srgrimesstruct table_entry { 681592Srgrimes CTL_MSG request; 691592Srgrimes long time; 701592Srgrimes TABLE_ENTRY *next; 711592Srgrimes TABLE_ENTRY *last; 721592Srgrimes}; 731592Srgrimes 7490261Simpstatic void delete(TABLE_ENTRY *); 7590261Simp 76241777Sedstatic TABLE_ENTRY *table = NIL; 7731491Scharnier 781592Srgrimes/* 791592Srgrimes * Look in the table for an invitation that matches the current 801592Srgrimes * request looking for an invitation 811592Srgrimes */ 821592SrgrimesCTL_MSG * 8390261Simpfind_match(CTL_MSG *request) 841592Srgrimes{ 8590261Simp TABLE_ENTRY *ptr; 861592Srgrimes time_t current_time; 871592Srgrimes 88211056Sed gettimeofday(&tp, NULL); 891592Srgrimes current_time = tp.tv_sec; 901592Srgrimes if (debug) 911592Srgrimes print_request("find_match", request); 921592Srgrimes for (ptr = table; ptr != NIL; ptr = ptr->next) { 931592Srgrimes if ((ptr->time - current_time) > MAX_LIFE) { 941592Srgrimes /* the entry is too old */ 951592Srgrimes if (debug) 961592Srgrimes print_request("deleting expired entry", 971592Srgrimes &ptr->request); 981592Srgrimes delete(ptr); 991592Srgrimes continue; 1001592Srgrimes } 1011592Srgrimes if (debug) 1021592Srgrimes print_request("", &ptr->request); 1031592Srgrimes if (strcmp(request->l_name, ptr->request.r_name) == 0 && 1041592Srgrimes strcmp(request->r_name, ptr->request.l_name) == 0 && 1051592Srgrimes ptr->request.type == LEAVE_INVITE) 1061592Srgrimes return (&ptr->request); 1071592Srgrimes } 1081592Srgrimes return ((CTL_MSG *)0); 1091592Srgrimes} 1101592Srgrimes 1111592Srgrimes/* 1121592Srgrimes * Look for an identical request, as opposed to a complimentary 1138870Srgrimes * one as find_match does 1141592Srgrimes */ 1151592SrgrimesCTL_MSG * 11690261Simpfind_request(CTL_MSG *request) 1171592Srgrimes{ 11890261Simp TABLE_ENTRY *ptr; 1191592Srgrimes time_t current_time; 1201592Srgrimes 121211056Sed gettimeofday(&tp, NULL); 1221592Srgrimes current_time = tp.tv_sec; 1231592Srgrimes /* 1241592Srgrimes * See if this is a repeated message, and check for 1251592Srgrimes * out of date entries in the table while we are it. 1261592Srgrimes */ 1271592Srgrimes if (debug) 1281592Srgrimes print_request("find_request", request); 1291592Srgrimes for (ptr = table; ptr != NIL; ptr = ptr->next) { 1301592Srgrimes if ((ptr->time - current_time) > MAX_LIFE) { 1311592Srgrimes /* the entry is too old */ 1321592Srgrimes if (debug) 1331592Srgrimes print_request("deleting expired entry", 1341592Srgrimes &ptr->request); 1351592Srgrimes delete(ptr); 1361592Srgrimes continue; 1371592Srgrimes } 1381592Srgrimes if (debug) 1391592Srgrimes print_request("", &ptr->request); 1401592Srgrimes if (strcmp(request->r_name, ptr->request.r_name) == 0 && 1411592Srgrimes strcmp(request->l_name, ptr->request.l_name) == 0 && 1421592Srgrimes request->type == ptr->request.type && 1431592Srgrimes request->pid == ptr->request.pid) { 1441592Srgrimes /* update the time if we 'touch' it */ 1451592Srgrimes ptr->time = current_time; 1461592Srgrimes return (&ptr->request); 1471592Srgrimes } 1481592Srgrimes } 1491592Srgrimes return ((CTL_MSG *)0); 1501592Srgrimes} 1511592Srgrimes 15231491Scharniervoid 15390261Simpinsert_table(CTL_MSG *request, CTL_RESPONSE *response) 1541592Srgrimes{ 15590261Simp TABLE_ENTRY *ptr; 1561592Srgrimes time_t current_time; 1571592Srgrimes 158211056Sed gettimeofday(&tp, NULL); 1591592Srgrimes current_time = tp.tv_sec; 1601592Srgrimes request->id_num = new_id(); 1611592Srgrimes response->id_num = htonl(request->id_num); 1621592Srgrimes /* insert a new entry into the top of the list */ 1631592Srgrimes ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); 1641592Srgrimes if (ptr == NIL) { 1651592Srgrimes syslog(LOG_ERR, "insert_table: Out of memory"); 1661592Srgrimes _exit(1); 1671592Srgrimes } 1681592Srgrimes ptr->time = current_time; 1691592Srgrimes ptr->request = *request; 1701592Srgrimes ptr->next = table; 1711592Srgrimes if (ptr->next != NIL) 1721592Srgrimes ptr->next->last = ptr; 1731592Srgrimes ptr->last = NIL; 1741592Srgrimes table = ptr; 1751592Srgrimes} 1761592Srgrimes 1771592Srgrimes/* 1781592Srgrimes * Generate a unique non-zero sequence number 1791592Srgrimes */ 18031491Scharnierint 18190261Simpnew_id(void) 1821592Srgrimes{ 1831592Srgrimes static int current_id = 0; 1841592Srgrimes 1851592Srgrimes current_id = (current_id + 1) % MAX_ID; 1861592Srgrimes /* 0 is reserved, helps to pick up bugs */ 1871592Srgrimes if (current_id == 0) 1881592Srgrimes current_id = 1; 1891592Srgrimes return (current_id); 1901592Srgrimes} 1911592Srgrimes 1921592Srgrimes/* 1931592Srgrimes * Delete the invitation with id 'id_num' 1941592Srgrimes */ 19531491Scharnierint 196112998Sjmallettdelete_invite(u_int32_t id_num) 1971592Srgrimes{ 19890261Simp TABLE_ENTRY *ptr; 1991592Srgrimes 2001592Srgrimes ptr = table; 2011592Srgrimes if (debug) 2021592Srgrimes syslog(LOG_DEBUG, "delete_invite(%d)", id_num); 2031592Srgrimes for (ptr = table; ptr != NIL; ptr = ptr->next) { 2041592Srgrimes if (ptr->request.id_num == id_num) 2051592Srgrimes break; 2061592Srgrimes if (debug) 2071592Srgrimes print_request("", &ptr->request); 2081592Srgrimes } 2091592Srgrimes if (ptr != NIL) { 2101592Srgrimes delete(ptr); 2111592Srgrimes return (SUCCESS); 2121592Srgrimes } 2131592Srgrimes return (NOT_HERE); 2141592Srgrimes} 2151592Srgrimes 2161592Srgrimes/* 2171592Srgrimes * Classic delete from a double-linked list 2181592Srgrimes */ 21990261Simpstatic void 22090261Simpdelete(TABLE_ENTRY *ptr) 2211592Srgrimes{ 2221592Srgrimes 2231592Srgrimes if (debug) 2241592Srgrimes print_request("delete", &ptr->request); 2251592Srgrimes if (table == ptr) 2261592Srgrimes table = ptr->next; 2271592Srgrimes else if (ptr->last != NIL) 2281592Srgrimes ptr->last->next = ptr->next; 2291592Srgrimes if (ptr->next != NIL) 2301592Srgrimes ptr->next->last = ptr->last; 2311592Srgrimes free((char *)ptr); 2321592Srgrimes} 233