I wonder why these weren't in CVS, but maybe signal 11 sent to "cvs" has something...
[libipt_ACCOUNT] / src / ipt_ACCOUNT_cl.c
CommitLineData
a61040d6
TJ
1/***************************************************************************
2 * Copyright (C) 2004 by Intra2net AG *
3 * opensource@intra2net.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU Lesser General Public License *
7 * version 2.1 as published by the Free Software Foundation; *
8 * *
9 ***************************************************************************/
10
322f2b5b
TJ
11#include <sys/types.h>
12#include <sys/socket.h>
322f2b5b
TJ
13
14#include <ipt_ACCOUNT_cl.h>
15
16int ipt_ACCOUNT_init(struct ipt_ACCOUNT_context *ctx)
17{
18 memset (ctx, 0, sizeof(struct ipt_ACCOUNT_context));
19
20 ctx->sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
21 if (ctx->sockfd < 0)
22 {
23 ctx->sockfd = -1;
24 ctx->error_str = "Can't open socket to kernel. Permission denied or ipt_ACCOUNT module not loaded";
25 return -1;
26 }
27
28 // 4096 bytes default buffer should save us from reallocations
29 // as it fits 200 concurrent active clients
30 if((ctx->data = (void *)malloc(IPT_ACCOUNT_MIN_BUFSIZE)) == NULL)
31 {
32 close (ctx->sockfd);
33 ctx->sockfd = -1;
34 ctx->error_str = "Out of memory for data buffer";
35 return -1;
36 }
37 ctx->data_size = IPT_ACCOUNT_MIN_BUFSIZE;
38
39 return 0;
40}
41
42void ipt_ACCOUNT_free_entries(struct ipt_ACCOUNT_context *ctx)
43{
44 if (ctx->handle.handle_nr >= 0)
45 {
46 setsockopt(ctx->sockfd, IPPROTO_IP, IPT_SO_SET_ACCOUNT_HANDLE_FREE, &ctx->handle, sizeof (struct ipt_account_handle_sockopt));
47 ctx->handle.handle_nr = -1;
48 }
49
50 ctx->handle.itemcount = 0;
51 ctx->pos = 0;
52}
53
54void ipt_ACCOUNT_deinit(struct ipt_ACCOUNT_context *ctx)
55{
56 free(ctx->data);
57 ctx->data = NULL;
58
59 ipt_ACCOUNT_free_entries(ctx);
60
61 close(ctx->sockfd);
62 ctx->sockfd =-1;
63}
64
65int ipt_ACCOUNT_read_entries(struct ipt_ACCOUNT_context *ctx, char *table, char dont_flush)
66{
67 unsigned int s = sizeof (struct ipt_account_handle_sockopt);
68 int rtn;
69
70 strncpy(ctx->handle.name, table, ACCOUNT_TABLE_NAME_LEN-1);
71
72 // Get table information
73 if (!dont_flush)
74 rtn = getsockopt(ctx->sockfd, IPPROTO_IP, IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH, &ctx->handle, &s);
75 else
76 rtn = getsockopt(ctx->sockfd, IPPROTO_IP, IPT_SO_GET_ACCOUNT_PREPARE_READ, &ctx->handle, &s);
77
78 if (rtn < 0)
79 {
80 ctx->error_str = "Can't get table information from kernel. Is the table existing?";
81 return -1;
82 }
83
84 // Check data buffer size
85 ctx->pos = 0;
86 unsigned int new_size = ctx->handle.itemcount * sizeof(struct ipt_account_handle_ip);
87 // We want to prevent reallocations all the time
88 if (new_size < IPT_ACCOUNT_MIN_BUFSIZE)
89 new_size = IPT_ACCOUNT_MIN_BUFSIZE;
90
91 // Reallocate if it's too small or twice as big
92 if (ctx->data_size < new_size || ctx->data_size > new_size*2)
93 {
94 // Free old buffer
95 free (ctx->data);
96 ctx->data_size = 0;
97
98 if ((ctx->data = (void*)malloc(new_size)) == NULL)
99 {
100 ctx->error_str = "Out of memory for data buffer";
101 ipt_ACCOUNT_free_entries(ctx);
102 return -1;
103 }
104
105 ctx->data_size = new_size;
106 }
107
108 // Copy data from kernel
109 memcpy(ctx->data, &ctx->handle, sizeof(struct ipt_account_handle_sockopt));
110 rtn = getsockopt(ctx->sockfd, IPPROTO_IP, IPT_SO_GET_ACCOUNT_GET_DATA, ctx->data, &ctx->data_size);
111 if (rtn < 0)
112 {
113 ctx->error_str = "Can't get data from kernel. Check /var/log/messages for details.";
114 ipt_ACCOUNT_free_entries(ctx);
115 return -1;
116 }
117
118 // Free kernel handle but don't reset pos/itemcount
119 setsockopt(ctx->sockfd, IPPROTO_IP, IPT_SO_SET_ACCOUNT_HANDLE_FREE, &ctx->handle, sizeof (struct ipt_account_handle_sockopt));
120 ctx->handle.handle_nr = -1;
121
122 return 0;
123}
124
125struct ipt_account_handle_ip *ipt_ACCOUNT_get_next_entry(struct ipt_ACCOUNT_context *ctx)
126{
127 struct ipt_account_handle_ip *rtn;
128
129 // Empty or no more items left to return?
130 if (!ctx->handle.itemcount || ctx->pos >= ctx->handle.itemcount)
131 return NULL;
132
133 // Get next entry
134 rtn = (struct ipt_account_handle_ip *)(ctx->data + ctx->pos*sizeof(struct ipt_account_handle_ip));
135 ctx->pos++;
136
137 return rtn;
138}