1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 * 22 * Copyright 2002 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T 28 * All Rights Reserved. 29 */ 30 31 /* 32 * University Copyright- Copyright (c) 1982, 1986, 1988 33 * The Regents of the University of California. 34 * All Rights Reserved. 35 * 36 * University Acknowledgment- Portions of this document are derived from 37 * software developed by the University of California, Berkeley, and its 38 * contributors. 39 */ 40 41 /* 42 * Routines to handle insertion, deletion, etc on the table 43 * of requests kept by the daemon. Nothing fancy here, linear 44 * search on a double-linked list. A time is kept with each 45 * entry so that overly old invitations can be eliminated. 46 * 47 * Consider this a mis-guided attempt at modularity 48 */ 49 50 #include <sys/time.h> 51 #include <string.h> 52 #include <stdio.h> 53 #include <malloc.h> 54 #include "talkd_impl.h" 55 56 #define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ 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 struct timeval tp; 68 static TABLE_ENTRY *table = NULL; 69 70 static void delete(TABLE_ENTRY *ptr); 71 72 /* 73 * Look in the table for an invitation that matches the current 74 * request looking for an invitation. 75 */ 76 77 CTL_MSG * 78 find_match(CTL_MSG *request) 79 { 80 TABLE_ENTRY *ptr; 81 TABLE_ENTRY *prevp; 82 long current_time; 83 84 (void) gettimeofday(&tp, NULL); 85 current_time = tp.tv_sec; 86 87 ptr = table; 88 89 if (debug) { 90 (void) printf("Entering Look-Up with : \n"); 91 print_request(request); 92 } 93 94 while (ptr != NULL) { 95 96 if ((ptr->time - current_time) > MAX_LIFE) { 97 /* the entry is too old */ 98 if (debug) { 99 (void) printf("Deleting expired entry : \n"); 100 print_request(&ptr->request); 101 } 102 prevp = ptr; 103 ptr = ptr->next; 104 delete(prevp); 105 continue; 106 } 107 108 if (debug) 109 print_request(&ptr->request); 110 111 if (strcmp(request->l_name, ptr->request.r_name) == 0 && 112 strcmp(request->r_name, ptr->request.l_name) == 0 && 113 ptr->request.type == LEAVE_INVITE) { 114 return (&ptr->request); 115 } 116 117 ptr = ptr->next; 118 } 119 120 return (NULL); 121 } 122 123 /* 124 * Look for an identical request, as opposed to a complimentary 125 * one as find_match does. 126 */ 127 128 CTL_MSG * 129 find_request(CTL_MSG *request) 130 { 131 TABLE_ENTRY *ptr; 132 TABLE_ENTRY *prevp; 133 long current_time; 134 135 (void) gettimeofday(&tp, NULL); 136 current_time = tp.tv_sec; 137 138 /* 139 * See if this is a repeated message, and check for 140 * out of date entries in the table while we are it. 141 */ 142 143 ptr = table; 144 145 if (debug) { 146 (void) printf("Entering find_request with : \n"); 147 print_request(request); 148 } 149 150 while (ptr != NULL) { 151 152 if ((ptr->time - current_time) > MAX_LIFE) { 153 /* the entry is too old */ 154 if (debug) { 155 (void) printf("Deleting expired entry : \n"); 156 print_request(&ptr->request); 157 } 158 prevp = ptr; 159 ptr = ptr->next; 160 delete(prevp); 161 continue; 162 } 163 164 if (debug) 165 print_request(&ptr->request); 166 167 if (strcmp(request->r_name, ptr->request.r_name) == 0 && 168 strcmp(request->l_name, ptr->request.l_name) == 0 && 169 request->type == ptr->request.type && 170 request->pid == ptr->request.pid) { 171 172 /* update the time if we 'touch' it */ 173 ptr->time = current_time; 174 return (&ptr->request); 175 } 176 177 ptr = ptr->next; 178 } 179 180 return (NULL); 181 } 182 183 void 184 insert_table(CTL_MSG *request, CTL_RESPONSE *response) 185 { 186 TABLE_ENTRY *ptr; 187 long current_time; 188 189 (void) gettimeofday(&tp, NULL); 190 current_time = tp.tv_sec; 191 192 response->id_num = request->id_num = new_id(); 193 194 /* 195 * Insert a new entry into the top of the list. 196 */ 197 ptr = (TABLE_ENTRY *) malloc(sizeof (TABLE_ENTRY)); 198 199 if (ptr == NULL) { 200 print_error("malloc in insert_table"); 201 } 202 203 ptr->time = current_time; 204 ptr->request = *request; 205 206 ptr->next = table; 207 if (ptr->next != NULL) { 208 ptr->next->last = ptr; 209 } 210 ptr->last = NULL; 211 table = ptr; 212 } 213 214 /* 215 * Generate a unique non-zero sequence number. 216 */ 217 218 int 219 new_id(void) 220 { 221 static int current_id = 0; 222 223 current_id = (current_id + 1) % MAX_ID; 224 225 /* 0 is reserved, helps to pick up bugs */ 226 if (current_id == 0) 227 current_id = 1; 228 229 return (current_id); 230 } 231 232 /* 233 * Delete the invitation with id 'id_num'. 234 */ 235 236 int 237 delete_invite(int id_num) 238 { 239 TABLE_ENTRY *ptr; 240 241 ptr = table; 242 243 if (debug) 244 (void) printf("Entering delete_invite with %d\n", id_num); 245 246 while (ptr != NULL && ptr->request.id_num != id_num) { 247 if (debug) 248 print_request(&ptr->request); 249 ptr = ptr->next; 250 } 251 252 if (ptr != NULL) { 253 delete(ptr); 254 return (SUCCESS); 255 } 256 257 return (NOT_HERE); 258 } 259 260 /* 261 * Classic delete from a double-linked list. 262 */ 263 264 static void 265 delete(TABLE_ENTRY *ptr) 266 { 267 if (debug) { 268 (void) printf("Deleting : "); 269 print_request(&ptr->request); 270 } 271 if (table == ptr) { 272 table = ptr->next; 273 } else if (ptr->last != NULL) { 274 ptr->last->next = ptr->next; 275 } 276 277 if (ptr->next != NULL) { 278 ptr->next->last = ptr->last; 279 } 280 281 free(ptr); 282 } 283