pppoe plugin stuff - Michal Ostrowski's version, lightly hacked
[ppp.git] / pppd / plugins / pppoe / pppoehash.c
1 /* PPPoE support library "libpppoe"
2  *
3  * Copyright 2000 Michal Ostrowski <mostrows@styx.uwaterloo.ca>,
4  *                Jamal Hadi Salim <hadi@cyberus.ca>
5  *
6  *  This program is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU General Public License
8  *  as published by the Free Software Foundation; either version
9  *  2 of the License, or (at your option) any later version.
10  */
11 #include "pppoe.h"
12
13
14 #define PPPOE_HASH_SIZE 16
15
16
17 static inline int keycmp(char *a, char *b, int x, int y){
18     return x==y && !memcmp(a,b,x);
19 }
20
21 static int hash_con(int key_len, char* key)
22 {
23     int i = 0;
24     char hash[sizeof(int)]={0,};
25
26     for (i = 0; i < key_len ; ++i)
27         hash[i% sizeof(int)] = hash[i%sizeof(int)] ^ key[i];
28
29     i = (*((int*)hash)) ;
30     i &= PPPOE_HASH_SIZE - 1;
31
32     return i;
33 }       
34
35 static struct pppoe_con *con_ht[PPPOE_HASH_SIZE] = { 0, };
36
37 struct pppoe_con *get_con(int len, char *key)
38 {
39     int hash = hash_con(len, key);
40     struct pppoe_con *ret;
41
42     ret = con_ht[hash];
43
44     while (ret && !keycmp(ret->key,key, ret->key_len, len))
45         ret = ret->next;
46
47     return ret;
48 }
49
50 int store_con(struct pppoe_con *pc)
51 {
52     int hash = hash_con(pc->key_len, pc->key);
53     struct pppoe_con *ret;
54
55     ret = con_ht[hash];
56     while (ret) {
57         if (!keycmp(ret->key, pc->key, ret->key_len, pc->key_len))
58             return -EALREADY;
59         
60         ret = ret->next;
61     }
62
63     if (!ret) {
64         pc->next = con_ht[hash];
65         con_ht[hash] = pc;
66     }
67
68     return 0;
69 }
70
71 struct pppoe_con *delete_con(unsigned long len, char *key)
72 {
73     int hash = hash_con(len, key);
74     struct pppoe_con *ret, **src;
75
76     ret = con_ht[hash];
77     src = &con_ht[hash];
78
79     while (ret) {
80         if (keycmp(ret->key,key, ret->key_len, len)) {
81             *src = ret->next;
82             break;
83         }
84         
85         src = &ret->next;
86         ret = ret->next;
87     }
88
89     return ret;
90 }
91