1331722Seadler/* 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. 13262136Sbrueffer * 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/11/libexec/talkd/table.c 311749 2017-01-09 05:50:52Z 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 63311749Sdelphijstatic 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{ 85311746Sdelphij TABLE_ENTRY *ptr, *next; 861592Srgrimes time_t current_time; 871592Srgrimes 88311749Sdelphij clock_gettime(CLOCK_MONOTONIC_FAST, &ts); 89311749Sdelphij current_time = ts.tv_sec; 901592Srgrimes if (debug) 911592Srgrimes print_request("find_match", request); 92311746Sdelphij for (ptr = table; ptr != NIL; ptr = next) { 93311746Sdelphij 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{ 119311746Sdelphij TABLE_ENTRY *ptr, *next; 1201592Srgrimes time_t current_time; 1211592Srgrimes 122311749Sdelphij clock_gettime(CLOCK_MONOTONIC_FAST, &ts); 123311749Sdelphij 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); 130311746Sdelphij for (ptr = table; ptr != NIL; ptr = next) { 131311746Sdelphij 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 160311749Sdelphij clock_gettime(CLOCK_MONOTONIC_FAST, &ts); 161311749Sdelphij 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 if (debug) 2031592Srgrimes syslog(LOG_DEBUG, "delete_invite(%d)", id_num); 2041592Srgrimes for (ptr = table; ptr != NIL; ptr = ptr->next) { 2051592Srgrimes if (ptr->request.id_num == id_num) 2061592Srgrimes break; 2071592Srgrimes if (debug) 2081592Srgrimes print_request("", &ptr->request); 2091592Srgrimes } 2101592Srgrimes if (ptr != NIL) { 2111592Srgrimes delete(ptr); 2121592Srgrimes return (SUCCESS); 2131592Srgrimes } 2141592Srgrimes return (NOT_HERE); 2151592Srgrimes} 2161592Srgrimes 2171592Srgrimes/* 2181592Srgrimes * Classic delete from a double-linked list 2191592Srgrimes */ 22090261Simpstatic void 22190261Simpdelete(TABLE_ENTRY *ptr) 2221592Srgrimes{ 2231592Srgrimes 2241592Srgrimes if (debug) 2251592Srgrimes print_request("delete", &ptr->request); 2261592Srgrimes if (table == ptr) 2271592Srgrimes table = ptr->next; 2281592Srgrimes else if (ptr->last != NIL) 2291592Srgrimes ptr->last->next = ptr->next; 2301592Srgrimes if (ptr->next != NIL) 2311592Srgrimes ptr->next->last = ptr->last; 2321592Srgrimes free((char *)ptr); 2331592Srgrimes} 234