Add counters for MPTP buffers and syscalls.
[swifty.git] / src / raw / socket_manager_list.c
1 /*
2  * Linked list management for sockets
3  *
4  * Use sock_list structure to store information about sockets. Use functions
5  * to add, remove, find and update information in list.
6  *
7  * 2011, Razvan Deaconescu, razvan.deaconescu@cs.pub.ro
8  */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <netinet/in.h>
16 #include <unistd.h>
17 #include <errno.h>
18
19 #include "swift_types.h"
20 #include "socket_manager.h"
21 #include "debug.h"
22 #include "util.h"
23
24 enum sock_bind_state {
25         STATE_NOTBOUND,
26         STATE_BOUND
27 };
28
29 /* socket management structure */
30 struct sock_list {
31         int s;
32         struct sockaddr addr;
33         enum sock_bind_state bind_state;
34         struct sock_list *next;
35         struct sock_list *prev;
36 };
37
38 /* socket management list head */
39 static struct sock_list sock_list_head = {
40         .next = &sock_list_head,
41         .prev = &sock_list_head
42 };
43
44 /*
45  * Find socket in socket management list.
46  */
47
48 static struct sock_list *list_get_link(int s)
49 {
50         struct sock_list *ptr;
51
52         for (ptr = sock_list_head.next; ptr != &sock_list_head; ptr = ptr->next)
53                 if (ptr->s == s)
54                         return ptr;
55
56         return NULL;
57 }
58
59 /*
60  * Find socket in socket management list by address.
61  */
62
63 static struct sock_list *list_get_link_by_address(const struct sockaddr *addr)
64 {
65         struct sock_list *ptr;
66
67         for (ptr = sock_list_head.next; ptr != &sock_list_head; ptr = ptr->next)
68                 if (memcmp(addr, &ptr->addr, sizeof(*addr)) == 0)
69                         return ptr;
70
71         return NULL;
72 }
73
74 /*
75  * Unlink socket from list. Called by sm_del.
76  */
77
78 static void list_unlink(struct sock_list *ptr)
79 {
80         ptr->next->prev = ptr->prev;
81         ptr->prev->next = ptr->next;
82         ptr->next = ptr;
83         ptr->prev = ptr;
84 }
85
86 /*
87  * Link socket to list. Add socket to tail of list.
88  */
89
90 static void list_link(struct sock_list *ptr)
91 {
92         ptr->next = &sock_list_head;
93         ptr->prev = sock_list_head.prev;
94         sock_list_head.prev->next = ptr;
95         sock_list_head.prev = ptr;
96 }
97
98 /*
99  * Add new socket to list. Called by sw_socket "syscall".
100  */
101
102 int sm_add(int s)
103 {
104         struct sock_list *ptr = malloc(sizeof(*ptr));
105         if (ptr == NULL)
106                 return -1;
107
108         ptr->s = s;
109         list_link(ptr);
110
111         return 0;
112 }
113
114 /*
115  * Bind socket to given address. Called by sw_bind "syscall".
116  */
117
118 int sm_update_address(int s, const struct sockaddr *addr)
119 {
120         struct sock_list *ptr;
121
122         ptr = list_get_link(s);
123         if (ptr == NULL)
124                 return -1;
125
126         memcpy(&ptr->addr, addr, sizeof(ptr->addr));
127
128         return 0;
129 }
130
131 /*
132  * Remove socket from list. Called by sw_close "syscall".
133  */
134
135 int sm_del(int s)
136 {
137         struct sock_list *ptr;
138
139         ptr = list_get_link(s);
140         if (ptr == NULL)
141                 return -1;
142
143         list_unlink(ptr);
144         free(ptr);
145
146         return 0;
147 }
148
149 /*
150  * Check if a socket is bound.
151  */
152
153 int sm_is_bound(int s)
154 {
155         struct sock_list *ptr;
156
157         ptr = list_get_link(s);
158         if (ptr == NULL)
159                 return 0;
160
161         if (ptr->bind_state == STATE_BOUND)
162                 return 1;
163
164         return 0;
165 }
166
167 /*
168  * Mark socket as bound.
169  */
170
171 int sm_mark_bound(int s)
172 {
173         struct sock_list *ptr;
174         
175         ptr = list_get_link(s);
176         if (ptr == NULL)
177                 return -1;
178
179         ptr->bind_state = STATE_BOUND;
180
181         return 0;
182 }
183
184 /*
185  * Mark socket as unbound.
186  */
187
188 int sm_mark_unbound(int s)
189 {
190         struct sock_list *ptr;
191
192         ptr = list_get_link(s);
193         if (ptr == NULL)
194                 return -1;
195
196         ptr->bind_state = STATE_NOTBOUND;
197
198         return 0;
199 }
200
201 /*
202  * Check if adress is asociated with a given socket.
203  */
204
205 int sm_address_exists(const struct sockaddr *addr)
206 {
207         struct sock_list *ptr;
208
209         ptr = list_get_link_by_address(addr);
210         if (ptr == NULL)
211                 return 0;
212
213         return 1;
214 }
215
216 /*
217  * Find socket address.
218  */
219
220 struct sockaddr *sm_get_address(int s)
221 {
222         struct sock_list *ptr;
223
224         ptr = list_get_link(s);
225         if (ptr == NULL)
226                 return NULL;
227
228         return &ptr->addr;
229 }