1*89fa7c41Sdholland /* $NetBSD: table.c,v 1.11 2015/09/03 08:16:36 dholland Exp $ */
25a6c7829Schristos
361f28255Scgd /*
45a6c7829Schristos * Copyright (c) 1983, 1993
55a6c7829Schristos * The Regents of the University of California. All rights reserved.
661f28255Scgd *
761f28255Scgd * Redistribution and use in source and binary forms, with or without
861f28255Scgd * modification, are permitted provided that the following conditions
961f28255Scgd * are met:
1061f28255Scgd * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd * notice, this list of conditions and the following disclaimer.
1261f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd * notice, this list of conditions and the following disclaimer in the
1461f28255Scgd * documentation and/or other materials provided with the distribution.
158e6ab883Sagc * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd * may be used to endorse or promote products derived from this software
1761f28255Scgd * without specific prior written permission.
1861f28255Scgd *
1961f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd * SUCH DAMAGE.
3061f28255Scgd */
3161f28255Scgd
325a6c7829Schristos #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
345a6c7829Schristos #if 0
355a6c7829Schristos static char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/4/93";
365a6c7829Schristos #else
37*89fa7c41Sdholland __RCSID("$NetBSD: table.c,v 1.11 2015/09/03 08:16:36 dholland Exp $");
385a6c7829Schristos #endif
3961f28255Scgd #endif /* not lint */
4061f28255Scgd
4161f28255Scgd /*
4261f28255Scgd * Routines to handle insertion, deletion, etc on the table
4361f28255Scgd * of requests kept by the daemon. Nothing fancy here, linear
4461f28255Scgd * search on a double-linked list. A time is kept with each
4561f28255Scgd * entry so that overly old invitations can be eliminated.
4661f28255Scgd *
4761f28255Scgd * Consider this a mis-guided attempt at modularity
4861f28255Scgd */
4961f28255Scgd #include <sys/param.h>
5061f28255Scgd #include <sys/time.h>
5161f28255Scgd #include <sys/socket.h>
5261f28255Scgd #include <protocols/talkd.h>
537056a591Slukem #include <inttypes.h>
5461f28255Scgd #include <syslog.h>
5561f28255Scgd #include <unistd.h>
5661f28255Scgd #include <stdio.h>
5761f28255Scgd #include <stdlib.h>
5861f28255Scgd #include <string.h>
5930b86603Schristos #include "extern.h"
6061f28255Scgd
6161f28255Scgd #define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */
6261f28255Scgd
6361f28255Scgd #define NIL ((TABLE_ENTRY *)0)
6461f28255Scgd
6561f28255Scgd struct timeval tp;
6661f28255Scgd
6761f28255Scgd typedef struct table_entry TABLE_ENTRY;
6861f28255Scgd
6961f28255Scgd struct table_entry {
7061f28255Scgd CTL_MSG request;
716e8d2b93Sdholland time_t time;
7261f28255Scgd TABLE_ENTRY *next;
7361f28255Scgd TABLE_ENTRY *last;
7461f28255Scgd };
7561f28255Scgd
7661f28255Scgd TABLE_ENTRY *table = NIL;
7730b86603Schristos
7846067dc3Slukem static void delete(TABLE_ENTRY *);
7961f28255Scgd
8061f28255Scgd /*
8161f28255Scgd * Look in the table for an invitation that matches the current
8261f28255Scgd * request looking for an invitation
8361f28255Scgd */
8461f28255Scgd CTL_MSG *
find_match(CTL_MSG * request)8546067dc3Slukem find_match(CTL_MSG *request)
8661f28255Scgd {
8730b86603Schristos TABLE_ENTRY *ptr;
8861f28255Scgd time_t current_time;
8961f28255Scgd
90c6b94776Sdholland gettimeofday(&tp, NULL);
9161f28255Scgd current_time = tp.tv_sec;
9261f28255Scgd if (debug)
9361f28255Scgd print_request("find_match", request);
9461f28255Scgd for (ptr = table; ptr != NIL; ptr = ptr->next) {
9561f28255Scgd if ((ptr->time - current_time) > MAX_LIFE) {
9661f28255Scgd /* the entry is too old */
9761f28255Scgd if (debug)
9861f28255Scgd print_request("deleting expired entry",
9961f28255Scgd &ptr->request);
10061f28255Scgd delete(ptr);
10161f28255Scgd continue;
10261f28255Scgd }
10361f28255Scgd if (debug)
10461f28255Scgd print_request("", &ptr->request);
10561f28255Scgd if (strcmp(request->l_name, ptr->request.r_name) == 0 &&
10661f28255Scgd strcmp(request->r_name, ptr->request.l_name) == 0 &&
10761f28255Scgd ptr->request.type == LEAVE_INVITE)
10861f28255Scgd return (&ptr->request);
10961f28255Scgd }
11061f28255Scgd return ((CTL_MSG *)0);
11161f28255Scgd }
11261f28255Scgd
11361f28255Scgd /*
11461f28255Scgd * Look for an identical request, as opposed to a complimentary
11561f28255Scgd * one as find_match does
11661f28255Scgd */
11761f28255Scgd CTL_MSG *
find_request(CTL_MSG * request)11846067dc3Slukem find_request(CTL_MSG *request)
11961f28255Scgd {
12030b86603Schristos TABLE_ENTRY *ptr;
12161f28255Scgd time_t current_time;
12261f28255Scgd
123c6b94776Sdholland gettimeofday(&tp, NULL);
12461f28255Scgd current_time = tp.tv_sec;
12561f28255Scgd /*
12661f28255Scgd * See if this is a repeated message, and check for
12761f28255Scgd * out of date entries in the table while we are it.
12861f28255Scgd */
12961f28255Scgd if (debug)
13061f28255Scgd print_request("find_request", request);
13161f28255Scgd for (ptr = table; ptr != NIL; ptr = ptr->next) {
13261f28255Scgd if ((ptr->time - current_time) > MAX_LIFE) {
13361f28255Scgd /* the entry is too old */
13461f28255Scgd if (debug)
13561f28255Scgd print_request("deleting expired entry",
13661f28255Scgd &ptr->request);
13761f28255Scgd delete(ptr);
13861f28255Scgd continue;
13961f28255Scgd }
14061f28255Scgd if (debug)
14161f28255Scgd print_request("", &ptr->request);
14261f28255Scgd if (strcmp(request->r_name, ptr->request.r_name) == 0 &&
14361f28255Scgd strcmp(request->l_name, ptr->request.l_name) == 0 &&
14461f28255Scgd request->type == ptr->request.type &&
14561f28255Scgd request->pid == ptr->request.pid) {
14661f28255Scgd /* update the time if we 'touch' it */
14761f28255Scgd ptr->time = current_time;
14861f28255Scgd return (&ptr->request);
14961f28255Scgd }
15061f28255Scgd }
15161f28255Scgd return ((CTL_MSG *)0);
15261f28255Scgd }
15361f28255Scgd
15430b86603Schristos void
insert_table(CTL_MSG * request,CTL_RESPONSE * response)15546067dc3Slukem insert_table(CTL_MSG *request, CTL_RESPONSE *response)
15661f28255Scgd {
15730b86603Schristos TABLE_ENTRY *ptr;
15861f28255Scgd time_t current_time;
15961f28255Scgd
160c6b94776Sdholland gettimeofday(&tp, NULL);
16161f28255Scgd current_time = tp.tv_sec;
16261f28255Scgd request->id_num = new_id();
16361f28255Scgd response->id_num = htonl(request->id_num);
16461f28255Scgd /* insert a new entry into the top of the list */
16561f28255Scgd ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY));
16661f28255Scgd if (ptr == NIL) {
16761f28255Scgd syslog(LOG_ERR, "insert_table: Out of memory");
16861f28255Scgd _exit(1);
16961f28255Scgd }
17061f28255Scgd ptr->time = current_time;
17161f28255Scgd ptr->request = *request;
17261f28255Scgd ptr->next = table;
17361f28255Scgd if (ptr->next != NIL)
17461f28255Scgd ptr->next->last = ptr;
17561f28255Scgd ptr->last = NIL;
17661f28255Scgd table = ptr;
17761f28255Scgd }
17861f28255Scgd
17961f28255Scgd /*
18061f28255Scgd * Generate a unique non-zero sequence number
18161f28255Scgd */
1827056a591Slukem uint32_t
new_id(void)18346067dc3Slukem new_id(void)
18461f28255Scgd {
1857056a591Slukem static uint32_t current_id = 0;
18661f28255Scgd
18761f28255Scgd current_id = (current_id + 1) % MAX_ID;
18861f28255Scgd /* 0 is reserved, helps to pick up bugs */
18961f28255Scgd if (current_id == 0)
19061f28255Scgd current_id = 1;
19161f28255Scgd return (current_id);
19261f28255Scgd }
19361f28255Scgd
19461f28255Scgd /*
19561f28255Scgd * Delete the invitation with id 'id_num'
19661f28255Scgd */
1977056a591Slukem u_char
delete_invite(uint32_t id_num)1987056a591Slukem delete_invite(uint32_t id_num)
19961f28255Scgd {
20030b86603Schristos TABLE_ENTRY *ptr;
20161f28255Scgd
20261f28255Scgd if (debug)
2037056a591Slukem syslog(LOG_DEBUG, "delete_invite(%"PRIu32")", id_num);
20461f28255Scgd for (ptr = table; ptr != NIL; ptr = ptr->next) {
20561f28255Scgd if (ptr->request.id_num == id_num)
20661f28255Scgd break;
20761f28255Scgd if (debug)
20861f28255Scgd print_request("", &ptr->request);
20961f28255Scgd }
21061f28255Scgd if (ptr != NIL) {
21161f28255Scgd delete(ptr);
21261f28255Scgd return (SUCCESS);
21361f28255Scgd }
21461f28255Scgd return (NOT_HERE);
21561f28255Scgd }
21661f28255Scgd
21761f28255Scgd /*
21861f28255Scgd * Classic delete from a double-linked list
21961f28255Scgd */
22030b86603Schristos static void
delete(TABLE_ENTRY * ptr)22146067dc3Slukem delete(TABLE_ENTRY *ptr)
22261f28255Scgd {
22361f28255Scgd
22461f28255Scgd if (debug)
22561f28255Scgd print_request("delete", &ptr->request);
22661f28255Scgd if (table == ptr)
22761f28255Scgd table = ptr->next;
22861f28255Scgd else if (ptr->last != NIL)
22961f28255Scgd ptr->last->next = ptr->next;
23061f28255Scgd if (ptr->next != NIL)
23161f28255Scgd ptr->next->last = ptr->last;
23261f28255Scgd free((char *)ptr);
23361f28255Scgd }
234