table.c revision 296373
1109864Sjeff/* 2165762Sjeff * Copyright (c) 1983, 1993 3109864Sjeff * The Regents of the University of California. All rights reserved. 4109864Sjeff * 5109864Sjeff * Redistribution and use in source and binary forms, with or without 6109864Sjeff * modification, are permitted provided that the following conditions 7109864Sjeff * are met: 8109864Sjeff * 1. Redistributions of source code must retain the above copyright 9109864Sjeff * notice, this list of conditions and the following disclaimer. 10109864Sjeff * 2. Redistributions in binary form must reproduce the above copyright 11109864Sjeff * notice, this list of conditions and the following disclaimer in the 12109864Sjeff * documentation and/or other materials provided with the distribution. 13109864Sjeff * 3. Neither the name of the University nor the names of its contributors 14109864Sjeff * may be used to endorse or promote products derived from this software 15109864Sjeff * without specific prior written permission. 16109864Sjeff * 17109864Sjeff * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18109864Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19109864Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20109864Sjeff * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21109864Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22109864Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23109864Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24109864Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25109864Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26109864Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27171482Sjeff * SUCH DAMAGE. 28171482Sjeff */ 29171482Sjeff 30171482Sjeff#ifndef lint 31171482Sjeff#if 0 32171482Sjeffstatic char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/4/93"; 33171482Sjeff#endif 34171482Sjeffstatic const char rcsid[] = 35171482Sjeff "$FreeBSD: releng/10.3/libexec/talkd/table.c 262435 2014-02-24 08:21:49Z brueffer $"; 36171482Sjeff#endif /* not lint */ 37171482Sjeff 38116182Sobrien/* 39116182Sobrien * Routines to handle insertion, deletion, etc on the table 40116182Sobrien * of requests kept by the daemon. Nothing fancy here, linear 41147565Speter * search on a double-linked list. A time is kept with each 42147565Speter * entry so that overly old invitations can be eliminated. 43134649Sscottl * 44109864Sjeff * Consider this a mis-guided attempt at modularity 45109864Sjeff */ 46131929Smarcel#include <sys/param.h> 47109864Sjeff#include <sys/time.h> 48109864Sjeff#include <sys/socket.h> 49109864Sjeff#include <netinet/in.h> 50109864Sjeff#include <protocols/talkd.h> 51109864Sjeff#include <stdio.h> 52112966Sjeff#include <stdlib.h> 53122038Sjeff#include <string.h> 54109864Sjeff#include <syslog.h> 55109864Sjeff#include <unistd.h> 56109864Sjeff 57109864Sjeff#include "extern.h" 58109864Sjeff 59139453Sjhb#define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ 60161599Sdavidxu 61109864Sjeff#define NIL ((TABLE_ENTRY *)0) 62109864Sjeff 63109864Sjeffstatic struct timeval tp; 64109864Sjeff 65109864Sjefftypedef struct table_entry TABLE_ENTRY; 66109864Sjeff 67145256Sjkoshystruct table_entry { 68145256Sjkoshy CTL_MSG request; 69145256Sjkoshy long time; 70145256Sjkoshy TABLE_ENTRY *next; 71109864Sjeff TABLE_ENTRY *last; 72121790Sjeff}; 73109864Sjeff 74166190Sjeffstatic void delete(TABLE_ENTRY *); 75166190Sjeff 76166190Sjeffstatic TABLE_ENTRY *table = NIL; 77166190Sjeff 78171482Sjeff/* 79166137Sjeff * Look in the table for an invitation that matches the current 80166137Sjeff * request looking for an invitation 81171482Sjeff */ 82171482SjeffCTL_MSG * 83146954Sjefffind_match(CTL_MSG *request) 84164936Sjulian{ 85171482Sjeff TABLE_ENTRY *ptr; 86171482Sjeff time_t current_time; 87171482Sjeff 88171482Sjeff gettimeofday(&tp, NULL); 89171482Sjeff current_time = tp.tv_sec; 90164936Sjulian if (debug) 91171482Sjeff print_request("find_match", request); 92171482Sjeff for (ptr = table; ptr != NIL; ptr = ptr->next) { 93171482Sjeff if ((ptr->time - current_time) > MAX_LIFE) { 94171482Sjeff /* the entry is too old */ 95134791Sjulian if (debug) 96164936Sjulian print_request("deleting expired entry", 97164936Sjulian &ptr->request); 98164936Sjulian delete(ptr); 99166108Sjeff continue; 100166108Sjeff } 101166108Sjeff if (debug) 102134791Sjulian print_request("", &ptr->request); 103164936Sjulian if (strcmp(request->l_name, ptr->request.r_name) == 0 && 104166108Sjeff strcmp(request->r_name, ptr->request.l_name) == 0 && 105166108Sjeff ptr->request.type == LEAVE_INVITE) 106121790Sjeff return (&ptr->request); 107164936Sjulian } 108109864Sjeff return ((CTL_MSG *)0); 109109864Sjeff} 110165762Sjeff 111111857Sjeff/* 112165762Sjeff * Look for an identical request, as opposed to a complimentary 113165762Sjeff * one as find_match does 114165796Sjeff */ 115165762SjeffCTL_MSG * 116165762Sjefffind_request(CTL_MSG *request) 117165762Sjeff{ 118165762Sjeff TABLE_ENTRY *ptr; 119165762Sjeff time_t current_time; 120165762Sjeff 121165796Sjeff gettimeofday(&tp, NULL); 122165762Sjeff current_time = tp.tv_sec; 123165762Sjeff /* 124165830Sjeff * See if this is a repeated message, and check for 125165762Sjeff * out of date entries in the table while we are it. 126165762Sjeff */ 127165762Sjeff if (debug) 128165762Sjeff print_request("find_request", request); 129165762Sjeff for (ptr = table; ptr != NIL; ptr = ptr->next) { 130165762Sjeff if ((ptr->time - current_time) > MAX_LIFE) { 131165762Sjeff /* the entry is too old */ 132165762Sjeff if (debug) 133165762Sjeff print_request("deleting expired entry", 134116642Sjeff &ptr->request); 135165762Sjeff delete(ptr); 136165762Sjeff continue; 137109864Sjeff } 138165762Sjeff if (debug) 139121869Sjeff print_request("", &ptr->request); 140165762Sjeff if (strcmp(request->r_name, ptr->request.r_name) == 0 && 141165762Sjeff strcmp(request->l_name, ptr->request.l_name) == 0 && 142170787Sjeff request->type == ptr->request.type && 143165762Sjeff request->pid == ptr->request.pid) { 144165762Sjeff /* update the time if we 'touch' it */ 145165827Sjeff ptr->time = current_time; 146165762Sjeff return (&ptr->request); 147109864Sjeff } 148109864Sjeff } 149165762Sjeff return ((CTL_MSG *)0); 150165762Sjeff} 151165762Sjeff 152165762Sjeffvoid 153109864Sjeffinsert_table(CTL_MSG *request, CTL_RESPONSE *response) 154110645Sjeff{ 155110645Sjeff TABLE_ENTRY *ptr; 156121868Sjeff time_t current_time; 157116365Sjeff 158111857Sjeff gettimeofday(&tp, NULL); 159109864Sjeff current_time = tp.tv_sec; 160165762Sjeff request->id_num = new_id(); 161165762Sjeff response->id_num = htonl(request->id_num); 162116365Sjeff /* insert a new entry into the top of the list */ 163116365Sjeff ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); 164121126Sjeff if (ptr == NIL) { 165111857Sjeff syslog(LOG_ERR, "insert_table: Out of memory"); 166109864Sjeff _exit(1); 167165762Sjeff } 168165762Sjeff ptr->time = current_time; 169165762Sjeff ptr->request = *request; 170165762Sjeff ptr->next = table; 171165762Sjeff if (ptr->next != NIL) 172171482Sjeff ptr->next->last = ptr; 173109864Sjeff ptr->last = NIL; 174165762Sjeff table = ptr; 175165762Sjeff} 176165762Sjeff 177165762Sjeff/* 178171482Sjeff * Generate a unique non-zero sequence number 179109864Sjeff */ 180109864Sjeffint 181171482Sjeffnew_id(void) 182171482Sjeff{ 183171482Sjeff static int current_id = 0; 184109864Sjeff 185164936Sjulian current_id = (current_id + 1) % MAX_ID; 186171482Sjeff /* 0 is reserved, helps to pick up bugs */ 187171482Sjeff if (current_id == 0) 188171482Sjeff current_id = 1; 189165620Sjeff return (current_id); 190171482Sjeff} 191166557Sjeff 192166557Sjeff/* 193110267Sjeff * Delete the invitation with id 'id_num' 194171482Sjeff */ 195171482Sjeffint 196165620Sjeffdelete_invite(u_int32_t id_num) 197165620Sjeff{ 198125289Sjeff TABLE_ENTRY *ptr; 199165620Sjeff 200110267Sjeff ptr = table; 201171482Sjeff if (debug) 202171482Sjeff syslog(LOG_DEBUG, "delete_invite(%d)", id_num); 203109864Sjeff for (ptr = table; ptr != NIL; ptr = ptr->next) { 204166108Sjeff if (ptr->request.id_num == id_num) 205123433Sjeff break; 206109864Sjeff if (debug) 207164936Sjulian print_request("", &ptr->request); 208123433Sjeff } 209123433Sjeff if (ptr != NIL) { 210123433Sjeff delete(ptr); 211123433Sjeff return (SUCCESS); 212123433Sjeff } 213123433Sjeff return (NOT_HERE); 214164936Sjulian} 215165620Sjeff 216165620Sjeff/* 217165620Sjeff * Classic delete from a double-linked list 218165620Sjeff */ 219165620Sjeffstatic void 220165620Sjeffdelete(TABLE_ENTRY *ptr) 221165620Sjeff{ 222171482Sjeff 223123433Sjeff if (debug) 224171482Sjeff print_request("delete", &ptr->request); 225166108Sjeff if (table == ptr) 226166108Sjeff table = ptr->next; 227123433Sjeff else if (ptr->last != NIL) 228166108Sjeff ptr->last->next = ptr->next; 229166108Sjeff if (ptr->next != NIL) 230171506Sjeff ptr->next->last = ptr->last; 231171506Sjeff free((char *)ptr); 232171506Sjeff} 233166108Sjeff