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: stable/10/libexec/talkd/table.c 311751 2017-01-09 05:52:30Z delphij $"; 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 63311751Sdelphijstatic struct timespec ts; 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{ 85311747Sdelphij TABLE_ENTRY *ptr, *next; 861592Srgrimes time_t current_time; 871592Srgrimes 88311751Sdelphij clock_gettime(CLOCK_MONOTONIC_FAST, &ts); 89311751Sdelphij current_time = ts.tv_sec; 901592Srgrimes if (debug) 911592Srgrimes print_request("find_match", request); 92311747Sdelphij for (ptr = table; ptr != NIL; ptr = next) { 93311747Sdelphij next = ptr->next; 941592Srgrimes if ((ptr->time - current_time) > MAX_LIFE) { 951592Srgrimes /* the entry is too old */ 961592Srgrimes if (debug) 971592Srgrimes print_request("deleting expired entry", 981592Srgrimes &ptr->request); 991592Srgrimes delete(ptr); 1001592Srgrimes continue; 1011592Srgrimes } 1021592Srgrimes if (debug) 1031592Srgrimes print_request("", &ptr->request); 1041592Srgrimes if (strcmp(request->l_name, ptr->request.r_name) == 0 && 1051592Srgrimes strcmp(request->r_name, ptr->request.l_name) == 0 && 1061592Srgrimes ptr->request.type == LEAVE_INVITE) 1071592Srgrimes return (&ptr->request); 1081592Srgrimes } 1091592Srgrimes return ((CTL_MSG *)0); 1101592Srgrimes} 1111592Srgrimes 1121592Srgrimes/* 1131592Srgrimes * Look for an identical request, as opposed to a complimentary 1148870Srgrimes * one as find_match does 1151592Srgrimes */ 1161592SrgrimesCTL_MSG * 11790261Simpfind_request(CTL_MSG *request) 1181592Srgrimes{ 119311747Sdelphij TABLE_ENTRY *ptr, *next; 1201592Srgrimes time_t current_time; 1211592Srgrimes 122311751Sdelphij clock_gettime(CLOCK_MONOTONIC_FAST, &ts); 123311751Sdelphij current_time = ts.tv_sec; 1241592Srgrimes /* 1251592Srgrimes * See if this is a repeated message, and check for 1261592Srgrimes * out of date entries in the table while we are it. 1271592Srgrimes */ 1281592Srgrimes if (debug) 1291592Srgrimes print_request("find_request", request); 130311747Sdelphij for (ptr = table; ptr != NIL; ptr = next) { 131311747Sdelphij next = ptr->next; 1321592Srgrimes if ((ptr->time - current_time) > MAX_LIFE) { 1331592Srgrimes /* the entry is too old */ 1341592Srgrimes if (debug) 1351592Srgrimes print_request("deleting expired entry", 1361592Srgrimes &ptr->request); 1371592Srgrimes delete(ptr); 1381592Srgrimes continue; 1391592Srgrimes } 1401592Srgrimes if (debug) 1411592Srgrimes print_request("", &ptr->request); 1421592Srgrimes if (strcmp(request->r_name, ptr->request.r_name) == 0 && 1431592Srgrimes strcmp(request->l_name, ptr->request.l_name) == 0 && 1441592Srgrimes request->type == ptr->request.type && 1451592Srgrimes request->pid == ptr->request.pid) { 1461592Srgrimes /* update the time if we 'touch' it */ 1471592Srgrimes ptr->time = current_time; 1481592Srgrimes return (&ptr->request); 1491592Srgrimes } 1501592Srgrimes } 1511592Srgrimes return ((CTL_MSG *)0); 1521592Srgrimes} 1531592Srgrimes 15431491Scharniervoid 15590261Simpinsert_table(CTL_MSG *request, CTL_RESPONSE *response) 1561592Srgrimes{ 15790261Simp TABLE_ENTRY *ptr; 1581592Srgrimes time_t current_time; 1591592Srgrimes 160311751Sdelphij clock_gettime(CLOCK_MONOTONIC_FAST, &ts); 161311751Sdelphij current_time = ts.tv_sec; 1621592Srgrimes request->id_num = new_id(); 1631592Srgrimes response->id_num = htonl(request->id_num); 1641592Srgrimes /* insert a new entry into the top of the list */ 1651592Srgrimes ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); 1661592Srgrimes if (ptr == NIL) { 1671592Srgrimes syslog(LOG_ERR, "insert_table: Out of memory"); 1681592Srgrimes _exit(1); 1691592Srgrimes } 1701592Srgrimes ptr->time = current_time; 1711592Srgrimes ptr->request = *request; 1721592Srgrimes ptr->next = table; 1731592Srgrimes if (ptr->next != NIL) 1741592Srgrimes ptr->next->last = ptr; 1751592Srgrimes ptr->last = NIL; 1761592Srgrimes table = ptr; 1771592Srgrimes} 1781592Srgrimes 1791592Srgrimes/* 1801592Srgrimes * Generate a unique non-zero sequence number 1811592Srgrimes */ 18231491Scharnierint 18390261Simpnew_id(void) 1841592Srgrimes{ 1851592Srgrimes static int current_id = 0; 1861592Srgrimes 1871592Srgrimes current_id = (current_id + 1) % MAX_ID; 1881592Srgrimes /* 0 is reserved, helps to pick up bugs */ 1891592Srgrimes if (current_id == 0) 1901592Srgrimes current_id = 1; 1911592Srgrimes return (current_id); 1921592Srgrimes} 1931592Srgrimes 1941592Srgrimes/* 1951592Srgrimes * Delete the invitation with id 'id_num' 1961592Srgrimes */ 19731491Scharnierint 198112998Sjmallettdelete_invite(u_int32_t id_num) 1991592Srgrimes{ 20090261Simp TABLE_ENTRY *ptr; 2011592Srgrimes 2021592Srgrimes ptr = table; 2031592Srgrimes if (debug) 2041592Srgrimes syslog(LOG_DEBUG, "delete_invite(%d)", id_num); 2051592Srgrimes for (ptr = table; ptr != NIL; ptr = ptr->next) { 2061592Srgrimes if (ptr->request.id_num == id_num) 2071592Srgrimes break; 2081592Srgrimes if (debug) 2091592Srgrimes print_request("", &ptr->request); 2101592Srgrimes } 2111592Srgrimes if (ptr != NIL) { 2121592Srgrimes delete(ptr); 2131592Srgrimes return (SUCCESS); 2141592Srgrimes } 2151592Srgrimes return (NOT_HERE); 2161592Srgrimes} 2171592Srgrimes 2181592Srgrimes/* 2191592Srgrimes * Classic delete from a double-linked list 2201592Srgrimes */ 22190261Simpstatic void 22290261Simpdelete(TABLE_ENTRY *ptr) 2231592Srgrimes{ 2241592Srgrimes 2251592Srgrimes if (debug) 2261592Srgrimes print_request("delete", &ptr->request); 2271592Srgrimes if (table == ptr) 2281592Srgrimes table = ptr->next; 2291592Srgrimes else if (ptr->last != NIL) 2301592Srgrimes ptr->last->next = ptr->next; 2311592Srgrimes if (ptr->next != NIL) 2321592Srgrimes ptr->next->last = ptr->last; 2331592Srgrimes free((char *)ptr); 2341592Srgrimes} 235