initial support to PPP protocol
[decrew:groink.git] / src / protos.c
1 /*
2  * Copyright (c) Denatured Ethyl Crew
3  *
4  * This file is part of GroinK.
5  *
6  * GroinK is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GroinK is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GroinK.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 #include "protos.h"
20 #include "packet.h"
21 #include "protocols/ethernet.h"
22 #include "protocols/arp.h"
23 #include "protocols/pppoe.h"
24 #include "protocols/raw.h"
25 #include "protocols/ipv4.h"
26 #include "protocols/ipv6.h"
27 #include "protocols/tcp.h"
28 #include "protocols/udp.h"
29 #include "protocols/icmp.h"
30 #include "protocols/icmp6.h"
31 #include "protocols/http.h"
32 #include "protocols/ftp.h"
33 #include "protocols/sll.h"
34 #include "protocols/ppp.h"
35 #include "debug.h"
36 #include "base.h"
37 #include "hashtable.h"
38 #include "threads.h"
39
40 typedef void(*proto_cb)();
41
42 static const proto_cb protos[] = {
43   register_ether,
44   register_arp,
45   register_pppoe,
46   register_raw,
47   register_ipv4,
48   register_tcp,
49   register_udp,
50   register_icmp,
51   register_ipv6,
52   register_icmp6,
53   register_http,
54   register_ftp,
55   register_sll,
56   register_ppp,
57   NULL
58 };
59
60 struct _pname_table {
61   char *name;
62   proto_t *p;
63   UT_hash_handle hh;
64 };
65
66 struct _pport_table {
67   int port;
68   proto_t *p;
69   UT_hash_handle hh;
70 };
71
72 /* Protocols hashtables */
73 static struct _pname_table *name_ptable = NULL;
74 static struct _pport_table *port_ptable = NULL;
75
76 /* Mutex for hashtable that contains protos by name */
77 static pthread_mutex_t mutex_ht1 = PTHREAD_MUTEX_INITIALIZER;
78
79 /* Mutex for hashtable that contains protos by port */
80 static pthread_mutex_t mutex_ht2 = PTHREAD_MUTEX_INITIALIZER;
81
82 /* Load all suported protocols */
83 void protos_init()
84 {
85   int i = 0;
86   for (i=0; protos[i]!=NULL; i++)
87     protos[i]();
88
89   debug("loaded %d protocol%c", i, (i > 1)? 's' : ' ');
90 }
91
92 static void cleanup_protos_name_table()
93 {
94   struct _pname_table *curr = NULL, *tmp = NULL;
95
96   HASH_ITER(hh, name_ptable, curr, tmp) {
97     HASH_DEL(name_ptable, curr);
98     
99     curr->p->refcount--;
100     if (curr->p->refcount == 0) {
101       free(curr->p);
102       curr->p = NULL;
103     }
104
105     free(curr);
106     curr = NULL;
107   }
108
109   name_ptable = NULL;
110 }
111
112 static void cleanup_protos_port_table()
113 {
114   struct _pport_table *curr = NULL, *tmp = NULL;
115
116   HASH_ITER(hh, port_ptable, curr, tmp) {
117     HASH_DEL(port_ptable, curr);
118     
119     curr->p->refcount--;
120     if (curr->p->refcount == 0) {
121       free(curr->p);
122       curr->p = NULL;
123     }
124
125     free(curr);
126     curr = NULL;
127   }
128   port_ptable = NULL;
129 }
130
131 void protos_destroy()
132 {
133   cleanup_protos_port_table();
134   cleanup_protos_name_table();
135   debug("cleanup loaded protocols");
136 }
137
138 void proto_register_byname(char *name, proto_t *p)
139 {
140   struct _pname_table *e = (struct _pname_table *)safe_alloc(sizeof(struct _pname_table));
141   e->name = name;
142   e->p = p;
143
144   /* Increment refcount of the protocol struct */
145   p->refcount++;
146
147   MUTEX_LOCK(&mutex_ht1);
148   HASH_ADD_KEYPTR(hh, name_ptable, e->name, strlen(e->name), e);
149   MUTEX_UNLOCK(&mutex_ht1);
150 }
151
152 void proto_register_byport(int port, proto_t *p)
153 {
154   struct _pport_table *e = (struct _pport_table *)safe_alloc(sizeof(struct _pport_table));
155   e->port = port;
156   e->p = p;
157
158   /* Increment refcount of the protocol struct */
159   p->refcount++;
160
161   MUTEX_LOCK(&mutex_ht2);
162   HASH_ADD_INT(port_ptable, port, e);
163   MUTEX_UNLOCK(&mutex_ht2);
164 }
165
166
167 void proto_unregister_byname(char *name)
168 {
169   /* TODO */
170 }
171
172 void proto_unregister_byport(int port)
173 {
174   /* TODO */
175 }
176
177 proto_t *proto_get_byname(char *name)
178 {
179   struct _pname_table *e = NULL;
180
181   MUTEX_LOCK(&mutex_ht1);
182   HASH_FIND_STR(name_ptable, name, e);
183   MUTEX_UNLOCK(&mutex_ht1);
184
185   if (e != NULL)
186     return e->p;
187   return NULL;
188 }
189
190 proto_t *proto_get_byport(int port)
191 {
192   struct _pport_table *e = NULL;
193
194   MUTEX_LOCK(&mutex_ht2);  
195   HASH_FIND_INT(port_ptable, &port, e);
196   MUTEX_UNLOCK(&mutex_ht2);
197
198   if (e != NULL)
199     return e->p;
200   return NULL;
201 }