table.c revision 211056
1272343Sngie/*
2272343Sngie * Copyright (c) 1983, 1993
3272343Sngie *	The Regents of the University of California.  All rights reserved.
4272343Sngie *
5272343Sngie * Redistribution and use in source and binary forms, with or without
6272343Sngie * modification, are permitted provided that the following conditions
7272343Sngie * are met:
8272343Sngie * 1. Redistributions of source code must retain the above copyright
9272343Sngie *    notice, this list of conditions and the following disclaimer.
10272343Sngie * 2. Redistributions in binary form must reproduce the above copyright
11272343Sngie *    notice, this list of conditions and the following disclaimer in the
12272343Sngie *    documentation and/or other materials provided with the distribution.
13272343Sngie * 3. All advertising materials mentioning features or use of this software
14272343Sngie *    must display the following acknowledgement:
15272343Sngie *	This product includes software developed by the University of
16272343Sngie *	California, Berkeley and its contributors.
17272343Sngie * 4. Neither the name of the University nor the names of its contributors
18272343Sngie *    may be used to endorse or promote products derived from this software
19272343Sngie *    without specific prior written permission.
20272343Sngie *
21272343Sngie * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22272343Sngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23272343Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24272343Sngie * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25272343Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27272343Sngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28272343Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29272343Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30272343Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31272343Sngie * SUCH DAMAGE.
32272343Sngie */
33272343Sngie
34272343Sngie#ifndef lint
35272343Sngie#if 0
36272343Sngiestatic char sccsid[] = "@(#)table.c	8.1 (Berkeley) 6/4/93";
37272343Sngie#endif
38272343Sngiestatic const char rcsid[] =
39272343Sngie  "$FreeBSD: head/libexec/talkd/table.c 211056 2010-08-08 02:45:48Z ed $";
40272343Sngie#endif /* not lint */
41272343Sngie
42272343Sngie/*
43272343Sngie * Routines to handle insertion, deletion, etc on the table
44272343Sngie * of requests kept by the daemon. Nothing fancy here, linear
45272343Sngie * search on a double-linked list. A time is kept with each
46272343Sngie * entry so that overly old invitations can be eliminated.
47272343Sngie *
48272343Sngie * Consider this a mis-guided attempt at modularity
49272343Sngie */
50272343Sngie#include <sys/param.h>
51272343Sngie#include <sys/time.h>
52272343Sngie#include <sys/socket.h>
53272343Sngie#include <netinet/in.h>
54272343Sngie#include <protocols/talkd.h>
55272343Sngie#include <stdio.h>
56272343Sngie#include <stdlib.h>
57272343Sngie#include <string.h>
58272343Sngie#include <syslog.h>
59272343Sngie#include <unistd.h>
60272343Sngie
61272343Sngie#include "extern.h"
62272343Sngie
63272343Sngie#define MAX_ID 16000	/* << 2^15 so I don't have sign troubles */
64272343Sngie
65272343Sngie#define NIL ((TABLE_ENTRY *)0)
66272343Sngie
67272343Sngieextern	int debug;
68272343Sngiestruct	timeval tp;
69272343Sngie
70272343Sngietypedef struct table_entry TABLE_ENTRY;
71272343Sngie
72272343Sngiestruct table_entry {
73272343Sngie	CTL_MSG request;
74272343Sngie	long	time;
75272343Sngie	TABLE_ENTRY *next;
76272343Sngie	TABLE_ENTRY *last;
77272343Sngie};
78272343Sngie
79272343Sngiestatic void delete(TABLE_ENTRY *);
80272343Sngie
81272343SngieTABLE_ENTRY *table = NIL;
82272343Sngie
83272343Sngie/*
84272343Sngie * Look in the table for an invitation that matches the current
85272343Sngie * request looking for an invitation
86272343Sngie */
87272343SngieCTL_MSG *
88272343Sngiefind_match(CTL_MSG *request)
89272343Sngie{
90272343Sngie	TABLE_ENTRY *ptr;
91272343Sngie	time_t current_time;
92272343Sngie
93272343Sngie	gettimeofday(&tp, NULL);
94272343Sngie	current_time = tp.tv_sec;
95272343Sngie	if (debug)
96272343Sngie		print_request("find_match", request);
97272343Sngie	for (ptr = table; ptr != NIL; ptr = ptr->next) {
98272343Sngie		if ((ptr->time - current_time) > MAX_LIFE) {
99272343Sngie			/* the entry is too old */
100272343Sngie			if (debug)
101272343Sngie				print_request("deleting expired entry",
102272343Sngie				    &ptr->request);
103272343Sngie			delete(ptr);
104272343Sngie			continue;
105272343Sngie		}
106272343Sngie		if (debug)
107272343Sngie			print_request("", &ptr->request);
108272343Sngie		if (strcmp(request->l_name, ptr->request.r_name) == 0 &&
109272343Sngie		    strcmp(request->r_name, ptr->request.l_name) == 0 &&
110272343Sngie		     ptr->request.type == LEAVE_INVITE)
111272343Sngie			return (&ptr->request);
112272343Sngie	}
113272343Sngie	return ((CTL_MSG *)0);
114272343Sngie}
115272343Sngie
116272343Sngie/*
117272343Sngie * Look for an identical request, as opposed to a complimentary
118272343Sngie * one as find_match does
119272343Sngie */
120272343SngieCTL_MSG *
121272343Sngiefind_request(CTL_MSG *request)
122272343Sngie{
123272343Sngie	TABLE_ENTRY *ptr;
124272343Sngie	time_t current_time;
125272343Sngie
126272343Sngie	gettimeofday(&tp, NULL);
127272343Sngie	current_time = tp.tv_sec;
128272343Sngie	/*
129272343Sngie	 * See if this is a repeated message, and check for
130272343Sngie	 * out of date entries in the table while we are it.
131272343Sngie	 */
132272343Sngie	if (debug)
133272343Sngie		print_request("find_request", request);
134272343Sngie	for (ptr = table; ptr != NIL; ptr = ptr->next) {
135272343Sngie		if ((ptr->time - current_time) > MAX_LIFE) {
136272343Sngie			/* the entry is too old */
137272343Sngie			if (debug)
138272343Sngie				print_request("deleting expired entry",
139272343Sngie				    &ptr->request);
140272343Sngie			delete(ptr);
141272343Sngie			continue;
142272343Sngie		}
143272343Sngie		if (debug)
144272343Sngie			print_request("", &ptr->request);
145272343Sngie		if (strcmp(request->r_name, ptr->request.r_name) == 0 &&
146272343Sngie		    strcmp(request->l_name, ptr->request.l_name) == 0 &&
147272343Sngie		    request->type == ptr->request.type &&
148272343Sngie		    request->pid == ptr->request.pid) {
149272343Sngie			/* update the time if we 'touch' it */
150272343Sngie			ptr->time = current_time;
151272343Sngie			return (&ptr->request);
152272343Sngie		}
153272343Sngie	}
154272343Sngie	return ((CTL_MSG *)0);
155272343Sngie}
156272343Sngie
157272343Sngievoid
158272343Sngieinsert_table(CTL_MSG *request, CTL_RESPONSE *response)
159272343Sngie{
160272343Sngie	TABLE_ENTRY *ptr;
161272343Sngie	time_t current_time;
162272343Sngie
163272343Sngie	gettimeofday(&tp, NULL);
164272343Sngie	current_time = tp.tv_sec;
165272343Sngie	request->id_num = new_id();
166272343Sngie	response->id_num = htonl(request->id_num);
167272343Sngie	/* insert a new entry into the top of the list */
168272343Sngie	ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY));
169272343Sngie	if (ptr == NIL) {
170272343Sngie		syslog(LOG_ERR, "insert_table: Out of memory");
171272343Sngie		_exit(1);
172272343Sngie	}
173272343Sngie	ptr->time = current_time;
174272343Sngie	ptr->request = *request;
175272343Sngie	ptr->next = table;
176272343Sngie	if (ptr->next != NIL)
177272343Sngie		ptr->next->last = ptr;
178272343Sngie	ptr->last = NIL;
179272343Sngie	table = ptr;
180272343Sngie}
181272343Sngie
182272343Sngie/*
183272343Sngie * Generate a unique non-zero sequence number
184272343Sngie */
185272343Sngieint
186272343Sngienew_id(void)
187272343Sngie{
188272343Sngie	static int current_id = 0;
189272343Sngie
190272343Sngie	current_id = (current_id + 1) % MAX_ID;
191272343Sngie	/* 0 is reserved, helps to pick up bugs */
192272343Sngie	if (current_id == 0)
193272343Sngie		current_id = 1;
194272343Sngie	return (current_id);
195}
196
197/*
198 * Delete the invitation with id 'id_num'
199 */
200int
201delete_invite(u_int32_t id_num)
202{
203	TABLE_ENTRY *ptr;
204
205	ptr = table;
206	if (debug)
207		syslog(LOG_DEBUG, "delete_invite(%d)", id_num);
208	for (ptr = table; ptr != NIL; ptr = ptr->next) {
209		if (ptr->request.id_num == id_num)
210			break;
211		if (debug)
212			print_request("", &ptr->request);
213	}
214	if (ptr != NIL) {
215		delete(ptr);
216		return (SUCCESS);
217	}
218	return (NOT_HERE);
219}
220
221/*
222 * Classic delete from a double-linked list
223 */
224static void
225delete(TABLE_ENTRY *ptr)
226{
227
228	if (debug)
229		print_request("delete", &ptr->request);
230	if (table == ptr)
231		table = ptr->next;
232	else if (ptr->last != NIL)
233		ptr->last->next = ptr->next;
234	if (ptr->next != NIL)
235		ptr->next->last = ptr->last;
236	free((char *)ptr);
237}
238