xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.sbin/in.talkd/table.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
42 
43 
44 /*
45  * Routines to handle insertion, deletion, etc on the table
46  * of requests kept by the daemon. Nothing fancy here, linear
47  * search on a double-linked list. A time is kept with each
48  * entry so that overly old invitations can be eliminated.
49  *
50  * Consider this a mis-guided attempt at modularity
51  */
52 
53 #include <sys/time.h>
54 #include <string.h>
55 #include <stdio.h>
56 #include <malloc.h>
57 #include "talkd_impl.h"
58 
59 #define	MAX_ID 16000 /* << 2^15 so I don't have sign troubles */
60 
61 typedef struct table_entry TABLE_ENTRY;
62 
63 struct table_entry {
64     CTL_MSG request;
65     long time;
66     TABLE_ENTRY *next;
67     TABLE_ENTRY *last;
68 };
69 
70 static struct timeval tp;
71 static TABLE_ENTRY *table = NULL;
72 
73 static void delete(TABLE_ENTRY *ptr);
74 
75 /*
76  * Look in the table for an invitation that matches the current
77  * request looking for an invitation.
78  */
79 
80 CTL_MSG *
81 find_match(CTL_MSG *request)
82 {
83 	TABLE_ENTRY *ptr;
84 	TABLE_ENTRY *prevp;
85 	long current_time;
86 
87 	(void) gettimeofday(&tp, NULL);
88 	current_time = tp.tv_sec;
89 
90 	ptr = table;
91 
92 	if (debug) {
93 		(void) printf("Entering Look-Up with : \n");
94 		print_request(request);
95 	}
96 
97 	while (ptr != NULL) {
98 
99 		if ((ptr->time - current_time) > MAX_LIFE) {
100 		/* the entry is too old */
101 			if (debug) {
102 				(void) printf("Deleting expired entry : \n");
103 				print_request(&ptr->request);
104 			}
105 			prevp = ptr;
106 			ptr = ptr->next;
107 			delete(prevp);
108 			continue;
109 		}
110 
111 		if (debug)
112 			print_request(&ptr->request);
113 
114 		if (strcmp(request->l_name, ptr->request.r_name) == 0 &&
115 		    strcmp(request->r_name, ptr->request.l_name) == 0 &&
116 		    ptr->request.type == LEAVE_INVITE) {
117 			return (&ptr->request);
118 		}
119 
120 		ptr = ptr->next;
121 	}
122 
123 	return (NULL);
124 }
125 
126 /*
127  * Look for an identical request, as opposed to a complimentary
128  * one as find_match does.
129  */
130 
131 CTL_MSG *
132 find_request(CTL_MSG *request)
133 {
134 	TABLE_ENTRY *ptr;
135 	TABLE_ENTRY *prevp;
136 	long current_time;
137 
138 	(void) gettimeofday(&tp, NULL);
139 	current_time = tp.tv_sec;
140 
141 	/*
142 	 * See if this is a repeated message, and check for
143 	 * out of date entries in the table while we are it.
144 	 */
145 
146 	ptr = table;
147 
148 	if (debug) {
149 		(void) printf("Entering find_request with : \n");
150 		print_request(request);
151 	}
152 
153 	while (ptr != NULL) {
154 
155 		if ((ptr->time - current_time) > MAX_LIFE) {
156 			/* the entry is too old */
157 			if (debug) {
158 				(void) printf("Deleting expired entry : \n");
159 				print_request(&ptr->request);
160 			}
161 			prevp = ptr;
162 			ptr = ptr->next;
163 			delete(prevp);
164 			continue;
165 		}
166 
167 		if (debug)
168 			print_request(&ptr->request);
169 
170 		if (strcmp(request->r_name, ptr->request.r_name) == 0 &&
171 		    strcmp(request->l_name, ptr->request.l_name) == 0 &&
172 		    request->type == ptr->request.type &&
173 		    request->pid == ptr->request.pid) {
174 
175 			/* update the time if we 'touch' it */
176 			ptr->time = current_time;
177 			return (&ptr->request);
178 		}
179 
180 		ptr = ptr->next;
181 	}
182 
183 	return (NULL);
184 }
185 
186 void
187 insert_table(CTL_MSG *request, CTL_RESPONSE *response)
188 {
189 	TABLE_ENTRY *ptr;
190 	long current_time;
191 
192 	(void) gettimeofday(&tp, NULL);
193 	current_time = tp.tv_sec;
194 
195 	response->id_num = request->id_num = new_id();
196 
197 	/*
198 	 * Insert a new entry into the top of the list.
199 	 */
200 	ptr = (TABLE_ENTRY *) malloc(sizeof (TABLE_ENTRY));
201 
202 	if (ptr == NULL) {
203 		print_error("malloc in insert_table");
204 	}
205 
206 	ptr->time = current_time;
207 	ptr->request = *request;
208 
209 	ptr->next = table;
210 	if (ptr->next != NULL) {
211 		ptr->next->last = ptr;
212 	}
213 	ptr->last = NULL;
214 	table = ptr;
215 }
216 
217 /*
218  * Generate a unique non-zero sequence number.
219  */
220 
221 int
222 new_id(void)
223 {
224 	static int current_id = 0;
225 
226 	current_id = (current_id + 1) % MAX_ID;
227 
228 	/* 0 is reserved, helps to pick up bugs */
229 	if (current_id == 0)
230 		current_id = 1;
231 
232 	return (current_id);
233 }
234 
235 /*
236  * Delete the invitation with id 'id_num'.
237  */
238 
239 int
240 delete_invite(int id_num)
241 {
242 	TABLE_ENTRY *ptr;
243 
244 	ptr = table;
245 
246 	if (debug)
247 		(void) printf("Entering delete_invite with %d\n", id_num);
248 
249 	while (ptr != NULL && ptr->request.id_num != id_num) {
250 		if (debug)
251 			print_request(&ptr->request);
252 			ptr = ptr->next;
253 	}
254 
255 	if (ptr != NULL) {
256 		delete(ptr);
257 		return (SUCCESS);
258 	}
259 
260 	return (NOT_HERE);
261 }
262 
263 /*
264  * Classic delete from a double-linked list.
265  */
266 
267 static void
268 delete(TABLE_ENTRY *ptr)
269 {
270 	if (debug) {
271 		(void) printf("Deleting : ");
272 		print_request(&ptr->request);
273 	}
274 	if (table == ptr) {
275 		table = ptr->next;
276 	} else if (ptr->last != NULL) {
277 		ptr->last->next = ptr->next;
278 	}
279 
280 	if (ptr->next != NULL) {
281 		ptr->next->last = ptr->last;
282 	}
283 
284 	free(ptr);
285 }
286