1
2use crate::db_sqlite::SqliteConnection;
3use crate::types::{Error, ErrorKind};
4
5use crate::ipv4::Ipv4AssignmentStore;
6
7use r2d2_sqlite::rusqlite;
8
9#[derive(Debug, Clone)]
10pub struct SqliteIpv4AssignmentStore {
11 db: SqliteConnection,
12}
13
14impl SqliteIpv4AssignmentStore {
15 pub fn new(db: SqliteConnection) -> Self {
16 SqliteIpv4AssignmentStore { db }
17 }
18}
19
20impl Ipv4AssignmentStore for SqliteIpv4AssignmentStore {
21 fn get_space(&self, space_id: i32) -> Result<crate::ipv4::AssignmentSpaceIpv4, Error> {
22 let conn = self.db.get_conn()?;
23 let mut stmt = conn.prepare("SELECT id, name, description, space_visibility, ipv4_prefix, ipv4_prefix_len FROM assignment_space_ipv4 WHERE id = ?")?;
24 let mut rows = stmt.query(rusqlite::params![space_id])?;
25 let row = rows.next()?;
26 let space = match row {
27 Some(row) => {
28 let space = crate::ipv4::AssignmentSpaceIpv4 {
29 id: row.get(0)?,
30 name: row.get(1)?,
31 description: row.get(2)?,
32 space_visibility: row.get(3)?,
33 ipv4_prefix: row.get(4)?,
34 ipv4_prefix_len: row.get(5)?,
35 };
36 Some(space)
37 },
38 None => None,
39 };
40 let space = if let Some(space) = space {
41 space
42 } else {
43 return Err(Error::new(ErrorKind::NotFound,"Space not found".to_string()));
44 };
45 Ok(space)
46 }
47
48 fn get_spaces(&self) -> Result<Vec<crate::ipv4::AssignmentSpaceIpv4>, Error> {
49 let conn = self.db.get_conn()?;
50 let mut stmt = conn.prepare("SELECT id, name, description, space_visibility, ipv4_prefix, ipv4_prefix_len FROM assignment_space_ipv4 ORDER BY ipv4_prefix ASC")?;
51 let mut rows = stmt.query(rusqlite::params![])?;
52 let mut spaces = Vec::new();
53 while let Some(row) = rows.next()? {
54 let space = crate::ipv4::AssignmentSpaceIpv4 {
55 id: row.get(0)?,
56 name: row.get(1)?,
57 description: row.get(2)?,
58 space_visibility: row.get(3)?,
59 ipv4_prefix: row.get(4)?,
60 ipv4_prefix_len: row.get(5)?,
61 };
62 spaces.push(space);
63 }
64 Ok(spaces)
65 }
66
67 fn create_space(&self, space: &crate::ipv4::AssignmentSpaceIpv4) -> Result<i32, Error> {
68 use crate::ipv4::ipv4_network_address;
69 use crate::ipv4::ipv4_broadcast_address;
70
71 let mut conn = self.db.get_conn()?;
72 let tx = conn.transaction()?;
73
74 {
75 let ipv4_network = ipv4_network_address(space.ipv4_prefix, (space.ipv4_prefix_len & 255) as u8);
76 let ipv4_broadcast = ipv4_broadcast_address(space.ipv4_prefix, (space.ipv4_prefix_len & 255) as u8);
77 let mut stmt = tx.prepare(
78 "SELECT COUNT(*) FROM assignment_space_ipv4
79 WHERE ipv4_prefix >= ? AND ipv4_prefix <= ?"
80 )?;
81 let count: i32 = stmt.query_row(
82 rusqlite::params![
83 ipv4_network, ipv4_broadcast,
84 ],
85 |row| row.get(0)
86 )?;
87
88 if count > 0 {
89 return Err(Error::new(ErrorKind::InvalidInput, "Overlapping space exists".to_string()));
90 }
91 }
92
93 for i in 0..space.ipv4_prefix_len {
94 let ipv4_network = ipv4_network_address(space.ipv4_prefix, (i & 255) as u8);
95 let mut stmt = tx.prepare(
96 "SELECT COUNT(*) FROM assignment_space_ipv4
97 WHERE ipv4_prefix = ? AND ipv4_prefix_len = ?"
98 )?;
99 let count: i32 = stmt.query_row(
100 rusqlite::params![
101 ipv4_network, i,
102 ],
103 |row| row.get(0)
104 )?;
105
106 if count > 0 {
107 return Err(Error::new(ErrorKind::InvalidInput, "Overlapping space exists".to_string()));
108 }
109 }
110
111 {
112 let mut stmt = tx.prepare(
113 "INSERT INTO assignment_space_ipv4 (name, description, space_visibility, ipv4_prefix, ipv4_prefix_len)
114 VALUES (?, ?, ?, ?, ?)"
115 )?;
116 stmt.execute(rusqlite::params![
117 space.name, space.description, space.space_visibility, space.ipv4_prefix, space.ipv4_prefix_len
118 ])?;
119 }
120
121 tx.commit()?;
122
123 let id = conn.last_insert_rowid();
124 Ok(id as i32)
125 }
126
127 fn update_space(&self, id: i32, name: &str, description: &str) -> Result<(), Error> {
128 let conn = self.db.get_conn()?;
129 let mut stmt = conn.prepare("UPDATE assignment_space_ipv4 SET name = ?, description = ? WHERE id = ?")?;
130 stmt.execute(rusqlite::params![name, description, id])?;
131 Ok(())
132 }
133
134 fn delete_space(&self, space_id: i32) -> Result<(), Error> {
135 let conn = self.db.get_conn()?;
136 let mut stmt = conn.prepare("DELETE FROM assignment_space_ipv4 WHERE id = ?")?;
137 stmt.execute(rusqlite::params![space_id])?;
138 Ok(())
139 }
140
141 fn get_pool(&self, pool_id: i32) -> Result<crate::ipv4::AssignmentPoolIpv4, Error> {
142 let conn = self.db.get_conn()?;
143 let mut stmt = conn.prepare("SELECT id, name, description, pool_visibility, ipv4_prefix, ipv4_prefix_len, assignment_space_id FROM assignment_pool_ipv4 WHERE id = ?")?;
144 let mut rows = stmt.query(rusqlite::params![pool_id])?;
145 let row = rows.next()?;
146 let pool = match row {
147 Some(row) => {
148 let pool = crate::ipv4::AssignmentPoolIpv4 {
149 id: row.get(0)?,
150 name: row.get(1)?,
151 description: row.get(2)?,
152 pool_visibility: row.get(3)?,
153 ipv4_prefix: row.get(4)?,
154 ipv4_prefix_len: row.get(5)?,
155 assignment_space_id: row.get(6)?,
156 };
157 Some(pool)
158 },
159 None => None,
160 };
161 let pool = if let Some(pool) = pool {
162 pool
163 } else {
164 return Err(Error::new(ErrorKind::NotFound, "Pool not found".to_string()));
165 };
166 Ok(pool)
167 }
168
169 fn get_pools(&self, space_id: i32) -> Result<Vec<crate::ipv4::AssignmentPoolIpv4>, Error> {
170 let conn = self.db.get_conn()?;
171 let mut stmt = conn.prepare("SELECT id, name, description, pool_visibility, ipv4_prefix, ipv4_prefix_len, assignment_space_id FROM assignment_pool_ipv4 WHERE assignment_space_id = ? ORDER BY ipv4_prefix ASC")?;
172 let mut rows = stmt.query(rusqlite::params![space_id])?;
173 let mut pools = Vec::new();
174 while let Some(row) = rows.next()? {
175 let pool = crate::ipv4::AssignmentPoolIpv4 {
176 id: row.get(0)?,
177 name: row.get(1)?,
178 description: row.get(2)?,
179 pool_visibility: row.get(3)?,
180 ipv4_prefix: row.get(4)?,
181 ipv4_prefix_len: row.get(5)?,
182 assignment_space_id: row.get(6)?,
183 };
184 pools.push(pool);
185 }
186 Ok(pools)
187 }
188
189 fn create_pool(&self, pool: &crate::ipv4::AssignmentPoolIpv4) -> Result<i32, Error> {
190 use crate::ipv4::ipv4_network_address;
191 use crate::ipv4::ipv4_broadcast_address;
192
193 let mut conn = self.db.get_conn()?;
194 let tx = conn.transaction()?;
195 {
196 let pool_network = ipv4_network_address(pool.ipv4_prefix, (pool.ipv4_prefix_len & 255) as u8);
197 let pool_broadcast = ipv4_broadcast_address(pool.ipv4_prefix, (pool.ipv4_prefix_len & 255) as u8);
198
199 let mut stmt = tx.prepare(
200 "SELECT ipv4_prefix, ipv4_prefix_len FROM assignment_space_ipv4 WHERE id = ?"
201 )?;
202 let mut rows = stmt.query(rusqlite::params![pool.assignment_space_id])?;
203 let row = rows.next()?;
204 let (space_network, space_broadcast) = match row {
205 Some(row) => {
206 let space_prefix = row.get(0)?;
207 let space_prefix_len: u8 = row.get(1)?;
208 let space_network = ipv4_network_address(space_prefix, (space_prefix_len & 255) as u8);
209 let space_broadcast = ipv4_broadcast_address(space_prefix, (space_prefix_len & 255) as u8);
210 (space_network, space_broadcast)
211 },
212 None => return Err(Error::new(ErrorKind::NotFound, "Parent space not found".to_string())),
213 };
214
215 if pool_network < space_network || pool_broadcast > space_broadcast {
216 return Err(Error::new(ErrorKind::InvalidInput, "Pool is not contained within the parent space".to_string()));
217 }
218 }
219
220 {
221 let ipv4_network = ipv4_network_address(pool.ipv4_prefix, (pool.ipv4_prefix_len & 255) as u8);
222 let ipv4_broadcast = ipv4_broadcast_address(pool.ipv4_prefix, (pool.ipv4_prefix_len & 255) as u8);
223 let mut stmt = tx.prepare(
224 "SELECT COUNT(*) FROM assignment_pool_ipv4
225 WHERE ipv4_prefix >= ? AND ipv4_prefix <= ?"
226 )?;
227 let count: i32 = stmt.query_row(
228 rusqlite::params![
229 ipv4_network, ipv4_broadcast,
230 ],
231 |row| row.get(0)
232 )?;
233
234 if count > 0 {
235 return Err(Error::new(ErrorKind::InvalidInput, "Overlapping pool exists".to_string()));
236 }
237 }
238
239 for i in 0..pool.ipv4_prefix_len {
240 let ipv4_network = ipv4_network_address(pool.ipv4_prefix, (i & 255) as u8);
241 let mut stmt = tx.prepare(
242 "SELECT COUNT(*) FROM assignment_pool_ipv4
243 WHERE ipv4_prefix = ? AND ipv4_prefix_len = ?"
244 )?;
245 let count: i32 = stmt.query_row(
246 rusqlite::params![
247 ipv4_network, i,
248 ],
249 |row| row.get(0)
250 )?;
251
252 if count > 0 {
253 return Err(Error::new(ErrorKind::InvalidInput, "Overlapping pool exists".to_string()));
254 }
255 }
256
257 {
258 let mut stmt = tx.prepare(
259 "INSERT INTO assignment_pool_ipv4 (name, description, pool_visibility, ipv4_prefix, ipv4_prefix_len, assignment_space_id)
260 VALUES (?, ?, ?, ?, ?, ?)"
261 )?;
262 stmt.execute(rusqlite::params![
263 pool.name, pool.description, pool.pool_visibility, pool.ipv4_prefix, pool.ipv4_prefix_len, pool.assignment_space_id
264 ])?;
265 }
266
267 tx.commit()?;
268
269 let id = conn.last_insert_rowid();
270 Ok(id as i32)
271 }
272
273 fn update_pool(&self, id: i32, name: &str, description: &str) -> Result<(), Error> {
274 let conn = self.db.get_conn()?;
275 let mut stmt = conn.prepare("UPDATE assignment_pool_ipv4 SET name = ?, description = ? WHERE id = ?")?;
276 stmt.execute(rusqlite::params![name, description, id])?;
277 Ok(())
278 }
279
280 fn delete_pool(&self, pool_id: i32) -> Result<(), Error> {
281 let conn = self.db.get_conn()?;
282 let mut stmt = conn.prepare("DELETE FROM assignment_pool_ipv4 WHERE id = ?")?;
283 stmt.execute(rusqlite::params![pool_id])?;
284 Ok(())
285 }
286
287 fn get_assignment(&self, assignment_id: i32) -> Result<crate::ipv4::AssignmentIpv4, Error> {
288 let conn = self.db.get_conn()?;
289 let mut stmt = conn.prepare("SELECT id, name, description, ipv4_prefix, ipv4_prefix_len, assignment_pool_id, assignment_visibility FROM assignment_ipv4 WHERE id = ?")?;
290 let mut rows = stmt.query(rusqlite::params![assignment_id])?;
291 let row = rows.next()?;
292 let assignment = match row {
293 Some(row) => {
294 let assignment = crate::ipv4::AssignmentIpv4 {
295 id: row.get(0)?,
296 name: row.get(1)?,
297 description: row.get(2)?,
298 ipv4_prefix: row.get(3)?,
299 ipv4_prefix_len: row.get(4)?,
300 assignment_pool_id: row.get(5)?,
301 assignment_visibility: row.get(6)?,
302 };
303 Some(assignment)
304 },
305 None => None,
306 };
307 let assignment = if let Some(assignment) = assignment {
308 assignment
309 } else {
310 return Err(Error::new(ErrorKind::NotFound, "Assignment not found".to_string()));
311 };
312 Ok(assignment)
313 }
314
315 fn get_assignments(&self, pool_id: i32) -> Result<Vec<crate::ipv4::AssignmentIpv4>, Error> {
316 let conn = self.db.get_conn()?;
317 let mut stmt = conn.prepare("SELECT id, name, description, ipv4_prefix, ipv4_prefix_len, assignment_pool_id, assignment_visibility FROM assignment_ipv4 WHERE assignment_pool_id = ? ORDER BY ipv4_prefix ASC")?;
318 let mut rows = stmt.query(rusqlite::params![pool_id])?;
319 let mut assignments = Vec::new();
320 while let Some(row) = rows.next()? {
321 let assignment = crate::ipv4::AssignmentIpv4 {
322 id: row.get(0)?,
323 name: row.get(1)?,
324 description: row.get(2)?,
325 ipv4_prefix: row.get(3)?,
326 ipv4_prefix_len: row.get(4)?,
327 assignment_pool_id: row.get(5)?,
328 assignment_visibility: row.get(6)?,
329 };
330 assignments.push(assignment);
331 }
332 Ok(assignments)
333 }
334
335 fn create_assignment(&self, assignment: &crate::ipv4::AssignmentIpv4) -> Result<i32, Error> {
336 use crate::ipv4::ipv4_network_address;
337 use crate::ipv4::ipv4_broadcast_address;
338
339 let mut conn = self.db.get_conn()?;
340 let tx = conn.transaction()?;
341 {
342 let assignment_network = ipv4_network_address(assignment.ipv4_prefix, (assignment.ipv4_prefix_len & 255) as u8);
343 let assignment_broadcast = ipv4_broadcast_address(assignment.ipv4_prefix, (assignment.ipv4_prefix_len & 255) as u8);
344
345 let mut stmt = tx.prepare(
346 "SELECT ipv4_prefix, ipv4_prefix_len FROM assignment_pool_ipv4 WHERE id = ?"
347 )?;
348 let mut rows = stmt.query(rusqlite::params![assignment.assignment_pool_id])?;
349 let row = rows.next()?;
350 let (pool_network, pool_broadcast) = match row {
351 Some(row) => {
352 let pool_prefix = row.get(0)?;
353 let pool_prefix_len: u8 = row.get(1)?;
354 let pool_network = ipv4_network_address(pool_prefix, (pool_prefix_len & 255) as u8);
355 let pool_broadcast = ipv4_broadcast_address(pool_prefix, (pool_prefix_len & 255) as u8);
356 (pool_network, pool_broadcast)
357 },
358 None => return Err(Error::new(ErrorKind::NotFound, "Parent pool not found".to_string())),
359 };
360
361 if assignment_network < pool_network || assignment_broadcast > pool_broadcast {
362 return Err(Error::new(ErrorKind::InvalidInput, "Assignment is not contained within the parent pool".to_string()));
363 }
364 }
365
366 {
367 let ipv4_network = ipv4_network_address(assignment.ipv4_prefix, (assignment.ipv4_prefix_len & 255) as u8);
368 let ipv4_broadcast = ipv4_broadcast_address(assignment.ipv4_prefix, (assignment.ipv4_prefix_len & 255) as u8);
369 let mut stmt = tx.prepare(
370 "SELECT COUNT(*) FROM assignment_ipv4
371 WHERE ipv4_prefix >= ? AND ipv4_prefix <= ?"
372 )?;
373 let count: i32 = stmt.query_row(
374 rusqlite::params![
375 ipv4_network, ipv4_broadcast,
376 ],
377 |row| row.get(0)
378 )?;
379
380 if count > 0 {
381 return Err(Error::new(ErrorKind::InvalidInput, "overlapping assingment exists".to_string()));
382 }
383 }
384
385 for i in 0..assignment.ipv4_prefix_len {
386 let ipv4_network = ipv4_network_address(assignment.ipv4_prefix, (i & 255) as u8);
387 let mut stmt = tx.prepare(
388 "SELECT COUNT(*) FROM assignment_ipv4
389 WHERE ipv4_prefix = ? AND ipv4_prefix_len = ?"
390 )?;
391 let count: i32 = stmt.query_row(
392 rusqlite::params![
393 ipv4_network, i,
394 ],
395 |row| row.get(0)
396 )?;
397
398 if count > 0 {
399 return Err(Error::new(ErrorKind::InvalidInput, "Overlapping assignment exists".to_string()));
400 }
401 }
402
403 {
404 let mut stmt = tx.prepare(
405 "INSERT INTO assignment_ipv4 (name, description, ipv4_prefix, ipv4_prefix_len, assignment_pool_id, assignment_visibility)
406 VALUES (?, ?, ?, ?, ?, ?)"
407 )?;
408 stmt.execute(rusqlite::params![
409 assignment.name, assignment.description, assignment.ipv4_prefix, assignment.ipv4_prefix_len, assignment.assignment_pool_id, assignment.assignment_visibility
410 ])?;
411 }
412
413 tx.commit()?;
414
415 let id = conn.last_insert_rowid();
416 Ok(id as i32)
417 }
418
419 fn update_assignment(&self, id: i32, name: &str, description: &str) -> Result<(), Error> {
420 let conn = self.db.get_conn()?;
421 let mut stmt = conn.prepare("UPDATE assignment_ipv4 SET name = ?, description = ? WHERE id = ?")?;
422 stmt.execute(rusqlite::params![name, description, id])?;
423 Ok(())
424 }
425
426 fn delete_assignment(&self, assignment_id: i32) -> Result<(), Error> {
427 let conn = self.db.get_conn()?;
428 let mut stmt = conn.prepare("DELETE FROM assignment_ipv4 WHERE id = ?")?;
429 stmt.execute(rusqlite::params![assignment_id])?;
430 Ok(())
431 }
432}
433