1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)table.c 8.1 (Berkeley) 6/4/93 30 * $FreeBSD: src/libexec/talkd/table.c,v 1.7 1999/08/28 00:10:17 peter Exp $ 31 */ 32 33 /* 34 * Routines to handle insertion, deletion, etc on the table 35 * of requests kept by the daemon. Nothing fancy here, linear 36 * search on a double-linked list. A time is kept with each 37 * entry so that overly old invitations can be eliminated. 38 * 39 * Consider this a mis-guided attempt at modularity 40 */ 41 #include <sys/param.h> 42 #include <sys/time.h> 43 #include <sys/socket.h> 44 #include <protocols/talkd.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <syslog.h> 49 #include <unistd.h> 50 51 #include "extern.h" 52 53 #define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ 54 55 extern int debug; 56 struct timeval tp; 57 58 typedef struct table_entry TABLE_ENTRY; 59 60 struct table_entry { 61 CTL_MSG request; 62 long time; 63 TABLE_ENTRY *next; 64 TABLE_ENTRY *last; 65 }; 66 67 static void delete(TABLE_ENTRY *); 68 69 TABLE_ENTRY *table = NULL; 70 71 /* 72 * Look in the table for an invitation that matches the current 73 * request looking for an invitation 74 */ 75 CTL_MSG * 76 find_match(CTL_MSG *request) 77 { 78 TABLE_ENTRY *ptr; 79 time_t current_time; 80 81 gettimeofday(&tp, NULL); 82 current_time = tp.tv_sec; 83 if (debug) 84 print_request("find_match", request); 85 for (ptr = table; ptr != NULL; ptr = ptr->next) { 86 if ((ptr->time - current_time) > MAX_LIFE) { 87 /* the entry is too old */ 88 if (debug) 89 print_request("deleting expired entry", 90 &ptr->request); 91 delete(ptr); 92 continue; 93 } 94 if (debug) 95 print_request("", &ptr->request); 96 if (strcmp(request->l_name, ptr->request.r_name) == 0 && 97 strcmp(request->r_name, ptr->request.l_name) == 0 && 98 ptr->request.type == LEAVE_INVITE) 99 return (&ptr->request); 100 } 101 return (NULL); 102 } 103 104 /* 105 * Look for an identical request, as opposed to a complimentary 106 * one as find_match does 107 */ 108 CTL_MSG * 109 find_request(CTL_MSG *request) 110 { 111 TABLE_ENTRY *ptr; 112 time_t current_time; 113 114 gettimeofday(&tp, NULL); 115 current_time = tp.tv_sec; 116 /* 117 * See if this is a repeated message, and check for 118 * out of date entries in the table while we are it. 119 */ 120 if (debug) 121 print_request("find_request", request); 122 for (ptr = table; ptr != NULL; ptr = ptr->next) { 123 if ((ptr->time - current_time) > MAX_LIFE) { 124 /* the entry is too old */ 125 if (debug) 126 print_request("deleting expired entry", 127 &ptr->request); 128 delete(ptr); 129 continue; 130 } 131 if (debug) 132 print_request("", &ptr->request); 133 if (strcmp(request->r_name, ptr->request.r_name) == 0 && 134 strcmp(request->l_name, ptr->request.l_name) == 0 && 135 request->type == ptr->request.type && 136 request->pid == ptr->request.pid) { 137 /* update the time if we 'touch' it */ 138 ptr->time = current_time; 139 return (&ptr->request); 140 } 141 } 142 return (NULL); 143 } 144 145 void 146 insert_table(CTL_MSG *request, CTL_RESPONSE *response) 147 { 148 TABLE_ENTRY *ptr; 149 time_t current_time; 150 151 gettimeofday(&tp, NULL); 152 current_time = tp.tv_sec; 153 request->id_num = new_id(); 154 response->id_num = htonl(request->id_num); 155 /* insert a new entry into the top of the list */ 156 ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); 157 if (ptr == NULL) { 158 syslog(LOG_ERR, "insert_table: Out of memory"); 159 _exit(1); 160 } 161 ptr->time = current_time; 162 ptr->request = *request; 163 ptr->next = table; 164 if (ptr->next != NULL) 165 ptr->next->last = ptr; 166 ptr->last = NULL; 167 table = ptr; 168 } 169 170 /* 171 * Generate a unique non-zero sequence number 172 */ 173 int 174 new_id(void) 175 { 176 static int current_id = 0; 177 178 current_id = (current_id + 1) % MAX_ID; 179 /* 0 is reserved, helps to pick up bugs */ 180 if (current_id == 0) 181 current_id = 1; 182 return (current_id); 183 } 184 185 /* 186 * Delete the invitation with id 'id_num' 187 */ 188 int 189 delete_invite(unsigned int id_num) 190 { 191 TABLE_ENTRY *ptr; 192 193 ptr = table; 194 if (debug) 195 syslog(LOG_DEBUG, "delete_invite(%d)", id_num); 196 for (ptr = table; ptr != NULL; ptr = ptr->next) { 197 if (ptr->request.id_num == id_num) 198 break; 199 if (debug) 200 print_request("", &ptr->request); 201 } 202 if (ptr != NULL) { 203 delete(ptr); 204 return (SUCCESS); 205 } 206 return (NOT_HERE); 207 } 208 209 /* 210 * Classic delete from a double-linked list 211 */ 212 static void 213 delete(TABLE_ENTRY *ptr) 214 { 215 216 if (debug) 217 print_request("delete", &ptr->request); 218 if (table == ptr) 219 table = ptr->next; 220 else if (ptr->last != NULL) 221 ptr->last->next = ptr->next; 222 if (ptr->next != NULL) 223 ptr->next->last = ptr->last; 224 free((char *)ptr); 225 } 226